[PATCH v3 01/21] dt-bindings: mmc: sunxi: Add Allwinner A100 and H616 compatibles

325 views
Skip to first unread message

Andre Przywara

unread,
Jan 17, 2021, 9:09:31 PM1/17/21
to Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Icenowy Zheng, Linus Walleij, Rob Herring, Clément Péron, Samuel Holland, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com
From: Yangtao Li <fr...@allwinnertech.com>

Add binding for A100's and H616's mmc and emmc controller.

Signed-off-by: Yangtao Li <fr...@allwinnertech.com>
Signed-off-by: Andre Przywara <andre.p...@arm.com>
Acked-by: Rob Herring <ro...@kernel.org>
---
.../devicetree/bindings/mmc/allwinner,sun4i-a10-mmc.yaml | 8 ++++++++
1 file changed, 8 insertions(+)

diff --git a/Documentation/devicetree/bindings/mmc/allwinner,sun4i-a10-mmc.yaml b/Documentation/devicetree/bindings/mmc/allwinner,sun4i-a10-mmc.yaml
index e82c9a07b6fb..e75b3a8ba816 100644
--- a/Documentation/devicetree/bindings/mmc/allwinner,sun4i-a10-mmc.yaml
+++ b/Documentation/devicetree/bindings/mmc/allwinner,sun4i-a10-mmc.yaml
@@ -26,6 +26,8 @@ properties:
- const: allwinner,sun9i-a80-mmc
- const: allwinner,sun50i-a64-emmc
- const: allwinner,sun50i-a64-mmc
+ - const: allwinner,sun50i-a100-emmc
+ - const: allwinner,sun50i-a100-mmc
- items:
- const: allwinner,sun8i-a83t-mmc
- const: allwinner,sun7i-a20-mmc
@@ -47,6 +49,12 @@ properties:
- items:
- const: allwinner,sun50i-h6-mmc
- const: allwinner,sun50i-a64-mmc
+ - items:
+ - const: allwinner,sun50i-h616-emmc
+ - const: allwinner,sun50i-a100-emmc
+ - items:
+ - const: allwinner,sun50i-h616-mmc
+ - const: allwinner,sun50i-a100-mmc

reg:
maxItems: 1
--
2.17.5

Andre Przywara

unread,
Jan 17, 2021, 9:09:31 PM1/17/21
to Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Icenowy Zheng, Linus Walleij, Rob Herring, Clément Péron, Samuel Holland, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com
Hi,

an update from the v2 in December, to add support for the Allwinner H616
SoC. This time it's based on sunxi/for-next, which is based on 5.11-rc1.
The A100 watchdog binding patch is already merged, so omitted,
and Ulf has already queued the two MMC patch to his next branch. I am
still including them here to get a complete series on the list.

I was wondering if at least the basic pinctrl, clock and MFD patch (up
until patch 9) might make it into 5.12? Maybe the EMAC (patches 10-12)
as well?

Besides some fixes and addressed comments, this version adds RSB support:
this seems to be a similar story like for the H6 (omitted from the manual,
but fully functional).

USB seems to work now *sometimes*, one issue was the dodgy power situation
when powering with a bad USB-C cable from a laptop. Powering from a proper
USB-C power supply works better, however I still get enumeration errors
from Linux ("error -62") occasionally. On some boots it works just fine.

I keep the reserved-memory node in the .dtsi for now. Trusted Firmware now
properly adds this to the DT, but U-Boot does not propagate this to a
freshly loaded DTB (using $fdtcontroladdr works, though). When this gets
fixed in U-Boot, we can remove this from the .dtsi.

For a more detailed changelog, see below.

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.

Various DT binding patches are sprinkled throughout the series, to add
the new compatible names right before they are used.
Patch 4 and 5 add pinctrl support, with the "-R" controller now being
crippled down to two I2C pins only. If we grow tired of repeating this
exercise for every new SoC variant, I am happy to revive my more
versatile sunxi pinctrl driver effort from a few years back [1].
Patch 7 and 8 add clock support. For the -R clock this is shared with
the H6 code, as the clocks are identical, with the H616 just having
fewer of them. The main clocks are different enough to warrant a separate
file.
Patch 9 teaches the AXP MFD driver to get along without having an
interrupt, as the H616 apparently does not have an NMI controller anymore.
Patch 11 and 12 add some tweaks to the syscon and EMAC driver, to deal
with the second EMAC clock used for the second Ethernet controller.
Patches 13 and 16 add USB support.

The remaining patches add DT bindings, which just add the new compatible
string along with an existing name as a fallback string.
Eventually we get the .dtsi for the SoC in patch 19, and the .dts for
the OrangePi Zero2 board[2] in the last patch.

We have U-Boot and Trusted-Firmware support in a working state, booting
via FEL or SD card and even TFTPing kernels work already [3][4].

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 can also be found here:
https://github.com/apritzel/linux/commits/h616-v3

Happy reviewing!

Cheers,
Andre

[1] https://patchwork.ozlabs.org/project/linux-gpio/cover/20171113012523.232...@arm.com/
[2] https://linux-sunxi.org/Xunlong_Orange_Pi_Zero2
[3] https://github.com/jernejsk/u-boot/commits/h616-v2
[4] https://github.com/apritzel/arm-trusted-firmware/commits/h616-v1

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 (19):
dt-bindings: pinctrl: Add Allwinner H616 compatible strings
pinctrl: sunxi: Add support for the Allwinner H616 pin controller
pinctrl: sunxi: Add support for the Allwinner H616-R pin controller
dt-bindings: clk: sunxi-ccu: Add compatible string for Allwinner H616
clk: sunxi-ng: Add support for the Allwinner H616 R-CCU
clk: sunxi-ng: Add support for the Allwinner H616 CCU
mfd: axp20x: Allow AXP chips without interrupt lines
dt-bindings: sram: sunxi-sram: Add H616 compatible string
soc: sunxi: sram: Add support for more than one EMAC clock
net: stmmac: dwmac-sun8i: Prepare for second EMAC clock register
phy: sun4i-usb: Rework HCI PHY (aka. "pmu_unk1") handling
dt-bindings: usb: Add H616 compatible string
dt-bindings: usb: sunxi-musb: Add H616 compatible string
phy: sun4i-usb: Add support for the H616 USB PHY
dt-bindings: watchdog: sun4i: Add H616 compatible string
dt-bindings: allwinner: Add H616 compatible strings
arm64: dts: allwinner: Add Allwinner H616 .dtsi file
dt-bindings: arm: sunxi: Add OrangePi Zero 2 binding
arm64: dts: allwinner: Add OrangePi Zero 2 .dts

Yangtao Li (2):
dt-bindings: mmc: sunxi: Add Allwinner A100 and H616 compatibles
mmc: sunxi: add support for A100 mmc controller

.../devicetree/bindings/arm/sunxi.yaml | 5 +
.../clock/allwinner,sun4i-a10-ccu.yaml | 2 +
.../bindings/i2c/marvell,mv64xxx-i2c.yaml | 21 +-
.../media/allwinner,sun4i-a10-ir.yaml | 16 +-
.../bindings/mmc/allwinner,sun4i-a10-mmc.yaml | 8 +
.../phy/allwinner,sun8i-h3-usb-phy.yaml | 4 +-
.../pinctrl/allwinner,sun4i-a10-pinctrl.yaml | 17 +-
.../bindings/rtc/allwinner,sun6i-a31-rtc.yaml | 3 +
.../bindings/spi/allwinner,sun6i-a31-spi.yaml | 1 +
.../allwinner,sun4i-a10-system-control.yaml | 1 +
.../usb/allwinner,sun4i-a10-musb.yaml | 3 +
.../watchdog/allwinner,sun4i-a10-wdt.yaml | 12 +-
arch/arm64/boot/dts/allwinner/Makefile | 1 +
.../allwinner/sun50i-h616-orangepi-zero2.dts | 240 ++++
.../arm64/boot/dts/allwinner/sun50i-h616.dtsi | 750 +++++++++++
drivers/clk/sunxi-ng/Kconfig | 7 +-
drivers/clk/sunxi-ng/Makefile | 1 +
drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c | 48 +
drivers/clk/sunxi-ng/ccu-sun50i-h616.c | 1150 +++++++++++++++++
drivers/clk/sunxi-ng/ccu-sun50i-h616.h | 56 +
drivers/mfd/axp20x.c | 17 +-
drivers/mmc/host/sunxi-mmc.c | 28 +-
.../net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 12 +-
drivers/phy/allwinner/phy-sun4i-usb.c | 40 +-
drivers/pinctrl/sunxi/Kconfig | 10 +
drivers/pinctrl/sunxi/Makefile | 2 +
drivers/pinctrl/sunxi/pinctrl-sun50i-h616-r.c | 56 +
drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c | 548 ++++++++
drivers/soc/sunxi/sunxi_sram.c | 31 +-
include/dt-bindings/clock/sun50i-h616-ccu.h | 115 ++
include/dt-bindings/reset/sun50i-h616-ccu.h | 70 +
31 files changed, 3204 insertions(+), 71 deletions(-)
create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-h616-orangepi-zero2.dts
create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi
create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-h616.c
create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-h616.h
create mode 100644 drivers/pinctrl/sunxi/pinctrl-sun50i-h616-r.c
create mode 100644 drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c
create mode 100644 include/dt-bindings/clock/sun50i-h616-ccu.h
create mode 100644 include/dt-bindings/reset/sun50i-h616-ccu.h

--
2.17.5

Andre Przywara

unread,
Jan 17, 2021, 9:09:33 PM1/17/21
to Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Icenowy Zheng, Linus Walleij, Rob Herring, Clément Péron, Samuel Holland, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com
From: Yangtao Li <fr...@allwinnertech.com>

This patch adds support for A100 MMC controller, which use word address
for internal dma.

Signed-off-by: Yangtao Li <fr...@allwinnertech.com>
Signed-off-by: Andre Przywara <andre.p...@arm.com>
---
drivers/mmc/host/sunxi-mmc.c | 28 +++++++++++++++++++++++++---
1 file changed, 25 insertions(+), 3 deletions(-)

diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c
index 6310693f2ac0..e46bb4e404a8 100644
--- a/drivers/mmc/host/sunxi-mmc.c
+++ b/drivers/mmc/host/sunxi-mmc.c
@@ -245,6 +245,7 @@ struct sunxi_idma_des {

struct sunxi_mmc_cfg {
u32 idma_des_size_bits;
+ u32 idma_des_shift;
const struct sunxi_mmc_clk_delay *clk_delays;

/* does the IP block support autocalibration? */
@@ -344,7 +345,7 @@ static int sunxi_mmc_init_host(struct sunxi_mmc_host *host)
/* Enable CEATA support */
mmc_writel(host, REG_FUNS, SDXC_CEATA_ON);
/* Set DMA descriptor list base address */
- mmc_writel(host, REG_DLBA, host->sg_dma);
+ mmc_writel(host, REG_DLBA, host->sg_dma >> host->cfg->idma_des_shift);

rval = mmc_readl(host, REG_GCTRL);
rval |= SDXC_INTERRUPT_ENABLE_BIT;
@@ -374,8 +375,10 @@ static void sunxi_mmc_init_idma_des(struct sunxi_mmc_host *host,

next_desc += sizeof(struct sunxi_idma_des);
pdes[i].buf_addr_ptr1 =
- cpu_to_le32(sg_dma_address(&data->sg[i]));
- pdes[i].buf_addr_ptr2 = cpu_to_le32((u32)next_desc);
+ cpu_to_le32(sg_dma_address(&data->sg[i]) >>
+ host->cfg->idma_des_shift);
+ pdes[i].buf_addr_ptr2 = cpu_to_le32((u32)next_desc >>
+ host->cfg->idma_des_shift);
}

pdes[0].config |= cpu_to_le32(SDXC_IDMAC_DES0_FD);
@@ -1179,6 +1182,23 @@ static const struct sunxi_mmc_cfg sun50i_a64_emmc_cfg = {
.needs_new_timings = true,
};

+static const struct sunxi_mmc_cfg sun50i_a100_cfg = {
+ .idma_des_size_bits = 16,
+ .idma_des_shift = 2,
+ .clk_delays = NULL,
+ .can_calibrate = true,
+ .mask_data0 = true,
+ .needs_new_timings = true,
+};
+
+static const struct sunxi_mmc_cfg sun50i_a100_emmc_cfg = {
+ .idma_des_size_bits = 13,
+ .idma_des_shift = 2,
+ .clk_delays = NULL,
+ .can_calibrate = true,
+ .needs_new_timings = true,
+};
+
static const struct of_device_id sunxi_mmc_of_match[] = {
{ .compatible = "allwinner,sun4i-a10-mmc", .data = &sun4i_a10_cfg },
{ .compatible = "allwinner,sun5i-a13-mmc", .data = &sun5i_a13_cfg },
@@ -1187,6 +1207,8 @@ static const struct of_device_id sunxi_mmc_of_match[] = {
{ .compatible = "allwinner,sun9i-a80-mmc", .data = &sun9i_a80_cfg },
{ .compatible = "allwinner,sun50i-a64-mmc", .data = &sun50i_a64_cfg },
{ .compatible = "allwinner,sun50i-a64-emmc", .data = &sun50i_a64_emmc_cfg },
+ { .compatible = "allwinner,sun50i-a100-mmc", .data = &sun50i_a100_cfg },
+ { .compatible = "allwinner,sun50i-a100-emmc", .data = &sun50i_a100_emmc_cfg },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, sunxi_mmc_of_match);
--
2.17.5

Andre Przywara

unread,
Jan 17, 2021, 9:09:35 PM1/17/21
to Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Icenowy Zheng, Linus Walleij, Rob Herring, Clément Péron, Samuel Holland, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, linux...@vger.kernel.org, devic...@vger.kernel.org
A new SoC, a new compatible string.
Also we were too miserly with just allowing seven interrupt banks.

Signed-off-by: Andre Przywara <andre.p...@arm.com>
---
.../pinctrl/allwinner,sun4i-a10-pinctrl.yaml | 17 +++++++++++++++--
1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/pinctrl/allwinner,sun4i-a10-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/allwinner,sun4i-a10-pinctrl.yaml
index 5240487dfe50..cce63c3cc463 100644
--- a/Documentation/devicetree/bindings/pinctrl/allwinner,sun4i-a10-pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/allwinner,sun4i-a10-pinctrl.yaml
@@ -53,6 +53,8 @@ properties:
- allwinner,sun50i-h5-pinctrl
- allwinner,sun50i-h6-pinctrl
- allwinner,sun50i-h6-r-pinctrl
+ - allwinner,sun50i-h616-pinctrl
+ - allwinner,sun50i-h616-r-pinctrl
- allwinner,suniv-f1c100s-pinctrl
- nextthing,gr8-pinctrl

@@ -61,7 +63,7 @@ properties:

interrupts:
minItems: 1
- maxItems: 7
+ maxItems: 8
description:
One interrupt per external interrupt bank supported on the
controller, sorted by bank number ascending order.
@@ -91,7 +93,7 @@ properties:
bank found in the controller
$ref: /schemas/types.yaml#/definitions/uint32-array
minItems: 1
- maxItems: 5
+ maxItems: 8

patternProperties:
# It's pretty scary, but the basic idea is that:
@@ -145,6 +147,17 @@ allOf:
# boards are defining it at the moment so it would generate a lot of
# warnings.

+ - if:
+ properties:
+ compatible:
+ enum:
+ - allwinner,sun50i-h616-pinctrl
+
+ then:
+ properties:
+ interrupts:
+ minItems: 8
+
- if:
properties:
compatible:
--
2.17.5

Andre Przywara

unread,
Jan 17, 2021, 9:09:38 PM1/17/21
to Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Icenowy Zheng, Linus Walleij, Rob Herring, Clément Péron, Samuel Holland, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, linux...@vger.kernel.org
Port A is used for an internal connection to some analogue circuitry
which looks like an AC200 IP (as in the H6), though this is not
mentioned in the manual.

Signed-off-by: Andre Przywara <andre.p...@arm.com>
---
drivers/pinctrl/sunxi/Kconfig | 5 +
drivers/pinctrl/sunxi/Makefile | 1 +
drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c | 548 ++++++++++++++++++++
3 files changed, 554 insertions(+)
create mode 100644 drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c

diff --git a/drivers/pinctrl/sunxi/Kconfig b/drivers/pinctrl/sunxi/Kconfig
index 593293584ecc..73e88ce71a48 100644
--- a/drivers/pinctrl/sunxi/Kconfig
+++ b/drivers/pinctrl/sunxi/Kconfig
@@ -119,4 +119,9 @@ config PINCTRL_SUN50I_H6_R
default ARM64 && ARCH_SUNXI
select PINCTRL_SUNXI

+config PINCTRL_SUN50I_H616
+ bool "Support for the Allwinner H616 PIO"
+ default ARM64 && ARCH_SUNXI
+ select PINCTRL_SUNXI
+
endif
diff --git a/drivers/pinctrl/sunxi/Makefile b/drivers/pinctrl/sunxi/Makefile
index 8b7ff0dc3bdf..5359327a3c8f 100644
--- a/drivers/pinctrl/sunxi/Makefile
+++ b/drivers/pinctrl/sunxi/Makefile
@@ -23,5 +23,6 @@ obj-$(CONFIG_PINCTRL_SUN8I_V3S) += pinctrl-sun8i-v3s.o
obj-$(CONFIG_PINCTRL_SUN50I_H5) += pinctrl-sun50i-h5.o
obj-$(CONFIG_PINCTRL_SUN50I_H6) += pinctrl-sun50i-h6.o
obj-$(CONFIG_PINCTRL_SUN50I_H6_R) += pinctrl-sun50i-h6-r.o
+obj-$(CONFIG_PINCTRL_SUN50I_H616) += pinctrl-sun50i-h616.o
obj-$(CONFIG_PINCTRL_SUN9I_A80) += pinctrl-sun9i-a80.o
obj-$(CONFIG_PINCTRL_SUN9I_A80_R) += pinctrl-sun9i-a80-r.o
diff --git a/drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c b/drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c
new file mode 100644
index 000000000000..ce1917e230f4
--- /dev/null
+++ b/drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c
@@ -0,0 +1,548 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Allwinner H616 SoC pinctrl driver.
+ *
+ * Copyright (C) 2020 Arm Ltd.
+ * based on the H6 pinctrl driver
+ * Copyright (C) 2017 Icenowy Zheng <ice...@aosc.io>
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/pinctrl.h>
+
+#include "pinctrl-sunxi.h"
+
+static const struct sunxi_desc_pin h616_pins[] = {
+ /* Internal connection to the AC200 part */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 0),
+ SUNXI_FUNCTION(0x2, "emac1")), /* ERXD1 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 1),
+ SUNXI_FUNCTION(0x2, "emac1")), /* ERXD0 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 2),
+ SUNXI_FUNCTION(0x2, "emac1")), /* ECRS_DV */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 3),
+ SUNXI_FUNCTION(0x2, "emac1")), /* ERXERR */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 4),
+ SUNXI_FUNCTION(0x2, "emac1")), /* ETXD1 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 5),
+ SUNXI_FUNCTION(0x2, "emac1")), /* ETXD0 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 6),
+ SUNXI_FUNCTION(0x2, "emac1")), /* ETXCK */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 7),
+ SUNXI_FUNCTION(0x2, "emac1")), /* ETXEN */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 8),
+ SUNXI_FUNCTION(0x2, "emac1")), /* EMDC */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 9),
+ SUNXI_FUNCTION(0x2, "emac1")), /* EMDIO */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 10),
+ SUNXI_FUNCTION(0x2, "i2c3")), /* SCK */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 11),
+ SUNXI_FUNCTION(0x2, "i2c3")), /* SDA */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 12),
+ SUNXI_FUNCTION(0x2, "pwm5")),
+ /* Hole */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 0),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* WE */
+ SUNXI_FUNCTION(0x3, "mmc2"), /* DS */
+ SUNXI_FUNCTION(0x4, "spi0"), /* CLK */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 0)), /* PC_EINT0 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 1),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* ALE */
+ SUNXI_FUNCTION(0x3, "mmc2"), /* RST */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 1)), /* PC_EINT1 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 2),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* CLE */
+ SUNXI_FUNCTION(0x4, "spi0"), /* MOSI */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 2)), /* PC_EINT2 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 3),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* CE1 */
+ SUNXI_FUNCTION(0x4, "spi0"), /* CS0 */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 3)), /* PC_EINT3 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 4),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* CE0 */
+ SUNXI_FUNCTION(0x4, "spi0"), /* MISO */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 4)), /* PC_EINT4 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 5),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* RE */
+ SUNXI_FUNCTION(0x3, "mmc2"), /* CLK */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 5)), /* PC_EINT5 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 6),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* RB0 */
+ SUNXI_FUNCTION(0x3, "mmc2"), /* CMD */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 6)), /* PC_EINT6 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 7),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* RB1 */
+ SUNXI_FUNCTION(0x4, "spi0"), /* CS1 */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 7)), /* PC_EINT7 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 8),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* DQ7 */
+ SUNXI_FUNCTION(0x3, "mmc2"), /* D3 */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 8)), /* PC_EINT8 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 9),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* DQ6 */
+ SUNXI_FUNCTION(0x3, "mmc2"), /* D4 */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 9)), /* PC_EINT9 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 10),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* DQ5 */
+ SUNXI_FUNCTION(0x3, "mmc2"), /* D0 */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 10)), /* PC_EINT10 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 11),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* DQ4 */
+ SUNXI_FUNCTION(0x3, "mmc2"), /* D5 */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 11)), /* PC_EINT11 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 12),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* DQS */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 12)), /* PC_EINT12 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 13),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* DQ3 */
+ SUNXI_FUNCTION(0x3, "mmc2"), /* D1 */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 13)), /* PC_EINT13 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 14),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* DQ2 */
+ SUNXI_FUNCTION(0x3, "mmc2"), /* D6 */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 14)), /* PC_EINT14 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 15),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* DQ1 */
+ SUNXI_FUNCTION(0x3, "mmc2"), /* D2 */
+ SUNXI_FUNCTION(0x4, "spi0"), /* WP */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 15)), /* PC_EINT15 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 16),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* DQ0 */
+ SUNXI_FUNCTION(0x3, "mmc2"), /* D7 */
+ SUNXI_FUNCTION(0x4, "spi0"), /* HOLD */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 16)), /* PC_EINT16 */
+ /* Hole */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 0),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc0"), /* D1 */
+ SUNXI_FUNCTION(0x3, "jtag"), /* MS */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 4, 0)), /* PF_EINT0 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 1),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc0"), /* D0 */
+ SUNXI_FUNCTION(0x3, "jtag"), /* DI */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 4, 1)), /* PF_EINT1 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 2),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc0"), /* CLK */
+ SUNXI_FUNCTION(0x3, "uart0"), /* TX */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 4, 2)), /* PF_EINT2 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 3),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc0"), /* CMD */
+ SUNXI_FUNCTION(0x3, "jtag"), /* DO */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 4, 3)), /* PF_EINT3 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 4),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc0"), /* D3 */
+ SUNXI_FUNCTION(0x3, "uart0"), /* RX */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 4, 4)), /* PF_EINT4 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 5),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc0"), /* D2 */
+ SUNXI_FUNCTION(0x3, "jtag"), /* CK */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 4, 5)), /* PF_EINT5 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 6),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 4, 6)), /* PF_EINT6 */
+ /* Hole */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 0),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc1"), /* CLK */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 5, 0)), /* PG_EINT0 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 1),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc1"), /* CMD */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 5, 1)), /* PG_EINT1 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 2),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc1"), /* D0 */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 5, 2)), /* PG_EINT2 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 3),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc1"), /* D1 */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 5, 3)), /* PG_EINT3 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 4),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc1"), /* D2 */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 5, 4)), /* PG_EINT4 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 5),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc1"), /* D3 */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 5, 5)), /* PG_EINT5 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 6),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "uart1"), /* TX */
+ SUNXI_FUNCTION(0x4, "jtag"), /* MS */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 5, 6)), /* PG_EINT6 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 7),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "uart1"), /* RX */
+ SUNXI_FUNCTION(0x4, "jtag"), /* CK */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 5, 7)), /* PG_EINT7 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 8),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "uart1"), /* RTS */
+ SUNXI_FUNCTION(0x3, "clock"), /* PLL_LOCK_DEBUG */
+ SUNXI_FUNCTION(0x4, "jtag"), /* DO */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 5, 8)), /* PG_EINT8 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 9),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "uart1"), /* CTS */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 5, 9)), /* PG_EINT9 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 10),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2s2"), /* MCLK */
+ SUNXI_FUNCTION(0x3, "clock"), /* X32KFOUT */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 5, 10)), /* PG_EINT10 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 11),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2s2"), /* BCLK */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 5, 11)), /* PG_EINT11 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 12),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2s2"), /* SYNC */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 5, 12)), /* PG_EINT12 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 13),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2s2"), /* DOUT */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 5, 13)), /* PG_EINT13 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 14),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2s2"), /* DIN */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 5, 14)), /* PG_EINT14 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 15),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "uart2"), /* TX */
+ SUNXI_FUNCTION(0x5, "i2c4"), /* SCK */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 5, 15)), /* PG_EINT15 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 16),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "uart2"), /* RX */
+ SUNXI_FUNCTION(0x5, "i2c4"), /* SDA */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 5, 16)), /* PG_EINT16 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 17),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "uart2"), /* RTS */
+ SUNXI_FUNCTION(0x5, "i2c3"), /* SCK */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 5, 17)), /* PG_EINT17 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 18),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "uart2"), /* CTS */
+ SUNXI_FUNCTION(0x5, "i2c3"), /* SDA */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 5, 18)), /* PG_EINT18 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 19),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x4, "pwm1"),
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 5, 19)), /* PG_EINT19 */
+ /* Hole */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 0),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "uart0"), /* TX */
+ SUNXI_FUNCTION(0x4, "pwm3"),
+ SUNXI_FUNCTION(0x5, "i2c1"), /* SCK */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 6, 0)), /* PH_EINT0 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 1),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "uart0"), /* RX */
+ SUNXI_FUNCTION(0x4, "pwm4"),
+ SUNXI_FUNCTION(0x5, "i2c1"), /* SDA */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 6, 1)), /* PH_EINT1 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 2),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "uart5"), /* TX */
+ SUNXI_FUNCTION(0x3, "spdif"), /* MCLK */
+ SUNXI_FUNCTION(0x4, "pwm2"),
+ SUNXI_FUNCTION(0x5, "i2c2"), /* SCK */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 6, 2)), /* PH_EINT2 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 3),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "uart5"), /* RX */
+ SUNXI_FUNCTION(0x4, "pwm1"),
+ SUNXI_FUNCTION(0x5, "i2c2"), /* SDA */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 6, 3)), /* PH_EINT3 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 4),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x3, "spdif"), /* OUT */
+ SUNXI_FUNCTION(0x5, "i2c3"), /* SCK */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 6, 4)), /* PH_EINT4 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 5),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "uart2"), /* TX */
+ SUNXI_FUNCTION(0x3, "i2s3"), /* MCLK */
+ SUNXI_FUNCTION(0x4, "spi1"), /* CS0 */
+ SUNXI_FUNCTION(0x5, "i2c3"), /* SDA */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 6, 5)), /* PH_EINT5 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 6),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "uart2"), /* RX */
+ SUNXI_FUNCTION(0x3, "i2s3"), /* BCLK */
+ SUNXI_FUNCTION(0x4, "spi1"), /* CLK */
+ SUNXI_FUNCTION(0x5, "i2c4"), /* SCK */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 6, 6)), /* PH_EINT6 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 7),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "uart2"), /* RTS */
+ SUNXI_FUNCTION(0x3, "i2s3"), /* SYNC */
+ SUNXI_FUNCTION(0x4, "spi1"), /* MOSI */
+ SUNXI_FUNCTION(0x5, "i2c4"), /* SDA */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 6, 7)), /* PH_EINT7 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 8),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "uart2"), /* CTS */
+ SUNXI_FUNCTION(0x3, "i2s3"), /* DO0 */
+ SUNXI_FUNCTION(0x4, "spi1"), /* MISO */
+ SUNXI_FUNCTION(0x5, "i2s3"), /* DI1 */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 6, 8)), /* PH_EINT8 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 9),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x3, "i2s3"), /* DI0 */
+ SUNXI_FUNCTION(0x4, "spi1"), /* CS1 */
+ SUNXI_FUNCTION(0x3, "i2s3"), /* DO1 */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 6, 9)), /* PH_EINT9 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 10),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x3, "ir_rx"),
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 6, 10)), /* PH_EINT10 */
+ /* Hole */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 0),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac0"), /* ERXD3 */
+ SUNXI_FUNCTION(0x3, "dmic"), /* CLK */
+ SUNXI_FUNCTION(0x4, "i2s0"), /* MCLK */
+ SUNXI_FUNCTION(0x5, "hdmi"), /* HSCL */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 7, 0)), /* PI_EINT0 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 1),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac0"), /* ERXD2 */
+ SUNXI_FUNCTION(0x3, "dmic"), /* DATA0 */
+ SUNXI_FUNCTION(0x4, "i2s0"), /* BCLK */
+ SUNXI_FUNCTION(0x5, "hdmi"), /* HSDA */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 7, 1)), /* PI_EINT1 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 2),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac0"), /* ERXD1 */
+ SUNXI_FUNCTION(0x3, "dmic"), /* DATA1 */
+ SUNXI_FUNCTION(0x4, "i2s0"), /* SYNC */
+ SUNXI_FUNCTION(0x5, "hdmi"), /* HCEC */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 7, 2)), /* PI_EINT2 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 3),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac0"), /* ERXD0 */
+ SUNXI_FUNCTION(0x3, "dmic"), /* DATA2 */
+ SUNXI_FUNCTION(0x4, "i2s0_dout0"), /* DO0 */
+ SUNXI_FUNCTION(0x5, "i2s0_din1"), /* DI1 */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 7, 3)), /* PI_EINT3 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 4),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac0"), /* ERXCK */
+ SUNXI_FUNCTION(0x3, "dmic"), /* DATA3 */
+ SUNXI_FUNCTION(0x4, "i2s0_din0"), /* DI0 */
+ SUNXI_FUNCTION(0x5, "i2s0_dout1"), /* DO1 */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 7, 4)), /* PI_EINT4 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 5),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac0"), /* ERXCTL */
+ SUNXI_FUNCTION(0x3, "uart2"), /* TX */
+ SUNXI_FUNCTION(0x4, "ts0"), /* CLK */
+ SUNXI_FUNCTION(0x5, "i2c0"), /* SCK */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 7, 5)), /* PI_EINT5 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 6),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac0"), /* ENULL */
+ SUNXI_FUNCTION(0x3, "uart2"), /* RX */
+ SUNXI_FUNCTION(0x4, "ts0"), /* ERR */
+ SUNXI_FUNCTION(0x5, "i2c0"), /* SDA */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 7, 6)), /* PI_EINT6 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 7),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac0"), /* ETXD3 */
+ SUNXI_FUNCTION(0x3, "uart2"), /* RTS */
+ SUNXI_FUNCTION(0x4, "ts0"), /* SYNC */
+ SUNXI_FUNCTION(0x5, "i2c1"), /* SCK */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 7, 7)), /* PI_EINT7 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 8),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac0"), /* ETXD2 */
+ SUNXI_FUNCTION(0x3, "uart2"), /* CTS */
+ SUNXI_FUNCTION(0x4, "ts0"), /* DVLD */
+ SUNXI_FUNCTION(0x5, "i2c1"), /* SDA */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 7, 8)), /* PI_EINT8 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 9),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac0"), /* ETXD1 */
+ SUNXI_FUNCTION(0x3, "uart3"), /* TX */
+ SUNXI_FUNCTION(0x4, "ts0"), /* D0 */
+ SUNXI_FUNCTION(0x5, "i2c2"), /* SCK */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 7, 9)), /* PI_EINT9 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 10),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac0"), /* ETXD0 */
+ SUNXI_FUNCTION(0x3, "uart3"), /* RX */
+ SUNXI_FUNCTION(0x4, "ts0"), /* D1 */
+ SUNXI_FUNCTION(0x5, "i2c2"), /* SDA */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 7, 10)), /* PI_EINT10 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 11),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac0"), /* ETXCK */
+ SUNXI_FUNCTION(0x3, "uart3"), /* RTS */
+ SUNXI_FUNCTION(0x4, "ts0"), /* D2 */
+ SUNXI_FUNCTION(0x5, "pwm1"),
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 7, 11)), /* PI_EINT11 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 12),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac0"), /* ETXCTL */
+ SUNXI_FUNCTION(0x3, "uart3"), /* CTS */
+ SUNXI_FUNCTION(0x4, "ts0"), /* D3 */
+ SUNXI_FUNCTION(0x5, "pwm2"),
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 7, 12)), /* PI_EINT12 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 13),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac0"), /* ECLKIN */
+ SUNXI_FUNCTION(0x3, "uart4"), /* TX */
+ SUNXI_FUNCTION(0x4, "ts0"), /* D4 */
+ SUNXI_FUNCTION(0x5, "pwm3"),
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 7, 13)), /* PI_EINT13 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 14),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac0"), /* MDC */
+ SUNXI_FUNCTION(0x3, "uart4"), /* RX */
+ SUNXI_FUNCTION(0x4, "ts0"), /* D5 */
+ SUNXI_FUNCTION(0x5, "pwm4"),
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 7, 14)), /* PI_EINT14 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 15),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac0"), /* MDIO */
+ SUNXI_FUNCTION(0x3, "uart4"), /* RTS */
+ SUNXI_FUNCTION(0x4, "ts0"), /* D6 */
+ SUNXI_FUNCTION(0x5, "clock"), /* CLK_FANOUT0 */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 7, 15)), /* PI_EINT15 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 16),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac0"), /* EPHY_CLK */
+ SUNXI_FUNCTION(0x3, "uart4"), /* CTS */
+ SUNXI_FUNCTION(0x4, "ts0"), /* D7 */
+ SUNXI_FUNCTION(0x5, "clock"), /* CLK_FANOUT1 */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 7, 16)), /* PI_EINT16 */
+};
+static const unsigned int h616_irq_bank_map[] = { 0, 2, 3, 4, 5, 6, 7, 8 };
+
+static const struct sunxi_pinctrl_desc h616_pinctrl_data = {
+ .pins = h616_pins,
+ .npins = ARRAY_SIZE(h616_pins),
+ .irq_banks = ARRAY_SIZE(h616_irq_bank_map),
+ .irq_bank_map = h616_irq_bank_map,
+ .irq_read_needs_mux = true,
+ .io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_SEL,
+};
+
+static int h616_pinctrl_probe(struct platform_device *pdev)
+{
+ return sunxi_pinctrl_init(pdev, &h616_pinctrl_data);
+}
+
+static const struct of_device_id h616_pinctrl_match[] = {
+ { .compatible = "allwinner,sun50i-h616-pinctrl", },
+ {}
+};
+
+static struct platform_driver h616_pinctrl_driver = {
+ .probe = h616_pinctrl_probe,
+ .driver = {
+ .name = "sun50i-h616-pinctrl",
+ .of_match_table = h616_pinctrl_match,
+ },
+};
+builtin_platform_driver(h616_pinctrl_driver);
--
2.17.5

Andre Przywara

unread,
Jan 17, 2021, 9:09:39 PM1/17/21
to Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Icenowy Zheng, Linus Walleij, Rob Herring, Clément Péron, Samuel Holland, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, linux...@vger.kernel.org
There are only two pins left now, used to connect to the PMIC via I2C.

Signed-off-by: Andre Przywara <andre.p...@arm.com>
Acked-by: Maxime Ripard <mri...@kernel.org>
Reviewed-by: Jernej Skrabec <jernej....@siol.net>
---
drivers/pinctrl/sunxi/Kconfig | 5 ++
drivers/pinctrl/sunxi/Makefile | 1 +
drivers/pinctrl/sunxi/pinctrl-sun50i-h616-r.c | 56 +++++++++++++++++++
3 files changed, 62 insertions(+)
create mode 100644 drivers/pinctrl/sunxi/pinctrl-sun50i-h616-r.c

diff --git a/drivers/pinctrl/sunxi/Kconfig b/drivers/pinctrl/sunxi/Kconfig
index 73e88ce71a48..33751a6a0757 100644
--- a/drivers/pinctrl/sunxi/Kconfig
+++ b/drivers/pinctrl/sunxi/Kconfig
@@ -124,4 +124,9 @@ config PINCTRL_SUN50I_H616
default ARM64 && ARCH_SUNXI
select PINCTRL_SUNXI

+config PINCTRL_SUN50I_H616_R
+ bool "Support for the Allwinner H616 R-PIO"
+ default ARM64 && ARCH_SUNXI
+ select PINCTRL_SUNXI
+
endif
diff --git a/drivers/pinctrl/sunxi/Makefile b/drivers/pinctrl/sunxi/Makefile
index 5359327a3c8f..d3440c42b9d6 100644
--- a/drivers/pinctrl/sunxi/Makefile
+++ b/drivers/pinctrl/sunxi/Makefile
@@ -24,5 +24,6 @@ obj-$(CONFIG_PINCTRL_SUN50I_H5) += pinctrl-sun50i-h5.o
obj-$(CONFIG_PINCTRL_SUN50I_H6) += pinctrl-sun50i-h6.o
obj-$(CONFIG_PINCTRL_SUN50I_H6_R) += pinctrl-sun50i-h6-r.o
obj-$(CONFIG_PINCTRL_SUN50I_H616) += pinctrl-sun50i-h616.o
+obj-$(CONFIG_PINCTRL_SUN50I_H616_R) += pinctrl-sun50i-h616-r.o
obj-$(CONFIG_PINCTRL_SUN9I_A80) += pinctrl-sun9i-a80.o
obj-$(CONFIG_PINCTRL_SUN9I_A80_R) += pinctrl-sun9i-a80-r.o
diff --git a/drivers/pinctrl/sunxi/pinctrl-sun50i-h616-r.c b/drivers/pinctrl/sunxi/pinctrl-sun50i-h616-r.c
new file mode 100644
index 000000000000..8e4f10ab96ce
--- /dev/null
+++ b/drivers/pinctrl/sunxi/pinctrl-sun50i-h616-r.c
@@ -0,0 +1,56 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Allwinner H616 R_PIO pin controller driver
+ *
+ * Copyright (C) 2020 Arm Ltd.
+ * Based on former work, which is:
+ * Copyright (C) 2017 Icenowy Zheng <ice...@aosc.io>
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/reset.h>
+
+#include "pinctrl-sunxi.h"
+
+static const struct sunxi_desc_pin sun50i_h616_r_pins[] = {
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 0),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "s_rsb"), /* SCK */
+ SUNXI_FUNCTION(0x3, "s_i2c")), /* SCK */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 1),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "s_rsb"), /* SDA */
+ SUNXI_FUNCTION(0x3, "s_i2c")), /* SDA */
+};
+
+static const struct sunxi_pinctrl_desc sun50i_h616_r_pinctrl_data = {
+ .pins = sun50i_h616_r_pins,
+ .npins = ARRAY_SIZE(sun50i_h616_r_pins),
+ .pin_base = PL_BASE,
+};
+
+static int sun50i_h616_r_pinctrl_probe(struct platform_device *pdev)
+{
+ return sunxi_pinctrl_init(pdev,
+ &sun50i_h616_r_pinctrl_data);
+}
+
+static const struct of_device_id sun50i_h616_r_pinctrl_match[] = {
+ { .compatible = "allwinner,sun50i-h616-r-pinctrl", },
+ {}
+};
+
+static struct platform_driver sun50i_h616_r_pinctrl_driver = {
+ .probe = sun50i_h616_r_pinctrl_probe,
+ .driver = {
+ .name = "sun50i-h616-r-pinctrl",
+ .of_match_table = sun50i_h616_r_pinctrl_match,
+ },
+};
+builtin_platform_driver(sun50i_h616_r_pinctrl_driver);
--
2.17.5

Andre Przywara

unread,
Jan 17, 2021, 9:09:43 PM1/17/21
to Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Icenowy Zheng, Linus Walleij, Rob Herring, Clément Péron, Samuel Holland, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Stephen Boyd, Michael Turquette, linu...@vger.kernel.org, devic...@vger.kernel.org
Signed-off-by: Andre Przywara <andre.p...@arm.com>
Acked-by: Rob Herring <ro...@kernel.org>
---
.../devicetree/bindings/clock/allwinner,sun4i-a10-ccu.yaml | 2 ++
1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-ccu.yaml b/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-ccu.yaml
index 3b45344ed758..b7e891803bb4 100644
--- a/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-ccu.yaml
+++ b/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-ccu.yaml
@@ -41,6 +41,8 @@ properties:
- allwinner,sun50i-h5-ccu
- allwinner,sun50i-h6-ccu
- allwinner,sun50i-h6-r-ccu
+ - allwinner,sun50i-h616-ccu
+ - allwinner,sun50i-h616-r-ccu
- allwinner,suniv-f1c100s-ccu
- nextthing,gr8-ccu

--
2.17.5

Andre Przywara

unread,
Jan 17, 2021, 9:09:45 PM1/17/21
to Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Icenowy Zheng, Linus Walleij, Rob Herring, Clément Péron, Samuel Holland, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Stephen Boyd, Michael Turquette, linu...@vger.kernel.org, Philipp Zabel
The clocks itself are identical to the H6 R-CCU, it's just that the H616
has not all of them implemented (or connected).

Signed-off-by: Andre Przywara <andre.p...@arm.com>
---
drivers/clk/sunxi-ng/Kconfig | 2 +-
drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c | 48 ++++++++++++++++++++++++++
2 files changed, 49 insertions(+), 1 deletion(-)

diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig
index ce5f5847d5d3..feeb8d2074ee 100644
--- a/drivers/clk/sunxi-ng/Kconfig
+++ b/drivers/clk/sunxi-ng/Kconfig
@@ -33,7 +33,7 @@ config SUN50I_H6_CCU
depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST

config SUN50I_H6_R_CCU
- bool "Support for the Allwinner H6 PRCM CCU"
+ bool "Support for the Allwinner H6 and H616 PRCM CCU"
default ARM64 && ARCH_SUNXI
depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST

diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c b/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c
index 56e351b513f3..f8909a7ed553 100644
--- a/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c
@@ -139,6 +139,16 @@ static struct ccu_common *sun50i_h6_r_ccu_clks[] = {
&w1_clk.common,
};

+static struct ccu_common *sun50i_h616_r_ccu_clks[] = {
+ &r_apb1_clk.common,
+ &r_apb2_clk.common,
+ &r_apb1_twd_clk.common,
+ &r_apb2_i2c_clk.common,
+ &r_apb2_rsb_clk.common,
+ &r_apb1_ir_clk.common,
+ &ir_clk.common,
+};
+
static struct clk_hw_onecell_data sun50i_h6_r_hw_clks = {
.hws = {
[CLK_AR100] = &ar100_clk.common.hw,
@@ -159,6 +169,20 @@ static struct clk_hw_onecell_data sun50i_h6_r_hw_clks = {
.num = CLK_NUMBER,
};

+static struct clk_hw_onecell_data sun50i_h616_r_hw_clks = {
+ .hws = {
+ [CLK_R_AHB] = &r_ahb_clk.hw,
+ [CLK_R_APB1] = &r_apb1_clk.common.hw,
+ [CLK_R_APB2] = &r_apb2_clk.common.hw,
+ [CLK_R_APB1_TWD] = &r_apb1_twd_clk.common.hw,
+ [CLK_R_APB2_I2C] = &r_apb2_i2c_clk.common.hw,
+ [CLK_R_APB2_RSB] = &r_apb2_rsb_clk.common.hw,
+ [CLK_R_APB1_IR] = &r_apb1_ir_clk.common.hw,
+ [CLK_IR] = &ir_clk.common.hw,
+ },
+ .num = CLK_NUMBER,
+};
+
static struct ccu_reset_map sun50i_h6_r_ccu_resets[] = {
[RST_R_APB1_TIMER] = { 0x11c, BIT(16) },
[RST_R_APB1_TWD] = { 0x12c, BIT(16) },
@@ -170,6 +194,13 @@ static struct ccu_reset_map sun50i_h6_r_ccu_resets[] = {
[RST_R_APB1_W1] = { 0x1ec, BIT(16) },
};

+static struct ccu_reset_map sun50i_h616_r_ccu_resets[] = {
+ [RST_R_APB1_TWD] = { 0x12c, BIT(16) },
+ [RST_R_APB2_I2C] = { 0x19c, BIT(16) },
+ [RST_R_APB2_RSB] = { 0x1bc, BIT(16) },
+ [RST_R_APB1_IR] = { 0x1cc, BIT(16) },
+};
+
static const struct sunxi_ccu_desc sun50i_h6_r_ccu_desc = {
.ccu_clks = sun50i_h6_r_ccu_clks,
.num_ccu_clks = ARRAY_SIZE(sun50i_h6_r_ccu_clks),
@@ -180,6 +211,16 @@ static const struct sunxi_ccu_desc sun50i_h6_r_ccu_desc = {
.num_resets = ARRAY_SIZE(sun50i_h6_r_ccu_resets),
};

+static const struct sunxi_ccu_desc sun50i_h616_r_ccu_desc = {
+ .ccu_clks = sun50i_h616_r_ccu_clks,
+ .num_ccu_clks = ARRAY_SIZE(sun50i_h616_r_ccu_clks),
+
+ .hw_clks = &sun50i_h616_r_hw_clks,
+
+ .resets = sun50i_h616_r_ccu_resets,
+ .num_resets = ARRAY_SIZE(sun50i_h616_r_ccu_resets),
+};
+
static void __init sunxi_r_ccu_init(struct device_node *node,
const struct sunxi_ccu_desc *desc)
{
@@ -200,3 +241,10 @@ static void __init sun50i_h6_r_ccu_setup(struct device_node *node)
}
CLK_OF_DECLARE(sun50i_h6_r_ccu, "allwinner,sun50i-h6-r-ccu",
sun50i_h6_r_ccu_setup);
+
+static void __init sun50i_h616_r_ccu_setup(struct device_node *node)
+{
+ sunxi_r_ccu_init(node, &sun50i_h616_r_ccu_desc);
+}
+CLK_OF_DECLARE(sun50i_h616_r_ccu, "allwinner,sun50i-h616-r-ccu",
+ sun50i_h616_r_ccu_setup);
--
2.17.5

Andre Przywara

unread,
Jan 17, 2021, 9:09:49 PM1/17/21
to Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Icenowy Zheng, Linus Walleij, Rob Herring, Clément Péron, Samuel Holland, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Stephen Boyd, Michael Turquette, linu...@vger.kernel.org, Philipp Zabel
While the clocks are fairly similar to the H6, many differ in tiny
details, so a separate clock driver seems indicated.

Derived from the H6 clock driver, and adjusted according to the manual.

Signed-off-by: Andre Przywara <andre.p...@arm.com>
---
drivers/clk/sunxi-ng/Kconfig | 5 +
drivers/clk/sunxi-ng/Makefile | 1 +
drivers/clk/sunxi-ng/ccu-sun50i-h616.c | 1150 +++++++++++++++++++
drivers/clk/sunxi-ng/ccu-sun50i-h616.h | 56 +
include/dt-bindings/clock/sun50i-h616-ccu.h | 115 ++
include/dt-bindings/reset/sun50i-h616-ccu.h | 70 ++
6 files changed, 1397 insertions(+)
create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-h616.c
create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-h616.h
create mode 100644 include/dt-bindings/clock/sun50i-h616-ccu.h
create mode 100644 include/dt-bindings/reset/sun50i-h616-ccu.h

diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig
index feeb8d2074ee..cd46d8853876 100644
--- a/drivers/clk/sunxi-ng/Kconfig
+++ b/drivers/clk/sunxi-ng/Kconfig
@@ -32,6 +32,11 @@ config SUN50I_H6_CCU
default ARM64 && ARCH_SUNXI
depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST

+config SUN50I_H616_CCU
+ bool "Support for the Allwinner H616 CCU"
+ default ARM64 && ARCH_SUNXI
+ depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST
+
config SUN50I_H6_R_CCU
bool "Support for the Allwinner H6 and H616 PRCM CCU"
default ARM64 && ARCH_SUNXI
diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
index 3eb5cff40eac..96c324306d97 100644
--- a/drivers/clk/sunxi-ng/Makefile
+++ b/drivers/clk/sunxi-ng/Makefile
@@ -26,6 +26,7 @@ obj-$(CONFIG_SUN50I_A64_CCU) += ccu-sun50i-a64.o
obj-$(CONFIG_SUN50I_A100_CCU) += ccu-sun50i-a100.o
obj-$(CONFIG_SUN50I_A100_R_CCU) += ccu-sun50i-a100-r.o
obj-$(CONFIG_SUN50I_H6_CCU) += ccu-sun50i-h6.o
+obj-$(CONFIG_SUN50I_H616_CCU) += ccu-sun50i-h616.o
obj-$(CONFIG_SUN50I_H6_R_CCU) += ccu-sun50i-h6-r.o
obj-$(CONFIG_SUN4I_A10_CCU) += ccu-sun4i-a10.o
obj-$(CONFIG_SUN5I_CCU) += ccu-sun5i.o
diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h616.c b/drivers/clk/sunxi-ng/ccu-sun50i-h616.c
new file mode 100644
index 000000000000..225307305880
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-h616.c
@@ -0,0 +1,1150 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2020 Arm Ltd.
+ * Based on the H6 CCU driver, which is:
+ * Copyright (c) 2017 Icenowy Zheng <ice...@aosc.io>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+
+#include "ccu_common.h"
+#include "ccu_reset.h"
+
+#include "ccu_div.h"
+#include "ccu_gate.h"
+#include "ccu_mp.h"
+#include "ccu_mult.h"
+#include "ccu_nk.h"
+#include "ccu_nkm.h"
+#include "ccu_nkmp.h"
+#include "ccu_nm.h"
+
+#include "ccu-sun50i-h616.h"
+
+/*
+ * The CPU PLL is actually NP clock, with P being /1, /2 or /4. However
+ * P should only be used for output frequencies lower than 288 MHz.
+ *
+ * For now we can just model it as a multiplier clock, and force P to /1.
+ *
+ * The M factor is present in the register's description, but not in the
+ * frequency formula, and it's documented as "M is only used for backdoor
+ * testing", so it's not modelled and then force to 0.
+ */
+#define SUN50I_H616_PLL_CPUX_REG 0x000
+static struct ccu_mult pll_cpux_clk = {
+ .enable = BIT(31),
+ .lock = BIT(28),
+ .mult = _SUNXI_CCU_MULT_MIN(8, 8, 12),
+ .common = {
+ .reg = 0x000,
+ .hw.init = CLK_HW_INIT("pll-cpux", "osc24M",
+ &ccu_mult_ops,
+ CLK_SET_RATE_UNGATE),
+ },
+};
+
+/* Some PLLs are input * N / div1 / P. Model them as NKMP with no K */
+#define SUN50I_H616_PLL_DDR0_REG 0x010
+static struct ccu_nkmp pll_ddr0_clk = {
+ .enable = BIT(31),
+ .lock = BIT(28),
+ .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
+ .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
+ .p = _SUNXI_CCU_DIV(0, 1), /* output divider */
+ .common = {
+ .reg = 0x010,
+ .hw.init = CLK_HW_INIT("pll-ddr0", "osc24M",
+ &ccu_nkmp_ops,
+ CLK_SET_RATE_UNGATE),
+ },
+};
+
+#define SUN50I_H616_PLL_DDR1_REG 0x018
+static struct ccu_nkmp pll_ddr1_clk = {
+ .enable = BIT(31),
+ .lock = BIT(28),
+ .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
+ .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
+ .p = _SUNXI_CCU_DIV(0, 1), /* output divider */
+ .common = {
+ .reg = 0x018,
+ .hw.init = CLK_HW_INIT("pll-ddr1", "osc24M",
+ &ccu_nkmp_ops,
+ CLK_SET_RATE_UNGATE),
+ },
+};
+
+#define SUN50I_H616_PLL_PERIPH0_REG 0x020
+static struct ccu_nkmp pll_periph0_clk = {
+ .enable = BIT(31),
+ .lock = BIT(28),
+ .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
+ .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
+ .p = _SUNXI_CCU_DIV(0, 1), /* output divider */
+ .fixed_post_div = 2,
+ .common = {
+ .reg = 0x020,
+ .features = CCU_FEATURE_FIXED_POSTDIV,
+ .hw.init = CLK_HW_INIT("pll-periph0", "osc24M",
+ &ccu_nkmp_ops,
+ CLK_SET_RATE_UNGATE),
+ },
+};
+
+#define SUN50I_H616_PLL_PERIPH1_REG 0x028
+static struct ccu_nkmp pll_periph1_clk = {
+ .enable = BIT(31),
+ .lock = BIT(28),
+ .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
+ .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
+ .p = _SUNXI_CCU_DIV(0, 1), /* output divider */
+ .fixed_post_div = 2,
+ .common = {
+ .reg = 0x028,
+ .features = CCU_FEATURE_FIXED_POSTDIV,
+ .hw.init = CLK_HW_INIT("pll-periph1", "osc24M",
+ &ccu_nkmp_ops,
+ CLK_SET_RATE_UNGATE),
+ },
+};
+
+#define SUN50I_H616_PLL_GPU_REG 0x030
+static struct ccu_nkmp pll_gpu_clk = {
+ .enable = BIT(31),
+ .lock = BIT(28),
+ .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
+ .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
+ .p = _SUNXI_CCU_DIV(0, 1), /* output divider */
+ .common = {
+ .reg = 0x030,
+ .hw.init = CLK_HW_INIT("pll-gpu", "osc24M",
+ &ccu_nkmp_ops,
+ CLK_SET_RATE_UNGATE),
+ },
+};
+
+/*
+ * For Video PLLs, the output divider is described as "used for testing"
+ * in the user manual. So it's not modelled and forced to 0.
+ */
+#define SUN50I_H616_PLL_VIDEO0_REG 0x040
+static struct ccu_nm pll_video0_clk = {
+ .enable = BIT(31),
+ .lock = BIT(28),
+ .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
+ .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
+ .fixed_post_div = 4,
+ .min_rate = 288000000,
+ .max_rate = 2400000000UL,
+ .common = {
+ .reg = 0x040,
+ .features = CCU_FEATURE_FIXED_POSTDIV,
+ .hw.init = CLK_HW_INIT("pll-video0", "osc24M",
+ &ccu_nm_ops,
+ CLK_SET_RATE_UNGATE),
+ },
+};
+
+#define SUN50I_H616_PLL_VIDEO1_REG 0x048
+static struct ccu_nm pll_video1_clk = {
+ .enable = BIT(31),
+ .lock = BIT(28),
+ .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
+ .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
+ .fixed_post_div = 4,
+ .min_rate = 288000000,
+ .max_rate = 2400000000UL,
+ .common = {
+ .reg = 0x048,
+ .features = CCU_FEATURE_FIXED_POSTDIV,
+ .hw.init = CLK_HW_INIT("pll-video1", "osc24M",
+ &ccu_nm_ops,
+ CLK_SET_RATE_UNGATE),
+ },
+};
+
+#define SUN50I_H616_PLL_VIDEO2_REG 0x050
+static struct ccu_nm pll_video2_clk = {
+ .enable = BIT(31),
+ .lock = BIT(28),
+ .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
+ .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
+ .fixed_post_div = 4,
+ .min_rate = 288000000,
+ .max_rate = 2400000000UL,
+ .common = {
+ .reg = 0x050,
+ .features = CCU_FEATURE_FIXED_POSTDIV,
+ .hw.init = CLK_HW_INIT("pll-video2", "osc24M",
+ &ccu_nm_ops,
+ CLK_SET_RATE_UNGATE),
+ },
+};
+
+#define SUN50I_H616_PLL_VE_REG 0x058
+static struct ccu_nkmp pll_ve_clk = {
+ .enable = BIT(31),
+ .lock = BIT(28),
+ .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
+ .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
+ .p = _SUNXI_CCU_DIV(0, 1), /* output divider */
+ .common = {
+ .reg = 0x058,
+ .hw.init = CLK_HW_INIT("pll-ve", "osc24M",
+ &ccu_nkmp_ops,
+ CLK_SET_RATE_UNGATE),
+ },
+};
+
+#define SUN50I_H616_PLL_DE_REG 0x060
+static struct ccu_nkmp pll_de_clk = {
+ .enable = BIT(31),
+ .lock = BIT(28),
+ .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
+ .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
+ .p = _SUNXI_CCU_DIV(0, 1), /* output divider */
+ .common = {
+ .reg = 0x060,
+ .hw.init = CLK_HW_INIT("pll-de", "osc24M",
+ &ccu_nkmp_ops,
+ CLK_SET_RATE_UNGATE),
+ },
+};
+
+/*
+ * TODO: Determine SDM settings for the audio PLL. The manual suggests
+ * PLL_FACTOR_N=16, PLL_POST_DIV_P=2, OUTPUT_DIV=2, pattern=0xe000c49b
+ * for 24.576 MHz, and PLL_FACTOR_N=22, PLL_POST_DIV_P=3, OUTPUT_DIV=2,
+ * pattern=0xe001288c for 22.5792 MHz.
+ * This clashes with our fixed PLL_POST_DIV_P.
+ */
+#define SUN50I_H616_PLL_AUDIO_REG 0x078
+static struct ccu_nm pll_audio_hs_clk = {
+ .enable = BIT(31),
+ .lock = BIT(28),
+ .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
+ .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
+ .common = {
+ .reg = 0x078,
+ .hw.init = CLK_HW_INIT("pll-audio-hs", "osc24M",
+ &ccu_nm_ops,
+ CLK_SET_RATE_UNGATE),
+ },
+};
+
+static const char * const cpux_parents[] = { "osc24M", "osc32k",
+ "iosc", "pll-cpux", "pll-periph0" };
+static SUNXI_CCU_MUX(cpux_clk, "cpux", cpux_parents,
+ 0x500, 24, 3, CLK_SET_RATE_PARENT | CLK_IS_CRITICAL);
+static SUNXI_CCU_M(axi_clk, "axi", "cpux", 0x500, 0, 2, 0);
+static SUNXI_CCU_M(cpux_apb_clk, "cpux-apb", "cpux", 0x500, 8, 2, 0);
+
+static const char * const psi_ahb1_ahb2_parents[] = { "osc24M", "osc32k",
+ "iosc", "pll-periph0" };
+static SUNXI_CCU_MP_WITH_MUX(psi_ahb1_ahb2_clk, "psi-ahb1-ahb2",
+ psi_ahb1_ahb2_parents,
+ 0x510,
+ 0, 2, /* M */
+ 8, 2, /* P */
+ 24, 2, /* mux */
+ 0);
+
+static const char * const ahb3_apb1_apb2_parents[] = { "osc24M", "osc32k",
+ "psi-ahb1-ahb2",
+ "pll-periph0" };
+static SUNXI_CCU_MP_WITH_MUX(ahb3_clk, "ahb3", ahb3_apb1_apb2_parents, 0x51c,
+ 0, 2, /* M */
+ 8, 2, /* P */
+ 24, 2, /* mux */
+ 0);
+
+static SUNXI_CCU_MP_WITH_MUX(apb1_clk, "apb1", ahb3_apb1_apb2_parents, 0x520,
+ 0, 2, /* M */
+ 8, 2, /* P */
+ 24, 2, /* mux */
+ 0);
+
+static SUNXI_CCU_MP_WITH_MUX(apb2_clk, "apb2", ahb3_apb1_apb2_parents, 0x524,
+ 0, 2, /* M */
+ 8, 2, /* P */
+ 24, 2, /* mux */
+ 0);
+
+static const char * const mbus_parents[] = { "osc24M", "pll-periph0-2x",
+ "pll-ddr0", "pll-ddr1" };
+static SUNXI_CCU_M_WITH_MUX_GATE(mbus_clk, "mbus", mbus_parents, 0x540,
+ 0, 3, /* M */
+ 24, 2, /* mux */
+ BIT(31), /* gate */
+ CLK_IS_CRITICAL);
+
+static const char * const de_parents[] = { "pll-de", "pll-periph0-2x" };
+static SUNXI_CCU_M_WITH_MUX_GATE(de_clk, "de", de_parents, 0x600,
+ 0, 4, /* M */
+ 24, 1, /* mux */
+ BIT(31), /* gate */
+ CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_GATE(bus_de_clk, "bus-de", "psi-ahb1-ahb2",
+ 0x60c, BIT(0), 0);
+
+static SUNXI_CCU_M_WITH_MUX_GATE(deinterlace_clk, "deinterlace",
+ de_parents,
+ 0x620,
+ 0, 4, /* M */
+ 24, 1, /* mux */
+ BIT(31), /* gate */
+ 0);
+
+static SUNXI_CCU_GATE(bus_deinterlace_clk, "bus-deinterlace", "psi-ahb1-ahb2",
+ 0x62c, BIT(0), 0);
+
+static SUNXI_CCU_M_WITH_MUX_GATE(g2d_clk, "g2d", de_parents, 0x630,
+ 0, 4, /* M */
+ 24, 1, /* mux */
+ BIT(31), /* gate */
+ 0);
+
+static SUNXI_CCU_GATE(bus_g2d_clk, "bus-g2d", "psi-ahb1-ahb2",
+ 0x63c, BIT(0), 0);
+
+static const char * const gpu0_parents[] = { "pll-gpu", "gpu1" };
+static SUNXI_CCU_M_WITH_MUX_GATE(gpu0_clk, "gpu0", gpu0_parents, 0x670,
+ 0, 2, /* M */
+ 24, 1, /* mux */
+ BIT(31), /* gate */
+ CLK_SET_RATE_PARENT);
+static SUNXI_CCU_M_WITH_GATE(gpu1_clk, "gpu1", "pll-periph0-2x", 0x674,
+ 0, 2, /* M */
+ BIT(31),/* gate */
+ 0);
+
+static SUNXI_CCU_GATE(bus_gpu_clk, "bus-gpu", "psi-ahb1-ahb2",
+ 0x67c, BIT(0), 0);
+
+static const char * const ce_parents[] = { "osc24M", "pll-periph0-2x" };
+static SUNXI_CCU_MP_WITH_MUX_GATE(ce_clk, "ce", ce_parents, 0x680,
+ 0, 4, /* M */
+ 8, 2, /* N */
+ 24, 1, /* mux */
+ BIT(31),/* gate */
+ 0);
+
+static SUNXI_CCU_GATE(bus_ce_clk, "bus-ce", "psi-ahb1-ahb2",
+ 0x68c, BIT(0), 0);
+
+static const char * const ve_parents[] = { "pll-ve" };
+static SUNXI_CCU_M_WITH_MUX_GATE(ve_clk, "ve", ve_parents, 0x690,
+ 0, 3, /* M */
+ 24, 1, /* mux */
+ BIT(31), /* gate */
+ CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_GATE(bus_ve_clk, "bus-ve", "psi-ahb1-ahb2",
+ 0x69c, BIT(0), 0);
+
+static SUNXI_CCU_GATE(bus_dma_clk, "bus-dma", "psi-ahb1-ahb2",
+ 0x70c, BIT(0), 0);
+
+static SUNXI_CCU_GATE(bus_hstimer_clk, "bus-hstimer", "psi-ahb1-ahb2",
+ 0x73c, BIT(0), 0);
+
+static SUNXI_CCU_GATE(avs_clk, "avs", "osc24M", 0x740, BIT(31), 0);
+
+static SUNXI_CCU_GATE(bus_dbg_clk, "bus-dbg", "psi-ahb1-ahb2",
+ 0x78c, BIT(0), 0);
+
+static SUNXI_CCU_GATE(bus_psi_clk, "bus-psi", "psi-ahb1-ahb2",
+ 0x79c, BIT(0), 0);
+
+static SUNXI_CCU_GATE(bus_pwm_clk, "bus-pwm", "apb1", 0x7ac, BIT(0), 0);
+
+static SUNXI_CCU_GATE(bus_iommu_clk, "bus-iommu", "apb1", 0x7bc, BIT(0), 0);
+
+static const char * const dram_parents[] = { "pll-ddr0", "pll-ddr1" };
+static struct ccu_div dram_clk = {
+ .div = _SUNXI_CCU_DIV(0, 2),
+ .mux = _SUNXI_CCU_MUX(24, 2),
+ .common = {
+ .reg = 0x800,
+ .hw.init = CLK_HW_INIT_PARENTS("dram",
+ dram_parents,
+ &ccu_div_ops,
+ CLK_IS_CRITICAL),
+ },
+};
+
+static SUNXI_CCU_GATE(mbus_dma_clk, "mbus-dma", "mbus",
+ 0x804, BIT(0), 0);
+static SUNXI_CCU_GATE(mbus_ve_clk, "mbus-ve", "mbus",
+ 0x804, BIT(1), 0);
+static SUNXI_CCU_GATE(mbus_ce_clk, "mbus-ce", "mbus",
+ 0x804, BIT(2), 0);
+static SUNXI_CCU_GATE(mbus_ts_clk, "mbus-ts", "mbus",
+ 0x804, BIT(3), 0);
+static SUNXI_CCU_GATE(mbus_nand_clk, "mbus-nand", "mbus",
+ 0x804, BIT(5), 0);
+static SUNXI_CCU_GATE(mbus_g2d_clk, "mbus-g2d", "mbus",
+ 0x804, BIT(10), 0);
+
+static SUNXI_CCU_GATE(bus_dram_clk, "bus-dram", "psi-ahb1-ahb2",
+ 0x80c, BIT(0), CLK_IS_CRITICAL);
+
+static const char * const nand_spi_parents[] = { "osc24M", "pll-periph0",
+ "pll-periph1", "pll-periph0-2x",
+ "pll-periph1-2x" };
+static SUNXI_CCU_MP_WITH_MUX_GATE(nand0_clk, "nand0", nand_spi_parents, 0x810,
+ 0, 4, /* M */
+ 8, 2, /* N */
+ 24, 3, /* mux */
+ BIT(31),/* gate */
+ 0);
+
+static SUNXI_CCU_MP_WITH_MUX_GATE(nand1_clk, "nand1", nand_spi_parents, 0x814,
+ 0, 4, /* M */
+ 8, 2, /* N */
+ 24, 3, /* mux */
+ BIT(31),/* gate */
+ 0);
+
+static SUNXI_CCU_GATE(bus_nand_clk, "bus-nand", "ahb3", 0x82c, BIT(0), 0);
+
+static const char * const mmc_parents[] = { "osc24M", "pll-periph0-2x",
+ "pll-periph1-2x" };
+static SUNXI_CCU_MP_WITH_MUX_GATE_POSTDIV(mmc0_clk, "mmc0", mmc_parents, 0x830,
+ 0, 4, /* M */
+ 8, 2, /* N */
+ 24, 2, /* mux */
+ BIT(31), /* gate */
+ 2, /* post-div */
+ 0);
+
+static SUNXI_CCU_MP_WITH_MUX_GATE_POSTDIV(mmc1_clk, "mmc1", mmc_parents, 0x834,
+ 0, 4, /* M */
+ 8, 2, /* N */
+ 24, 2, /* mux */
+ BIT(31), /* gate */
+ 2, /* post-div */
+ 0);
+
+static SUNXI_CCU_MP_WITH_MUX_GATE_POSTDIV(mmc2_clk, "mmc2", mmc_parents, 0x838,
+ 0, 4, /* M */
+ 8, 2, /* N */
+ 24, 2, /* mux */
+ BIT(31), /* gate */
+ 2, /* post-div */
+ 0);
+
+static SUNXI_CCU_GATE(bus_mmc0_clk, "bus-mmc0", "ahb3", 0x84c, BIT(0), 0);
+static SUNXI_CCU_GATE(bus_mmc1_clk, "bus-mmc1", "ahb3", 0x84c, BIT(1), 0);
+static SUNXI_CCU_GATE(bus_mmc2_clk, "bus-mmc2", "ahb3", 0x84c, BIT(2), 0);
+
+static SUNXI_CCU_GATE(bus_uart0_clk, "bus-uart0", "apb2", 0x90c, BIT(0), 0);
+static SUNXI_CCU_GATE(bus_uart1_clk, "bus-uart1", "apb2", 0x90c, BIT(1), 0);
+static SUNXI_CCU_GATE(bus_uart2_clk, "bus-uart2", "apb2", 0x90c, BIT(2), 0);
+static SUNXI_CCU_GATE(bus_uart3_clk, "bus-uart3", "apb2", 0x90c, BIT(3), 0);
+static SUNXI_CCU_GATE(bus_uart4_clk, "bus-uart4", "apb2", 0x90c, BIT(4), 0);
+static SUNXI_CCU_GATE(bus_uart5_clk, "bus-uart5", "apb2", 0x90c, BIT(5), 0);
+
+static SUNXI_CCU_GATE(bus_i2c0_clk, "bus-i2c0", "apb2", 0x91c, BIT(0), 0);
+static SUNXI_CCU_GATE(bus_i2c1_clk, "bus-i2c1", "apb2", 0x91c, BIT(1), 0);
+static SUNXI_CCU_GATE(bus_i2c2_clk, "bus-i2c2", "apb2", 0x91c, BIT(2), 0);
+static SUNXI_CCU_GATE(bus_i2c3_clk, "bus-i2c3", "apb2", 0x91c, BIT(3), 0);
+static SUNXI_CCU_GATE(bus_i2c4_clk, "bus-i2c4", "apb2", 0x91c, BIT(4), 0);
+
+static SUNXI_CCU_MP_WITH_MUX_GATE(spi0_clk, "spi0", nand_spi_parents, 0x940,
+ 0, 4, /* M */
+ 8, 2, /* N */
+ 24, 3, /* mux */
+ BIT(31),/* gate */
+ 0);
+
+static SUNXI_CCU_MP_WITH_MUX_GATE(spi1_clk, "spi1", nand_spi_parents, 0x944,
+ 0, 4, /* M */
+ 8, 2, /* N */
+ 24, 3, /* mux */
+ BIT(31),/* gate */
+ 0);
+
+static SUNXI_CCU_GATE(bus_spi0_clk, "bus-spi0", "ahb3", 0x96c, BIT(0), 0);
+static SUNXI_CCU_GATE(bus_spi1_clk, "bus-spi1", "ahb3", 0x96c, BIT(1), 0);
+
+static SUNXI_CCU_GATE(emac_25m_clk, "emac-25m", "ahb3", 0x970,
+ BIT(31) | BIT(30), 0);
+
+static SUNXI_CCU_GATE(bus_emac0_clk, "bus-emac0", "ahb3", 0x97c, BIT(0), 0);
+static SUNXI_CCU_GATE(bus_emac1_clk, "bus-emac1", "ahb3", 0x97c, BIT(1), 0);
+
+static const char * const ts_parents[] = { "osc24M", "pll-periph0" };
+static SUNXI_CCU_MP_WITH_MUX_GATE(ts_clk, "ts", ts_parents, 0x9b0,
+ 0, 4, /* M */
+ 8, 2, /* N */
+ 24, 1, /* mux */
+ BIT(31),/* gate */
+ 0);
+
+static SUNXI_CCU_GATE(bus_ts_clk, "bus-ts", "ahb3", 0x9bc, BIT(0), 0);
+
+static SUNXI_CCU_GATE(bus_ths_clk, "bus-ths", "apb1", 0x9fc, BIT(0), 0);
+
+static const char * const audio_parents[] = { "pll-audio-1x", "pll-audio-2x",
+ "pll-audio-4x", "pll-audio-hs" };
+static struct ccu_div spdif_clk = {
+ .enable = BIT(31),
+ .div = _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO),
+ .mux = _SUNXI_CCU_MUX(24, 2),
+ .common = {
+ .reg = 0xa20,
+ .hw.init = CLK_HW_INIT_PARENTS("spdif",
+ audio_parents,
+ &ccu_div_ops,
+ 0),
+ },
+};
+
+static SUNXI_CCU_GATE(bus_spdif_clk, "bus-spdif", "apb1", 0xa2c, BIT(0), 0);
+
+static struct ccu_div dmic_clk = {
+ .enable = BIT(31),
+ .div = _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO),
+ .mux = _SUNXI_CCU_MUX(24, 2),
+ .common = {
+ .reg = 0xa40,
+ .hw.init = CLK_HW_INIT_PARENTS("dmic",
+ audio_parents,
+ &ccu_div_ops,
+ 0),
+ },
+};
+
+static SUNXI_CCU_GATE(bus_dmic_clk, "bus-dmic", "apb1", 0xa4c, BIT(0), 0);
+
+static SUNXI_CCU_M_WITH_MUX_GATE(audio_codec_1x_clk, "audio-codec-1x",
+ audio_parents, 0xa50,
+ 0, 4, /* M */
+ 24, 2, /* mux */
+ BIT(31), /* gate */
+ CLK_SET_RATE_PARENT);
+static SUNXI_CCU_M_WITH_MUX_GATE(audio_codec_4x_clk, "audio-codec-4x",
+ audio_parents, 0xa54,
+ 0, 4, /* M */
+ 24, 2, /* mux */
+ BIT(31), /* gate */
+ CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_GATE(bus_audio_codec_clk, "bus-audio-codec", "apb1", 0xa5c,
+ BIT(0), 0);
+
+static struct ccu_div audio_hub_clk = {
+ .enable = BIT(31),
+ .div = _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO),
+ .mux = _SUNXI_CCU_MUX(24, 2),
+ .common = {
+ .reg = 0xa60,
+ .hw.init = CLK_HW_INIT_PARENTS("audio-hub",
+ audio_parents,
+ &ccu_div_ops,
+ 0),
+ },
+};
+
+static SUNXI_CCU_GATE(bus_audio_hub_clk, "bus-audio-hub", "apb1", 0xa6c, BIT(0), 0);
+
+/*
+ * There are OHCI 12M clock source selection bits for the four USB 2.0 ports.
+ * We will force them to 0 (12M divided from 48M).
+ */
+#define SUN50I_H616_USB0_CLK_REG 0xa70
+#define SUN50I_H616_USB1_CLK_REG 0xa74
+#define SUN50I_H616_USB2_CLK_REG 0xa78
+#define SUN50I_H616_USB3_CLK_REG 0xa7c
+
+static SUNXI_CCU_GATE(usb_ohci0_clk, "usb-ohci0", "osc12M", 0xa70, BIT(31), 0);
+static SUNXI_CCU_GATE(usb_phy0_clk, "usb-phy0", "osc24M", 0xa70, BIT(29), 0);
+
+static SUNXI_CCU_GATE(usb_ohci1_clk, "usb-ohci1", "osc12M", 0xa74, BIT(31), 0);
+static SUNXI_CCU_GATE(usb_phy1_clk, "usb-phy1", "osc24M", 0xa74, BIT(29), 0);
+
+static SUNXI_CCU_GATE(usb_ohci2_clk, "usb-ohci2", "osc12M", 0xa78, BIT(31), 0);
+static SUNXI_CCU_GATE(usb_phy2_clk, "usb-phy2", "osc24M", 0xa78, BIT(29), 0);
+
+static SUNXI_CCU_GATE(usb_ohci3_clk, "usb-ohci3", "osc12M", 0xa7c, BIT(31), 0);
+static SUNXI_CCU_GATE(usb_phy3_clk, "usb-phy3", "osc24M", 0xa7c, BIT(29), 0);
+
+static SUNXI_CCU_GATE(bus_ohci0_clk, "bus-ohci0", "ahb3", 0xa8c, BIT(0), 0);
+static SUNXI_CCU_GATE(bus_ohci1_clk, "bus-ohci1", "ahb3", 0xa8c, BIT(1), 0);
+static SUNXI_CCU_GATE(bus_ohci2_clk, "bus-ohci2", "ahb3", 0xa8c, BIT(2), 0);
+static SUNXI_CCU_GATE(bus_ohci3_clk, "bus-ohci3", "ahb3", 0xa8c, BIT(3), 0);
+static SUNXI_CCU_GATE(bus_ehci0_clk, "bus-ehci0", "ahb3", 0xa8c, BIT(4), 0);
+static SUNXI_CCU_GATE(bus_ehci1_clk, "bus-ehci1", "ahb3", 0xa8c, BIT(5), 0);
+static SUNXI_CCU_GATE(bus_ehci2_clk, "bus-ehci2", "ahb3", 0xa8c, BIT(6), 0);
+static SUNXI_CCU_GATE(bus_ehci3_clk, "bus-ehci3", "ahb3", 0xa8c, BIT(7), 0);
+static SUNXI_CCU_GATE(bus_otg_clk, "bus-otg", "ahb3", 0xa8c, BIT(8), 0);
+
+static SUNXI_CCU_GATE(bus_keyadc_clk, "bus-keyadc", "apb1", 0xa9c, BIT(0), 0);
+
+static const char * const hdmi_parents[] = { "pll-video0", "pll-video0-4x",
+ "pll-video2", "pll-video2-4x" };
+static SUNXI_CCU_M_WITH_MUX_GATE(hdmi_clk, "hdmi", hdmi_parents, 0xb00,
+ 0, 4, /* M */
+ 24, 2, /* mux */
+ BIT(31), /* gate */
+ 0);
+
+static SUNXI_CCU_GATE(hdmi_slow_clk, "hdmi-slow", "osc24M", 0xb04, BIT(31), 0);
+
+static const char * const hdmi_cec_parents[] = { "osc32k", "pll-periph0-2x" };
+static const struct ccu_mux_fixed_prediv hdmi_cec_predivs[] = {
+ { .index = 1, .div = 36621 },
+};
+
+#define SUN50I_H616_HDMI_CEC_CLK_REG 0xb10
+static struct ccu_mux hdmi_cec_clk = {
+ .enable = BIT(31) | BIT(30),
+
+ .mux = {
+ .shift = 24,
+ .width = 2,
+
+ .fixed_predivs = hdmi_cec_predivs,
+ .n_predivs = ARRAY_SIZE(hdmi_cec_predivs),
+ },
+
+ .common = {
+ .reg = 0xb10,
+ .features = CCU_FEATURE_FIXED_PREDIV,
+ .hw.init = CLK_HW_INIT_PARENTS("hdmi-cec",
+ hdmi_cec_parents,
+ &ccu_mux_ops,
+ 0),
+ },
+};
+
+static SUNXI_CCU_GATE(bus_hdmi_clk, "bus-hdmi", "ahb3", 0xb1c, BIT(0), 0);
+
+static SUNXI_CCU_GATE(bus_tcon_top_clk, "bus-tcon-top", "ahb3",
+ 0xb5c, BIT(0), 0);
+
+static const char * const tcon_tv_parents[] = { "pll-video0",
+ "pll-video0-4x",
+ "pll-video1",
+ "pll-video1-4x" };
+static SUNXI_CCU_MP_WITH_MUX_GATE(tcon_tv0_clk, "tcon-tv0",
+ tcon_tv_parents, 0xb80,
+ 0, 4, /* M */
+ 8, 2, /* P */
+ 24, 3, /* mux */
+ BIT(31), /* gate */
+ CLK_SET_RATE_PARENT);
+static SUNXI_CCU_MP_WITH_MUX_GATE(tcon_tv1_clk, "tcon-tv1",
+ tcon_tv_parents, 0xb84,
+ 0, 4, /* M */
+ 8, 2, /* P */
+ 24, 3, /* mux */
+ BIT(31), /* gate */
+ CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_GATE(bus_tcon_tv0_clk, "bus-tcon-tv0", "ahb3",
+ 0xb9c, BIT(0), 0);
+static SUNXI_CCU_GATE(bus_tcon_tv1_clk, "bus-tcon-tv1", "ahb3",
+ 0xb9c, BIT(1), 0);
+
+static SUNXI_CCU_MP_WITH_MUX_GATE(tve0_clk, "tve0",
+ tcon_tv_parents, 0xbb0,
+ 0, 4, /* M */
+ 8, 2, /* P */
+ 24, 3, /* mux */
+ BIT(31), /* gate */
+ CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_GATE(bus_tve_top_clk, "bus-tve-top", "ahb3",
+ 0xbbc, BIT(0), 0);
+static SUNXI_CCU_GATE(bus_tve0_clk, "bus-tve0", "ahb3",
+ 0xbbc, BIT(1), 0);
+
+static const char * const hdcp_parents[] = { "pll-periph0", "pll-periph1" };
+static SUNXI_CCU_M_WITH_MUX_GATE(hdcp_clk, "hdcp", hdcp_parents, 0xc40,
+ 0, 4, /* M */
+ 24, 2, /* mux */
+ BIT(31), /* gate */
+ 0);
+
+static SUNXI_CCU_GATE(bus_hdcp_clk, "bus-hdcp", "ahb3", 0xc4c, BIT(0), 0);
+
+/* Fixed factor clocks */
+static CLK_FIXED_FACTOR_FW_NAME(osc12M_clk, "osc12M", "hosc", 2, 1, 0);
+
+static const struct clk_hw *clk_parent_pll_audio[] = {
+ &pll_audio_hs_clk.common.hw
+};
+
+/*
+ * The divider of pll-audio is fixed to 24 for now, so 24576000 and 22579200
+ * rates can be set exactly in conjunction with sigma-delta modulation.
+ */
+static CLK_FIXED_FACTOR_HWS(pll_audio_1x_clk, "pll-audio-1x",
+ clk_parent_pll_audio,
+ 96, 1, CLK_SET_RATE_PARENT);
+static CLK_FIXED_FACTOR_HWS(pll_audio_2x_clk, "pll-audio-2x",
+ clk_parent_pll_audio,
+ 48, 1, CLK_SET_RATE_PARENT);
+static CLK_FIXED_FACTOR_HWS(pll_audio_4x_clk, "pll-audio-4x",
+ clk_parent_pll_audio,
+ 24, 1, CLK_SET_RATE_PARENT);
+
+static const struct clk_hw *pll_periph0_parents[] = {
+ &pll_periph0_clk.common.hw
+};
+
+static CLK_FIXED_FACTOR_HWS(pll_periph0_2x_clk, "pll-periph0-2x",
+ pll_periph0_parents,
+ 1, 2, 0);
+
+static const struct clk_hw *pll_periph1_parents[] = {
+ &pll_periph1_clk.common.hw
+};
+
+static CLK_FIXED_FACTOR_HWS(pll_periph1_2x_clk, "pll-periph1-2x",
+ pll_periph1_parents,
+ 1, 2, 0);
+
+static CLK_FIXED_FACTOR_HW(pll_video0_4x_clk, "pll-video0-4x",
+ &pll_video0_clk.common.hw,
+ 1, 4, CLK_SET_RATE_PARENT);
+static CLK_FIXED_FACTOR_HW(pll_video1_4x_clk, "pll-video1-4x",
+ &pll_video1_clk.common.hw,
+ 1, 4, CLK_SET_RATE_PARENT);
+static CLK_FIXED_FACTOR_HW(pll_video2_4x_clk, "pll-video2-4x",
+ &pll_video2_clk.common.hw,
+ 1, 4, CLK_SET_RATE_PARENT);
+
+static struct ccu_common *sun50i_h616_ccu_clks[] = {
+ &pll_cpux_clk.common,
+ &pll_ddr0_clk.common,
+ &pll_ddr1_clk.common,
+ &pll_periph0_clk.common,
+ &pll_periph1_clk.common,
+ &pll_gpu_clk.common,
+ &pll_video0_clk.common,
+ &pll_video1_clk.common,
+ &pll_video2_clk.common,
+ &pll_ve_clk.common,
+ &pll_de_clk.common,
+ &pll_audio_hs_clk.common,
+ &cpux_clk.common,
+ &axi_clk.common,
+ &cpux_apb_clk.common,
+ &psi_ahb1_ahb2_clk.common,
+ &ahb3_clk.common,
+ &apb1_clk.common,
+ &apb2_clk.common,
+ &mbus_clk.common,
+ &de_clk.common,
+ &bus_de_clk.common,
+ &deinterlace_clk.common,
+ &bus_deinterlace_clk.common,
+ &g2d_clk.common,
+ &bus_g2d_clk.common,
+ &gpu0_clk.common,
+ &bus_gpu_clk.common,
+ &gpu1_clk.common,
+ &ce_clk.common,
+ &bus_ce_clk.common,
+ &ve_clk.common,
+ &bus_ve_clk.common,
+ &bus_dma_clk.common,
+ &bus_hstimer_clk.common,
+ &avs_clk.common,
+ &bus_dbg_clk.common,
+ &bus_psi_clk.common,
+ &bus_pwm_clk.common,
+ &bus_iommu_clk.common,
+ &dram_clk.common,
+ &mbus_dma_clk.common,
+ &mbus_ve_clk.common,
+ &mbus_ce_clk.common,
+ &mbus_ts_clk.common,
+ &mbus_nand_clk.common,
+ &mbus_g2d_clk.common,
+ &bus_dram_clk.common,
+ &nand0_clk.common,
+ &nand1_clk.common,
+ &bus_nand_clk.common,
+ &mmc0_clk.common,
+ &mmc1_clk.common,
+ &mmc2_clk.common,
+ &bus_mmc0_clk.common,
+ &bus_mmc1_clk.common,
+ &bus_mmc2_clk.common,
+ &bus_uart0_clk.common,
+ &bus_uart1_clk.common,
+ &bus_uart2_clk.common,
+ &bus_uart3_clk.common,
+ &bus_uart4_clk.common,
+ &bus_uart5_clk.common,
+ &bus_i2c0_clk.common,
+ &bus_i2c1_clk.common,
+ &bus_i2c2_clk.common,
+ &bus_i2c3_clk.common,
+ &bus_i2c4_clk.common,
+ &spi0_clk.common,
+ &spi1_clk.common,
+ &bus_spi0_clk.common,
+ &bus_spi1_clk.common,
+ &emac_25m_clk.common,
+ &bus_emac0_clk.common,
+ &bus_emac1_clk.common,
+ &ts_clk.common,
+ &bus_ts_clk.common,
+ &bus_ths_clk.common,
+ &spdif_clk.common,
+ &bus_spdif_clk.common,
+ &dmic_clk.common,
+ &bus_dmic_clk.common,
+ &audio_codec_1x_clk.common,
+ &audio_codec_4x_clk.common,
+ &bus_audio_codec_clk.common,
+ &audio_hub_clk.common,
+ &bus_audio_hub_clk.common,
+ &usb_ohci0_clk.common,
+ &usb_phy0_clk.common,
+ &usb_ohci1_clk.common,
+ &usb_phy1_clk.common,
+ &usb_ohci2_clk.common,
+ &usb_phy2_clk.common,
+ &usb_ohci3_clk.common,
+ &usb_phy3_clk.common,
+ &bus_ohci0_clk.common,
+ &bus_ohci1_clk.common,
+ &bus_ohci2_clk.common,
+ &bus_ohci3_clk.common,
+ &bus_ehci0_clk.common,
+ &bus_ehci1_clk.common,
+ &bus_ehci2_clk.common,
+ &bus_ehci3_clk.common,
+ &bus_otg_clk.common,
+ &bus_keyadc_clk.common,
+ &hdmi_clk.common,
+ &hdmi_slow_clk.common,
+ &hdmi_cec_clk.common,
+ &bus_hdmi_clk.common,
+ &bus_tcon_top_clk.common,
+ &tcon_tv0_clk.common,
+ &tcon_tv1_clk.common,
+ &bus_tcon_tv0_clk.common,
+ &bus_tcon_tv1_clk.common,
+ &tve0_clk.common,
+ &bus_tve_top_clk.common,
+ &bus_tve0_clk.common,
+ &hdcp_clk.common,
+ &bus_hdcp_clk.common,
+};
+
+static struct clk_hw_onecell_data sun50i_h616_hw_clks = {
+ .hws = {
+ [CLK_OSC12M] = &osc12M_clk.hw,
+ [CLK_PLL_CPUX] = &pll_cpux_clk.common.hw,
+ [CLK_PLL_DDR0] = &pll_ddr0_clk.common.hw,
+ [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_PERIPH1] = &pll_periph1_clk.common.hw,
+ [CLK_PLL_PERIPH1_2X] = &pll_periph1_2x_clk.hw,
+ [CLK_PLL_GPU] = &pll_gpu_clk.common.hw,
+ [CLK_PLL_VIDEO0] = &pll_video0_clk.common.hw,
+ [CLK_PLL_VIDEO0_4X] = &pll_video0_4x_clk.hw,
+ [CLK_PLL_VIDEO1] = &pll_video1_clk.common.hw,
+ [CLK_PLL_VIDEO1_4X] = &pll_video1_4x_clk.hw,
+ [CLK_PLL_VIDEO2] = &pll_video2_clk.common.hw,
+ [CLK_PLL_VIDEO2_4X] = &pll_video2_4x_clk.hw,
+ [CLK_PLL_VE] = &pll_ve_clk.common.hw,
+ [CLK_PLL_DE] = &pll_de_clk.common.hw,
+ [CLK_PLL_AUDIO_HS] = &pll_audio_hs_clk.common.hw,
+ [CLK_PLL_AUDIO_1X] = &pll_audio_1x_clk.hw,
+ [CLK_PLL_AUDIO_2X] = &pll_audio_2x_clk.hw,
+ [CLK_PLL_AUDIO_4X] = &pll_audio_4x_clk.hw,
+ [CLK_CPUX] = &cpux_clk.common.hw,
+ [CLK_AXI] = &axi_clk.common.hw,
+ [CLK_CPUX_APB] = &cpux_apb_clk.common.hw,
+ [CLK_PSI_AHB1_AHB2] = &psi_ahb1_ahb2_clk.common.hw,
+ [CLK_AHB3] = &ahb3_clk.common.hw,
+ [CLK_APB1] = &apb1_clk.common.hw,
+ [CLK_APB2] = &apb2_clk.common.hw,
+ [CLK_MBUS] = &mbus_clk.common.hw,
+ [CLK_DE] = &de_clk.common.hw,
+ [CLK_BUS_DE] = &bus_de_clk.common.hw,
+ [CLK_DEINTERLACE] = &deinterlace_clk.common.hw,
+ [CLK_BUS_DEINTERLACE] = &bus_deinterlace_clk.common.hw,
+ [CLK_G2D] = &g2d_clk.common.hw,
+ [CLK_BUS_G2D] = &bus_g2d_clk.common.hw,
+ [CLK_GPU0] = &gpu0_clk.common.hw,
+ [CLK_BUS_GPU] = &bus_gpu_clk.common.hw,
+ [CLK_GPU1] = &gpu1_clk.common.hw,
+ [CLK_CE] = &ce_clk.common.hw,
+ [CLK_BUS_CE] = &bus_ce_clk.common.hw,
+ [CLK_VE] = &ve_clk.common.hw,
+ [CLK_BUS_VE] = &bus_ve_clk.common.hw,
+ [CLK_BUS_DMA] = &bus_dma_clk.common.hw,
+ [CLK_BUS_HSTIMER] = &bus_hstimer_clk.common.hw,
+ [CLK_AVS] = &avs_clk.common.hw,
+ [CLK_BUS_DBG] = &bus_dbg_clk.common.hw,
+ [CLK_BUS_PSI] = &bus_psi_clk.common.hw,
+ [CLK_BUS_PWM] = &bus_pwm_clk.common.hw,
+ [CLK_BUS_IOMMU] = &bus_iommu_clk.common.hw,
+ [CLK_DRAM] = &dram_clk.common.hw,
+ [CLK_MBUS_DMA] = &mbus_dma_clk.common.hw,
+ [CLK_MBUS_VE] = &mbus_ve_clk.common.hw,
+ [CLK_MBUS_CE] = &mbus_ce_clk.common.hw,
+ [CLK_MBUS_TS] = &mbus_ts_clk.common.hw,
+ [CLK_MBUS_NAND] = &mbus_nand_clk.common.hw,
+ [CLK_MBUS_G2D] = &mbus_g2d_clk.common.hw,
+ [CLK_BUS_DRAM] = &bus_dram_clk.common.hw,
+ [CLK_NAND0] = &nand0_clk.common.hw,
+ [CLK_NAND1] = &nand1_clk.common.hw,
+ [CLK_BUS_NAND] = &bus_nand_clk.common.hw,
+ [CLK_MMC0] = &mmc0_clk.common.hw,
+ [CLK_MMC1] = &mmc1_clk.common.hw,
+ [CLK_MMC2] = &mmc2_clk.common.hw,
+ [CLK_BUS_MMC0] = &bus_mmc0_clk.common.hw,
+ [CLK_BUS_MMC1] = &bus_mmc1_clk.common.hw,
+ [CLK_BUS_MMC2] = &bus_mmc2_clk.common.hw,
+ [CLK_BUS_UART0] = &bus_uart0_clk.common.hw,
+ [CLK_BUS_UART1] = &bus_uart1_clk.common.hw,
+ [CLK_BUS_UART2] = &bus_uart2_clk.common.hw,
+ [CLK_BUS_UART3] = &bus_uart3_clk.common.hw,
+ [CLK_BUS_UART4] = &bus_uart4_clk.common.hw,
+ [CLK_BUS_UART5] = &bus_uart5_clk.common.hw,
+ [CLK_BUS_I2C0] = &bus_i2c0_clk.common.hw,
+ [CLK_BUS_I2C1] = &bus_i2c1_clk.common.hw,
+ [CLK_BUS_I2C2] = &bus_i2c2_clk.common.hw,
+ [CLK_BUS_I2C3] = &bus_i2c3_clk.common.hw,
+ [CLK_BUS_I2C4] = &bus_i2c4_clk.common.hw,
+ [CLK_SPI0] = &spi0_clk.common.hw,
+ [CLK_SPI1] = &spi1_clk.common.hw,
+ [CLK_BUS_SPI0] = &bus_spi0_clk.common.hw,
+ [CLK_BUS_SPI1] = &bus_spi1_clk.common.hw,
+ [CLK_EMAC_25M] = &emac_25m_clk.common.hw,
+ [CLK_BUS_EMAC0] = &bus_emac0_clk.common.hw,
+ [CLK_BUS_EMAC1] = &bus_emac1_clk.common.hw,
+ [CLK_TS] = &ts_clk.common.hw,
+ [CLK_BUS_TS] = &bus_ts_clk.common.hw,
+ [CLK_BUS_THS] = &bus_ths_clk.common.hw,
+ [CLK_SPDIF] = &spdif_clk.common.hw,
+ [CLK_BUS_SPDIF] = &bus_spdif_clk.common.hw,
+ [CLK_DMIC] = &dmic_clk.common.hw,
+ [CLK_BUS_DMIC] = &bus_dmic_clk.common.hw,
+ [CLK_AUDIO_CODEC_1X] = &audio_codec_1x_clk.common.hw,
+ [CLK_AUDIO_CODEC_4X] = &audio_codec_4x_clk.common.hw,
+ [CLK_BUS_AUDIO_CODEC] = &bus_audio_codec_clk.common.hw,
+ [CLK_AUDIO_HUB] = &audio_hub_clk.common.hw,
+ [CLK_BUS_AUDIO_HUB] = &bus_audio_hub_clk.common.hw,
+ [CLK_USB_OHCI0] = &usb_ohci0_clk.common.hw,
+ [CLK_USB_PHY0] = &usb_phy0_clk.common.hw,
+ [CLK_USB_OHCI1] = &usb_ohci1_clk.common.hw,
+ [CLK_USB_PHY1] = &usb_phy1_clk.common.hw,
+ [CLK_USB_OHCI2] = &usb_ohci2_clk.common.hw,
+ [CLK_USB_PHY2] = &usb_phy2_clk.common.hw,
+ [CLK_USB_OHCI3] = &usb_ohci3_clk.common.hw,
+ [CLK_USB_PHY3] = &usb_phy3_clk.common.hw,
+ [CLK_BUS_OHCI0] = &bus_ohci0_clk.common.hw,
+ [CLK_BUS_OHCI1] = &bus_ohci1_clk.common.hw,
+ [CLK_BUS_OHCI2] = &bus_ohci2_clk.common.hw,
+ [CLK_BUS_OHCI3] = &bus_ohci3_clk.common.hw,
+ [CLK_BUS_EHCI0] = &bus_ehci0_clk.common.hw,
+ [CLK_BUS_EHCI1] = &bus_ehci1_clk.common.hw,
+ [CLK_BUS_EHCI2] = &bus_ehci2_clk.common.hw,
+ [CLK_BUS_EHCI3] = &bus_ehci3_clk.common.hw,
+ [CLK_BUS_OTG] = &bus_otg_clk.common.hw,
+ [CLK_BUS_KEYADC] = &bus_keyadc_clk.common.hw,
+ [CLK_HDMI] = &hdmi_clk.common.hw,
+ [CLK_HDMI_SLOW] = &hdmi_slow_clk.common.hw,
+ [CLK_HDMI_CEC] = &hdmi_cec_clk.common.hw,
+ [CLK_BUS_HDMI] = &bus_hdmi_clk.common.hw,
+ [CLK_BUS_TCON_TOP] = &bus_tcon_top_clk.common.hw,
+ [CLK_TCON_TV0] = &tcon_tv0_clk.common.hw,
+ [CLK_TCON_TV1] = &tcon_tv1_clk.common.hw,
+ [CLK_BUS_TCON_TV0] = &bus_tcon_tv0_clk.common.hw,
+ [CLK_BUS_TCON_TV1] = &bus_tcon_tv1_clk.common.hw,
+ [CLK_TVE0] = &tve0_clk.common.hw,
+ [CLK_BUS_TVE_TOP] = &bus_tve_top_clk.common.hw,
+ [CLK_BUS_TVE0] = &bus_tve0_clk.common.hw,
+ [CLK_HDCP] = &hdcp_clk.common.hw,
+ [CLK_BUS_HDCP] = &bus_hdcp_clk.common.hw,
+ },
+ .num = CLK_NUMBER,
+};
+
+static struct ccu_reset_map sun50i_h616_ccu_resets[] = {
+ [RST_MBUS] = { 0x540, BIT(30) },
+
+ [RST_BUS_DE] = { 0x60c, BIT(16) },
+ [RST_BUS_DEINTERLACE] = { 0x62c, BIT(16) },
+ [RST_BUS_GPU] = { 0x67c, BIT(16) },
+ [RST_BUS_CE] = { 0x68c, BIT(16) },
+ [RST_BUS_VE] = { 0x69c, BIT(16) },
+ [RST_BUS_DMA] = { 0x70c, BIT(16) },
+ [RST_BUS_HSTIMER] = { 0x73c, BIT(16) },
+ [RST_BUS_DBG] = { 0x78c, BIT(16) },
+ [RST_BUS_PSI] = { 0x79c, BIT(16) },
+ [RST_BUS_PWM] = { 0x7ac, BIT(16) },
+ [RST_BUS_IOMMU] = { 0x7bc, BIT(16) },
+ [RST_BUS_DRAM] = { 0x80c, BIT(16) },
+ [RST_BUS_NAND] = { 0x82c, BIT(16) },
+ [RST_BUS_MMC0] = { 0x84c, BIT(16) },
+ [RST_BUS_MMC1] = { 0x84c, BIT(17) },
+ [RST_BUS_MMC2] = { 0x84c, BIT(18) },
+ [RST_BUS_UART0] = { 0x90c, BIT(16) },
+ [RST_BUS_UART1] = { 0x90c, BIT(17) },
+ [RST_BUS_UART2] = { 0x90c, BIT(18) },
+ [RST_BUS_UART3] = { 0x90c, BIT(19) },
+ [RST_BUS_UART4] = { 0x90c, BIT(20) },
+ [RST_BUS_UART5] = { 0x90c, BIT(21) },
+ [RST_BUS_I2C0] = { 0x91c, BIT(16) },
+ [RST_BUS_I2C1] = { 0x91c, BIT(17) },
+ [RST_BUS_I2C2] = { 0x91c, BIT(18) },
+ [RST_BUS_I2C3] = { 0x91c, BIT(19) },
+ [RST_BUS_I2C4] = { 0x91c, BIT(20) },
+ [RST_BUS_SPI0] = { 0x96c, BIT(16) },
+ [RST_BUS_SPI1] = { 0x96c, BIT(17) },
+ [RST_BUS_EMAC0] = { 0x97c, BIT(16) },
+ [RST_BUS_EMAC1] = { 0x97c, BIT(17) },
+ [RST_BUS_TS] = { 0x9bc, BIT(16) },
+ [RST_BUS_THS] = { 0x9fc, BIT(16) },
+ [RST_BUS_SPDIF] = { 0xa2c, BIT(16) },
+ [RST_BUS_DMIC] = { 0xa4c, BIT(16) },
+ [RST_BUS_AUDIO_CODEC] = { 0xa5c, BIT(16) },
+ [RST_BUS_AUDIO_HUB] = { 0xa6c, BIT(16) },
+
+ [RST_USB_PHY0] = { 0xa70, BIT(30) },
+ [RST_USB_PHY1] = { 0xa74, BIT(30) },
+ [RST_USB_PHY2] = { 0xa78, BIT(30) },
+ [RST_USB_PHY3] = { 0xa7c, BIT(30) },
+ [RST_BUS_OHCI0] = { 0xa8c, BIT(16) },
+ [RST_BUS_OHCI1] = { 0xa8c, BIT(17) },
+ [RST_BUS_OHCI2] = { 0xa8c, BIT(18) },
+ [RST_BUS_OHCI3] = { 0xa8c, BIT(19) },
+ [RST_BUS_EHCI0] = { 0xa8c, BIT(20) },
+ [RST_BUS_EHCI1] = { 0xa8c, BIT(21) },
+ [RST_BUS_EHCI2] = { 0xa8c, BIT(22) },
+ [RST_BUS_EHCI3] = { 0xa8c, BIT(23) },
+ [RST_BUS_OTG] = { 0xa8c, BIT(24) },
+ [RST_BUS_KEYADC] = { 0xa9c, BIT(16) },
+
+ [RST_BUS_HDMI] = { 0xb1c, BIT(16) },
+ [RST_BUS_HDMI_SUB] = { 0xb1c, BIT(17) },
+ [RST_BUS_TCON_TOP] = { 0xb5c, BIT(16) },
+ [RST_BUS_TCON_TV0] = { 0xb9c, BIT(16) },
+ [RST_BUS_TCON_TV1] = { 0xb9c, BIT(17) },
+ [RST_BUS_TVE_TOP] = { 0xbbc, BIT(16) },
+ [RST_BUS_TVE0] = { 0xbbc, BIT(17) },
+ [RST_BUS_HDCP] = { 0xc4c, BIT(16) },
+};
+
+static const struct sunxi_ccu_desc sun50i_h616_ccu_desc = {
+ .ccu_clks = sun50i_h616_ccu_clks,
+ .num_ccu_clks = ARRAY_SIZE(sun50i_h616_ccu_clks),
+
+ .hw_clks = &sun50i_h616_hw_clks,
+
+ .resets = sun50i_h616_ccu_resets,
+ .num_resets = ARRAY_SIZE(sun50i_h616_ccu_resets),
+};
+
+static const u32 pll_regs[] = {
+ SUN50I_H616_PLL_CPUX_REG,
+ SUN50I_H616_PLL_DDR0_REG,
+ SUN50I_H616_PLL_DDR1_REG,
+ SUN50I_H616_PLL_PERIPH0_REG,
+ SUN50I_H616_PLL_PERIPH1_REG,
+ SUN50I_H616_PLL_GPU_REG,
+ SUN50I_H616_PLL_VIDEO0_REG,
+ SUN50I_H616_PLL_VIDEO1_REG,
+ SUN50I_H616_PLL_VIDEO2_REG,
+ SUN50I_H616_PLL_VE_REG,
+ SUN50I_H616_PLL_DE_REG,
+ SUN50I_H616_PLL_AUDIO_REG,
+};
+
+static const u32 pll_video_regs[] = {
+ SUN50I_H616_PLL_VIDEO0_REG,
+ SUN50I_H616_PLL_VIDEO1_REG,
+ SUN50I_H616_PLL_VIDEO2_REG,
+};
+
+static const u32 usb2_clk_regs[] = {
+ SUN50I_H616_USB0_CLK_REG,
+ SUN50I_H616_USB1_CLK_REG,
+ SUN50I_H616_USB2_CLK_REG,
+ SUN50I_H616_USB3_CLK_REG,
+};
+
+static void __init sun50i_h616_ccu_setup(struct device_node *node)
+{
+ void __iomem *reg;
+ u32 val;
+ int i;
+
+ reg = of_io_request_and_map(node, 0, of_node_full_name(node));
+ if (IS_ERR(reg)) {
+ pr_err("%pOF: Could not map clock registers\n", node);
+ return;
+ }
+
+ /* Enable the lock bits and the output enable bits on all PLLs */
+ for (i = 0; i < ARRAY_SIZE(pll_regs); i++) {
+ val = readl(reg + pll_regs[i]);
+ val |= BIT(29) | BIT(27);
+ writel(val, reg + pll_regs[i]);
+ }
+
+ /*
+ * Force the output divider of video PLLs to 0.
+ *
+ * See the comment before pll-video0 definition for the reason.
+ */
+ for (i = 0; i < ARRAY_SIZE(pll_video_regs); i++) {
+ val = readl(reg + pll_video_regs[i]);
+ val &= ~BIT(0);
+ writel(val, reg + pll_video_regs[i]);
+ }
+
+ /*
+ * Force OHCI 12M clock sources to 00 (12MHz divided from 48MHz)
+ *
+ * This clock mux is still mysterious, and the code just enforces
+ * it to have a valid clock parent.
+ */
+ for (i = 0; i < ARRAY_SIZE(usb2_clk_regs); i++) {
+ val = readl(reg + usb2_clk_regs[i]);
+ val &= ~GENMASK(25, 24);
+ writel(val, reg + usb2_clk_regs[i]);
+ }
+
+ /*
+ * Force the post-divider of pll-audio to 12 and the output divider
+ * of it to 2, so 24576000 and 22579200 rates can be set exactly.
+ */
+ val = readl(reg + SUN50I_H616_PLL_AUDIO_REG);
+ val &= ~(GENMASK(21, 16) | BIT(0));
+ writel(val | (11 << 16) | BIT(0), reg + SUN50I_H616_PLL_AUDIO_REG);
+
+ /*
+ * First clock parent (osc32K) is unusable for CEC. But since there
+ * is no good way to force parent switch (both run with same frequency),
+ * just set second clock parent here.
+ */
+ val = readl(reg + SUN50I_H616_HDMI_CEC_CLK_REG);
+ val |= BIT(24);
+ writel(val, reg + SUN50I_H616_HDMI_CEC_CLK_REG);
+
+ i = sunxi_ccu_probe(node, reg, &sun50i_h616_ccu_desc);
+ if (i)
+ pr_err("%pOF: probing clocks fails: %d\n", node, i);
+}
+
+CLK_OF_DECLARE(sun50i_h616_ccu, "allwinner,sun50i-h616-ccu",
+ sun50i_h616_ccu_setup);
diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h616.h b/drivers/clk/sunxi-ng/ccu-sun50i-h616.h
new file mode 100644
index 000000000000..dd671b413f22
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-h616.h
@@ -0,0 +1,56 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright 2020 Arm Ltd.
+ */
+
+#ifndef _CCU_SUN50I_H616_H_
+#define _CCU_SUN50I_H616_H_
+
+#include <dt-bindings/clock/sun50i-h616-ccu.h>
+#include <dt-bindings/reset/sun50i-h616-ccu.h>
+
+#define CLK_OSC12M 0
+#define CLK_PLL_CPUX 1
+#define CLK_PLL_DDR0 2
+#define CLK_PLL_DDR1 3
+
+/* PLL_PERIPH0 exported for PRCM */
+
+#define CLK_PLL_PERIPH0_2X 5
+#define CLK_PLL_PERIPH1 6
+#define CLK_PLL_PERIPH1_2X 7
+#define CLK_PLL_GPU 8
+#define CLK_PLL_VIDEO0 9
+#define CLK_PLL_VIDEO0_4X 10
+#define CLK_PLL_VIDEO1 11
+#define CLK_PLL_VIDEO1_4X 12
+#define CLK_PLL_VIDEO2 13
+#define CLK_PLL_VIDEO2_4X 14
+#define CLK_PLL_VE 15
+#define CLK_PLL_DE 16
+#define CLK_PLL_AUDIO_HS 17
+#define CLK_PLL_AUDIO_1X 18
+#define CLK_PLL_AUDIO_2X 19
+#define CLK_PLL_AUDIO_4X 20
+
+/* CPUX clock exported for DVFS */
+
+#define CLK_AXI 22
+#define CLK_CPUX_APB 23
+#define CLK_PSI_AHB1_AHB2 24
+#define CLK_AHB3 25
+
+/* APB1 clock exported for PIO */
+
+#define CLK_APB2 27
+#define CLK_MBUS 28
+
+/* All module clocks and bus gates are exported except DRAM */
+
+#define CLK_DRAM 49
+
+#define CLK_BUS_DRAM 56
+
+#define CLK_NUMBER (CLK_BUS_HDCP + 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
new file mode 100644
index 000000000000..4fc08b0df2f3
--- /dev/null
+++ b/include/dt-bindings/clock/sun50i-h616-ccu.h
@@ -0,0 +1,115 @@
+/* SPDX-License-Identifier: (GPL-2.0+ or MIT) */
+/*
+ * Copyright (C) 2020 Arm Ltd.
+ */
+
+#ifndef _DT_BINDINGS_CLK_SUN50I_H616_H_
+#define _DT_BINDINGS_CLK_SUN50I_H616_H_
+
+#define CLK_PLL_PERIPH0 4
+
+#define CLK_CPUX 21
+
+#define CLK_APB1 26
+
+#define CLK_DE 29
+#define CLK_BUS_DE 30
+#define CLK_DEINTERLACE 31
+#define CLK_BUS_DEINTERLACE 32
+#define CLK_G2D 33
+#define CLK_BUS_G2D 34
+#define CLK_GPU0 35
+#define CLK_BUS_GPU 36
+#define CLK_GPU1 37
+#define CLK_CE 38
+#define CLK_BUS_CE 39
+#define CLK_VE 40
+#define CLK_BUS_VE 41
+#define CLK_BUS_DMA 42
+#define CLK_BUS_HSTIMER 43
+#define CLK_AVS 44
+#define CLK_BUS_DBG 45
+#define CLK_BUS_PSI 46
+#define CLK_BUS_PWM 47
+#define CLK_BUS_IOMMU 48
+
+#define CLK_MBUS_DMA 50
+#define CLK_MBUS_VE 51
+#define CLK_MBUS_CE 52
+#define CLK_MBUS_TS 53
+#define CLK_MBUS_NAND 54
+#define CLK_MBUS_G2D 55
+
+#define CLK_NAND0 57
+#define CLK_NAND1 58
+#define CLK_BUS_NAND 59
+#define CLK_MMC0 60
+#define CLK_MMC1 61
+#define CLK_MMC2 62
+#define CLK_BUS_MMC0 63
+#define CLK_BUS_MMC1 64
+#define CLK_BUS_MMC2 65
+#define CLK_BUS_UART0 66
+#define CLK_BUS_UART1 67
+#define CLK_BUS_UART2 68
+#define CLK_BUS_UART3 69
+#define CLK_BUS_UART4 70
+#define CLK_BUS_UART5 71
+#define CLK_BUS_I2C0 72
+#define CLK_BUS_I2C1 73
+#define CLK_BUS_I2C2 74
+#define CLK_BUS_I2C3 75
+#define CLK_BUS_I2C4 76
+#define CLK_SPI0 77
+#define CLK_SPI1 78
+#define CLK_BUS_SPI0 79
+#define CLK_BUS_SPI1 80
+#define CLK_EMAC_25M 81
+#define CLK_BUS_EMAC0 82
+#define CLK_BUS_EMAC1 83
+#define CLK_TS 84
+#define CLK_BUS_TS 85
+#define CLK_BUS_THS 86
+#define CLK_SPDIF 87
+#define CLK_BUS_SPDIF 88
+#define CLK_DMIC 89
+#define CLK_BUS_DMIC 90
+#define CLK_AUDIO_CODEC_1X 91
+#define CLK_AUDIO_CODEC_4X 92
+#define CLK_BUS_AUDIO_CODEC 93
+#define CLK_AUDIO_HUB 94
+#define CLK_BUS_AUDIO_HUB 95
+#define CLK_USB_OHCI0 96
+#define CLK_USB_PHY0 97
+#define CLK_USB_OHCI1 98
+#define CLK_USB_PHY1 99
+#define CLK_USB_OHCI2 100
+#define CLK_USB_PHY2 101
+#define CLK_USB_OHCI3 102
+#define CLK_USB_PHY3 103
+#define CLK_BUS_OHCI0 104
+#define CLK_BUS_OHCI1 105
+#define CLK_BUS_OHCI2 106
+#define CLK_BUS_OHCI3 107
+#define CLK_BUS_EHCI0 108
+#define CLK_BUS_EHCI1 109
+#define CLK_BUS_EHCI2 110
+#define CLK_BUS_EHCI3 111
+#define CLK_BUS_OTG 112
+#define CLK_BUS_KEYADC 113
+#define CLK_HDMI 114
+#define CLK_HDMI_SLOW 115
+#define CLK_HDMI_CEC 116
+#define CLK_BUS_HDMI 117
+#define CLK_BUS_TCON_TOP 118
+#define CLK_TCON_TV0 119
+#define CLK_TCON_TV1 120
+#define CLK_BUS_TCON_TV0 121
+#define CLK_BUS_TCON_TV1 122
+#define CLK_TVE0 123
+#define CLK_BUS_TVE_TOP 124
+#define CLK_BUS_TVE0 125
+#define CLK_HDCP 126
+#define CLK_BUS_HDCP 127
+
+#endif /* _DT_BINDINGS_CLK_SUN50I_H616_H_ */
diff --git a/include/dt-bindings/reset/sun50i-h616-ccu.h b/include/dt-bindings/reset/sun50i-h616-ccu.h
new file mode 100644
index 000000000000..cb6285a8d128
--- /dev/null
+++ b/include/dt-bindings/reset/sun50i-h616-ccu.h
@@ -0,0 +1,70 @@
+/* SPDX-License-Identifier: (GPL-2.0+ or MIT) */
+/*
+ * Copyright (C) 2020 Arm Ltd.
+ */
+
+#ifndef _DT_BINDINGS_RESET_SUN50I_H616_H_
+#define _DT_BINDINGS_RESET_SUN50I_H616_H_
+
+#define RST_MBUS 0
+#define RST_BUS_DE 1
+#define RST_BUS_DEINTERLACE 2
+#define RST_BUS_GPU 3
+#define RST_BUS_CE 4
+#define RST_BUS_VE 5
+#define RST_BUS_DMA 6
+#define RST_BUS_HSTIMER 7
+#define RST_BUS_DBG 8
+#define RST_BUS_PSI 9
+#define RST_BUS_PWM 10
+#define RST_BUS_IOMMU 11
+#define RST_BUS_DRAM 12
+#define RST_BUS_NAND 13
+#define RST_BUS_MMC0 14
+#define RST_BUS_MMC1 15
+#define RST_BUS_MMC2 16
+#define RST_BUS_UART0 17
+#define RST_BUS_UART1 18
+#define RST_BUS_UART2 19
+#define RST_BUS_UART3 20
+#define RST_BUS_UART4 21
+#define RST_BUS_UART5 22
+#define RST_BUS_I2C0 23
+#define RST_BUS_I2C1 24
+#define RST_BUS_I2C2 25
+#define RST_BUS_I2C3 26
+#define RST_BUS_I2C4 27
+#define RST_BUS_SPI0 28
+#define RST_BUS_SPI1 29
+#define RST_BUS_EMAC0 30
+#define RST_BUS_EMAC1 31
+#define RST_BUS_TS 32
+#define RST_BUS_THS 33
+#define RST_BUS_SPDIF 34
+#define RST_BUS_DMIC 35
+#define RST_BUS_AUDIO_CODEC 36
+#define RST_BUS_AUDIO_HUB 37
+#define RST_USB_PHY0 38
+#define RST_USB_PHY1 39
+#define RST_USB_PHY2 40
+#define RST_USB_PHY3 41
+#define RST_BUS_OHCI0 42
+#define RST_BUS_OHCI1 43
+#define RST_BUS_OHCI2 44
+#define RST_BUS_OHCI3 45
+#define RST_BUS_EHCI0 46
+#define RST_BUS_EHCI1 47
+#define RST_BUS_EHCI2 48
+#define RST_BUS_EHCI3 49
+#define RST_BUS_OTG 50
+#define RST_BUS_HDMI 51
+#define RST_BUS_HDMI_SUB 52
+#define RST_BUS_TCON_TOP 53
+#define RST_BUS_TCON_TV0 54
+#define RST_BUS_TCON_TV1 55
+#define RST_BUS_TVE_TOP 56
+#define RST_BUS_TVE0 57
+#define RST_BUS_HDCP 58
+#define RST_BUS_KEYADC 59
+
+#endif /* _DT_BINDINGS_RESET_SUN50I_H616_H_ */
--
2.17.5

Andre Przywara

unread,
Jan 17, 2021, 9:09:50 PM1/17/21
to Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Icenowy Zheng, Linus Walleij, Rob Herring, Clément Péron, Samuel Holland, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Lee Jones
Currently the AXP chip requires to have its IRQ line connected to some
interrupt controller, and will fail probing when this is not the case.

On a new Allwinner SoC (H616) there is no NMI pin anymore, so the
interrupt functionality of the AXP chip is simply not available.

Check whether the DT describes the AXP chip as an interrupt controller
before trying to register the irqchip, to avoid probe failures on
setups without an interrupt.

Signed-off-by: Andre Przywara <andre.p...@arm.com>
---
drivers/mfd/axp20x.c | 17 +++++++++++------
1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c
index aa59496e4376..a52595c49d40 100644
--- a/drivers/mfd/axp20x.c
+++ b/drivers/mfd/axp20x.c
@@ -959,12 +959,17 @@ int axp20x_device_probe(struct axp20x_dev *axp20x)
AXP806_REG_ADDR_EXT_ADDR_SLAVE_MODE);
}

- ret = regmap_add_irq_chip(axp20x->regmap, axp20x->irq,
- IRQF_ONESHOT | IRQF_SHARED | axp20x->irq_flags,
- -1, axp20x->regmap_irq_chip, &axp20x->regmap_irqc);
- if (ret) {
- dev_err(axp20x->dev, "failed to add irq chip: %d\n", ret);
- return ret;
+ if (!axp20x->dev->of_node ||
+ of_property_read_bool(axp20x->dev->of_node, "interrupt-controller")) {
+ ret = regmap_add_irq_chip(axp20x->regmap, axp20x->irq,
+ IRQF_ONESHOT | IRQF_SHARED | axp20x->irq_flags,
+ -1, axp20x->regmap_irq_chip,
+ &axp20x->regmap_irqc);
+ if (ret) {
+ dev_err(axp20x->dev, "failed to add irq chip: %d\n",
+ ret);
+ return ret;
+ }
}

ret = mfd_add_devices(axp20x->dev, -1, axp20x->cells,
--
2.17.5

Andre Przywara

unread,
Jan 17, 2021, 9:09:52 PM1/17/21
to Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Icenowy Zheng, Linus Walleij, Rob Herring, Clément Péron, Samuel Holland, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, devic...@vger.kernel.org
The H616 adds a second EMAC clock register. We don't know about the
exact SRAM properties yet, so this gets omitted for now.

Signed-off-by: Andre Przywara <andre.p...@arm.com>
Acked-by: Rob Herring <ro...@kernel.org>
---
.../bindings/sram/allwinner,sun4i-a10-system-control.yaml | 1 +
1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/sram/allwinner,sun4i-a10-system-control.yaml b/Documentation/devicetree/bindings/sram/allwinner,sun4i-a10-system-control.yaml
index b66a07e21d1e..1c426c211e36 100644
--- a/Documentation/devicetree/bindings/sram/allwinner,sun4i-a10-system-control.yaml
+++ b/Documentation/devicetree/bindings/sram/allwinner,sun4i-a10-system-control.yaml
@@ -49,6 +49,7 @@ properties:
- items:
- const: allwinner,suniv-f1c100s-system-control
- const: allwinner,sun4i-a10-system-control
+ - const: allwinner,sun50i-h616-system-control

Andre Przywara

unread,
Jan 17, 2021, 9:09:55 PM1/17/21
to Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Icenowy Zheng, Linus Walleij, Rob Herring, Clément Péron, Samuel Holland, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com
The Allwinner H616 adds a second EMAC clock register at offset 0x34, for
controlling the second EMAC in this chip.

Allow to extend the regmap in this case, to cover more than the current
4 bytes exported.

Signed-off-by: Andre Przywara <andre.p...@arm.com>
---
drivers/soc/sunxi/sunxi_sram.c | 31 +++++++++++++++++++++++--------
1 file changed, 23 insertions(+), 8 deletions(-)

diff --git a/drivers/soc/sunxi/sunxi_sram.c b/drivers/soc/sunxi/sunxi_sram.c
index d4c7bd59429e..42833e33a96c 100644
--- a/drivers/soc/sunxi/sunxi_sram.c
+++ b/drivers/soc/sunxi/sunxi_sram.c
@@ -283,7 +283,7 @@ int sunxi_sram_release(struct device *dev)
EXPORT_SYMBOL(sunxi_sram_release);

struct sunxi_sramc_variant {
- bool has_emac_clock;
+ int num_emac_clocks;
};

static const struct sunxi_sramc_variant sun4i_a10_sramc_variant = {
@@ -291,20 +291,31 @@ static const struct sunxi_sramc_variant sun4i_a10_sramc_variant = {
};

static const struct sunxi_sramc_variant sun8i_h3_sramc_variant = {
- .has_emac_clock = true,
+ .num_emac_clocks = 1,
};

static const struct sunxi_sramc_variant sun50i_a64_sramc_variant = {
- .has_emac_clock = true,
+ .num_emac_clocks = 1,
+};
+
+static const struct sunxi_sramc_variant sun50i_h616_sramc_variant = {
+ .num_emac_clocks = 2,
};

#define SUNXI_SRAM_EMAC_CLOCK_REG 0x30
static bool sunxi_sram_regmap_accessible_reg(struct device *dev,
unsigned int reg)
{
- if (reg == SUNXI_SRAM_EMAC_CLOCK_REG)
- return true;
- return false;
+ const struct sunxi_sramc_variant *variant;
+
+ variant = of_device_get_match_data(dev);
+
+ if (reg < SUNXI_SRAM_EMAC_CLOCK_REG)
+ return false;
+ if (reg > SUNXI_SRAM_EMAC_CLOCK_REG + variant->num_emac_clocks * 4)
+ return false;
+
+ return true;
}

static struct regmap_config sunxi_sram_emac_clock_regmap = {
@@ -312,7 +323,7 @@ static struct regmap_config sunxi_sram_emac_clock_regmap = {
.val_bits = 32,
.reg_stride = 4,
/* last defined register */
- .max_register = SUNXI_SRAM_EMAC_CLOCK_REG,
+ .max_register = SUNXI_SRAM_EMAC_CLOCK_REG + 4,
/* other devices have no business accessing other registers */
.readable_reg = sunxi_sram_regmap_accessible_reg,
.writeable_reg = sunxi_sram_regmap_accessible_reg,
@@ -343,7 +354,7 @@ static int sunxi_sram_probe(struct platform_device *pdev)
if (!d)
return -ENOMEM;

- if (variant->has_emac_clock) {
+ if (variant->num_emac_clocks > 0) {
emac_clock = devm_regmap_init_mmio(&pdev->dev, base,
&sunxi_sram_emac_clock_regmap);

@@ -387,6 +398,10 @@ static const struct of_device_id sunxi_sram_dt_match[] = {
.compatible = "allwinner,sun50i-h5-system-control",
.data = &sun50i_a64_sramc_variant,
},
+ {
+ .compatible = "allwinner,sun50i-h616-system-control",
+ .data = &sun50i_h616_sramc_variant,
+ },
{ },
};
MODULE_DEVICE_TABLE(of, sunxi_sram_dt_match);
--
2.17.5

Andre Przywara

unread,
Jan 17, 2021, 9:09:57 PM1/17/21
to Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Icenowy Zheng, Linus Walleij, Rob Herring, Clément Péron, Samuel Holland, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Alexandre Torgue, David S . Miller, Giuseppe Cavallaro, Jakub Kicinski, Jose Abreu, net...@vger.kernel.org
The Allwinner H616 SoC has two EMAC controllers, with the second one
being tied to the internal PHY, but also using a separate EMAC clock
register.

To tell the driver about which clock register to use, we add a parameter
to our syscon phandle. The driver will use this value as an index into
the regmap, so that we can address more than the first register, if
needed.

Signed-off-by: Andre Przywara <andre.p...@arm.com>
---
drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
index 58e0511badba..00c10ec7b693 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
@@ -1129,6 +1129,8 @@ static int sun8i_dwmac_probe(struct platform_device *pdev)
struct stmmac_priv *priv;
struct net_device *ndev;
struct regmap *regmap;
+ struct reg_field syscon_field;
+ u32 syscon_idx = 0;

ret = stmmac_get_platform_resources(pdev, &stmmac_res);
if (ret)
@@ -1190,8 +1192,12 @@ static int sun8i_dwmac_probe(struct platform_device *pdev)
return ret;
}

- gmac->regmap_field = devm_regmap_field_alloc(dev, regmap,
- *gmac->variant->syscon_field);
+ syscon_field = *gmac->variant->syscon_field;
+ ret = of_property_read_u32_index(pdev->dev.of_node, "syscon", 1,
+ &syscon_idx);
+ if (!ret)
+ syscon_field.reg += syscon_idx * sizeof(u32);
+ gmac->regmap_field = devm_regmap_field_alloc(dev, regmap, syscon_field);
if (IS_ERR(gmac->regmap_field)) {
ret = PTR_ERR(gmac->regmap_field);
dev_err(dev, "Unable to map syscon register: %d\n", ret);
@@ -1263,6 +1269,8 @@ static const struct of_device_id sun8i_dwmac_match[] = {
.data = &emac_variant_a64 },
{ .compatible = "allwinner,sun50i-h6-emac",
.data = &emac_variant_h6 },
+ { .compatible = "allwinner,sun50i-h616-emac",
+ .data = &emac_variant_h6 },
{ }
};
MODULE_DEVICE_TABLE(of, sun8i_dwmac_match);
--
2.17.5

Andre Przywara

unread,
Jan 17, 2021, 9:10:00 PM1/17/21
to Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Icenowy Zheng, Linus Walleij, Rob Herring, Clément Péron, Samuel Holland, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Kishon Vijay Abraham I, Vinod Koul
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, to cover newer SoCs: The A100 and H616 use a different
bit for the SIDDQ control.

Signed-off-by: Andre Przywara <andre.p...@arm.com>
---
drivers/phy/allwinner/phy-sun4i-usb.c | 29 +++++++++++----------------
1 file changed, 12 insertions(+), 17 deletions(-)

diff --git a/drivers/phy/allwinner/phy-sun4i-usb.c b/drivers/phy/allwinner/phy-sun4i-usb.c
index 788dd5cdbb7d..539209fe3468 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)

@@ -115,9 +115,9 @@ struct sun4i_usb_phy_cfg {
int hsic_index;
enum sun4i_usb_phy_type type;
u32 disc_thresh;
+ u32 hci_phy_ctl_siddq;
u8 phyctl_offset;
bool dedicated_clocks;
- bool enable_pmu_unk1;
bool phy0_dual_route;
int missing_phys;
};
@@ -288,6 +288,12 @@ static int sun4i_usb_phy_init(struct phy *_phy)
return ret;
}

+ if (phy->pmu && data->cfg->hci_phy_ctl_siddq) {
+ val = readl(phy->pmu + REG_HCI_PHY_CTL);
+ val &= ~data->cfg->hci_phy_ctl_siddq;
+ 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 +303,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 +864,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 +872,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 +880,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 +888,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 +896,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 +904,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 +920,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_siddq = BIT(1),
.phy0_dual_route = true,
};

@@ -935,7 +930,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_siddq = BIT(1),
.phy0_dual_route = true,
};

@@ -945,7 +940,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_siddq = BIT(1),
.phy0_dual_route = true,
};

@@ -955,7 +950,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_siddq = BIT(1),
.phy0_dual_route = true,
};

--
2.17.5

Andre Przywara

unread,
Jan 17, 2021, 9:10:01 PM1/17/21
to Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Icenowy Zheng, Linus Walleij, Rob Herring, Clément Péron, Samuel Holland, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Kishon Vijay Abraham I, Vinod Koul, devic...@vger.kernel.org
The H616 has four PHYs as the H3, along with their respective clock
gates and resets, so the property description is identical.

However the PHYs itself need some special bits, so we need a new
compatible string for it.

Signed-off-by: Andre Przywara <andre.p...@arm.com>
---
.../devicetree/bindings/phy/allwinner,sun8i-h3-usb-phy.yaml | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/phy/allwinner,sun8i-h3-usb-phy.yaml b/Documentation/devicetree/bindings/phy/allwinner,sun8i-h3-usb-phy.yaml
index 60c344585276..f6f2dcb6dc1e 100644
--- a/Documentation/devicetree/bindings/phy/allwinner,sun8i-h3-usb-phy.yaml
+++ b/Documentation/devicetree/bindings/phy/allwinner,sun8i-h3-usb-phy.yaml
@@ -15,7 +15,9 @@ properties:
const: 1

compatible:
- const: allwinner,sun8i-h3-usb-phy
+ oneOf:
+ - const: allwinner,sun8i-h3-usb-phy
+ - const: allwinner,sun50i-h616-usb-phy

reg:
items:
--
2.17.5

Andre Przywara

unread,
Jan 17, 2021, 9:10:06 PM1/17/21
to Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Icenowy Zheng, Linus Walleij, Rob Herring, Clément Péron, Samuel Holland, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Kishon Vijay Abraham I, Vinod Koul, Greg Kroah-Hartman, devic...@vger.kernel.org
The H616 MUSB peripheral is presumably compatible to the H3 one.

Signed-off-by: Andre Przywara <andre.p...@arm.com>
---
.../devicetree/bindings/usb/allwinner,sun4i-a10-musb.yaml | 3 +++
1 file changed, 3 insertions(+)

diff --git a/Documentation/devicetree/bindings/usb/allwinner,sun4i-a10-musb.yaml b/Documentation/devicetree/bindings/usb/allwinner,sun4i-a10-musb.yaml
index d9207bf9d894..ad8983debeba 100644
--- a/Documentation/devicetree/bindings/usb/allwinner,sun4i-a10-musb.yaml
+++ b/Documentation/devicetree/bindings/usb/allwinner,sun4i-a10-musb.yaml
@@ -22,6 +22,9 @@ properties:
- allwinner,sun8i-a83t-musb
- allwinner,sun50i-h6-musb
- const: allwinner,sun8i-a33-musb
+ - items:
+ - const: allwinner,sun50i-h616-musb
+ - const: allwinner,sun8i-h3-musb

Andre Przywara

unread,
Jan 17, 2021, 9:10:06 PM1/17/21
to Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Icenowy Zheng, Linus Walleij, Rob Herring, Clément Péron, Samuel Holland, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Kishon Vijay Abraham I, Vinod Koul
The USB PHY used in the Allwinner H616 SoC inherits some traits from its
various predecessors: it has four full PHYs like the H3, needs some
extra bits to be set like the H6, and clears a different bit in the
PMU_UNK1 register like the A100.

Name all those properties in a new config struct and assign a new
compatible name to it.

Signed-off-by: Andre Przywara <andre.p...@arm.com>
---
drivers/phy/allwinner/phy-sun4i-usb.c | 11 +++++++++++
1 file changed, 11 insertions(+)

diff --git a/drivers/phy/allwinner/phy-sun4i-usb.c b/drivers/phy/allwinner/phy-sun4i-usb.c
index 539209fe3468..e71d6b8ccf16 100644
--- a/drivers/phy/allwinner/phy-sun4i-usb.c
+++ b/drivers/phy/allwinner/phy-sun4i-usb.c
@@ -964,6 +964,16 @@ static const struct sun4i_usb_phy_cfg sun50i_h6_cfg = {
.missing_phys = BIT(1) | BIT(2),
};

+static const struct sun4i_usb_phy_cfg sun50i_h616_cfg = {
+ .num_phys = 4,
+ .type = sun50i_h6_phy,
+ .disc_thresh = 3,
+ .phyctl_offset = REG_PHYCTL_A33,
+ .dedicated_clocks = true,
+ .phy0_dual_route = true,
+ .hci_phy_ctl_siddq = BIT(3),
+};
+
static const struct of_device_id sun4i_usb_phy_of_match[] = {
{ .compatible = "allwinner,sun4i-a10-usb-phy", .data = &sun4i_a10_cfg },
{ .compatible = "allwinner,sun5i-a13-usb-phy", .data = &sun5i_a13_cfg },
@@ -978,6 +988,7 @@ static const struct of_device_id sun4i_usb_phy_of_match[] = {
{ .compatible = "allwinner,sun50i-a64-usb-phy",
.data = &sun50i_a64_cfg},
{ .compatible = "allwinner,sun50i-h6-usb-phy", .data = &sun50i_h6_cfg },
+ { .compatible = "allwinner,sun50i-h616-usb-phy", .data = &sun50i_h616_cfg },
{ },
};
MODULE_DEVICE_TABLE(of, sun4i_usb_phy_of_match);
--
2.17.5

Andre Przywara

unread,
Jan 17, 2021, 9:10:10 PM1/17/21
to Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Icenowy Zheng, Linus Walleij, Rob Herring, Clément Péron, Samuel Holland, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Guenter Roeck, Wim Van Sebroeck, devic...@vger.kernel.org, linux-w...@vger.kernel.org
Use enums to group all compatible devices together on the way.

Signed-off-by: Andre Przywara <andre.p...@arm.com>
Acked-by: Rob Herring <ro...@kernel.org>
---
.../bindings/watchdog/allwinner,sun4i-a10-wdt.yaml | 12 +++++-------
1 file changed, 5 insertions(+), 7 deletions(-)

diff --git a/Documentation/devicetree/bindings/watchdog/allwinner,sun4i-a10-wdt.yaml b/Documentation/devicetree/bindings/watchdog/allwinner,sun4i-a10-wdt.yaml
index 5ac607de8be4..9aa3c313c49f 100644
--- a/Documentation/devicetree/bindings/watchdog/allwinner,sun4i-a10-wdt.yaml
+++ b/Documentation/devicetree/bindings/watchdog/allwinner,sun4i-a10-wdt.yaml
@@ -19,13 +19,11 @@ properties:
- const: allwinner,sun4i-a10-wdt
- const: allwinner,sun6i-a31-wdt
- items:
- - const: allwinner,sun50i-a64-wdt
- - const: allwinner,sun6i-a31-wdt
- - items:
- - const: allwinner,sun50i-a100-wdt
- - const: allwinner,sun6i-a31-wdt
- - items:
- - const: allwinner,sun50i-h6-wdt
+ - enum:
+ - allwinner,sun50i-a64-wdt
+ - allwinner,sun50i-a100-wdt
+ - allwinner,sun50i-h6-wdt
+ - allwinner,sun50i-h616-wdt
- const: allwinner,sun6i-a31-wdt
- items:
- const: allwinner,suniv-f1c100s-wdt
--
2.17.5

Andre Przywara

unread,
Jan 17, 2021, 9:10:14 PM1/17/21
to Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Icenowy Zheng, Linus Walleij, Rob Herring, Clément Péron, Samuel Holland, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Alessandro Zummo, Alexandre Belloni, Gregory CLEMENT, Mark Brown, Mauro Carvalho Chehab, devic...@vger.kernel.org, linu...@vger.kernel.org, linux...@vger.kernel.org, linu...@vger.kernel.org, linu...@vger.kernel.org
Add simple "allwinner,sun50i-h616-xxx" compatible names to existing
bindings, and pair them with an existing fallback compatible string,
as the devices are compatible.
This covers I2C, infrared, RTC and SPI.

Use enums to group all compatible devices together.

Signed-off-by: Andre Przywara <andre.p...@arm.com>
Acked-by: Rob Herring <ro...@kernel.org>
Acked-by: Wolfram Sang <w...@kernel.org> # for I2C
---
.../bindings/i2c/marvell,mv64xxx-i2c.yaml | 21 +++++++------------
.../media/allwinner,sun4i-a10-ir.yaml | 16 ++++++--------
.../bindings/rtc/allwinner,sun6i-a31-rtc.yaml | 3 +++
.../bindings/spi/allwinner,sun6i-a31-spi.yaml | 1 +
4 files changed, 17 insertions(+), 24 deletions(-)

diff --git a/Documentation/devicetree/bindings/i2c/marvell,mv64xxx-i2c.yaml b/Documentation/devicetree/bindings/i2c/marvell,mv64xxx-i2c.yaml
index 5b5ae402f97a..eb72dd571def 100644
--- a/Documentation/devicetree/bindings/i2c/marvell,mv64xxx-i2c.yaml
+++ b/Documentation/devicetree/bindings/i2c/marvell,mv64xxx-i2c.yaml
@@ -18,21 +18,14 @@ properties:
- const: allwinner,sun4i-a10-i2c
- const: allwinner,sun6i-a31-i2c
- items:
- - const: allwinner,sun8i-a23-i2c
+ - enum:
+ - allwinner,sun8i-a23-i2c
+ - allwinner,sun8i-a83t-i2c
+ - allwinner,sun50i-a64-i2c
+ - allwinner,sun50i-a100-i2c
+ - allwinner,sun50i-h6-i2c
+ - allwinner,sun50i-h616-i2c
- const: allwinner,sun6i-a31-i2c
- - items:
- - const: allwinner,sun8i-a83t-i2c
- - const: allwinner,sun6i-a31-i2c
- - items:
- - const: allwinner,sun50i-a64-i2c
- - const: allwinner,sun6i-a31-i2c
- - items:
- - const: allwinner,sun50i-a100-i2c
- - const: allwinner,sun6i-a31-i2c
- - items:
- - const: allwinner,sun50i-h6-i2c
- - const: allwinner,sun6i-a31-i2c
-
- const: marvell,mv64xxx-i2c
- const: marvell,mv78230-i2c
- const: marvell,mv78230-a0-i2c
diff --git a/Documentation/devicetree/bindings/media/allwinner,sun4i-a10-ir.yaml b/Documentation/devicetree/bindings/media/allwinner,sun4i-a10-ir.yaml
index 5fa19d4aeaf3..6d8395d6bca0 100644
--- a/Documentation/devicetree/bindings/media/allwinner,sun4i-a10-ir.yaml
+++ b/Documentation/devicetree/bindings/media/allwinner,sun4i-a10-ir.yaml
@@ -20,16 +20,12 @@ properties:
- const: allwinner,sun5i-a13-ir
- const: allwinner,sun6i-a31-ir
- items:
- - const: allwinner,sun8i-a83t-ir
- - const: allwinner,sun6i-a31-ir
- - items:
- - const: allwinner,sun8i-r40-ir
- - const: allwinner,sun6i-a31-ir
- - items:
- - const: allwinner,sun50i-a64-ir
- - const: allwinner,sun6i-a31-ir
- - items:
- - const: allwinner,sun50i-h6-ir
+ - enum:
+ - allwinner,sun8i-a83t-ir
+ - allwinner,sun8i-r40-ir
+ - allwinner,sun50i-a64-ir
+ - allwinner,sun50i-h6-ir
+ - allwinner,sun50i-h616-ir
- const: allwinner,sun6i-a31-ir

reg:
diff --git a/Documentation/devicetree/bindings/rtc/allwinner,sun6i-a31-rtc.yaml b/Documentation/devicetree/bindings/rtc/allwinner,sun6i-a31-rtc.yaml
index 37c2a601c3fa..97928efd2bc9 100644
--- a/Documentation/devicetree/bindings/rtc/allwinner,sun6i-a31-rtc.yaml
+++ b/Documentation/devicetree/bindings/rtc/allwinner,sun6i-a31-rtc.yaml
@@ -26,6 +26,9 @@ properties:
- const: allwinner,sun50i-a64-rtc
- const: allwinner,sun8i-h3-rtc
- const: allwinner,sun50i-h6-rtc
+ - items:
+ - const: allwinner,sun50i-h616-rtc
+ - const: allwinner,sun50i-h6-rtc

reg:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/spi/allwinner,sun6i-a31-spi.yaml b/Documentation/devicetree/bindings/spi/allwinner,sun6i-a31-spi.yaml
index 7866a655d81c..908248260afa 100644
--- a/Documentation/devicetree/bindings/spi/allwinner,sun6i-a31-spi.yaml
+++ b/Documentation/devicetree/bindings/spi/allwinner,sun6i-a31-spi.yaml
@@ -25,6 +25,7 @@ properties:
- enum:
- allwinner,sun8i-r40-spi
- allwinner,sun50i-h6-spi
+ - allwinner,sun50i-h616-spi
- const: allwinner,sun8i-h3-spi

reg:
--
2.17.5

Andre Przywara

unread,
Jan 17, 2021, 9:10:14 PM1/17/21
to Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Icenowy Zheng, Linus Walleij, Rob Herring, Clément Péron, Samuel Holland, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, devic...@vger.kernel.org
This (relatively) new SoC is similar to the H6, but drops the (broken)
PCIe support and the USB 3.0 controller. It also gets the management
controller removed, which in turn removes *some*, but not all of the
devices formerly dedicated to the ARISC (CPUS).
There does not seem to be an extra interrupt controller anymore, also
it lacks the corresponding NMI pin, so no interrupts for the PMIC.

Signed-off-by: Andre Przywara <andre.p...@arm.com>
---
.../arm64/boot/dts/allwinner/sun50i-h616.dtsi | 750 ++++++++++++++++++
1 file changed, 750 insertions(+)
create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi

diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi
new file mode 100644
index 000000000000..953e8fac20f0
--- /dev/null
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi
@@ -0,0 +1,750 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+// Copyright (C) 2020 Arm Ltd.
+// based on the H6 dtsi, which is:
+// Copyright (C) 2017 Icenowy Zheng <ice...@aosc.io>
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/clock/sun50i-h616-ccu.h>
+#include <dt-bindings/clock/sun50i-h6-r-ccu.h>
+#include <dt-bindings/reset/sun50i-h616-ccu.h>
+#include <dt-bindings/reset/sun50i-h6-r-ccu.h>
+
+/ {
+ interrupt-parent = <&gic>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu0: cpu@0 {
+ compatible = "arm,cortex-a53";
+ device_type = "cpu";
+ reg = <0>;
+ enable-method = "psci";
+ clocks = <&ccu CLK_CPUX>;
+ };
+
+ cpu1: cpu@1 {
+ compatible = "arm,cortex-a53";
+ device_type = "cpu";
+ reg = <1>;
+ enable-method = "psci";
+ clocks = <&ccu CLK_CPUX>;
+ };
+
+ cpu2: cpu@2 {
+ compatible = "arm,cortex-a53";
+ device_type = "cpu";
+ reg = <2>;
+ enable-method = "psci";
+ clocks = <&ccu CLK_CPUX>;
+ };
+
+ cpu3: cpu@3 {
+ compatible = "arm,cortex-a53";
+ device_type = "cpu";
+ reg = <3>;
+ enable-method = "psci";
+ clocks = <&ccu CLK_CPUX>;
+ };
+ };
+
+ reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ /* 512KiB reserved for ARM Trusted Firmware (BL31) */
+ secmon_reserved: secmon@40000000 {
+ reg = <0x0 0x40000000 0x0 0x80000>;
+ no-map;
+ };
+ };
+
+ osc24M: osc24M_clk {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <24000000>;
+ clock-output-names = "osc24M";
+ };
+
+ pmu {
+ compatible = "arm,cortex-a53-pmu";
+ interrupts = <GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 141 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 142 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-affinity = <&cpu0>, <&cpu1>, <&cpu2>, <&cpu3>;
+ };
+
+ psci {
+ compatible = "arm,psci-0.2";
+ method = "smc";
+ };
+
+ timer {
+ compatible = "arm,armv8-timer";
+ arm,no-tick-in-suspend;
+ interrupts = <GIC_PPI 13
+ (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>,
+ <GIC_PPI 14
+ (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>,
+ <GIC_PPI 11
+ (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>,
+ <GIC_PPI 10
+ (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
+ };
+
+ soc {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0x0 0x0 0x0 0x40000000>;
+
+ syscon: syscon@3000000 {
+ compatible = "allwinner,sun50i-h616-system-control";
+ reg = <0x03000000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ sram_c: sram@28000 {
+ compatible = "mmio-sram";
+ reg = <0x00028000 0x30000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 0x00028000 0x30000>;
+ };
+ };
+
+ ccu: clock@3001000 {
+ compatible = "allwinner,sun50i-h616-ccu";
+ reg = <0x03001000 0x1000>;
+ clocks = <&osc24M>, <&rtc 0>, <&rtc 2>;
+ clock-names = "hosc", "losc", "iosc";
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ };
+
+ watchdog: watchdog@30090a0 {
+ compatible = "allwinner,sun50i-h616-wdt",
+ "allwinner,sun6i-a31-wdt";
+ reg = <0x030090a0 0x20>;
+ interrupts = <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&osc24M>;
+ status = "disabled";
+ };
+
+ pio: pinctrl@300b000 {
+ compatible = "allwinner,sun50i-h616-pinctrl";
+ reg = <0x0300b000 0x400>;
+ interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_APB1>, <&osc24M>, <&rtc 0>;
+ clock-names = "apb", "hosc", "losc";
+ gpio-controller;
+ #gpio-cells = <3>;
+ interrupt-controller;
+ #interrupt-cells = <3>;
+
+ ext_rgmii_pins: rgmii-pins {
+ pins = "PI0", "PI1", "PI2", "PI3", "PI4",
+ "PI5", "PI7", "PI8", "PI9", "PI10",
+ "PI11", "PI12", "PI13", "PI14", "PI15",
+ "PI16";
+ function = "emac0";
+ drive-strength = <40>;
+ };
+
+ i2c0_pins: i2c0-pins {
+ pins = "PI6", "PI7";
+ function = "i2c0";
+ };
+
+ i2c3_ph_pins: i2c3-ph-pins {
+ pins = "PH4", "PH5";
+ function = "i2c3";
+ };
+
+ ir_rx_pin: ir_rx_pin {
+ pins = "PH10";
+ function = "ir_rx";
+ };
+
+ mmc0_pins: mmc0-pins {
+ pins = "PF0", "PF1", "PF2", "PF3",
+ "PF4", "PF5";
+ function = "mmc0";
+ drive-strength = <30>;
+ bias-pull-up;
+ };
+
+ mmc1_pins: mmc1-pins {
+ pins = "PG0", "PG1", "PG2", "PG3",
+ "PG4", "PG5";
+ function = "mmc1";
+ drive-strength = <30>;
+ bias-pull-up;
+ };
+
+ mmc2_pins: mmc2-pins {
+ pins = "PC0", "PC1", "PC5", "PC6",
+ "PC8", "PC9", "PC10", "PC11",
+ "PC13", "PC14", "PC15", "PC16";
+ function = "mmc2";
+ drive-strength = <30>;
+ bias-pull-up;
+ };
+
+ spi0_pins: spi0-pins {
+ pins = "PC0", "PC2", "PC3", "PC4";
+ function = "spi0";
+ };
+
+ spi1_pins: spi1-pins {
+ pins = "PH6", "PH7", "PH8";
+ function = "spi1";
+ };
+
+ spi1_cs_pin: spi1-cs-pin {
+ pins = "PH5";
+ function = "spi1";
+ };
+
+ uart0_ph_pins: uart0-ph-pins {
+ pins = "PH0", "PH1";
+ function = "uart0";
+ };
+
+ uart1_pins: uart1-pins {
+ pins = "PG6", "PG7";
+ function = "uart1";
+ };
+
+ uart1_rts_cts_pins: uart1-rts-cts-pins {
+ pins = "PG8", "PG9";
+ function = "uart1";
+ };
+ };
+
+ gic: interrupt-controller@3021000 {
+ compatible = "arm,gic-400";
+ reg = <0x03021000 0x1000>,
+ <0x03022000 0x2000>,
+ <0x03024000 0x2000>,
+ <0x03026000 0x2000>;
+ interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
+ interrupt-controller;
+ #interrupt-cells = <3>;
+ };
+
+ mmc0: mmc@4020000 {
+ compatible = "allwinner,sun50i-h616-mmc",
+ "allwinner,sun50i-a100-mmc";
+ reg = <0x04020000 0x1000>;
+ clocks = <&ccu CLK_BUS_MMC0>, <&ccu CLK_MMC0>;
+ clock-names = "ahb", "mmc";
+ resets = <&ccu RST_BUS_MMC0>;
+ reset-names = "ahb";
+ interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&mmc0_pins>;
+ status = "disabled";
+ cap-sd-highspeed;
+ cap-mmc-highspeed;
+ mmc-ddr-3_3v;
+ mmc-ddr-1_8v;
+ cap-sdio-irq;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ mmc1: mmc@4021000 {
+ compatible = "allwinner,sun50i-h616-mmc",
+ "allwinner,sun50i-a100-mmc";
+ reg = <0x04021000 0x1000>;
+ clocks = <&ccu CLK_BUS_MMC1>, <&ccu CLK_MMC1>;
+ clock-names = "ahb", "mmc";
+ resets = <&ccu RST_BUS_MMC1>;
+ reset-names = "ahb";
+ interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&mmc1_pins>;
+ status = "disabled";
+ cap-sd-highspeed;
+ cap-mmc-highspeed;
+ mmc-ddr-3_3v;
+ mmc-ddr-1_8v;
+ cap-sdio-irq;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ mmc2: mmc@4022000 {
+ compatible = "allwinner,sun50i-h616-emmc",
+ "allwinner,sun50i-a100-emmc";
+ reg = <0x04022000 0x1000>;
+ clocks = <&ccu CLK_BUS_MMC2>, <&ccu CLK_MMC2>;
+ clock-names = "ahb", "mmc";
+ resets = <&ccu RST_BUS_MMC2>;
+ reset-names = "ahb";
+ interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&mmc2_pins>;
+ status = "disabled";
+ cap-sd-highspeed;
+ cap-mmc-highspeed;
+ mmc-ddr-3_3v;
+ mmc-ddr-1_8v;
+ cap-sdio-irq;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ uart0: serial@5000000 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x05000000 0x400>;
+ interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ clocks = <&ccu CLK_BUS_UART0>;
+ resets = <&ccu RST_BUS_UART0>;
+ status = "disabled";
+ };
+
+ uart1: serial@5000400 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x05000400 0x400>;
+ interrupts = <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ clocks = <&ccu CLK_BUS_UART1>;
+ resets = <&ccu RST_BUS_UART1>;
+ status = "disabled";
+ };
+
+ uart2: serial@5000800 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x05000800 0x400>;
+ interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ clocks = <&ccu CLK_BUS_UART2>;
+ resets = <&ccu RST_BUS_UART2>;
+ status = "disabled";
+ };
+
+ uart3: serial@5000c00 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x05000c00 0x400>;
+ interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ clocks = <&ccu CLK_BUS_UART3>;
+ resets = <&ccu RST_BUS_UART3>;
+ status = "disabled";
+ };
+
+ uart4: serial@5001000 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x05001000 0x400>;
+ interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ clocks = <&ccu CLK_BUS_UART4>;
+ resets = <&ccu RST_BUS_UART4>;
+ status = "disabled";
+ };
+
+ uart5: serial@5001400 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x05001400 0x400>;
+ interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ clocks = <&ccu CLK_BUS_UART5>;
+ resets = <&ccu RST_BUS_UART5>;
+ status = "disabled";
+ };
+
+ i2c0: i2c@5002000 {
+ compatible = "allwinner,sun50i-h616-i2c",
+ "allwinner,sun6i-a31-i2c";
+ reg = <0x05002000 0x400>;
+ interrupts = <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_I2C0>;
+ resets = <&ccu RST_BUS_I2C0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c0_pins>;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ i2c1: i2c@5002400 {
+ compatible = "allwinner,sun50i-h616-i2c",
+ "allwinner,sun6i-a31-i2c";
+ reg = <0x05002400 0x400>;
+ interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_I2C1>;
+ resets = <&ccu RST_BUS_I2C1>;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ i2c2: i2c@5002800 {
+ compatible = "allwinner,sun50i-h616-i2c",
+ "allwinner,sun6i-a31-i2c";
+ reg = <0x05002800 0x400>;
+ interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_I2C2>;
+ resets = <&ccu RST_BUS_I2C2>;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ i2c3: i2c@5002c00 {
+ compatible = "allwinner,sun50i-h616-i2c",
+ "allwinner,sun6i-a31-i2c";
+ reg = <0x05002c00 0x400>;
+ interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_I2C3>;
+ resets = <&ccu RST_BUS_I2C3>;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ i2c4: i2c@5003000 {
+ compatible = "allwinner,sun50i-h616-i2c",
+ "allwinner,sun6i-a31-i2c";
+ reg = <0x05003000 0x400>;
+ interrupts = <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_I2C4>;
+ resets = <&ccu RST_BUS_I2C4>;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ spi0: spi@5010000 {
+ compatible = "allwinner,sun50i-h616-spi",
+ "allwinner,sun8i-h3-spi";
+ reg = <0x05010000 0x1000>;
+ interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_SPI0>, <&ccu CLK_SPI0>;
+ clock-names = "ahb", "mod";
+ resets = <&ccu RST_BUS_SPI0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi0_pins>;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ spi1: spi@5011000 {
+ compatible = "allwinner,sun50i-h616-spi",
+ "allwinner,sun8i-h3-spi";
+ reg = <0x05011000 0x1000>;
+ interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_SPI1>, <&ccu CLK_SPI1>;
+ clock-names = "ahb", "mod";
+ resets = <&ccu RST_BUS_SPI1>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi1_pins>;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ emac0: ethernet@5020000 {
+ compatible = "allwinner,sun50i-h616-emac",
+ "allwinner,sun50i-a64-emac";
+ syscon = <&syscon>;
+ reg = <0x05020000 0x10000>;
+ interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "macirq";
+ resets = <&ccu RST_BUS_EMAC0>;
+ reset-names = "stmmaceth";
+ clocks = <&ccu CLK_BUS_EMAC0>;
+ clock-names = "stmmaceth";
+ status = "disabled";
+
+ mdio0: mdio {
+ compatible = "snps,dwmac-mdio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+ };
+
+ emac1: ethernet@5030000 {
+ compatible = "allwinner,sun50i-h616-emac";
+ syscon = <&syscon 1>;
+ reg = <0x05030000 0x10000>;
+ interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "macirq";
+ resets = <&ccu RST_BUS_EMAC1>;
+ reset-names = "stmmaceth";
+ clocks = <&ccu CLK_BUS_EMAC1>;
+ clock-names = "stmmaceth";
+ status = "disabled";
+
+ mdio1: mdio {
+ compatible = "snps,dwmac-mdio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+ };
+
+ 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>;
+ clock-names = "usb0_phy",
+ "usb1_phy",
+ "usb2_phy",
+ "usb3_phy";
+ 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",
+ "allwinner,sun50i-h6-rtc";
+ reg = <0x07000000 0x400>;
+ interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>;
+ clock-output-names = "osc32k", "osc32k-out", "iosc";
+ #clock-cells = <1>;
+ };
+
+ r_ccu: clock@7010000 {
+ compatible = "allwinner,sun50i-h616-r-ccu";
+ reg = <0x07010000 0x400>;
+ clocks = <&osc24M>, <&rtc 0>, <&rtc 2>,
+ <&ccu CLK_PLL_PERIPH0>;
+ clock-names = "hosc", "losc", "iosc", "pll-periph";
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ };
+
+ r_pio: pinctrl@7022000 {
+ compatible = "allwinner,sun50i-h616-r-pinctrl";
+ reg = <0x07022000 0x400>;
+ interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&r_ccu CLK_R_APB1>, <&osc24M>, <&rtc 0>;
+ clock-names = "apb", "hosc", "losc";
+ gpio-controller;
+ #gpio-cells = <3>;
+ interrupt-controller;
+ #interrupt-cells = <3>;
+
+ r_i2c_pins: r-i2c-pins {
+ pins = "PL0", "PL1";
+ function = "s_i2c";
+ };
+
+ r_rsb_pins: r-rsb-pins {
+ pins = "PL0", "PL1";
+ function = "s_rsb";
+ };
+ };
+
+ ir: ir@7040000 {
+ compatible = "allwinner,sun50i-h616-ir",
+ "allwinner,sun6i-a31-ir";
+ reg = <0x07040000 0x400>;
+ interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&r_ccu CLK_R_APB1_IR>,
+ <&r_ccu CLK_IR>;
+ clock-names = "apb", "ir";
+ resets = <&r_ccu RST_R_APB1_IR>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&ir_rx_pin>;
+ status = "disabled";
+ };
+
+ r_i2c: i2c@7081400 {
+ compatible = "allwinner,sun50i-h616-i2c",
+ "allwinner,sun6i-a31-i2c";
+ reg = <0x07081400 0x400>;
+ interrupts = <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&r_ccu CLK_R_APB2_I2C>;
+ resets = <&r_ccu RST_R_APB2_I2C>;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ r_rsb: rsb@7083000 {
+ compatible = "allwinner,sun50i-h616-rsb",
+ "allwinner,sun8i-a23-rsb";
+ reg = <0x07083000 0x400>;
+ interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&r_ccu CLK_R_APB2_RSB>;
+ clock-frequency = <3000000>;
+ resets = <&r_ccu RST_R_APB2_RSB>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&r_rsb_pins>;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+ };
+};
--
2.17.5

Andre Przywara

unread,
Jan 17, 2021, 9:10:17 PM1/17/21
to Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Icenowy Zheng, Linus Walleij, Rob Herring, Clément Péron, Samuel Holland, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, devic...@vger.kernel.org
Signed-off-by: Andre Przywara <andre.p...@arm.com>
Acked-by: Rob Herring <ro...@kernel.org>
---
Documentation/devicetree/bindings/arm/sunxi.yaml | 5 +++++
1 file changed, 5 insertions(+)

diff --git a/Documentation/devicetree/bindings/arm/sunxi.yaml b/Documentation/devicetree/bindings/arm/sunxi.yaml
index 7ea4d9645e93..6a2fa84bb785 100644
--- a/Documentation/devicetree/bindings/arm/sunxi.yaml
+++ b/Documentation/devicetree/bindings/arm/sunxi.yaml
@@ -931,4 +931,9 @@ properties:
- const: xunlong,orangepi-zero-plus2-h3
- const: allwinner,sun8i-h3

+ - description: Xunlong OrangePi Zero 2
+ items:
+ - const: xunlong,orangepi-zero2
+ - const: allwinner,sun50i-h616
+
additionalProperties: true
--
2.17.5

Andre Przywara

unread,
Jan 17, 2021, 9:10:19 PM1/17/21
to Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Icenowy Zheng, Linus Walleij, Rob Herring, Clément Péron, Samuel Holland, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, devic...@vger.kernel.org
The OrangePi Zero 2 is a development board with the new H616 SoC.

It features the usual connectors used on those small boards, and comes
with the AXP305, which seems to be compatible with the AXP805.

For more details see: http://linux-sunxi.org/Xunlong_Orange_Pi_Zero2

Signed-off-by: Andre Przywara <andre.p...@arm.com>
---
arch/arm64/boot/dts/allwinner/Makefile | 1 +
.../allwinner/sun50i-h616-orangepi-zero2.dts | 240 ++++++++++++++++++
2 files changed, 241 insertions(+)
create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-h616-orangepi-zero2.dts

diff --git a/arch/arm64/boot/dts/allwinner/Makefile b/arch/arm64/boot/dts/allwinner/Makefile
index 41ce680e5f8d..9ba4b5d92657 100644
--- a/arch/arm64/boot/dts/allwinner/Makefile
+++ b/arch/arm64/boot/dts/allwinner/Makefile
@@ -36,3 +36,4 @@ dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-orangepi-one-plus.dtb
dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-pine-h64.dtb
dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-pine-h64-model-b.dtb
dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-tanix-tx6.dtb
+dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h616-orangepi-zero2.dtb
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h616-orangepi-zero2.dts b/arch/arm64/boot/dts/allwinner/sun50i-h616-orangepi-zero2.dts
new file mode 100644
index 000000000000..7f49d192fe41
--- /dev/null
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h616-orangepi-zero2.dts
@@ -0,0 +1,240 @@
+// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+/*
+ * Copyright (C) 2020 Arm Ltd.
+ */
+
+/dts-v1/;
+
+#include "sun50i-h616.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/leds/common.h>
+
+/ {
+ model = "OrangePi Zero2";
+ compatible = "xunlong,orangepi-zero2", "allwinner,sun50i-h616";
+
+ aliases {
+ ethernet0 = &emac0;
+ serial0 = &uart0;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ led-0 {
+ function = LED_FUNCTION_POWER;
+ color = <LED_COLOR_ID_RED>;
+ gpios = <&pio 2 12 GPIO_ACTIVE_HIGH>; /* PC12 */
+ default-state = "on";
+ };
+
+ led-1 {
+ function = LED_FUNCTION_STATUS;
+ color = <LED_COLOR_ID_GREEN>;
+ gpios = <&pio 2 13 GPIO_ACTIVE_HIGH>; /* PC13 */
+ };
+ };
+
+ reg_vcc5v: vcc5v {
+ /* board wide 5V supply directly from the USB-C socket */
+ compatible = "regulator-fixed";
+ regulator-name = "vcc-5v";
+ regulator-min-microvolt = <5000000>;
+ 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";
+ };
+};
+
+&ehci0 {
+ status = "okay";
+};
+
+&ehci1 {
+ status = "okay";
+};
+
+/* USB 2 & 3 are on headers only. */
+
+&emac0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&ext_rgmii_pins>;
+ phy-mode = "rgmii";
+ phy-handle = <&ext_rgmii_phy>;
+ phy-supply = <&reg_dcdce>;
+ allwinner,rx-delay-ps = <3100>;
+ allwinner,tx-delay-ps = <700>;
+ status = "okay";
+};
+
+&mdio0 {
+ ext_rgmii_phy: ethernet-phy@1 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <1>;
+ };
+};
+
+&mmc0 {
+ vmmc-supply = <&reg_dcdce>;
+ cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; /* PF6 */
+ bus-width = <4>;
+ status = "okay";
+};
+
+&ohci0 {
+ status = "okay";
+};
+
+&ohci1 {
+ status = "okay";
+};
+
+&r_rsb {
+ status = "okay";
+
+ axp305: pmic@745 {
+ compatible = "x-powers,axp305", "x-powers,axp805",
+ "x-powers,axp806";
+ reg = <0x745>;
+
+ x-powers,self-working-mode;
+ vina-supply = <&reg_vcc5v>;
+ vinb-supply = <&reg_vcc5v>;
+ vinc-supply = <&reg_vcc5v>;
+ vind-supply = <&reg_vcc5v>;
+ vine-supply = <&reg_vcc5v>;
+ aldoin-supply = <&reg_vcc5v>;
+ bldoin-supply = <&reg_vcc5v>;
+ cldoin-supply = <&reg_vcc5v>;
+
+ regulators {
+ reg_aldo1: aldo1 {
+ regulator-always-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-name = "vcc-sys";
+ };
+
+ reg_aldo2: aldo2 { /* 3.3V on headers */
+ regulator-always-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-name = "vcc3v3-ext";
+ };
+
+ reg_aldo3: aldo3 { /* 3.3V on headers */
+ regulator-always-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-name = "vcc3v3-ext2";
+ };
+
+ reg_bldo1: bldo1 {
+ regulator-always-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-name = "vcc1v8";
+ };
+
+ bldo2 {
+ /* unused */
+ };
+
+ bldo3 {
+ /* unused */
+ };
+
+ bldo4 {
+ /* unused */
+ };
+
+ cldo1 {
+ /* reserved */
+ };
+
+ cldo2 {
+ /* unused */
+ };
+
+ cldo3 {
+ /* unused */
+ };
+
+ reg_dcdca: dcdca {
+ regulator-always-on;
+ regulator-min-microvolt = <810000>;
+ regulator-max-microvolt = <1080000>;
+ regulator-name = "vdd-cpu";
+ };
+
+ reg_dcdcc: dcdcc {
+ regulator-always-on;
+ regulator-min-microvolt = <810000>;
+ regulator-max-microvolt = <1080000>;
+ regulator-name = "vdd-gpu-sys";
+ };
+
+ reg_dcdcd: dcdcd {
+ regulator-always-on;
+ regulator-min-microvolt = <1500000>;
+ regulator-max-microvolt = <1500000>;
+ regulator-name = "vdd-dram";
+ };
+
+ reg_dcdce: dcdce {
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-name = "vcc-eth-mmc";
+ };
+
+ sw {
+ /* unused */
+ };
+ };
+ };
+};
+
+&spi0 {
+ status = "okay";
+
+ flash@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "jedec,spi-nor";
+ reg = <0>;
+ spi-max-frequency = <40000000>;
+ };
+};
+
+&uart0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_ph_pins>;
+ status = "okay";
+};
+
+&usbotg {
+ dr_mode = "peripheral";
+ status = "okay";
+};
+
+&usbphy {
+ usb1_vbus-supply = <&reg_usb1_vbus>;
+ status = "okay";
+};
--
2.17.5

Samuel Holland

unread,
Jan 17, 2021, 10:37:27 PM1/17/21
to Andre Przywara, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Icenowy Zheng, Linus Walleij, Rob Herring, Clément Péron, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Lee Jones
On 1/17/21 8:08 PM, Andre Przywara wrote:
> Currently the AXP chip requires to have its IRQ line connected to some
> interrupt controller, and will fail probing when this is not the case.
>
> On a new Allwinner SoC (H616) there is no NMI pin anymore, so the
> interrupt functionality of the AXP chip is simply not available.
>
> Check whether the DT describes the AXP chip as an interrupt controller
> before trying to register the irqchip, to avoid probe failures on
> setups without an interrupt.

The AXP305 has an IRQ pin. It is still an interrupt controller, even if
its output is not connected anywhere. And even though the NMI pin on the
H616 is gone, the PMIC IRQ line could be connected to a GPIO. So it is
not appropriate to remove "interrupt-controller".

Per the binding, both "interrupts" and "interrupt-controller" are
required properties. It would make more sense to make "interrupts"
optional. Either way, you need to update the binding.

Though I'm concerned about how this may affect drivers for regmap cells
which use interrupts (such as axp20x-pek). If the irqchip is not
registered, requesting those interrupts will fail. While I don't
currently know of any boards that have the AXP305 power key wired up, it
prevents us from modelling the hardware correctly and supporting that
configuration.

Cheers,
Samuel

Samuel Holland

unread,
Jan 17, 2021, 11:28:53 PM1/17/21
to Andre Przywara, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Icenowy Zheng, Linus Walleij, Rob Herring, Clément Péron, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Alessandro Zummo, Alexandre Belloni, Gregory CLEMENT, Mark Brown, Mauro Carvalho Chehab, devic...@vger.kernel.org, linu...@vger.kernel.org, linux...@vger.kernel.org, linu...@vger.kernel.org, linu...@vger.kernel.org
On 1/17/21 8:08 PM, Andre Przywara wrote:
Since H6, the RTC manages the 24 MHz DCXO, so it provides a fourth clock
output. If this is easy to change later, then it is fine for now, but
maybe it is better to get the H616 binding correct from the beginning?

Cheers,
Samuel

Samuel Holland

unread,
Jan 17, 2021, 11:36:01 PM1/17/21
to Andre Przywara, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Icenowy Zheng, Linus Walleij, Rob Herring, Clément Péron, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, devic...@vger.kernel.org
On 1/17/21 8:08 PM, Andre Przywara wrote:
Why is this disabled? Is it broken like the H6?

> + };
> +
[...]
> + rtc: rtc@7000000 {
> + compatible = "allwinner,sun50i-h616-rtc",
> + "allwinner,sun50i-h6-rtc";
> + reg = <0x07000000 0x400>;
> + interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>,
> + <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>;
> + clock-output-names = "osc32k", "osc32k-out", "iosc";
> + #clock-cells = <1>;
> + };
> +
> + r_ccu: clock@7010000 {
> + compatible = "allwinner,sun50i-h616-r-ccu";
> + reg = <0x07010000 0x400>;

This range overlaps the NMI controller[1] at 0x07010320, which I
verified does exist. I don't know what it is connected to, since there
is no NMI pin. Maybe the ATE/AC200?

I suggest reducing the size to 0x210, since 0x20c is the highest
clock-gate-related register.

Cheers,
Samuel

[1]
https://github.com/orangepi-xunlong/linux-orangepi/blob/orange-pi-4.9-sun50iw9/arch/arm64/boot/dts/sunxi/sun50iw9p1.dtsi#L358

Mark Brown

unread,
Jan 18, 2021, 7:06:38 AM1/18/21
to Andre Przywara, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Icenowy Zheng, Linus Walleij, Rob Herring, Clément Péron, Samuel Holland, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Alessandro Zummo, Alexandre Belloni, Gregory CLEMENT, Mauro Carvalho Chehab, devic...@vger.kernel.org, linu...@vger.kernel.org, linux...@vger.kernel.org, linu...@vger.kernel.org, linu...@vger.kernel.org
On Mon, Jan 18, 2021 at 02:08:45AM +0000, Andre Przywara wrote:
> Add simple "allwinner,sun50i-h616-xxx" compatible names to existing
> bindings, and pair them with an existing fallback compatible string,
> as the devices are compatible.
> This covers I2C, infrared, RTC and SPI.
>
> Use enums to group all compatible devices together.

Please submit normal, per subsystem patches for things like this.
signature.asc

Maxime Ripard

unread,
Jan 18, 2021, 8:29:01 AM1/18/21
to Andre Przywara, Chen-Yu Tsai, Jernej Skrabec, Icenowy Zheng, Linus Walleij, Rob Herring, Clément Péron, Samuel Holland, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com
Hi,

On Mon, Jan 18, 2021 at 02:08:29AM +0000, Andre Przywara wrote:
> From: Yangtao Li <fr...@allwinnertech.com>
>
> This patch adds support for A100 MMC controller, which use word address
> for internal dma.
>
> Signed-off-by: Yangtao Li <fr...@allwinnertech.com>
> Signed-off-by: Andre Przywara <andre.p...@arm.com>

We should also disable the timings setup in probe to derive them from
the DT. This is causing issues on some SoCs already, so it would be best
to not make the situation worse

Maxime
signature.asc

Maxime Ripard

unread,
Jan 18, 2021, 8:29:27 AM1/18/21
to Andre Przywara, Chen-Yu Tsai, Jernej Skrabec, Icenowy Zheng, Linus Walleij, Rob Herring, Clément Péron, Samuel Holland, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, linux...@vger.kernel.org, devic...@vger.kernel.org
On Mon, Jan 18, 2021 at 02:08:30AM +0000, Andre Przywara wrote:
> A new SoC, a new compatible string.
> Also we were too miserly with just allowing seven interrupt banks.
>
> Signed-off-by: Andre Przywara <andre.p...@arm.com>

Acked-by: Maxime Ripard <mri...@kernel.org>

Maxime
signature.asc

Maxime Ripard

unread,
Jan 18, 2021, 10:26:08 AM1/18/21
to Andre Przywara, Chen-Yu Tsai, Jernej Skrabec, Icenowy Zheng, Linus Walleij, Rob Herring, Clément Péron, Samuel Holland, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, linux...@vger.kernel.org
On Mon, Jan 18, 2021 at 02:08:31AM +0000, Andre Przywara wrote:
> Port A is used for an internal connection to some analogue circuitry
> which looks like an AC200 IP (as in the H6), though this is not
> mentioned in the manual.
>
> Signed-off-by: Andre Przywara <andre.p...@arm.com>

Acked-by: Maxime Ripard <mri...@kernel.org>

Thanks!
Maxime
signature.asc

Maxime Ripard

unread,
Jan 18, 2021, 10:26:50 AM1/18/21
to Andre Przywara, Chen-Yu Tsai, Jernej Skrabec, Icenowy Zheng, Linus Walleij, Rob Herring, Clément Péron, Samuel Holland, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Stephen Boyd, Michael Turquette, linu...@vger.kernel.org, devic...@vger.kernel.org
On Mon, Jan 18, 2021 at 02:08:33AM +0000, Andre Przywara wrote:
> Signed-off-by: Andre Przywara <andre.p...@arm.com>
> Acked-by: Rob Herring <ro...@kernel.org>

signature.asc

Maxime Ripard

unread,
Jan 18, 2021, 10:30:19 AM1/18/21
to Andre Przywara, Chen-Yu Tsai, Jernej Skrabec, Icenowy Zheng, Linus Walleij, Rob Herring, Clément Péron, Samuel Holland, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Stephen Boyd, Michael Turquette, linu...@vger.kernel.org, Philipp Zabel
On Mon, Jan 18, 2021 at 02:08:34AM +0000, Andre Przywara wrote:
> The clocks itself are identical to the H6 R-CCU, it's just that the H616
> has not all of them implemented (or connected).
>
> Signed-off-by: Andre Przywara <andre.p...@arm.com>

signature.asc

Maxime Ripard

unread,
Jan 18, 2021, 10:31:03 AM1/18/21
to Andre Przywara, Chen-Yu Tsai, Jernej Skrabec, Icenowy Zheng, Linus Walleij, Rob Herring, Clément Péron, Samuel Holland, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Stephen Boyd, Michael Turquette, linu...@vger.kernel.org, Philipp Zabel
On Mon, Jan 18, 2021 at 02:08:35AM +0000, Andre Przywara wrote:
> While the clocks are fairly similar to the H6, many differ in tiny
> details, so a separate clock driver seems indicated.
>
> Derived from the H6 clock driver, and adjusted according to the manual.
>
> Signed-off-by: Andre Przywara <andre.p...@arm.com>

signature.asc

Maxime Ripard

unread,
Jan 18, 2021, 10:32:31 AM1/18/21
to Andre Przywara, Chen-Yu Tsai, Jernej Skrabec, Icenowy Zheng, Linus Walleij, Rob Herring, Clément Péron, Samuel Holland, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Kishon Vijay Abraham I, Vinod Koul
On Mon, Jan 18, 2021 at 02:08:40AM +0000, 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, to cover newer SoCs: The A100 and H616 use a different
> bit for the SIDDQ control.
>
> Signed-off-by: Andre Przywara <andre.p...@arm.com>

Acked-by: Maxime Ripard <mri...@kernel.org>

maxime
signature.asc

Maxime Ripard

unread,
Jan 18, 2021, 10:33:30 AM1/18/21
to Andre Przywara, Chen-Yu Tsai, Jernej Skrabec, Icenowy Zheng, Linus Walleij, Rob Herring, Clément Péron, Samuel Holland, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Kishon Vijay Abraham I, Vinod Koul, devic...@vger.kernel.org
While equivalent, enums produce errors that are easier to read. It would
be better to switch to one here

Maxime
signature.asc

Maxime Ripard

unread,
Jan 18, 2021, 10:33:50 AM1/18/21
to Andre Przywara, Chen-Yu Tsai, Jernej Skrabec, Icenowy Zheng, Linus Walleij, Rob Herring, Clément Péron, Samuel Holland, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Kishon Vijay Abraham I, Vinod Koul, Greg Kroah-Hartman, devic...@vger.kernel.org
On Mon, Jan 18, 2021 at 02:08:42AM +0000, Andre Przywara wrote:
> The H616 MUSB peripheral is presumably compatible to the H3 one.
>
> Signed-off-by: Andre Przywara <andre.p...@arm.com>

signature.asc

Maxime Ripard

unread,
Jan 18, 2021, 10:34:02 AM1/18/21
to Andre Przywara, Chen-Yu Tsai, Jernej Skrabec, Icenowy Zheng, Linus Walleij, Rob Herring, Clément Péron, Samuel Holland, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Kishon Vijay Abraham I, Vinod Koul
On Mon, Jan 18, 2021 at 02:08:43AM +0000, Andre Przywara wrote:
> The USB PHY used in the Allwinner H616 SoC inherits some traits from its
> various predecessors: it has four full PHYs like the H3, needs some
> extra bits to be set like the H6, and clears a different bit in the
> PMU_UNK1 register like the A100.
>
> Name all those properties in a new config struct and assign a new
> compatible name to it.
>
> Signed-off-by: Andre Przywara <andre.p...@arm.com>

signature.asc

max...@cerno.tech

unread,
Jan 18, 2021, 10:34:21 AM1/18/21
to Andre Przywara, Chen-Yu Tsai, Jernej Skrabec, Icenowy Zheng, Linus Walleij, Rob Herring, Clément Péron, Samuel Holland, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Guenter Roeck, Wim Van Sebroeck, devic...@vger.kernel.org, linux-w...@vger.kernel.org
On Mon, Jan 18, 2021 at 02:08:44AM +0000, Andre Przywara wrote:
> Use enums to group all compatible devices together on the way.
>
> Signed-off-by: Andre Przywara <andre.p...@arm.com>
> Acked-by: Rob Herring <ro...@kernel.org>

signature.asc

Andre Przywara

unread,
Jan 18, 2021, 10:53:30 AM1/18/21
to Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Icenowy Zheng, Linus Walleij, Rob Herring, Clément Péron, Samuel Holland, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Ulf Hansson
On Mon, 18 Jan 2021 14:28:54 +0100
Maxime Ripard <max...@cerno.tech> wrote:

Hi Maxime,
But only for those new SoCs, where we have the speed modes in the DT
in every case (so only new ones)? And this disabling would be
SoC/compatible string dependent? Happy to send a patch later if that is
what you were thinking about.

Also I was wondering about the voltage dependent speed modes: At the
moment the driver declares both MMC_CAP_1_8V_DDR and MMC_CAP_3_3V_DDR,
so I mimic this in the .dtsi. However in the eventual DTB this looks
somewhat dodgy, since most boards only support one of those voltages. Do
we ignore this, and rely on the vqmmc-supply to limit this choice?

Cheers,
Andre

Btw: This patch is already in Ulf's -next tree, I just included it here
for the sake of completeness. Is that a problem? I don't think it
affects the build, so we don't care too much?

Chen-Yu Tsai

unread,
Jan 18, 2021, 10:55:45 AM1/18/21
to André Przywara, Maxime Ripard, Jernej Skrabec, Icenowy Zheng, Linus Walleij, Rob Herring, Clément Péron, Samuel Holland, Shuosheng Huang, Yangtao Li, linux-arm-kernel, linux-kernel, linux-sunxi, Ulf Hansson
On Mon, Jan 18, 2021 at 11:53 PM Andre Przywara <andre.p...@arm.com> wrote:
>
> On Mon, 18 Jan 2021 14:28:54 +0100
> Maxime Ripard <max...@cerno.tech> wrote:
>
> Hi Maxime,
>
> > On Mon, Jan 18, 2021 at 02:08:29AM +0000, Andre Przywara wrote:
> > > From: Yangtao Li <fr...@allwinnertech.com>
> > >
> > > This patch adds support for A100 MMC controller, which use word
> > > address for internal dma.
> > >
> > > Signed-off-by: Yangtao Li <fr...@allwinnertech.com>
> > > Signed-off-by: Andre Przywara <andre.p...@arm.com>
> >
> > We should also disable the timings setup in probe to derive them from
> > the DT. This is causing issues on some SoCs already, so it would be
> > best to not make the situation worse
>
> But only for those new SoCs, where we have the speed modes in the DT
> in every case (so only new ones)? And this disabling would be
> SoC/compatible string dependent? Happy to send a patch later if that is
> what you were thinking about.
>
> Also I was wondering about the voltage dependent speed modes: At the
> moment the driver declares both MMC_CAP_1_8V_DDR and MMC_CAP_3_3V_DDR,
> so I mimic this in the .dtsi. However in the eventual DTB this looks
> somewhat dodgy, since most boards only support one of those voltages. Do
> we ignore this, and rely on the vqmmc-supply to limit this choice?

IIRC the DDR flags for separate voltages was added after we (I) added
MMC DDR support to our driver.

And yes, the core also checks vqmmc-supply before actually selecting
the mode.

ChenYu

> Cheers,
> Andre
>
> Btw: This patch is already in Ulf's -next tree, I just included it here
> for the sake of completeness. Is that a problem? I don't think it
> affects the build, so we don't care too much?
>
> --
> You received this message because you are subscribed to the Google Groups "linux-sunxi" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to linux-sunxi...@googlegroups.com.
> To view this discussion on the web, visit https://groups.google.com/d/msgid/linux-sunxi/20210118155228.3bd0e909%40slackpad.fritz.box.

Andre Przywara

unread,
Jan 21, 2021, 10:55:19 AM1/21/21
to Samuel Holland, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Icenowy Zheng, Linus Walleij, Rob Herring, Clément Péron, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Lee Jones
On Sun, 17 Jan 2021 21:37:22 -0600
Samuel Holland <sam...@sholland.org> wrote:

Hi Samuel,

thanks for your input!

> On 1/17/21 8:08 PM, Andre Przywara wrote:
> > Currently the AXP chip requires to have its IRQ line connected to some
> > interrupt controller, and will fail probing when this is not the case.
> >
> > On a new Allwinner SoC (H616) there is no NMI pin anymore, so the
> > interrupt functionality of the AXP chip is simply not available.
> >
> > Check whether the DT describes the AXP chip as an interrupt controller
> > before trying to register the irqchip, to avoid probe failures on
> > setups without an interrupt.
>
> The AXP305 has an IRQ pin. It is still an interrupt controller, even if
> its output is not connected anywhere. And even though the NMI pin on the
> H616 is gone, the PMIC IRQ line could be connected to a GPIO. So it is
> not appropriate to remove "interrupt-controller".

That's a fair point.

> Per the binding, both "interrupts" and "interrupt-controller" are
> required properties. It would make more sense to make "interrupts"
> optional. Either way, you need to update the binding.

I agree.

So I will replace the explicit check for the interrupt-controller
property with a check for axp20x->irq being not 0 (which is apparently
the right check for this, according to my research).

And also adjust the binding to make "interrupts" optional.

> Though I'm concerned about how this may affect drivers for regmap cells
> which use interrupts (such as axp20x-pek). If the irqchip is not
> registered, requesting those interrupts will fail. While I don't
> currently know of any boards that have the AXP305 power key wired up, it
> prevents us from modelling the hardware correctly and supporting that
> configuration.

Good point! Indeed axp20x_pek_probe() crashes with a NULL pointer
dereference. I think this device is unconditionally tied to the AXP
drivers, and this is probably fine, as it looks trivial to check the
regmap_irqc pointer before passing it on to regmap_irq_get_virq(),
bailing out if this is NULL.

Will send the patch shortly, then update this patch here as well.

And I guess the outcome (power button input device not available) is
reasonable as well. The hardware power button feature (off after 6s)
would work nevertheless. If board vendors expect more functionality
from the button, they should connect the AXP IRQ pin to a GPIO.

Cheers,
Andre

Maxime Ripard

unread,
Jan 21, 2021, 11:38:36 AM1/21/21
to Andre Przywara, Chen-Yu Tsai, Jernej Skrabec, Icenowy Zheng, Linus Walleij, Rob Herring, Clément Péron, Samuel Holland, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Ulf Hansson
Hi Andre,

On Mon, Jan 18, 2021 at 03:52:28PM +0000, Andre Przywara wrote:
> On Mon, 18 Jan 2021 14:28:54 +0100
> Maxime Ripard <max...@cerno.tech> wrote:
>
> Hi Maxime,
>
> > On Mon, Jan 18, 2021 at 02:08:29AM +0000, Andre Przywara wrote:
> > > From: Yangtao Li <fr...@allwinnertech.com>
> > >
> > > This patch adds support for A100 MMC controller, which use word
> > > address for internal dma.
> > >
> > > Signed-off-by: Yangtao Li <fr...@allwinnertech.com>
> > > Signed-off-by: Andre Przywara <andre.p...@arm.com>
> >
> > We should also disable the timings setup in probe to derive them from
> > the DT. This is causing issues on some SoCs already, so it would be
> > best to not make the situation worse
>
> But only for those new SoCs, where we have the speed modes in the DT
> in every case (so only new ones)? And this disabling would be
> SoC/compatible string dependent? Happy to send a patch later if that is
> what you were thinking about.

Yeah, we should only do it for new SoCs at the moment, based on the
compatible.

I guess at some point we'll have to remove it for the older SoCs as well
since we have reports of it failing for SoCs as old as the A20, but
we'll probably want to make it as smooth as possible.

Maxime
signature.asc

Linus Walleij

unread,
Jan 21, 2021, 4:13:04 PM1/21/21
to Andre Przywara, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Icenowy Zheng, Rob Herring, Clément Péron, Samuel Holland, Shuosheng Huang, Yangtao Li, Linux ARM, linux-...@vger.kernel.org, linux-sunxi, open list:GPIO SUBSYSTEM, open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS
On Mon, Jan 18, 2021 at 3:09 AM Andre Przywara <andre.p...@arm.com> wrote:

> A new SoC, a new compatible string.
> Also we were too miserly with just allowing seven interrupt banks.
>
> Signed-off-by: Andre Przywara <andre.p...@arm.com>

Patch applied to the pinctrl tree.

Yours,
Linus Walleij

Linus Walleij

unread,
Jan 21, 2021, 4:15:08 PM1/21/21
to Andre Przywara, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Icenowy Zheng, Rob Herring, Clément Péron, Samuel Holland, Shuosheng Huang, Yangtao Li, Linux ARM, linux-...@vger.kernel.org, linux-sunxi, open list:GPIO SUBSYSTEM
On Mon, Jan 18, 2021 at 3:09 AM Andre Przywara <andre.p...@arm.com> wrote:

> Port A is used for an internal connection to some analogue circuitry
> which looks like an AC200 IP (as in the H6), though this is not
> mentioned in the manual.
>

Linus Walleij

unread,
Jan 21, 2021, 4:16:21 PM1/21/21
to Andre Przywara, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Icenowy Zheng, Rob Herring, Clément Péron, Samuel Holland, Shuosheng Huang, Yangtao Li, Linux ARM, linux-...@vger.kernel.org, linux-sunxi, open list:GPIO SUBSYSTEM
On Mon, Jan 18, 2021 at 3:09 AM Andre Przywara <andre.p...@arm.com> wrote:

> There are only two pins left now, used to connect to the PMIC via I2C.
>
> Signed-off-by: Andre Przywara <andre.p...@arm.com>
> Acked-by: Maxime Ripard <mri...@kernel.org>
> Reviewed-by: Jernej Skrabec <jernej....@siol.net>

Guenter Roeck

unread,
Jan 23, 2021, 12:31:52 PM1/23/21
to Andre Przywara, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Icenowy Zheng, Linus Walleij, Rob Herring, Clément Péron, Samuel Holland, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Wim Van Sebroeck, devic...@vger.kernel.org, linux-w...@vger.kernel.org
On Mon, Jan 18, 2021 at 02:08:44AM +0000, Andre Przywara wrote:
> Use enums to group all compatible devices together on the way.
>
> Signed-off-by: Andre Przywara <andre.p...@arm.com>
> Acked-by: Rob Herring <ro...@kernel.org>
> Acked-by: Maxime Ripard <mri...@kernel.org>

Reviewed-by: Guenter Roeck <li...@roeck-us.net>

> ---
> .../bindings/watchdog/allwinner,sun4i-a10-wdt.yaml | 12 +++++-------
> 1 file changed, 5 insertions(+), 7 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/watchdog/allwinner,sun4i-a10-wdt.yaml b/Documentation/devicetree/bindings/watchdog/allwinner,sun4i-a10-wdt.yaml
> index 5ac607de8be4..9aa3c313c49f 100644
> --- a/Documentation/devicetree/bindings/watchdog/allwinner,sun4i-a10-wdt.yaml
> +++ b/Documentation/devicetree/bindings/watchdog/allwinner,sun4i-a10-wdt.yaml
> @@ -19,13 +19,11 @@ properties:
> - const: allwinner,sun4i-a10-wdt
> - const: allwinner,sun6i-a31-wdt
> - items:
> - - const: allwinner,sun50i-a64-wdt
> - - const: allwinner,sun6i-a31-wdt
> - - items:
> - - const: allwinner,sun50i-a100-wdt
> - - const: allwinner,sun6i-a31-wdt
> - - items:
> - - const: allwinner,sun50i-h6-wdt
> + - enum:
> + - allwinner,sun50i-a64-wdt
> + - allwinner,sun50i-a100-wdt
> + - allwinner,sun50i-h6-wdt
> + - allwinner,sun50i-h616-wdt
> - const: allwinner,sun6i-a31-wdt
> - items:
> - const: allwinner,suniv-f1c100s-wdt

Andre Przywara

unread,
Jan 25, 2021, 7:00:32 AM1/25/21
to Samuel Holland, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Icenowy Zheng, Linus Walleij, Rob Herring, Clément Péron, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Alessandro Zummo, Alexandre Belloni, Gregory CLEMENT, Mark Brown, Mauro Carvalho Chehab, devic...@vger.kernel.org, linu...@vger.kernel.org, linux...@vger.kernel.org, linu...@vger.kernel.org, linu...@vger.kernel.org
On Sun, 17 Jan 2021 22:28:47 -0600
Samuel Holland <sam...@sholland.org> wrote:

Hi,
So you mean that RTC register +0x160 controls the system HOSC clock,
so the main input clock for all the PLLs and other clocks? And by
clearing bit 1 in there we can stop this?

And if that is the case, do you suggest that we should model this in
the DT, so that the fixed-clock "<&osc24M>" should be replaced with
"<&rtc 3>"?

So from a "the DT describes the hardware" point of view that would
probably the right way, but not sure if Linux is happy about that. At
the very least that would mean to extend the RTC driver to export a
fourth clock, and all devices would now depend on the RTC (also for
probing!). And Linux can realistically never turn that clock off
anyway (without grinding to a halt), so this register is more useful
for ARISC firmware?

So I am somewhat undecided: changing this for the H6 would make newer
DTs unusable on older kernels, without anything we really gain. When
we really want this, we should indeed use the opportunity to
introduce this at least for the H616 from day one, to avoid this
situation here.
But this requires more changes than just the binding, doesn't it?

Cheers,
Andre

Andre Przywara

unread,
Jan 25, 2021, 10:18:57 AM1/25/21
to Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland, Icenowy Zheng, Rob Herring, Clément Péron, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Linus Walleij, Ulf Hansson
Hi,

an update from the v3 last week, to add support for the Allwinner H616
SoC. Still based on the (updated) sunxi/for-next branch.
I am omitting the MMC and pinctrl patches now, as they have been taken
by Ulf and LinusW already into their trees.

I addressed the comments from the list, though not sure if the HOSC clock
coming from the RTC is really a good idea (didn't change it).

I was hoping that at least the clock and AXP patches (01/21-06/21) could
make it into 5.12 still? That would allow booting boards from SD card.
I am happy to strip the .dtsi and .dts patch to only contain the devices
that we actually support then, if needed.

For the changes: I split the joint DT bindings patch into subsystem
specific ones, hopefully this simplifies merging. There is a new fix
for the axp20x-pek driver, and the AXP IRQ fix has been amended as well
(according to Samuel's comments).

I eventually got USB to work, by requiring PHY 2 for [EO]HCI 1 & 3 as well.
Not sure this is the right fix, it might be just one clock or reset
line from that PHY that is needed for the others as well. Will do further
experiments.

For a more detailed changelog, see below.

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.

Various DT binding patches are sprinkled throughout the series, to add
the new compatible names right before they are used.
Patch 2 and 3 add clock support. For the -R clock this is shared with
the H6 code, as the clocks are identical, with the H616 just having
fewer of them. The main clocks are different enough to warrant a separate
file.
Patches 5 and 6 teach the AXP MFD driver to get along without having an
interrupt, as the missing NMI pin on the H616 leads to some boards not
having the AXP IRQ line connected.
Patch 8 and 14 add some tweaks to the syscon and EMAC driver, to deal
with the second EMAC clock used for the second Ethernet controller.
Patches 15 and 18 add USB support.

The remaining patches add DT bindings, which just add the new compatible
string along with an existing name as a fallback string.
Eventually we get the .dtsi for the SoC in patch 19, and the .dts for
the OrangePi Zero2 board[1] in the last patch.

We have U-Boot and Trusted-Firmware support in a working state, booting
via FEL or SD card and even TFTPing kernels work already [2][3].
The U-Boot patches are going to be merged this week.

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 other patches) can also be found here:
https://github.com/apritzel/linux/commits/h616-v4

Happy reviewing!

Cheers,
Andre

[1] https://linux-sunxi.org/Xunlong_Orange_Pi_Zero2
[2] https://github.com/jernejsk/u-boot/commits/h616-v2
[3] https://github.com/apritzel/arm-trusted-firmware/commits/h616-v1

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 (21):
dt-bindings: clk: sunxi-ccu: Add compatible string for Allwinner H616
clk: sunxi-ng: Add support for the Allwinner H616 R-CCU
clk: sunxi-ng: Add support for the Allwinner H616 CCU
dt-bindings: mfd: axp20x: Add AXP305 compatible (plus optional IRQ)
Input: axp20x-pek: Bail out if AXP has no interrupt line connected
mfd: axp20x: Allow AXP chips without interrupt lines
dt-bindings: sram: sunxi-sram: Add H616 compatible string
soc: sunxi: sram: Add support for more than one EMAC clock
dt-bindings: watchdog: sun4i: Add H616 compatible string
dt-bindings: i2c: mv64xxx: Add H616 compatible string
dt-bindings: media: IR: Add H616 IR compatible string
dt-bindings: rtc: sun6i: Add H616 compatible string
dt-bindings: spi: sunxi: Add H616 compatible string
net: stmmac: dwmac-sun8i: Prepare for second EMAC clock register
phy: sun4i-usb: Rework HCI PHY (aka. "pmu_unk1") handling
dt-bindings: usb: Add H616 compatible string
dt-bindings: usb: sunxi-musb: Add H616 compatible string
phy: sun4i-usb: Add support for the H616 USB PHY
arm64: dts: allwinner: Add Allwinner H616 .dtsi file
dt-bindings: arm: sunxi: Add OrangePi Zero 2 binding
arm64: dts: allwinner: Add OrangePi Zero 2 .dts

.../devicetree/bindings/arm/sunxi.yaml | 5 +
.../clock/allwinner,sun4i-a10-ccu.yaml | 2 +
.../bindings/i2c/marvell,mv64xxx-i2c.yaml | 21 +-
.../media/allwinner,sun4i-a10-ir.yaml | 16 +-
.../devicetree/bindings/mfd/axp20x.txt | 3 +-
.../phy/allwinner,sun8i-h3-usb-phy.yaml | 4 +-
.../bindings/rtc/allwinner,sun6i-a31-rtc.yaml | 3 +
.../bindings/spi/allwinner,sun6i-a31-spi.yaml | 1 +
.../allwinner,sun4i-a10-system-control.yaml | 1 +
.../usb/allwinner,sun4i-a10-musb.yaml | 3 +
.../watchdog/allwinner,sun4i-a10-wdt.yaml | 12 +-
arch/arm64/boot/dts/allwinner/Makefile | 1 +
.../allwinner/sun50i-h616-orangepi-zero2.dts | 242 ++++
.../arm64/boot/dts/allwinner/sun50i-h616.dtsi | 750 +++++++++++
drivers/clk/sunxi-ng/Kconfig | 7 +-
drivers/clk/sunxi-ng/Makefile | 1 +
drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c | 48 +
drivers/clk/sunxi-ng/ccu-sun50i-h616.c | 1150 +++++++++++++++++
drivers/clk/sunxi-ng/ccu-sun50i-h616.h | 56 +
drivers/input/misc/axp20x-pek.c | 4 +
drivers/mfd/axp20x.c | 17 +-
.../net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 12 +-
drivers/phy/allwinner/phy-sun4i-usb.c | 40 +-
drivers/soc/sunxi/sunxi_sram.c | 31 +-
include/dt-bindings/clock/sun50i-h616-ccu.h | 115 ++
include/dt-bindings/reset/sun50i-h616-ccu.h | 70 +
26 files changed, 2548 insertions(+), 67 deletions(-)
create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-h616-orangepi-zero2.dts
create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi
create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-h616.c
create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-h616.h
create mode 100644 include/dt-bindings/clock/sun50i-h616-ccu.h
create mode 100644 include/dt-bindings/reset/sun50i-h616-ccu.h

--
2.17.5

Andre Przywara

unread,
Jan 25, 2021, 10:18:58 AM1/25/21
to Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland, Icenowy Zheng, Rob Herring, Clément Péron, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Stephen Boyd, Michael Turquette, linu...@vger.kernel.org, devic...@vger.kernel.org
Signed-off-by: Andre Przywara <andre.p...@arm.com>
Acked-by: Rob Herring <ro...@kernel.org>
Acked-by: Maxime Ripard <mri...@kernel.org>
---
.../devicetree/bindings/clock/allwinner,sun4i-a10-ccu.yaml | 2 ++
1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-ccu.yaml b/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-ccu.yaml
index 3b45344ed758..b7e891803bb4 100644
--- a/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-ccu.yaml
+++ b/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-ccu.yaml
@@ -41,6 +41,8 @@ properties:
- allwinner,sun50i-h5-ccu
- allwinner,sun50i-h6-ccu
- allwinner,sun50i-h6-r-ccu
+ - allwinner,sun50i-h616-ccu
+ - allwinner,sun50i-h616-r-ccu
- allwinner,suniv-f1c100s-ccu
- nextthing,gr8-ccu

--
2.17.5

Andre Przywara

unread,
Jan 25, 2021, 10:19:00 AM1/25/21
to Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland, Icenowy Zheng, Rob Herring, Clément Péron, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Stephen Boyd, Michael Turquette, linu...@vger.kernel.org, Philipp Zabel
The clocks itself are identical to the H6 R-CCU, it's just that the H616
has not all of them implemented (or connected).

Signed-off-by: Andre Przywara <andre.p...@arm.com>
Acked-by: Maxime Ripard <mri...@kernel.org>
---
drivers/clk/sunxi-ng/Kconfig | 2 +-
drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c | 48 ++++++++++++++++++++++++++
2 files changed, 49 insertions(+), 1 deletion(-)

diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig
index ce5f5847d5d3..feeb8d2074ee 100644
--- a/drivers/clk/sunxi-ng/Kconfig
+++ b/drivers/clk/sunxi-ng/Kconfig
@@ -33,7 +33,7 @@ config SUN50I_H6_CCU
depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST

config SUN50I_H6_R_CCU
- bool "Support for the Allwinner H6 PRCM CCU"
+ bool "Support for the Allwinner H6 and H616 PRCM CCU"
default ARM64 && ARCH_SUNXI
depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST

diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c b/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c
index 56e351b513f3..f8909a7ed553 100644
--- a/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c
@@ -139,6 +139,16 @@ static struct ccu_common *sun50i_h6_r_ccu_clks[] = {
&w1_clk.common,
};

+static struct ccu_common *sun50i_h616_r_ccu_clks[] = {
+ &r_apb1_clk.common,
+ &r_apb2_clk.common,
+ &r_apb1_twd_clk.common,
+ &r_apb2_i2c_clk.common,
+ &r_apb2_rsb_clk.common,
+ &r_apb1_ir_clk.common,
+ &ir_clk.common,
+};
+
static struct clk_hw_onecell_data sun50i_h6_r_hw_clks = {
.hws = {
[CLK_AR100] = &ar100_clk.common.hw,
@@ -159,6 +169,20 @@ static struct clk_hw_onecell_data sun50i_h6_r_hw_clks = {
.num = CLK_NUMBER,
};

+static struct clk_hw_onecell_data sun50i_h616_r_hw_clks = {
+ .hws = {
+ [CLK_R_AHB] = &r_ahb_clk.hw,
+ [CLK_R_APB1] = &r_apb1_clk.common.hw,
+ [CLK_R_APB2] = &r_apb2_clk.common.hw,
+ [CLK_R_APB1_TWD] = &r_apb1_twd_clk.common.hw,
+ [CLK_R_APB2_I2C] = &r_apb2_i2c_clk.common.hw,
+ [CLK_R_APB2_RSB] = &r_apb2_rsb_clk.common.hw,
+ [CLK_R_APB1_IR] = &r_apb1_ir_clk.common.hw,
+ [CLK_IR] = &ir_clk.common.hw,
+ },
+ .num = CLK_NUMBER,
+};
+
static struct ccu_reset_map sun50i_h6_r_ccu_resets[] = {
[RST_R_APB1_TIMER] = { 0x11c, BIT(16) },
[RST_R_APB1_TWD] = { 0x12c, BIT(16) },
@@ -170,6 +194,13 @@ static struct ccu_reset_map sun50i_h6_r_ccu_resets[] = {
[RST_R_APB1_W1] = { 0x1ec, BIT(16) },
};

+static struct ccu_reset_map sun50i_h616_r_ccu_resets[] = {
+ [RST_R_APB1_TWD] = { 0x12c, BIT(16) },
+ [RST_R_APB2_I2C] = { 0x19c, BIT(16) },
+ [RST_R_APB2_RSB] = { 0x1bc, BIT(16) },
+ [RST_R_APB1_IR] = { 0x1cc, BIT(16) },
+};
+
static const struct sunxi_ccu_desc sun50i_h6_r_ccu_desc = {
.ccu_clks = sun50i_h6_r_ccu_clks,
.num_ccu_clks = ARRAY_SIZE(sun50i_h6_r_ccu_clks),
@@ -180,6 +211,16 @@ static const struct sunxi_ccu_desc sun50i_h6_r_ccu_desc = {
.num_resets = ARRAY_SIZE(sun50i_h6_r_ccu_resets),
};

+static const struct sunxi_ccu_desc sun50i_h616_r_ccu_desc = {
+ .ccu_clks = sun50i_h616_r_ccu_clks,
+ .num_ccu_clks = ARRAY_SIZE(sun50i_h616_r_ccu_clks),
+
+ .hw_clks = &sun50i_h616_r_hw_clks,
+
+ .resets = sun50i_h616_r_ccu_resets,
+ .num_resets = ARRAY_SIZE(sun50i_h616_r_ccu_resets),
+};
+
static void __init sunxi_r_ccu_init(struct device_node *node,
const struct sunxi_ccu_desc *desc)
{
@@ -200,3 +241,10 @@ static void __init sun50i_h6_r_ccu_setup(struct device_node *node)
}
CLK_OF_DECLARE(sun50i_h6_r_ccu, "allwinner,sun50i-h6-r-ccu",
sun50i_h6_r_ccu_setup);
+
+static void __init sun50i_h616_r_ccu_setup(struct device_node *node)
+{
+ sunxi_r_ccu_init(node, &sun50i_h616_r_ccu_desc);
+}
+CLK_OF_DECLARE(sun50i_h616_r_ccu, "allwinner,sun50i-h616-r-ccu",
+ sun50i_h616_r_ccu_setup);
--
2.17.5

Andre Przywara

unread,
Jan 25, 2021, 10:19:03 AM1/25/21
to Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland, Icenowy Zheng, Rob Herring, Clément Péron, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Stephen Boyd, Michael Turquette, linu...@vger.kernel.org, Philipp Zabel
While the clocks are fairly similar to the H6, many differ in tiny
details, so a separate clock driver seems indicated.

Derived from the H6 clock driver, and adjusted according to the manual.

Signed-off-by: Andre Przywara <andre.p...@arm.com>
Acked-by: Maxime Ripard <mri...@kernel.org>
---
drivers/clk/sunxi-ng/Kconfig | 5 +
drivers/clk/sunxi-ng/Makefile | 1 +
drivers/clk/sunxi-ng/ccu-sun50i-h616.c | 1150 +++++++++++++++++++
drivers/clk/sunxi-ng/ccu-sun50i-h616.h | 56 +
include/dt-bindings/clock/sun50i-h616-ccu.h | 115 ++
include/dt-bindings/reset/sun50i-h616-ccu.h | 70 ++
6 files changed, 1397 insertions(+)
create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-h616.c
create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-h616.h
create mode 100644 include/dt-bindings/clock/sun50i-h616-ccu.h
create mode 100644 include/dt-bindings/reset/sun50i-h616-ccu.h

diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig
index feeb8d2074ee..cd46d8853876 100644
--- a/drivers/clk/sunxi-ng/Kconfig
+++ b/drivers/clk/sunxi-ng/Kconfig
@@ -32,6 +32,11 @@ config SUN50I_H6_CCU
default ARM64 && ARCH_SUNXI
depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST

+config SUN50I_H616_CCU
+ bool "Support for the Allwinner H616 CCU"
+ default ARM64 && ARCH_SUNXI
+ depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST
+
config SUN50I_H6_R_CCU
bool "Support for the Allwinner H6 and H616 PRCM CCU"
default ARM64 && ARCH_SUNXI
diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
index 3eb5cff40eac..96c324306d97 100644
--- a/drivers/clk/sunxi-ng/Makefile
+++ b/drivers/clk/sunxi-ng/Makefile
@@ -26,6 +26,7 @@ obj-$(CONFIG_SUN50I_A64_CCU) += ccu-sun50i-a64.o
obj-$(CONFIG_SUN50I_A100_CCU) += ccu-sun50i-a100.o
obj-$(CONFIG_SUN50I_A100_R_CCU) += ccu-sun50i-a100-r.o
obj-$(CONFIG_SUN50I_H6_CCU) += ccu-sun50i-h6.o
+obj-$(CONFIG_SUN50I_H616_CCU) += ccu-sun50i-h616.o
obj-$(CONFIG_SUN50I_H6_R_CCU) += ccu-sun50i-h6-r.o
obj-$(CONFIG_SUN4I_A10_CCU) += ccu-sun4i-a10.o
obj-$(CONFIG_SUN5I_CCU) += ccu-sun5i.o
diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h616.c b/drivers/clk/sunxi-ng/ccu-sun50i-h616.c
new file mode 100644
index 000000000000..225307305880
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-h616.c
@@ -0,0 +1,1150 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2020 Arm Ltd.
+ * Based on the H6 CCU driver, which is:
+ * Copyright (c) 2017 Icenowy Zheng <ice...@aosc.io>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+
+#include "ccu_common.h"
+#include "ccu_reset.h"
+
+#include "ccu_div.h"
+#include "ccu_gate.h"
+#include "ccu_mp.h"
+#include "ccu_mult.h"
+#include "ccu_nk.h"
+#include "ccu_nkm.h"
+#include "ccu_nkmp.h"
+#include "ccu_nm.h"
+
+#include "ccu-sun50i-h616.h"
+
+/*
+ * The CPU PLL is actually NP clock, with P being /1, /2 or /4. However
+ * P should only be used for output frequencies lower than 288 MHz.
+ *
+ * For now we can just model it as a multiplier clock, and force P to /1.
+ *
+ * The M factor is present in the register's description, but not in the
+ * frequency formula, and it's documented as "M is only used for backdoor
+ * testing", so it's not modelled and then force to 0.
+ */
+#define SUN50I_H616_PLL_CPUX_REG 0x000
+static struct ccu_mult pll_cpux_clk = {
+ .enable = BIT(31),
+ .lock = BIT(28),
+ .mult = _SUNXI_CCU_MULT_MIN(8, 8, 12),
+ .common = {
+ .reg = 0x000,
+ .hw.init = CLK_HW_INIT("pll-cpux", "osc24M",
+ &ccu_mult_ops,
+ CLK_SET_RATE_UNGATE),
+ },
+};
+
+/* Some PLLs are input * N / div1 / P. Model them as NKMP with no K */
+#define SUN50I_H616_PLL_DDR0_REG 0x010
+static struct ccu_nkmp pll_ddr0_clk = {
+ .enable = BIT(31),
+ .lock = BIT(28),
+ .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
+ .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
+ .p = _SUNXI_CCU_DIV(0, 1), /* output divider */
+ .common = {
+ .reg = 0x010,
+ .hw.init = CLK_HW_INIT("pll-ddr0", "osc24M",
+ &ccu_nkmp_ops,
+ CLK_SET_RATE_UNGATE),
+ },
+};
+
+#define SUN50I_H616_PLL_DDR1_REG 0x018
+static struct ccu_nkmp pll_ddr1_clk = {
+ .enable = BIT(31),
+ .lock = BIT(28),
+ .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
+ .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
+ .p = _SUNXI_CCU_DIV(0, 1), /* output divider */
+ .common = {
+ .reg = 0x018,
+ .hw.init = CLK_HW_INIT("pll-ddr1", "osc24M",
+ &ccu_nkmp_ops,
+ CLK_SET_RATE_UNGATE),
+ },
+};
+
+#define SUN50I_H616_PLL_PERIPH0_REG 0x020
+static struct ccu_nkmp pll_periph0_clk = {
+ .enable = BIT(31),
+ .lock = BIT(28),
+ .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
+ .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
+ .p = _SUNXI_CCU_DIV(0, 1), /* output divider */
+ .fixed_post_div = 2,
+ .common = {
+ .reg = 0x020,
+ .features = CCU_FEATURE_FIXED_POSTDIV,
+ .hw.init = CLK_HW_INIT("pll-periph0", "osc24M",
+ &ccu_nkmp_ops,
+ CLK_SET_RATE_UNGATE),
+ },
+};
+
+#define SUN50I_H616_PLL_PERIPH1_REG 0x028
+static struct ccu_nkmp pll_periph1_clk = {
+ .enable = BIT(31),
+ .lock = BIT(28),
+ .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
+ .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
+ .p = _SUNXI_CCU_DIV(0, 1), /* output divider */
+ .fixed_post_div = 2,
+ .common = {
+ .reg = 0x028,
+ .features = CCU_FEATURE_FIXED_POSTDIV,
+ .hw.init = CLK_HW_INIT("pll-periph1", "osc24M",
+ &ccu_nkmp_ops,
+ CLK_SET_RATE_UNGATE),
+ },
+};
+
+#define SUN50I_H616_PLL_GPU_REG 0x030
+static struct ccu_nkmp pll_gpu_clk = {
+ .enable = BIT(31),
+ .lock = BIT(28),
+ .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
+ .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
+ .p = _SUNXI_CCU_DIV(0, 1), /* output divider */
+ .common = {
+ .reg = 0x030,
+ .hw.init = CLK_HW_INIT("pll-gpu", "osc24M",
+ &ccu_nkmp_ops,
+ CLK_SET_RATE_UNGATE),
+ },
+};
+
+/*
+ * For Video PLLs, the output divider is described as "used for testing"
+ * in the user manual. So it's not modelled and forced to 0.
+ */
+#define SUN50I_H616_PLL_VIDEO0_REG 0x040
+static struct ccu_nm pll_video0_clk = {
+ .enable = BIT(31),
+ .lock = BIT(28),
+ .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
+ .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
+ .fixed_post_div = 4,
+ .min_rate = 288000000,
+ .max_rate = 2400000000UL,
+ .common = {
+ .reg = 0x040,
+ .features = CCU_FEATURE_FIXED_POSTDIV,
+ .hw.init = CLK_HW_INIT("pll-video0", "osc24M",
+ &ccu_nm_ops,
+ CLK_SET_RATE_UNGATE),
+ },
+};
+
+#define SUN50I_H616_PLL_VIDEO1_REG 0x048
+static struct ccu_nm pll_video1_clk = {
+ .enable = BIT(31),
+ .lock = BIT(28),
+ .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
+ .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
+ .fixed_post_div = 4,
+ .min_rate = 288000000,
+ .max_rate = 2400000000UL,
+ .common = {
+ .reg = 0x048,
+ .features = CCU_FEATURE_FIXED_POSTDIV,
+ .hw.init = CLK_HW_INIT("pll-video1", "osc24M",
+ &ccu_nm_ops,
+ CLK_SET_RATE_UNGATE),
+ },
+};
+
+#define SUN50I_H616_PLL_VIDEO2_REG 0x050
+static struct ccu_nm pll_video2_clk = {
+ .enable = BIT(31),
+ .lock = BIT(28),
+ .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
+ .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
+ .fixed_post_div = 4,
+ .min_rate = 288000000,
+ .max_rate = 2400000000UL,
+ .common = {
+ .reg = 0x050,
+ .features = CCU_FEATURE_FIXED_POSTDIV,
+ .hw.init = CLK_HW_INIT("pll-video2", "osc24M",
+ &ccu_nm_ops,
+ CLK_SET_RATE_UNGATE),
+ },
+};
+
+#define SUN50I_H616_PLL_VE_REG 0x058
+static struct ccu_nkmp pll_ve_clk = {
+ .enable = BIT(31),
+ .lock = BIT(28),
+ .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
+ .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
+ .p = _SUNXI_CCU_DIV(0, 1), /* output divider */
+ .common = {
+ .reg = 0x058,
+ .hw.init = CLK_HW_INIT("pll-ve", "osc24M",
+ &ccu_nkmp_ops,
+ CLK_SET_RATE_UNGATE),
+ },
+};
+
+#define SUN50I_H616_PLL_DE_REG 0x060
+static struct ccu_nkmp pll_de_clk = {
+ .enable = BIT(31),
+ .lock = BIT(28),
+ .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
+ .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
+ .p = _SUNXI_CCU_DIV(0, 1), /* output divider */
+ .common = {
+ .reg = 0x060,
+ .hw.init = CLK_HW_INIT("pll-de", "osc24M",
+ &ccu_nkmp_ops,
+ CLK_SET_RATE_UNGATE),
+ },
+};
+
+/*
+ * TODO: Determine SDM settings for the audio PLL. The manual suggests
+ * PLL_FACTOR_N=16, PLL_POST_DIV_P=2, OUTPUT_DIV=2, pattern=0xe000c49b
+ * for 24.576 MHz, and PLL_FACTOR_N=22, PLL_POST_DIV_P=3, OUTPUT_DIV=2,
+ * pattern=0xe001288c for 22.5792 MHz.
+ * This clashes with our fixed PLL_POST_DIV_P.
+ */
+#define SUN50I_H616_PLL_AUDIO_REG 0x078
+static struct ccu_nm pll_audio_hs_clk = {
+ .enable = BIT(31),
+ .lock = BIT(28),
+ .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
+ .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
+ .common = {
+ .reg = 0x078,
+ .hw.init = CLK_HW_INIT("pll-audio-hs", "osc24M",
+ &ccu_nm_ops,
+ CLK_SET_RATE_UNGATE),
+ },
+};
+
+static const char * const cpux_parents[] = { "osc24M", "osc32k",
+ "iosc", "pll-cpux", "pll-periph0" };
+static SUNXI_CCU_MUX(cpux_clk, "cpux", cpux_parents,
+ 0x500, 24, 3, CLK_SET_RATE_PARENT | CLK_IS_CRITICAL);
+static SUNXI_CCU_M(axi_clk, "axi", "cpux", 0x500, 0, 2, 0);
+static SUNXI_CCU_M(cpux_apb_clk, "cpux-apb", "cpux", 0x500, 8, 2, 0);
+
+static const char * const psi_ahb1_ahb2_parents[] = { "osc24M", "osc32k",
+ "iosc", "pll-periph0" };
+static SUNXI_CCU_MP_WITH_MUX(psi_ahb1_ahb2_clk, "psi-ahb1-ahb2",
+ psi_ahb1_ahb2_parents,
+ 0x510,
+ 0, 2, /* M */
+ 8, 2, /* P */
+ 24, 2, /* mux */
+ 0);
+
+static const char * const ahb3_apb1_apb2_parents[] = { "osc24M", "osc32k",
+ "psi-ahb1-ahb2",
+ "pll-periph0" };
+static SUNXI_CCU_MP_WITH_MUX(ahb3_clk, "ahb3", ahb3_apb1_apb2_parents, 0x51c,
+ 0, 2, /* M */
+ 8, 2, /* P */
+ 24, 2, /* mux */
+ 0);
+
+static SUNXI_CCU_MP_WITH_MUX(apb1_clk, "apb1", ahb3_apb1_apb2_parents, 0x520,
+ 0, 2, /* M */
+ 8, 2, /* P */
+ 24, 2, /* mux */
+ 0);
+
+static SUNXI_CCU_MP_WITH_MUX(apb2_clk, "apb2", ahb3_apb1_apb2_parents, 0x524,
+ 0, 2, /* M */
+ 8, 2, /* P */
+ 24, 2, /* mux */
+ 0);
+
+static const char * const mbus_parents[] = { "osc24M", "pll-periph0-2x",
+ "pll-ddr0", "pll-ddr1" };
+static SUNXI_CCU_M_WITH_MUX_GATE(mbus_clk, "mbus", mbus_parents, 0x540,
+ 0, 3, /* M */
+ 24, 2, /* mux */
+ BIT(31), /* gate */
+ CLK_IS_CRITICAL);
+
+static const char * const de_parents[] = { "pll-de", "pll-periph0-2x" };
+static SUNXI_CCU_M_WITH_MUX_GATE(de_clk, "de", de_parents, 0x600,
+ 0, 4, /* M */
+ 24, 1, /* mux */
+ BIT(31), /* gate */
+ CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_GATE(bus_de_clk, "bus-de", "psi-ahb1-ahb2",
+ 0x60c, BIT(0), 0);
+
+static SUNXI_CCU_M_WITH_MUX_GATE(deinterlace_clk, "deinterlace",
+ de_parents,
+ 0x620,
+ 0, 4, /* M */
+ 24, 1, /* mux */
+ BIT(31), /* gate */
+ 0);
+
+static SUNXI_CCU_GATE(bus_deinterlace_clk, "bus-deinterlace", "psi-ahb1-ahb2",
+ 0x62c, BIT(0), 0);
+
+static SUNXI_CCU_M_WITH_MUX_GATE(g2d_clk, "g2d", de_parents, 0x630,
+ 0, 4, /* M */
+ 24, 1, /* mux */
+ BIT(31), /* gate */
+ 0);
+
+static SUNXI_CCU_GATE(bus_g2d_clk, "bus-g2d", "psi-ahb1-ahb2",
+ 0x63c, BIT(0), 0);
+
+static const char * const gpu0_parents[] = { "pll-gpu", "gpu1" };
+static SUNXI_CCU_M_WITH_MUX_GATE(gpu0_clk, "gpu0", gpu0_parents, 0x670,
+ 0, 2, /* M */
+ 24, 1, /* mux */
+ BIT(31), /* gate */
+ CLK_SET_RATE_PARENT);
+static SUNXI_CCU_M_WITH_GATE(gpu1_clk, "gpu1", "pll-periph0-2x", 0x674,
+ 0, 2, /* M */
+ BIT(31),/* gate */
+ 0);
+
+static SUNXI_CCU_GATE(bus_gpu_clk, "bus-gpu", "psi-ahb1-ahb2",
+ 0x67c, BIT(0), 0);
+
+static const char * const ce_parents[] = { "osc24M", "pll-periph0-2x" };
+static SUNXI_CCU_MP_WITH_MUX_GATE(ce_clk, "ce", ce_parents, 0x680,
+ 0, 4, /* M */
+ 8, 2, /* N */
+ 24, 1, /* mux */
+ BIT(31),/* gate */
+ 0);
+
+static SUNXI_CCU_GATE(bus_ce_clk, "bus-ce", "psi-ahb1-ahb2",
+ 0x68c, BIT(0), 0);
+
+static const char * const ve_parents[] = { "pll-ve" };
+static SUNXI_CCU_M_WITH_MUX_GATE(ve_clk, "ve", ve_parents, 0x690,
+ 0, 3, /* M */
+ 24, 1, /* mux */
+ BIT(31), /* gate */
+ CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_GATE(bus_ve_clk, "bus-ve", "psi-ahb1-ahb2",
+ 0x69c, BIT(0), 0);
+
+static SUNXI_CCU_GATE(bus_dma_clk, "bus-dma", "psi-ahb1-ahb2",
+ 0x70c, BIT(0), 0);
+
+static SUNXI_CCU_GATE(bus_hstimer_clk, "bus-hstimer", "psi-ahb1-ahb2",
+ 0x73c, BIT(0), 0);
+
+static SUNXI_CCU_GATE(avs_clk, "avs", "osc24M", 0x740, BIT(31), 0);
+
+static SUNXI_CCU_GATE(bus_dbg_clk, "bus-dbg", "psi-ahb1-ahb2",
+ 0x78c, BIT(0), 0);
+
+static SUNXI_CCU_GATE(bus_psi_clk, "bus-psi", "psi-ahb1-ahb2",
+ 0x79c, BIT(0), 0);
+
+static SUNXI_CCU_GATE(bus_pwm_clk, "bus-pwm", "apb1", 0x7ac, BIT(0), 0);
+
+static SUNXI_CCU_GATE(bus_iommu_clk, "bus-iommu", "apb1", 0x7bc, BIT(0), 0);
+
+static const char * const dram_parents[] = { "pll-ddr0", "pll-ddr1" };
+static struct ccu_div dram_clk = {
+ .div = _SUNXI_CCU_DIV(0, 2),
+ .mux = _SUNXI_CCU_MUX(24, 2),
+ .common = {
+ .reg = 0x800,
+ .hw.init = CLK_HW_INIT_PARENTS("dram",
+ dram_parents,
+ &ccu_div_ops,
+ CLK_IS_CRITICAL),
+ },
+};
+
+static SUNXI_CCU_GATE(mbus_dma_clk, "mbus-dma", "mbus",
+ 0x804, BIT(0), 0);
+static SUNXI_CCU_GATE(mbus_ve_clk, "mbus-ve", "mbus",
+ 0x804, BIT(1), 0);
+static SUNXI_CCU_GATE(mbus_ce_clk, "mbus-ce", "mbus",
+ 0x804, BIT(2), 0);
+static SUNXI_CCU_GATE(mbus_ts_clk, "mbus-ts", "mbus",
+ 0x804, BIT(3), 0);
+static SUNXI_CCU_GATE(mbus_nand_clk, "mbus-nand", "mbus",
+ 0x804, BIT(5), 0);
+static SUNXI_CCU_GATE(mbus_g2d_clk, "mbus-g2d", "mbus",
+ 0x804, BIT(10), 0);
+
+static SUNXI_CCU_GATE(bus_dram_clk, "bus-dram", "psi-ahb1-ahb2",
+ 0x80c, BIT(0), CLK_IS_CRITICAL);
+
+static const char * const nand_spi_parents[] = { "osc24M", "pll-periph0",
+ "pll-periph1", "pll-periph0-2x",
+ "pll-periph1-2x" };
+static SUNXI_CCU_MP_WITH_MUX_GATE(nand0_clk, "nand0", nand_spi_parents, 0x810,
+ 0, 4, /* M */
+ 8, 2, /* N */
+ 24, 3, /* mux */
+ BIT(31),/* gate */
+ 0);
+
+static SUNXI_CCU_MP_WITH_MUX_GATE(nand1_clk, "nand1", nand_spi_parents, 0x814,
+ 0, 4, /* M */
+ 8, 2, /* N */
+ 24, 3, /* mux */
+ BIT(31),/* gate */
+ 0);
+
+static SUNXI_CCU_GATE(bus_nand_clk, "bus-nand", "ahb3", 0x82c, BIT(0), 0);
+
+static const char * const mmc_parents[] = { "osc24M", "pll-periph0-2x",
+ "pll-periph1-2x" };
+static SUNXI_CCU_MP_WITH_MUX_GATE_POSTDIV(mmc0_clk, "mmc0", mmc_parents, 0x830,
+ 0, 4, /* M */
+ 8, 2, /* N */
+ 24, 2, /* mux */
+ BIT(31), /* gate */
+ 2, /* post-div */
+ 0);
+
+static SUNXI_CCU_MP_WITH_MUX_GATE_POSTDIV(mmc1_clk, "mmc1", mmc_parents, 0x834,
+ 0, 4, /* M */
+ 8, 2, /* N */
+ 24, 2, /* mux */
+ BIT(31), /* gate */
+ 2, /* post-div */
+ 0);
+
+static SUNXI_CCU_MP_WITH_MUX_GATE_POSTDIV(mmc2_clk, "mmc2", mmc_parents, 0x838,
+ 0, 4, /* M */
+ 8, 2, /* N */
+ 24, 2, /* mux */
+ BIT(31), /* gate */
+ 2, /* post-div */
+ 0);
+
+static SUNXI_CCU_GATE(bus_mmc0_clk, "bus-mmc0", "ahb3", 0x84c, BIT(0), 0);
+static SUNXI_CCU_GATE(bus_mmc1_clk, "bus-mmc1", "ahb3", 0x84c, BIT(1), 0);
+static SUNXI_CCU_GATE(bus_mmc2_clk, "bus-mmc2", "ahb3", 0x84c, BIT(2), 0);
+
+static SUNXI_CCU_GATE(bus_uart0_clk, "bus-uart0", "apb2", 0x90c, BIT(0), 0);
+static SUNXI_CCU_GATE(bus_uart1_clk, "bus-uart1", "apb2", 0x90c, BIT(1), 0);
+static SUNXI_CCU_GATE(bus_uart2_clk, "bus-uart2", "apb2", 0x90c, BIT(2), 0);
+static SUNXI_CCU_GATE(bus_uart3_clk, "bus-uart3", "apb2", 0x90c, BIT(3), 0);
+static SUNXI_CCU_GATE(bus_uart4_clk, "bus-uart4", "apb2", 0x90c, BIT(4), 0);
+static SUNXI_CCU_GATE(bus_uart5_clk, "bus-uart5", "apb2", 0x90c, BIT(5), 0);
+
+static SUNXI_CCU_GATE(bus_i2c0_clk, "bus-i2c0", "apb2", 0x91c, BIT(0), 0);
+static SUNXI_CCU_GATE(bus_i2c1_clk, "bus-i2c1", "apb2", 0x91c, BIT(1), 0);
+static SUNXI_CCU_GATE(bus_i2c2_clk, "bus-i2c2", "apb2", 0x91c, BIT(2), 0);
+static SUNXI_CCU_GATE(bus_i2c3_clk, "bus-i2c3", "apb2", 0x91c, BIT(3), 0);
+static SUNXI_CCU_GATE(bus_i2c4_clk, "bus-i2c4", "apb2", 0x91c, BIT(4), 0);
+
+static SUNXI_CCU_MP_WITH_MUX_GATE(spi0_clk, "spi0", nand_spi_parents, 0x940,
+ 0, 4, /* M */
+ 8, 2, /* N */
+ 24, 3, /* mux */
+ BIT(31),/* gate */
+ 0);
+
+static SUNXI_CCU_MP_WITH_MUX_GATE(spi1_clk, "spi1", nand_spi_parents, 0x944,
+ 0, 4, /* M */
+ 8, 2, /* N */
+ 24, 3, /* mux */
+ BIT(31),/* gate */
+ 0);
+
+static SUNXI_CCU_GATE(bus_spi0_clk, "bus-spi0", "ahb3", 0x96c, BIT(0), 0);
+static SUNXI_CCU_GATE(bus_spi1_clk, "bus-spi1", "ahb3", 0x96c, BIT(1), 0);
+
+static SUNXI_CCU_GATE(emac_25m_clk, "emac-25m", "ahb3", 0x970,
+ BIT(31) | BIT(30), 0);
+
+static SUNXI_CCU_GATE(bus_emac0_clk, "bus-emac0", "ahb3", 0x97c, BIT(0), 0);
+static SUNXI_CCU_GATE(bus_emac1_clk, "bus-emac1", "ahb3", 0x97c, BIT(1), 0);
+
+static const char * const ts_parents[] = { "osc24M", "pll-periph0" };
+static SUNXI_CCU_MP_WITH_MUX_GATE(ts_clk, "ts", ts_parents, 0x9b0,
+ 0, 4, /* M */
+ 8, 2, /* N */
+ 24, 1, /* mux */
+ BIT(31),/* gate */
+ 0);
+
+static SUNXI_CCU_GATE(bus_ts_clk, "bus-ts", "ahb3", 0x9bc, BIT(0), 0);
+
+static SUNXI_CCU_GATE(bus_ths_clk, "bus-ths", "apb1", 0x9fc, BIT(0), 0);
+
+static const char * const audio_parents[] = { "pll-audio-1x", "pll-audio-2x",
+ "pll-audio-4x", "pll-audio-hs" };
+static struct ccu_div spdif_clk = {
+ .enable = BIT(31),
+ .div = _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO),
+ .mux = _SUNXI_CCU_MUX(24, 2),
+ .common = {
+ .reg = 0xa20,
+ .hw.init = CLK_HW_INIT_PARENTS("spdif",
+ audio_parents,
+ &ccu_div_ops,
+ 0),
+ },
+};
+
+static SUNXI_CCU_GATE(bus_spdif_clk, "bus-spdif", "apb1", 0xa2c, BIT(0), 0);
+
+static struct ccu_div dmic_clk = {
+ .enable = BIT(31),
+ .div = _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO),
+ .mux = _SUNXI_CCU_MUX(24, 2),
+ .common = {
+ .reg = 0xa40,
+ .hw.init = CLK_HW_INIT_PARENTS("dmic",
+ audio_parents,
+ &ccu_div_ops,
+ 0),
+ },
+};
+
+static SUNXI_CCU_GATE(bus_dmic_clk, "bus-dmic", "apb1", 0xa4c, BIT(0), 0);
+
+static SUNXI_CCU_M_WITH_MUX_GATE(audio_codec_1x_clk, "audio-codec-1x",
+ audio_parents, 0xa50,
+ 0, 4, /* M */
+ 24, 2, /* mux */
+ BIT(31), /* gate */
+ CLK_SET_RATE_PARENT);
+static SUNXI_CCU_M_WITH_MUX_GATE(audio_codec_4x_clk, "audio-codec-4x",
+ audio_parents, 0xa54,
+ 0, 4, /* M */
+ 24, 2, /* mux */
+ BIT(31), /* gate */
+ CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_GATE(bus_audio_codec_clk, "bus-audio-codec", "apb1", 0xa5c,
+ BIT(0), 0);
+
+static struct ccu_div audio_hub_clk = {
+ .enable = BIT(31),
+ .div = _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO),
+ .mux = _SUNXI_CCU_MUX(24, 2),
+ .common = {
+ .reg = 0xa60,
+ .hw.init = CLK_HW_INIT_PARENTS("audio-hub",
+ audio_parents,
+ &ccu_div_ops,
+ 0),
+ },
+};
+
+static SUNXI_CCU_GATE(bus_audio_hub_clk, "bus-audio-hub", "apb1", 0xa6c, BIT(0), 0);
+
+/*
+ * There are OHCI 12M clock source selection bits for the four USB 2.0 ports.
+ * We will force them to 0 (12M divided from 48M).
+ */
+#define SUN50I_H616_USB0_CLK_REG 0xa70
+#define SUN50I_H616_USB1_CLK_REG 0xa74
+#define SUN50I_H616_USB2_CLK_REG 0xa78
+#define SUN50I_H616_USB3_CLK_REG 0xa7c
+
+static SUNXI_CCU_GATE(usb_ohci0_clk, "usb-ohci0", "osc12M", 0xa70, BIT(31), 0);
+static SUNXI_CCU_GATE(usb_phy0_clk, "usb-phy0", "osc24M", 0xa70, BIT(29), 0);
+
+static SUNXI_CCU_GATE(usb_ohci1_clk, "usb-ohci1", "osc12M", 0xa74, BIT(31), 0);
+static SUNXI_CCU_GATE(usb_phy1_clk, "usb-phy1", "osc24M", 0xa74, BIT(29), 0);
+
+static SUNXI_CCU_GATE(usb_ohci2_clk, "usb-ohci2", "osc12M", 0xa78, BIT(31), 0);
+static SUNXI_CCU_GATE(usb_phy2_clk, "usb-phy2", "osc24M", 0xa78, BIT(29), 0);
+
+static SUNXI_CCU_GATE(usb_ohci3_clk, "usb-ohci3", "osc12M", 0xa7c, BIT(31), 0);
+static SUNXI_CCU_GATE(usb_phy3_clk, "usb-phy3", "osc24M", 0xa7c, BIT(29), 0);
+
+static SUNXI_CCU_GATE(bus_ohci0_clk, "bus-ohci0", "ahb3", 0xa8c, BIT(0), 0);
+static SUNXI_CCU_GATE(bus_ohci1_clk, "bus-ohci1", "ahb3", 0xa8c, BIT(1), 0);
+static SUNXI_CCU_GATE(bus_ohci2_clk, "bus-ohci2", "ahb3", 0xa8c, BIT(2), 0);
+static SUNXI_CCU_GATE(bus_ohci3_clk, "bus-ohci3", "ahb3", 0xa8c, BIT(3), 0);
+static SUNXI_CCU_GATE(bus_ehci0_clk, "bus-ehci0", "ahb3", 0xa8c, BIT(4), 0);
+static SUNXI_CCU_GATE(bus_ehci1_clk, "bus-ehci1", "ahb3", 0xa8c, BIT(5), 0);
+static SUNXI_CCU_GATE(bus_ehci2_clk, "bus-ehci2", "ahb3", 0xa8c, BIT(6), 0);
+static SUNXI_CCU_GATE(bus_ehci3_clk, "bus-ehci3", "ahb3", 0xa8c, BIT(7), 0);
+static SUNXI_CCU_GATE(bus_otg_clk, "bus-otg", "ahb3", 0xa8c, BIT(8), 0);
+
+static SUNXI_CCU_GATE(bus_keyadc_clk, "bus-keyadc", "apb1", 0xa9c, BIT(0), 0);
+
+static const char * const hdmi_parents[] = { "pll-video0", "pll-video0-4x",
+ "pll-video2", "pll-video2-4x" };
+static SUNXI_CCU_M_WITH_MUX_GATE(hdmi_clk, "hdmi", hdmi_parents, 0xb00,
+ 0, 4, /* M */
+ 24, 2, /* mux */
+ BIT(31), /* gate */
+ 0);
+
+static SUNXI_CCU_GATE(hdmi_slow_clk, "hdmi-slow", "osc24M", 0xb04, BIT(31), 0);
+
+static const char * const hdmi_cec_parents[] = { "osc32k", "pll-periph0-2x" };
+static const struct ccu_mux_fixed_prediv hdmi_cec_predivs[] = {
+ { .index = 1, .div = 36621 },
+};
+
+#define SUN50I_H616_HDMI_CEC_CLK_REG 0xb10
+static struct ccu_mux hdmi_cec_clk = {
+ .enable = BIT(31) | BIT(30),
+
+ .mux = {
+ .shift = 24,
+ .width = 2,
+
+ .fixed_predivs = hdmi_cec_predivs,
+ .n_predivs = ARRAY_SIZE(hdmi_cec_predivs),
+ },
+
+ .common = {
+ .reg = 0xb10,
+ .features = CCU_FEATURE_FIXED_PREDIV,
+ .hw.init = CLK_HW_INIT_PARENTS("hdmi-cec",
+ hdmi_cec_parents,
+ &ccu_mux_ops,
+ 0),
+ },
+};
+
+static SUNXI_CCU_GATE(bus_hdmi_clk, "bus-hdmi", "ahb3", 0xb1c, BIT(0), 0);
+
+static SUNXI_CCU_GATE(bus_tcon_top_clk, "bus-tcon-top", "ahb3",
+ 0xb5c, BIT(0), 0);
+
+static const char * const tcon_tv_parents[] = { "pll-video0",
+ "pll-video0-4x",
+ "pll-video1",
+ "pll-video1-4x" };
+static SUNXI_CCU_MP_WITH_MUX_GATE(tcon_tv0_clk, "tcon-tv0",
+ tcon_tv_parents, 0xb80,
+ 0, 4, /* M */
+ 8, 2, /* P */
+ 24, 3, /* mux */
+ BIT(31), /* gate */
+ CLK_SET_RATE_PARENT);
+static SUNXI_CCU_MP_WITH_MUX_GATE(tcon_tv1_clk, "tcon-tv1",
+ tcon_tv_parents, 0xb84,
+ 0, 4, /* M */
+ 8, 2, /* P */
+ 24, 3, /* mux */
+ BIT(31), /* gate */
+ CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_GATE(bus_tcon_tv0_clk, "bus-tcon-tv0", "ahb3",
+ 0xb9c, BIT(0), 0);
+static SUNXI_CCU_GATE(bus_tcon_tv1_clk, "bus-tcon-tv1", "ahb3",
+ 0xb9c, BIT(1), 0);
+
+static SUNXI_CCU_MP_WITH_MUX_GATE(tve0_clk, "tve0",
+ tcon_tv_parents, 0xbb0,
+ 0, 4, /* M */
+ 8, 2, /* P */
+ 24, 3, /* mux */
+ BIT(31), /* gate */
+ CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_GATE(bus_tve_top_clk, "bus-tve-top", "ahb3",
+ 0xbbc, BIT(0), 0);
+static SUNXI_CCU_GATE(bus_tve0_clk, "bus-tve0", "ahb3",
+ 0xbbc, BIT(1), 0);
+
+static const char * const hdcp_parents[] = { "pll-periph0", "pll-periph1" };
+static SUNXI_CCU_M_WITH_MUX_GATE(hdcp_clk, "hdcp", hdcp_parents, 0xc40,
+ 0, 4, /* M */
+ 24, 2, /* mux */
+ BIT(31), /* gate */
+ 0);
+
+static SUNXI_CCU_GATE(bus_hdcp_clk, "bus-hdcp", "ahb3", 0xc4c, BIT(0), 0);
+
+/* Fixed factor clocks */
+static CLK_FIXED_FACTOR_FW_NAME(osc12M_clk, "osc12M", "hosc", 2, 1, 0);
+
+static const struct clk_hw *clk_parent_pll_audio[] = {
+ &pll_audio_hs_clk.common.hw
+};
+
+/*
+ * The divider of pll-audio is fixed to 24 for now, so 24576000 and 22579200
+ * rates can be set exactly in conjunction with sigma-delta modulation.
+ */
+static CLK_FIXED_FACTOR_HWS(pll_audio_1x_clk, "pll-audio-1x",
+ clk_parent_pll_audio,
+ 96, 1, CLK_SET_RATE_PARENT);
+static CLK_FIXED_FACTOR_HWS(pll_audio_2x_clk, "pll-audio-2x",
+ clk_parent_pll_audio,
+ 48, 1, CLK_SET_RATE_PARENT);
+static CLK_FIXED_FACTOR_HWS(pll_audio_4x_clk, "pll-audio-4x",
+ clk_parent_pll_audio,
+ 24, 1, CLK_SET_RATE_PARENT);
+
+static const struct clk_hw *pll_periph0_parents[] = {
+ &pll_periph0_clk.common.hw
+};
+
+static CLK_FIXED_FACTOR_HWS(pll_periph0_2x_clk, "pll-periph0-2x",
+ pll_periph0_parents,
+ 1, 2, 0);
+
+static const struct clk_hw *pll_periph1_parents[] = {
+ &pll_periph1_clk.common.hw
+};
+
+static CLK_FIXED_FACTOR_HWS(pll_periph1_2x_clk, "pll-periph1-2x",
+ pll_periph1_parents,
+ 1, 2, 0);
+
+static CLK_FIXED_FACTOR_HW(pll_video0_4x_clk, "pll-video0-4x",
+ &pll_video0_clk.common.hw,
+ 1, 4, CLK_SET_RATE_PARENT);
+static CLK_FIXED_FACTOR_HW(pll_video1_4x_clk, "pll-video1-4x",
+ &pll_video1_clk.common.hw,
+ 1, 4, CLK_SET_RATE_PARENT);
+static CLK_FIXED_FACTOR_HW(pll_video2_4x_clk, "pll-video2-4x",
+ &pll_video2_clk.common.hw,
+ 1, 4, CLK_SET_RATE_PARENT);
+
+static struct ccu_common *sun50i_h616_ccu_clks[] = {
+ &pll_cpux_clk.common,
+ &pll_ddr0_clk.common,
+ &pll_ddr1_clk.common,
+ &pll_periph0_clk.common,
+ &pll_periph1_clk.common,
+ &pll_gpu_clk.common,
+ &pll_video0_clk.common,
+ &pll_video1_clk.common,
+ &pll_video2_clk.common,
+ &pll_ve_clk.common,
+ &pll_de_clk.common,
+ &pll_audio_hs_clk.common,
+ &cpux_clk.common,
+ &axi_clk.common,
+ &cpux_apb_clk.common,
+ &psi_ahb1_ahb2_clk.common,
+ &ahb3_clk.common,
+ &apb1_clk.common,
+ &apb2_clk.common,
+ &mbus_clk.common,
+ &de_clk.common,
+ &bus_de_clk.common,
+ &deinterlace_clk.common,
+ &bus_deinterlace_clk.common,
+ &g2d_clk.common,
+ &bus_g2d_clk.common,
+ &gpu0_clk.common,
+ &bus_gpu_clk.common,
+ &gpu1_clk.common,
+ &ce_clk.common,
+ &bus_ce_clk.common,
+ &ve_clk.common,
+ &bus_ve_clk.common,
+ &bus_dma_clk.common,
+ &bus_hstimer_clk.common,
+ &avs_clk.common,
+ &bus_dbg_clk.common,
+ &bus_psi_clk.common,
+ &bus_pwm_clk.common,
+ &bus_iommu_clk.common,
+ &dram_clk.common,
+ &mbus_dma_clk.common,
+ &mbus_ve_clk.common,
+ &mbus_ce_clk.common,
+ &mbus_ts_clk.common,
+ &mbus_nand_clk.common,
+ &mbus_g2d_clk.common,
+ &bus_dram_clk.common,
+ &nand0_clk.common,
+ &nand1_clk.common,
+ &bus_nand_clk.common,
+ &mmc0_clk.common,
+ &mmc1_clk.common,
+ &mmc2_clk.common,
+ &bus_mmc0_clk.common,
+ &bus_mmc1_clk.common,
+ &bus_mmc2_clk.common,
+ &bus_uart0_clk.common,
+ &bus_uart1_clk.common,
+ &bus_uart2_clk.common,
+ &bus_uart3_clk.common,
+ &bus_uart4_clk.common,
+ &bus_uart5_clk.common,
+ &bus_i2c0_clk.common,
+ &bus_i2c1_clk.common,
+ &bus_i2c2_clk.common,
+ &bus_i2c3_clk.common,
+ &bus_i2c4_clk.common,
+ &spi0_clk.common,
+ &spi1_clk.common,
+ &bus_spi0_clk.common,
+ &bus_spi1_clk.common,
+ &emac_25m_clk.common,
+ &bus_emac0_clk.common,
+ &bus_emac1_clk.common,
+ &ts_clk.common,
+ &bus_ts_clk.common,
+ &bus_ths_clk.common,
+ &spdif_clk.common,
+ &bus_spdif_clk.common,
+ &dmic_clk.common,
+ &bus_dmic_clk.common,
+ &audio_codec_1x_clk.common,
+ &audio_codec_4x_clk.common,
+ &bus_audio_codec_clk.common,
+ &audio_hub_clk.common,
+ &bus_audio_hub_clk.common,
+ &usb_ohci0_clk.common,
+ &usb_phy0_clk.common,
+ &usb_ohci1_clk.common,
+ &usb_phy1_clk.common,
+ &usb_ohci2_clk.common,
+ &usb_phy2_clk.common,
+ &usb_ohci3_clk.common,
+ &usb_phy3_clk.common,
+ &bus_ohci0_clk.common,
+ &bus_ohci1_clk.common,
+ &bus_ohci2_clk.common,
+ &bus_ohci3_clk.common,
+ &bus_ehci0_clk.common,
+ &bus_ehci1_clk.common,
+ &bus_ehci2_clk.common,
+ &bus_ehci3_clk.common,
+ &bus_otg_clk.common,
+ &bus_keyadc_clk.common,
+ &hdmi_clk.common,
+ &hdmi_slow_clk.common,
+ &hdmi_cec_clk.common,
+ &bus_hdmi_clk.common,
+ &bus_tcon_top_clk.common,
+ &tcon_tv0_clk.common,
+ &tcon_tv1_clk.common,
+ &bus_tcon_tv0_clk.common,
+ &bus_tcon_tv1_clk.common,
+ &tve0_clk.common,
+ &bus_tve_top_clk.common,
+ &bus_tve0_clk.common,
+ &hdcp_clk.common,
+ &bus_hdcp_clk.common,
+};
+
+static struct clk_hw_onecell_data sun50i_h616_hw_clks = {
+ .hws = {
+ [CLK_OSC12M] = &osc12M_clk.hw,
+ [CLK_PLL_CPUX] = &pll_cpux_clk.common.hw,
+ [CLK_PLL_DDR0] = &pll_ddr0_clk.common.hw,
+ [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_PERIPH1] = &pll_periph1_clk.common.hw,
+ [CLK_PLL_PERIPH1_2X] = &pll_periph1_2x_clk.hw,
+ [CLK_PLL_GPU] = &pll_gpu_clk.common.hw,
+ [CLK_PLL_VIDEO0] = &pll_video0_clk.common.hw,
+ [CLK_PLL_VIDEO0_4X] = &pll_video0_4x_clk.hw,
+ [CLK_PLL_VIDEO1] = &pll_video1_clk.common.hw,
+ [CLK_PLL_VIDEO1_4X] = &pll_video1_4x_clk.hw,
+ [CLK_PLL_VIDEO2] = &pll_video2_clk.common.hw,
+ [CLK_PLL_VIDEO2_4X] = &pll_video2_4x_clk.hw,
+ [CLK_PLL_VE] = &pll_ve_clk.common.hw,
+ [CLK_PLL_DE] = &pll_de_clk.common.hw,
+ [CLK_PLL_AUDIO_HS] = &pll_audio_hs_clk.common.hw,
+ [CLK_PLL_AUDIO_1X] = &pll_audio_1x_clk.hw,
+ [CLK_PLL_AUDIO_2X] = &pll_audio_2x_clk.hw,
+ [CLK_PLL_AUDIO_4X] = &pll_audio_4x_clk.hw,
+ [CLK_CPUX] = &cpux_clk.common.hw,
+ [CLK_AXI] = &axi_clk.common.hw,
+ [CLK_CPUX_APB] = &cpux_apb_clk.common.hw,
+ [CLK_PSI_AHB1_AHB2] = &psi_ahb1_ahb2_clk.common.hw,
+ [CLK_AHB3] = &ahb3_clk.common.hw,
+ [CLK_APB1] = &apb1_clk.common.hw,
+ [CLK_APB2] = &apb2_clk.common.hw,
+ [CLK_MBUS] = &mbus_clk.common.hw,
+ [CLK_DE] = &de_clk.common.hw,
+ [CLK_BUS_DE] = &bus_de_clk.common.hw,
+ [CLK_DEINTERLACE] = &deinterlace_clk.common.hw,
+ [CLK_BUS_DEINTERLACE] = &bus_deinterlace_clk.common.hw,
+ [CLK_G2D] = &g2d_clk.common.hw,
+ [CLK_BUS_G2D] = &bus_g2d_clk.common.hw,
+ [CLK_GPU0] = &gpu0_clk.common.hw,
+ [CLK_BUS_GPU] = &bus_gpu_clk.common.hw,
+ [CLK_GPU1] = &gpu1_clk.common.hw,
+ [CLK_CE] = &ce_clk.common.hw,
+ [CLK_BUS_CE] = &bus_ce_clk.common.hw,
+ [CLK_VE] = &ve_clk.common.hw,
+ [CLK_BUS_VE] = &bus_ve_clk.common.hw,
+ [CLK_BUS_DMA] = &bus_dma_clk.common.hw,
+ [CLK_BUS_HSTIMER] = &bus_hstimer_clk.common.hw,
+ [CLK_AVS] = &avs_clk.common.hw,
+ [CLK_BUS_DBG] = &bus_dbg_clk.common.hw,
+ [CLK_BUS_PSI] = &bus_psi_clk.common.hw,
+ [CLK_BUS_PWM] = &bus_pwm_clk.common.hw,
+ [CLK_BUS_IOMMU] = &bus_iommu_clk.common.hw,
+ [CLK_DRAM] = &dram_clk.common.hw,
+ [CLK_MBUS_DMA] = &mbus_dma_clk.common.hw,
+ [CLK_MBUS_VE] = &mbus_ve_clk.common.hw,
+ [CLK_MBUS_CE] = &mbus_ce_clk.common.hw,
+ [CLK_MBUS_TS] = &mbus_ts_clk.common.hw,
+ [CLK_MBUS_NAND] = &mbus_nand_clk.common.hw,
+ [CLK_MBUS_G2D] = &mbus_g2d_clk.common.hw,
+ [CLK_BUS_DRAM] = &bus_dram_clk.common.hw,
+ [CLK_NAND0] = &nand0_clk.common.hw,
+ [CLK_NAND1] = &nand1_clk.common.hw,
+ [CLK_BUS_NAND] = &bus_nand_clk.common.hw,
+ [CLK_MMC0] = &mmc0_clk.common.hw,
+ [CLK_MMC1] = &mmc1_clk.common.hw,
+ [CLK_MMC2] = &mmc2_clk.common.hw,
+ [CLK_BUS_MMC0] = &bus_mmc0_clk.common.hw,
+ [CLK_BUS_MMC1] = &bus_mmc1_clk.common.hw,
+ [CLK_BUS_MMC2] = &bus_mmc2_clk.common.hw,
+ [CLK_BUS_UART0] = &bus_uart0_clk.common.hw,
+ [CLK_BUS_UART1] = &bus_uart1_clk.common.hw,
+ [CLK_BUS_UART2] = &bus_uart2_clk.common.hw,
+ [CLK_BUS_UART3] = &bus_uart3_clk.common.hw,
+ [CLK_BUS_UART4] = &bus_uart4_clk.common.hw,
+ [CLK_BUS_UART5] = &bus_uart5_clk.common.hw,
+ [CLK_BUS_I2C0] = &bus_i2c0_clk.common.hw,
+ [CLK_BUS_I2C1] = &bus_i2c1_clk.common.hw,
+ [CLK_BUS_I2C2] = &bus_i2c2_clk.common.hw,
+ [CLK_BUS_I2C3] = &bus_i2c3_clk.common.hw,
+ [CLK_BUS_I2C4] = &bus_i2c4_clk.common.hw,
+ [CLK_SPI0] = &spi0_clk.common.hw,
+ [CLK_SPI1] = &spi1_clk.common.hw,
+ [CLK_BUS_SPI0] = &bus_spi0_clk.common.hw,
+ [CLK_BUS_SPI1] = &bus_spi1_clk.common.hw,
+ [CLK_EMAC_25M] = &emac_25m_clk.common.hw,
+ [CLK_BUS_EMAC0] = &bus_emac0_clk.common.hw,
+ [CLK_BUS_EMAC1] = &bus_emac1_clk.common.hw,
+ [CLK_TS] = &ts_clk.common.hw,
+ [CLK_BUS_TS] = &bus_ts_clk.common.hw,
+ [CLK_BUS_THS] = &bus_ths_clk.common.hw,
+ [CLK_SPDIF] = &spdif_clk.common.hw,
+ [CLK_BUS_SPDIF] = &bus_spdif_clk.common.hw,
+ [CLK_DMIC] = &dmic_clk.common.hw,
+ [CLK_BUS_DMIC] = &bus_dmic_clk.common.hw,
+ [CLK_AUDIO_CODEC_1X] = &audio_codec_1x_clk.common.hw,
+ [CLK_AUDIO_CODEC_4X] = &audio_codec_4x_clk.common.hw,
+ [CLK_BUS_AUDIO_CODEC] = &bus_audio_codec_clk.common.hw,
+ [CLK_AUDIO_HUB] = &audio_hub_clk.common.hw,
+ [CLK_BUS_AUDIO_HUB] = &bus_audio_hub_clk.common.hw,
+ [CLK_USB_OHCI0] = &usb_ohci0_clk.common.hw,
+ [CLK_USB_PHY0] = &usb_phy0_clk.common.hw,
+ [CLK_USB_OHCI1] = &usb_ohci1_clk.common.hw,
+ [CLK_USB_PHY1] = &usb_phy1_clk.common.hw,
+ [CLK_USB_OHCI2] = &usb_ohci2_clk.common.hw,
+ [CLK_USB_PHY2] = &usb_phy2_clk.common.hw,
+ [CLK_USB_OHCI3] = &usb_ohci3_clk.common.hw,
+ [CLK_USB_PHY3] = &usb_phy3_clk.common.hw,
+ [CLK_BUS_OHCI0] = &bus_ohci0_clk.common.hw,
+ [CLK_BUS_OHCI1] = &bus_ohci1_clk.common.hw,
+ [CLK_BUS_OHCI2] = &bus_ohci2_clk.common.hw,
+ [CLK_BUS_OHCI3] = &bus_ohci3_clk.common.hw,
+ [CLK_BUS_EHCI0] = &bus_ehci0_clk.common.hw,
+ [CLK_BUS_EHCI1] = &bus_ehci1_clk.common.hw,
+ [CLK_BUS_EHCI2] = &bus_ehci2_clk.common.hw,
+ [CLK_BUS_EHCI3] = &bus_ehci3_clk.common.hw,
+ [CLK_BUS_OTG] = &bus_otg_clk.common.hw,
+ [CLK_BUS_KEYADC] = &bus_keyadc_clk.common.hw,
+ [CLK_HDMI] = &hdmi_clk.common.hw,
+ [CLK_HDMI_SLOW] = &hdmi_slow_clk.common.hw,
+ [CLK_HDMI_CEC] = &hdmi_cec_clk.common.hw,
+ [CLK_BUS_HDMI] = &bus_hdmi_clk.common.hw,
+ [CLK_BUS_TCON_TOP] = &bus_tcon_top_clk.common.hw,
+ [CLK_TCON_TV0] = &tcon_tv0_clk.common.hw,
+ [CLK_TCON_TV1] = &tcon_tv1_clk.common.hw,
+ [CLK_BUS_TCON_TV0] = &bus_tcon_tv0_clk.common.hw,
+ [CLK_BUS_TCON_TV1] = &bus_tcon_tv1_clk.common.hw,
+ [CLK_TVE0] = &tve0_clk.common.hw,
+ [CLK_BUS_TVE_TOP] = &bus_tve_top_clk.common.hw,
+ [CLK_BUS_TVE0] = &bus_tve0_clk.common.hw,
+ [CLK_HDCP] = &hdcp_clk.common.hw,
+ [CLK_BUS_HDCP] = &bus_hdcp_clk.common.hw,
+ },
+ .num = CLK_NUMBER,
+};
+
+static struct ccu_reset_map sun50i_h616_ccu_resets[] = {
+ [RST_MBUS] = { 0x540, BIT(30) },
+
+ [RST_BUS_DE] = { 0x60c, BIT(16) },
+ [RST_BUS_DEINTERLACE] = { 0x62c, BIT(16) },
+ [RST_BUS_GPU] = { 0x67c, BIT(16) },
+ [RST_BUS_CE] = { 0x68c, BIT(16) },
+ [RST_BUS_VE] = { 0x69c, BIT(16) },
+ [RST_BUS_DMA] = { 0x70c, BIT(16) },
+ [RST_BUS_HSTIMER] = { 0x73c, BIT(16) },
+ [RST_BUS_DBG] = { 0x78c, BIT(16) },
+ [RST_BUS_PSI] = { 0x79c, BIT(16) },
+ [RST_BUS_PWM] = { 0x7ac, BIT(16) },
+ [RST_BUS_IOMMU] = { 0x7bc, BIT(16) },
+ [RST_BUS_DRAM] = { 0x80c, BIT(16) },
+ [RST_BUS_NAND] = { 0x82c, BIT(16) },
+ [RST_BUS_MMC0] = { 0x84c, BIT(16) },
+ [RST_BUS_MMC1] = { 0x84c, BIT(17) },
+ [RST_BUS_MMC2] = { 0x84c, BIT(18) },
+ [RST_BUS_UART0] = { 0x90c, BIT(16) },
+ [RST_BUS_UART1] = { 0x90c, BIT(17) },
+ [RST_BUS_UART2] = { 0x90c, BIT(18) },
+ [RST_BUS_UART3] = { 0x90c, BIT(19) },
+ [RST_BUS_UART4] = { 0x90c, BIT(20) },
+ [RST_BUS_UART5] = { 0x90c, BIT(21) },
+ [RST_BUS_I2C0] = { 0x91c, BIT(16) },
+ [RST_BUS_I2C1] = { 0x91c, BIT(17) },
+ [RST_BUS_I2C2] = { 0x91c, BIT(18) },
+ [RST_BUS_I2C3] = { 0x91c, BIT(19) },
+ [RST_BUS_I2C4] = { 0x91c, BIT(20) },
+ [RST_BUS_SPI0] = { 0x96c, BIT(16) },
+ [RST_BUS_SPI1] = { 0x96c, BIT(17) },
+ [RST_BUS_EMAC0] = { 0x97c, BIT(16) },
+ [RST_BUS_EMAC1] = { 0x97c, BIT(17) },
+ [RST_BUS_TS] = { 0x9bc, BIT(16) },
+ [RST_BUS_THS] = { 0x9fc, BIT(16) },
+ [RST_BUS_SPDIF] = { 0xa2c, BIT(16) },
+ [RST_BUS_DMIC] = { 0xa4c, BIT(16) },
+ [RST_BUS_AUDIO_CODEC] = { 0xa5c, BIT(16) },
+ [RST_BUS_AUDIO_HUB] = { 0xa6c, BIT(16) },
+
+ [RST_USB_PHY0] = { 0xa70, BIT(30) },
+ [RST_USB_PHY1] = { 0xa74, BIT(30) },
+ [RST_USB_PHY2] = { 0xa78, BIT(30) },
+ [RST_USB_PHY3] = { 0xa7c, BIT(30) },
+ [RST_BUS_OHCI0] = { 0xa8c, BIT(16) },
+ [RST_BUS_OHCI1] = { 0xa8c, BIT(17) },
+ [RST_BUS_OHCI2] = { 0xa8c, BIT(18) },
+ [RST_BUS_OHCI3] = { 0xa8c, BIT(19) },
+ [RST_BUS_EHCI0] = { 0xa8c, BIT(20) },
+ [RST_BUS_EHCI1] = { 0xa8c, BIT(21) },
+ [RST_BUS_EHCI2] = { 0xa8c, BIT(22) },
+ [RST_BUS_EHCI3] = { 0xa8c, BIT(23) },
+ [RST_BUS_OTG] = { 0xa8c, BIT(24) },
+ [RST_BUS_KEYADC] = { 0xa9c, BIT(16) },
+
+ [RST_BUS_HDMI] = { 0xb1c, BIT(16) },
+ [RST_BUS_HDMI_SUB] = { 0xb1c, BIT(17) },
+ [RST_BUS_TCON_TOP] = { 0xb5c, BIT(16) },
+ [RST_BUS_TCON_TV0] = { 0xb9c, BIT(16) },
+ [RST_BUS_TCON_TV1] = { 0xb9c, BIT(17) },
+ [RST_BUS_TVE_TOP] = { 0xbbc, BIT(16) },
+ [RST_BUS_TVE0] = { 0xbbc, BIT(17) },
+ [RST_BUS_HDCP] = { 0xc4c, BIT(16) },
+};
+
+static const struct sunxi_ccu_desc sun50i_h616_ccu_desc = {
+ .ccu_clks = sun50i_h616_ccu_clks,
+ .num_ccu_clks = ARRAY_SIZE(sun50i_h616_ccu_clks),
+
+ .hw_clks = &sun50i_h616_hw_clks,
+
+ .resets = sun50i_h616_ccu_resets,
+ .num_resets = ARRAY_SIZE(sun50i_h616_ccu_resets),
+};
+
+static const u32 pll_regs[] = {
+ SUN50I_H616_PLL_CPUX_REG,
+ SUN50I_H616_PLL_DDR0_REG,
+ SUN50I_H616_PLL_DDR1_REG,
+ SUN50I_H616_PLL_PERIPH0_REG,
+ SUN50I_H616_PLL_PERIPH1_REG,
+ SUN50I_H616_PLL_GPU_REG,
+ SUN50I_H616_PLL_VIDEO0_REG,
+ SUN50I_H616_PLL_VIDEO1_REG,
+ SUN50I_H616_PLL_VIDEO2_REG,
+ SUN50I_H616_PLL_VE_REG,
+ SUN50I_H616_PLL_DE_REG,
+ SUN50I_H616_PLL_AUDIO_REG,
+};
+
+static const u32 pll_video_regs[] = {
+ SUN50I_H616_PLL_VIDEO0_REG,
+ SUN50I_H616_PLL_VIDEO1_REG,
+ SUN50I_H616_PLL_VIDEO2_REG,
+};
+
+static const u32 usb2_clk_regs[] = {
+ SUN50I_H616_USB0_CLK_REG,
+ SUN50I_H616_USB1_CLK_REG,
+ SUN50I_H616_USB2_CLK_REG,
+ SUN50I_H616_USB3_CLK_REG,
+};
+
+static void __init sun50i_h616_ccu_setup(struct device_node *node)
+{
+ void __iomem *reg;
+ u32 val;
+ int i;
+
+ reg = of_io_request_and_map(node, 0, of_node_full_name(node));
+ if (IS_ERR(reg)) {
+ pr_err("%pOF: Could not map clock registers\n", node);
+ return;
+ }
+
+ /* Enable the lock bits and the output enable bits on all PLLs */
+ for (i = 0; i < ARRAY_SIZE(pll_regs); i++) {
+ val = readl(reg + pll_regs[i]);
+ val |= BIT(29) | BIT(27);
+ writel(val, reg + pll_regs[i]);
+ }
+
+ /*
+ * Force the output divider of video PLLs to 0.
+ *
+ * See the comment before pll-video0 definition for the reason.
+ */
+ for (i = 0; i < ARRAY_SIZE(pll_video_regs); i++) {
+ val = readl(reg + pll_video_regs[i]);
+ val &= ~BIT(0);
+ writel(val, reg + pll_video_regs[i]);
+ }
+
+ /*
+ * Force OHCI 12M clock sources to 00 (12MHz divided from 48MHz)
+ *
+ * This clock mux is still mysterious, and the code just enforces
+ * it to have a valid clock parent.
+ */
+ for (i = 0; i < ARRAY_SIZE(usb2_clk_regs); i++) {
+ val = readl(reg + usb2_clk_regs[i]);
+ val &= ~GENMASK(25, 24);
+ writel(val, reg + usb2_clk_regs[i]);
+ }
+
+ /*
+ * Force the post-divider of pll-audio to 12 and the output divider
+ * of it to 2, so 24576000 and 22579200 rates can be set exactly.
+ */
+ val = readl(reg + SUN50I_H616_PLL_AUDIO_REG);
+ val &= ~(GENMASK(21, 16) | BIT(0));
+ writel(val | (11 << 16) | BIT(0), reg + SUN50I_H616_PLL_AUDIO_REG);
+
+ /*
+ * First clock parent (osc32K) is unusable for CEC. But since there
+ * is no good way to force parent switch (both run with same frequency),
+ * just set second clock parent here.
+ */
+ val = readl(reg + SUN50I_H616_HDMI_CEC_CLK_REG);
+ val |= BIT(24);
+ writel(val, reg + SUN50I_H616_HDMI_CEC_CLK_REG);
+
+ i = sunxi_ccu_probe(node, reg, &sun50i_h616_ccu_desc);
+ if (i)
+ pr_err("%pOF: probing clocks fails: %d\n", node, i);
+}
+
+CLK_OF_DECLARE(sun50i_h616_ccu, "allwinner,sun50i-h616-ccu",
+ sun50i_h616_ccu_setup);
diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h616.h b/drivers/clk/sunxi-ng/ccu-sun50i-h616.h
new file mode 100644
index 000000000000..dd671b413f22
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-h616.h
@@ -0,0 +1,56 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright 2020 Arm Ltd.
+ */
+
+#ifndef _CCU_SUN50I_H616_H_
+#define _CCU_SUN50I_H616_H_
+
+#include <dt-bindings/clock/sun50i-h616-ccu.h>
+#include <dt-bindings/reset/sun50i-h616-ccu.h>
+
+#define CLK_OSC12M 0
+#define CLK_PLL_CPUX 1
+#define CLK_PLL_DDR0 2
+#define CLK_PLL_DDR1 3
+
+/* PLL_PERIPH0 exported for PRCM */
+
+#define CLK_PLL_PERIPH0_2X 5
+#define CLK_PLL_PERIPH1 6
+#define CLK_PLL_PERIPH1_2X 7
+#define CLK_PLL_GPU 8
+#define CLK_PLL_VIDEO0 9
+#define CLK_PLL_VIDEO0_4X 10
+#define CLK_PLL_VIDEO1 11
+#define CLK_PLL_VIDEO1_4X 12
+#define CLK_PLL_VIDEO2 13
+#define CLK_PLL_VIDEO2_4X 14
+#define CLK_PLL_VE 15
+#define CLK_PLL_DE 16
+#define CLK_PLL_AUDIO_HS 17
+#define CLK_PLL_AUDIO_1X 18
+#define CLK_PLL_AUDIO_2X 19
+#define CLK_PLL_AUDIO_4X 20
+
+/* CPUX clock exported for DVFS */
+
+#define CLK_AXI 22
+#define CLK_CPUX_APB 23
+#define CLK_PSI_AHB1_AHB2 24
+#define CLK_AHB3 25
+
+/* APB1 clock exported for PIO */
+
+#define CLK_APB2 27
+#define CLK_MBUS 28
+
+/* All module clocks and bus gates are exported except DRAM */
+
+#define CLK_DRAM 49
+
+#define CLK_BUS_DRAM 56
+
+#define CLK_NUMBER (CLK_BUS_HDCP + 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
new file mode 100644
index 000000000000..4fc08b0df2f3
--- /dev/null
+++ b/include/dt-bindings/clock/sun50i-h616-ccu.h
@@ -0,0 +1,115 @@
+/* SPDX-License-Identifier: (GPL-2.0+ or MIT) */
+/*
+ * Copyright (C) 2020 Arm Ltd.
+ */
+
+#ifndef _DT_BINDINGS_CLK_SUN50I_H616_H_
+#define _DT_BINDINGS_CLK_SUN50I_H616_H_
+
+#define CLK_PLL_PERIPH0 4
+
+#define CLK_CPUX 21
+
+#define CLK_APB1 26
+
+#define CLK_DE 29
+#define CLK_BUS_DE 30
+#define CLK_DEINTERLACE 31
+#define CLK_BUS_DEINTERLACE 32
+#define CLK_G2D 33
+#define CLK_BUS_G2D 34
+#define CLK_GPU0 35
+#define CLK_BUS_GPU 36
+#define CLK_GPU1 37
+#define CLK_CE 38
+#define CLK_BUS_CE 39
+#define CLK_VE 40
+#define CLK_BUS_VE 41
+#define CLK_BUS_DMA 42
+#define CLK_BUS_HSTIMER 43
+#define CLK_AVS 44
+#define CLK_BUS_DBG 45
+#define CLK_BUS_PSI 46
+#define CLK_BUS_PWM 47
+#define CLK_BUS_IOMMU 48
+
+#define CLK_MBUS_DMA 50
+#define CLK_MBUS_VE 51
+#define CLK_MBUS_CE 52
+#define CLK_MBUS_TS 53
+#define CLK_MBUS_NAND 54
+#define CLK_MBUS_G2D 55
+
+#define CLK_NAND0 57
+#define CLK_NAND1 58
+#define CLK_BUS_NAND 59
+#define CLK_MMC0 60
+#define CLK_MMC1 61
+#define CLK_MMC2 62
+#define CLK_BUS_MMC0 63
+#define CLK_BUS_MMC1 64
+#define CLK_BUS_MMC2 65
+#define CLK_BUS_UART0 66
+#define CLK_BUS_UART1 67
+#define CLK_BUS_UART2 68
+#define CLK_BUS_UART3 69
+#define CLK_BUS_UART4 70
+#define CLK_BUS_UART5 71
+#define CLK_BUS_I2C0 72
+#define CLK_BUS_I2C1 73
+#define CLK_BUS_I2C2 74
+#define CLK_BUS_I2C3 75
+#define CLK_BUS_I2C4 76
+#define CLK_SPI0 77
+#define CLK_SPI1 78
+#define CLK_BUS_SPI0 79
+#define CLK_BUS_SPI1 80
+#define CLK_EMAC_25M 81
+#define CLK_BUS_EMAC0 82
+#define CLK_BUS_EMAC1 83
+#define CLK_TS 84
+#define CLK_BUS_TS 85
+#define CLK_BUS_THS 86
+#define CLK_SPDIF 87
+#define CLK_BUS_SPDIF 88
+#define CLK_DMIC 89
+#define CLK_BUS_DMIC 90
+#define CLK_AUDIO_CODEC_1X 91
+#define CLK_AUDIO_CODEC_4X 92
+#define CLK_BUS_AUDIO_CODEC 93
+#define CLK_AUDIO_HUB 94
+#define CLK_BUS_AUDIO_HUB 95
+#define CLK_USB_OHCI0 96
+#define CLK_USB_PHY0 97
+#define CLK_USB_OHCI1 98
+#define CLK_USB_PHY1 99
+#define CLK_USB_OHCI2 100
+#define CLK_USB_PHY2 101
+#define CLK_USB_OHCI3 102
+#define CLK_USB_PHY3 103
+#define CLK_BUS_OHCI0 104
+#define CLK_BUS_OHCI1 105
+#define CLK_BUS_OHCI2 106
+#define CLK_BUS_OHCI3 107
+#define CLK_BUS_EHCI0 108
+#define CLK_BUS_EHCI1 109
+#define CLK_BUS_EHCI2 110
+#define CLK_BUS_EHCI3 111
+#define CLK_BUS_OTG 112
+#define CLK_BUS_KEYADC 113
+#define CLK_HDMI 114
+#define CLK_HDMI_SLOW 115
+#define CLK_HDMI_CEC 116
+#define CLK_BUS_HDMI 117
+#define CLK_BUS_TCON_TOP 118
+#define CLK_TCON_TV0 119
+#define CLK_TCON_TV1 120
+#define CLK_BUS_TCON_TV0 121
+#define CLK_BUS_TCON_TV1 122
+#define CLK_TVE0 123
+#define CLK_BUS_TVE_TOP 124
+#define CLK_BUS_TVE0 125
+#define CLK_HDCP 126
+#define CLK_BUS_HDCP 127
+
+#endif /* _DT_BINDINGS_CLK_SUN50I_H616_H_ */
diff --git a/include/dt-bindings/reset/sun50i-h616-ccu.h b/include/dt-bindings/reset/sun50i-h616-ccu.h
new file mode 100644
index 000000000000..cb6285a8d128
--- /dev/null
+++ b/include/dt-bindings/reset/sun50i-h616-ccu.h
@@ -0,0 +1,70 @@
+/* SPDX-License-Identifier: (GPL-2.0+ or MIT) */
+/*
+ * Copyright (C) 2020 Arm Ltd.
+ */
+
+#ifndef _DT_BINDINGS_RESET_SUN50I_H616_H_
+#define _DT_BINDINGS_RESET_SUN50I_H616_H_
+
+#define RST_MBUS 0
+#define RST_BUS_DE 1
+#define RST_BUS_DEINTERLACE 2
+#define RST_BUS_GPU 3
+#define RST_BUS_CE 4
+#define RST_BUS_VE 5
+#define RST_BUS_DMA 6
+#define RST_BUS_HSTIMER 7
+#define RST_BUS_DBG 8
+#define RST_BUS_PSI 9
+#define RST_BUS_PWM 10
+#define RST_BUS_IOMMU 11
+#define RST_BUS_DRAM 12
+#define RST_BUS_NAND 13
+#define RST_BUS_MMC0 14
+#define RST_BUS_MMC1 15
+#define RST_BUS_MMC2 16
+#define RST_BUS_UART0 17
+#define RST_BUS_UART1 18
+#define RST_BUS_UART2 19
+#define RST_BUS_UART3 20
+#define RST_BUS_UART4 21
+#define RST_BUS_UART5 22
+#define RST_BUS_I2C0 23
+#define RST_BUS_I2C1 24
+#define RST_BUS_I2C2 25
+#define RST_BUS_I2C3 26
+#define RST_BUS_I2C4 27
+#define RST_BUS_SPI0 28
+#define RST_BUS_SPI1 29
+#define RST_BUS_EMAC0 30
+#define RST_BUS_EMAC1 31
+#define RST_BUS_TS 32
+#define RST_BUS_THS 33
+#define RST_BUS_SPDIF 34
+#define RST_BUS_DMIC 35
+#define RST_BUS_AUDIO_CODEC 36
+#define RST_BUS_AUDIO_HUB 37
+#define RST_USB_PHY0 38
+#define RST_USB_PHY1 39
+#define RST_USB_PHY2 40
+#define RST_USB_PHY3 41
+#define RST_BUS_OHCI0 42
+#define RST_BUS_OHCI1 43
+#define RST_BUS_OHCI2 44
+#define RST_BUS_OHCI3 45
+#define RST_BUS_EHCI0 46
+#define RST_BUS_EHCI1 47
+#define RST_BUS_EHCI2 48
+#define RST_BUS_EHCI3 49
+#define RST_BUS_OTG 50
+#define RST_BUS_HDMI 51
+#define RST_BUS_HDMI_SUB 52
+#define RST_BUS_TCON_TOP 53
+#define RST_BUS_TCON_TV0 54
+#define RST_BUS_TCON_TV1 55
+#define RST_BUS_TVE_TOP 56
+#define RST_BUS_TVE0 57
+#define RST_BUS_HDCP 58
+#define RST_BUS_KEYADC 59
+
+#endif /* _DT_BINDINGS_RESET_SUN50I_H616_H_ */
--
2.17.5

Andre Przywara

unread,
Jan 25, 2021, 10:19:05 AM1/25/21
to Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland, Icenowy Zheng, Rob Herring, Clément Péron, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Lee Jones, devic...@vger.kernel.org
The AXP305 PMIC used in AXP805 seems to be fully compatible to the
AXP805 PMIC, so add the proper chain of compatible strings.

Also at least on one board (Orangepi Zero2) there is no interrupt line
connected to the CPU, so make the "interrupts" property optional.

Signed-off-by: Andre Przywara <andre.p...@arm.com>
---
Documentation/devicetree/bindings/mfd/axp20x.txt | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/mfd/axp20x.txt b/Documentation/devicetree/bindings/mfd/axp20x.txt
index 4991a6415796..4fd748101e3c 100644
--- a/Documentation/devicetree/bindings/mfd/axp20x.txt
+++ b/Documentation/devicetree/bindings/mfd/axp20x.txt
@@ -26,10 +26,10 @@ Required properties:
* "x-powers,axp803"
* "x-powers,axp806"
* "x-powers,axp805", "x-powers,axp806"
+ * "x-powers,axp803", "x-powers,axp805", "x-powers,axp806"
* "x-powers,axp809"
* "x-powers,axp813"
- reg: The I2C slave address or RSB hardware address for the AXP chip
-- interrupts: SoC NMI / GPIO interrupt connected to the PMIC's IRQ pin
- interrupt-controller: The PMIC has its own internal IRQs
- #interrupt-cells: Should be set to 1

@@ -43,6 +43,7 @@ more information:
AXP20x/LDO3: software-based implementation

Optional properties:
+- interrupts: SoC NMI / GPIO interrupt connected to the PMIC's IRQ pin
- x-powers,dcdc-freq: defines the work frequency of DC-DC in KHz
AXP152/20X: range: 750-1875, Default: 1.5 MHz
AXP22X/8XX: range: 1800-4050, Default: 3 MHz
--
2.17.5

Andre Przywara

unread,
Jan 25, 2021, 10:19:10 AM1/25/21
to Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland, Icenowy Zheng, Rob Herring, Clément Péron, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Lee Jones, Dmitry Torokhov, linux...@vger.kernel.org
On at least one board (Orangepi Zero2) the AXP305 PMIC does not have its
interrupt line connected to the CPU (mostly because the H616 SoC does
not feature an NMI pin anymore).
After allowing the AXP driver to proceed without an "interrupts"
property [1], the axp20x-pek driver crashes with a NULL pointer
dereference (see below).

Check for the regmap_irqc member to be not NULL before proceeding with
probe. This gets normally filled by the call to regmap_add_irq_chip(),
which we allow to skip now, when the DT node lacks an interrupt
property.

....
[ 3.843388] sunxi-rsb 7083000.rsb: RSB running at 3000000 Hz
[ 3.849972] axp20x-rsb sunxi-rsb-745: AXP20x variant AXP806 found
[ 3.857971] Unable to handle kernel NULL pointer dereference at
virtual address 00000000000001b8
[ 3.866855] Mem abort info:
[ 3.869691] ESR = 0x96000004
[ 3.872749] EC = 0x25: DABT (current EL), IL = 32 bits
[ 3.878092] SET = 0, FnV = 0
[ 3.881149] EA = 0, S1PTW = 0
[ 3.884309] Data abort info:
[ 3.887210] ISV = 0, ISS = 0x00000004
[ 3.891062] CM = 0, WnR = 0
[ 3.894049] [00000000000001b8] user address but active_mm is swapper
[ 3.900590] Internal error: Oops: 96000004 [#1] PREEMPT SMP
[ 3.906166] Modules linked in:
[ 3.909227] CPU: 2 PID: 34 Comm: kworker/2:1 Not tainted 5.11.0-rc1
[ 3.915925] Hardware name: OrangePi Zero2 (DT)
[ 3.920367] Workqueue: events deferred_probe_work_func
[ 3.925518] pstate: 40000005 (nZcv daif -PAN -UAO -TCO BTYPE=--)
[ 3.931522] pc : regmap_irq_get_virq+0x0/0x48
[ 3.935883] lr : axp20x_pek_probe+0x78/0x200
[ 3.940147] sp : ffff800012fdb450
[ 3.943459] x29: ffff800012fdb450 x28: ffff0000054af340
[ 3.948776] x27: ffff000005534000 x26: ffff000005534810
[ 3.954091] x25: ffff800012883028 x24: 0000000000000002
[ 3.959407] x23: ffff80001157eaf0 x22: ffff000005534810
[ 3.964722] x21: ffff000005534800 x20: ffff0000054b0580
[ 3.970037] x19: 000000000000000b x18: 0000000000000000
[ 3.975353] x17: 0000000000000001 x16: 0000000000000019
[ 3.980668] x15: 000002ce4ea04ae6 x14: 000000000000014f
[ 3.985983] x13: 0000000000000282 x12: 0000000000000030
[ 3.991298] x11: 0000000000000038 x10: 0101010101010101
[ 3.996613] x9 : 0000000000000000 x8 : 7f7f7f7f7f7f7f7f
[ 4.001928] x7 : ff5141435e4a444f x6 : 0000000000000080
[ 4.007243] x5 : 0000000000000000 x4 : 8000000000000000
[ 4.012558] x3 : 0000000000000000 x2 : 0000000000000000
[ 4.017872] x1 : 000000000000000b x0 : 0000000000000000
[ 4.023188] Call trace:
[ 4.025635] regmap_irq_get_virq+0x0/0x48
[ 4.029646] platform_probe+0x68/0xd8
[ 4.033312] really_probe+0xe4/0x3b0
[ 4.036889] driver_probe_device+0x58/0xb8
[ 4.040986] __device_attach_driver+0x84/0xc8
[ 4.045342] bus_for_each_drv+0x78/0xc8
[ 4.049178] __device_attach+0xf0/0x150
[ 4.053013] device_initial_probe+0x14/0x20
[ 4.057196] bus_probe_device+0x9c/0xa8
[ 4.061032] device_add+0x36c/0x7b8
[ 4.064525] platform_device_add+0x100/0x238
[ 4.068796] mfd_add_devices+0x494/0x718
[ 4.072721] axp20x_device_probe+0x70/0x158
[ 4.076904] axp20x_rsb_probe+0x94/0xd0
[ 4.080741] sunxi_rsb_device_probe+0x6c/0x88
[ 4.085102] really_probe+0xe4/0x3b0
[ 4.088679] driver_probe_device+0x58/0xb8
[ 4.092776] __device_attach_driver+0x84/0xc8
[ 4.097132] bus_for_each_drv+0x78/0xc8
[ 4.100967] __device_attach+0xf0/0x150
[ 4.104803] device_initial_probe+0x14/0x20
[ 4.108986] bus_probe_device+0x9c/0xa8
[ 4.112821] device_add+0x36c/0x7b8
[ 4.116313] device_register+0x20/0x30
[ 4.120065] sunxi_rsb_probe+0x4e4/0x608
....

[1] http://lists.infradead.org/pipermail/linux-arm-kernel/2021-January/633392.html

Signed-off-by: Andre Przywara <andre.p...@arm.com>
---
drivers/input/misc/axp20x-pek.c | 4 ++++
1 file changed, 4 insertions(+)

diff --git a/drivers/input/misc/axp20x-pek.c b/drivers/input/misc/axp20x-pek.c
index 9c6386b2af33..abe52ef194ee 100644
--- a/drivers/input/misc/axp20x-pek.c
+++ b/drivers/input/misc/axp20x-pek.c
@@ -309,6 +309,10 @@ static int axp20x_pek_probe(struct platform_device *pdev)

axp20x_pek->axp20x = dev_get_drvdata(pdev->dev.parent);

+ /* In case there is no interrupt line from the AXP towards the CPU. */
+ if (!axp20x_pek->axp20x->regmap_irqc)
+ return -ENODEV;
+
axp20x_pek->irq_dbr = platform_get_irq_byname(pdev, "PEK_DBR");
if (axp20x_pek->irq_dbr < 0)
return axp20x_pek->irq_dbr;
--
2.17.5

Andre Przywara

unread,
Jan 25, 2021, 10:19:10 AM1/25/21
to Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland, Icenowy Zheng, Rob Herring, Clément Péron, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Lee Jones
Currently the AXP chip requires to have its IRQ line connected to some
interrupt controller, and will fail probing when this is not the case.

On a new Allwinner SoC (H616) there is no NMI pin anymore, and at
least one board does not connect the AXP's IRQ pin to anything else,
so the interrupt functionality of the AXP chip is simply not available.

Check whether the interrupt line number returned by the platform code is
valid, before trying to register the irqchip. If not, we skip this
registration, to avoid the driver to bail out completely.

Signed-off-by: Andre Przywara <andre.p...@arm.com>
---
drivers/mfd/axp20x.c | 17 +++++++++++------
1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c
index 3eae04e24ac8..00c163a1e20d 100644
--- a/drivers/mfd/axp20x.c
+++ b/drivers/mfd/axp20x.c
@@ -959,12 +959,17 @@ int axp20x_device_probe(struct axp20x_dev *axp20x)
AXP806_REG_ADDR_EXT_ADDR_SLAVE_MODE);
}

- ret = regmap_add_irq_chip(axp20x->regmap, axp20x->irq,
- IRQF_ONESHOT | IRQF_SHARED | axp20x->irq_flags,
- -1, axp20x->regmap_irq_chip, &axp20x->regmap_irqc);
- if (ret) {
- dev_err(axp20x->dev, "failed to add irq chip: %d\n", ret);
- return ret;
+ /* Only if there is an interrupt line connected towards the CPU. */
+ if (axp20x->irq > 0) {
+ ret = regmap_add_irq_chip(axp20x->regmap, axp20x->irq,
+ IRQF_ONESHOT | IRQF_SHARED | axp20x->irq_flags,
+ -1, axp20x->regmap_irq_chip,
+ &axp20x->regmap_irqc);
+ if (ret) {
+ dev_err(axp20x->dev, "failed to add irq chip: %d\n",
+ ret);
+ return ret;
+ }
}

ret = mfd_add_devices(axp20x->dev, -1, axp20x->cells,
--
2.17.5

Andre Przywara

unread,
Jan 25, 2021, 10:19:13 AM1/25/21
to Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland, Icenowy Zheng, Rob Herring, Clément Péron, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, devic...@vger.kernel.org
The H616 adds a second EMAC clock register. We don't know about the
exact SRAM properties yet, so this gets omitted for now.

Signed-off-by: Andre Przywara <andre.p...@arm.com>
Acked-by: Rob Herring <ro...@kernel.org>
---
.../bindings/sram/allwinner,sun4i-a10-system-control.yaml | 1 +
1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/sram/allwinner,sun4i-a10-system-control.yaml b/Documentation/devicetree/bindings/sram/allwinner,sun4i-a10-system-control.yaml
index b66a07e21d1e..1c426c211e36 100644
--- a/Documentation/devicetree/bindings/sram/allwinner,sun4i-a10-system-control.yaml
+++ b/Documentation/devicetree/bindings/sram/allwinner,sun4i-a10-system-control.yaml
@@ -49,6 +49,7 @@ properties:
- items:
- const: allwinner,suniv-f1c100s-system-control
- const: allwinner,sun4i-a10-system-control
+ - const: allwinner,sun50i-h616-system-control

reg:
maxItems: 1
--
2.17.5

Andre Przywara

unread,
Jan 25, 2021, 10:19:17 AM1/25/21
to Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland, Icenowy Zheng, Rob Herring, Clément Péron, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Guenter Roeck, Wim Van Sebroeck, devic...@vger.kernel.org, linux-w...@vger.kernel.org
Use enums to group all compatible devices together on the way.

Signed-off-by: Andre Przywara <andre.p...@arm.com>
Acked-by: Rob Herring <ro...@kernel.org>
Acked-by: Maxime Ripard <mri...@kernel.org>
Reviewed-by: Guenter Roeck <li...@roeck-us.net>
---
.../bindings/watchdog/allwinner,sun4i-a10-wdt.yaml | 12 +++++-------
1 file changed, 5 insertions(+), 7 deletions(-)

diff --git a/Documentation/devicetree/bindings/watchdog/allwinner,sun4i-a10-wdt.yaml b/Documentation/devicetree/bindings/watchdog/allwinner,sun4i-a10-wdt.yaml
index 5ac607de8be4..9aa3c313c49f 100644
--- a/Documentation/devicetree/bindings/watchdog/allwinner,sun4i-a10-wdt.yaml
+++ b/Documentation/devicetree/bindings/watchdog/allwinner,sun4i-a10-wdt.yaml
@@ -19,13 +19,11 @@ properties:
- const: allwinner,sun4i-a10-wdt
- const: allwinner,sun6i-a31-wdt
- items:
- - const: allwinner,sun50i-a64-wdt
- - const: allwinner,sun6i-a31-wdt
- - items:
- - const: allwinner,sun50i-a100-wdt
- - const: allwinner,sun6i-a31-wdt
- - items:
- - const: allwinner,sun50i-h6-wdt
+ - enum:
+ - allwinner,sun50i-a64-wdt
+ - allwinner,sun50i-a100-wdt
+ - allwinner,sun50i-h6-wdt
+ - allwinner,sun50i-h616-wdt
- const: allwinner,sun6i-a31-wdt
- items:
- const: allwinner,suniv-f1c100s-wdt
--
2.17.5

Andre Przywara

unread,
Jan 25, 2021, 10:19:19 AM1/25/21
to Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland, Icenowy Zheng, Rob Herring, Clément Péron, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Gregory CLEMENT, devic...@vger.kernel.org, linu...@vger.kernel.org
Add the obvious compatible name to the existing I2C binding, and pair
it with the existing A31 fallback compatible string, as the devices
are compatible.

On the way use enums to group all compatible devices together.

Signed-off-by: Andre Przywara <andre.p...@arm.com>
Acked-by: Rob Herring <ro...@kernel.org>
Acked-by: Wolfram Sang <w...@kernel.org>
---
.../bindings/i2c/marvell,mv64xxx-i2c.yaml | 21 +++++++------------
1 file changed, 7 insertions(+), 14 deletions(-)

diff --git a/Documentation/devicetree/bindings/i2c/marvell,mv64xxx-i2c.yaml b/Documentation/devicetree/bindings/i2c/marvell,mv64xxx-i2c.yaml
index 5b5ae402f97a..eb72dd571def 100644
--- a/Documentation/devicetree/bindings/i2c/marvell,mv64xxx-i2c.yaml
+++ b/Documentation/devicetree/bindings/i2c/marvell,mv64xxx-i2c.yaml
@@ -18,21 +18,14 @@ properties:
- const: allwinner,sun4i-a10-i2c
- const: allwinner,sun6i-a31-i2c
- items:
- - const: allwinner,sun8i-a23-i2c
+ - enum:
+ - allwinner,sun8i-a23-i2c
+ - allwinner,sun8i-a83t-i2c
+ - allwinner,sun50i-a64-i2c
+ - allwinner,sun50i-a100-i2c
+ - allwinner,sun50i-h6-i2c
+ - allwinner,sun50i-h616-i2c
- const: allwinner,sun6i-a31-i2c
- - items:
- - const: allwinner,sun8i-a83t-i2c
- - const: allwinner,sun6i-a31-i2c
- - items:
- - const: allwinner,sun50i-a64-i2c
- - const: allwinner,sun6i-a31-i2c
- - items:
- - const: allwinner,sun50i-a100-i2c
- - const: allwinner,sun6i-a31-i2c
- - items:
- - const: allwinner,sun50i-h6-i2c
- - const: allwinner,sun6i-a31-i2c
-
- const: marvell,mv64xxx-i2c
- const: marvell,mv78230-i2c
- const: marvell,mv78230-a0-i2c
--
2.17.5

Andre Przywara

unread,
Jan 25, 2021, 10:19:21 AM1/25/21
to Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland, Icenowy Zheng, Rob Herring, Clément Péron, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com
The Allwinner H616 adds a second EMAC clock register at offset 0x34, for
controlling the second EMAC in this chip.

Allow to extend the regmap in this case, to cover more than the current
4 bytes exported.

Signed-off-by: Andre Przywara <andre.p...@arm.com>
---
drivers/soc/sunxi/sunxi_sram.c | 31 +++++++++++++++++++++++--------
1 file changed, 23 insertions(+), 8 deletions(-)

diff --git a/drivers/soc/sunxi/sunxi_sram.c b/drivers/soc/sunxi/sunxi_sram.c
index d4c7bd59429e..42833e33a96c 100644
--- a/drivers/soc/sunxi/sunxi_sram.c
+++ b/drivers/soc/sunxi/sunxi_sram.c
@@ -283,7 +283,7 @@ int sunxi_sram_release(struct device *dev)
EXPORT_SYMBOL(sunxi_sram_release);

struct sunxi_sramc_variant {
- bool has_emac_clock;
+ int num_emac_clocks;
};

static const struct sunxi_sramc_variant sun4i_a10_sramc_variant = {
@@ -291,20 +291,31 @@ static const struct sunxi_sramc_variant sun4i_a10_sramc_variant = {
};

static const struct sunxi_sramc_variant sun8i_h3_sramc_variant = {
- .has_emac_clock = true,
+ .num_emac_clocks = 1,
};

static const struct sunxi_sramc_variant sun50i_a64_sramc_variant = {
- .has_emac_clock = true,
+ .num_emac_clocks = 1,
+};
+
+static const struct sunxi_sramc_variant sun50i_h616_sramc_variant = {
+ .num_emac_clocks = 2,
};

#define SUNXI_SRAM_EMAC_CLOCK_REG 0x30
static bool sunxi_sram_regmap_accessible_reg(struct device *dev,
unsigned int reg)
{
- if (reg == SUNXI_SRAM_EMAC_CLOCK_REG)
- return true;
- return false;
+ const struct sunxi_sramc_variant *variant;
+
+ variant = of_device_get_match_data(dev);
+
+ if (reg < SUNXI_SRAM_EMAC_CLOCK_REG)
+ return false;
+ if (reg > SUNXI_SRAM_EMAC_CLOCK_REG + variant->num_emac_clocks * 4)
+ return false;
+
+ return true;
}

static struct regmap_config sunxi_sram_emac_clock_regmap = {
@@ -312,7 +323,7 @@ static struct regmap_config sunxi_sram_emac_clock_regmap = {
.val_bits = 32,
.reg_stride = 4,
/* last defined register */
- .max_register = SUNXI_SRAM_EMAC_CLOCK_REG,
+ .max_register = SUNXI_SRAM_EMAC_CLOCK_REG + 4,
/* other devices have no business accessing other registers */
.readable_reg = sunxi_sram_regmap_accessible_reg,
.writeable_reg = sunxi_sram_regmap_accessible_reg,
@@ -343,7 +354,7 @@ static int sunxi_sram_probe(struct platform_device *pdev)
if (!d)
return -ENOMEM;

- if (variant->has_emac_clock) {
+ if (variant->num_emac_clocks > 0) {
emac_clock = devm_regmap_init_mmio(&pdev->dev, base,
&sunxi_sram_emac_clock_regmap);

@@ -387,6 +398,10 @@ static const struct of_device_id sunxi_sram_dt_match[] = {
.compatible = "allwinner,sun50i-h5-system-control",
.data = &sun50i_a64_sramc_variant,
},
+ {
+ .compatible = "allwinner,sun50i-h616-system-control",
+ .data = &sun50i_h616_sramc_variant,
+ },
{ },
};
MODULE_DEVICE_TABLE(of, sunxi_sram_dt_match);
--
2.17.5

Andre Przywara

unread,
Jan 25, 2021, 10:19:22 AM1/25/21
to Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland, Icenowy Zheng, Rob Herring, Clément Péron, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Mauro Carvalho Chehab, devic...@vger.kernel.org, linux...@vger.kernel.org
Add the obvious compatible name to the existing IR binding, and pair
it with the existing A31 fallback compatible string, as the devices
are compatible.

On the way use enums to group all compatible devices together.

Signed-off-by: Andre Przywara <andre.p...@arm.com>
Acked-by: Rob Herring <ro...@kernel.org>
---
.../bindings/media/allwinner,sun4i-a10-ir.yaml | 16 ++++++----------
1 file changed, 6 insertions(+), 10 deletions(-)

diff --git a/Documentation/devicetree/bindings/media/allwinner,sun4i-a10-ir.yaml b/Documentation/devicetree/bindings/media/allwinner,sun4i-a10-ir.yaml
index 5fa19d4aeaf3..6d8395d6bca0 100644
--- a/Documentation/devicetree/bindings/media/allwinner,sun4i-a10-ir.yaml
+++ b/Documentation/devicetree/bindings/media/allwinner,sun4i-a10-ir.yaml
@@ -20,16 +20,12 @@ properties:
- const: allwinner,sun5i-a13-ir
- const: allwinner,sun6i-a31-ir
- items:
- - const: allwinner,sun8i-a83t-ir
- - const: allwinner,sun6i-a31-ir
- - items:
- - const: allwinner,sun8i-r40-ir
- - const: allwinner,sun6i-a31-ir
- - items:
- - const: allwinner,sun50i-a64-ir
- - const: allwinner,sun6i-a31-ir
- - items:
- - const: allwinner,sun50i-h6-ir
+ - enum:
+ - allwinner,sun8i-a83t-ir
+ - allwinner,sun8i-r40-ir
+ - allwinner,sun50i-a64-ir
+ - allwinner,sun50i-h6-ir
+ - allwinner,sun50i-h616-ir
- const: allwinner,sun6i-a31-ir

reg:
--
2.17.5

Andre Przywara

unread,
Jan 25, 2021, 10:19:24 AM1/25/21
to Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland, Icenowy Zheng, Rob Herring, Clément Péron, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Alessandro Zummo, Alexandre Belloni, devic...@vger.kernel.org, linu...@vger.kernel.org
Add the obvious compatible name to the existing RTC binding, and pair
it with the existing H6 fallback compatible string, as the devices are
compatible.

Signed-off-by: Andre Przywara <andre.p...@arm.com>
Acked-by: Rob Herring <ro...@kernel.org>
---
.../devicetree/bindings/rtc/allwinner,sun6i-a31-rtc.yaml | 3 +++
1 file changed, 3 insertions(+)

diff --git a/Documentation/devicetree/bindings/rtc/allwinner,sun6i-a31-rtc.yaml b/Documentation/devicetree/bindings/rtc/allwinner,sun6i-a31-rtc.yaml
index b1b0ee769b71..4193e5813344 100644
--- a/Documentation/devicetree/bindings/rtc/allwinner,sun6i-a31-rtc.yaml
+++ b/Documentation/devicetree/bindings/rtc/allwinner,sun6i-a31-rtc.yaml
@@ -26,6 +26,9 @@ properties:
- const: allwinner,sun50i-a64-rtc
- const: allwinner,sun8i-h3-rtc
- const: allwinner,sun50i-h6-rtc
+ - items:
+ - const: allwinner,sun50i-h616-rtc
+ - const: allwinner,sun50i-h6-rtc

Andre Przywara

unread,
Jan 25, 2021, 10:19:28 AM1/25/21
to Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland, Icenowy Zheng, Rob Herring, Clément Péron, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Mark Brown, devic...@vger.kernel.org, linu...@vger.kernel.org
Add the obvious compatible name to the existing SPI binding, and pair
it with the existing H3 fallback compatible string, as the devices are
compatible.

Signed-off-by: Andre Przywara <andre.p...@arm.com>
Acked-by: Rob Herring <ro...@kernel.org>
---
.../devicetree/bindings/spi/allwinner,sun6i-a31-spi.yaml | 1 +
1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/spi/allwinner,sun6i-a31-spi.yaml b/Documentation/devicetree/bindings/spi/allwinner,sun6i-a31-spi.yaml
index 7866a655d81c..908248260afa 100644
--- a/Documentation/devicetree/bindings/spi/allwinner,sun6i-a31-spi.yaml
+++ b/Documentation/devicetree/bindings/spi/allwinner,sun6i-a31-spi.yaml
@@ -25,6 +25,7 @@ properties:
- enum:
- allwinner,sun8i-r40-spi
- allwinner,sun50i-h6-spi
+ - allwinner,sun50i-h616-spi
- const: allwinner,sun8i-h3-spi

reg:
--
2.17.5

Andre Przywara

unread,
Jan 25, 2021, 10:19:30 AM1/25/21
to Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland, Icenowy Zheng, Rob Herring, Clément Péron, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Alexandre Torgue, David S . Miller, Giuseppe Cavallaro, Jakub Kicinski, Jose Abreu, net...@vger.kernel.org
The Allwinner H616 SoC has two EMAC controllers, with the second one
being tied to the internal PHY, but also using a separate EMAC clock
register.

To tell the driver about which clock register to use, we add a parameter
to our syscon phandle. The driver will use this value as an index into
the regmap, so that we can address more than the first register, if
needed.

Signed-off-by: Andre Przywara <andre.p...@arm.com>
---
drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
index 58e0511badba..c7951790ed98 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
@@ -1124,11 +1124,13 @@ static int sun8i_dwmac_probe(struct platform_device *pdev)
struct stmmac_resources stmmac_res;
struct sunxi_priv_data *gmac;
struct device *dev = &pdev->dev;
+ struct reg_field syscon_field;
phy_interface_t interface;
int ret;
struct stmmac_priv *priv;
struct net_device *ndev;
struct regmap *regmap;
+ u32 syscon_idx = 0;

ret = stmmac_get_platform_resources(pdev, &stmmac_res);
if (ret)
@@ -1190,8 +1192,12 @@ static int sun8i_dwmac_probe(struct platform_device *pdev)
return ret;
}

- gmac->regmap_field = devm_regmap_field_alloc(dev, regmap,
- *gmac->variant->syscon_field);
+ syscon_field = *gmac->variant->syscon_field;
+ ret = of_property_read_u32_index(pdev->dev.of_node, "syscon", 1,
+ &syscon_idx);
+ if (!ret)
+ syscon_field.reg += syscon_idx * sizeof(u32);
+ gmac->regmap_field = devm_regmap_field_alloc(dev, regmap, syscon_field);
if (IS_ERR(gmac->regmap_field)) {
ret = PTR_ERR(gmac->regmap_field);
dev_err(dev, "Unable to map syscon register: %d\n", ret);
@@ -1263,6 +1269,8 @@ static const struct of_device_id sun8i_dwmac_match[] = {
.data = &emac_variant_a64 },
{ .compatible = "allwinner,sun50i-h6-emac",
.data = &emac_variant_h6 },
+ { .compatible = "allwinner,sun50i-h616-emac",
+ .data = &emac_variant_h6 },
{ }
};
MODULE_DEVICE_TABLE(of, sun8i_dwmac_match);
--
2.17.5

Andre Przywara

unread,
Jan 25, 2021, 10:19:31 AM1/25/21
to Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland, Icenowy Zheng, Rob Herring, Clément Péron, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Kishon Vijay Abraham I, Vinod Koul
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, to cover newer SoCs: The A100 and H616 use a different
bit for the SIDDQ control.

Signed-off-by: Andre Przywara <andre.p...@arm.com>
Acked-by: Maxime Ripard <mri...@kernel.org>
---
drivers/phy/allwinner/phy-sun4i-usb.c | 29 +++++++++++----------------
1 file changed, 12 insertions(+), 17 deletions(-)

diff --git a/drivers/phy/allwinner/phy-sun4i-usb.c b/drivers/phy/allwinner/phy-sun4i-usb.c
index 788dd5cdbb7d..539209fe3468 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)

@@ -115,9 +115,9 @@ struct sun4i_usb_phy_cfg {
int hsic_index;
enum sun4i_usb_phy_type type;
u32 disc_thresh;
+ u32 hci_phy_ctl_siddq;
u8 phyctl_offset;
bool dedicated_clocks;
- bool enable_pmu_unk1;
bool phy0_dual_route;
int missing_phys;
};
@@ -288,6 +288,12 @@ static int sun4i_usb_phy_init(struct phy *_phy)
return ret;
}

+ if (phy->pmu && data->cfg->hci_phy_ctl_siddq) {
+ val = readl(phy->pmu + REG_HCI_PHY_CTL);
+ val &= ~data->cfg->hci_phy_ctl_siddq;
+ 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 +303,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 +864,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 +872,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 +880,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 +888,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 +896,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 +904,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 +920,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_siddq = BIT(1),
.phy0_dual_route = true,
};

@@ -935,7 +930,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_siddq = BIT(1),
.phy0_dual_route = true,
};

@@ -945,7 +940,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_siddq = BIT(1),
.phy0_dual_route = true,
};

@@ -955,7 +950,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_siddq = BIT(1),
.phy0_dual_route = true,
};

--
2.17.5

Andre Przywara

unread,
Jan 25, 2021, 10:19:34 AM1/25/21
to Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland, Icenowy Zheng, Rob Herring, Clément Péron, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Kishon Vijay Abraham I, Vinod Koul, devic...@vger.kernel.org
The H616 has four PHYs as the H3, along with their respective clock
gates and resets, so the property description is identical.

However the PHYs itself need some special bits, so we need a new
compatible string for it.

Signed-off-by: Andre Przywara <andre.p...@arm.com>
---
.../devicetree/bindings/phy/allwinner,sun8i-h3-usb-phy.yaml | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/phy/allwinner,sun8i-h3-usb-phy.yaml b/Documentation/devicetree/bindings/phy/allwinner,sun8i-h3-usb-phy.yaml
index 60c344585276..b76a1803dc5f 100644
--- a/Documentation/devicetree/bindings/phy/allwinner,sun8i-h3-usb-phy.yaml
+++ b/Documentation/devicetree/bindings/phy/allwinner,sun8i-h3-usb-phy.yaml
@@ -15,7 +15,9 @@ properties:
const: 1

compatible:
- const: allwinner,sun8i-h3-usb-phy
+ enum:
+ - allwinner,sun8i-h3-usb-phy
+ - allwinner,sun50i-h616-usb-phy

reg:
items:
--
2.17.5

Andre Przywara

unread,
Jan 25, 2021, 10:19:38 AM1/25/21
to Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland, Icenowy Zheng, Rob Herring, Clément Péron, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Kishon Vijay Abraham I, Vinod Koul, Greg Kroah-Hartman, devic...@vger.kernel.org
The H616 MUSB peripheral is presumably compatible to the H3 one.

Signed-off-by: Andre Przywara <andre.p...@arm.com>
Acked-by: Maxime Ripard <mri...@kernel.org>
---
.../devicetree/bindings/usb/allwinner,sun4i-a10-musb.yaml | 3 +++
1 file changed, 3 insertions(+)

diff --git a/Documentation/devicetree/bindings/usb/allwinner,sun4i-a10-musb.yaml b/Documentation/devicetree/bindings/usb/allwinner,sun4i-a10-musb.yaml
index d9207bf9d894..ad8983debeba 100644
--- a/Documentation/devicetree/bindings/usb/allwinner,sun4i-a10-musb.yaml
+++ b/Documentation/devicetree/bindings/usb/allwinner,sun4i-a10-musb.yaml
@@ -22,6 +22,9 @@ properties:
- allwinner,sun8i-a83t-musb
- allwinner,sun50i-h6-musb
- const: allwinner,sun8i-a33-musb
+ - items:
+ - const: allwinner,sun50i-h616-musb
+ - const: allwinner,sun8i-h3-musb

Andre Przywara

unread,
Jan 25, 2021, 10:19:41 AM1/25/21
to Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland, Icenowy Zheng, Rob Herring, Clément Péron, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Kishon Vijay Abraham I, Vinod Koul
The USB PHY used in the Allwinner H616 SoC inherits some traits from its
various predecessors: it has four full PHYs like the H3, needs some
extra bits to be set like the H6, and clears a different bit in the
PMU_UNK1 register like the A100.

Name all those properties in a new config struct and assign a new
compatible name to it.

Signed-off-by: Andre Przywara <andre.p...@arm.com>
Acked-by: Maxime Ripard <mri...@kernel.org>
---
drivers/phy/allwinner/phy-sun4i-usb.c | 11 +++++++++++
1 file changed, 11 insertions(+)

diff --git a/drivers/phy/allwinner/phy-sun4i-usb.c b/drivers/phy/allwinner/phy-sun4i-usb.c
index 539209fe3468..e71d6b8ccf16 100644
--- a/drivers/phy/allwinner/phy-sun4i-usb.c
+++ b/drivers/phy/allwinner/phy-sun4i-usb.c
@@ -964,6 +964,16 @@ static const struct sun4i_usb_phy_cfg sun50i_h6_cfg = {
.missing_phys = BIT(1) | BIT(2),
};

+static const struct sun4i_usb_phy_cfg sun50i_h616_cfg = {
+ .num_phys = 4,
+ .type = sun50i_h6_phy,
+ .disc_thresh = 3,
+ .phyctl_offset = REG_PHYCTL_A33,
+ .dedicated_clocks = true,
+ .phy0_dual_route = true,
+ .hci_phy_ctl_siddq = BIT(3),
+};
+
static const struct of_device_id sun4i_usb_phy_of_match[] = {
{ .compatible = "allwinner,sun4i-a10-usb-phy", .data = &sun4i_a10_cfg },
{ .compatible = "allwinner,sun5i-a13-usb-phy", .data = &sun5i_a13_cfg },
@@ -978,6 +988,7 @@ static const struct of_device_id sun4i_usb_phy_of_match[] = {
{ .compatible = "allwinner,sun50i-a64-usb-phy",
.data = &sun50i_a64_cfg},
{ .compatible = "allwinner,sun50i-h6-usb-phy", .data = &sun50i_h6_cfg },
+ { .compatible = "allwinner,sun50i-h616-usb-phy", .data = &sun50i_h616_cfg },
{ },
};
MODULE_DEVICE_TABLE(of, sun4i_usb_phy_of_match);
--
2.17.5

Andre Przywara

unread,
Jan 25, 2021, 10:19:45 AM1/25/21
to Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland, Icenowy Zheng, Rob Herring, Clément Péron, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, devic...@vger.kernel.org
This (relatively) new SoC is similar to the H6, but drops the (broken)
PCIe support and the USB 3.0 controller. It also gets the management
controller removed, which in turn removes *some*, but not all of the
devices formerly dedicated to the ARISC (CPUS).
There does not seem to be an extra interrupt controller anymore, also
it lacks the corresponding NMI pin, so no interrupts for the PMIC.

Signed-off-by: Andre Przywara <andre.p...@arm.com>
---
.../arm64/boot/dts/allwinner/sun50i-h616.dtsi | 750 ++++++++++++++++++
1 file changed, 750 insertions(+)
create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi

diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi
new file mode 100644
index 000000000000..f74713e54a66
--- /dev/null
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi
@@ -0,0 +1,750 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+// Copyright (C) 2020 Arm Ltd.
+// based on the H6 dtsi, which is:
+// Copyright (C) 2017 Icenowy Zheng <ice...@aosc.io>
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/clock/sun50i-h616-ccu.h>
+#include <dt-bindings/clock/sun50i-h6-r-ccu.h>
+#include <dt-bindings/reset/sun50i-h616-ccu.h>
+#include <dt-bindings/reset/sun50i-h6-r-ccu.h>
+
+/ {
+ interrupt-parent = <&gic>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu0: cpu@0 {
+ compatible = "arm,cortex-a53";
+ device_type = "cpu";
+ reg = <0>;
+ enable-method = "psci";
+ clocks = <&ccu CLK_CPUX>;
+ };
+
+ cpu1: cpu@1 {
+ compatible = "arm,cortex-a53";
+ device_type = "cpu";
+ reg = <1>;
+ enable-method = "psci";
+ clocks = <&ccu CLK_CPUX>;
+ };
+
+ cpu2: cpu@2 {
+ compatible = "arm,cortex-a53";
+ device_type = "cpu";
+ reg = <2>;
+ enable-method = "psci";
+ clocks = <&ccu CLK_CPUX>;
+ };
+
+ cpu3: cpu@3 {
+ compatible = "arm,cortex-a53";
+ device_type = "cpu";
+ reg = <3>;
+ enable-method = "psci";
+ clocks = <&ccu CLK_CPUX>;
+ };
+ };
+
+ reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ /* 512KiB reserved for ARM Trusted Firmware (BL31) */
+ secmon_reserved: secmon@40000000 {
+ reg = <0x0 0x40000000 0x0 0x80000>;
+ no-map;
+ };
+ };
+
+ osc24M: osc24M_clk {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <24000000>;
+ clock-output-names = "osc24M";
+ };
+
+ pmu {
+ compatible = "arm,cortex-a53-pmu";
+ interrupts = <GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 141 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 142 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-affinity = <&cpu0>, <&cpu1>, <&cpu2>, <&cpu3>;
+ };
+
+ psci {
+ compatible = "arm,psci-0.2";
+ method = "smc";
+ };
+
+ timer {
+ compatible = "arm,armv8-timer";
+ arm,no-tick-in-suspend;
+ interrupts = <GIC_PPI 13
+ (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>,
+ <GIC_PPI 14
+ (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>,
+ <GIC_PPI 11
+ (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>,
+ <GIC_PPI 10
+ (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
+ };
+
+ soc {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0x0 0x0 0x0 0x40000000>;
+
+ syscon: syscon@3000000 {
+ compatible = "allwinner,sun50i-h616-system-control";
+ reg = <0x03000000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ sram_c: sram@28000 {
+ compatible = "mmio-sram";
+ reg = <0x00028000 0x30000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 0x00028000 0x30000>;
+ };
+ };
+
+ ccu: clock@3001000 {
+ compatible = "allwinner,sun50i-h616-ccu";
+ reg = <0x03001000 0x1000>;
+ clocks = <&osc24M>, <&rtc 0>, <&rtc 2>;
+ clock-names = "hosc", "losc", "iosc";
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ };
+
+ watchdog: watchdog@30090a0 {
+ compatible = "allwinner,sun50i-h616-wdt",
+ "allwinner,sun6i-a31-wdt";
+ reg = <0x030090a0 0x20>;
+ interrupts = <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&osc24M>;
+ status = "okay";
+ };
+
+ pio: pinctrl@300b000 {
+ compatible = "allwinner,sun50i-h616-pinctrl";
+ reg = <0x0300b000 0x400>;
+ interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_APB1>, <&osc24M>, <&rtc 0>;
+ clock-names = "apb", "hosc", "losc";
+ gpio-controller;
+ #gpio-cells = <3>;
+ interrupt-controller;
+ #interrupt-cells = <3>;
+
+ ext_rgmii_pins: rgmii-pins {
+ pins = "PI0", "PI1", "PI2", "PI3", "PI4",
+ "PI5", "PI7", "PI8", "PI9", "PI10",
+ "PI11", "PI12", "PI13", "PI14", "PI15",
+ "PI16";
+ function = "emac0";
+ drive-strength = <40>;
+ };
+
+ i2c0_pins: i2c0-pins {
+ pins = "PI6", "PI7";
+ function = "i2c0";
+ };
+
+ i2c3_ph_pins: i2c3-ph-pins {
+ pins = "PH4", "PH5";
+ function = "i2c3";
+ };
+
+ ir_rx_pin: ir_rx_pin {
+ pins = "PH10";
+ function = "ir_rx";
+ };
+
+ mmc0_pins: mmc0-pins {
+ pins = "PF0", "PF1", "PF2", "PF3",
+ "PF4", "PF5";
+ function = "mmc0";
+ drive-strength = <30>;
+ bias-pull-up;
+ };
+
+ mmc1_pins: mmc1-pins {
+ pins = "PG0", "PG1", "PG2", "PG3",
+ "PG4", "PG5";
+ function = "mmc1";
+ drive-strength = <30>;
+ bias-pull-up;
+ };
+
+ mmc2_pins: mmc2-pins {
+ pins = "PC0", "PC1", "PC5", "PC6",
+ "PC8", "PC9", "PC10", "PC11",
+ "PC13", "PC14", "PC15", "PC16";
+ function = "mmc2";
+ drive-strength = <30>;
+ bias-pull-up;
+ };
+
+ spi0_pins: spi0-pins {
+ pins = "PC0", "PC2", "PC3", "PC4";
+ function = "spi0";
+ };
+
+ spi1_pins: spi1-pins {
+ pins = "PH6", "PH7", "PH8";
+ function = "spi1";
+ };
+
+ spi1_cs_pin: spi1-cs-pin {
+ pins = "PH5";
+ function = "spi1";
+ };
+
+ uart0_ph_pins: uart0-ph-pins {
+ pins = "PH0", "PH1";
+ function = "uart0";
+ };
+
+ uart1_pins: uart1-pins {
+ pins = "PG6", "PG7";
+ function = "uart1";
+ };
+
+ uart1_rts_cts_pins: uart1-rts-cts-pins {
+ pins = "PG8", "PG9";
+ function = "uart1";
+ };
+ };
+
+ gic: interrupt-controller@3021000 {
+ compatible = "arm,gic-400";
+ reg = <0x03021000 0x1000>,
+ <0x03022000 0x2000>,
+ <0x03024000 0x2000>,
+ <0x03026000 0x2000>;
+ interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
+ interrupt-controller;
+ #interrupt-cells = <3>;
+ };
+
+ mmc0: mmc@4020000 {
+ compatible = "allwinner,sun50i-h616-mmc",
+ "allwinner,sun50i-a100-mmc";
+ reg = <0x04020000 0x1000>;
+ clocks = <&ccu CLK_BUS_MMC0>, <&ccu CLK_MMC0>;
+ clock-names = "ahb", "mmc";
+ resets = <&ccu RST_BUS_MMC0>;
+ reset-names = "ahb";
+ interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&mmc0_pins>;
+ status = "disabled";
+ cap-sd-highspeed;
+ cap-mmc-highspeed;
+ mmc-ddr-3_3v;
+ mmc-ddr-1_8v;
+ cap-sdio-irq;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ mmc1: mmc@4021000 {
+ compatible = "allwinner,sun50i-h616-mmc",
+ "allwinner,sun50i-a100-mmc";
+ reg = <0x04021000 0x1000>;
+ clocks = <&ccu CLK_BUS_MMC1>, <&ccu CLK_MMC1>;
+ clock-names = "ahb", "mmc";
+ resets = <&ccu RST_BUS_MMC1>;
+ reset-names = "ahb";
+ interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&mmc1_pins>;
+ status = "disabled";
+ cap-sd-highspeed;
+ cap-mmc-highspeed;
+ mmc-ddr-3_3v;
+ mmc-ddr-1_8v;
+ cap-sdio-irq;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ mmc2: mmc@4022000 {
+ compatible = "allwinner,sun50i-h616-emmc",
+ "allwinner,sun50i-a100-emmc";
+ reg = <0x04022000 0x1000>;
+ clocks = <&ccu CLK_BUS_MMC2>, <&ccu CLK_MMC2>;
+ clock-names = "ahb", "mmc";
+ resets = <&ccu RST_BUS_MMC2>;
+ reset-names = "ahb";
+ interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&mmc2_pins>;
+ status = "disabled";
+ cap-sd-highspeed;
+ cap-mmc-highspeed;
+ mmc-ddr-3_3v;
+ mmc-ddr-1_8v;
+ cap-sdio-irq;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ uart0: serial@5000000 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x05000000 0x400>;
+ interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ clocks = <&ccu CLK_BUS_UART0>;
+ resets = <&ccu RST_BUS_UART0>;
+ status = "disabled";
+ };
+
+ uart1: serial@5000400 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x05000400 0x400>;
+ interrupts = <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ clocks = <&ccu CLK_BUS_UART1>;
+ resets = <&ccu RST_BUS_UART1>;
+ status = "disabled";
+ };
+
+ uart2: serial@5000800 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x05000800 0x400>;
+ interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ clocks = <&ccu CLK_BUS_UART2>;
+ resets = <&ccu RST_BUS_UART2>;
+ status = "disabled";
+ };
+
+ uart3: serial@5000c00 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x05000c00 0x400>;
+ interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ clocks = <&ccu CLK_BUS_UART3>;
+ resets = <&ccu RST_BUS_UART3>;
+ status = "disabled";
+ };
+
+ uart4: serial@5001000 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x05001000 0x400>;
+ interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ clocks = <&ccu CLK_BUS_UART4>;
+ resets = <&ccu RST_BUS_UART4>;
+ status = "disabled";
+ };
+
+ uart5: serial@5001400 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x05001400 0x400>;
+ interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ clocks = <&ccu CLK_BUS_UART5>;
+ resets = <&ccu RST_BUS_UART5>;
+ status = "disabled";
+ };
+
+ i2c0: i2c@5002000 {
+ compatible = "allwinner,sun50i-h616-i2c",
+ "allwinner,sun6i-a31-i2c";
+ reg = <0x05002000 0x400>;
+ interrupts = <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_I2C0>;
+ resets = <&ccu RST_BUS_I2C0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c0_pins>;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ i2c1: i2c@5002400 {
+ compatible = "allwinner,sun50i-h616-i2c",
+ "allwinner,sun6i-a31-i2c";
+ reg = <0x05002400 0x400>;
+ interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_I2C1>;
+ resets = <&ccu RST_BUS_I2C1>;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ i2c2: i2c@5002800 {
+ compatible = "allwinner,sun50i-h616-i2c",
+ "allwinner,sun6i-a31-i2c";
+ reg = <0x05002800 0x400>;
+ interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_I2C2>;
+ resets = <&ccu RST_BUS_I2C2>;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ i2c3: i2c@5002c00 {
+ compatible = "allwinner,sun50i-h616-i2c",
+ "allwinner,sun6i-a31-i2c";
+ reg = <0x05002c00 0x400>;
+ interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_I2C3>;
+ resets = <&ccu RST_BUS_I2C3>;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ i2c4: i2c@5003000 {
+ compatible = "allwinner,sun50i-h616-i2c",
+ "allwinner,sun6i-a31-i2c";
+ reg = <0x05003000 0x400>;
+ interrupts = <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_I2C4>;
+ resets = <&ccu RST_BUS_I2C4>;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ spi0: spi@5010000 {
+ compatible = "allwinner,sun50i-h616-spi",
+ "allwinner,sun8i-h3-spi";
+ reg = <0x05010000 0x1000>;
+ interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_SPI0>, <&ccu CLK_SPI0>;
+ clock-names = "ahb", "mod";
+ resets = <&ccu RST_BUS_SPI0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi0_pins>;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ spi1: spi@5011000 {
+ compatible = "allwinner,sun50i-h616-spi",
+ "allwinner,sun8i-h3-spi";
+ reg = <0x05011000 0x1000>;
+ interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_SPI1>, <&ccu CLK_SPI1>;
+ clock-names = "ahb", "mod";
+ resets = <&ccu RST_BUS_SPI1>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi1_pins>;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ emac0: ethernet@5020000 {
+ compatible = "allwinner,sun50i-h616-emac",
+ "allwinner,sun50i-a64-emac";
+ syscon = <&syscon>;
+ reg = <0x05020000 0x10000>;
+ interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "macirq";
+ resets = <&ccu RST_BUS_EMAC0>;
+ reset-names = "stmmaceth";
+ clocks = <&ccu CLK_BUS_EMAC0>;
+ clock-names = "stmmaceth";
+ status = "disabled";
+
+ mdio0: mdio {
+ compatible = "snps,dwmac-mdio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+ };
+
+ emac1: ethernet@5030000 {
+ compatible = "allwinner,sun50i-h616-emac";
+ syscon = <&syscon 1>;
+ reg = <0x05030000 0x10000>;
+ interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "macirq";
+ resets = <&ccu RST_BUS_EMAC1>;
+ reset-names = "stmmaceth";
+ clocks = <&ccu CLK_BUS_EMAC1>;
+ clock-names = "stmmaceth";
+ status = "disabled";
+
+ mdio1: mdio {
+ compatible = "snps,dwmac-mdio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+ };
+
+ 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>;
+ clock-names = "usb0_phy",
+ "usb1_phy",
+ "usb2_phy",
+ "usb3_phy";
+ 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>, <&usbphy 2>;
+ 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>, <&usbphy 2>;
+ 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>, <&usbphy 2>;
+ 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>, <&usbphy 2>;
+ phy-names = "usb";
+ status = "disabled";
+ };
+
+ rtc: rtc@7000000 {
+ compatible = "allwinner,sun50i-h616-rtc",
+ "allwinner,sun50i-h6-rtc";
+ reg = <0x07000000 0x400>;
+ interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>;
+ clock-output-names = "osc32k", "osc32k-out", "iosc";
+ #clock-cells = <1>;
+ };
+
+ r_ccu: clock@7010000 {
+ compatible = "allwinner,sun50i-h616-r-ccu";
+ reg = <0x07010000 0x210>;
+ clocks = <&osc24M>, <&rtc 0>, <&rtc 2>,
+ <&ccu CLK_PLL_PERIPH0>;
+ clock-names = "hosc", "losc", "iosc", "pll-periph";
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ };
+
+ r_pio: pinctrl@7022000 {
+ compatible = "allwinner,sun50i-h616-r-pinctrl";
+ reg = <0x07022000 0x400>;
+ interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&r_ccu CLK_R_APB1>, <&osc24M>, <&rtc 0>;
+ clock-names = "apb", "hosc", "losc";
+ gpio-controller;
+ #gpio-cells = <3>;
+ interrupt-controller;
+ #interrupt-cells = <3>;
+
+ r_i2c_pins: r-i2c-pins {
+ pins = "PL0", "PL1";
+ function = "s_i2c";
+ };
+
+ r_rsb_pins: r-rsb-pins {
+ pins = "PL0", "PL1";
+ function = "s_rsb";
+ };
+ };
+
+ ir: ir@7040000 {
+ compatible = "allwinner,sun50i-h616-ir",
+ "allwinner,sun6i-a31-ir";
+ reg = <0x07040000 0x400>;
+ interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&r_ccu CLK_R_APB1_IR>,
+ <&r_ccu CLK_IR>;
+ clock-names = "apb", "ir";
+ resets = <&r_ccu RST_R_APB1_IR>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&ir_rx_pin>;
+ status = "disabled";
+ };
+
+ r_i2c: i2c@7081400 {
+ compatible = "allwinner,sun50i-h616-i2c",
+ "allwinner,sun6i-a31-i2c";
+ reg = <0x07081400 0x400>;
+ interrupts = <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&r_ccu CLK_R_APB2_I2C>;
+ resets = <&r_ccu RST_R_APB2_I2C>;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ r_rsb: rsb@7083000 {
+ compatible = "allwinner,sun50i-h616-rsb",
+ "allwinner,sun8i-a23-rsb";
+ reg = <0x07083000 0x400>;
+ interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&r_ccu CLK_R_APB2_RSB>;
+ clock-frequency = <3000000>;
+ resets = <&r_ccu RST_R_APB2_RSB>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&r_rsb_pins>;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+ };
+};
--
2.17.5

Andre Przywara

unread,
Jan 25, 2021, 10:19:48 AM1/25/21
to Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland, Icenowy Zheng, Rob Herring, Clément Péron, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, devic...@vger.kernel.org
Signed-off-by: Andre Przywara <andre.p...@arm.com>
Acked-by: Rob Herring <ro...@kernel.org>
---
Documentation/devicetree/bindings/arm/sunxi.yaml | 5 +++++
1 file changed, 5 insertions(+)

diff --git a/Documentation/devicetree/bindings/arm/sunxi.yaml b/Documentation/devicetree/bindings/arm/sunxi.yaml
index 08607c7ec1bf..aeb8771b14c4 100644
--- a/Documentation/devicetree/bindings/arm/sunxi.yaml
+++ b/Documentation/devicetree/bindings/arm/sunxi.yaml
@@ -932,4 +932,9 @@ properties:
- const: xunlong,orangepi-zero-plus2-h3
- const: allwinner,sun8i-h3

+ - description: Xunlong OrangePi Zero 2
+ items:
+ - const: xunlong,orangepi-zero2
+ - const: allwinner,sun50i-h616
+
additionalProperties: true
--
2.17.5

Andre Przywara

unread,
Jan 25, 2021, 10:19:49 AM1/25/21
to Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland, Icenowy Zheng, Rob Herring, Clément Péron, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, devic...@vger.kernel.org
The OrangePi Zero 2 is a development board with the new H616 SoC.

It features the usual connectors used on those small boards, and comes
with the AXP305, which seems to be compatible with the AXP805.

For more details see: http://linux-sunxi.org/Xunlong_Orange_Pi_Zero2

Signed-off-by: Andre Przywara <andre.p...@arm.com>
---
arch/arm64/boot/dts/allwinner/Makefile | 1 +
.../allwinner/sun50i-h616-orangepi-zero2.dts | 242 ++++++++++++++++++
2 files changed, 243 insertions(+)
create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-h616-orangepi-zero2.dts

diff --git a/arch/arm64/boot/dts/allwinner/Makefile b/arch/arm64/boot/dts/allwinner/Makefile
index 41ce680e5f8d..9ba4b5d92657 100644
--- a/arch/arm64/boot/dts/allwinner/Makefile
+++ b/arch/arm64/boot/dts/allwinner/Makefile
@@ -36,3 +36,4 @@ dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-orangepi-one-plus.dtb
dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-pine-h64.dtb
dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-pine-h64-model-b.dtb
dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-tanix-tx6.dtb
+dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h616-orangepi-zero2.dtb
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h616-orangepi-zero2.dts b/arch/arm64/boot/dts/allwinner/sun50i-h616-orangepi-zero2.dts
new file mode 100644
index 000000000000..e6de49f89e39
--- /dev/null
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h616-orangepi-zero2.dts
@@ -0,0 +1,242 @@
+// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+/*
+ * Copyright (C) 2020 Arm Ltd.
+ */
+
+/dts-v1/;
+
+#include "sun50i-h616.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/leds/common.h>
+
+/ {
+ model = "OrangePi Zero2";
+ compatible = "xunlong,orangepi-zero2", "allwinner,sun50i-h616";
+
+ aliases {
+ ethernet0 = &emac0;
+ serial0 = &uart0;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ led-0 {
+ function = LED_FUNCTION_POWER;
+ color = <LED_COLOR_ID_RED>;
+ gpios = <&pio 2 12 GPIO_ACTIVE_HIGH>; /* PC12 */
+ default-state = "on";
+ };
+
+ led-1 {
+ function = LED_FUNCTION_STATUS;
+ color = <LED_COLOR_ID_GREEN>;
+ gpios = <&pio 2 13 GPIO_ACTIVE_HIGH>; /* PC13 */
+ };
+ };
+
+ reg_vcc5v: vcc5v {
+ /* board wide 5V supply directly from the USB-C socket */
+ compatible = "regulator-fixed";
+ regulator-name = "vcc-5v";
+ regulator-min-microvolt = <5000000>;
+ 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";
+ };
+};
+
+&ehci0 {
+ status = "okay";
+};
+
+&ehci1 {
+ status = "okay";
+};
+
+/* USB 2 & 3 are on headers only. */
+
+&emac0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&ext_rgmii_pins>;
+ phy-mode = "rgmii";
+ phy-handle = <&ext_rgmii_phy>;
+ phy-supply = <&reg_dcdce>;
+ allwinner,rx-delay-ps = <3100>;
+ allwinner,tx-delay-ps = <700>;
+ status = "okay";
+};
+
+&mdio0 {
+ ext_rgmii_phy: ethernet-phy@1 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <1>;
+ };
+};
+
+&mmc0 {
+ vmmc-supply = <&reg_dcdce>;
+ cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; /* PF6 */
+ bus-width = <4>;
+ status = "okay";
+};
+
+&ohci0 {
+ status = "okay";
+};
+
+&ohci1 {
+ status = "okay";
+};
+
+&r_rsb {
+ status = "okay";
+
+ axp305: pmic@745 {
+ compatible = "x-powers,axp305", "x-powers,axp805",
+ "x-powers,axp806";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ reg = <0x745>;
+
+ x-powers,self-working-mode;
+ vina-supply = <&reg_vcc5v>;
+ vinb-supply = <&reg_vcc5v>;
+ vinc-supply = <&reg_vcc5v>;
+ vind-supply = <&reg_vcc5v>;
+ vine-supply = <&reg_vcc5v>;
+ aldoin-supply = <&reg_vcc5v>;
+ bldoin-supply = <&reg_vcc5v>;
+ cldoin-supply = <&reg_vcc5v>;
+
+ regulators {
+ reg_aldo1: aldo1 {
+ regulator-always-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-name = "vcc-sys";
+ };
+
+ reg_aldo2: aldo2 { /* 3.3V on headers */
+ regulator-always-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-name = "vcc3v3-ext";
+ };
+
+ reg_aldo3: aldo3 { /* 3.3V on headers */
+ regulator-always-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-name = "vcc3v3-ext2";
+ };
+
+ reg_bldo1: bldo1 {
+ regulator-always-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-name = "vcc1v8";
+ };
+
+ bldo2 {
+ /* unused */
+ };
+
+ bldo3 {
+ /* unused */
+ };
+
+ bldo4 {
+ /* unused */
+ };
+
+ cldo1 {
+ /* reserved */
+ };
+
+ cldo2 {
+ /* unused */
+ };
+
+ cldo3 {
+ /* unused */
+ };
+
+ reg_dcdca: dcdca {
+ regulator-always-on;
+ regulator-min-microvolt = <810000>;
+ regulator-max-microvolt = <1080000>;
+ regulator-name = "vdd-cpu";
+ };
+
+ reg_dcdcc: dcdcc {
+ regulator-always-on;
+ regulator-min-microvolt = <810000>;
+ regulator-max-microvolt = <1080000>;
+ regulator-name = "vdd-gpu-sys";
+ };
+
+ reg_dcdcd: dcdcd {
+ regulator-always-on;
+ regulator-min-microvolt = <1500000>;
+ regulator-max-microvolt = <1500000>;
+ regulator-name = "vdd-dram";
+ };
+
+ reg_dcdce: dcdce {
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-name = "vcc-eth-mmc";
+ };
+
+ sw {
+ /* unused */
+ };
+ };
+ };
+};
+
+&spi0 {
+ status = "okay";
+
+ flash@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "jedec,spi-nor";
+ reg = <0>;
+ spi-max-frequency = <40000000>;
+ };
+};
+
+&uart0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_ph_pins>;
+ status = "okay";
+};
+
+&usbotg {
+ dr_mode = "peripheral";
+ status = "okay";
+};
+
+&usbphy {
+ usb1_vbus-supply = <&reg_usb1_vbus>;
+ status = "okay";
+};
--
2.17.5

Alexandre Belloni

unread,
Jan 25, 2021, 5:51:07 PM1/25/21
to Andre Przywara, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland, Icenowy Zheng, Rob Herring, Clément Péron, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Alessandro Zummo, devic...@vger.kernel.org, linu...@vger.kernel.org
Hello Andre,

On 25/01/2021 15:18:02+0000, Andre Przywara wrote:
> Add the obvious compatible name to the existing RTC binding, and pair
> it with the existing H6 fallback compatible string, as the devices are
> compatible.
>
> Signed-off-by: Andre Przywara <andre.p...@arm.com>
> Acked-by: Rob Herring <ro...@kernel.org>
> ---
> .../devicetree/bindings/rtc/allwinner,sun6i-a31-rtc.yaml | 3 +++
> 1 file changed, 3 insertions(+)
>

How do you expect that patch to be merged? I was thinking it would go
through Rob's tree.

> diff --git a/Documentation/devicetree/bindings/rtc/allwinner,sun6i-a31-rtc.yaml b/Documentation/devicetree/bindings/rtc/allwinner,sun6i-a31-rtc.yaml
> index b1b0ee769b71..4193e5813344 100644
> --- a/Documentation/devicetree/bindings/rtc/allwinner,sun6i-a31-rtc.yaml
> +++ b/Documentation/devicetree/bindings/rtc/allwinner,sun6i-a31-rtc.yaml
> @@ -26,6 +26,9 @@ properties:
> - const: allwinner,sun50i-a64-rtc
> - const: allwinner,sun8i-h3-rtc
> - const: allwinner,sun50i-h6-rtc
> + - items:
> + - const: allwinner,sun50i-h616-rtc
> + - const: allwinner,sun50i-h6-rtc
>
> reg:
> maxItems: 1
> --
> 2.17.5
>

--
Alexandre Belloni, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

Andre Przywara

unread,
Jan 25, 2021, 7:15:05 PM1/25/21
to Alexandre Belloni, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland, Icenowy Zheng, Rob Herring, Clément Péron, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Alessandro Zummo, devic...@vger.kernel.org, linu...@vger.kernel.org
On Mon, 25 Jan 2021 23:51:01 +0100
Alexandre Belloni <alexandr...@bootlin.com> wrote:

Hi Alexandre,

> On 25/01/2021 15:18:02+0000, Andre Przywara wrote:
> > Add the obvious compatible name to the existing RTC binding, and pair
> > it with the existing H6 fallback compatible string, as the devices are
> > compatible.
> >
> > Signed-off-by: Andre Przywara <andre.p...@arm.com>
> > Acked-by: Rob Herring <ro...@kernel.org>
> > ---
> > .../devicetree/bindings/rtc/allwinner,sun6i-a31-rtc.yaml | 3 +++
> > 1 file changed, 3 insertions(+)
> >
>
> How do you expect that patch to be merged? I was thinking it would go
> through Rob's tree.

Yes, and that's why I originally combined all those trivial patches
into one, but broonie asked for a split up.

So I guess there is not much to do there, unless you want to object ;-)

Cheers,
Andre

Maxime Ripard

unread,
Jan 26, 2021, 7:07:55 AM1/26/21
to Andre Przywara, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland, Icenowy Zheng, Rob Herring, Clément Péron, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Linus Walleij, Ulf Hansson
Hi,

On Mon, Jan 25, 2021 at 03:17:50PM +0000, Andre Przywara wrote:
> Hi,
>
> an update from the v3 last week, to add support for the Allwinner H616
> SoC. Still based on the (updated) sunxi/for-next branch.
> I am omitting the MMC and pinctrl patches now, as they have been taken
> by Ulf and LinusW already into their trees.
>
> I addressed the comments from the list, though not sure if the HOSC clock
> coming from the RTC is really a good idea (didn't change it).
>
> I was hoping that at least the clock and AXP patches (01/21-06/21) could
> make it into 5.12 still? That would allow booting boards from SD card.
> I am happy to strip the .dtsi and .dts patch to only contain the devices
> that we actually support then, if needed.
>
> For the changes: I split the joint DT bindings patch into subsystem
> specific ones, hopefully this simplifies merging. There is a new fix
> for the axp20x-pek driver, and the AXP IRQ fix has been amended as well
> (according to Samuel's comments).
>
> I eventually got USB to work, by requiring PHY 2 for [EO]HCI 1 & 3 as well.
> Not sure this is the right fix, it might be just one clock or reset
> line from that PHY that is needed for the others as well. Will do further
> experiments.
>
> For a more detailed changelog, see below.

With your series applied:

ARCH=arm64 make -j18 dtbs_check
arch/arm64/Makefile:25: ld does not support --fix-cortex-a53-843419; kernel may be susceptible to erratum
arch/arm64/Makefile:33: LSE atomics not supported by binutils
arch/arm64/Makefile:44: Detected assembler with broken .inst; disassembly will be unreliable
DTC arch/arm64/boot/dts/allwinner/sun50i-h616-orangepi-zero2.dtb
DTC arch/arm64/boot/dts/allwinner/sun50i-h616-orangepi-zero2.dt.yaml
CHECK arch/arm64/boot/dts/allwinner/sun50i-h616-orangepi-zero2.dt.yaml
/home/max/Work/allwinner/build/arm64/arch/arm64/boot/dts/allwinner/sun50i-h616-orangepi-zero2.dt.yaml: clock@3001000: clocks: [[7], [8, 0], [8, 2]] is too long
From schema: /home/max/Work/repos/linux/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-ccu.yaml
/home/max/Work/allwinner/build/arm64/arch/arm64/boot/dts/allwinner/sun50i-h616-orangepi-zero2.dt.yaml: clock@3001000: clock-names: ['hosc', 'losc', 'iosc'] is too long
From schema: /home/max/Work/repos/linux/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-ccu.yaml
/home/max/Work/allwinner/build/arm64/arch/arm64/boot/dts/allwinner/sun50i-h616-orangepi-zero2.dt.yaml: ethernet@5020000: compatible: 'oneOf' conditional failed, one must be fixed:
['allwinner,sun50i-h616-emac', 'allwinner,sun50i-a64-emac'] is too long
Additional items are not allowed ('allwinner,sun50i-a64-emac' was unexpected)
'allwinner,sun8i-a83t-emac' was expected
'allwinner,sun8i-h3-emac' was expected
'allwinner,sun8i-r40-emac' was expected
'allwinner,sun8i-v3s-emac' was expected
'allwinner,sun50i-a64-emac' was expected
'allwinner,sun50i-h6-emac' was expected
From schema: /home/max/Work/repos/linux/Documentation/devicetree/bindings/net/allwinner,sun8i-a83t-emac.yaml
/home/max/Work/allwinner/build/arm64/arch/arm64/boot/dts/allwinner/sun50i-h616-orangepi-zero2.dt.yaml: clock@7010000: clocks: [[7], [8, 0], [8, 2], [2, 4]] is too long
From schema: /home/max/Work/repos/linux/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-ccu.yaml
/home/max/Work/allwinner/build/arm64/arch/arm64/boot/dts/allwinner/sun50i-h616-orangepi-zero2.dt.yaml: clock@7010000: clock-names: ['hosc', 'losc', 'iosc', 'pll-periph'] is too long
From schema: /home/max/Work/repos/linux/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-ccu.yaml
/home/max/Work/allwinner/build/arm64/arch/arm64/boot/dts/allwinner/sun50i-h616-orangepi-zero2.dt.yaml: rsb@7083000: compatible: 'oneOf' conditional failed, one must be fixed:
['allwinner,sun50i-h616-rsb', 'allwinner,sun8i-a23-rsb'] is too long
Additional items are not allowed ('allwinner,sun8i-a23-rsb' was unexpected)
'allwinner,sun8i-a23-rsb' was expected
'allwinner,sun8i-a83t-rsb' was expected
From schema: /home/max/Work/repos/linux/Documentation/devicetree/bindings/bus/allwinner,sun8i-a23-rsb.yaml
/home/max/Work/allwinner/build/arm64/arch/arm64/boot/dts/allwinner/sun50i-h616-orangepi-zero2.dt.yaml: leds: led-0:default-state:0: 'on' is not of type 'array'
From schema: /home/max/Work/repos/linux/Documentation/devicetree/bindings/leds/leds-gpio.yaml

The last one is not related to your changes, but the rest must be fixed

Maxime
signature.asc

Mark Brown

unread,
Jan 27, 2021, 12:16:16 PM1/27/21
to Maxime Ripard, Andre Przywara, Chen-Yu Tsai, Clément Péron, Ulf Hansson, Linus Walleij, Yangtao Li, Shuosheng Huang, Jernej Skrabec, Icenowy Zheng, linux...@googlegroups.com, linux-...@vger.kernel.org, linux-ar...@lists.infradead.org, Samuel Holland
On Mon, 25 Jan 2021 15:17:50 +0000, Andre Przywara wrote:
> an update from the v3 last week, to add support for the Allwinner H616
> SoC. Still based on the (updated) sunxi/for-next branch.
> I am omitting the MMC and pinctrl patches now, as they have been taken
> by Ulf and LinusW already into their trees.
>
> I addressed the comments from the list, though not sure if the HOSC clock
> coming from the RTC is really a good idea (didn't change it).
>
> [...]

Applied to

https://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git for-next

Thanks!

[13/21] dt-bindings: spi: sunxi: Add H616 compatible string
commit: 6589daf8bb98c75ad1065edad87c099ffb9f5d87

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

Andre Przywara

unread,
Jan 27, 2021, 12:25:50 PM1/27/21
to Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland, Icenowy Zheng, Rob Herring, Clément Péron, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com
Hi,

this is a small update from v4, fixing some DT validation issues:
dtbs_check now comes back clean for me.
Also I dropped USB support for now. It turns out that this is more messy
than we thought: it only works if all four USB controllers are enabled
(and not just some PHYs). That smells like some shared reset or clock
gate, but we haven't found the culprit yet. Also the BSP source suggests
that there is a "hardware design issue" that requires some PHY tune
register to be programmed, so we probably need more code anyway.
I also dropped the DT node for the second EMAC, as this is mostly
untested at this point.

Changelog below. Based on the (updated) sunxi/for-next branch.

I was hoping that at least the clock and AXP patches (01/20-06/20) could
make it into 5.12 still? That would allow booting boards from SD card.
Patch 08/20 would enable Ethernet.
U-Boot support is now merged into its master tree.

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.

Various DT binding patches are sprinkled throughout the series, to add
the new compatible names right before they are used.
Patch 2 and 3 add clock support. For the -R clock this is shared with
the H6 code, as the clocks are identical, with the H616 just having
fewer of them. The main clocks are different enough to warrant a separate
file.
Patches 5 and 6 teach the AXP MFD driver to get along without having an
interrupt, as the missing NMI pin on the H616 leads to some boards not
having the AXP IRQ line connected.
Patch 8 and 16 add some tweaks to the syscon and EMAC driver, to deal
with the second EMAC clock used for the second Ethernet controller.
This is somewhat optional for the current .dts, as this doesn't use
the second EMAC.

The remaining patches add DT bindings, which just add the new compatible
string along with an existing name as a fallback string.
Eventually we get the .dtsi for the SoC in patch 19, and the .dts for
the OrangePi Zero2 board[1] in the last patch.

We have U-Boot and Trusted-Firmware support in a working state, booting
via FEL or SD card and even TFTPing kernels work already [2][3].
The U-Boot patches are already merged into the mainline repository.

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 other patches) can also be found here:
https://github.com/apritzel/linux/commits/h616-v5

Happy reviewing!

Cheers,
Andre

[1] https://linux-sunxi.org/Xunlong_Orange_Pi_Zero2
[2] https://github.com/jernejsk/u-boot/commits/h616-v2
[3] https://github.com/apritzel/arm-trusted-firmware/commits/h616-v1

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 (20):
dt-bindings: clk: sunxi-ccu: Add compatible string for Allwinner H616
clk: sunxi-ng: Add support for the Allwinner H616 R-CCU
clk: sunxi-ng: Add support for the Allwinner H616 CCU
dt-bindings: mfd: axp20x: Add AXP305 compatible (plus optional IRQ)
Input: axp20x-pek: Bail out if AXP has no interrupt line connected
mfd: axp20x: Allow AXP chips without interrupt lines
dt-bindings: sram: sunxi-sram: Add H616 compatible string
soc: sunxi: sram: Add support for more than one EMAC clock
dt-bindings: watchdog: sun4i: Add H616 compatible string
dt-bindings: i2c: mv64xxx: Add H616 compatible string
dt-bindings: media: IR: Add H616 IR compatible string
dt-bindings: rtc: sun6i: Add H616 compatible string
dt-bindings: spi: sunxi: Add H616 compatible string
dt-bindings: bus: rsb: Add H616 compatible string
dt-bindings: net: sun8i-emac: Add H616 compatible string
net: stmmac: dwmac-sun8i: Prepare for second EMAC clock register
phy: sun4i-usb: Rework HCI PHY (aka. "pmu_unk1") handling
arm64: dts: allwinner: Add Allwinner H616 .dtsi file
dt-bindings: arm: sunxi: Add OrangePi Zero 2 binding
arm64: dts: allwinner: Add OrangePi Zero 2 .dts

.../devicetree/bindings/arm/sunxi.yaml | 5 +
.../bindings/bus/allwinner,sun8i-a23-rsb.yaml | 4 +-
.../clock/allwinner,sun4i-a10-ccu.yaml | 4 +
.../bindings/i2c/marvell,mv64xxx-i2c.yaml | 21 +-
.../media/allwinner,sun4i-a10-ir.yaml | 16 +-
.../devicetree/bindings/mfd/axp20x.txt | 3 +-
.../net/allwinner,sun8i-a83t-emac.yaml | 4 +-
.../bindings/rtc/allwinner,sun6i-a31-rtc.yaml | 3 +
.../bindings/spi/allwinner,sun6i-a31-spi.yaml | 1 +
.../allwinner,sun4i-a10-system-control.yaml | 1 +
.../watchdog/allwinner,sun4i-a10-wdt.yaml | 12 +-
arch/arm64/boot/dts/allwinner/Makefile | 1 +
.../allwinner/sun50i-h616-orangepi-zero2.dts | 203 +++
.../arm64/boot/dts/allwinner/sun50i-h616.dtsi | 573 ++++++++
drivers/clk/sunxi-ng/Kconfig | 7 +-
drivers/clk/sunxi-ng/Makefile | 1 +
drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c | 48 +
drivers/clk/sunxi-ng/ccu-sun50i-h616.c | 1150 +++++++++++++++++
drivers/clk/sunxi-ng/ccu-sun50i-h616.h | 56 +
drivers/input/misc/axp20x-pek.c | 4 +
drivers/mfd/axp20x.c | 17 +-
.../net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 12 +-
drivers/phy/allwinner/phy-sun4i-usb.c | 29 +-
drivers/soc/sunxi/sunxi_sram.c | 31 +-
include/dt-bindings/clock/sun50i-h616-ccu.h | 115 ++
include/dt-bindings/reset/sun50i-h616-ccu.h | 70 +
26 files changed, 2323 insertions(+), 68 deletions(-)
create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-h616-orangepi-zero2.dts
create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi
create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-h616.c
create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-h616.h
create mode 100644 include/dt-bindings/clock/sun50i-h616-ccu.h
create mode 100644 include/dt-bindings/reset/sun50i-h616-ccu.h

--
2.17.5

Andre Przywara

unread,
Jan 27, 2021, 12:25:51 PM1/27/21
to Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland, Icenowy Zheng, Rob Herring, Clément Péron, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Stephen Boyd, Michael Turquette, linu...@vger.kernel.org, devic...@vger.kernel.org
Signed-off-by: Andre Przywara <andre.p...@arm.com>
Acked-by: Rob Herring <ro...@kernel.org>
Acked-by: Maxime Ripard <mri...@kernel.org>
---
.../devicetree/bindings/clock/allwinner,sun4i-a10-ccu.yaml | 4 ++++
1 file changed, 4 insertions(+)

diff --git a/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-ccu.yaml b/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-ccu.yaml
index 3b45344ed758..a27025cd3909 100644
--- a/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-ccu.yaml
+++ b/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-ccu.yaml
@@ -41,6 +41,8 @@ properties:
- allwinner,sun50i-h5-ccu
- allwinner,sun50i-h6-ccu
- allwinner,sun50i-h6-r-ccu
+ - allwinner,sun50i-h616-ccu
+ - allwinner,sun50i-h616-r-ccu
- allwinner,suniv-f1c100s-ccu
- nextthing,gr8-ccu

@@ -82,6 +84,7 @@ if:
- allwinner,sun50i-a64-r-ccu
- allwinner,sun50i-a100-r-ccu
- allwinner,sun50i-h6-r-ccu
+ - allwinner,sun50i-h616-r-ccu

then:
properties:
@@ -100,6 +103,7 @@ else:
enum:
- allwinner,sun50i-a100-ccu
- allwinner,sun50i-h6-ccu
+ - allwinner,sun50i-h616-ccu

then:
properties:
--
2.17.5

Andre Przywara

unread,
Jan 27, 2021, 12:25:55 PM1/27/21
to Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland, Icenowy Zheng, Rob Herring, Clément Péron, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Stephen Boyd, Michael Turquette, linu...@vger.kernel.org, Philipp Zabel
The clocks itself are identical to the H6 R-CCU, it's just that the H616
has not all of them implemented (or connected).

Signed-off-by: Andre Przywara <andre.p...@arm.com>
Acked-by: Maxime Ripard <mri...@kernel.org>
---
drivers/clk/sunxi-ng/Kconfig | 2 +-
drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c | 48 ++++++++++++++++++++++++++
2 files changed, 49 insertions(+), 1 deletion(-)

diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig
index ce5f5847d5d3..feeb8d2074ee 100644
--- a/drivers/clk/sunxi-ng/Kconfig
+++ b/drivers/clk/sunxi-ng/Kconfig
@@ -33,7 +33,7 @@ config SUN50I_H6_CCU
depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST

config SUN50I_H6_R_CCU
- bool "Support for the Allwinner H6 PRCM CCU"
+ bool "Support for the Allwinner H6 and H616 PRCM CCU"
default ARM64 && ARCH_SUNXI
depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST

diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c b/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c
index 56e351b513f3..f8909a7ed553 100644
--- a/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c
@@ -139,6 +139,16 @@ static struct ccu_common *sun50i_h6_r_ccu_clks[] = {
&w1_clk.common,
};

+static struct ccu_common *sun50i_h616_r_ccu_clks[] = {
+ &r_apb1_clk.common,
+ &r_apb2_clk.common,
+ &r_apb1_twd_clk.common,
+ &r_apb2_i2c_clk.common,
+ &r_apb2_rsb_clk.common,
+ &r_apb1_ir_clk.common,
+ &ir_clk.common,
+};
+
static struct clk_hw_onecell_data sun50i_h6_r_hw_clks = {
.hws = {
[CLK_AR100] = &ar100_clk.common.hw,
@@ -159,6 +169,20 @@ static struct clk_hw_onecell_data sun50i_h6_r_hw_clks = {
.num = CLK_NUMBER,
};

+static struct clk_hw_onecell_data sun50i_h616_r_hw_clks = {
+ .hws = {
+ [CLK_R_AHB] = &r_ahb_clk.hw,
+ [CLK_R_APB1] = &r_apb1_clk.common.hw,
+ [CLK_R_APB2] = &r_apb2_clk.common.hw,
+ [CLK_R_APB1_TWD] = &r_apb1_twd_clk.common.hw,
+ [CLK_R_APB2_I2C] = &r_apb2_i2c_clk.common.hw,
+ [CLK_R_APB2_RSB] = &r_apb2_rsb_clk.common.hw,
+ [CLK_R_APB1_IR] = &r_apb1_ir_clk.common.hw,
+ [CLK_IR] = &ir_clk.common.hw,
+ },
+ .num = CLK_NUMBER,
+};
+
static struct ccu_reset_map sun50i_h6_r_ccu_resets[] = {
[RST_R_APB1_TIMER] = { 0x11c, BIT(16) },
[RST_R_APB1_TWD] = { 0x12c, BIT(16) },
@@ -170,6 +194,13 @@ static struct ccu_reset_map sun50i_h6_r_ccu_resets[] = {
[RST_R_APB1_W1] = { 0x1ec, BIT(16) },
};

+static struct ccu_reset_map sun50i_h616_r_ccu_resets[] = {
+ [RST_R_APB1_TWD] = { 0x12c, BIT(16) },
+ [RST_R_APB2_I2C] = { 0x19c, BIT(16) },
+ [RST_R_APB2_RSB] = { 0x1bc, BIT(16) },
+ [RST_R_APB1_IR] = { 0x1cc, BIT(16) },
+};
+
static const struct sunxi_ccu_desc sun50i_h6_r_ccu_desc = {
.ccu_clks = sun50i_h6_r_ccu_clks,
.num_ccu_clks = ARRAY_SIZE(sun50i_h6_r_ccu_clks),
@@ -180,6 +211,16 @@ static const struct sunxi_ccu_desc sun50i_h6_r_ccu_desc = {
.num_resets = ARRAY_SIZE(sun50i_h6_r_ccu_resets),
};

+static const struct sunxi_ccu_desc sun50i_h616_r_ccu_desc = {
+ .ccu_clks = sun50i_h616_r_ccu_clks,
+ .num_ccu_clks = ARRAY_SIZE(sun50i_h616_r_ccu_clks),
+
+ .hw_clks = &sun50i_h616_r_hw_clks,
+
+ .resets = sun50i_h616_r_ccu_resets,
+ .num_resets = ARRAY_SIZE(sun50i_h616_r_ccu_resets),
+};
+
static void __init sunxi_r_ccu_init(struct device_node *node,
const struct sunxi_ccu_desc *desc)
{
@@ -200,3 +241,10 @@ static void __init sun50i_h6_r_ccu_setup(struct device_node *node)
}
CLK_OF_DECLARE(sun50i_h6_r_ccu, "allwinner,sun50i-h6-r-ccu",
sun50i_h6_r_ccu_setup);
+
+static void __init sun50i_h616_r_ccu_setup(struct device_node *node)
+{
+ sunxi_r_ccu_init(node, &sun50i_h616_r_ccu_desc);
+}
+CLK_OF_DECLARE(sun50i_h616_r_ccu, "allwinner,sun50i-h616-r-ccu",
+ sun50i_h616_r_ccu_setup);
--
2.17.5

Andre Przywara

unread,
Jan 27, 2021, 12:25:59 PM1/27/21
to Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland, Icenowy Zheng, Rob Herring, Clément Péron, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Stephen Boyd, Michael Turquette, linu...@vger.kernel.org, Philipp Zabel
While the clocks are fairly similar to the H6, many differ in tiny
details, so a separate clock driver seems indicated.

Derived from the H6 clock driver, and adjusted according to the manual.

Signed-off-by: Andre Przywara <andre.p...@arm.com>
Acked-by: Maxime Ripard <mri...@kernel.org>
---
drivers/clk/sunxi-ng/Kconfig | 5 +
drivers/clk/sunxi-ng/Makefile | 1 +
drivers/clk/sunxi-ng/ccu-sun50i-h616.c | 1150 +++++++++++++++++++
drivers/clk/sunxi-ng/ccu-sun50i-h616.h | 56 +
include/dt-bindings/clock/sun50i-h616-ccu.h | 115 ++
include/dt-bindings/reset/sun50i-h616-ccu.h | 70 ++
6 files changed, 1397 insertions(+)
create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-h616.c
create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-h616.h
create mode 100644 include/dt-bindings/clock/sun50i-h616-ccu.h
create mode 100644 include/dt-bindings/reset/sun50i-h616-ccu.h

diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig
index feeb8d2074ee..cd46d8853876 100644
--- a/drivers/clk/sunxi-ng/Kconfig
+++ b/drivers/clk/sunxi-ng/Kconfig
@@ -32,6 +32,11 @@ config SUN50I_H6_CCU
default ARM64 && ARCH_SUNXI
depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST

+config SUN50I_H616_CCU
+ bool "Support for the Allwinner H616 CCU"
+ default ARM64 && ARCH_SUNXI
+ depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST
+
config SUN50I_H6_R_CCU
bool "Support for the Allwinner H6 and H616 PRCM CCU"
default ARM64 && ARCH_SUNXI
diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
index 3eb5cff40eac..96c324306d97 100644
--- a/drivers/clk/sunxi-ng/Makefile
+++ b/drivers/clk/sunxi-ng/Makefile
@@ -26,6 +26,7 @@ obj-$(CONFIG_SUN50I_A64_CCU) += ccu-sun50i-a64.o
obj-$(CONFIG_SUN50I_A100_CCU) += ccu-sun50i-a100.o
obj-$(CONFIG_SUN50I_A100_R_CCU) += ccu-sun50i-a100-r.o
obj-$(CONFIG_SUN50I_H6_CCU) += ccu-sun50i-h6.o
+obj-$(CONFIG_SUN50I_H616_CCU) += ccu-sun50i-h616.o
obj-$(CONFIG_SUN50I_H6_R_CCU) += ccu-sun50i-h6-r.o
obj-$(CONFIG_SUN4I_A10_CCU) += ccu-sun4i-a10.o
obj-$(CONFIG_SUN5I_CCU) += ccu-sun5i.o
diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h616.c b/drivers/clk/sunxi-ng/ccu-sun50i-h616.c
new file mode 100644
index 000000000000..225307305880
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-h616.c
@@ -0,0 +1,1150 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2020 Arm Ltd.
+ * Based on the H6 CCU driver, which is:
+ * Copyright (c) 2017 Icenowy Zheng <ice...@aosc.io>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+
+#include "ccu_common.h"
+#include "ccu_reset.h"
+
+#include "ccu_div.h"
+#include "ccu_gate.h"
+#include "ccu_mp.h"
+#include "ccu_mult.h"
+#include "ccu_nk.h"
+#include "ccu_nkm.h"
+#include "ccu_nkmp.h"
+#include "ccu_nm.h"
+
+#include "ccu-sun50i-h616.h"
+
+/*
+ * The CPU PLL is actually NP clock, with P being /1, /2 or /4. However
+ * P should only be used for output frequencies lower than 288 MHz.
+ *
+ * For now we can just model it as a multiplier clock, and force P to /1.
+ *
+ * The M factor is present in the register's description, but not in the
+ * frequency formula, and it's documented as "M is only used for backdoor
+ * testing", so it's not modelled and then force to 0.
+ */
+#define SUN50I_H616_PLL_CPUX_REG 0x000
+static struct ccu_mult pll_cpux_clk = {
+ .enable = BIT(31),
+ .lock = BIT(28),
+ .mult = _SUNXI_CCU_MULT_MIN(8, 8, 12),
+ .common = {
+ .reg = 0x000,
+ .hw.init = CLK_HW_INIT("pll-cpux", "osc24M",
+ &ccu_mult_ops,
+ CLK_SET_RATE_UNGATE),
+ },
+};
+
+/* Some PLLs are input * N / div1 / P. Model them as NKMP with no K */
+#define SUN50I_H616_PLL_DDR0_REG 0x010
+static struct ccu_nkmp pll_ddr0_clk = {
+ .enable = BIT(31),
+ .lock = BIT(28),
+ .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
+ .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
+ .p = _SUNXI_CCU_DIV(0, 1), /* output divider */
+ .common = {
+ .reg = 0x010,
+ .hw.init = CLK_HW_INIT("pll-ddr0", "osc24M",
+ &ccu_nkmp_ops,
+ CLK_SET_RATE_UNGATE),
+ },
+};
+
+#define SUN50I_H616_PLL_DDR1_REG 0x018
+static struct ccu_nkmp pll_ddr1_clk = {
+ .enable = BIT(31),
+ .lock = BIT(28),
+ .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
+ .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
+ .p = _SUNXI_CCU_DIV(0, 1), /* output divider */
+ .common = {
+ .reg = 0x018,
+ .hw.init = CLK_HW_INIT("pll-ddr1", "osc24M",
+ &ccu_nkmp_ops,
+ CLK_SET_RATE_UNGATE),
+ },
+};
+
+#define SUN50I_H616_PLL_PERIPH0_REG 0x020
+static struct ccu_nkmp pll_periph0_clk = {
+ .enable = BIT(31),
+ .lock = BIT(28),
+ .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
+ .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
+ .p = _SUNXI_CCU_DIV(0, 1), /* output divider */
+ .fixed_post_div = 2,
+ .common = {
+ .reg = 0x020,
+ .features = CCU_FEATURE_FIXED_POSTDIV,
+ .hw.init = CLK_HW_INIT("pll-periph0", "osc24M",
+ &ccu_nkmp_ops,
+ CLK_SET_RATE_UNGATE),
+ },
+};
+
+#define SUN50I_H616_PLL_PERIPH1_REG 0x028
+static struct ccu_nkmp pll_periph1_clk = {
+ .enable = BIT(31),
+ .lock = BIT(28),
+ .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
+ .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
+ .p = _SUNXI_CCU_DIV(0, 1), /* output divider */
+ .fixed_post_div = 2,
+ .common = {
+ .reg = 0x028,
+ .features = CCU_FEATURE_FIXED_POSTDIV,
+ .hw.init = CLK_HW_INIT("pll-periph1", "osc24M",
+ &ccu_nkmp_ops,
+ CLK_SET_RATE_UNGATE),
+ },
+};
+
+#define SUN50I_H616_PLL_GPU_REG 0x030
+static struct ccu_nkmp pll_gpu_clk = {
+ .enable = BIT(31),
+ .lock = BIT(28),
+ .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
+ .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
+ .p = _SUNXI_CCU_DIV(0, 1), /* output divider */
+ .common = {
+ .reg = 0x030,
+ .hw.init = CLK_HW_INIT("pll-gpu", "osc24M",
+ &ccu_nkmp_ops,
+ CLK_SET_RATE_UNGATE),
+ },
+};
+
+/*
+ * For Video PLLs, the output divider is described as "used for testing"
+ * in the user manual. So it's not modelled and forced to 0.
+ */
+#define SUN50I_H616_PLL_VIDEO0_REG 0x040
+static struct ccu_nm pll_video0_clk = {
+ .enable = BIT(31),
+ .lock = BIT(28),
+ .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
+ .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
+ .fixed_post_div = 4,
+ .min_rate = 288000000,
+ .max_rate = 2400000000UL,
+ .common = {
+ .reg = 0x040,
+ .features = CCU_FEATURE_FIXED_POSTDIV,
+ .hw.init = CLK_HW_INIT("pll-video0", "osc24M",
+ &ccu_nm_ops,
+ CLK_SET_RATE_UNGATE),
+ },
+};
+
+#define SUN50I_H616_PLL_VIDEO1_REG 0x048
+static struct ccu_nm pll_video1_clk = {
+ .enable = BIT(31),
+ .lock = BIT(28),
+ .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
+ .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
+ .fixed_post_div = 4,
+ .min_rate = 288000000,
+ .max_rate = 2400000000UL,
+ .common = {
+ .reg = 0x048,
+ .features = CCU_FEATURE_FIXED_POSTDIV,
+ .hw.init = CLK_HW_INIT("pll-video1", "osc24M",
+ &ccu_nm_ops,
+ CLK_SET_RATE_UNGATE),
+ },
+};
+
+#define SUN50I_H616_PLL_VIDEO2_REG 0x050
+static struct ccu_nm pll_video2_clk = {
+ .enable = BIT(31),
+ .lock = BIT(28),
+ .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
+ .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
+ .fixed_post_div = 4,
+ .min_rate = 288000000,
+ .max_rate = 2400000000UL,
+ .common = {
+ .reg = 0x050,
+ .features = CCU_FEATURE_FIXED_POSTDIV,
+ .hw.init = CLK_HW_INIT("pll-video2", "osc24M",
+ &ccu_nm_ops,
+ CLK_SET_RATE_UNGATE),
+ },
+};
+
+#define SUN50I_H616_PLL_VE_REG 0x058
+static struct ccu_nkmp pll_ve_clk = {
+ .enable = BIT(31),
+ .lock = BIT(28),
+ .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
+ .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
+ .p = _SUNXI_CCU_DIV(0, 1), /* output divider */
+ .common = {
+ .reg = 0x058,
+ .hw.init = CLK_HW_INIT("pll-ve", "osc24M",
+ &ccu_nkmp_ops,
+ CLK_SET_RATE_UNGATE),
+ },
+};
+
+#define SUN50I_H616_PLL_DE_REG 0x060
+static struct ccu_nkmp pll_de_clk = {
+ .enable = BIT(31),
+ .lock = BIT(28),
+ .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
+ .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
+ .p = _SUNXI_CCU_DIV(0, 1), /* output divider */
+ .common = {
+ .reg = 0x060,
+ .hw.init = CLK_HW_INIT("pll-de", "osc24M",
+ &ccu_nkmp_ops,
+ CLK_SET_RATE_UNGATE),
+ },
+};
+
+/*
+ * TODO: Determine SDM settings for the audio PLL. The manual suggests
+ * PLL_FACTOR_N=16, PLL_POST_DIV_P=2, OUTPUT_DIV=2, pattern=0xe000c49b
+ * for 24.576 MHz, and PLL_FACTOR_N=22, PLL_POST_DIV_P=3, OUTPUT_DIV=2,
+ * pattern=0xe001288c for 22.5792 MHz.
+ * This clashes with our fixed PLL_POST_DIV_P.
+ */
+#define SUN50I_H616_PLL_AUDIO_REG 0x078
+static struct ccu_nm pll_audio_hs_clk = {
+ .enable = BIT(31),
+ .lock = BIT(28),
+ .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
+ .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
+ .common = {
+ .reg = 0x078,
+ .hw.init = CLK_HW_INIT("pll-audio-hs", "osc24M",
+ &ccu_nm_ops,
+ CLK_SET_RATE_UNGATE),
+ },
+};
+
+static const char * const cpux_parents[] = { "osc24M", "osc32k",
+ "iosc", "pll-cpux", "pll-periph0" };
+static SUNXI_CCU_MUX(cpux_clk, "cpux", cpux_parents,
+ 0x500, 24, 3, CLK_SET_RATE_PARENT | CLK_IS_CRITICAL);
+static SUNXI_CCU_M(axi_clk, "axi", "cpux", 0x500, 0, 2, 0);
+static SUNXI_CCU_M(cpux_apb_clk, "cpux-apb", "cpux", 0x500, 8, 2, 0);
+
+static const char * const psi_ahb1_ahb2_parents[] = { "osc24M", "osc32k",
+ "iosc", "pll-periph0" };
+static SUNXI_CCU_MP_WITH_MUX(psi_ahb1_ahb2_clk, "psi-ahb1-ahb2",
+ psi_ahb1_ahb2_parents,
+ 0x510,
+ 0, 2, /* M */
+ 8, 2, /* P */
+ 24, 2, /* mux */
+ 0);
+
+static const char * const ahb3_apb1_apb2_parents[] = { "osc24M", "osc32k",
+ "psi-ahb1-ahb2",
+ "pll-periph0" };
+static SUNXI_CCU_MP_WITH_MUX(ahb3_clk, "ahb3", ahb3_apb1_apb2_parents, 0x51c,
+ 0, 2, /* M */
+ 8, 2, /* P */
+ 24, 2, /* mux */
+ 0);
+
+static SUNXI_CCU_MP_WITH_MUX(apb1_clk, "apb1", ahb3_apb1_apb2_parents, 0x520,
+ 0, 2, /* M */
+ 8, 2, /* P */
+ 24, 2, /* mux */
+ 0);
+
+static SUNXI_CCU_MP_WITH_MUX(apb2_clk, "apb2", ahb3_apb1_apb2_parents, 0x524,
+ 0, 2, /* M */
+ 8, 2, /* P */
+ 24, 2, /* mux */
+ 0);
+
+static const char * const mbus_parents[] = { "osc24M", "pll-periph0-2x",
+ "pll-ddr0", "pll-ddr1" };
+static SUNXI_CCU_M_WITH_MUX_GATE(mbus_clk, "mbus", mbus_parents, 0x540,
+ 0, 3, /* M */
+ 24, 2, /* mux */
+ BIT(31), /* gate */
+ CLK_IS_CRITICAL);
+
+static const char * const de_parents[] = { "pll-de", "pll-periph0-2x" };
+static SUNXI_CCU_M_WITH_MUX_GATE(de_clk, "de", de_parents, 0x600,
+ 0, 4, /* M */
+ 24, 1, /* mux */
+ BIT(31), /* gate */
+ CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_GATE(bus_de_clk, "bus-de", "psi-ahb1-ahb2",
+ 0x60c, BIT(0), 0);
+
+static SUNXI_CCU_M_WITH_MUX_GATE(deinterlace_clk, "deinterlace",
+ de_parents,
+ 0x620,
+ 0, 4, /* M */
+ 24, 1, /* mux */
+ BIT(31), /* gate */
+ 0);
+
+static SUNXI_CCU_GATE(bus_deinterlace_clk, "bus-deinterlace", "psi-ahb1-ahb2",
+ 0x62c, BIT(0), 0);
+
+static SUNXI_CCU_M_WITH_MUX_GATE(g2d_clk, "g2d", de_parents, 0x630,
+ 0, 4, /* M */
+ 24, 1, /* mux */
+ BIT(31), /* gate */
+ 0);
+
+static SUNXI_CCU_GATE(bus_g2d_clk, "bus-g2d", "psi-ahb1-ahb2",
+ 0x63c, BIT(0), 0);
+
+static const char * const gpu0_parents[] = { "pll-gpu", "gpu1" };
+static SUNXI_CCU_M_WITH_MUX_GATE(gpu0_clk, "gpu0", gpu0_parents, 0x670,
+ 0, 2, /* M */
+ 24, 1, /* mux */
+ BIT(31), /* gate */
+ CLK_SET_RATE_PARENT);
+static SUNXI_CCU_M_WITH_GATE(gpu1_clk, "gpu1", "pll-periph0-2x", 0x674,
+ 0, 2, /* M */
+ BIT(31),/* gate */
+ 0);
+
+static SUNXI_CCU_GATE(bus_gpu_clk, "bus-gpu", "psi-ahb1-ahb2",
+ 0x67c, BIT(0), 0);
+
+static const char * const ce_parents[] = { "osc24M", "pll-periph0-2x" };
+static SUNXI_CCU_MP_WITH_MUX_GATE(ce_clk, "ce", ce_parents, 0x680,
+ 0, 4, /* M */
+ 8, 2, /* N */
+ 24, 1, /* mux */
+ BIT(31),/* gate */
+ 0);
+
+static SUNXI_CCU_GATE(bus_ce_clk, "bus-ce", "psi-ahb1-ahb2",
+ 0x68c, BIT(0), 0);
+
+static const char * const ve_parents[] = { "pll-ve" };
+static SUNXI_CCU_M_WITH_MUX_GATE(ve_clk, "ve", ve_parents, 0x690,
+ 0, 3, /* M */
+ 24, 1, /* mux */
+ BIT(31), /* gate */
+ CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_GATE(bus_ve_clk, "bus-ve", "psi-ahb1-ahb2",
+ 0x69c, BIT(0), 0);
+
+static SUNXI_CCU_GATE(bus_dma_clk, "bus-dma", "psi-ahb1-ahb2",
+ 0x70c, BIT(0), 0);
+
+static SUNXI_CCU_GATE(bus_hstimer_clk, "bus-hstimer", "psi-ahb1-ahb2",
+ 0x73c, BIT(0), 0);
+
+static SUNXI_CCU_GATE(avs_clk, "avs", "osc24M", 0x740, BIT(31), 0);
+
+static SUNXI_CCU_GATE(bus_dbg_clk, "bus-dbg", "psi-ahb1-ahb2",
+ 0x78c, BIT(0), 0);
+
+static SUNXI_CCU_GATE(bus_psi_clk, "bus-psi", "psi-ahb1-ahb2",
+ 0x79c, BIT(0), 0);
+
+static SUNXI_CCU_GATE(bus_pwm_clk, "bus-pwm", "apb1", 0x7ac, BIT(0), 0);
+
+static SUNXI_CCU_GATE(bus_iommu_clk, "bus-iommu", "apb1", 0x7bc, BIT(0), 0);
+
+static const char * const dram_parents[] = { "pll-ddr0", "pll-ddr1" };
+static struct ccu_div dram_clk = {
+ .div = _SUNXI_CCU_DIV(0, 2),
+ .mux = _SUNXI_CCU_MUX(24, 2),
+ .common = {
+ .reg = 0x800,
+ .hw.init = CLK_HW_INIT_PARENTS("dram",
+ dram_parents,
+ &ccu_div_ops,
+ CLK_IS_CRITICAL),
+ },
+};
+
+static SUNXI_CCU_GATE(mbus_dma_clk, "mbus-dma", "mbus",
+ 0x804, BIT(0), 0);
+static SUNXI_CCU_GATE(mbus_ve_clk, "mbus-ve", "mbus",
+ 0x804, BIT(1), 0);
+static SUNXI_CCU_GATE(mbus_ce_clk, "mbus-ce", "mbus",
+ 0x804, BIT(2), 0);
+static SUNXI_CCU_GATE(mbus_ts_clk, "mbus-ts", "mbus",
+ 0x804, BIT(3), 0);
+static SUNXI_CCU_GATE(mbus_nand_clk, "mbus-nand", "mbus",
+ 0x804, BIT(5), 0);
+static SUNXI_CCU_GATE(mbus_g2d_clk, "mbus-g2d", "mbus",
+ 0x804, BIT(10), 0);
+
+static SUNXI_CCU_GATE(bus_dram_clk, "bus-dram", "psi-ahb1-ahb2",
+ 0x80c, BIT(0), CLK_IS_CRITICAL);
+
+static const char * const nand_spi_parents[] = { "osc24M", "pll-periph0",
+ "pll-periph1", "pll-periph0-2x",
+ "pll-periph1-2x" };
+static SUNXI_CCU_MP_WITH_MUX_GATE(nand0_clk, "nand0", nand_spi_parents, 0x810,
+ 0, 4, /* M */
+ 8, 2, /* N */
+ 24, 3, /* mux */
+ BIT(31),/* gate */
+ 0);
+
+static SUNXI_CCU_MP_WITH_MUX_GATE(nand1_clk, "nand1", nand_spi_parents, 0x814,
+ 0, 4, /* M */
+ 8, 2, /* N */
+ 24, 3, /* mux */
+ BIT(31),/* gate */
+ 0);
+
+static SUNXI_CCU_GATE(bus_nand_clk, "bus-nand", "ahb3", 0x82c, BIT(0), 0);
+
+static const char * const mmc_parents[] = { "osc24M", "pll-periph0-2x",
+ "pll-periph1-2x" };
+static SUNXI_CCU_MP_WITH_MUX_GATE_POSTDIV(mmc0_clk, "mmc0", mmc_parents, 0x830,
+ 0, 4, /* M */
+ 8, 2, /* N */
+ 24, 2, /* mux */
+ BIT(31), /* gate */
+ 2, /* post-div */
+ 0);
+
+static SUNXI_CCU_MP_WITH_MUX_GATE_POSTDIV(mmc1_clk, "mmc1", mmc_parents, 0x834,
+ 0, 4, /* M */
+ 8, 2, /* N */
+ 24, 2, /* mux */
+ BIT(31), /* gate */
+ 2, /* post-div */
+ 0);
+
+static SUNXI_CCU_MP_WITH_MUX_GATE_POSTDIV(mmc2_clk, "mmc2", mmc_parents, 0x838,
+ 0, 4, /* M */
+ 8, 2, /* N */
+ 24, 2, /* mux */
+ BIT(31), /* gate */
+ 2, /* post-div */
+ 0);
+
+static SUNXI_CCU_GATE(bus_mmc0_clk, "bus-mmc0", "ahb3", 0x84c, BIT(0), 0);
+static SUNXI_CCU_GATE(bus_mmc1_clk, "bus-mmc1", "ahb3", 0x84c, BIT(1), 0);
+static SUNXI_CCU_GATE(bus_mmc2_clk, "bus-mmc2", "ahb3", 0x84c, BIT(2), 0);
+
+static SUNXI_CCU_GATE(bus_uart0_clk, "bus-uart0", "apb2", 0x90c, BIT(0), 0);
+static SUNXI_CCU_GATE(bus_uart1_clk, "bus-uart1", "apb2", 0x90c, BIT(1), 0);
+static SUNXI_CCU_GATE(bus_uart2_clk, "bus-uart2", "apb2", 0x90c, BIT(2), 0);
+static SUNXI_CCU_GATE(bus_uart3_clk, "bus-uart3", "apb2", 0x90c, BIT(3), 0);
+static SUNXI_CCU_GATE(bus_uart4_clk, "bus-uart4", "apb2", 0x90c, BIT(4), 0);
+static SUNXI_CCU_GATE(bus_uart5_clk, "bus-uart5", "apb2", 0x90c, BIT(5), 0);
+
+static SUNXI_CCU_GATE(bus_i2c0_clk, "bus-i2c0", "apb2", 0x91c, BIT(0), 0);
+static SUNXI_CCU_GATE(bus_i2c1_clk, "bus-i2c1", "apb2", 0x91c, BIT(1), 0);
+static SUNXI_CCU_GATE(bus_i2c2_clk, "bus-i2c2", "apb2", 0x91c, BIT(2), 0);
+static SUNXI_CCU_GATE(bus_i2c3_clk, "bus-i2c3", "apb2", 0x91c, BIT(3), 0);
+static SUNXI_CCU_GATE(bus_i2c4_clk, "bus-i2c4", "apb2", 0x91c, BIT(4), 0);
+
+static SUNXI_CCU_MP_WITH_MUX_GATE(spi0_clk, "spi0", nand_spi_parents, 0x940,
+ 0, 4, /* M */
+ 8, 2, /* N */
+ 24, 3, /* mux */
+ BIT(31),/* gate */
+ 0);
+
+static SUNXI_CCU_MP_WITH_MUX_GATE(spi1_clk, "spi1", nand_spi_parents, 0x944,
+ 0, 4, /* M */
+ 8, 2, /* N */
+ 24, 3, /* mux */
+ BIT(31),/* gate */
+ 0);
+
+static SUNXI_CCU_GATE(bus_spi0_clk, "bus-spi0", "ahb3", 0x96c, BIT(0), 0);
+static SUNXI_CCU_GATE(bus_spi1_clk, "bus-spi1", "ahb3", 0x96c, BIT(1), 0);
+
+static SUNXI_CCU_GATE(emac_25m_clk, "emac-25m", "ahb3", 0x970,
+ BIT(31) | BIT(30), 0);
+
+static SUNXI_CCU_GATE(bus_emac0_clk, "bus-emac0", "ahb3", 0x97c, BIT(0), 0);
+static SUNXI_CCU_GATE(bus_emac1_clk, "bus-emac1", "ahb3", 0x97c, BIT(1), 0);
+
+static const char * const ts_parents[] = { "osc24M", "pll-periph0" };
+static SUNXI_CCU_MP_WITH_MUX_GATE(ts_clk, "ts", ts_parents, 0x9b0,
+ 0, 4, /* M */
+ 8, 2, /* N */
+ 24, 1, /* mux */
+ BIT(31),/* gate */
+ 0);
+
+static SUNXI_CCU_GATE(bus_ts_clk, "bus-ts", "ahb3", 0x9bc, BIT(0), 0);
+
+static SUNXI_CCU_GATE(bus_ths_clk, "bus-ths", "apb1", 0x9fc, BIT(0), 0);
+
+static const char * const audio_parents[] = { "pll-audio-1x", "pll-audio-2x",
+ "pll-audio-4x", "pll-audio-hs" };
+static struct ccu_div spdif_clk = {
+ .enable = BIT(31),
+ .div = _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO),
+ .mux = _SUNXI_CCU_MUX(24, 2),
+ .common = {
+ .reg = 0xa20,
+ .hw.init = CLK_HW_INIT_PARENTS("spdif",
+ audio_parents,
+ &ccu_div_ops,
+ 0),
+ },
+};
+
+static SUNXI_CCU_GATE(bus_spdif_clk, "bus-spdif", "apb1", 0xa2c, BIT(0), 0);
+
+static struct ccu_div dmic_clk = {
+ .enable = BIT(31),
+ .div = _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO),
+ .mux = _SUNXI_CCU_MUX(24, 2),
+ .common = {
+ .reg = 0xa40,
+ .hw.init = CLK_HW_INIT_PARENTS("dmic",
+ audio_parents,
+ &ccu_div_ops,
+ 0),
+ },
+};
+
+static SUNXI_CCU_GATE(bus_dmic_clk, "bus-dmic", "apb1", 0xa4c, BIT(0), 0);
+
+static SUNXI_CCU_M_WITH_MUX_GATE(audio_codec_1x_clk, "audio-codec-1x",
+ audio_parents, 0xa50,
+ 0, 4, /* M */
+ 24, 2, /* mux */
+ BIT(31), /* gate */
+ CLK_SET_RATE_PARENT);
+static SUNXI_CCU_M_WITH_MUX_GATE(audio_codec_4x_clk, "audio-codec-4x",
+ audio_parents, 0xa54,
+ 0, 4, /* M */
+ 24, 2, /* mux */
+ BIT(31), /* gate */
+ CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_GATE(bus_audio_codec_clk, "bus-audio-codec", "apb1", 0xa5c,
+ BIT(0), 0);
+
+static struct ccu_div audio_hub_clk = {
+ .enable = BIT(31),
+ .div = _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO),
+ .mux = _SUNXI_CCU_MUX(24, 2),
+ .common = {
+ .reg = 0xa60,
+ .hw.init = CLK_HW_INIT_PARENTS("audio-hub",
+ audio_parents,
+ &ccu_div_ops,
+ 0),
+ },
+};
+
+static SUNXI_CCU_GATE(bus_audio_hub_clk, "bus-audio-hub", "apb1", 0xa6c, BIT(0), 0);
+
+/*
+ * There are OHCI 12M clock source selection bits for the four USB 2.0 ports.
+ * We will force them to 0 (12M divided from 48M).
+ */
+#define SUN50I_H616_USB0_CLK_REG 0xa70
+#define SUN50I_H616_USB1_CLK_REG 0xa74
+#define SUN50I_H616_USB2_CLK_REG 0xa78
+#define SUN50I_H616_USB3_CLK_REG 0xa7c
+
+static SUNXI_CCU_GATE(usb_ohci0_clk, "usb-ohci0", "osc12M", 0xa70, BIT(31), 0);
+static SUNXI_CCU_GATE(usb_phy0_clk, "usb-phy0", "osc24M", 0xa70, BIT(29), 0);
+
+static SUNXI_CCU_GATE(usb_ohci1_clk, "usb-ohci1", "osc12M", 0xa74, BIT(31), 0);
+static SUNXI_CCU_GATE(usb_phy1_clk, "usb-phy1", "osc24M", 0xa74, BIT(29), 0);
+
+static SUNXI_CCU_GATE(usb_ohci2_clk, "usb-ohci2", "osc12M", 0xa78, BIT(31), 0);
+static SUNXI_CCU_GATE(usb_phy2_clk, "usb-phy2", "osc24M", 0xa78, BIT(29), 0);
+
+static SUNXI_CCU_GATE(usb_ohci3_clk, "usb-ohci3", "osc12M", 0xa7c, BIT(31), 0);
+static SUNXI_CCU_GATE(usb_phy3_clk, "usb-phy3", "osc24M", 0xa7c, BIT(29), 0);
+
+static SUNXI_CCU_GATE(bus_ohci0_clk, "bus-ohci0", "ahb3", 0xa8c, BIT(0), 0);
+static SUNXI_CCU_GATE(bus_ohci1_clk, "bus-ohci1", "ahb3", 0xa8c, BIT(1), 0);
+static SUNXI_CCU_GATE(bus_ohci2_clk, "bus-ohci2", "ahb3", 0xa8c, BIT(2), 0);
+static SUNXI_CCU_GATE(bus_ohci3_clk, "bus-ohci3", "ahb3", 0xa8c, BIT(3), 0);
+static SUNXI_CCU_GATE(bus_ehci0_clk, "bus-ehci0", "ahb3", 0xa8c, BIT(4), 0);
+static SUNXI_CCU_GATE(bus_ehci1_clk, "bus-ehci1", "ahb3", 0xa8c, BIT(5), 0);
+static SUNXI_CCU_GATE(bus_ehci2_clk, "bus-ehci2", "ahb3", 0xa8c, BIT(6), 0);
+static SUNXI_CCU_GATE(bus_ehci3_clk, "bus-ehci3", "ahb3", 0xa8c, BIT(7), 0);
+static SUNXI_CCU_GATE(bus_otg_clk, "bus-otg", "ahb3", 0xa8c, BIT(8), 0);
+
+static SUNXI_CCU_GATE(bus_keyadc_clk, "bus-keyadc", "apb1", 0xa9c, BIT(0), 0);
+
+static const char * const hdmi_parents[] = { "pll-video0", "pll-video0-4x",
+ "pll-video2", "pll-video2-4x" };
+static SUNXI_CCU_M_WITH_MUX_GATE(hdmi_clk, "hdmi", hdmi_parents, 0xb00,
+ 0, 4, /* M */
+ 24, 2, /* mux */
+ BIT(31), /* gate */
+ 0);
+
+static SUNXI_CCU_GATE(hdmi_slow_clk, "hdmi-slow", "osc24M", 0xb04, BIT(31), 0);
+
+static const char * const hdmi_cec_parents[] = { "osc32k", "pll-periph0-2x" };
+static const struct ccu_mux_fixed_prediv hdmi_cec_predivs[] = {
+ { .index = 1, .div = 36621 },
+};
+
+#define SUN50I_H616_HDMI_CEC_CLK_REG 0xb10
+static struct ccu_mux hdmi_cec_clk = {
+ .enable = BIT(31) | BIT(30),
+
+ .mux = {
+ .shift = 24,
+ .width = 2,
+
+ .fixed_predivs = hdmi_cec_predivs,
+ .n_predivs = ARRAY_SIZE(hdmi_cec_predivs),
+ },
+
+ .common = {
+ .reg = 0xb10,
+ .features = CCU_FEATURE_FIXED_PREDIV,
+ .hw.init = CLK_HW_INIT_PARENTS("hdmi-cec",
+ hdmi_cec_parents,
+ &ccu_mux_ops,
+ 0),
+ },
+};
+
+static SUNXI_CCU_GATE(bus_hdmi_clk, "bus-hdmi", "ahb3", 0xb1c, BIT(0), 0);
+
+static SUNXI_CCU_GATE(bus_tcon_top_clk, "bus-tcon-top", "ahb3",
+ 0xb5c, BIT(0), 0);
+
+static const char * const tcon_tv_parents[] = { "pll-video0",
+ "pll-video0-4x",
+ "pll-video1",
+ "pll-video1-4x" };
+static SUNXI_CCU_MP_WITH_MUX_GATE(tcon_tv0_clk, "tcon-tv0",
+ tcon_tv_parents, 0xb80,
+ 0, 4, /* M */
+ 8, 2, /* P */
+ 24, 3, /* mux */
+ BIT(31), /* gate */
+ CLK_SET_RATE_PARENT);
+static SUNXI_CCU_MP_WITH_MUX_GATE(tcon_tv1_clk, "tcon-tv1",
+ tcon_tv_parents, 0xb84,
+ 0, 4, /* M */
+ 8, 2, /* P */
+ 24, 3, /* mux */
+ BIT(31), /* gate */
+ CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_GATE(bus_tcon_tv0_clk, "bus-tcon-tv0", "ahb3",
+ 0xb9c, BIT(0), 0);
+static SUNXI_CCU_GATE(bus_tcon_tv1_clk, "bus-tcon-tv1", "ahb3",
+ 0xb9c, BIT(1), 0);
+
+static SUNXI_CCU_MP_WITH_MUX_GATE(tve0_clk, "tve0",
+ tcon_tv_parents, 0xbb0,
+ 0, 4, /* M */
+ 8, 2, /* P */
+ 24, 3, /* mux */
+ BIT(31), /* gate */
+ CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_GATE(bus_tve_top_clk, "bus-tve-top", "ahb3",
+ 0xbbc, BIT(0), 0);
+static SUNXI_CCU_GATE(bus_tve0_clk, "bus-tve0", "ahb3",
+ 0xbbc, BIT(1), 0);
+
+static const char * const hdcp_parents[] = { "pll-periph0", "pll-periph1" };
+static SUNXI_CCU_M_WITH_MUX_GATE(hdcp_clk, "hdcp", hdcp_parents, 0xc40,
+ 0, 4, /* M */
+ 24, 2, /* mux */
+ BIT(31), /* gate */
+ 0);
+
+static SUNXI_CCU_GATE(bus_hdcp_clk, "bus-hdcp", "ahb3", 0xc4c, BIT(0), 0);
+
+/* Fixed factor clocks */
+static CLK_FIXED_FACTOR_FW_NAME(osc12M_clk, "osc12M", "hosc", 2, 1, 0);
+
+static const struct clk_hw *clk_parent_pll_audio[] = {
+ &pll_audio_hs_clk.common.hw
+};
+
+/*
+ * The divider of pll-audio is fixed to 24 for now, so 24576000 and 22579200
+ * rates can be set exactly in conjunction with sigma-delta modulation.
+ */
+static CLK_FIXED_FACTOR_HWS(pll_audio_1x_clk, "pll-audio-1x",
+ clk_parent_pll_audio,
+ 96, 1, CLK_SET_RATE_PARENT);
+static CLK_FIXED_FACTOR_HWS(pll_audio_2x_clk, "pll-audio-2x",
+ clk_parent_pll_audio,
+ 48, 1, CLK_SET_RATE_PARENT);
+static CLK_FIXED_FACTOR_HWS(pll_audio_4x_clk, "pll-audio-4x",
+ clk_parent_pll_audio,
+ 24, 1, CLK_SET_RATE_PARENT);
+
+static const struct clk_hw *pll_periph0_parents[] = {
+ &pll_periph0_clk.common.hw
+};
+
+static CLK_FIXED_FACTOR_HWS(pll_periph0_2x_clk, "pll-periph0-2x",
+ pll_periph0_parents,
+ 1, 2, 0);
+
+static const struct clk_hw *pll_periph1_parents[] = {
+ &pll_periph1_clk.common.hw
+};
+
+static CLK_FIXED_FACTOR_HWS(pll_periph1_2x_clk, "pll-periph1-2x",
+ pll_periph1_parents,
+ 1, 2, 0);
+
+static CLK_FIXED_FACTOR_HW(pll_video0_4x_clk, "pll-video0-4x",
+ &pll_video0_clk.common.hw,
+ 1, 4, CLK_SET_RATE_PARENT);
+static CLK_FIXED_FACTOR_HW(pll_video1_4x_clk, "pll-video1-4x",
+ &pll_video1_clk.common.hw,
+ 1, 4, CLK_SET_RATE_PARENT);
+static CLK_FIXED_FACTOR_HW(pll_video2_4x_clk, "pll-video2-4x",
+ &pll_video2_clk.common.hw,
+ 1, 4, CLK_SET_RATE_PARENT);
+
+static struct ccu_common *sun50i_h616_ccu_clks[] = {
+ &pll_cpux_clk.common,
+ &pll_ddr0_clk.common,
+ &pll_ddr1_clk.common,
+ &pll_periph0_clk.common,
+ &pll_periph1_clk.common,
+ &pll_gpu_clk.common,
+ &pll_video0_clk.common,
+ &pll_video1_clk.common,
+ &pll_video2_clk.common,
+ &pll_ve_clk.common,
+ &pll_de_clk.common,
+ &pll_audio_hs_clk.common,
+ &cpux_clk.common,
+ &axi_clk.common,
+ &cpux_apb_clk.common,
+ &psi_ahb1_ahb2_clk.common,
+ &ahb3_clk.common,
+ &apb1_clk.common,
+ &apb2_clk.common,
+ &mbus_clk.common,
+ &de_clk.common,
+ &bus_de_clk.common,
+ &deinterlace_clk.common,
+ &bus_deinterlace_clk.common,
+ &g2d_clk.common,
+ &bus_g2d_clk.common,
+ &gpu0_clk.common,
+ &bus_gpu_clk.common,
+ &gpu1_clk.common,
+ &ce_clk.common,
+ &bus_ce_clk.common,
+ &ve_clk.common,
+ &bus_ve_clk.common,
+ &bus_dma_clk.common,
+ &bus_hstimer_clk.common,
+ &avs_clk.common,
+ &bus_dbg_clk.common,
+ &bus_psi_clk.common,
+ &bus_pwm_clk.common,
+ &bus_iommu_clk.common,
+ &dram_clk.common,
+ &mbus_dma_clk.common,
+ &mbus_ve_clk.common,
+ &mbus_ce_clk.common,
+ &mbus_ts_clk.common,
+ &mbus_nand_clk.common,
+ &mbus_g2d_clk.common,
+ &bus_dram_clk.common,
+ &nand0_clk.common,
+ &nand1_clk.common,
+ &bus_nand_clk.common,
+ &mmc0_clk.common,
+ &mmc1_clk.common,
+ &mmc2_clk.common,
+ &bus_mmc0_clk.common,
+ &bus_mmc1_clk.common,
+ &bus_mmc2_clk.common,
+ &bus_uart0_clk.common,
+ &bus_uart1_clk.common,
+ &bus_uart2_clk.common,
+ &bus_uart3_clk.common,
+ &bus_uart4_clk.common,
+ &bus_uart5_clk.common,
+ &bus_i2c0_clk.common,
+ &bus_i2c1_clk.common,
+ &bus_i2c2_clk.common,
+ &bus_i2c3_clk.common,
+ &bus_i2c4_clk.common,
+ &spi0_clk.common,
+ &spi1_clk.common,
+ &bus_spi0_clk.common,
+ &bus_spi1_clk.common,
+ &emac_25m_clk.common,
+ &bus_emac0_clk.common,
+ &bus_emac1_clk.common,
+ &ts_clk.common,
+ &bus_ts_clk.common,
+ &bus_ths_clk.common,
+ &spdif_clk.common,
+ &bus_spdif_clk.common,
+ &dmic_clk.common,
+ &bus_dmic_clk.common,
+ &audio_codec_1x_clk.common,
+ &audio_codec_4x_clk.common,
+ &bus_audio_codec_clk.common,
+ &audio_hub_clk.common,
+ &bus_audio_hub_clk.common,
+ &usb_ohci0_clk.common,
+ &usb_phy0_clk.common,
+ &usb_ohci1_clk.common,
+ &usb_phy1_clk.common,
+ &usb_ohci2_clk.common,
+ &usb_phy2_clk.common,
+ &usb_ohci3_clk.common,
+ &usb_phy3_clk.common,
+ &bus_ohci0_clk.common,
+ &bus_ohci1_clk.common,
+ &bus_ohci2_clk.common,
+ &bus_ohci3_clk.common,
+ &bus_ehci0_clk.common,
+ &bus_ehci1_clk.common,
+ &bus_ehci2_clk.common,
+ &bus_ehci3_clk.common,
+ &bus_otg_clk.common,
+ &bus_keyadc_clk.common,
+ &hdmi_clk.common,
+ &hdmi_slow_clk.common,
+ &hdmi_cec_clk.common,
+ &bus_hdmi_clk.common,
+ &bus_tcon_top_clk.common,
+ &tcon_tv0_clk.common,
+ &tcon_tv1_clk.common,
+ &bus_tcon_tv0_clk.common,
+ &bus_tcon_tv1_clk.common,
+ &tve0_clk.common,
+ &bus_tve_top_clk.common,
+ &bus_tve0_clk.common,
+ &hdcp_clk.common,
+ &bus_hdcp_clk.common,
+};
+
+static struct clk_hw_onecell_data sun50i_h616_hw_clks = {
+ .hws = {
+ [CLK_OSC12M] = &osc12M_clk.hw,
+ [CLK_PLL_CPUX] = &pll_cpux_clk.common.hw,
+ [CLK_PLL_DDR0] = &pll_ddr0_clk.common.hw,
+ [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_PERIPH1] = &pll_periph1_clk.common.hw,
+ [CLK_PLL_PERIPH1_2X] = &pll_periph1_2x_clk.hw,
+ [CLK_PLL_GPU] = &pll_gpu_clk.common.hw,
+ [CLK_PLL_VIDEO0] = &pll_video0_clk.common.hw,
+ [CLK_PLL_VIDEO0_4X] = &pll_video0_4x_clk.hw,
+ [CLK_PLL_VIDEO1] = &pll_video1_clk.common.hw,
+ [CLK_PLL_VIDEO1_4X] = &pll_video1_4x_clk.hw,
+ [CLK_PLL_VIDEO2] = &pll_video2_clk.common.hw,
+ [CLK_PLL_VIDEO2_4X] = &pll_video2_4x_clk.hw,
+ [CLK_PLL_VE] = &pll_ve_clk.common.hw,
+ [CLK_PLL_DE] = &pll_de_clk.common.hw,
+ [CLK_PLL_AUDIO_HS] = &pll_audio_hs_clk.common.hw,
+ [CLK_PLL_AUDIO_1X] = &pll_audio_1x_clk.hw,
+ [CLK_PLL_AUDIO_2X] = &pll_audio_2x_clk.hw,
+ [CLK_PLL_AUDIO_4X] = &pll_audio_4x_clk.hw,
+ [CLK_CPUX] = &cpux_clk.common.hw,
+ [CLK_AXI] = &axi_clk.common.hw,
+ [CLK_CPUX_APB] = &cpux_apb_clk.common.hw,
+ [CLK_PSI_AHB1_AHB2] = &psi_ahb1_ahb2_clk.common.hw,
+ [CLK_AHB3] = &ahb3_clk.common.hw,
+ [CLK_APB1] = &apb1_clk.common.hw,
+ [CLK_APB2] = &apb2_clk.common.hw,
+ [CLK_MBUS] = &mbus_clk.common.hw,
+ [CLK_DE] = &de_clk.common.hw,
+ [CLK_BUS_DE] = &bus_de_clk.common.hw,
+ [CLK_DEINTERLACE] = &deinterlace_clk.common.hw,
+ [CLK_BUS_DEINTERLACE] = &bus_deinterlace_clk.common.hw,
+ [CLK_G2D] = &g2d_clk.common.hw,
+ [CLK_BUS_G2D] = &bus_g2d_clk.common.hw,
+ [CLK_GPU0] = &gpu0_clk.common.hw,
+ [CLK_BUS_GPU] = &bus_gpu_clk.common.hw,
+ [CLK_GPU1] = &gpu1_clk.common.hw,
+ [CLK_CE] = &ce_clk.common.hw,
+ [CLK_BUS_CE] = &bus_ce_clk.common.hw,
+ [CLK_VE] = &ve_clk.common.hw,
+ [CLK_BUS_VE] = &bus_ve_clk.common.hw,
+ [CLK_BUS_DMA] = &bus_dma_clk.common.hw,
+ [CLK_BUS_HSTIMER] = &bus_hstimer_clk.common.hw,
+ [CLK_AVS] = &avs_clk.common.hw,
+ [CLK_BUS_DBG] = &bus_dbg_clk.common.hw,
+ [CLK_BUS_PSI] = &bus_psi_clk.common.hw,
+ [CLK_BUS_PWM] = &bus_pwm_clk.common.hw,
+ [CLK_BUS_IOMMU] = &bus_iommu_clk.common.hw,
+ [CLK_DRAM] = &dram_clk.common.hw,
+ [CLK_MBUS_DMA] = &mbus_dma_clk.common.hw,
+ [CLK_MBUS_VE] = &mbus_ve_clk.common.hw,
+ [CLK_MBUS_CE] = &mbus_ce_clk.common.hw,
+ [CLK_MBUS_TS] = &mbus_ts_clk.common.hw,
+ [CLK_MBUS_NAND] = &mbus_nand_clk.common.hw,
+ [CLK_MBUS_G2D] = &mbus_g2d_clk.common.hw,
+ [CLK_BUS_DRAM] = &bus_dram_clk.common.hw,
+ [CLK_NAND0] = &nand0_clk.common.hw,
+ [CLK_NAND1] = &nand1_clk.common.hw,
+ [CLK_BUS_NAND] = &bus_nand_clk.common.hw,
+ [CLK_MMC0] = &mmc0_clk.common.hw,
+ [CLK_MMC1] = &mmc1_clk.common.hw,
+ [CLK_MMC2] = &mmc2_clk.common.hw,
+ [CLK_BUS_MMC0] = &bus_mmc0_clk.common.hw,
+ [CLK_BUS_MMC1] = &bus_mmc1_clk.common.hw,
+ [CLK_BUS_MMC2] = &bus_mmc2_clk.common.hw,
+ [CLK_BUS_UART0] = &bus_uart0_clk.common.hw,
+ [CLK_BUS_UART1] = &bus_uart1_clk.common.hw,
+ [CLK_BUS_UART2] = &bus_uart2_clk.common.hw,
+ [CLK_BUS_UART3] = &bus_uart3_clk.common.hw,
+ [CLK_BUS_UART4] = &bus_uart4_clk.common.hw,
+ [CLK_BUS_UART5] = &bus_uart5_clk.common.hw,
+ [CLK_BUS_I2C0] = &bus_i2c0_clk.common.hw,
+ [CLK_BUS_I2C1] = &bus_i2c1_clk.common.hw,
+ [CLK_BUS_I2C2] = &bus_i2c2_clk.common.hw,
+ [CLK_BUS_I2C3] = &bus_i2c3_clk.common.hw,
+ [CLK_BUS_I2C4] = &bus_i2c4_clk.common.hw,
+ [CLK_SPI0] = &spi0_clk.common.hw,
+ [CLK_SPI1] = &spi1_clk.common.hw,
+ [CLK_BUS_SPI0] = &bus_spi0_clk.common.hw,
+ [CLK_BUS_SPI1] = &bus_spi1_clk.common.hw,
+ [CLK_EMAC_25M] = &emac_25m_clk.common.hw,
+ [CLK_BUS_EMAC0] = &bus_emac0_clk.common.hw,
+ [CLK_BUS_EMAC1] = &bus_emac1_clk.common.hw,
+ [CLK_TS] = &ts_clk.common.hw,
+ [CLK_BUS_TS] = &bus_ts_clk.common.hw,
+ [CLK_BUS_THS] = &bus_ths_clk.common.hw,
+ [CLK_SPDIF] = &spdif_clk.common.hw,
+ [CLK_BUS_SPDIF] = &bus_spdif_clk.common.hw,
+ [CLK_DMIC] = &dmic_clk.common.hw,
+ [CLK_BUS_DMIC] = &bus_dmic_clk.common.hw,
+ [CLK_AUDIO_CODEC_1X] = &audio_codec_1x_clk.common.hw,
+ [CLK_AUDIO_CODEC_4X] = &audio_codec_4x_clk.common.hw,
+ [CLK_BUS_AUDIO_CODEC] = &bus_audio_codec_clk.common.hw,
+ [CLK_AUDIO_HUB] = &audio_hub_clk.common.hw,
+ [CLK_BUS_AUDIO_HUB] = &bus_audio_hub_clk.common.hw,
+ [CLK_USB_OHCI0] = &usb_ohci0_clk.common.hw,
+ [CLK_USB_PHY0] = &usb_phy0_clk.common.hw,
+ [CLK_USB_OHCI1] = &usb_ohci1_clk.common.hw,
+ [CLK_USB_PHY1] = &usb_phy1_clk.common.hw,
+ [CLK_USB_OHCI2] = &usb_ohci2_clk.common.hw,
+ [CLK_USB_PHY2] = &usb_phy2_clk.common.hw,
+ [CLK_USB_OHCI3] = &usb_ohci3_clk.common.hw,
+ [CLK_USB_PHY3] = &usb_phy3_clk.common.hw,
+ [CLK_BUS_OHCI0] = &bus_ohci0_clk.common.hw,
+ [CLK_BUS_OHCI1] = &bus_ohci1_clk.common.hw,
+ [CLK_BUS_OHCI2] = &bus_ohci2_clk.common.hw,
+ [CLK_BUS_OHCI3] = &bus_ohci3_clk.common.hw,
+ [CLK_BUS_EHCI0] = &bus_ehci0_clk.common.hw,
+ [CLK_BUS_EHCI1] = &bus_ehci1_clk.common.hw,
+ [CLK_BUS_EHCI2] = &bus_ehci2_clk.common.hw,
+ [CLK_BUS_EHCI3] = &bus_ehci3_clk.common.hw,
+ [CLK_BUS_OTG] = &bus_otg_clk.common.hw,
+ [CLK_BUS_KEYADC] = &bus_keyadc_clk.common.hw,
+ [CLK_HDMI] = &hdmi_clk.common.hw,
+ [CLK_HDMI_SLOW] = &hdmi_slow_clk.common.hw,
+ [CLK_HDMI_CEC] = &hdmi_cec_clk.common.hw,
+ [CLK_BUS_HDMI] = &bus_hdmi_clk.common.hw,
+ [CLK_BUS_TCON_TOP] = &bus_tcon_top_clk.common.hw,
+ [CLK_TCON_TV0] = &tcon_tv0_clk.common.hw,
+ [CLK_TCON_TV1] = &tcon_tv1_clk.common.hw,
+ [CLK_BUS_TCON_TV0] = &bus_tcon_tv0_clk.common.hw,
+ [CLK_BUS_TCON_TV1] = &bus_tcon_tv1_clk.common.hw,
+ [CLK_TVE0] = &tve0_clk.common.hw,
+ [CLK_BUS_TVE_TOP] = &bus_tve_top_clk.common.hw,
+ [CLK_BUS_TVE0] = &bus_tve0_clk.common.hw,
+ [CLK_HDCP] = &hdcp_clk.common.hw,
+ [CLK_BUS_HDCP] = &bus_hdcp_clk.common.hw,
+ },
+ .num = CLK_NUMBER,
+};
+
+static struct ccu_reset_map sun50i_h616_ccu_resets[] = {
+ [RST_MBUS] = { 0x540, BIT(30) },
+
+ [RST_BUS_DE] = { 0x60c, BIT(16) },
+ [RST_BUS_DEINTERLACE] = { 0x62c, BIT(16) },
+ [RST_BUS_GPU] = { 0x67c, BIT(16) },
+ [RST_BUS_CE] = { 0x68c, BIT(16) },
+ [RST_BUS_VE] = { 0x69c, BIT(16) },
+ [RST_BUS_DMA] = { 0x70c, BIT(16) },
+ [RST_BUS_HSTIMER] = { 0x73c, BIT(16) },
+ [RST_BUS_DBG] = { 0x78c, BIT(16) },
+ [RST_BUS_PSI] = { 0x79c, BIT(16) },
+ [RST_BUS_PWM] = { 0x7ac, BIT(16) },
+ [RST_BUS_IOMMU] = { 0x7bc, BIT(16) },
+ [RST_BUS_DRAM] = { 0x80c, BIT(16) },
+ [RST_BUS_NAND] = { 0x82c, BIT(16) },
+ [RST_BUS_MMC0] = { 0x84c, BIT(16) },
+ [RST_BUS_MMC1] = { 0x84c, BIT(17) },
+ [RST_BUS_MMC2] = { 0x84c, BIT(18) },
+ [RST_BUS_UART0] = { 0x90c, BIT(16) },
+ [RST_BUS_UART1] = { 0x90c, BIT(17) },
+ [RST_BUS_UART2] = { 0x90c, BIT(18) },
+ [RST_BUS_UART3] = { 0x90c, BIT(19) },
+ [RST_BUS_UART4] = { 0x90c, BIT(20) },
+ [RST_BUS_UART5] = { 0x90c, BIT(21) },
+ [RST_BUS_I2C0] = { 0x91c, BIT(16) },
+ [RST_BUS_I2C1] = { 0x91c, BIT(17) },
+ [RST_BUS_I2C2] = { 0x91c, BIT(18) },
+ [RST_BUS_I2C3] = { 0x91c, BIT(19) },
+ [RST_BUS_I2C4] = { 0x91c, BIT(20) },
+ [RST_BUS_SPI0] = { 0x96c, BIT(16) },
+ [RST_BUS_SPI1] = { 0x96c, BIT(17) },
+ [RST_BUS_EMAC0] = { 0x97c, BIT(16) },
+ [RST_BUS_EMAC1] = { 0x97c, BIT(17) },
+ [RST_BUS_TS] = { 0x9bc, BIT(16) },
+ [RST_BUS_THS] = { 0x9fc, BIT(16) },
+ [RST_BUS_SPDIF] = { 0xa2c, BIT(16) },
+ [RST_BUS_DMIC] = { 0xa4c, BIT(16) },
+ [RST_BUS_AUDIO_CODEC] = { 0xa5c, BIT(16) },
+ [RST_BUS_AUDIO_HUB] = { 0xa6c, BIT(16) },
+
+ [RST_USB_PHY0] = { 0xa70, BIT(30) },
+ [RST_USB_PHY1] = { 0xa74, BIT(30) },
+ [RST_USB_PHY2] = { 0xa78, BIT(30) },
+ [RST_USB_PHY3] = { 0xa7c, BIT(30) },
+ [RST_BUS_OHCI0] = { 0xa8c, BIT(16) },
+ [RST_BUS_OHCI1] = { 0xa8c, BIT(17) },
+ [RST_BUS_OHCI2] = { 0xa8c, BIT(18) },
+ [RST_BUS_OHCI3] = { 0xa8c, BIT(19) },
+ [RST_BUS_EHCI0] = { 0xa8c, BIT(20) },
+ [RST_BUS_EHCI1] = { 0xa8c, BIT(21) },
+ [RST_BUS_EHCI2] = { 0xa8c, BIT(22) },
+ [RST_BUS_EHCI3] = { 0xa8c, BIT(23) },
+ [RST_BUS_OTG] = { 0xa8c, BIT(24) },
+ [RST_BUS_KEYADC] = { 0xa9c, BIT(16) },
+
+ [RST_BUS_HDMI] = { 0xb1c, BIT(16) },
+ [RST_BUS_HDMI_SUB] = { 0xb1c, BIT(17) },
+ [RST_BUS_TCON_TOP] = { 0xb5c, BIT(16) },
+ [RST_BUS_TCON_TV0] = { 0xb9c, BIT(16) },
+ [RST_BUS_TCON_TV1] = { 0xb9c, BIT(17) },
+ [RST_BUS_TVE_TOP] = { 0xbbc, BIT(16) },
+ [RST_BUS_TVE0] = { 0xbbc, BIT(17) },
+ [RST_BUS_HDCP] = { 0xc4c, BIT(16) },
+};
+
+static const struct sunxi_ccu_desc sun50i_h616_ccu_desc = {
+ .ccu_clks = sun50i_h616_ccu_clks,
+ .num_ccu_clks = ARRAY_SIZE(sun50i_h616_ccu_clks),
+
+ .hw_clks = &sun50i_h616_hw_clks,
+
+ .resets = sun50i_h616_ccu_resets,
+ .num_resets = ARRAY_SIZE(sun50i_h616_ccu_resets),
+};
+
+static const u32 pll_regs[] = {
+ SUN50I_H616_PLL_CPUX_REG,
+ SUN50I_H616_PLL_DDR0_REG,
+ SUN50I_H616_PLL_DDR1_REG,
+ SUN50I_H616_PLL_PERIPH0_REG,
+ SUN50I_H616_PLL_PERIPH1_REG,
+ SUN50I_H616_PLL_GPU_REG,
+ SUN50I_H616_PLL_VIDEO0_REG,
+ SUN50I_H616_PLL_VIDEO1_REG,
+ SUN50I_H616_PLL_VIDEO2_REG,
+ SUN50I_H616_PLL_VE_REG,
+ SUN50I_H616_PLL_DE_REG,
+ SUN50I_H616_PLL_AUDIO_REG,
+};
+
+static const u32 pll_video_regs[] = {
+ SUN50I_H616_PLL_VIDEO0_REG,
+ SUN50I_H616_PLL_VIDEO1_REG,
+ SUN50I_H616_PLL_VIDEO2_REG,
+};
+
+static const u32 usb2_clk_regs[] = {
+ SUN50I_H616_USB0_CLK_REG,
+ SUN50I_H616_USB1_CLK_REG,
+ SUN50I_H616_USB2_CLK_REG,
+ SUN50I_H616_USB3_CLK_REG,
+};
+
+static void __init sun50i_h616_ccu_setup(struct device_node *node)
+{
+ void __iomem *reg;
+ u32 val;
+ int i;
+
+ reg = of_io_request_and_map(node, 0, of_node_full_name(node));
+ if (IS_ERR(reg)) {
+ pr_err("%pOF: Could not map clock registers\n", node);
+ return;
+ }
+
+ /* Enable the lock bits and the output enable bits on all PLLs */
+ for (i = 0; i < ARRAY_SIZE(pll_regs); i++) {
+ val = readl(reg + pll_regs[i]);
+ val |= BIT(29) | BIT(27);
+ writel(val, reg + pll_regs[i]);
+ }
+
+ /*
+ * Force the output divider of video PLLs to 0.
+ *
+ * See the comment before pll-video0 definition for the reason.
+ */
+ for (i = 0; i < ARRAY_SIZE(pll_video_regs); i++) {
+ val = readl(reg + pll_video_regs[i]);
+ val &= ~BIT(0);
+ writel(val, reg + pll_video_regs[i]);
+ }
+
+ /*
+ * Force OHCI 12M clock sources to 00 (12MHz divided from 48MHz)
+ *
+ * This clock mux is still mysterious, and the code just enforces
+ * it to have a valid clock parent.
+ */
+ for (i = 0; i < ARRAY_SIZE(usb2_clk_regs); i++) {
+ val = readl(reg + usb2_clk_regs[i]);
+ val &= ~GENMASK(25, 24);
+ writel(val, reg + usb2_clk_regs[i]);
+ }
+
+ /*
+ * Force the post-divider of pll-audio to 12 and the output divider
+ * of it to 2, so 24576000 and 22579200 rates can be set exactly.
+ */
+ val = readl(reg + SUN50I_H616_PLL_AUDIO_REG);
+ val &= ~(GENMASK(21, 16) | BIT(0));
+ writel(val | (11 << 16) | BIT(0), reg + SUN50I_H616_PLL_AUDIO_REG);
+
+ /*
+ * First clock parent (osc32K) is unusable for CEC. But since there
+ * is no good way to force parent switch (both run with same frequency),
+ * just set second clock parent here.
+ */
+ val = readl(reg + SUN50I_H616_HDMI_CEC_CLK_REG);
+ val |= BIT(24);
+ writel(val, reg + SUN50I_H616_HDMI_CEC_CLK_REG);
+
+ i = sunxi_ccu_probe(node, reg, &sun50i_h616_ccu_desc);
+ if (i)
+ pr_err("%pOF: probing clocks fails: %d\n", node, i);
+}
+
+CLK_OF_DECLARE(sun50i_h616_ccu, "allwinner,sun50i-h616-ccu",
+ sun50i_h616_ccu_setup);
diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h616.h b/drivers/clk/sunxi-ng/ccu-sun50i-h616.h
new file mode 100644
index 000000000000..dd671b413f22
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-h616.h
@@ -0,0 +1,56 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright 2020 Arm Ltd.
+ */
+
+#ifndef _CCU_SUN50I_H616_H_
+#define _CCU_SUN50I_H616_H_
+
+#include <dt-bindings/clock/sun50i-h616-ccu.h>
+#include <dt-bindings/reset/sun50i-h616-ccu.h>
+
+#define CLK_OSC12M 0
+#define CLK_PLL_CPUX 1
+#define CLK_PLL_DDR0 2
+#define CLK_PLL_DDR1 3
+
+/* PLL_PERIPH0 exported for PRCM */
+
+#define CLK_PLL_PERIPH0_2X 5
+#define CLK_PLL_PERIPH1 6
+#define CLK_PLL_PERIPH1_2X 7
+#define CLK_PLL_GPU 8
+#define CLK_PLL_VIDEO0 9
+#define CLK_PLL_VIDEO0_4X 10
+#define CLK_PLL_VIDEO1 11
+#define CLK_PLL_VIDEO1_4X 12
+#define CLK_PLL_VIDEO2 13
+#define CLK_PLL_VIDEO2_4X 14
+#define CLK_PLL_VE 15
+#define CLK_PLL_DE 16
+#define CLK_PLL_AUDIO_HS 17
+#define CLK_PLL_AUDIO_1X 18
+#define CLK_PLL_AUDIO_2X 19
+#define CLK_PLL_AUDIO_4X 20
+
+/* CPUX clock exported for DVFS */
+
+#define CLK_AXI 22
+#define CLK_CPUX_APB 23
+#define CLK_PSI_AHB1_AHB2 24
+#define CLK_AHB3 25
+
+/* APB1 clock exported for PIO */
+
+#define CLK_APB2 27
+#define CLK_MBUS 28
+
+/* All module clocks and bus gates are exported except DRAM */
+
+#define CLK_DRAM 49
+
+#define CLK_BUS_DRAM 56
+
+#define CLK_NUMBER (CLK_BUS_HDCP + 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
new file mode 100644
index 000000000000..4fc08b0df2f3
--- /dev/null
+++ b/include/dt-bindings/clock/sun50i-h616-ccu.h
@@ -0,0 +1,115 @@
+/* SPDX-License-Identifier: (GPL-2.0+ or MIT) */
+/*
+ * Copyright (C) 2020 Arm Ltd.
+ */
+
+#ifndef _DT_BINDINGS_CLK_SUN50I_H616_H_
+#define _DT_BINDINGS_CLK_SUN50I_H616_H_
+
+#define CLK_PLL_PERIPH0 4
+
+#define CLK_CPUX 21
+
+#define CLK_APB1 26
+
+#define CLK_DE 29
+#define CLK_BUS_DE 30
+#define CLK_DEINTERLACE 31
+#define CLK_BUS_DEINTERLACE 32
+#define CLK_G2D 33
+#define CLK_BUS_G2D 34
+#define CLK_GPU0 35
+#define CLK_BUS_GPU 36
+#define CLK_GPU1 37
+#define CLK_CE 38
+#define CLK_BUS_CE 39
+#define CLK_VE 40
+#define CLK_BUS_VE 41
+#define CLK_BUS_DMA 42
+#define CLK_BUS_HSTIMER 43
+#define CLK_AVS 44
+#define CLK_BUS_DBG 45
+#define CLK_BUS_PSI 46
+#define CLK_BUS_PWM 47
+#define CLK_BUS_IOMMU 48
+
+#define CLK_MBUS_DMA 50
+#define CLK_MBUS_VE 51
+#define CLK_MBUS_CE 52
+#define CLK_MBUS_TS 53
+#define CLK_MBUS_NAND 54
+#define CLK_MBUS_G2D 55
+
+#define CLK_NAND0 57
+#define CLK_NAND1 58
+#define CLK_BUS_NAND 59
+#define CLK_MMC0 60
+#define CLK_MMC1 61
+#define CLK_MMC2 62
+#define CLK_BUS_MMC0 63
+#define CLK_BUS_MMC1 64
+#define CLK_BUS_MMC2 65
+#define CLK_BUS_UART0 66
+#define CLK_BUS_UART1 67
+#define CLK_BUS_UART2 68
+#define CLK_BUS_UART3 69
+#define CLK_BUS_UART4 70
+#define CLK_BUS_UART5 71
+#define CLK_BUS_I2C0 72
+#define CLK_BUS_I2C1 73
+#define CLK_BUS_I2C2 74
+#define CLK_BUS_I2C3 75
+#define CLK_BUS_I2C4 76
+#define CLK_SPI0 77
+#define CLK_SPI1 78
+#define CLK_BUS_SPI0 79
+#define CLK_BUS_SPI1 80
+#define CLK_EMAC_25M 81
+#define CLK_BUS_EMAC0 82
+#define CLK_BUS_EMAC1 83
+#define CLK_TS 84
+#define CLK_BUS_TS 85
+#define CLK_BUS_THS 86
+#define CLK_SPDIF 87
+#define CLK_BUS_SPDIF 88
+#define CLK_DMIC 89
+#define CLK_BUS_DMIC 90
+#define CLK_AUDIO_CODEC_1X 91
+#define CLK_AUDIO_CODEC_4X 92
+#define CLK_BUS_AUDIO_CODEC 93
+#define CLK_AUDIO_HUB 94
+#define CLK_BUS_AUDIO_HUB 95
+#define CLK_USB_OHCI0 96
+#define CLK_USB_PHY0 97
+#define CLK_USB_OHCI1 98
+#define CLK_USB_PHY1 99
+#define CLK_USB_OHCI2 100
+#define CLK_USB_PHY2 101
+#define CLK_USB_OHCI3 102
+#define CLK_USB_PHY3 103
+#define CLK_BUS_OHCI0 104
+#define CLK_BUS_OHCI1 105
+#define CLK_BUS_OHCI2 106
+#define CLK_BUS_OHCI3 107
+#define CLK_BUS_EHCI0 108
+#define CLK_BUS_EHCI1 109
+#define CLK_BUS_EHCI2 110
+#define CLK_BUS_EHCI3 111
+#define CLK_BUS_OTG 112
+#define CLK_BUS_KEYADC 113
+#define CLK_HDMI 114
+#define CLK_HDMI_SLOW 115
+#define CLK_HDMI_CEC 116
+#define CLK_BUS_HDMI 117
+#define CLK_BUS_TCON_TOP 118
+#define CLK_TCON_TV0 119
+#define CLK_TCON_TV1 120
+#define CLK_BUS_TCON_TV0 121
+#define CLK_BUS_TCON_TV1 122
+#define CLK_TVE0 123
+#define CLK_BUS_TVE_TOP 124
+#define CLK_BUS_TVE0 125
+#define CLK_HDCP 126
+#define CLK_BUS_HDCP 127
+
+#endif /* _DT_BINDINGS_CLK_SUN50I_H616_H_ */
diff --git a/include/dt-bindings/reset/sun50i-h616-ccu.h b/include/dt-bindings/reset/sun50i-h616-ccu.h
new file mode 100644
index 000000000000..cb6285a8d128
--- /dev/null
+++ b/include/dt-bindings/reset/sun50i-h616-ccu.h
@@ -0,0 +1,70 @@
+/* SPDX-License-Identifier: (GPL-2.0+ or MIT) */
+/*
+ * Copyright (C) 2020 Arm Ltd.
+ */
+
+#ifndef _DT_BINDINGS_RESET_SUN50I_H616_H_
+#define _DT_BINDINGS_RESET_SUN50I_H616_H_
+
+#define RST_MBUS 0
+#define RST_BUS_DE 1
+#define RST_BUS_DEINTERLACE 2
+#define RST_BUS_GPU 3
+#define RST_BUS_CE 4
+#define RST_BUS_VE 5
+#define RST_BUS_DMA 6
+#define RST_BUS_HSTIMER 7
+#define RST_BUS_DBG 8
+#define RST_BUS_PSI 9
+#define RST_BUS_PWM 10
+#define RST_BUS_IOMMU 11
+#define RST_BUS_DRAM 12
+#define RST_BUS_NAND 13
+#define RST_BUS_MMC0 14
+#define RST_BUS_MMC1 15
+#define RST_BUS_MMC2 16
+#define RST_BUS_UART0 17
+#define RST_BUS_UART1 18
+#define RST_BUS_UART2 19
+#define RST_BUS_UART3 20
+#define RST_BUS_UART4 21
+#define RST_BUS_UART5 22
+#define RST_BUS_I2C0 23
+#define RST_BUS_I2C1 24
+#define RST_BUS_I2C2 25
+#define RST_BUS_I2C3 26
+#define RST_BUS_I2C4 27
+#define RST_BUS_SPI0 28
+#define RST_BUS_SPI1 29
+#define RST_BUS_EMAC0 30
+#define RST_BUS_EMAC1 31
+#define RST_BUS_TS 32
+#define RST_BUS_THS 33
+#define RST_BUS_SPDIF 34
+#define RST_BUS_DMIC 35
+#define RST_BUS_AUDIO_CODEC 36
+#define RST_BUS_AUDIO_HUB 37
+#define RST_USB_PHY0 38
+#define RST_USB_PHY1 39
+#define RST_USB_PHY2 40
+#define RST_USB_PHY3 41
+#define RST_BUS_OHCI0 42
+#define RST_BUS_OHCI1 43
+#define RST_BUS_OHCI2 44
+#define RST_BUS_OHCI3 45
+#define RST_BUS_EHCI0 46
+#define RST_BUS_EHCI1 47
+#define RST_BUS_EHCI2 48
+#define RST_BUS_EHCI3 49
+#define RST_BUS_OTG 50
+#define RST_BUS_HDMI 51
+#define RST_BUS_HDMI_SUB 52
+#define RST_BUS_TCON_TOP 53
+#define RST_BUS_TCON_TV0 54
+#define RST_BUS_TCON_TV1 55
+#define RST_BUS_TVE_TOP 56
+#define RST_BUS_TVE0 57
+#define RST_BUS_HDCP 58
+#define RST_BUS_KEYADC 59
+
+#endif /* _DT_BINDINGS_RESET_SUN50I_H616_H_ */
--
2.17.5

Andre Przywara

unread,
Jan 27, 2021, 12:25:59 PM1/27/21
to Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland, Icenowy Zheng, Rob Herring, Clément Péron, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Lee Jones, devic...@vger.kernel.org
The AXP305 PMIC used in AXP805 seems to be fully compatible to the
AXP805 PMIC, so add the proper chain of compatible strings.

Also at least on one board (Orangepi Zero2) there is no interrupt line
connected to the CPU, so make the "interrupts" property optional.

Signed-off-by: Andre Przywara <andre.p...@arm.com>
---
Documentation/devicetree/bindings/mfd/axp20x.txt | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/mfd/axp20x.txt b/Documentation/devicetree/bindings/mfd/axp20x.txt
index 4991a6415796..4fd748101e3c 100644
--- a/Documentation/devicetree/bindings/mfd/axp20x.txt
+++ b/Documentation/devicetree/bindings/mfd/axp20x.txt
@@ -26,10 +26,10 @@ Required properties:
* "x-powers,axp803"
* "x-powers,axp806"
* "x-powers,axp805", "x-powers,axp806"
+ * "x-powers,axp803", "x-powers,axp805", "x-powers,axp806"
* "x-powers,axp809"
* "x-powers,axp813"
- reg: The I2C slave address or RSB hardware address for the AXP chip
-- interrupts: SoC NMI / GPIO interrupt connected to the PMIC's IRQ pin
- interrupt-controller: The PMIC has its own internal IRQs
- #interrupt-cells: Should be set to 1

@@ -43,6 +43,7 @@ more information:
AXP20x/LDO3: software-based implementation

Optional properties:
+- interrupts: SoC NMI / GPIO interrupt connected to the PMIC's IRQ pin
- x-powers,dcdc-freq: defines the work frequency of DC-DC in KHz
AXP152/20X: range: 750-1875, Default: 1.5 MHz
AXP22X/8XX: range: 1800-4050, Default: 3 MHz
--
2.17.5

Andre Przywara

unread,
Jan 27, 2021, 12:26:02 PM1/27/21
to Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland, Icenowy Zheng, Rob Herring, Clément Péron, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Lee Jones, Dmitry Torokhov, linux...@vger.kernel.org
On at least one board (Orangepi Zero2) the AXP305 PMIC does not have its
interrupt line connected to the CPU (mostly because the H616 SoC does
not feature an NMI pin anymore).
After allowing the AXP driver to proceed without an "interrupts"
property [1], the axp20x-pek driver crashes with a NULL pointer
dereference (see below).

Check for the regmap_irqc member to be not NULL before proceeding with
probe. This gets normally filled by the call to regmap_add_irq_chip(),
which we allow to skip now, when the DT node lacks an interrupt
property.

....
[ 3.843388] sunxi-rsb 7083000.rsb: RSB running at 3000000 Hz
[ 3.849972] axp20x-rsb sunxi-rsb-745: AXP20x variant AXP806 found
[ 3.857971] Unable to handle kernel NULL pointer dereference at
virtual address 00000000000001b8
[ 3.866855] Mem abort info:
[ 3.869691] ESR = 0x96000004
[ 3.872749] EC = 0x25: DABT (current EL), IL = 32 bits
[ 3.878092] SET = 0, FnV = 0
[ 3.881149] EA = 0, S1PTW = 0
[ 3.884309] Data abort info:
[ 3.887210] ISV = 0, ISS = 0x00000004
[ 3.891062] CM = 0, WnR = 0
[ 3.894049] [00000000000001b8] user address but active_mm is swapper
[ 3.900590] Internal error: Oops: 96000004 [#1] PREEMPT SMP
[ 3.906166] Modules linked in:
[ 3.909227] CPU: 2 PID: 34 Comm: kworker/2:1 Not tainted 5.11.0-rc1
[ 3.915925] Hardware name: OrangePi Zero2 (DT)
[ 3.920367] Workqueue: events deferred_probe_work_func
[ 3.925518] pstate: 40000005 (nZcv daif -PAN -UAO -TCO BTYPE=--)
[ 3.931522] pc : regmap_irq_get_virq+0x0/0x48
[ 3.935883] lr : axp20x_pek_probe+0x78/0x200
[ 3.940147] sp : ffff800012fdb450
[ 3.943459] x29: ffff800012fdb450 x28: ffff0000054af340
[ 3.948776] x27: ffff000005534000 x26: ffff000005534810
[ 3.954091] x25: ffff800012883028 x24: 0000000000000002
[ 3.959407] x23: ffff80001157eaf0 x22: ffff000005534810
[ 3.964722] x21: ffff000005534800 x20: ffff0000054b0580
[ 3.970037] x19: 000000000000000b x18: 0000000000000000
[ 3.975353] x17: 0000000000000001 x16: 0000000000000019
[ 3.980668] x15: 000002ce4ea04ae6 x14: 000000000000014f
[ 3.985983] x13: 0000000000000282 x12: 0000000000000030
[ 3.991298] x11: 0000000000000038 x10: 0101010101010101
[ 3.996613] x9 : 0000000000000000 x8 : 7f7f7f7f7f7f7f7f
[ 4.001928] x7 : ff5141435e4a444f x6 : 0000000000000080
[ 4.007243] x5 : 0000000000000000 x4 : 8000000000000000
[ 4.012558] x3 : 0000000000000000 x2 : 0000000000000000
[ 4.017872] x1 : 000000000000000b x0 : 0000000000000000
[ 4.023188] Call trace:
[ 4.025635] regmap_irq_get_virq+0x0/0x48
[ 4.029646] platform_probe+0x68/0xd8
[ 4.033312] really_probe+0xe4/0x3b0
[ 4.036889] driver_probe_device+0x58/0xb8
[ 4.040986] __device_attach_driver+0x84/0xc8
[ 4.045342] bus_for_each_drv+0x78/0xc8
[ 4.049178] __device_attach+0xf0/0x150
[ 4.053013] device_initial_probe+0x14/0x20
[ 4.057196] bus_probe_device+0x9c/0xa8
[ 4.061032] device_add+0x36c/0x7b8
[ 4.064525] platform_device_add+0x100/0x238
[ 4.068796] mfd_add_devices+0x494/0x718
[ 4.072721] axp20x_device_probe+0x70/0x158
[ 4.076904] axp20x_rsb_probe+0x94/0xd0
[ 4.080741] sunxi_rsb_device_probe+0x6c/0x88
[ 4.085102] really_probe+0xe4/0x3b0
[ 4.088679] driver_probe_device+0x58/0xb8
[ 4.092776] __device_attach_driver+0x84/0xc8
[ 4.097132] bus_for_each_drv+0x78/0xc8
[ 4.100967] __device_attach+0xf0/0x150
[ 4.104803] device_initial_probe+0x14/0x20
[ 4.108986] bus_probe_device+0x9c/0xa8
[ 4.112821] device_add+0x36c/0x7b8
[ 4.116313] device_register+0x20/0x30
[ 4.120065] sunxi_rsb_probe+0x4e4/0x608
....

[1] http://lists.infradead.org/pipermail/linux-arm-kernel/2021-January/633392.html

Signed-off-by: Andre Przywara <andre.p...@arm.com>
---
drivers/input/misc/axp20x-pek.c | 4 ++++
1 file changed, 4 insertions(+)

diff --git a/drivers/input/misc/axp20x-pek.c b/drivers/input/misc/axp20x-pek.c
index 9c6386b2af33..abe52ef194ee 100644
--- a/drivers/input/misc/axp20x-pek.c
+++ b/drivers/input/misc/axp20x-pek.c
@@ -309,6 +309,10 @@ static int axp20x_pek_probe(struct platform_device *pdev)

axp20x_pek->axp20x = dev_get_drvdata(pdev->dev.parent);

+ /* In case there is no interrupt line from the AXP towards the CPU. */
+ if (!axp20x_pek->axp20x->regmap_irqc)
+ return -ENODEV;
+
axp20x_pek->irq_dbr = platform_get_irq_byname(pdev, "PEK_DBR");
if (axp20x_pek->irq_dbr < 0)
return axp20x_pek->irq_dbr;
--
2.17.5

Andre Przywara

unread,
Jan 27, 2021, 12:26:04 PM1/27/21
to Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland, Icenowy Zheng, Rob Herring, Clément Péron, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Lee Jones
Currently the AXP chip requires to have its IRQ line connected to some
interrupt controller, and will fail probing when this is not the case.

On a new Allwinner SoC (H616) there is no NMI pin anymore, and at
least one board does not connect the AXP's IRQ pin to anything else,
so the interrupt functionality of the AXP chip is simply not available.

Check whether the interrupt line number returned by the platform code is
valid, before trying to register the irqchip. If not, we skip this
registration, to avoid the driver to bail out completely.

Signed-off-by: Andre Przywara <andre.p...@arm.com>
---
drivers/mfd/axp20x.c | 17 +++++++++++------
1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c
index 3eae04e24ac8..00c163a1e20d 100644
--- a/drivers/mfd/axp20x.c
+++ b/drivers/mfd/axp20x.c
@@ -959,12 +959,17 @@ int axp20x_device_probe(struct axp20x_dev *axp20x)
AXP806_REG_ADDR_EXT_ADDR_SLAVE_MODE);
}

- ret = regmap_add_irq_chip(axp20x->regmap, axp20x->irq,
- IRQF_ONESHOT | IRQF_SHARED | axp20x->irq_flags,
- -1, axp20x->regmap_irq_chip, &axp20x->regmap_irqc);
- if (ret) {
- dev_err(axp20x->dev, "failed to add irq chip: %d\n", ret);
- return ret;
+ /* Only if there is an interrupt line connected towards the CPU. */
+ if (axp20x->irq > 0) {
+ ret = regmap_add_irq_chip(axp20x->regmap, axp20x->irq,
+ IRQF_ONESHOT | IRQF_SHARED | axp20x->irq_flags,
+ -1, axp20x->regmap_irq_chip,
+ &axp20x->regmap_irqc);
+ if (ret) {
+ dev_err(axp20x->dev, "failed to add irq chip: %d\n",
+ ret);
+ return ret;
+ }
}

ret = mfd_add_devices(axp20x->dev, -1, axp20x->cells,
--
2.17.5

Andre Przywara

unread,
Jan 27, 2021, 12:26:08 PM1/27/21
to Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland, Icenowy Zheng, Rob Herring, Clément Péron, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, devic...@vger.kernel.org
The H616 adds a second EMAC clock register. We don't know about the
exact SRAM properties yet, so this gets omitted for now.

Signed-off-by: Andre Przywara <andre.p...@arm.com>
Acked-by: Rob Herring <ro...@kernel.org>
---
.../bindings/sram/allwinner,sun4i-a10-system-control.yaml | 1 +
1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/sram/allwinner,sun4i-a10-system-control.yaml b/Documentation/devicetree/bindings/sram/allwinner,sun4i-a10-system-control.yaml
index b66a07e21d1e..1c426c211e36 100644
--- a/Documentation/devicetree/bindings/sram/allwinner,sun4i-a10-system-control.yaml
+++ b/Documentation/devicetree/bindings/sram/allwinner,sun4i-a10-system-control.yaml
@@ -49,6 +49,7 @@ properties:
- items:
- const: allwinner,suniv-f1c100s-system-control
- const: allwinner,sun4i-a10-system-control
+ - const: allwinner,sun50i-h616-system-control

Andre Przywara

unread,
Jan 27, 2021, 12:26:09 PM1/27/21
to Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland, Icenowy Zheng, Rob Herring, Clément Péron, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com
The Allwinner H616 adds a second EMAC clock register at offset 0x34, for
controlling the second EMAC in this chip.

Allow to extend the regmap in this case, to cover more than the current
4 bytes exported.

Signed-off-by: Andre Przywara <andre.p...@arm.com>
---
drivers/soc/sunxi/sunxi_sram.c | 31 +++++++++++++++++++++++--------
1 file changed, 23 insertions(+), 8 deletions(-)

diff --git a/drivers/soc/sunxi/sunxi_sram.c b/drivers/soc/sunxi/sunxi_sram.c
index d4c7bd59429e..42833e33a96c 100644
--- a/drivers/soc/sunxi/sunxi_sram.c
+++ b/drivers/soc/sunxi/sunxi_sram.c
@@ -283,7 +283,7 @@ int sunxi_sram_release(struct device *dev)
EXPORT_SYMBOL(sunxi_sram_release);

struct sunxi_sramc_variant {
- bool has_emac_clock;
+ int num_emac_clocks;
};

static const struct sunxi_sramc_variant sun4i_a10_sramc_variant = {
@@ -291,20 +291,31 @@ static const struct sunxi_sramc_variant sun4i_a10_sramc_variant = {
};

static const struct sunxi_sramc_variant sun8i_h3_sramc_variant = {
- .has_emac_clock = true,
+ .num_emac_clocks = 1,
};

static const struct sunxi_sramc_variant sun50i_a64_sramc_variant = {
- .has_emac_clock = true,
+ .num_emac_clocks = 1,
+};
+

Andre Przywara

unread,
Jan 27, 2021, 12:26:11 PM1/27/21
to Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland, Icenowy Zheng, Rob Herring, Clément Péron, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Guenter Roeck, Wim Van Sebroeck, devic...@vger.kernel.org, linux-w...@vger.kernel.org
Use enums to group all compatible devices together on the way.

Signed-off-by: Andre Przywara <andre.p...@arm.com>
Acked-by: Rob Herring <ro...@kernel.org>
Acked-by: Maxime Ripard <mri...@kernel.org>
Reviewed-by: Guenter Roeck <li...@roeck-us.net>
---
.../bindings/watchdog/allwinner,sun4i-a10-wdt.yaml | 12 +++++-------
1 file changed, 5 insertions(+), 7 deletions(-)

diff --git a/Documentation/devicetree/bindings/watchdog/allwinner,sun4i-a10-wdt.yaml b/Documentation/devicetree/bindings/watchdog/allwinner,sun4i-a10-wdt.yaml
index 5ac607de8be4..9aa3c313c49f 100644
--- a/Documentation/devicetree/bindings/watchdog/allwinner,sun4i-a10-wdt.yaml
+++ b/Documentation/devicetree/bindings/watchdog/allwinner,sun4i-a10-wdt.yaml
@@ -19,13 +19,11 @@ properties:
- const: allwinner,sun4i-a10-wdt
- const: allwinner,sun6i-a31-wdt
- items:
- - const: allwinner,sun50i-a64-wdt
- - const: allwinner,sun6i-a31-wdt
- - items:
- - const: allwinner,sun50i-a100-wdt
- - const: allwinner,sun6i-a31-wdt
- - items:
- - const: allwinner,sun50i-h6-wdt
+ - enum:
+ - allwinner,sun50i-a64-wdt
+ - allwinner,sun50i-a100-wdt
+ - allwinner,sun50i-h6-wdt
+ - allwinner,sun50i-h616-wdt
- const: allwinner,sun6i-a31-wdt
- items:
- const: allwinner,suniv-f1c100s-wdt
--
2.17.5

Andre Przywara

unread,
Jan 27, 2021, 12:26:13 PM1/27/21
to Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland, Icenowy Zheng, Rob Herring, Clément Péron, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Gregory CLEMENT, devic...@vger.kernel.org, linu...@vger.kernel.org
Add the obvious compatible name to the existing I2C binding, and pair
it with the existing A31 fallback compatible string, as the devices
are compatible.

On the way use enums to group all compatible devices together.

Signed-off-by: Andre Przywara <andre.p...@arm.com>
Acked-by: Rob Herring <ro...@kernel.org>
Acked-by: Wolfram Sang <w...@kernel.org>
---
.../bindings/i2c/marvell,mv64xxx-i2c.yaml | 21 +++++++------------
1 file changed, 7 insertions(+), 14 deletions(-)

diff --git a/Documentation/devicetree/bindings/i2c/marvell,mv64xxx-i2c.yaml b/Documentation/devicetree/bindings/i2c/marvell,mv64xxx-i2c.yaml
index 5b5ae402f97a..eb72dd571def 100644
--- a/Documentation/devicetree/bindings/i2c/marvell,mv64xxx-i2c.yaml
+++ b/Documentation/devicetree/bindings/i2c/marvell,mv64xxx-i2c.yaml
@@ -18,21 +18,14 @@ properties:
- const: allwinner,sun4i-a10-i2c
- const: allwinner,sun6i-a31-i2c
- items:
- - const: allwinner,sun8i-a23-i2c
+ - enum:
+ - allwinner,sun8i-a23-i2c
+ - allwinner,sun8i-a83t-i2c
+ - allwinner,sun50i-a64-i2c
+ - allwinner,sun50i-a100-i2c
+ - allwinner,sun50i-h6-i2c
+ - allwinner,sun50i-h616-i2c
- const: allwinner,sun6i-a31-i2c
- - items:
- - const: allwinner,sun8i-a83t-i2c
- - const: allwinner,sun6i-a31-i2c
- - items:
- - const: allwinner,sun50i-a64-i2c
- - const: allwinner,sun6i-a31-i2c
- - items:
- - const: allwinner,sun50i-a100-i2c
- - const: allwinner,sun6i-a31-i2c
- - items:
- - const: allwinner,sun50i-h6-i2c
- - const: allwinner,sun6i-a31-i2c
-
- const: marvell,mv64xxx-i2c
- const: marvell,mv78230-i2c
- const: marvell,mv78230-a0-i2c
--
2.17.5

Andre Przywara

unread,
Jan 27, 2021, 12:26:16 PM1/27/21
to Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland, Icenowy Zheng, Rob Herring, Clément Péron, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Mauro Carvalho Chehab, devic...@vger.kernel.org, linux...@vger.kernel.org
Add the obvious compatible name to the existing IR binding, and pair
it with the existing A31 fallback compatible string, as the devices
are compatible.

On the way use enums to group all compatible devices together.

Signed-off-by: Andre Przywara <andre.p...@arm.com>
Acked-by: Rob Herring <ro...@kernel.org>
---
.../bindings/media/allwinner,sun4i-a10-ir.yaml | 16 ++++++----------
1 file changed, 6 insertions(+), 10 deletions(-)

diff --git a/Documentation/devicetree/bindings/media/allwinner,sun4i-a10-ir.yaml b/Documentation/devicetree/bindings/media/allwinner,sun4i-a10-ir.yaml
index 5fa19d4aeaf3..6d8395d6bca0 100644
--- a/Documentation/devicetree/bindings/media/allwinner,sun4i-a10-ir.yaml
+++ b/Documentation/devicetree/bindings/media/allwinner,sun4i-a10-ir.yaml
@@ -20,16 +20,12 @@ properties:
- const: allwinner,sun5i-a13-ir
- const: allwinner,sun6i-a31-ir
- items:
- - const: allwinner,sun8i-a83t-ir
- - const: allwinner,sun6i-a31-ir
- - items:
- - const: allwinner,sun8i-r40-ir
- - const: allwinner,sun6i-a31-ir
- - items:
- - const: allwinner,sun50i-a64-ir
- - const: allwinner,sun6i-a31-ir
- - items:
- - const: allwinner,sun50i-h6-ir
+ - enum:
+ - allwinner,sun8i-a83t-ir
+ - allwinner,sun8i-r40-ir
+ - allwinner,sun50i-a64-ir
+ - allwinner,sun50i-h6-ir
+ - allwinner,sun50i-h616-ir
- const: allwinner,sun6i-a31-ir

reg:
--
2.17.5

Andre Przywara

unread,
Jan 27, 2021, 12:26:19 PM1/27/21
to Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland, Icenowy Zheng, Rob Herring, Clément Péron, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Alessandro Zummo, Alexandre Belloni, devic...@vger.kernel.org, linu...@vger.kernel.org
Add the obvious compatible name to the existing RTC binding, and pair
it with the existing H6 fallback compatible string, as the devices are
compatible.

Signed-off-by: Andre Przywara <andre.p...@arm.com>
Acked-by: Rob Herring <ro...@kernel.org>
---
.../devicetree/bindings/rtc/allwinner,sun6i-a31-rtc.yaml | 3 +++
1 file changed, 3 insertions(+)

diff --git a/Documentation/devicetree/bindings/rtc/allwinner,sun6i-a31-rtc.yaml b/Documentation/devicetree/bindings/rtc/allwinner,sun6i-a31-rtc.yaml
index b1b0ee769b71..4193e5813344 100644
--- a/Documentation/devicetree/bindings/rtc/allwinner,sun6i-a31-rtc.yaml
+++ b/Documentation/devicetree/bindings/rtc/allwinner,sun6i-a31-rtc.yaml
@@ -26,6 +26,9 @@ properties:
- const: allwinner,sun50i-a64-rtc
- const: allwinner,sun8i-h3-rtc
- const: allwinner,sun50i-h6-rtc
+ - items:
+ - const: allwinner,sun50i-h616-rtc
+ - const: allwinner,sun50i-h6-rtc

Andre Przywara

unread,
Jan 27, 2021, 12:26:21 PM1/27/21
to Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland, Icenowy Zheng, Rob Herring, Clément Péron, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Mark Brown, devic...@vger.kernel.org, linu...@vger.kernel.org
Add the obvious compatible name to the existing SPI binding, and pair
it with the existing H3 fallback compatible string, as the devices are
compatible.

Signed-off-by: Andre Przywara <andre.p...@arm.com>
Acked-by: Rob Herring <ro...@kernel.org>
---
.../devicetree/bindings/spi/allwinner,sun6i-a31-spi.yaml | 1 +
1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/spi/allwinner,sun6i-a31-spi.yaml b/Documentation/devicetree/bindings/spi/allwinner,sun6i-a31-spi.yaml
index 7866a655d81c..908248260afa 100644
--- a/Documentation/devicetree/bindings/spi/allwinner,sun6i-a31-spi.yaml
+++ b/Documentation/devicetree/bindings/spi/allwinner,sun6i-a31-spi.yaml
@@ -25,6 +25,7 @@ properties:
- enum:
- allwinner,sun8i-r40-spi
- allwinner,sun50i-h6-spi
+ - allwinner,sun50i-h616-spi
- const: allwinner,sun8i-h3-spi

reg:
--
2.17.5

Andre Przywara

unread,
Jan 27, 2021, 12:26:24 PM1/27/21
to Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland, Icenowy Zheng, Rob Herring, Clément Péron, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, devic...@vger.kernel.org
Add the obvious compatible name to the existing RSB binding, and pair
it with the existing A23 fallback compatible string, as the devices are
compatible.

Signed-off-by: Andre Przywara <andre.p...@arm.com>
---
.../devicetree/bindings/bus/allwinner,sun8i-a23-rsb.yaml | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/bus/allwinner,sun8i-a23-rsb.yaml b/Documentation/devicetree/bindings/bus/allwinner,sun8i-a23-rsb.yaml
index 32d33b983d66..3d719f468a5b 100644
--- a/Documentation/devicetree/bindings/bus/allwinner,sun8i-a23-rsb.yaml
+++ b/Documentation/devicetree/bindings/bus/allwinner,sun8i-a23-rsb.yaml
@@ -21,7 +21,9 @@ properties:
oneOf:
- const: allwinner,sun8i-a23-rsb
- items:
- - const: allwinner,sun8i-a83t-rsb
+ - enum:
+ - allwinner,sun8i-a83t-rsb
+ - allwinner,sun50i-h616-rsb
- const: allwinner,sun8i-a23-rsb

reg:
--
2.17.5

Andre Przywara

unread,
Jan 27, 2021, 12:26:25 PM1/27/21
to Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland, Icenowy Zheng, Rob Herring, Clément Péron, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, devic...@vger.kernel.org
Add the obvious compatible name to the existing EMAC binding, and pair
it with the existing A64 fallback compatible string, as the devices are
compatible.

On the way use enums to group the compatible devices together.

Signed-off-by: Andre Przywara <andre.p...@arm.com>
---
.../devicetree/bindings/net/allwinner,sun8i-a83t-emac.yaml | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/net/allwinner,sun8i-a83t-emac.yaml b/Documentation/devicetree/bindings/net/allwinner,sun8i-a83t-emac.yaml
index 7f2578d48e3f..0ccdab103f59 100644
--- a/Documentation/devicetree/bindings/net/allwinner,sun8i-a83t-emac.yaml
+++ b/Documentation/devicetree/bindings/net/allwinner,sun8i-a83t-emac.yaml
@@ -19,7 +19,9 @@ properties:
- const: allwinner,sun8i-v3s-emac
- const: allwinner,sun50i-a64-emac
- items:
- - const: allwinner,sun50i-h6-emac
+ - enum:
+ - allwinner,sun50i-h6-emac
+ - allwinner,sun50i-h616-emac
- const: allwinner,sun50i-a64-emac

reg:
--
2.17.5

Andre Przywara

unread,
Jan 27, 2021, 12:26:29 PM1/27/21
to Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland, Icenowy Zheng, Rob Herring, Clément Péron, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Alexandre Torgue, David S . Miller, Giuseppe Cavallaro, Jakub Kicinski, Jose Abreu, net...@vger.kernel.org
The Allwinner H616 SoC has two EMAC controllers, with the second one
being tied to the internal PHY, but also using a separate EMAC clock
register.

To tell the driver about which clock register to use, we add a parameter
to our syscon phandle. The driver will use this value as an index into
the regmap, so that we can address more than the first register, if
needed.

Signed-off-by: Andre Przywara <andre.p...@arm.com>
---
drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
index 58e0511badba..c7951790ed98 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
@@ -1124,11 +1124,13 @@ static int sun8i_dwmac_probe(struct platform_device *pdev)
struct stmmac_resources stmmac_res;
struct sunxi_priv_data *gmac;
struct device *dev = &pdev->dev;
+ struct reg_field syscon_field;
phy_interface_t interface;
int ret;
struct stmmac_priv *priv;
struct net_device *ndev;
struct regmap *regmap;
+ u32 syscon_idx = 0;

ret = stmmac_get_platform_resources(pdev, &stmmac_res);
if (ret)
@@ -1190,8 +1192,12 @@ static int sun8i_dwmac_probe(struct platform_device *pdev)
return ret;
}

- gmac->regmap_field = devm_regmap_field_alloc(dev, regmap,
- *gmac->variant->syscon_field);
+ syscon_field = *gmac->variant->syscon_field;
+ ret = of_property_read_u32_index(pdev->dev.of_node, "syscon", 1,
+ &syscon_idx);
+ if (!ret)
+ syscon_field.reg += syscon_idx * sizeof(u32);
+ gmac->regmap_field = devm_regmap_field_alloc(dev, regmap, syscon_field);
if (IS_ERR(gmac->regmap_field)) {
ret = PTR_ERR(gmac->regmap_field);
dev_err(dev, "Unable to map syscon register: %d\n", ret);
@@ -1263,6 +1269,8 @@ static const struct of_device_id sun8i_dwmac_match[] = {
.data = &emac_variant_a64 },
{ .compatible = "allwinner,sun50i-h6-emac",
.data = &emac_variant_h6 },
+ { .compatible = "allwinner,sun50i-h616-emac",
+ .data = &emac_variant_h6 },
{ }
};
MODULE_DEVICE_TABLE(of, sun8i_dwmac_match);
--
2.17.5

Andre Przywara

unread,
Jan 27, 2021, 12:26:32 PM1/27/21
to Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland, Icenowy Zheng, Rob Herring, Clément Péron, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Kishon Vijay Abraham I, Vinod Koul
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, to cover newer SoCs: The A100 and H616 use a different
bit for the SIDDQ control.

Signed-off-by: Andre Przywara <andre.p...@arm.com>
Acked-by: Maxime Ripard <mri...@kernel.org>
---
drivers/phy/allwinner/phy-sun4i-usb.c | 29 +++++++++++----------------
1 file changed, 12 insertions(+), 17 deletions(-)

diff --git a/drivers/phy/allwinner/phy-sun4i-usb.c b/drivers/phy/allwinner/phy-sun4i-usb.c
index 788dd5cdbb7d..539209fe3468 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)

@@ -115,9 +115,9 @@ struct sun4i_usb_phy_cfg {
int hsic_index;
enum sun4i_usb_phy_type type;
u32 disc_thresh;
+ u32 hci_phy_ctl_siddq;
u8 phyctl_offset;
bool dedicated_clocks;
- bool enable_pmu_unk1;
bool phy0_dual_route;
int missing_phys;
};
@@ -288,6 +288,12 @@ static int sun4i_usb_phy_init(struct phy *_phy)
return ret;
}

+ if (phy->pmu && data->cfg->hci_phy_ctl_siddq) {
+ val = readl(phy->pmu + REG_HCI_PHY_CTL);
+ val &= ~data->cfg->hci_phy_ctl_siddq;
+ 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 +303,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 +864,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 +872,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 +880,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 +888,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 +896,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 +904,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 +920,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_siddq = BIT(1),
.phy0_dual_route = true,
};

@@ -935,7 +930,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_siddq = BIT(1),
.phy0_dual_route = true,
};

@@ -945,7 +940,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_siddq = BIT(1),
.phy0_dual_route = true,
};

@@ -955,7 +950,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_siddq = BIT(1),
.phy0_dual_route = true,
};

--
2.17.5

Andre Przywara

unread,
Jan 27, 2021, 12:26:33 PM1/27/21
to Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland, Icenowy Zheng, Rob Herring, Clément Péron, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, devic...@vger.kernel.org
This (relatively) new SoC is similar to the H6, but drops the (broken)
PCIe support and the USB 3.0 controller. It also gets the management
controller removed, which in turn removes *some*, but not all of the
devices formerly dedicated to the ARISC (CPUS).
There does not seem to be an extra interrupt controller anymore, also
it lacks the corresponding NMI pin, so no interrupts for the PMIC.

Signed-off-by: Andre Przywara <andre.p...@arm.com>
---
.../arm64/boot/dts/allwinner/sun50i-h616.dtsi | 573 ++++++++++++++++++
1 file changed, 573 insertions(+)
create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi

diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi
new file mode 100644
index 000000000000..c277b53f94ea
--- /dev/null
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi
@@ -0,0 +1,573 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+// Copyright (C) 2020 Arm Ltd.
+// based on the H6 dtsi, which is:
+// Copyright (C) 2017 Icenowy Zheng <ice...@aosc.io>
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/clock/sun50i-h616-ccu.h>
+#include <dt-bindings/clock/sun50i-h6-r-ccu.h>
+#include <dt-bindings/reset/sun50i-h616-ccu.h>
+#include <dt-bindings/reset/sun50i-h6-r-ccu.h>
+
+/ {
+ interrupt-parent = <&gic>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu0: cpu@0 {
+ compatible = "arm,cortex-a53";
+ device_type = "cpu";
+ reg = <0>;
+ enable-method = "psci";
+ clocks = <&ccu CLK_CPUX>;
+ };
+
+ cpu1: cpu@1 {
+ compatible = "arm,cortex-a53";
+ device_type = "cpu";
+ reg = <1>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0x0 0x0 0x0 0x40000000>;
+
+ syscon: syscon@3000000 {
+ compatible = "allwinner,sun50i-h616-system-control";
+ reg = <0x03000000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ sram_c: sram@28000 {
+ compatible = "mmio-sram";
+ reg = <0x00028000 0x30000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 0x00028000 0x30000>;
+ };
+ };
+
+ ccu: clock@3001000 {
+ compatible = "allwinner,sun50i-h616-ccu";
+ reg = <0x03001000 0x1000>;
+ clocks = <&osc24M>, <&rtc 0>, <&rtc 2>;
+ clock-names = "hosc", "losc", "iosc";
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ };
+
+ watchdog: watchdog@30090a0 {
+ compatible = "allwinner,sun50i-h616-wdt",
+ "allwinner,sun6i-a31-wdt";
+ reg = <0x030090a0 0x20>;
+ interrupts = <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&osc24M>;
+ status = "okay";
+ };
+
+ pio: pinctrl@300b000 {
+ compatible = "allwinner,sun50i-h616-pinctrl";
+ reg = <0x0300b000 0x400>;
+ interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_APB1>, <&osc24M>, <&rtc 0>;
+ clock-names = "apb", "hosc", "losc";
+ gpio-controller;
+ #gpio-cells = <3>;
+ interrupt-controller;
+ #interrupt-cells = <3>;
+
+ ext_rgmii_pins: rgmii-pins {
+ pins = "PI0", "PI1", "PI2", "PI3", "PI4",
+ "PI5", "PI7", "PI8", "PI9", "PI10",
+ "PI11", "PI12", "PI13", "PI14", "PI15",
+ "PI16";
+ function = "emac0";
+ drive-strength = <40>;
+ };
+
+ i2c0_pins: i2c0-pins {
+ pins = "PI6", "PI7";
+ function = "i2c0";
+ };
+
+ i2c3_ph_pins: i2c3-ph-pins {
+ pins = "PH4", "PH5";
+ function = "i2c3";
+ };
+
+ ir_rx_pin: ir-rx-pin {
+ interrupt-controller;
+ #interrupt-cells = <3>;
+ };
+
+ mmc0: mmc@4020000 {
+ compatible = "allwinner,sun50i-h616-mmc",
+ "allwinner,sun50i-a100-mmc";
+ reg = <0x04020000 0x1000>;
+ clocks = <&ccu CLK_BUS_MMC0>, <&ccu CLK_MMC0>;
+ clock-names = "ahb", "mmc";
+ resets = <&ccu RST_BUS_MMC0>;
+ reset-names = "ahb";
+ interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&mmc0_pins>;
+ status = "disabled";
+ cap-sd-highspeed;
+ cap-mmc-highspeed;
+ mmc-ddr-3_3v;
+ mmc-ddr-1_8v;
+ cap-sdio-irq;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ mmc1: mmc@4021000 {
+ compatible = "allwinner,sun50i-h616-mmc",
+ "allwinner,sun50i-a100-mmc";
+ reg = <0x04021000 0x1000>;
+ clocks = <&ccu CLK_BUS_MMC1>, <&ccu CLK_MMC1>;
+ clock-names = "ahb", "mmc";
+ resets = <&ccu RST_BUS_MMC1>;
+ reset-names = "ahb";
+ interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&mmc1_pins>;
+ status = "disabled";
+ cap-sd-highspeed;
+ cap-mmc-highspeed;
+ mmc-ddr-3_3v;
+ mmc-ddr-1_8v;
+ cap-sdio-irq;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ mmc2: mmc@4022000 {
+ compatible = "allwinner,sun50i-h616-emmc",
+ "allwinner,sun50i-a100-emmc";
+ reg = <0x04022000 0x1000>;
+ clocks = <&ccu CLK_BUS_MMC2>, <&ccu CLK_MMC2>;
+ clock-names = "ahb", "mmc";
+ resets = <&ccu RST_BUS_MMC2>;
+ reset-names = "ahb";
+ interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&mmc2_pins>;
+ status = "disabled";
+ cap-sd-highspeed;
+ cap-mmc-highspeed;
+ mmc-ddr-3_3v;
+ mmc-ddr-1_8v;
+ cap-sdio-irq;
+ #address-cells = <1>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c0_pins>;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ i2c1: i2c@5002400 {
+ compatible = "allwinner,sun50i-h616-i2c",
+ "allwinner,sun6i-a31-i2c";
+ reg = <0x05002400 0x400>;
+ interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_I2C1>;
+ resets = <&ccu RST_BUS_I2C1>;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ i2c2: i2c@5002800 {
+ compatible = "allwinner,sun50i-h616-i2c",
+ "allwinner,sun6i-a31-i2c";
+ reg = <0x05002800 0x400>;
+ interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_I2C2>;
+ resets = <&ccu RST_BUS_I2C2>;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ i2c3: i2c@5002c00 {
+ compatible = "allwinner,sun50i-h616-i2c",
+ "allwinner,sun6i-a31-i2c";
+ reg = <0x05002c00 0x400>;
+ interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_I2C3>;
+ resets = <&ccu RST_BUS_I2C3>;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ i2c4: i2c@5003000 {
+ compatible = "allwinner,sun50i-h616-i2c",
+ "allwinner,sun6i-a31-i2c";
+ reg = <0x05003000 0x400>;
+ interrupts = <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_I2C4>;
+ resets = <&ccu RST_BUS_I2C4>;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ spi0: spi@5010000 {
+ compatible = "allwinner,sun50i-h616-spi",
+ "allwinner,sun8i-h3-spi";
+ reg = <0x05010000 0x1000>;
+ interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_SPI0>, <&ccu CLK_SPI0>;
+ clock-names = "ahb", "mod";
+ resets = <&ccu RST_BUS_SPI0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi0_pins>;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ spi1: spi@5011000 {
+ compatible = "allwinner,sun50i-h616-spi",
+ "allwinner,sun8i-h3-spi";
+ reg = <0x05011000 0x1000>;
+ interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_SPI1>, <&ccu CLK_SPI1>;
+ clock-names = "ahb", "mod";
+ resets = <&ccu RST_BUS_SPI1>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi1_pins>;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ emac0: ethernet@5020000 {
+ compatible = "allwinner,sun50i-h616-emac",
+ "allwinner,sun50i-a64-emac";
+ syscon = <&syscon>;
+ reg = <0x05020000 0x10000>;
+ interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "macirq";
+ resets = <&ccu RST_BUS_EMAC0>;
+ reset-names = "stmmaceth";
+ clocks = <&ccu CLK_BUS_EMAC0>;
+ clock-names = "stmmaceth";
+ status = "disabled";
+
+ mdio0: mdio {
+ compatible = "snps,dwmac-mdio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+ };
+
+ rtc: rtc@7000000 {
+ compatible = "allwinner,sun50i-h616-rtc",
+ "allwinner,sun50i-h6-rtc";
+ reg = <0x07000000 0x400>;
+ interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>;
+ clock-output-names = "osc32k", "osc32k-out", "iosc";
+ #clock-cells = <1>;
+ };
+
+ r_ccu: clock@7010000 {
+ compatible = "allwinner,sun50i-h616-r-ccu";
+ reg = <0x07010000 0x210>;
+ clocks = <&osc24M>, <&rtc 0>, <&rtc 2>,
+ <&ccu CLK_PLL_PERIPH0>;
+ clock-names = "hosc", "losc", "iosc", "pll-periph";
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ };
+
+ r_pio: pinctrl@7022000 {
+ compatible = "allwinner,sun50i-h616-r-pinctrl";
+ reg = <0x07022000 0x400>;
+ interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&r_ccu CLK_R_APB1>, <&osc24M>, <&rtc 0>;
+ clock-names = "apb", "hosc", "losc";
+ gpio-controller;
+ #gpio-cells = <3>;
+ interrupt-controller;
+ #interrupt-cells = <3>;
+
+ r_i2c_pins: r-i2c-pins {
+ pins = "PL0", "PL1";
+ function = "s_i2c";
+ };
+
+ r_rsb_pins: r-rsb-pins {
+ pins = "PL0", "PL1";
+ function = "s_rsb";
+ };
+ };
+
+ ir: ir@7040000 {
+ compatible = "allwinner,sun50i-h616-ir",
+ "allwinner,sun6i-a31-ir";
+ reg = <0x07040000 0x400>;
+ interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&r_ccu CLK_R_APB1_IR>,
+ <&r_ccu CLK_IR>;
+ clock-names = "apb", "ir";
+ resets = <&r_ccu RST_R_APB1_IR>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&ir_rx_pin>;
+ status = "disabled";
+ };
+
+ r_i2c: i2c@7081400 {
+ compatible = "allwinner,sun50i-h616-i2c",
+ "allwinner,sun6i-a31-i2c";
+ reg = <0x07081400 0x400>;
+ interrupts = <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&r_ccu CLK_R_APB2_I2C>;
+ resets = <&r_ccu RST_R_APB2_I2C>;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ r_rsb: rsb@7083000 {
+ compatible = "allwinner,sun50i-h616-rsb",
+ "allwinner,sun8i-a23-rsb";
+ reg = <0x07083000 0x400>;
+ interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&r_ccu CLK_R_APB2_RSB>;
+ clock-frequency = <3000000>;
+ resets = <&r_ccu RST_R_APB2_RSB>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&r_rsb_pins>;
+ status = "disabled";
+ #address-cells = <1>;

Andre Przywara

unread,
Jan 27, 2021, 12:26:36 PM1/27/21
to Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland, Icenowy Zheng, Rob Herring, Clément Péron, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, devic...@vger.kernel.org
Signed-off-by: Andre Przywara <andre.p...@arm.com>

Andre Przywara

unread,
Jan 27, 2021, 12:26:38 PM1/27/21
to Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland, Icenowy Zheng, Rob Herring, Clément Péron, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, devic...@vger.kernel.org
The OrangePi Zero 2 is a development board with the new H616 SoC.

It features the usual connectors used on those small boards, and comes
with the AXP305, which seems to be compatible with the AXP805.

For more details see: http://linux-sunxi.org/Xunlong_Orange_Pi_Zero2

Signed-off-by: Andre Przywara <andre.p...@arm.com>
---
arch/arm64/boot/dts/allwinner/Makefile | 1 +
.../allwinner/sun50i-h616-orangepi-zero2.dts | 203 ++++++++++++++++++
2 files changed, 204 insertions(+)
create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-h616-orangepi-zero2.dts

diff --git a/arch/arm64/boot/dts/allwinner/Makefile b/arch/arm64/boot/dts/allwinner/Makefile
index 41ce680e5f8d..9ba4b5d92657 100644
--- a/arch/arm64/boot/dts/allwinner/Makefile
+++ b/arch/arm64/boot/dts/allwinner/Makefile
@@ -36,3 +36,4 @@ dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-orangepi-one-plus.dtb
dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-pine-h64.dtb
dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-pine-h64-model-b.dtb
dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-tanix-tx6.dtb
+dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h616-orangepi-zero2.dtb
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h616-orangepi-zero2.dts b/arch/arm64/boot/dts/allwinner/sun50i-h616-orangepi-zero2.dts
new file mode 100644
index 000000000000..ca07cae698ce
--- /dev/null
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h616-orangepi-zero2.dts
@@ -0,0 +1,203 @@
+&emac0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&ext_rgmii_pins>;
+ phy-mode = "rgmii";
+ phy-handle = <&ext_rgmii_phy>;
+ phy-supply = <&reg_dcdce>;
+ allwinner,rx-delay-ps = <3100>;
+ allwinner,tx-delay-ps = <700>;
+ status = "okay";
+};
+
+&mdio0 {
+ ext_rgmii_phy: ethernet-phy@1 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <1>;
+ };
+};
+
+&mmc0 {
+ vmmc-supply = <&reg_dcdce>;
+ cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; /* PF6 */
+ bus-width = <4>;
+ status = "okay";
+};
+
+&r_rsb {
+ status = "okay";
+
+ axp305: pmic@745 {
+ compatible = "x-powers,axp305", "x-powers,axp805",
+ "x-powers,axp806";
+ interrupt-controller;
+ status = "okay";
+
+ flash@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "jedec,spi-nor";
+ reg = <0>;
+ spi-max-frequency = <40000000>;
+ };
+};
+
+&uart0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_ph_pins>;
+ status = "okay";
+};
--
2.17.5

Andre Przywara

unread,
Jan 27, 2021, 12:29:59 PM1/27/21
to Mark Brown, Maxime Ripard, Chen-Yu Tsai, Clément Péron, Ulf Hansson, Linus Walleij, Yangtao Li, Shuosheng Huang, Jernej Skrabec, Icenowy Zheng, linux...@googlegroups.com, linux-...@vger.kernel.org, linux-ar...@lists.infradead.org, Samuel Holland
On Wed, 27 Jan 2021 17:15:30 +0000
Mark Brown <bro...@kernel.org> wrote:

> On Mon, 25 Jan 2021 15:17:50 +0000, Andre Przywara wrote:
> > an update from the v3 last week, to add support for the Allwinner H616
> > SoC. Still based on the (updated) sunxi/for-next branch.
> > I am omitting the MMC and pinctrl patches now, as they have been taken
> > by Ulf and LinusW already into their trees.
> >
> > I addressed the comments from the list, though not sure if the HOSC clock
> > coming from the RTC is really a good idea (didn't change it).
> >
> > [...]
>
> Applied to
>
> https://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git for-next
>
> Thanks!
>
> [13/21] dt-bindings: spi: sunxi: Add H616 compatible string
> commit: 6589daf8bb98c75ad1065edad87c099ffb9f5d87

Thanks for that. I just sent a v5, just before seeing your email, so
this one still has this patch, but without any changes. So please
ignore [PATCH v5 13/21].

Cheers,
Andre

Dmitry Torokhov

unread,
Jan 27, 2021, 2:42:23 PM1/27/21
to Andre Przywara, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland, Icenowy Zheng, Rob Herring, Clément Péron, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Lee Jones, linux...@vger.kernel.org
Hi Andre,

On Wed, Jan 27, 2021 at 05:24:45PM +0000, Andre Przywara wrote:
> On at least one board (Orangepi Zero2) the AXP305 PMIC does not have its
> interrupt line connected to the CPU (mostly because the H616 SoC does
> not feature an NMI pin anymore).
> After allowing the AXP driver to proceed without an "interrupts"
> property [1], the axp20x-pek driver crashes with a NULL pointer
> dereference (see below).
>
> Check for the regmap_irqc member to be not NULL before proceeding with
> probe. This gets normally filled by the call to regmap_add_irq_chip(),
> which we allow to skip now, when the DT node lacks an interrupt
> property.

No, the driver is not the right place to patch this; regmap should be
fixed so it does not crash instead.

Thanks.

--
Dmitry

Maxime Ripard

unread,
Jan 28, 2021, 5:15:12 AM1/28/21
to Andre Przywara, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland, Icenowy Zheng, Rob Herring, Clément Péron, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Lee Jones, devic...@vger.kernel.org
On Wed, Jan 27, 2021 at 05:24:44PM +0000, Andre Przywara wrote:
> The AXP305 PMIC used in AXP805 seems to be fully compatible to the
> AXP805 PMIC, so add the proper chain of compatible strings.
>
> Also at least on one board (Orangepi Zero2) there is no interrupt line
> connected to the CPU, so make the "interrupts" property optional.
>
> Signed-off-by: Andre Przywara <andre.p...@arm.com>

Acked-by: Maxime Ripard <mri...@kernel.org>

Maxime
signature.asc

Maxime Ripard

unread,
Jan 28, 2021, 5:15:51 AM1/28/21
to Andre Przywara, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland, Icenowy Zheng, Rob Herring, Clément Péron, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Lee Jones
On Wed, Jan 27, 2021 at 05:24:46PM +0000, Andre Przywara wrote:
> Currently the AXP chip requires to have its IRQ line connected to some
> interrupt controller, and will fail probing when this is not the case.
>
> On a new Allwinner SoC (H616) there is no NMI pin anymore, and at
> least one board does not connect the AXP's IRQ pin to anything else,
> so the interrupt functionality of the AXP chip is simply not available.
>
> Check whether the interrupt line number returned by the platform code is
> valid, before trying to register the irqchip. If not, we skip this
> registration, to avoid the driver to bail out completely.
>
> Signed-off-by: Andre Przywara <andre.p...@arm.com>

signature.asc

Maxime Ripard

unread,
Jan 28, 2021, 5:21:01 AM1/28/21
to Andre Przywara, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland, Icenowy Zheng, Rob Herring, Clément Péron, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Alessandro Zummo, Alexandre Belloni, devic...@vger.kernel.org, linu...@vger.kernel.org
On Wed, Jan 27, 2021 at 05:24:52PM +0000, Andre Przywara wrote:
> Add the obvious compatible name to the existing RTC binding, and pair
> it with the existing H6 fallback compatible string, as the devices are
> compatible.
>
> Signed-off-by: Andre Przywara <andre.p...@arm.com>
> Acked-by: Rob Herring <ro...@kernel.org>

Acked-by: Maxime Ripard <mri...@kernel.org>

maxime
signature.asc

Maxime Ripard

unread,
Jan 28, 2021, 5:21:17 AM1/28/21
to Andre Przywara, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland, Icenowy Zheng, Rob Herring, Clément Péron, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, devic...@vger.kernel.org
On Wed, Jan 27, 2021 at 05:24:55PM +0000, Andre Przywara wrote:
> Add the obvious compatible name to the existing EMAC binding, and pair
> it with the existing A64 fallback compatible string, as the devices are
> compatible.
>
> On the way use enums to group the compatible devices together.
>
> Signed-off-by: Andre Przywara <andre.p...@arm.com>

signature.asc

Maxime Ripard

unread,
Jan 28, 2021, 5:21:31 AM1/28/21
to Andre Przywara, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland, Icenowy Zheng, Rob Herring, Clément Péron, Shuosheng Huang, Yangtao Li, linux-ar...@lists.infradead.org, linux-...@vger.kernel.org, linux...@googlegroups.com, Alexandre Torgue, David S . Miller, Giuseppe Cavallaro, Jakub Kicinski, Jose Abreu, net...@vger.kernel.org
On Wed, Jan 27, 2021 at 05:24:56PM +0000, Andre Przywara wrote:
> The Allwinner H616 SoC has two EMAC controllers, with the second one
> being tied to the internal PHY, but also using a separate EMAC clock
> register.
>
> To tell the driver about which clock register to use, we add a parameter
> to our syscon phandle. The driver will use this value as an index into
> the regmap, so that we can address more than the first register, if
> needed.
>
> Signed-off-by: Andre Przywara <andre.p...@arm.com>

signature.asc
It is loading more messages.
0 new messages