2022-02-11 22:35:55

by Andre Przywara

[permalink] [raw]
Subject: [PATCH v10 00/18] arm64: sunxi: Initial Allwinner H616 SoC support

Hi,

an update of the H616 afer some silence, hope to get the ball rolling
on this again. This is now based on top of 5.17-rc2, plus Samuel's
H616 RTC clock patches, which Maxime took already locally.
This being the first user of this new clock driver revealed some issue,
where the actual RTC clock was not referenced, thus turned off. IIUC
Samuel is thinking about a fix to the clock driver for that. Meanwhile
clk_ignore_unused worked around the issue, so the clock driver and the
RTC work in general.
To accommodate the new clock driver, I needed to add two clocks (RTC bus
clock and the "32K system PLL"), this is done in patch 01 and 02.
The rest of the RTC driver patches (03-05) is just rebased, with the
actual enablement patch (06) now being trivial.
The .dtsi patch (07) has been amended to match the new RTC binding, also
fixing some smaller issues in there.

I also add the USB patches on top, since they seem to be needed by other
SoCs as well, and we should get them moving again. However I would be
happy enough to first see the RTC and basic DT patches handled.

For a complete changelog, see below.

Based on 5.17-rc2, plus Samuel's RTC clock driver series[1].
Let me know if you need a different base.

Also available here: https://github.com/apritzel/linux/commits/h616-v10

Thanks!
Andre

==================
This series gathers patches to support the Allwinner H616 SoC. This is
a rather uninspired SoC (Quad-A53 with the usual peripherals), but
allows for some cheap development boards and TV boxes, and supports
up to 4GB of DRAM.

Some DT binding patches are sprinkled throughout the series, to add
the new compatible names right before they are used.
Patch 3-6 add support for the new RTC: the date is now stored as a
linear number, not broken down into day-month-year. The benefit is that
this lifts the limit of the old date counter, which would have rolled
over around 2032. Also the alarm setting is using the same storage
format as the current time, compared to the number of seconds left used
in existing SoCs.
Eventually we get the .dtsi for the SoC in patch 7, and the .dts for
the OrangePi Zero2 board[2] in the next patch, followed by the .dts
for the X96 Mate TV box[3] afterwards.

U-Boot and Trusted Firmware support is now merged in released versions,
it allows booting via FEL or SD card, also you can TFTP kernels in on
the OrangePi Zero 2 board.

Many thanks to Jernej for his tremendous help on this, also for the
awesome input and help from the #linux-sunxi Freenode channel.

The whole series (including the prerequisites) can also be found here:
https://github.com/apritzel/linux/commits/h616-v10

Happy reviewing!

Cheers,
Andre

[1] https://lore.kernel.org/all/[email protected]/
[2] https://linux-sunxi.org/Orange_Pi_Zero_2
[3] https://linux-sunxi.org/X96_Mate

Changelog v9 .. v10:
- based on ccu-sun6i-rtc clock driver
- add RTC bus clock and 32k system PLL clock
- drop clock related code from actual RTC driver (just use RTC bits)
- .dtsi: remove redundant status = "okay"; from .dtsi
- .dts: drop #address-cells = <0> from IRQ controller nodes
- .dtsi: fix indentation of IR node
- .dtsi: adjust RTC node to new binding
- re-add USB patches

Changelog v8 .. v9:
- RTC: Rely on the division to split of the H:M:S part from the day part
- Add Jernej's Review tags

Changelog v7 .. v8:
- Rebase on top of 5.14-rc1, which already includes the previous v7 02/19
- Drop USB and Ethernet patches (to keep series small)
- Use "clocks: false" in RTC DT binding (2/11)
- Include fix for RTC overflow check (3/11)
- Use div_64() to avoid linking error on some 32-bit platforms (4+5/11)
- Adjust to changed RTC overflow check (5/11)
- Drop USB nodes from .dtsi file
- Move mmc-ddr-1_8v property from .dtsi file into board .dts
- Fix DTC warnings (underscore in node name, soc@0, #a-c in IRQ controllers)

Changelog v6 .. v7:
- Fix AXP305 binding documentation blunder (01/19)
- Improve new linear day support (use existing conversion functions) (04/19)
- Add support for changed RTC alarm registers (05/19)
- Add support for RTCs without a LOSC clock (06/19)
- Rework USB PHY2 SIDDQ quirk to use PHY clocks directly (14/19)
- Add X96 Mate compatible string to binding doc (17/19)
- Add Rob's ACKs

Changelog v5 .. v6:
- Drop already merged clock, pinctrl and MMC support from this series
- Properly fix AXP support by skipping power key initialisation
- Add patch to support new RTC date storage encoding
- Re-add USB HCI PHY refactoring
- Add patch to allow USB reset line sharing
- Add patch to introduce quirk for PHY2 SIDDQ clearing
- Re-add USB nodes to the .dtsi
- Add USB gadget support
- Add DT for X96 Mate TV box

Changelog v4 .. v5:
- Fix CCU binding to pass dtbs_check
- Add RSB compatible string to binding doc
- Rename IR pin name to pass dtbs_check
- Add EMAC compatible string to binding doc
- Drop USB PHY support and binding doc patches
- Drop USB nodes from .dtsi and .dts
- Drop second EMAC node from .dtsi

Changelog v3 .. v4:
- Drop MMC and pinctrl matches (already in some -next trees)
- Add Maxime's Acks
- Add patch to update the AXP MFD DT bindings
- Add new patch (05/21) to fix axp20x-pek driver
- Change AXP IRQ fix to check for invalid IRQ line number
- Split joint DT bindings patch (v3 18/21) into subsystems
- move dwmac variable to keep christmas tree
- Use enums for USB PHY compatible strings in DT binding
- Enable watchdog (briefly verified to work)
- Add PHY2 to HCI1&3, this fixes USB
- limit r-ccu register frame length to not collide with NMI controller
- add interrupt-controller property to AXP DT node

Changelog v2 .. v3:
- Add Rob's Acks
- Drop redundant maxItems from pinctrl DT binding
- Rename h_i2s* to just i2s* in pinctrl names
- Use more declarative i2s0_d{in,out}{0,1} names
- Add RSB pins to pinctrl
- Include RSB clocks (sharing with newly added H6 versions)
- Fix CEC clock (add 2nd enable bit, also fix predivider flag)
- Rename PMU_UNK1 register in USB PHY
- Add USB and MUSB DT binding patches
- Add MMC/SD speed modes to .dtsi

Changelog v1 .. v2:
- pinctrl: adjust irq bank map to cover undocumented GPIO bank IRQs
- use differing h_i2s0 pin output names
- r-ccu: fix number of used clocks
- ccu: remove PLL-PERIPHy(4X)
- ccu: fix gpu1 divider range
- ccu: fix usb-phy3 parent
- ccu: add missing TV clocks
- ccu: rework to CLK_OF_DECLARE style
- ccu: enable output bit for PLL clocks
- ccu: renumber clocks
- .dtsi: drop sun50i-a64-system-control fallback
- .dtsi: drop unknown SRAM regions
- .dtsi: add more (undocumented) GPIO interrupts
- .dtsi: fix I2C3 pin names
- .dtsi: use a100-emmc fallback for MMC2
- .dtsi: add second EMAC controller
- .dtsi: use H3 MUSB controller fallback
- .dtsi: fix frame size for USB PHY PMU registers
- .dtsi: add USB0 PHY references
- .dtsi: fix IR controller clock source
- .dts: fix LED naming and swap pins
- .dts: use 5V supply parent for USB supply
- .dts: drop dummy IRQ for AXP
- .dts: enable 3V3 header pin power rail
- .dts: add SPI flash node
- .dts: make USB-C port peripheral only
- add IRQ-less AXP support
- add two patches to support more than one EMAC clock
- add patch to rework and extend USB PHY support
- add DT binding documentation patches

Andre Przywara (18):
clk: sunxi-ng: h616-r: Add RTC gate clock
clk: sunxi-ng: h616: Add PLL derived 32KHz clock
rtc: sun6i: Fix time overflow handling
rtc: sun6i: Add support for linear day storage
rtc: sun6i: Add support for broken-down alarm registers
rtc: sun6i: Add Allwinner H616 support
arm64: dts: allwinner: Add Allwinner H616 .dtsi file
dt-bindings: arm: sunxi: Add two H616 board compatible strings
arm64: dts: allwinner: h616: Add OrangePi Zero 2 board support
arm64: dts: allwinner: h616: Add X96 Mate TV box support
dt-bindings: usb: Add H616 compatible string
phy: sun4i-usb: Rework HCI PHY (aka. "pmu_unk1") handling
phy: sun4i-usb: Allow reset line to be shared
phy: sun4i-usb: Introduce port2 SIDDQ quirk
phy: sun4i-usb: Add support for the H616 USB PHY
arm64: dts: allwinner: h616: Add USB nodes
arm64: dts: allwinner: h616: OrangePi Zero 2: Add USB nodes
arm64: dts: allwinner: h616: X96 Mate: Add USB nodes

.../devicetree/bindings/arm/sunxi.yaml | 10 +
.../devicetree/bindings/usb/generic-ehci.yaml | 1 +
.../devicetree/bindings/usb/generic-ohci.yaml | 1 +
arch/arm64/boot/dts/allwinner/Makefile | 2 +
.../allwinner/sun50i-h616-orangepi-zero2.dts | 245 ++++++
.../dts/allwinner/sun50i-h616-x96-mate.dts | 202 +++++
.../arm64/boot/dts/allwinner/sun50i-h616.dtsi | 734 ++++++++++++++++++
drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c | 4 +
drivers/clk/sunxi-ng/ccu-sun50i-h6-r.h | 2 +-
drivers/clk/sunxi-ng/ccu-sun50i-h616.c | 7 +
drivers/clk/sunxi-ng/ccu-sun50i-h616.h | 2 +-
drivers/phy/allwinner/phy-sun4i-usb.c | 103 ++-
drivers/rtc/rtc-sun6i.c | 134 ++--
include/dt-bindings/clock/sun50i-h6-r-ccu.h | 1 +
include/dt-bindings/clock/sun50i-h616-ccu.h | 1 +
15 files changed, 1384 insertions(+), 65 deletions(-)
create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-h616-orangepi-zero2.dts
create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-h616-x96-mate.dts
create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi

--
2.25.1


2022-02-12 10:40:47

by Andre Przywara

[permalink] [raw]
Subject: [PATCH v10 17/18] arm64: dts: allwinner: h616: OrangePi Zero 2: Add USB nodes

The OrangePi Zero 2 has one USB-A host port, VBUS is provided by
a GPIO controlled regulator.
The USB-C port is meant to power the board, but is also connected to
the USB 0 port, which we configure as an MUSB peripheral.

Signed-off-by: Andre Przywara <[email protected]>
---
.../allwinner/sun50i-h616-orangepi-zero2.dts | 42 +++++++++++++++++++
1 file changed, 42 insertions(+)

diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h616-orangepi-zero2.dts b/arch/arm64/boot/dts/allwinner/sun50i-h616-orangepi-zero2.dts
index ca07cae698ce..a26201288872 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h616-orangepi-zero2.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h616-orangepi-zero2.dts
@@ -49,8 +49,25 @@ reg_vcc5v: vcc5v {
regulator-max-microvolt = <5000000>;
regulator-always-on;
};
+
+ reg_usb1_vbus: usb1-vbus {
+ compatible = "regulator-fixed";
+ regulator-name = "usb1-vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ vin-supply = <&reg_vcc5v>;
+ enable-active-high;
+ gpio = <&pio 2 16 GPIO_ACTIVE_HIGH>; /* PC16 */
+ status = "okay";
+ };
};

+&ehci1 {
+ status = "okay";
+};
+
+/* USB 2 & 3 are on headers only. */
+
&emac0 {
pinctrl-names = "default";
pinctrl-0 = <&ext_rgmii_pins>;
@@ -76,6 +93,10 @@ &mmc0 {
status = "okay";
};

+&ohci1 {
+ status = "okay";
+};
+
&r_rsb {
status = "okay";

@@ -201,3 +222,24 @@ &uart0 {
pinctrl-0 = <&uart0_ph_pins>;
status = "okay";
};
+
+&usbotg {
+ /*
+ * PHY0 pins are connected to a USB-C socket, but a role switch
+ * is not implemented: both CC pins are pulled to GND.
+ * The VBUS pins power the device, so a fixed peripheral mode
+ * is the best choice.
+ * The board can be powered via GPIOs, in this case port0 *can*
+ * act as a host (with a cable/adapter ignoring CC), as VBUS is
+ * then provided by the GPIOs. Any user of this setup would
+ * need to adjust the DT accordingly: dr_mode set to "host",
+ * enabling OHCI0 and EHCI0.
+ */
+ dr_mode = "peripheral";
+ status = "okay";
+};
+
+&usbphy {
+ usb1_vbus-supply = <&reg_usb1_vbus>;
+ status = "okay";
+};
--
2.25.1

2022-02-12 13:05:35

by Andre Przywara

[permalink] [raw]
Subject: [PATCH v10 03/18] rtc: sun6i: Fix time overflow handling

Using "unsigned long" for UNIX timestamps is never a good idea, and
comparing the value of such a variable against U32_MAX does not do
anything useful on 32-bit systems.

Use the proper time64_t type when dealing with timestamps, and avoid
cutting down the time range unnecessarily. This also fixes the flawed
check for the alarm time being too far into the future.

The check for this condition is actually somewhat theoretical, as the
RTC counts till 2033 only anyways, and 2^32 seconds from now is not
before the year 2157 - at which point I hope nobody will be using this
hardware anymore.

Signed-off-by: Andre Przywara <[email protected]>
Reviewed-by: Jernej Skrabec <[email protected]>
---
drivers/rtc/rtc-sun6i.c | 14 +++++---------
1 file changed, 5 insertions(+), 9 deletions(-)

diff --git a/drivers/rtc/rtc-sun6i.c b/drivers/rtc/rtc-sun6i.c
index 35b34d14a1db..dc3ae851841c 100644
--- a/drivers/rtc/rtc-sun6i.c
+++ b/drivers/rtc/rtc-sun6i.c
@@ -139,7 +139,7 @@ struct sun6i_rtc_dev {
const struct sun6i_rtc_clk_data *data;
void __iomem *base;
int irq;
- unsigned long alarm;
+ time64_t alarm;

struct clk_hw hw;
struct clk_hw *int_osc;
@@ -511,10 +511,8 @@ static int sun6i_rtc_setalarm(struct device *dev, struct rtc_wkalrm *wkalrm)
struct sun6i_rtc_dev *chip = dev_get_drvdata(dev);
struct rtc_time *alrm_tm = &wkalrm->time;
struct rtc_time tm_now;
- unsigned long time_now = 0;
- unsigned long time_set = 0;
- unsigned long time_gap = 0;
- int ret = 0;
+ time64_t time_now, time_set;
+ int ret;

ret = sun6i_rtc_gettime(dev, &tm_now);
if (ret < 0) {
@@ -529,9 +527,7 @@ static int sun6i_rtc_setalarm(struct device *dev, struct rtc_wkalrm *wkalrm)
return -EINVAL;
}

- time_gap = time_set - time_now;
-
- if (time_gap > U32_MAX) {
+ if ((time_set - time_now) > U32_MAX) {
dev_err(dev, "Date too far in the future\n");
return -EINVAL;
}
@@ -540,7 +536,7 @@ static int sun6i_rtc_setalarm(struct device *dev, struct rtc_wkalrm *wkalrm)
writel(0, chip->base + SUN6I_ALRM_COUNTER);
usleep_range(100, 300);

- writel(time_gap, chip->base + SUN6I_ALRM_COUNTER);
+ writel(time_set - time_now, chip->base + SUN6I_ALRM_COUNTER);
chip->alarm = time_set;

sun6i_rtc_setaie(wkalrm->enabled, chip);
--
2.25.1

2022-02-12 13:17:11

by Andre Przywara

[permalink] [raw]
Subject: [PATCH v10 14/18] phy: sun4i-usb: Introduce port2 SIDDQ quirk

At least the Allwinner H616 SoC requires a weird quirk to make most
USB PHYs work: Only port2 works out of the box, but all other ports
need some help from this port2 to work correctly: The CLK_BUS_PHY2 and
RST_USB_PHY2 clock and reset need to be enabled, and the SIDDQ bit in
the PMU PHY control register needs to be cleared. For this register to
be accessible, CLK_BUS_ECHI2 needs to be ungated. Don't ask ....

Instead of disguising this as some generic feature, do exactly that
in our PHY init:
If the quirk bit is set, and we initialise a PHY other than PHY2, ungate
this one special clock, and clear the SIDDQ bit. We can pull in the
other required clocks via the DT.

Signed-off-by: Andre Przywara <[email protected]>
---
drivers/phy/allwinner/phy-sun4i-usb.c | 59 +++++++++++++++++++++++++++
1 file changed, 59 insertions(+)

diff --git a/drivers/phy/allwinner/phy-sun4i-usb.c b/drivers/phy/allwinner/phy-sun4i-usb.c
index 126ef74d013c..316ef5fca831 100644
--- a/drivers/phy/allwinner/phy-sun4i-usb.c
+++ b/drivers/phy/allwinner/phy-sun4i-usb.c
@@ -120,6 +120,7 @@ struct sun4i_usb_phy_cfg {
u8 phyctl_offset;
bool dedicated_clocks;
bool phy0_dual_route;
+ bool needs_phy2_siddq;
int missing_phys;
};

@@ -289,6 +290,50 @@ static int sun4i_usb_phy_init(struct phy *_phy)
return ret;
}

+ /* Some PHYs on some SoCs need the help of PHY2 to work. */
+ if (data->cfg->needs_phy2_siddq && phy->index != 2) {
+ struct sun4i_usb_phy *phy2 = &data->phys[2];
+
+ ret = clk_prepare_enable(phy2->clk);
+ if (ret) {
+ reset_control_assert(phy->reset);
+ clk_disable_unprepare(phy->clk2);
+ clk_disable_unprepare(phy->clk);
+ return ret;
+ }
+
+ ret = reset_control_deassert(phy2->reset);
+ if (ret) {
+ clk_disable_unprepare(phy2->clk);
+ reset_control_assert(phy->reset);
+ clk_disable_unprepare(phy->clk2);
+ clk_disable_unprepare(phy->clk);
+ return ret;
+ }
+
+ /*
+ * This extra clock is just needed to access the
+ * REG_HCI_PHY_CTL PMU register for PHY2.
+ */
+ ret = clk_prepare_enable(phy2->clk2);
+ if (ret) {
+ reset_control_assert(phy2->reset);
+ clk_disable_unprepare(phy2->clk);
+ reset_control_assert(phy->reset);
+ clk_disable_unprepare(phy->clk2);
+ clk_disable_unprepare(phy->clk);
+ return ret;
+ }
+
+ if (phy2->pmu && data->cfg->hci_phy_ctl_clear) {
+ val = readl(phy2->pmu + REG_HCI_PHY_CTL);
+ val &= ~data->cfg->hci_phy_ctl_clear;
+ writel(val, phy2->pmu + REG_HCI_PHY_CTL);
+ }
+
+ clk_disable_unprepare(phy->clk2);
+ }
+
if (phy->pmu && data->cfg->hci_phy_ctl_clear) {
val = readl(phy->pmu + REG_HCI_PHY_CTL);
val &= ~data->cfg->hci_phy_ctl_clear;
@@ -354,6 +399,13 @@ static int sun4i_usb_phy_exit(struct phy *_phy)
data->phy0_init = false;
}

+ if (data->cfg->needs_phy2_siddq && phy->index != 2) {
+ struct sun4i_usb_phy *phy2 = &data->phys[2];
+
+ clk_disable_unprepare(phy2->clk);
+ reset_control_assert(phy2->reset);
+ }
+
sun4i_usb_phy_passby(phy, 0);
reset_control_assert(phy->reset);
clk_disable_unprepare(phy->clk2);
@@ -785,6 +837,13 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
dev_err(dev, "failed to get clock %s\n", name);
return PTR_ERR(phy->clk2);
}
+ } else {
+ snprintf(name, sizeof(name), "pmu%d_clk", i);
+ phy->clk2 = devm_clk_get_optional(dev, name);
+ if (IS_ERR(phy->clk2)) {
+ dev_err(dev, "failed to get clock %s\n", name);
+ return PTR_ERR(phy->clk2);
+ }
}

snprintf(name, sizeof(name), "usb%d_reset", i);
--
2.25.1

2022-02-12 18:24:43

by Andre Przywara

[permalink] [raw]
Subject: [PATCH v10 11/18] dt-bindings: usb: Add H616 compatible string

The Allwinner H616 contains four fully OHCI/EHCI compatible USB host
controllers, so just add their compatible strings to the list of
generic OHCI/EHCI controllers.

Signed-off-by: Andre Przywara <[email protected]>
---
Documentation/devicetree/bindings/usb/generic-ehci.yaml | 1 +
Documentation/devicetree/bindings/usb/generic-ohci.yaml | 1 +
2 files changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/usb/generic-ehci.yaml b/Documentation/devicetree/bindings/usb/generic-ehci.yaml
index 8913497624de..f4fab05f60dd 100644
--- a/Documentation/devicetree/bindings/usb/generic-ehci.yaml
+++ b/Documentation/devicetree/bindings/usb/generic-ehci.yaml
@@ -30,6 +30,7 @@ properties:
- allwinner,sun4i-a10-ehci
- allwinner,sun50i-a64-ehci
- allwinner,sun50i-h6-ehci
+ - allwinner,sun50i-h616-ehci
- allwinner,sun5i-a13-ehci
- allwinner,sun6i-a31-ehci
- allwinner,sun7i-a20-ehci
diff --git a/Documentation/devicetree/bindings/usb/generic-ohci.yaml b/Documentation/devicetree/bindings/usb/generic-ohci.yaml
index acbf94fa5f74..d27e113b2e00 100644
--- a/Documentation/devicetree/bindings/usb/generic-ohci.yaml
+++ b/Documentation/devicetree/bindings/usb/generic-ohci.yaml
@@ -20,6 +20,7 @@ properties:
- allwinner,sun4i-a10-ohci
- allwinner,sun50i-a64-ohci
- allwinner,sun50i-h6-ohci
+ - allwinner,sun50i-h616-ohci
- allwinner,sun5i-a13-ohci
- allwinner,sun6i-a31-ohci
- allwinner,sun7i-a20-ohci
--
2.25.1

2022-02-13 18:11:43

by Andre Przywara

[permalink] [raw]
Subject: [PATCH v10 02/18] clk: sunxi-ng: h616: Add PLL derived 32KHz clock

The RTC section of the H616 manual mentions in a half-sentence the
existence of a clock "32K divided by PLL_PERI(2X)". This is used as
one of the possible inputs for the mux that selects the clock for the
32 KHz fanout pad. On the H616 this is routed to pin PG10, and some
boards use that clock output to compensate for a missing 32KHz crystal.
On the OrangePi Zero2 this is for instance connected to the LPO pin of
the WiFi/BT chip.
The new RTC clock binding requires this clock to be named as one input
clock, so we need to expose this to the DT. In contrast to the D1 SoC
there does not seem to be a gate for this clock, so just use a fixed
divider clock, using a newly assigned clock number.

Signed-off-by: Andre Przywara <[email protected]>
---
drivers/clk/sunxi-ng/ccu-sun50i-h616.c | 7 +++++++
drivers/clk/sunxi-ng/ccu-sun50i-h616.h | 2 +-
include/dt-bindings/clock/sun50i-h616-ccu.h | 1 +
3 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h616.c b/drivers/clk/sunxi-ng/ccu-sun50i-h616.c
index 49a2474cf314..f4e896b19a16 100644
--- a/drivers/clk/sunxi-ng/ccu-sun50i-h616.c
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-h616.c
@@ -704,6 +704,12 @@ static CLK_FIXED_FACTOR_HWS(pll_periph0_2x_clk, "pll-periph0-2x",
pll_periph0_parents,
1, 2, 0);

+static const struct clk_hw *pll_periph0_2x_hws[] = {
+ &pll_periph0_2x_clk.hw
+};
+static CLK_FIXED_FACTOR_HWS(pll_system_32k_clk, "pll-system-32k",
+ pll_periph0_2x_hws, 36621, 1, 0);
+
static const struct clk_hw *pll_periph1_parents[] = {
&pll_periph1_clk.common.hw
};
@@ -852,6 +858,7 @@ static struct clk_hw_onecell_data sun50i_h616_hw_clks = {
[CLK_PLL_DDR1] = &pll_ddr1_clk.common.hw,
[CLK_PLL_PERIPH0] = &pll_periph0_clk.common.hw,
[CLK_PLL_PERIPH0_2X] = &pll_periph0_2x_clk.hw,
+ [CLK_PLL_SYSTEM_32K] = &pll_system_32k_clk.hw,
[CLK_PLL_PERIPH1] = &pll_periph1_clk.common.hw,
[CLK_PLL_PERIPH1_2X] = &pll_periph1_2x_clk.hw,
[CLK_PLL_GPU] = &pll_gpu_clk.common.hw,
diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h616.h b/drivers/clk/sunxi-ng/ccu-sun50i-h616.h
index dd671b413f22..fdd2f4d5103f 100644
--- a/drivers/clk/sunxi-ng/ccu-sun50i-h616.h
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-h616.h
@@ -51,6 +51,6 @@

#define CLK_BUS_DRAM 56

-#define CLK_NUMBER (CLK_BUS_HDCP + 1)
+#define CLK_NUMBER (CLK_PLL_SYSTEM_32K + 1)

#endif /* _CCU_SUN50I_H616_H_ */
diff --git a/include/dt-bindings/clock/sun50i-h616-ccu.h b/include/dt-bindings/clock/sun50i-h616-ccu.h
index 4fc08b0df2f3..1191aca53ac6 100644
--- a/include/dt-bindings/clock/sun50i-h616-ccu.h
+++ b/include/dt-bindings/clock/sun50i-h616-ccu.h
@@ -111,5 +111,6 @@
#define CLK_BUS_TVE0 125
#define CLK_HDCP 126
#define CLK_BUS_HDCP 127
+#define CLK_PLL_SYSTEM_32K 128

#endif /* _DT_BINDINGS_CLK_SUN50I_H616_H_ */
--
2.25.1

2022-02-14 02:15:02

by Andre Przywara

[permalink] [raw]
Subject: [PATCH v10 12/18] phy: sun4i-usb: Rework HCI PHY (aka. "pmu_unk1") handling

As Icenowy pointed out, newer manuals (starting with H6) actually
document the register block at offset 0x800 as "HCI controller and PHY
interface", also describe the bits in our "PMU_UNK1" register.
Let's put proper names to those "unknown" variables and symbols.

While we are at it, generalise the existing code by allowing a bitmap
of bits to clear and set, to cover newer SoCs: The A100 and H616 use a
different bit for the SIDDQ control.

Signed-off-by: Andre Przywara <[email protected]>
---
drivers/phy/allwinner/phy-sun4i-usb.c | 30 ++++++++++++---------------
1 file changed, 13 insertions(+), 17 deletions(-)

diff --git a/drivers/phy/allwinner/phy-sun4i-usb.c b/drivers/phy/allwinner/phy-sun4i-usb.c
index 788dd5cdbb7d..142f4cafdc78 100644
--- a/drivers/phy/allwinner/phy-sun4i-usb.c
+++ b/drivers/phy/allwinner/phy-sun4i-usb.c
@@ -43,7 +43,7 @@
#define REG_PHYCTL_A33 0x10
#define REG_PHY_OTGCTL 0x20

-#define REG_PMU_UNK1 0x10
+#define REG_HCI_PHY_CTL 0x10

#define PHYCTL_DATA BIT(7)

@@ -82,6 +82,7 @@
/* A83T specific control bits for PHY0 */
#define PHY_CTL_VBUSVLDEXT BIT(5)
#define PHY_CTL_SIDDQ BIT(3)
+#define PHY_CTL_H3_SIDDQ BIT(1)

/* A83T specific control bits for PHY2 HSIC */
#define SUNXI_EHCI_HS_FORCE BIT(20)
@@ -115,9 +116,9 @@ struct sun4i_usb_phy_cfg {
int hsic_index;
enum sun4i_usb_phy_type type;
u32 disc_thresh;
+ u32 hci_phy_ctl_clear;
u8 phyctl_offset;
bool dedicated_clocks;
- bool enable_pmu_unk1;
bool phy0_dual_route;
int missing_phys;
};
@@ -288,6 +289,12 @@ static int sun4i_usb_phy_init(struct phy *_phy)
return ret;
}

+ if (phy->pmu && data->cfg->hci_phy_ctl_clear) {
+ val = readl(phy->pmu + REG_HCI_PHY_CTL);
+ val &= ~data->cfg->hci_phy_ctl_clear;
+ writel(val, phy->pmu + REG_HCI_PHY_CTL);
+ }
+
if (data->cfg->type == sun8i_a83t_phy ||
data->cfg->type == sun50i_h6_phy) {
if (phy->index == 0) {
@@ -297,11 +304,6 @@ static int sun4i_usb_phy_init(struct phy *_phy)
writel(val, data->base + data->cfg->phyctl_offset);
}
} else {
- if (phy->pmu && data->cfg->enable_pmu_unk1) {
- val = readl(phy->pmu + REG_PMU_UNK1);
- writel(val & ~2, phy->pmu + REG_PMU_UNK1);
- }
-
/* Enable USB 45 Ohm resistor calibration */
if (phy->index == 0)
sun4i_usb_phy_write(phy, PHY_RES45_CAL_EN, 0x01, 1);
@@ -863,7 +865,6 @@ static const struct sun4i_usb_phy_cfg sun4i_a10_cfg = {
.disc_thresh = 3,
.phyctl_offset = REG_PHYCTL_A10,
.dedicated_clocks = false,
- .enable_pmu_unk1 = false,
};

static const struct sun4i_usb_phy_cfg sun5i_a13_cfg = {
@@ -872,7 +873,6 @@ static const struct sun4i_usb_phy_cfg sun5i_a13_cfg = {
.disc_thresh = 2,
.phyctl_offset = REG_PHYCTL_A10,
.dedicated_clocks = false,
- .enable_pmu_unk1 = false,
};

static const struct sun4i_usb_phy_cfg sun6i_a31_cfg = {
@@ -881,7 +881,6 @@ static const struct sun4i_usb_phy_cfg sun6i_a31_cfg = {
.disc_thresh = 3,
.phyctl_offset = REG_PHYCTL_A10,
.dedicated_clocks = true,
- .enable_pmu_unk1 = false,
};

static const struct sun4i_usb_phy_cfg sun7i_a20_cfg = {
@@ -890,7 +889,6 @@ static const struct sun4i_usb_phy_cfg sun7i_a20_cfg = {
.disc_thresh = 2,
.phyctl_offset = REG_PHYCTL_A10,
.dedicated_clocks = false,
- .enable_pmu_unk1 = false,
};

static const struct sun4i_usb_phy_cfg sun8i_a23_cfg = {
@@ -899,7 +897,6 @@ static const struct sun4i_usb_phy_cfg sun8i_a23_cfg = {
.disc_thresh = 3,
.phyctl_offset = REG_PHYCTL_A10,
.dedicated_clocks = true,
- .enable_pmu_unk1 = false,
};

static const struct sun4i_usb_phy_cfg sun8i_a33_cfg = {
@@ -908,7 +905,6 @@ static const struct sun4i_usb_phy_cfg sun8i_a33_cfg = {
.disc_thresh = 3,
.phyctl_offset = REG_PHYCTL_A33,
.dedicated_clocks = true,
- .enable_pmu_unk1 = false,
};

static const struct sun4i_usb_phy_cfg sun8i_a83t_cfg = {
@@ -925,7 +921,7 @@ static const struct sun4i_usb_phy_cfg sun8i_h3_cfg = {
.disc_thresh = 3,
.phyctl_offset = REG_PHYCTL_A33,
.dedicated_clocks = true,
- .enable_pmu_unk1 = true,
+ .hci_phy_ctl_clear = PHY_CTL_H3_SIDDQ,
.phy0_dual_route = true,
};

@@ -935,7 +931,7 @@ static const struct sun4i_usb_phy_cfg sun8i_r40_cfg = {
.disc_thresh = 3,
.phyctl_offset = REG_PHYCTL_A33,
.dedicated_clocks = true,
- .enable_pmu_unk1 = true,
+ .hci_phy_ctl_clear = PHY_CTL_H3_SIDDQ,
.phy0_dual_route = true,
};

@@ -945,7 +941,7 @@ static const struct sun4i_usb_phy_cfg sun8i_v3s_cfg = {
.disc_thresh = 3,
.phyctl_offset = REG_PHYCTL_A33,
.dedicated_clocks = true,
- .enable_pmu_unk1 = true,
+ .hci_phy_ctl_clear = PHY_CTL_H3_SIDDQ,
.phy0_dual_route = true,
};

@@ -955,7 +951,7 @@ static const struct sun4i_usb_phy_cfg sun50i_a64_cfg = {
.disc_thresh = 3,
.phyctl_offset = REG_PHYCTL_A33,
.dedicated_clocks = true,
- .enable_pmu_unk1 = true,
+ .hci_phy_ctl_clear = PHY_CTL_H3_SIDDQ,
.phy0_dual_route = true,
};

--
2.25.1

2022-02-14 09:17:09

by Andre Przywara

[permalink] [raw]
Subject: [PATCH v10 16/18] arm64: dts: allwinner: h616: Add USB nodes

Add the nodes for the MUSB and the four USB host controllers to the SoC
.dtsi, along with the PHY node needed to bind all of them together.

EHCI/OHCI and MUSB are compatible to previous SoCs, but the PHY requires
some quirks (handled in the driver).

Signed-off-by: Andre Przywara <[email protected]>
---
.../arm64/boot/dts/allwinner/sun50i-h616.dtsi | 160 ++++++++++++++++++
1 file changed, 160 insertions(+)

diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi
index cc06cdd15ba5..bf27ad1890cb 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi
@@ -486,6 +486,166 @@ mdio0: mdio {
};
};

+ usbotg: usb@5100000 {
+ compatible = "allwinner,sun50i-h616-musb",
+ "allwinner,sun8i-h3-musb";
+ reg = <0x05100000 0x0400>;
+ clocks = <&ccu CLK_BUS_OTG>;
+ resets = <&ccu RST_BUS_OTG>;
+ interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "mc";
+ phys = <&usbphy 0>;
+ phy-names = "usb";
+ extcon = <&usbphy 0>;
+ status = "disabled";
+ };
+
+ usbphy: phy@5100400 {
+ compatible = "allwinner,sun50i-h616-usb-phy";
+ reg = <0x05100400 0x24>,
+ <0x05101800 0x14>,
+ <0x05200800 0x14>,
+ <0x05310800 0x14>,
+ <0x05311800 0x14>;
+ reg-names = "phy_ctrl",
+ "pmu0",
+ "pmu1",
+ "pmu2",
+ "pmu3";
+ clocks = <&ccu CLK_USB_PHY0>,
+ <&ccu CLK_USB_PHY1>,
+ <&ccu CLK_USB_PHY2>,
+ <&ccu CLK_USB_PHY3>,
+ <&ccu CLK_BUS_EHCI2>;
+ clock-names = "usb0_phy",
+ "usb1_phy",
+ "usb2_phy",
+ "usb3_phy",
+ "pmu2_clk";
+ resets = <&ccu RST_USB_PHY0>,
+ <&ccu RST_USB_PHY1>,
+ <&ccu RST_USB_PHY2>,
+ <&ccu RST_USB_PHY3>;
+ reset-names = "usb0_reset",
+ "usb1_reset",
+ "usb2_reset",
+ "usb3_reset";
+ status = "disabled";
+ #phy-cells = <1>;
+ };
+
+ ehci0: usb@5101000 {
+ compatible = "allwinner,sun50i-h616-ehci",
+ "generic-ehci";
+ reg = <0x05101000 0x100>;
+ interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_OHCI0>,
+ <&ccu CLK_BUS_EHCI0>,
+ <&ccu CLK_USB_OHCI0>;
+ resets = <&ccu RST_BUS_OHCI0>,
+ <&ccu RST_BUS_EHCI0>;
+ phys = <&usbphy 0>;
+ phy-names = "usb";
+ status = "disabled";
+ };
+
+ ohci0: usb@5101400 {
+ compatible = "allwinner,sun50i-h616-ohci",
+ "generic-ohci";
+ reg = <0x05101400 0x100>;
+ interrupts = <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_OHCI0>,
+ <&ccu CLK_USB_OHCI0>;
+ resets = <&ccu RST_BUS_OHCI0>;
+ phys = <&usbphy 0>;
+ phy-names = "usb";
+ status = "disabled";
+ };
+
+ ehci1: usb@5200000 {
+ compatible = "allwinner,sun50i-h616-ehci",
+ "generic-ehci";
+ reg = <0x05200000 0x100>;
+ interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_OHCI1>,
+ <&ccu CLK_BUS_EHCI1>,
+ <&ccu CLK_USB_OHCI1>;
+ resets = <&ccu RST_BUS_OHCI1>,
+ <&ccu RST_BUS_EHCI1>;
+ phys = <&usbphy 1>;
+ phy-names = "usb";
+ status = "disabled";
+ };
+
+ ohci1: usb@5200400 {
+ compatible = "allwinner,sun50i-h616-ohci",
+ "generic-ohci";
+ reg = <0x05200400 0x100>;
+ interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_OHCI1>,
+ <&ccu CLK_USB_OHCI1>;
+ resets = <&ccu RST_BUS_OHCI1>;
+ phys = <&usbphy 1>;
+ phy-names = "usb";
+ status = "disabled";
+ };
+
+ ehci2: usb@5310000 {
+ compatible = "allwinner,sun50i-h616-ehci",
+ "generic-ehci";
+ reg = <0x05310000 0x100>;
+ interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_OHCI2>,
+ <&ccu CLK_BUS_EHCI2>,
+ <&ccu CLK_USB_OHCI2>;
+ resets = <&ccu RST_BUS_OHCI2>,
+ <&ccu RST_BUS_EHCI2>;
+ phys = <&usbphy 2>;
+ phy-names = "usb";
+ status = "disabled";
+ };
+
+ ohci2: usb@5310400 {
+ compatible = "allwinner,sun50i-h616-ohci",
+ "generic-ohci";
+ reg = <0x05310400 0x100>;
+ interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_OHCI2>,
+ <&ccu CLK_USB_OHCI2>;
+ resets = <&ccu RST_BUS_OHCI2>;
+ phys = <&usbphy 2>;
+ phy-names = "usb";
+ status = "disabled";
+ };
+
+ ehci3: usb@5311000 {
+ compatible = "allwinner,sun50i-h616-ehci",
+ "generic-ehci";
+ reg = <0x05311000 0x100>;
+ interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_OHCI3>,
+ <&ccu CLK_BUS_EHCI3>,
+ <&ccu CLK_USB_OHCI3>;
+ resets = <&ccu RST_BUS_OHCI3>,
+ <&ccu RST_BUS_EHCI3>;
+ phys = <&usbphy 3>;
+ phy-names = "usb";
+ status = "disabled";
+ };
+
+ ohci3: usb@5311400 {
+ compatible = "allwinner,sun50i-h616-ohci",
+ "generic-ohci";
+ reg = <0x05311400 0x100>;
+ interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_OHCI3>,
+ <&ccu CLK_USB_OHCI3>;
+ resets = <&ccu RST_BUS_OHCI3>;
+ phys = <&usbphy 3>;
+ phy-names = "usb";
+ status = "disabled";
+ };
+
rtc: rtc@7000000 {
compatible = "allwinner,sun50i-h616-rtc";
reg = <0x07000000 0x400>;
--
2.25.1

2022-02-14 10:39:11

by Andre Przywara

[permalink] [raw]
Subject: [PATCH v10 04/18] rtc: sun6i: Add support for linear day storage

Newer versions of the Allwinner RTC, as for instance found in the H616
SoC, no longer store a broken-down day/month/year representation in the
RTC_DAY_REG, but just a linear day number.
The user manual does not give any indication about the expected epoch
time of this day count, but the BSP kernel uses the UNIX epoch, which
allows easy support due to existing conversion functions in the kernel.

Allow tagging a compatible string with a flag, and use that to mark
those new RTCs. Then convert between a UNIX day number (converted into
seconds) and the broken-down day representation using mktime64() and
time64_to_tm() in the set_time/get_time functions.

That enables support for the RTC in those new chips.

Signed-off-by: Andre Przywara <[email protected]>
Reviewed-by: Jernej Skrabec <[email protected]>
---
drivers/rtc/rtc-sun6i.c | 69 +++++++++++++++++++++++++++--------------
1 file changed, 46 insertions(+), 23 deletions(-)

diff --git a/drivers/rtc/rtc-sun6i.c b/drivers/rtc/rtc-sun6i.c
index dc3ae851841c..996d05938839 100644
--- a/drivers/rtc/rtc-sun6i.c
+++ b/drivers/rtc/rtc-sun6i.c
@@ -111,6 +111,8 @@
#define SUN6I_YEAR_MIN 1970
#define SUN6I_YEAR_OFF (SUN6I_YEAR_MIN - 1900)

+#define SECS_PER_DAY (24 * 3600ULL)
+
/*
* There are other differences between models, including:
*
@@ -134,12 +136,15 @@ struct sun6i_rtc_clk_data {
unsigned int has_auto_swt : 1;
};

+#define RTC_LINEAR_DAY BIT(0)
+
struct sun6i_rtc_dev {
struct rtc_device *rtc;
const struct sun6i_rtc_clk_data *data;
void __iomem *base;
int irq;
time64_t alarm;
+ unsigned long flags;

struct clk_hw hw;
struct clk_hw *int_osc;
@@ -468,22 +473,30 @@ static int sun6i_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
} while ((date != readl(chip->base + SUN6I_RTC_YMD)) ||
(time != readl(chip->base + SUN6I_RTC_HMS)));

+ if (chip->flags & RTC_LINEAR_DAY) {
+ /*
+ * Newer chips store a linear day number, the manual
+ * does not mandate any epoch base. The BSP driver uses
+ * the UNIX epoch, let's just copy that, as it's the
+ * easiest anyway.
+ */
+ rtc_time64_to_tm((date & 0xffff) * SECS_PER_DAY, rtc_tm);
+ } else {
+ rtc_tm->tm_mday = SUN6I_DATE_GET_DAY_VALUE(date);
+ rtc_tm->tm_mon = SUN6I_DATE_GET_MON_VALUE(date) - 1;
+ rtc_tm->tm_year = SUN6I_DATE_GET_YEAR_VALUE(date);
+
+ /*
+ * switch from (data_year->min)-relative offset to
+ * a (1900)-relative one
+ */
+ rtc_tm->tm_year += SUN6I_YEAR_OFF;
+ }
+
rtc_tm->tm_sec = SUN6I_TIME_GET_SEC_VALUE(time);
rtc_tm->tm_min = SUN6I_TIME_GET_MIN_VALUE(time);
rtc_tm->tm_hour = SUN6I_TIME_GET_HOUR_VALUE(time);

- rtc_tm->tm_mday = SUN6I_DATE_GET_DAY_VALUE(date);
- rtc_tm->tm_mon = SUN6I_DATE_GET_MON_VALUE(date);
- rtc_tm->tm_year = SUN6I_DATE_GET_YEAR_VALUE(date);
-
- rtc_tm->tm_mon -= 1;
-
- /*
- * switch from (data_year->min)-relative offset to
- * a (1900)-relative one
- */
- rtc_tm->tm_year += SUN6I_YEAR_OFF;
-
return 0;
}

@@ -568,20 +581,25 @@ static int sun6i_rtc_settime(struct device *dev, struct rtc_time *rtc_tm)
u32 date = 0;
u32 time = 0;

- rtc_tm->tm_year -= SUN6I_YEAR_OFF;
- rtc_tm->tm_mon += 1;
-
- date = SUN6I_DATE_SET_DAY_VALUE(rtc_tm->tm_mday) |
- SUN6I_DATE_SET_MON_VALUE(rtc_tm->tm_mon) |
- SUN6I_DATE_SET_YEAR_VALUE(rtc_tm->tm_year);
-
- if (is_leap_year(rtc_tm->tm_year + SUN6I_YEAR_MIN))
- date |= SUN6I_LEAP_SET_VALUE(1);
-
time = SUN6I_TIME_SET_SEC_VALUE(rtc_tm->tm_sec) |
SUN6I_TIME_SET_MIN_VALUE(rtc_tm->tm_min) |
SUN6I_TIME_SET_HOUR_VALUE(rtc_tm->tm_hour);

+ if (chip->flags & RTC_LINEAR_DAY) {
+ /* The division will cut off the H:M:S part of rtc_tm. */
+ date = div_u64(rtc_tm_to_time64(rtc_tm), SECS_PER_DAY);
+ } else {
+ rtc_tm->tm_year -= SUN6I_YEAR_OFF;
+ rtc_tm->tm_mon += 1;
+
+ date = SUN6I_DATE_SET_DAY_VALUE(rtc_tm->tm_mday) |
+ SUN6I_DATE_SET_MON_VALUE(rtc_tm->tm_mon) |
+ SUN6I_DATE_SET_YEAR_VALUE(rtc_tm->tm_year);
+
+ if (is_leap_year(rtc_tm->tm_year + SUN6I_YEAR_MIN))
+ date |= SUN6I_LEAP_SET_VALUE(1);
+ }
+
/* Check whether registers are writable */
if (sun6i_rtc_wait(chip, SUN6I_LOSC_CTRL,
SUN6I_LOSC_CTRL_ACC_MASK, 50)) {
@@ -714,6 +732,8 @@ static int sun6i_rtc_probe(struct platform_device *pdev)

platform_set_drvdata(pdev, chip);

+ chip->flags = (unsigned long)of_device_get_match_data(&pdev->dev);
+
chip->irq = platform_get_irq(pdev, 0);
if (chip->irq < 0)
return chip->irq;
@@ -760,7 +780,10 @@ static int sun6i_rtc_probe(struct platform_device *pdev)
return PTR_ERR(chip->rtc);

chip->rtc->ops = &sun6i_rtc_ops;
- chip->rtc->range_max = 2019686399LL; /* 2033-12-31 23:59:59 */
+ if (chip->flags & RTC_LINEAR_DAY)
+ chip->rtc->range_max = (65536 * SECS_PER_DAY) - 1;
+ else
+ chip->rtc->range_max = 2019686399LL; /* 2033-12-31 23:59:59 */

ret = devm_rtc_register_device(chip->rtc);
if (ret)
--
2.25.1

2022-02-18 00:27:57

by Rob Herring (Arm)

[permalink] [raw]
Subject: Re: [PATCH v10 11/18] dt-bindings: usb: Add H616 compatible string

On Fri, 11 Feb 2022 12:26:36 +0000, Andre Przywara wrote:
> The Allwinner H616 contains four fully OHCI/EHCI compatible USB host
> controllers, so just add their compatible strings to the list of
> generic OHCI/EHCI controllers.
>
> Signed-off-by: Andre Przywara <[email protected]>
> ---
> Documentation/devicetree/bindings/usb/generic-ehci.yaml | 1 +
> Documentation/devicetree/bindings/usb/generic-ohci.yaml | 1 +
> 2 files changed, 2 insertions(+)
>

Acked-by: Rob Herring <[email protected]>

2022-02-22 12:01:00

by Andre Przywara

[permalink] [raw]
Subject: Re: [PATCH v10 03/18] rtc: sun6i: Fix time overflow handling

On Fri, 11 Feb 2022 12:26:28 +0000
Andre Przywara <[email protected]> wrote:

Hi Alessandro, Alexandre,

I was wondering if you would consider taking this (as a fix)?
This (time_gap > U32_MAX) comparison looks flawed by design, and we should
use time_t these days anyway.

Also, do you have an opinion on the other RTC patches? The linear day
patch (v10 04/18)[1] and the broken-down alarm registers (v10 05/18)[2]
were on the list for a while now and are needed by other SoCs as well
(R329[3] and the RISC-V D1).

Cheers,
Andre
[1] https://lore.kernel.org/linux-arm-kernel/[email protected]/
[2] https://lore.kernel.org/linux-arm-kernel/[email protected]/
[3] https://lore.kernel.org/linux-arm-kernel/[email protected]/

> Using "unsigned long" for UNIX timestamps is never a good idea, and
> comparing the value of such a variable against U32_MAX does not do
> anything useful on 32-bit systems.
>
> Use the proper time64_t type when dealing with timestamps, and avoid
> cutting down the time range unnecessarily. This also fixes the flawed
> check for the alarm time being too far into the future.
>
> The check for this condition is actually somewhat theoretical, as the
> RTC counts till 2033 only anyways, and 2^32 seconds from now is not
> before the year 2157 - at which point I hope nobody will be using this
> hardware anymore.
>
> Signed-off-by: Andre Przywara <[email protected]>
> Reviewed-by: Jernej Skrabec <[email protected]>
> ---
> drivers/rtc/rtc-sun6i.c | 14 +++++---------
> 1 file changed, 5 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/rtc/rtc-sun6i.c b/drivers/rtc/rtc-sun6i.c
> index 35b34d14a1db..dc3ae851841c 100644
> --- a/drivers/rtc/rtc-sun6i.c
> +++ b/drivers/rtc/rtc-sun6i.c
> @@ -139,7 +139,7 @@ struct sun6i_rtc_dev {
> const struct sun6i_rtc_clk_data *data;
> void __iomem *base;
> int irq;
> - unsigned long alarm;
> + time64_t alarm;
>
> struct clk_hw hw;
> struct clk_hw *int_osc;
> @@ -511,10 +511,8 @@ static int sun6i_rtc_setalarm(struct device *dev,
> struct rtc_wkalrm *wkalrm) struct sun6i_rtc_dev *chip =
> dev_get_drvdata(dev); struct rtc_time *alrm_tm = &wkalrm->time;
> struct rtc_time tm_now;
> - unsigned long time_now = 0;
> - unsigned long time_set = 0;
> - unsigned long time_gap = 0;
> - int ret = 0;
> + time64_t time_now, time_set;
> + int ret;
>
> ret = sun6i_rtc_gettime(dev, &tm_now);
> if (ret < 0) {
> @@ -529,9 +527,7 @@ static int sun6i_rtc_setalarm(struct device *dev,
> struct rtc_wkalrm *wkalrm) return -EINVAL;
> }
>
> - time_gap = time_set - time_now;
> -
> - if (time_gap > U32_MAX) {
> + if ((time_set - time_now) > U32_MAX) {
> dev_err(dev, "Date too far in the future\n");
> return -EINVAL;
> }
> @@ -540,7 +536,7 @@ static int sun6i_rtc_setalarm(struct device *dev,
> struct rtc_wkalrm *wkalrm) writel(0, chip->base + SUN6I_ALRM_COUNTER);
> usleep_range(100, 300);
>
> - writel(time_gap, chip->base + SUN6I_ALRM_COUNTER);
> + writel(time_set - time_now, chip->base + SUN6I_ALRM_COUNTER);
> chip->alarm = time_set;
>
> sun6i_rtc_setaie(wkalrm->enabled, chip);

2022-02-23 09:15:58

by Samuel Holland

[permalink] [raw]
Subject: Re: [PATCH v10 02/18] clk: sunxi-ng: h616: Add PLL derived 32KHz clock

On 2/11/22 6:26 AM, Andre Przywara wrote:
> The RTC section of the H616 manual mentions in a half-sentence the
> existence of a clock "32K divided by PLL_PERI(2X)". This is used as
> one of the possible inputs for the mux that selects the clock for the
> 32 KHz fanout pad. On the H616 this is routed to pin PG10, and some
> boards use that clock output to compensate for a missing 32KHz crystal.
> On the OrangePi Zero2 this is for instance connected to the LPO pin of
> the WiFi/BT chip.
> The new RTC clock binding requires this clock to be named as one input
> clock, so we need to expose this to the DT. In contrast to the D1 SoC
> there does not seem to be a gate for this clock, so just use a fixed
> divider clock, using a newly assigned clock number.
>
> Signed-off-by: Andre Przywara <[email protected]>

Reviewed-by: Samuel Holland <[email protected]>

2022-02-23 09:45:30

by Samuel Holland

[permalink] [raw]
Subject: Re: [PATCH v10 14/18] phy: sun4i-usb: Introduce port2 SIDDQ quirk

On 2/11/22 6:26 AM, Andre Przywara wrote:
> At least the Allwinner H616 SoC requires a weird quirk to make most
> USB PHYs work: Only port2 works out of the box, but all other ports
> need some help from this port2 to work correctly: The CLK_BUS_PHY2 and
> RST_USB_PHY2 clock and reset need to be enabled, and the SIDDQ bit in
> the PMU PHY control register needs to be cleared. For this register to
> be accessible, CLK_BUS_ECHI2 needs to be ungated. Don't ask ....
>
> Instead of disguising this as some generic feature, do exactly that
> in our PHY init:
> If the quirk bit is set, and we initialise a PHY other than PHY2, ungate
> this one special clock, and clear the SIDDQ bit. We can pull in the
> other required clocks via the DT.
>
> Signed-off-by: Andre Przywara <[email protected]>
> ---
> drivers/phy/allwinner/phy-sun4i-usb.c | 59 +++++++++++++++++++++++++++
> 1 file changed, 59 insertions(+)
>
> diff --git a/drivers/phy/allwinner/phy-sun4i-usb.c b/drivers/phy/allwinner/phy-sun4i-usb.c
> index 126ef74d013c..316ef5fca831 100644
> --- a/drivers/phy/allwinner/phy-sun4i-usb.c
> +++ b/drivers/phy/allwinner/phy-sun4i-usb.c
> @@ -120,6 +120,7 @@ struct sun4i_usb_phy_cfg {
> u8 phyctl_offset;
> bool dedicated_clocks;
> bool phy0_dual_route;
> + bool needs_phy2_siddq;
> int missing_phys;
> };
>
> @@ -289,6 +290,50 @@ static int sun4i_usb_phy_init(struct phy *_phy)
> return ret;
> }
>
> + /* Some PHYs on some SoCs need the help of PHY2 to work. */
> + if (data->cfg->needs_phy2_siddq && phy->index != 2) {
> + struct sun4i_usb_phy *phy2 = &data->phys[2];
> +
> + ret = clk_prepare_enable(phy2->clk);
> + if (ret) {
> + reset_control_assert(phy->reset);
> + clk_disable_unprepare(phy->clk2);
> + clk_disable_unprepare(phy->clk);
> + return ret;
> + }
> +
> + ret = reset_control_deassert(phy2->reset);
> + if (ret) {
> + clk_disable_unprepare(phy2->clk);
> + reset_control_assert(phy->reset);
> + clk_disable_unprepare(phy->clk2);
> + clk_disable_unprepare(phy->clk);
> + return ret;
> + }
> +
> + /*
> + * This extra clock is just needed to access the
> + * REG_HCI_PHY_CTL PMU register for PHY2.
> + */
> + ret = clk_prepare_enable(phy2->clk2);
> + if (ret) {
> + reset_control_assert(phy2->reset);
> + clk_disable_unprepare(phy2->clk);
> + reset_control_assert(phy->reset);
> + clk_disable_unprepare(phy->clk2);
> + clk_disable_unprepare(phy->clk);

This is quite a lot of duplication. Please consider using goto for the error path.

> + return ret;
> + }
> +
> + if (phy2->pmu && data->cfg->hci_phy_ctl_clear) {
> + val = readl(phy2->pmu + REG_HCI_PHY_CTL);
> + val &= ~data->cfg->hci_phy_ctl_clear;
> + writel(val, phy2->pmu + REG_HCI_PHY_CTL);
> + }
> +
> + clk_disable_unprepare(phy->clk2);
> + }
> +
> if (phy->pmu && data->cfg->hci_phy_ctl_clear) {
> val = readl(phy->pmu + REG_HCI_PHY_CTL);
> val &= ~data->cfg->hci_phy_ctl_clear;
> @@ -354,6 +399,13 @@ static int sun4i_usb_phy_exit(struct phy *_phy)
> data->phy0_init = false;
> }
>
> + if (data->cfg->needs_phy2_siddq && phy->index != 2) {
> + struct sun4i_usb_phy *phy2 = &data->phys[2];
> +
> + clk_disable_unprepare(phy2->clk);
> + reset_control_assert(phy2->reset);
> + }
> +
> sun4i_usb_phy_passby(phy, 0);
> reset_control_assert(phy->reset);
> clk_disable_unprepare(phy->clk2);
> @@ -785,6 +837,13 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
> dev_err(dev, "failed to get clock %s\n", name);
> return PTR_ERR(phy->clk2);
> }
> + } else {
> + snprintf(name, sizeof(name), "pmu%d_clk", i);
> + phy->clk2 = devm_clk_get_optional(dev, name);

This clock is not documented anywhere in the binding.

Regards,
Samuel

> + if (IS_ERR(phy->clk2)) {
> + dev_err(dev, "failed to get clock %s\n", name);
> + return PTR_ERR(phy->clk2);
> + }
> }
>
> snprintf(name, sizeof(name), "usb%d_reset", i);
>

2022-02-23 10:16:37

by Samuel Holland

[permalink] [raw]
Subject: Re: [PATCH v10 12/18] phy: sun4i-usb: Rework HCI PHY (aka. "pmu_unk1") handling

On 2/11/22 6:26 AM, Andre Przywara wrote:
> As Icenowy pointed out, newer manuals (starting with H6) actually
> document the register block at offset 0x800 as "HCI controller and PHY
> interface", also describe the bits in our "PMU_UNK1" register.
> Let's put proper names to those "unknown" variables and symbols.
>
> While we are at it, generalise the existing code by allowing a bitmap
> of bits to clear and set, to cover newer SoCs: The A100 and H616 use a
> different bit for the SIDDQ control.
>
> Signed-off-by: Andre Przywara <[email protected]>

Acked-by: Samuel Holland <[email protected]>
Tested-by: Samuel Holland <[email protected]>

Tested on D1, which also requires this patch.

2022-03-08 23:57:16

by Alexandre Belloni

[permalink] [raw]
Subject: Re: (subset) [PATCH v10 03/18] rtc: sun6i: Fix time overflow handling

On Fri, 11 Feb 2022 12:26:28 +0000, Andre Przywara wrote:
> Using "unsigned long" for UNIX timestamps is never a good idea, and
> comparing the value of such a variable against U32_MAX does not do
> anything useful on 32-bit systems.
>
> Use the proper time64_t type when dealing with timestamps, and avoid
> cutting down the time range unnecessarily. This also fixes the flawed
> check for the alarm time being too far into the future.
>
> [...]

Applied, thanks!

[03/18] rtc: sun6i: Fix time overflow handling
commit: 25c9815569cefd4f719c6c1266fe897e57642278

Best regards,
--
Alexandre Belloni <[email protected]>

2022-03-09 00:21:12

by Alexandre Belloni

[permalink] [raw]
Subject: Re: (subset) [PATCH v10 04/18] rtc: sun6i: Add support for linear day storage

On Fri, 11 Feb 2022 12:26:29 +0000, Andre Przywara wrote:
> Newer versions of the Allwinner RTC, as for instance found in the H616
> SoC, no longer store a broken-down day/month/year representation in the
> RTC_DAY_REG, but just a linear day number.
> The user manual does not give any indication about the expected epoch
> time of this day count, but the BSP kernel uses the UNIX epoch, which
> allows easy support due to existing conversion functions in the kernel.
>
> [...]

Applied, thanks!

[04/18] rtc: sun6i: Add support for linear day storage
commit: 62a8306e7315a1ce4479bc7c4f35ba5f9c75b9ab

Best regards,
--
Alexandre Belloni <[email protected]>