* [PATCH 00/12] Support for Allwinner V853 SoC
@ 2025-01-10 12:39 Andras Szemzo
2025-01-10 12:39 ` [PATCH 01/12] clk: sunxi-ng: allow key feature in ccu reset Andras Szemzo
` (11 more replies)
0 siblings, 12 replies; 50+ messages in thread
From: Andras Szemzo @ 2025-01-10 12:39 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
Linus Walleij, Philipp Zabel, Maxime Ripard
Cc: Vinod Koul, Kishon Vijay Abraham I, Ulf Hansson, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Uwe Kleine-König,
Florian Fainelli, linux-clk, devicetree, linux-arm-kernel,
linux-sunxi, linux-kernel, linux-phy, linux-gpio, linux-pm,
linux-riscv
V85x is a device from Allwinner with video encoding targeted for the field of
IP Camera. It integrates the single CA7 core, and a T-Head E907 RISC-V mcu.
The SoC has the usual Allwinner peripherals and a Vivante NPU.
V853 is a BGA package without DRAM, V851s/V851s3 has the same die with
co-packaged 64MB/128MB DRAM (in a QFN88 package).
This patchset tries to add basical support for the V853 device family.
For review the ccu driver, I added a clk_summary debug output, maybe it'll help. [1]
PS:
As this is my first patchset, sorry for the rookie mistakes...
Andras Szemzo (12):
clk: sunxi-ng: allow key feature in ccu reset
dt-bindings: pinctrl: sunxi: add compatible for V853
pinctrl: sunxi: add driver for Allwinner V853.
dt-bindings: clock: sunxi-ng: add compatibles for V853
clk: sunxi-ng: add CCU drivers for V853
dt-bindings: clk: sunxi-ng: add V853 CCU clock/reset
devicetree: bindings: power: add v853 ppu
pmdomain: sunxi: add V853 ppu support
dt-bindings: power: add V853 ppu bindings
dt-bindings: phy: allwinner: add v853 usb phy
phy: allwinner: add v853 usb phy compatible
ARM: dts: sun8i: add DTSI file for V853
.../clock/allwinner,sun4i-a10-ccu.yaml | 2 +
.../phy/allwinner,sun8i-v853-usb-phy.yaml | 89 ++
.../pinctrl/allwinner,sun4i-a10-pinctrl.yaml | 13 +
.../power/allwinner,sun20i-d1-ppu.yaml | 1 +
arch/arm/boot/dts/allwinner/sun8i-v853.dtsi | 673 ++++++++++
drivers/clk/sunxi-ng/Kconfig | 10 +
drivers/clk/sunxi-ng/Makefile | 4 +
drivers/clk/sunxi-ng/ccu-sun8i-v853-r.c | 95 ++
drivers/clk/sunxi-ng/ccu-sun8i-v853-r.h | 15 +
drivers/clk/sunxi-ng/ccu-sun8i-v853.c | 1145 +++++++++++++++++
drivers/clk/sunxi-ng/ccu-sun8i-v853.h | 14 +
drivers/clk/sunxi-ng/ccu_common.h | 2 +
drivers/clk/sunxi-ng/ccu_mux.c | 4 +-
drivers/clk/sunxi-ng/ccu_reset.c | 7 +
drivers/clk/sunxi-ng/ccu_reset.h | 1 +
drivers/phy/allwinner/phy-sun4i-usb.c | 10 +
drivers/pinctrl/sunxi/Kconfig | 5 +
drivers/pinctrl/sunxi/Makefile | 1 +
drivers/pinctrl/sunxi/pinctrl-sun8i-v853.c | 980 ++++++++++++++
drivers/pinctrl/sunxi/pinctrl-sunxi.h | 1 +
drivers/pmdomain/sunxi/sun20i-ppu.c | 15 +
include/dt-bindings/clock/sun8i-v853-ccu.h | 132 ++
include/dt-bindings/clock/sun8i-v853-r-ccu.h | 16 +
.../power/allwinner,sun8i-v853-ppu.h | 10 +
include/dt-bindings/reset/sun8i-v853-ccu.h | 62 +
include/dt-bindings/reset/sun8i-v853-r-ccu.h | 14 +
26 files changed, 3318 insertions(+), 3 deletions(-)
create mode 100644 Documentation/devicetree/bindings/phy/allwinner,sun8i-v853-usb-phy.yaml
create mode 100644 arch/arm/boot/dts/allwinner/sun8i-v853.dtsi
create mode 100644 drivers/clk/sunxi-ng/ccu-sun8i-v853-r.c
create mode 100644 drivers/clk/sunxi-ng/ccu-sun8i-v853-r.h
create mode 100644 drivers/clk/sunxi-ng/ccu-sun8i-v853.c
create mode 100644 drivers/clk/sunxi-ng/ccu-sun8i-v853.h
create mode 100644 drivers/pinctrl/sunxi/pinctrl-sun8i-v853.c
create mode 100644 include/dt-bindings/clock/sun8i-v853-ccu.h
create mode 100644 include/dt-bindings/clock/sun8i-v853-r-ccu.h
create mode 100644 include/dt-bindings/power/allwinner,sun8i-v853-ppu.h
create mode 100644 include/dt-bindings/reset/sun8i-v853-ccu.h
create mode 100644 include/dt-bindings/reset/sun8i-v853-r-ccu.h
[1]:
enable prepare protect duty hardware connection
clock count count count rate accuracy phase cycle enable consumer id
---------------------------------------------------------------------------------------------------------------------------------------------
iosc 1 1 0 16000000 300000000 0 50000 Y deviceless no_connection_id
iosc-32k 1 1 0 31250 300000000 0 50000 Y deviceless no_connection_id
osc32k 1 1 0 31250 300000000 0 50000 Y deviceless no_connection_id
fanout2 0 0 0 31250 300000000 0 50000 N deviceless no_connection_id
fanout1 0 0 0 31250 300000000 0 50000 N deviceless no_connection_id
fanout0 0 0 0 31250 300000000 0 50000 N deviceless no_connection_id
rtc-32k 1 1 0 31250 300000000 0 50000 Y deviceless no_connection_id
osc32k-fanout 0 0 0 31250 300000000 0 50000 N deviceless no_connection_id
osc24M 9 9 0 24000000 0 0 50000 Y timer@2050000 no_connection_id
deviceless no_connection_id
fanout-12M 0 0 0 12000000 0 0 50000 N deviceless no_connection_id
fanout-24M 0 0 0 24000000 0 0 50000 N deviceless no_connection_id
riscv-cpu 0 0 0 24000000 0 0 50000 Y deviceless no_connection_id
riscv-axi 0 0 0 12000000 0 0 50000 Y deviceless no_connection_id
csi-mclk2 0 0 0 24000000 0 0 50000 N deviceless no_connection_id
csi-mclk1 0 0 0 24000000 0 0 50000 N deviceless no_connection_id
csi-mclk0 0 0 0 24000000 0 0 50000 N deviceless no_connection_id
mipi-dsi 0 0 0 24000000 0 0 50000 N deviceless no_connection_id
spif 0 0 0 24000000 0 0 50000 N deviceless no_connection_id
spi3 0 0 0 24000000 0 0 50000 N deviceless no_connection_id
spi2 0 0 0 24000000 0 0 50000 N deviceless no_connection_id
spi1 0 0 0 24000000 0 0 50000 N deviceless no_connection_id
mmc2 0 0 0 24000000 0 0 50000 N deviceless no_connection_id
avs 0 0 0 24000000 0 0 50000 N deviceless no_connection_id
apb1 1 1 0 24000000 0 0 50000 Y deviceless no_connection_id
bus-i2c4 0 0 0 24000000 0 0 50000 N deviceless no_connection_id
bus-i2c3 0 0 0 24000000 0 0 50000 N deviceless no_connection_id
bus-i2c2 0 0 0 24000000 0 0 50000 N 2502800.i2c no_connection_id
deviceless no_connection_id
bus-i2c1 0 0 0 24000000 0 0 50000 N deviceless no_connection_id
bus-i2c0 0 0 0 24000000 0 0 50000 N deviceless no_connection_id
bus-uart3 0 0 0 24000000 0 0 50000 N deviceless no_connection_id
bus-uart2 1 1 0 24000000 0 0 50000 Y 2500800.serial no_connection_id
deviceless no_connection_id
bus-uart1 0 0 0 24000000 0 0 50000 N deviceless no_connection_id
bus-uart0 0 0 0 24000000 0 0 50000 N deviceless no_connection_id
pll-npu-4x 1 1 0 1392000000 0 0 50000 Y deviceless no_connection_id
npu 1 1 0 348000000 0 0 50000 Y 3050000.npu core
deviceless no_connection_id
pll-audio-div5 0 0 0 614400000 0 0 50000 N deviceless no_connection_id
pll-audio-1x 0 0 0 614400000 0 0 50000 Y deviceless no_connection_id
audio-codec-adc 0 0 0 614400000 0 0 50000 N deviceless no_connection_id
audio-codec-dac 0 0 0 614400000 0 0 50000 N deviceless no_connection_id
dmic 0 0 0 614400000 0 0 50000 N deviceless no_connection_id
i2s1 0 0 0 614400000 0 0 50000 N deviceless no_connection_id
i2s0 0 0 0 614400000 0 0 50000 N deviceless no_connection_id
pll-csi-4x 0 0 0 1188000000 0 0 50000 N deviceless no_connection_id
pll-video-4x 0 0 0 1188000000 0 0 50000 N deviceless no_connection_id
tcon-lcd 0 0 0 1188000000 0 0 50000 N deviceless no_connection_id
pll-video-1x 0 0 0 297000000 0 0 50000 Y deviceless no_connection_id
fanout-27M 0 0 0 297000000 0 0 50000 N deviceless no_connection_id
pll-video-2x 0 0 0 594000000 0 0 50000 Y deviceless no_connection_id
pll-periph-4x 1 1 0 2400000000 0 0 50000 Y deviceless no_connection_id
pll-periph-480M 0 0 0 480000000 0 0 50000 Y deviceless no_connection_id
pll-periph-160M 0 0 0 160000000 0 0 50000 Y deviceless no_connection_id
fanout-16M 0 0 0 16000000 0 0 50000 N deviceless no_connection_id
pll-periph-800M 0 0 0 800000000 0 0 50000 Y deviceless no_connection_id
pll-periph-2x 1 1 0 1200000000 0 0 50000 Y deviceless no_connection_id
pll-periph-400M 0 0 0 400000000 0 0 50000 Y deviceless no_connection_id
mmc0 0 0 0 50000000 0 0 50000 N 4020000.mmc mmc
deviceless no_connection_id
mmc1 0 0 0 50000000 0 0 50000 N 4021000.mmc mmc
deviceless no_connection_id
ce 0 0 0 400000000 0 0 50000 N deviceless no_connection_id
pll-periph-200M 0 0 0 200000000 0 0 50000 Y deviceless no_connection_id
pll-periph-600M 2 2 0 600000000 0 0 50000 Y deviceless no_connection_id
apb0 2 2 0 100000000 0 0 50000 Y 2000000.pinctrl apb
deviceless no_connection_id
fanout-pclk 0 0 0 100000000 0 0 50000 N deviceless no_connection_id
bus-audio-codec 0 0 0 100000000 0 0 50000 N deviceless no_connection_id
bus-gpadc 1 1 0 100000000 0 0 50000 Y 2009000.adc no_connection_id
deviceless no_connection_id
bus-pwm 0 0 0 100000000 0 0 50000 N deviceless no_connection_id
ahb 8 8 0 200000000 0 0 50000 Y deviceless no_connection_id
riscv-cfg 0 0 0 200000000 0 0 50000 N deviceless no_connection_id
bus-wiegand 0 0 0 200000000 0 0 50000 N deviceless no_connection_id
bus-csi 0 0 0 200000000 0 0 50000 N deviceless no_connection_id
bus-tcon-lcd 0 0 0 200000000 0 0 50000 N deviceless no_connection_id
bus-mipi-dsi 0 0 0 200000000 0 0 50000 N deviceless no_connection_id
bus-dpss-top 0 0 0 200000000 0 0 50000 N deviceless no_connection_id
bus-otg 1 1 0 200000000 0 0 50000 Y 4100000.usb no_connection_id
deviceless no_connection_id
bus-ehci 1 1 0 200000000 0 0 50000 Y usb@4101000 no_connection_id
deviceless no_connection_id
bus-ohci 2 2 0 200000000 0 0 50000 Y usb@4101400 no_connection_id
usb@4101000 no_connection_id
deviceless no_connection_id
bus-dmic 0 0 0 200000000 0 0 50000 N deviceless no_connection_id
bus-i2s1 0 0 0 200000000 0 0 50000 N deviceless no_connection_id
bus-i2s0 0 0 0 200000000 0 0 50000 N deviceless no_connection_id
bus-ths 0 0 0 200000000 0 0 50000 N deviceless no_connection_id
bus-emac 0 0 0 200000000 0 0 50000 N deviceless no_connection_id
bus-spif 0 0 0 200000000 0 0 50000 N deviceless no_connection_id
bus-spi3 0 0 0 200000000 0 0 50000 N deviceless no_connection_id
bus-spi2 0 0 0 200000000 0 0 50000 N deviceless no_connection_id
bus-spi1 0 0 0 200000000 0 0 50000 N deviceless no_connection_id
bus-spi0 0 0 0 200000000 0 0 50000 N 4025000.spi ahb
deviceless no_connection_id
bus-mmc2 0 0 0 200000000 0 0 50000 N deviceless no_connection_id
bus-mmc1 0 0 0 200000000 0 0 50000 N 4021000.mmc ahb
deviceless no_connection_id
bus-mmc0 0 0 0 200000000 0 0 50000 N 4020000.mmc ahb
deviceless no_connection_id
bus-dram 1 1 0 200000000 0 0 50000 Y deviceless no_connection_id
bus-iommu 0 0 0 200000000 0 0 50000 N deviceless no_connection_id
bus-dbg 0 0 0 200000000 0 0 50000 N deviceless no_connection_id
bus-hstimer 1 1 0 200000000 0 0 50000 Y 3008000.hstimer no_connection_id
deviceless no_connection_id
bus-spinlock 1 1 0 200000000 0 0 50000 Y 3005000.hwlock ahb
deviceless no_connection_id
bus-msgbox1 0 0 0 200000000 0 0 50000 N deviceless no_connection_id
bus-msgbox0 0 0 0 200000000 0 0 50000 N deviceless no_connection_id
bus-dma 1 1 0 200000000 0 0 50000 Y 3002000.dma-controller no_connection_id
deviceless no_connection_id
bus-npu 1 1 0 200000000 0 0 50000 Y 3050000.npu bus
deviceless no_connection_id
bus-ve 0 0 0 200000000 0 0 50000 N deviceless no_connection_id
bus-ce 0 0 0 200000000 0 0 50000 N deviceless no_connection_id
bus-g2d 0 0 0 200000000 0 0 50000 N deviceless no_connection_id
bus-de 0 0 0 200000000 0 0 50000 N deviceless no_connection_id
pll-periph-300M 0 0 0 300000000 0 0 50000 Y deviceless no_connection_id
csi-top 0 0 0 300000000 0 0 50000 N deviceless no_connection_id
spi0 0 0 0 75000000 0 0 50000 N 4025000.spi mod
deviceless no_connection_id
ve 0 0 0 300000000 0 0 50000 N deviceless no_connection_id
g2d 0 0 0 300000000 0 0 50000 N deviceless no_connection_id
de 0 0 0 300000000 0 0 50000 N deviceless no_connection_id
pll-periph-150M 0 0 0 150000000 0 0 50000 Y deviceless no_connection_id
fanout-25M 0 0 0 25000000 0 0 50000 N deviceless no_connection_id
emac-25M 0 0 0 25000000 0 0 50000 N deviceless no_connection_id
pll-ddr 1 1 0 1056000000 0 0 50000 Y deviceless no_connection_id
dram 2 2 0 1056000000 0 0 50000 Y deviceless no_connection_id
mbus 1 1 0 264000000 0 0 50000 Y deviceless no_connection_id
mbus-g2d 0 0 0 264000000 0 0 50000 N deviceless no_connection_id
mbus-isp 0 0 0 264000000 0 0 50000 N deviceless no_connection_id
mbus-csi 0 0 0 264000000 0 0 50000 N deviceless no_connection_id
mbus-ce 0 0 0 264000000 0 0 50000 N deviceless no_connection_id
mbus-ve 0 0 0 264000000 0 0 50000 N deviceless no_connection_id
mbus-dma 1 1 0 264000000 0 0 50000 Y 3002000.dma-controller mbus
deviceless no_connection_id
pll-cpu 1 1 0 912000000 0 0 50000 Y deviceless no_connection_id
cpu 1 1 0 912000000 0 0 50000 Y deviceless no_connection_id
cpu-apb 0 0 0 228000000 0 0 50000 Y deviceless no_connection_id
cpu-axi 0 0 0 456000000 0 0 50000 Y deviceless no_connection_id
osc12M 1 1 0 12000000 0 0 50000 Y deviceless no_connection_id
usb 3 3 0 12000000 0 0 50000 Y usb@4101400 no_connection_id
usb@4101000 no_connection_id
4100400.phy usb0_phy
deviceless no_connection_id
osc24M-32k 0 0 0 32000 0 0 50000 N deviceless no_connection_id
r-cpucfg 0 0 0 24000000 0 0 50000 N deviceless no_connection_id
r-rtc 1 1 0 24000000 0 0 50000 Y 7090000.rtc bus
deviceless no_connection_id
r-ppu 1 1 0 24000000 0 0 50000 Y 7001000.power-controller no_connection_id
deviceless no_connection_id
r-twd 0 0 0 24000000 0 0 50000 N deviceless no_connection_id
pll-audio-div2 0 0 0 0 0 0 50000 Y deviceless no_connection_id
pll-audio-4x 0 0 0 0 0 0 50000 Y deviceless no_connection_id
--
2.39.5
^ permalink raw reply [flat|nested] 50+ messages in thread
* [PATCH 01/12] clk: sunxi-ng: allow key feature in ccu reset
2025-01-10 12:39 [PATCH 00/12] Support for Allwinner V853 SoC Andras Szemzo
@ 2025-01-10 12:39 ` Andras Szemzo
2025-01-10 12:39 ` [PATCH 02/12] dt-bindings: pinctrl: sunxi: add compatible for V853 Andras Szemzo
` (10 subsequent siblings)
11 siblings, 0 replies; 50+ messages in thread
From: Andras Szemzo @ 2025-01-10 12:39 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
Linus Walleij, Philipp Zabel, Maxime Ripard
Cc: Vinod Koul, Kishon Vijay Abraham I, Ulf Hansson, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Uwe Kleine-König,
Florian Fainelli, linux-clk, devicetree, linux-arm-kernel,
linux-sunxi, linux-kernel, linux-phy, linux-gpio, linux-pm,
linux-riscv
Some newer SoCs, like V853 has reset registers, what can be write only
with fixed key value. Move this value from ccu_mux and reuse
in the reset code.
Signed-off-by: Andras Szemzo <szemzo.andras@gmail.com>
---
drivers/clk/sunxi-ng/ccu_common.h | 2 ++
drivers/clk/sunxi-ng/ccu_mux.c | 4 +---
drivers/clk/sunxi-ng/ccu_reset.c | 7 +++++++
drivers/clk/sunxi-ng/ccu_reset.h | 1 +
4 files changed, 11 insertions(+), 3 deletions(-)
diff --git a/drivers/clk/sunxi-ng/ccu_common.h b/drivers/clk/sunxi-ng/ccu_common.h
index dd330426a6e5..36132cb8b920 100644
--- a/drivers/clk/sunxi-ng/ccu_common.h
+++ b/drivers/clk/sunxi-ng/ccu_common.h
@@ -23,6 +23,8 @@
/* MMC timing mode switch bit */
#define CCU_MMC_NEW_TIMING_MODE BIT(30)
+#define CCU_KEY_VALUE 0x16aa0000
+
struct device_node;
struct ccu_common {
diff --git a/drivers/clk/sunxi-ng/ccu_mux.c b/drivers/clk/sunxi-ng/ccu_mux.c
index d7ffbdeee9e0..127269ab20ea 100644
--- a/drivers/clk/sunxi-ng/ccu_mux.c
+++ b/drivers/clk/sunxi-ng/ccu_mux.c
@@ -12,8 +12,6 @@
#include "ccu_gate.h"
#include "ccu_mux.h"
-#define CCU_MUX_KEY_VALUE 0x16aa0000
-
static u16 ccu_mux_get_prediv(struct ccu_common *common,
struct ccu_mux_internal *cm,
int parent_index)
@@ -196,7 +194,7 @@ int ccu_mux_helper_set_parent(struct ccu_common *common,
/* The key field always reads as zero. */
if (common->features & CCU_FEATURE_KEY_FIELD)
- reg |= CCU_MUX_KEY_VALUE;
+ reg |= CCU_KEY_VALUE;
reg &= ~GENMASK(cm->width + cm->shift - 1, cm->shift);
writel(reg | (index << cm->shift), common->base + common->reg);
diff --git a/drivers/clk/sunxi-ng/ccu_reset.c b/drivers/clk/sunxi-ng/ccu_reset.c
index 55bc7c7cda0f..a9aee35c6617 100644
--- a/drivers/clk/sunxi-ng/ccu_reset.c
+++ b/drivers/clk/sunxi-ng/ccu_reset.c
@@ -9,6 +9,7 @@
#include <linux/reset-controller.h>
#include "ccu_reset.h"
+#include "ccu_common.h"
static int ccu_reset_assert(struct reset_controller_dev *rcdev,
unsigned long id)
@@ -21,6 +22,9 @@ static int ccu_reset_assert(struct reset_controller_dev *rcdev,
spin_lock_irqsave(ccu->lock, flags);
reg = readl(ccu->base + map->reg);
+ if (map->features & CCU_FEATURE_KEY_FIELD)
+ reg |= CCU_KEY_VALUE;
+
writel(reg & ~map->bit, ccu->base + map->reg);
spin_unlock_irqrestore(ccu->lock, flags);
@@ -39,6 +43,9 @@ static int ccu_reset_deassert(struct reset_controller_dev *rcdev,
spin_lock_irqsave(ccu->lock, flags);
reg = readl(ccu->base + map->reg);
+ if (map->features & CCU_FEATURE_KEY_FIELD)
+ reg |= CCU_KEY_VALUE;
+
writel(reg | map->bit, ccu->base + map->reg);
spin_unlock_irqrestore(ccu->lock, flags);
diff --git a/drivers/clk/sunxi-ng/ccu_reset.h b/drivers/clk/sunxi-ng/ccu_reset.h
index 941276a8ec2e..3fd5d427c26c 100644
--- a/drivers/clk/sunxi-ng/ccu_reset.h
+++ b/drivers/clk/sunxi-ng/ccu_reset.h
@@ -12,6 +12,7 @@
struct ccu_reset_map {
u16 reg;
u32 bit;
+ u32 features;
};
--
2.39.5
^ permalink raw reply related [flat|nested] 50+ messages in thread
* [PATCH 02/12] dt-bindings: pinctrl: sunxi: add compatible for V853
2025-01-10 12:39 [PATCH 00/12] Support for Allwinner V853 SoC Andras Szemzo
2025-01-10 12:39 ` [PATCH 01/12] clk: sunxi-ng: allow key feature in ccu reset Andras Szemzo
@ 2025-01-10 12:39 ` Andras Szemzo
2025-01-14 19:52 ` Rob Herring (Arm)
2025-01-16 9:08 ` Linus Walleij
2025-01-10 12:39 ` [PATCH 03/12] pinctrl: sunxi: add driver for Allwinner V853 Andras Szemzo
` (9 subsequent siblings)
11 siblings, 2 replies; 50+ messages in thread
From: Andras Szemzo @ 2025-01-10 12:39 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
Linus Walleij, Philipp Zabel, Maxime Ripard
Cc: Vinod Koul, Kishon Vijay Abraham I, Ulf Hansson, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Uwe Kleine-König,
Florian Fainelli, linux-clk, devicetree, linux-arm-kernel,
linux-sunxi, linux-kernel, linux-phy, linux-gpio, linux-pm,
linux-riscv
Add compatible strings for V853 family pinctrl.
Signed-off-by: Andras Szemzo <szemzo.andras@gmail.com>
---
.../pinctrl/allwinner,sun4i-a10-pinctrl.yaml | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/Documentation/devicetree/bindings/pinctrl/allwinner,sun4i-a10-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/allwinner,sun4i-a10-pinctrl.yaml
index 450240570314..990b78765427 100644
--- a/Documentation/devicetree/bindings/pinctrl/allwinner,sun4i-a10-pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/allwinner,sun4i-a10-pinctrl.yaml
@@ -44,6 +44,7 @@ properties:
- allwinner,sun8i-r40-pinctrl
- allwinner,sun8i-v3-pinctrl
- allwinner,sun8i-v3s-pinctrl
+ - allwinner,sun8i-v853-pinctrl
- allwinner,sun9i-a80-pinctrl
- allwinner,sun9i-a80-r-pinctrl
- allwinner,sun20i-d1-pinctrl
@@ -179,6 +180,18 @@ allOf:
minItems: 7
maxItems: 7
+ - if:
+ properties:
+ compatible:
+ enum:
+ - allwinner,sun8i-v853-pinctrl
+
+ then:
+ properties:
+ interrupts:
+ minItems: 8
+ maxItems: 8
+
- if:
properties:
compatible:
--
2.39.5
^ permalink raw reply related [flat|nested] 50+ messages in thread
* [PATCH 03/12] pinctrl: sunxi: add driver for Allwinner V853.
2025-01-10 12:39 [PATCH 00/12] Support for Allwinner V853 SoC Andras Szemzo
2025-01-10 12:39 ` [PATCH 01/12] clk: sunxi-ng: allow key feature in ccu reset Andras Szemzo
2025-01-10 12:39 ` [PATCH 02/12] dt-bindings: pinctrl: sunxi: add compatible for V853 Andras Szemzo
@ 2025-01-10 12:39 ` Andras Szemzo
2025-01-14 14:14 ` Linus Walleij
2025-01-14 14:19 ` Andre Przywara
2025-01-10 12:39 ` [PATCH 04/12] dt-bindings: clock: sunxi-ng: add compatibles for V853 Andras Szemzo
` (8 subsequent siblings)
11 siblings, 2 replies; 50+ messages in thread
From: Andras Szemzo @ 2025-01-10 12:39 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
Linus Walleij, Philipp Zabel, Maxime Ripard
Cc: Vinod Koul, Kishon Vijay Abraham I, Ulf Hansson, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Uwe Kleine-König,
Florian Fainelli, linux-clk, devicetree, linux-arm-kernel,
linux-sunxi, linux-kernel, linux-phy, linux-gpio, linux-pm,
linux-riscv
The V853 family has multiple package variants, from BGA to QFN88.
The latter has co-packaged DRAM and fewer pins, and less features (pin muxes).
All family members can be supported by a single driver, as the available pins
with allowed muxes is the same across the devices.
Signed-off-by: Andras Szemzo <szemzo.andras@gmail.com>
---
drivers/pinctrl/sunxi/Kconfig | 5 +
drivers/pinctrl/sunxi/Makefile | 1 +
drivers/pinctrl/sunxi/pinctrl-sun8i-v853.c | 980 +++++++++++++++++++++
drivers/pinctrl/sunxi/pinctrl-sunxi.h | 1 +
4 files changed, 987 insertions(+)
create mode 100644 drivers/pinctrl/sunxi/pinctrl-sun8i-v853.c
diff --git a/drivers/pinctrl/sunxi/Kconfig b/drivers/pinctrl/sunxi/Kconfig
index a78fdbbdfc0c..df67310672ac 100644
--- a/drivers/pinctrl/sunxi/Kconfig
+++ b/drivers/pinctrl/sunxi/Kconfig
@@ -86,6 +86,11 @@ config PINCTRL_SUN20I_D1
default MACH_SUN8I || (RISCV && ARCH_SUNXI)
select PINCTRL_SUNXI
+config PINCTRL_SUN8I_V853
+ bool "Support for the Allwinner V853 PIO"
+ default MACH_SUN8I
+ select PINCTRL_SUNXI
+
config PINCTRL_SUN50I_A64
bool "Support for the Allwinner A64 PIO"
default ARM64 && ARCH_SUNXI
diff --git a/drivers/pinctrl/sunxi/Makefile b/drivers/pinctrl/sunxi/Makefile
index 2ff5a55927ad..2042276e85d6 100644
--- a/drivers/pinctrl/sunxi/Makefile
+++ b/drivers/pinctrl/sunxi/Makefile
@@ -28,3 +28,4 @@ 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
+obj-$(CONFIG_PINCTRL_SUN8I_V853) += pinctrl-sun8i-v853.o
diff --git a/drivers/pinctrl/sunxi/pinctrl-sun8i-v853.c b/drivers/pinctrl/sunxi/pinctrl-sun8i-v853.c
new file mode 100644
index 000000000000..62b84404bd14
--- /dev/null
+++ b/drivers/pinctrl/sunxi/pinctrl-sun8i-v853.c
@@ -0,0 +1,980 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Allwinner V853 SoC pinctrl driver.
+ *
+ * Copyright (c) 2016-2021 weidonghui <weidonghui@allwinnertech.com>
+ * Copyright (c) 2023 Andras Szemzo <szemzo.andras@gmail.com>
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/io.h>
+
+#include "pinctrl-sunxi.h"
+
+/* Pin banks are: A C D E F G H I */
+static const struct sunxi_desc_pin sun8i_v853_pins[] = {
+
+ /* bank A */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 0),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi"), /* CKOP */
+ SUNXI_FUNCTION(0x3, "ncsi"), /* D8 */
+ SUNXI_FUNCTION(0x5, "test"),
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 0)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 1),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi"), /* CKON */
+ SUNXI_FUNCTION(0x3, "ncsi"), /* D9 */
+ SUNXI_FUNCTION(0x5, "test"), /* test */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 1)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 2),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi"), /* D1N */
+ SUNXI_FUNCTION(0x3, "ncsi"), /* D10 */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 2)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 3),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi"), /* D1P */
+ SUNXI_FUNCTION(0x3, "ncsi"), /* D11 */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 3)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 4),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi"), /* D0P */
+ SUNXI_FUNCTION(0x3, "ncsi"), /* D12 */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 4)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 5),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi"), /* D0N */
+ SUNXI_FUNCTION(0x3, "ncsi"), /* D13 */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 5)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 6),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi"), /* D0N/D2N */
+ SUNXI_FUNCTION(0x3, "ncsi"), /* D14 */
+ SUNXI_FUNCTION(0x4, "i2c1"), /* SCK */
+ SUNXI_FUNCTION(0x5, "pwm0"),
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 6)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 7),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi"), /* D0P/D2P */
+ SUNXI_FUNCTION(0x3, "ncsi"), /* D15 */
+ SUNXI_FUNCTION(0x4, "i2c1"), /* SDA */
+ SUNXI_FUNCTION(0x5, "pwm1"),
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 7)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 8),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi"), /* D1N/D3N */
+ SUNXI_FUNCTION(0x3, "i2c4"), /* SCK */
+ SUNXI_FUNCTION(0x4, "i2c3"), /* SCK */
+ SUNXI_FUNCTION(0x5, "pwm2"),
+ SUNXI_FUNCTION(0x6, "uart2"), /* TX */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 8)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 9),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi"), /* D1P/D3P */
+ SUNXI_FUNCTION(0x3, "i2c4"), /* SDA */
+ SUNXI_FUNCTION(0x4, "i2c3"), /* SDA */
+ SUNXI_FUNCTION(0x5, "pwm3"),
+ SUNXI_FUNCTION(0x6, "uart2"), /* RX */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 9)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 10),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi"), /* CKON */
+ SUNXI_FUNCTION(0x3, "ncsi"), /* HSYNC */
+ SUNXI_FUNCTION(0x4, "csi_mclk"), /* MCLK0 */
+ SUNXI_FUNCTION(0x5, "i2c0"), /* SCK */
+ SUNXI_FUNCTION(0x6, "clk"), /* FANOUT0 */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 10)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 11),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi"), /* CKOP */
+ SUNXI_FUNCTION(0x3, "ncsi"), /* VSYNC */
+ SUNXI_FUNCTION(0x4, "csi_mclk"), /* MCLK1 */
+ SUNXI_FUNCTION(0x5, "i2c0"), /* SDA */
+ SUNXI_FUNCTION(0x6, "clk"), /* FANOUT1 */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 11)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 12),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x3, "ncsi"), /* D0 */
+ SUNXI_FUNCTION(0x4, "csi_mclk"), /* MCLK0 */
+ SUNXI_FUNCTION(0x5, "uart0"), /* TX */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 12)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 13),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x3, "ncsi"), /* D1 */
+ SUNXI_FUNCTION(0x4, "csi_mclk"), /* MCLK1 */
+ SUNXI_FUNCTION(0x5, "uart0"), /* RX */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 13)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 14),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x3, "ncsi"), /* D2 */
+ SUNXI_FUNCTION(0x4, "i2c1"), /* SCK */
+ SUNXI_FUNCTION(0x5, "clk"), /* FANOUT0 */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 14)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 15),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x3, "ncsi"), /* D3 */
+ SUNXI_FUNCTION(0x4, "i2c1"), /* SDA */
+ SUNXI_FUNCTION(0x5, "clk"), /* FANOUT1 */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 15)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 16),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x3, "ncsi"), /* D4 */
+ SUNXI_FUNCTION(0x4, "i2c0"), /* SCK */
+ SUNXI_FUNCTION(0x5, "uart3"), /* TX */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 16)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 17),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x3, "ncsi"), /* D5 */
+ SUNXI_FUNCTION(0x4, "i2c0"), /* SDA */
+ SUNXI_FUNCTION(0x5, "uart3"), /* RX */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 17)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 18),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x3, "ncsi"), /* D6 */
+ SUNXI_FUNCTION(0x4, "wiegand"), /* D0 */
+ SUNXI_FUNCTION(0x5, "uart3"), /* RTS */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 18)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 19),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x3, "ncsi"), /* D7 */
+ SUNXI_FUNCTION(0x4, "wiegand"), /* D1 */
+ SUNXI_FUNCTION(0x5, "uart3"), /* CTS */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 19)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 20),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x3, "ncsi"), /* MCLK */
+ SUNXI_FUNCTION(0x4, "csi"), /* SM_VS */
+ SUNXI_FUNCTION(0x5, "tcon"), /* TRIG */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 20)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 21),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x3, "ncsi"), /* PCLK */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 21)),
+ /* bank C */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 0),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "spif"), /* CLK */
+ SUNXI_FUNCTION(0x3, "sdc2"), /* CLK */
+ SUNXI_FUNCTION(0x4, "spi0"), /* CLK */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 0)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 1),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "spif"), /* CS0 */
+ SUNXI_FUNCTION(0x3, "sdc2"), /* CMD */
+ SUNXI_FUNCTION(0x4, "spi0"), /* CS0 */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 1)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 2),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "spif"), /* MOSI_IO0 */
+ SUNXI_FUNCTION(0x3, "sdc2"), /* D2 */
+ SUNXI_FUNCTION(0x4, "spi0"), /* MOSI */
+ SUNXI_FUNCTION(0x5, "boot_sel0"), /* SEL0 */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 2)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 3),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "spif"), /* MOSI_IO1 */
+ SUNXI_FUNCTION(0x3, "sdc2"), /* D1 */
+ SUNXI_FUNCTION(0x4, "spi0"), /* MISO */
+ SUNXI_FUNCTION(0x5, "boot_sel1"), /* SEL1 */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 3)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 4),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "spif"), /* WP_IO2 */
+ SUNXI_FUNCTION(0x3, "sdc2"), /* D0 */
+ SUNXI_FUNCTION(0x4, "spi0"), /* WP */
+ SUNXI_FUNCTION(0x5, "pwm4"),
+ SUNXI_FUNCTION(0x6, "i2c1"), /* SCK */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 4)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 5),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "spif"), /* HOLD_IO3 */
+ SUNXI_FUNCTION(0x3, "sdc2"), /* D3 */
+ SUNXI_FUNCTION(0x4, "spi0"), /* HOLD */
+ SUNXI_FUNCTION(0x5, "pwm4"),
+ SUNXI_FUNCTION(0x6, "i2c1"), /* SDA */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 5)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 6),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "spif"), /* IO4 */
+ SUNXI_FUNCTION(0x3, "sdc2"), /* D4 */
+ SUNXI_FUNCTION(0x4, "spi0"), /* CSI */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 6)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 7),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "spif"), /* IO5 */
+ SUNXI_FUNCTION(0x3, "sdc2"), /* D5 */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 7)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 8),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "spif"), /* IO6 */
+ SUNXI_FUNCTION(0x3, "sdc2"), /* D6 */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 8)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 9),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "spif"), /* IO7 */
+ SUNXI_FUNCTION(0x3, "sdc2"), /* D7 */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 9)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 10),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "spif"), /* DQS */
+ SUNXI_FUNCTION(0x3, "sdc2"), /* DS */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 10)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 11),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x3, "sdc2"), /* RTS */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 11)),
+ /* bank D */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 0),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd"), /* D2 */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 0)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 1),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd"), /* D3 */
+ SUNXI_FUNCTION(0x3, "pwm0"),
+ SUNXI_FUNCTION(0x4, "emac"), /* RXD1 */
+ SUNXI_FUNCTION(0x5, "dsi"), /* D0N */
+ SUNXI_FUNCTION(0x6, "spi1"), /* CS0/CSX */
+ SUNXI_FUNCTION(0x7, "emac"), /* TXD0 */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 1)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 2),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd"), /* D4 */
+ SUNXI_FUNCTION(0x3, "pwm1"),
+ SUNXI_FUNCTION(0x4, "emac"), /* RXD0 */
+ SUNXI_FUNCTION(0x5, "dsi"), /* D1P */
+ SUNXI_FUNCTION(0x6, "spi1"), /* CLK/SCLK */
+ SUNXI_FUNCTION(0x7, "emac"), /* TXD1 */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 2)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 3),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd"), /* D5 */
+ SUNXI_FUNCTION(0x3, "pwm2"),
+ SUNXI_FUNCTION(0x4, "emac"), /* CRS_DV */
+ SUNXI_FUNCTION(0x5, "dsi"), /* D1N */
+ SUNXI_FUNCTION(0x6, "spi1"), /* MOSI/SDO */
+ SUNXI_FUNCTION(0x7, "emac"), /* RXER */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 3)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 4),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd"), /* D6 */
+ SUNXI_FUNCTION(0x3, "pwm3"),
+ SUNXI_FUNCTION(0x4, "emac"), /* RXER */
+ SUNXI_FUNCTION(0x5, "dsi"), /* D1P */
+ SUNXI_FUNCTION(0x6, "spi1"), /* MISO/SDI/TE/DCX */
+ SUNXI_FUNCTION(0x7, "emac"), /* CRS_DV */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 4)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 5),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd"), /* D7 */
+ SUNXI_FUNCTION(0x3, "pwm4"),
+ SUNXI_FUNCTION(0x4, "emac"), /* TXD1 */
+ SUNXI_FUNCTION(0x5, "dsi"), /* CKN */
+ SUNXI_FUNCTION(0x6, "spi1"), /* HOLD/DCX/WRX */
+ SUNXI_FUNCTION(0x7, "emac"), /* RXD1 */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 5)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 6),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd"), /* D10 */
+ SUNXI_FUNCTION(0x3, "pwm5"),
+ SUNXI_FUNCTION(0x4, "emac"), /* TXD0 */
+ SUNXI_FUNCTION(0x5, "dsi"), /* CKP */
+ SUNXI_FUNCTION(0x6, "spi1"), /* WP/TE */
+ SUNXI_FUNCTION(0x7, "emac"), /* RXD */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 6)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 7),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd"), /* D11 */
+ SUNXI_FUNCTION(0x3, "pwm6"),
+ SUNXI_FUNCTION(0x4, "emac"), /* TXCK */
+ SUNXI_FUNCTION(0x5, "dsi"), /* D2N */
+ SUNXI_FUNCTION(0x6, "spi1"), /* CS1 */
+ SUNXI_FUNCTION(0x7, "emac"), /* MDC */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 7)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 8),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd"), /* D12 */
+ SUNXI_FUNCTION(0x3, "pwm7"),
+ SUNXI_FUNCTION(0x4, "emac"), /* TXEN */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 8)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 9),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd"), /* D13 */
+ SUNXI_FUNCTION(0x3, "pwm8"),
+ SUNXI_FUNCTION(0x5, "dsi"), /* D2P */
+ SUNXI_FUNCTION(0x7, "emac"), /* MDIO */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 9)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 10),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd"), /* D14 */
+ SUNXI_FUNCTION(0x3, "i2s1"), /* MCLK */
+ SUNXI_FUNCTION(0x5, "dsi"), /* D3N */
+ SUNXI_FUNCTION(0x7, "emac"), /* TXEN */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 10)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 11),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd"), /* D15 */
+ SUNXI_FUNCTION(0x3, "i2s1"), /* BCLK */
+ SUNXI_FUNCTION(0x5, "dsi"), /* D3P */
+ SUNXI_FUNCTION(0x7, "emac"), /* TXCKk */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 11)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 12),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd"), /* D18 */
+ SUNXI_FUNCTION(0x3, "i2s1"), /* LCLK */
+ SUNXI_FUNCTION(0x5, "dmic"), /* DATA3 */
+ SUNXI_FUNCTION(0x7, "pwm11"),
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 12)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 13),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd"), /* D19 */
+ SUNXI_FUNCTION(0x3, "i2s1"), /* DOUT0 */
+ SUNXI_FUNCTION(0x5, "dmic"), /* DATA2 */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 13)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 14),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd"), /* D20 */
+ SUNXI_FUNCTION(0x3, "i2s1"), /* DOUT1 */
+ SUNXI_FUNCTION(0x4, "i2s1"), /* DIN1 */
+ SUNXI_FUNCTION(0x5, "dmic"), /* DATA1 */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 14)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 15),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd"), /* D21 */
+ SUNXI_FUNCTION(0x3, "i2s1"), /* DOUT2 */
+ SUNXI_FUNCTION(0x4, "i2s1"), /* DIN2 */
+ SUNXI_FUNCTION(0x5, "dmic"), /* DATA0 */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 15)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 16),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd"), /* D22 */
+ SUNXI_FUNCTION(0x3, "i2s1"), /* DOUT3 */
+ SUNXI_FUNCTION(0x4, "i2s1"), /* DIN3 */
+ SUNXI_FUNCTION(0x5, "dmic"), /* CLK */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 16)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 17),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd"), /* D23 */
+ SUNXI_FUNCTION(0x3, "i2s1"), /* DIN0 */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 17)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 18),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd"), /* CLK */
+ SUNXI_FUNCTION(0x4, "emac"), /* EPHY_25M */
+ SUNXI_FUNCTION(0x5, "spi2"), /* CLK */
+ SUNXI_FUNCTION(0x6, "i2c3"), /* SCK */
+ SUNXI_FUNCTION(0x7, "uart2"), /* TX */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 18)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 19),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd"), /* DE */
+ SUNXI_FUNCTION(0x3, "pwm9"),
+ SUNXI_FUNCTION(0x4, "tcon"), /* TRIG */
+ SUNXI_FUNCTION(0x5, "spi2"), /* MOSI */
+ SUNXI_FUNCTION(0x6, "i2c3"), /* SDA */
+ SUNXI_FUNCTION(0x7, "uart2"), /* RX */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 19)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 20),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd"), /* HSYNC */
+ SUNXI_FUNCTION(0x3, "pwm10"),
+ SUNXI_FUNCTION(0x4, "emac"), /* MDC */
+ SUNXI_FUNCTION(0x5, "spi2"), /* MISO */
+ SUNXI_FUNCTION(0x6, "i2c2"), /* SCK */
+ SUNXI_FUNCTION(0x7, "uart2"), /* RTS */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 20)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 21),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd"), /* VSYNC */
+ SUNXI_FUNCTION(0x4, "emac"), /* MDIO */
+ SUNXI_FUNCTION(0x5, "spi2"), /* CS0 */
+ SUNXI_FUNCTION(0x6, "i2c2"), /* SDA */
+ SUNXI_FUNCTION(0x7, "uart2"), /* CTS */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 21)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 22),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "pwm9"),
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 22)),
+ /* bank E */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 0),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "ncsi"), /* PCLK */
+ SUNXI_FUNCTION(0x3, "emac"), /* RXD/RXD1 */
+ SUNXI_FUNCTION(0x4, "i2s1"), /* MCLK */
+ SUNXI_FUNCTION(0x5, "pwm0"),
+ SUNXI_FUNCTION(0x6, "sdc1"), /* CLK */
+ SUNXI_FUNCTION(0x7, "uart3"), /* TX */
+ SUNXI_FUNCTION(0x8, "i2c3"), /* SCK */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 0)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 1),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "ncsi"), /* MCLK */
+ SUNXI_FUNCTION(0x3, "emac"), /* RXCK/TXCK */
+ SUNXI_FUNCTION(0x4, "i2s1"), /* BCLK */
+ SUNXI_FUNCTION(0x5, "pwm1"),
+ SUNXI_FUNCTION(0x6, "sdc1"), /* CMD */
+ SUNXI_FUNCTION(0x7, "uart3"), /* RX */
+ SUNXI_FUNCTION(0x8, "i2c3"), /* SDA */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 1)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 2),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "ncsi"), /* HSYNC */
+ SUNXI_FUNCTION(0x3, "emac"), /* RXCTL/CRS_DV */
+ SUNXI_FUNCTION(0x4, "i2s1"), /* LCLK */
+ SUNXI_FUNCTION(0x5, "pwm2"),
+ SUNXI_FUNCTION(0x6, "sdc1"), /* D0 */
+ SUNXI_FUNCTION(0x7, "uart3"), /* CTS */
+ SUNXI_FUNCTION(0x8, "i2c1"), /* SCK */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 2)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 3),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "ncsi"), /* VSYNC */
+ SUNXI_FUNCTION(0x3, "emac"), /* RXD0 */
+ SUNXI_FUNCTION(0x4, "i2s1"), /* DIN0 */
+ SUNXI_FUNCTION(0x5, "pwm3"),
+ SUNXI_FUNCTION(0x6, "sdc1"), /* D1 */
+ SUNXI_FUNCTION(0x7, "uart3"), /* RTS */
+ SUNXI_FUNCTION(0x8, "i2c1"), /* SDA */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 3)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 4),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "ncsi"), /* D0 */
+ SUNXI_FUNCTION(0x3, "emac"), /* TXD0 */
+ SUNXI_FUNCTION(0x4, "i2s1"), /* DOUT0 */
+ SUNXI_FUNCTION(0x5, "pwm4"),
+ SUNXI_FUNCTION(0x6, "sdc1"), /* D2 */
+ SUNXI_FUNCTION(0x7, "i2c3"), /* SCK */
+ SUNXI_FUNCTION(0x8, "i2c0"), /* SCK */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 4)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 5),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "ncsi"), /* D1 */
+ SUNXI_FUNCTION(0x3, "emac"), /* TXD1 */
+ SUNXI_FUNCTION(0x5, "pwm5"),
+ SUNXI_FUNCTION(0x6, "sdc1"), /* D3 */
+ SUNXI_FUNCTION(0x7, "i2c3"), /* SDA */
+ SUNXI_FUNCTION(0x8, "i2c0"), /* SDA */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 5)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 6),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "ncsi"), /* D2 */
+ SUNXI_FUNCTION(0x3, "emac"), /* TXCTL/TXEN */
+ SUNXI_FUNCTION(0x4, "lcd"), /* D2 */
+ SUNXI_FUNCTION(0x5, "pwm6"),
+ SUNXI_FUNCTION(0x6, "uart1"), /* TX */
+ SUNXI_FUNCTION(0x8, "i2c4"), /* SCK */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 6)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 7),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "ncsi"), /* D3 */
+ SUNXI_FUNCTION(0x3, "emac"), /* CLKIN/RXER */
+ SUNXI_FUNCTION(0x4, "lcd"), /* D15 */
+ SUNXI_FUNCTION(0x5, "pwm7"),
+ SUNXI_FUNCTION(0x6, "uart1"), /* TX */
+ SUNXI_FUNCTION(0x7, "i2s1"), /* DOUT0 */
+ SUNXI_FUNCTION(0x8, "i2c4"), /* SDA */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 7)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 8),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "ncsi"), /* D4 */
+ SUNXI_FUNCTION(0x3, "emac"), /* MDC */
+ SUNXI_FUNCTION(0x4, "lcd"), /* D18 */
+ SUNXI_FUNCTION(0x5, "pwm8"),
+ SUNXI_FUNCTION(0x6, "wiegand"), /* D0 */
+ SUNXI_FUNCTION(0x7, "i2s1"), /* DIN0 */
+ SUNXI_FUNCTION(0x8, "i2c1"), /* SCK */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 8)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 9),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "ncsi"), /* D5 */
+ SUNXI_FUNCTION(0x3, "emac"), /* MDIO */
+ SUNXI_FUNCTION(0x4, "lcd"), /* D19 */
+ SUNXI_FUNCTION(0x5, "pwm9"),
+ SUNXI_FUNCTION(0x6, "wiegand"), /* D1 */
+ SUNXI_FUNCTION(0x7, "i2s1"), /* LRCK */
+ SUNXI_FUNCTION(0x8, "i2c1"), /* SDA */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 9)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 10),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "ncsi"), /* D6 */
+ SUNXI_FUNCTION(0x3, "emac"), /* EPHY_25M */
+ SUNXI_FUNCTION(0x4, "lcd"), /* D20 */
+ SUNXI_FUNCTION(0x5, "pwm10"),
+ SUNXI_FUNCTION(0x6, "uart2"), /* RTS */
+ SUNXI_FUNCTION(0x7, "i2s1"), /* BCLK */
+ SUNXI_FUNCTION(0x8, "wiegand"), /* D0 */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 10)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 11),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "ncsi"), /* D7 */
+ SUNXI_FUNCTION(0x3, "emac"), /* RXD3 */
+ SUNXI_FUNCTION(0x4, "lcd"), /* D21 */
+ SUNXI_FUNCTION(0x5, "csi"), /* SM_VS */
+ SUNXI_FUNCTION(0x6, "uart2"), /* CTS */
+ SUNXI_FUNCTION(0x7, "i2s1"), /* MCLK */
+ SUNXI_FUNCTION(0x8, "wiegand"), /* D1 */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 11)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 12),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "ncsi"), /* D8 */
+ SUNXI_FUNCTION(0x3, "emac"), /* RXD2 */
+ SUNXI_FUNCTION(0x4, "lcd"), /* D22 */
+ SUNXI_FUNCTION(0x5, "csi"), /* MCLK0 */
+ SUNXI_FUNCTION(0x6, "uart2"), /* TX */
+ SUNXI_FUNCTION(0x7, "uart3"), /* TX */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 12)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 13),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "ncsi"), /* D9 */
+ SUNXI_FUNCTION(0x3, "emac"), /* RXCK */
+ SUNXI_FUNCTION(0x4, "lcd"), /* D23 */
+ SUNXI_FUNCTION(0x5, "csi"), /* MCLK1 */
+ SUNXI_FUNCTION(0x6, "uart2"), /* RX */
+ SUNXI_FUNCTION(0x7, "uart3"), /* RX */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 13)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 14),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "ncsi"), /* D10 */
+ SUNXI_FUNCTION(0x3, "emac"), /* TXD3 */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 14)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 15),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "ncsi"), /* D11 */
+ SUNXI_FUNCTION(0x3, "emac"), /* TXD2 */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 15)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 16),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2c0"), /* SCK */
+ SUNXI_FUNCTION(0x3, "i2c4"), /* SCK */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 16)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 17),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2c0"), /* SDA */
+ SUNXI_FUNCTION(0x3, "i2c4"), /* SDA */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 17)),
+ /* bank F */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 0),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "sdc0"), /* D1 */
+ SUNXI_FUNCTION(0x3, "jtag"), /* MS */
+ SUNXI_FUNCTION(0x4, "spi0"), /* CLK */
+ SUNXI_FUNCTION(0x5, "spi2"), /* CLK */
+ SUNXI_FUNCTION(0x6, "r_jtag"), /* MS */
+ SUNXI_FUNCTION(0x7, "cpu"), /* BIST0 */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 0)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 1),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "sdc0"), /* D0 */
+ SUNXI_FUNCTION(0x3, "jtag"), /* DI */
+ SUNXI_FUNCTION(0x4, "spi0"), /* MOSI */
+ SUNXI_FUNCTION(0x5, "spi2"), /* MOSI */
+ SUNXI_FUNCTION(0x6, "r_jtag"), /* DI */
+ SUNXI_FUNCTION(0x7, "cpu"), /* BIST1 */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 1)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 2),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "sdc0"), /* CLK */
+ SUNXI_FUNCTION(0x3, "uart0"), /* TX */
+ SUNXI_FUNCTION(0x4, "spi0"), /* MISO */
+ SUNXI_FUNCTION(0x5, "spi2"), /* MISO */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 2)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 3),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "sdc0"), /* CMD */
+ SUNXI_FUNCTION(0x3, "jtag"), /* DO */
+ SUNXI_FUNCTION(0x4, "spi0"), /* CSO */
+ SUNXI_FUNCTION(0x5, "spi2"), /* CS0 */
+ SUNXI_FUNCTION(0x6, "r_jtag"), /* DO */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 3)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 4),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "sdc0"), /* D3 */
+ SUNXI_FUNCTION(0x3, "uart0"), /* RX */
+ SUNXI_FUNCTION(0x4, "spi0"), /* CS1 */
+ SUNXI_FUNCTION(0x5, "spi2"), /* CS1 */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 4)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 5),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "sdc0"), /* D2 */
+ SUNXI_FUNCTION(0x3, "jtag"), /* CK */
+ SUNXI_FUNCTION(0x6, "r_jtag"), /* CK */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 5)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 6),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "dbg_clk"),
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 6)),
+ /* bank G */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 0),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "sdc1"), /* CLK */
+ SUNXI_FUNCTION(0x3, "lcd"), /* D0 */
+ SUNXI_FUNCTION(0x4, "uart3"), /* TX */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 0)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 1),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "sdc1"), /* CMD */
+ SUNXI_FUNCTION(0x3, "lcd"), /* D1 */
+ SUNXI_FUNCTION(0x4, "uart3"), /* RX */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 1)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 2),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "sdc1"), /* D0 */
+ SUNXI_FUNCTION(0x3, "lcd"), /* D8 */
+ SUNXI_FUNCTION(0x4, "uart3"), /* CTS */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 2)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 3),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "sdc1"), /* D1 */
+ SUNXI_FUNCTION(0x3, "lcd"), /* D9 */
+ SUNXI_FUNCTION(0x4, "uart3"), /* RTS */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 3)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 4),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "sdc1"), /* D2 */
+ SUNXI_FUNCTION(0x3, "lcd"), /* D16 */
+ SUNXI_FUNCTION(0x4, "uart1"), /* RTS */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 4)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 5),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "sdc1"), /* D3 */
+ SUNXI_FUNCTION(0x3, "lcd"), /* D17 */
+ SUNXI_FUNCTION(0x4, "uart1"), /* CTS */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 5)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 6),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2c4"), /* SCK */
+ SUNXI_FUNCTION(0x3, "clk"), /* FANOUT0 */
+ SUNXI_FUNCTION(0x4, "uart1"), /* TX */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 6)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 7),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2c4"), /* SDA */
+ SUNXI_FUNCTION(0x3, "clk"), /* FANOUT1 */
+ SUNXI_FUNCTION(0x4, "uart1"), /* RX */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 7)),
+ /* bank H */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 0),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "pwm0"),
+ SUNXI_FUNCTION(0x3, "i2s0"), /* MCLK */
+ SUNXI_FUNCTION(0x4, "spi1"), /* CLK */
+ SUNXI_FUNCTION(0x5, "uart3"), /* TX */
+ SUNXI_FUNCTION(0x6, "dmic"), /* DATA3 */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 0)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 1),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "pwm1"),
+ SUNXI_FUNCTION(0x3, "i2s0"), /* BCLK */
+ SUNXI_FUNCTION(0x4, "spi1"), /* MOSI */
+ SUNXI_FUNCTION(0x5, "uart3"), /* RX */
+ SUNXI_FUNCTION(0x6, "dmic"), /* DATA2 */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 1)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 2),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "pwm2"),
+ SUNXI_FUNCTION(0x3, "i2s0"), /* LRCK */
+ SUNXI_FUNCTION(0x4, "spi1"), /* MISO */
+ SUNXI_FUNCTION(0x5, "uart3"), /* CTS */
+ SUNXI_FUNCTION(0x6, "dmic"), /* DATA1 */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 2)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 3),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "pwm3"),
+ SUNXI_FUNCTION(0x3, "i2s0"), /* DOUT0 */
+ SUNXI_FUNCTION(0x4, "spi1"), /* CS0 */
+ SUNXI_FUNCTION(0x5, "uart3"), /* RTS */
+ SUNXI_FUNCTION(0x6, "dmic"), /* DATA0 */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 3)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 4),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "pwm4"),
+ SUNXI_FUNCTION(0x3, "i2s0"), /* DIN0 */
+ SUNXI_FUNCTION(0x4, "spi1"), /* CS1 */
+ SUNXI_FUNCTION(0x5, "clk"), /* FANOUT2 */
+ SUNXI_FUNCTION(0x6, "dmic"), /* CLK */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 4)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 5),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "pwm5"),
+ SUNXI_FUNCTION(0x3, "emac"), /* RXD1 */
+ SUNXI_FUNCTION(0x4, "i2c2"), /* SCK */
+ SUNXI_FUNCTION(0x5, "uart2"), /* TX */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 5)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 6),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "pwm6"),
+ SUNXI_FUNCTION(0x3, "emac"), /* RXD0 */
+ SUNXI_FUNCTION(0x4, "i2c2"), /* SDA */
+ SUNXI_FUNCTION(0x5, "uart2"), /* RX */
+ SUNXI_FUNCTION(0x6, "i2s1"), /* MCLK */
+ SUNXI_FUNCTION(0x7, "dmic"), /* DATA3 */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 6)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 7),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "pwm7"),
+ SUNXI_FUNCTION(0x3, "emac"), /* CRS_DV */
+ SUNXI_FUNCTION(0x4, "uart0"), /* TX */
+ SUNXI_FUNCTION(0x5, "uart2"), /* RTS */
+ SUNXI_FUNCTION(0x6, "i2s1"), /* BCLK */
+ SUNXI_FUNCTION(0x7, "dmic"), /* DATA2 */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 7)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 8),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "pwm8"),
+ SUNXI_FUNCTION(0x3, "emac"), /* RXER */
+ SUNXI_FUNCTION(0x4, "uart0"), /* RX */
+ SUNXI_FUNCTION(0x5, "uart2"), /* CTS */
+ SUNXI_FUNCTION(0x6, "i2s1"), /* LRCK */
+ SUNXI_FUNCTION(0x7, "dmic"), /* DATA1 */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 8)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 9),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "pwm9"),
+ SUNXI_FUNCTION(0x3, "emac"), /* TXD1 */
+ SUNXI_FUNCTION(0x4, "i2c3"), /* SCK */
+ SUNXI_FUNCTION(0x5, "uart0"), /* TX */
+ SUNXI_FUNCTION(0x6, "i2s1"), /* DIN0 */
+ SUNXI_FUNCTION(0x7, "dmic"), /* DATA0 */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 9)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 10),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "pwm10"),
+ SUNXI_FUNCTION(0x3, "emac"), /* TXD0 */
+ SUNXI_FUNCTION(0x4, "i2c3"), /* SDA */
+ SUNXI_FUNCTION(0x5, "uart0"), /* RX */
+ SUNXI_FUNCTION(0x6, "i2s1"), /* DOUT0 */
+ SUNXI_FUNCTION(0x7, "dmic"), /* CLK */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 10)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 11),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "jtag"), /* MS */
+ SUNXI_FUNCTION(0x3, "emac"), /* TXCK */
+ SUNXI_FUNCTION(0x4, "r_jtag"), /* MS */
+ SUNXI_FUNCTION(0x5, "i2c2"), /* SCK */
+ SUNXI_FUNCTION(0x6, "spi3"), /* CLK */
+ SUNXI_FUNCTION(0x7, "clk"), /* FANOUT0 */
+ SUNXI_FUNCTION(0x8, "pwm4"),
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 11)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 12),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "jtag"), /* CK */
+ SUNXI_FUNCTION(0x3, "emac"), /* TXEN */
+ SUNXI_FUNCTION(0x4, "r_jtag"), /* CK */
+ SUNXI_FUNCTION(0x5, "i2c2"), /* SDA */
+ SUNXI_FUNCTION(0x6, "spi3"), /* MOSI */
+ SUNXI_FUNCTION(0x7, "clk"), /* FANOUT1 */
+ SUNXI_FUNCTION(0x8, "pwm5"),
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 12)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 13),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "jtag"), /* DO */
+ SUNXI_FUNCTION(0x3, "emac"), /* MDC */
+ SUNXI_FUNCTION(0x4, "r_jtag"), /* DO */
+ SUNXI_FUNCTION(0x5, "i2c3"), /* SCK */
+ SUNXI_FUNCTION(0x6, "spi3"), /* MISO */
+ SUNXI_FUNCTION(0x7, "wiegand"), /* D0 */
+ SUNXI_FUNCTION(0x8, "pwm6"),
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 13)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 14),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "jtag"), /* DI */
+ SUNXI_FUNCTION(0x3, "emac"), /* MDIO */
+ SUNXI_FUNCTION(0x4, "r_jtag"), /* DI */
+ SUNXI_FUNCTION(0x5, "i2c3"), /* SDA */
+ SUNXI_FUNCTION(0x6, "spi3"), /* CS0 */
+ SUNXI_FUNCTION(0x7, "wiegand"), /* D1 */
+ SUNXI_FUNCTION(0x8, "pwm7"),
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 14)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 15),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "clk"), /* FANOUT2 */
+ SUNXI_FUNCTION(0x3, "ephy_25m"), /* EPHY_25M */
+ SUNXI_FUNCTION(0x6, "spi3"), /* CS1 */
+ SUNXI_FUNCTION(0x8, "pwm8"),
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 15)),
+ /* bank I */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 0),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi"), /* MCLK0 */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 7, 0)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 1),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi"), /* SM_HS */
+ SUNXI_FUNCTION(0x4, "spi2"), /* CLK */
+ SUNXI_FUNCTION(0x5, "i2c1"), /* SCK */
+ SUNXI_FUNCTION(0x6, "i2c4"), /* SCK */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 7, 1)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 2),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi"), /* SM_VS */
+ SUNXI_FUNCTION(0x3, "tcon"), /* TRIG */
+ SUNXI_FUNCTION(0x4, "spi2"), /* MOSI */
+ SUNXI_FUNCTION(0x5, "i2c1"), /* SDA */
+ SUNXI_FUNCTION(0x6, "i2c4"), /* SDA */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 7, 2)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 3),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x4, "spi2"), /* MISO */
+ SUNXI_FUNCTION(0x5, "i2c0"), /* SCA */
+ SUNXI_FUNCTION(0x6, "i2c3"), /* SCK */
+ SUNXI_FUNCTION(0x7, "clk"), /* FANOUT0 */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 7, 3)),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 4),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x4, "spi2"), /* CS0 */
+ SUNXI_FUNCTION(0x5, "i2c0"), /* SDA */
+ SUNXI_FUNCTION(0x6, "i2c3"), /* SDA */
+ SUNXI_FUNCTION(0x7, "clk"), /* FANOUT1 */
+ SUNXI_FUNCTION_IRQ_BANK(0xe, 7, 4)),
+};
+
+static const unsigned int sun8i_v853_irq_bank_map[] = { 0, 2, 3, 4, 5, 6, 7, 8 };
+
+static const struct sunxi_pinctrl_desc sun8i_v853_pinctrl_data = {
+ .pins = sun8i_v853_pins,
+ .npins = ARRAY_SIZE(sun8i_v853_pins),
+ .pin_base = 0,
+ .irq_banks = ARRAY_SIZE(sun8i_v853_irq_bank_map),
+ .irq_bank_map = sun8i_v853_irq_bank_map,
+ .io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_CTL,
+};
+
+static int sun8i_v853_pinctrl_probe(struct platform_device *pdev)
+{
+ unsigned long variant = (unsigned long)of_device_get_match_data(&pdev->dev);
+
+ return sunxi_pinctrl_init_with_variant(pdev, &sun8i_v853_pinctrl_data, variant);
+}
+
+static const struct of_device_id sun8i_v853_pinctrl_match[] = {
+ {
+ .compatible = "allwinner,sun8i-v853-pinctrl",
+ .data = (void *)PINCTRL_SUN8I_V853
+ },
+ {}
+};
+
+static struct platform_driver sun8i_v853_pinctrl_driver = {
+ .probe = sun8i_v853_pinctrl_probe,
+ .driver = {
+ .name = "sun8i-v853-pinctrl",
+ .of_match_table = sun8i_v853_pinctrl_match,
+ },
+};
+builtin_platform_driver(sun8i_v853_pinctrl_driver);
diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.h b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
index a87a2f944d60..f4b64f9156f1 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.h
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
@@ -94,6 +94,7 @@
#define PINCTRL_SUN8I_V3S BIT(10)
/* Variants below here have an updated register layout. */
#define PINCTRL_SUN20I_D1 BIT(11)
+#define PINCTRL_SUN8I_V853 BIT(12)
#define PIO_POW_MOD_SEL_REG 0x340
#define PIO_POW_MOD_CTL_REG 0x344
--
2.39.5
^ permalink raw reply related [flat|nested] 50+ messages in thread
* [PATCH 04/12] dt-bindings: clock: sunxi-ng: add compatibles for V853
2025-01-10 12:39 [PATCH 00/12] Support for Allwinner V853 SoC Andras Szemzo
` (2 preceding siblings ...)
2025-01-10 12:39 ` [PATCH 03/12] pinctrl: sunxi: add driver for Allwinner V853 Andras Szemzo
@ 2025-01-10 12:39 ` Andras Szemzo
2025-01-10 13:55 ` Krzysztof Kozlowski
2025-01-10 12:39 ` [PATCH 05/12] clk: sunxi-ng: add CCU drivers " Andras Szemzo
` (7 subsequent siblings)
11 siblings, 1 reply; 50+ messages in thread
From: Andras Szemzo @ 2025-01-10 12:39 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
Linus Walleij, Philipp Zabel, Maxime Ripard
Cc: Vinod Koul, Kishon Vijay Abraham I, Ulf Hansson, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Uwe Kleine-König,
Florian Fainelli, linux-clk, devicetree, linux-arm-kernel,
linux-sunxi, linux-kernel, linux-phy, linux-gpio, linux-pm,
linux-riscv
V853 has 2 CCUs, add compatible strings for it.
Signed-off-by: Andras Szemzo <szemzo.andras@gmail.com>
---
.../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 1690b9d99c3d..bb1fa032e789 100644
--- a/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-ccu.yaml
+++ b/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-ccu.yaml
@@ -36,6 +36,8 @@ properties:
- allwinner,sun9i-a80-ccu
- allwinner,sun20i-d1-ccu
- allwinner,sun20i-d1-r-ccu
+ - allwinner,sun8i-v853-ccu
+ - allwinner,sun8i-v853-r-ccu
- allwinner,sun50i-a64-ccu
- allwinner,sun50i-a64-r-ccu
- allwinner,sun50i-a100-ccu
--
2.39.5
^ permalink raw reply related [flat|nested] 50+ messages in thread
* [PATCH 05/12] clk: sunxi-ng: add CCU drivers for V853
2025-01-10 12:39 [PATCH 00/12] Support for Allwinner V853 SoC Andras Szemzo
` (3 preceding siblings ...)
2025-01-10 12:39 ` [PATCH 04/12] dt-bindings: clock: sunxi-ng: add compatibles for V853 Andras Szemzo
@ 2025-01-10 12:39 ` Andras Szemzo
2025-01-22 23:23 ` Jeff Johnson
2025-01-28 0:42 ` Andre Przywara
2025-01-10 12:39 ` [PATCH 06/12] dt-bindings: clk: sunxi-ng: add V853 CCU clock/reset Andras Szemzo
` (6 subsequent siblings)
11 siblings, 2 replies; 50+ messages in thread
From: Andras Szemzo @ 2025-01-10 12:39 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
Linus Walleij, Philipp Zabel, Maxime Ripard
Cc: Vinod Koul, Kishon Vijay Abraham I, Ulf Hansson, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Uwe Kleine-König,
Florian Fainelli, linux-clk, devicetree, linux-arm-kernel,
linux-sunxi, linux-kernel, linux-phy, linux-gpio, linux-pm,
linux-riscv
V853 has similar gates/resets like existing Allwinner SOCs. Add support for it's CCU and PRCM CCU.
Signed-off-by: Andras Szemzo <szemzo.andras@gmail.com>
---
drivers/clk/sunxi-ng/Kconfig | 10 +
drivers/clk/sunxi-ng/Makefile | 4 +
drivers/clk/sunxi-ng/ccu-sun8i-v853-r.c | 95 ++
drivers/clk/sunxi-ng/ccu-sun8i-v853-r.h | 15 +
drivers/clk/sunxi-ng/ccu-sun8i-v853.c | 1145 +++++++++++++++++++++++
drivers/clk/sunxi-ng/ccu-sun8i-v853.h | 14 +
6 files changed, 1283 insertions(+)
create mode 100644 drivers/clk/sunxi-ng/ccu-sun8i-v853-r.c
create mode 100644 drivers/clk/sunxi-ng/ccu-sun8i-v853-r.h
create mode 100644 drivers/clk/sunxi-ng/ccu-sun8i-v853.c
create mode 100644 drivers/clk/sunxi-ng/ccu-sun8i-v853.h
diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig
index b547198a2c65..c43002246b22 100644
--- a/drivers/clk/sunxi-ng/Kconfig
+++ b/drivers/clk/sunxi-ng/Kconfig
@@ -22,6 +22,16 @@ config SUN20I_D1_R_CCU
default y
depends on MACH_SUN8I || RISCV || COMPILE_TEST
+config SUN8I_V853_CCU
+ tristate "Support for the Allwinner V853 CCU"
+ default MACH_SUN8I
+ depends on MACH_SUN8I || COMPILE_TEST
+
+config SUN8I_V853_R_CCU
+ tristate "Support for the Allwinner V853 PRCM CCU"
+ default MACH_SUN8I
+ depends on MACH_SUN8I || COMPILE_TEST
+
config SUN50I_A64_CCU
tristate "Support for the Allwinner A64 CCU"
default y
diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
index 6b3ae2b620db..c32430d874ea 100644
--- a/drivers/clk/sunxi-ng/Makefile
+++ b/drivers/clk/sunxi-ng/Makefile
@@ -27,6 +27,8 @@ sunxi-ccu-y += ccu_mp.o
obj-$(CONFIG_SUNIV_F1C100S_CCU) += suniv-f1c100s-ccu.o
obj-$(CONFIG_SUN20I_D1_CCU) += sun20i-d1-ccu.o
obj-$(CONFIG_SUN20I_D1_R_CCU) += sun20i-d1-r-ccu.o
+obj-$(CONFIG_SUN8I_V853_CCU) += sun8i-v853-ccu.o
+obj-$(CONFIG_SUN8I_V853_R_CCU) += sun8i-v853-r-ccu.o
obj-$(CONFIG_SUN50I_A64_CCU) += sun50i-a64-ccu.o
obj-$(CONFIG_SUN50I_A100_CCU) += sun50i-a100-ccu.o
obj-$(CONFIG_SUN50I_A100_R_CCU) += sun50i-a100-r-ccu.o
@@ -50,6 +52,8 @@ obj-$(CONFIG_SUN9I_A80_CCU) += sun9i-a80-de-ccu.o
obj-$(CONFIG_SUN9I_A80_CCU) += sun9i-a80-usb-ccu.o
suniv-f1c100s-ccu-y += ccu-suniv-f1c100s.o
+sun8i-v853-ccu-y += ccu-sun8i-v853.o
+sun8i-v853-r-ccu-y += ccu-sun8i-v853-r.o
sun20i-d1-ccu-y += ccu-sun20i-d1.o
sun20i-d1-r-ccu-y += ccu-sun20i-d1-r.o
sun50i-a64-ccu-y += ccu-sun50i-a64.o
diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-v853-r.c b/drivers/clk/sunxi-ng/ccu-sun8i-v853-r.c
new file mode 100644
index 000000000000..19a8ba587793
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu-sun8i-v853-r.c
@@ -0,0 +1,95 @@
+// SPDX-License-Identifier: GPL-3.0
+/* Copyright(c) 2020 - 2023 Allwinner Technology Co.,Ltd. All rights reserved.
+ *
+ * Copyright (c) 2023 rengaomin@allwinnertech.com
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/module.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-sun8i-v853-r.h"
+
+
+static SUNXI_CCU_GATE(r_twd_clk, "r-twd", "osc24M", 0x012C, BIT(0), 0);
+static SUNXI_CCU_GATE(r_ppu_clk, "r-ppu", "osc24M", 0x01AC, BIT(0), 0);
+static SUNXI_CCU_GATE(r_rtc_clk, "r-rtc", "osc24M", 0x020C, BIT(0), 0);
+static SUNXI_CCU_GATE(r_cpucfg_clk, "r-cpucfg", "osc24M",
+ 0x022C, BIT(0), 0);
+
+static struct ccu_reset_map sun8i_v853_r_ccu_resets[] = {
+ [RST_BUS_R_PPU] = { 0x01ac, BIT(16) },
+ [RST_BUS_R_RTC] = { 0x020c, BIT(16) },
+ [RST_BUS_R_CPUCFG] = { 0x022c, BIT(16) },
+};
+
+static struct clk_hw_onecell_data sun8i_v853_r_hw_clks = {
+ .hws = {
+ [CLK_R_TWD] = &r_twd_clk.common.hw,
+ [CLK_R_PPU] = &r_ppu_clk.common.hw,
+ [CLK_R_RTC] = &r_rtc_clk.common.hw,
+ [CLK_R_CPUCFG] = &r_cpucfg_clk.common.hw,
+ },
+ .num = CLK_NUMBER,
+};
+
+static struct ccu_common *sun8i_v853_r_ccu_clks[] = {
+ &r_twd_clk.common,
+ &r_ppu_clk.common,
+ &r_rtc_clk.common,
+ &r_cpucfg_clk.common,
+};
+
+
+static const struct sunxi_ccu_desc sun8i_v853_r_ccu_desc = {
+ .ccu_clks = sun8i_v853_r_ccu_clks,
+ .num_ccu_clks = ARRAY_SIZE(sun8i_v853_r_ccu_clks),
+
+ .hw_clks = &sun8i_v853_r_hw_clks,
+
+ .resets = sun8i_v853_r_ccu_resets,
+ .num_resets = ARRAY_SIZE(sun8i_v853_r_ccu_resets),
+};
+
+static int sun8i_v853_r_ccu_probe(struct platform_device *pdev)
+{
+ void __iomem *reg;
+
+ reg = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(reg))
+ return PTR_ERR(reg);
+
+ return devm_sunxi_ccu_probe(&pdev->dev, reg, &sun8i_v853_r_ccu_desc);
+}
+
+static const struct of_device_id sun8i_v853_r_ccu_ids[] = {
+ { .compatible = "allwinner,sun8i-v853-r-ccu" },
+ { }
+};
+
+static struct platform_driver sun8i_v853_r_ccu_driver = {
+ .probe = sun8i_v853_r_ccu_probe,
+ .driver = {
+ .name = "sun8i-v853-r-ccu",
+ .suppress_bind_attrs = true,
+ .of_match_table = sun8i_v853_r_ccu_ids,
+ },
+};
+module_platform_driver(sun8i_v853_r_ccu_driver);
+
+MODULE_IMPORT_NS("SUNXI_CCU");
+MODULE_LICENSE("GPL");
diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-v853-r.h b/drivers/clk/sunxi-ng/ccu-sun8i-v853-r.h
new file mode 100644
index 000000000000..156ca15e8208
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu-sun8i-v853-r.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2020 - 2023 Allwinner Technology Co.,Ltd. All rights reserved.
+ *
+ * Copyright (c) 2023 rengaomin@allwinnertech.com
+ */
+
+#ifndef _CCU_SUN8I_V853_R_H
+#define _CCU_SUN8I_V853_R_H
+
+#include <dt-bindings/clock/sun8i-v853-r-ccu.h>
+#include <dt-bindings/reset/sun8i-v853-r-ccu.h>
+
+#define CLK_NUMBER CLK_R_MAX_NO
+
+#endif
diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-v853.c b/drivers/clk/sunxi-ng/ccu-sun8i-v853.c
new file mode 100644
index 000000000000..a1947357a08e
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu-sun8i-v853.c
@@ -0,0 +1,1145 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2024 Andras Szemzo <szemzo.andras@gmail.com>
+ *
+ * Based on ccu-sun20i-d1.c, which is:
+ * Copyright (C) 2021 Samuel Holland. All rights reserved.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include "../clk.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-sun8i-v853.h"
+
+static const struct clk_parent_data osc24M[] = {
+ { .fw_name = "hosc" }
+};
+
+/*
+ * For the CPU PLL, the output divider is described as "only for testing"
+ * in the user manual. So it's not modelled and forced to 0.
+ */
+#define SUN8I_V853_PLL_CPU_REG 0x000
+
+static struct ccu_mult pll_cpu_clk = {
+ .enable = BIT(27) | BIT(30) | BIT(31),
+ .lock = BIT(28),
+ .mult = _SUNXI_CCU_MULT_MIN(8, 8, 12),
+ .common = {
+ .reg = 0x000,
+ .hw.init = CLK_HW_INIT_PARENTS_DATA("pll-cpu", osc24M,
+ &ccu_mult_ops,
+ CLK_SET_RATE_UNGATE),
+ },
+};
+
+/* Some PLLs are input * N / div1 / P. Model them as NKMP with no K */
+#define SUN8I_V853_PLL_DDR_REG 0x010
+static struct ccu_nkmp pll_ddr_clk = {
+ .enable = BIT(27) | BIT(30) | 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_PARENTS_DATA("pll-ddr", osc24M,
+ &ccu_nkmp_ops,
+ CLK_SET_RATE_UNGATE),
+ },
+};
+
+#define SUN8I_V853_PLL_PERIPH_REG 0x020
+static struct ccu_nm pll_periph_4x_clk = {
+ .enable = BIT(27) | BIT(30) | BIT(31),
+ .lock = BIT(28),
+ .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
+ .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
+ .common = {
+ .reg = 0x020,
+ .hw.init = CLK_HW_INIT_PARENTS_DATA("pll-periph-4x", osc24M,
+ &ccu_nm_ops,
+ CLK_SET_RATE_UNGATE),
+ },
+};
+
+static SUNXI_CCU_M(pll_periph_2x_clk, "pll-periph-2x", "pll-periph-4x",
+ 0x020, 16, 3, 0);
+
+static SUNXI_CCU_M(pll_periph_800M_clk, "pll-periph-800M", "pll-periph-4x",
+ 0x020, 20, 3, 0);
+
+static SUNXI_CCU_M(pll_periph_480M_clk, "pll-periph-480M", "pll-periph-4x",
+ 0x020, 2, 3, 0);
+
+static CLK_FIXED_FACTOR_HW(pll_periph_600M_clk, "pll-periph-600M",
+ &pll_periph_2x_clk.common.hw, 2, 1, 0);
+
+static CLK_FIXED_FACTOR_HW(pll_periph_400M_clk, "pll-periph-400M",
+ &pll_periph_2x_clk.common.hw, 3, 1, 0);
+
+static CLK_FIXED_FACTOR_HW(pll_periph_300M_clk, "pll-periph-300M",
+ &pll_periph_600M_clk.hw, 2, 1, 0);
+
+static CLK_FIXED_FACTOR_HW(pll_periph_200M_clk, "pll-periph-200M",
+ &pll_periph_400M_clk.hw, 2, 1, 0);
+
+static CLK_FIXED_FACTOR_HW(pll_periph_160M_clk, "pll-periph-160M",
+ &pll_periph_480M_clk.common.hw, 3, 1, 0);
+
+static CLK_FIXED_FACTOR_HW(pll_periph_150M_clk, "pll-periph-150M",
+ &pll_periph_300M_clk.hw, 2, 1, 0);
+
+
+/*
+ * For Video PLLs, the output divider is described as "only for testing"
+ * in the user manual. So it's not modelled and forced to 0.
+ */
+#define SUN8I_V853_PLL_VIDEO_REG 0x040
+static struct ccu_nm pll_video_4x_clk = {
+ .enable = BIT(27) | BIT(30) | BIT(31),
+ .lock = BIT(28),
+ .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
+ .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
+ .common = {
+ .reg = 0x040,
+ .hw.init = CLK_HW_INIT_PARENTS_DATA("pll-video-4x", osc24M,
+ &ccu_nm_ops,
+ CLK_SET_RATE_UNGATE),
+ },
+};
+
+static const struct clk_hw *pll_video_4x_hws[] = {
+ &pll_video_4x_clk.common.hw
+};
+static CLK_FIXED_FACTOR_HWS(pll_video_2x_clk, "pll-video-2x",
+ pll_video_4x_hws, 2, 1, CLK_SET_RATE_PARENT);
+static CLK_FIXED_FACTOR_HWS(pll_video_1x_clk, "pll-video-1x",
+ pll_video_4x_hws, 4, 1, CLK_SET_RATE_PARENT);
+
+
+/*
+ * For CSI PLLs, the output divider is described as "only for testing"
+ * in the user manual. So it's not modelled and forced to 0.
+ */
+#define SUN8I_V853_PLL_CSI_REG 0x048
+static struct ccu_nm pll_csi_4x_clk = {
+ .enable = BIT(27) | BIT(30) | BIT(31),
+ .lock = BIT(28),
+ .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
+ .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
+ .common = {
+ .reg = 0x048,
+ .hw.init = CLK_HW_INIT_PARENTS_DATA("pll-csi-4x", osc24M,
+ &ccu_nm_ops,
+ CLK_SET_RATE_UNGATE),
+ },
+};
+
+static CLK_FIXED_FACTOR_HW(pll_csi_clk, "pll-csi",
+ &pll_csi_4x_clk.common.hw, 4, 1, CLK_SET_RATE_PARENT);
+
+
+#define SUN8I_V853_PLL_AUDIO_REG 0x78
+static struct ccu_sdm_setting pll_audio_div5_sdm_table[] = {
+ { .rate = 196608000, .pattern = 0xc001eb85, .m = 5, .n = 40 }, /* 24.576 */
+ { .rate = 67737600, .pattern = 0xc001288d, .m = 8, .n = 22 }, /* 22.5792 */
+};
+
+static struct ccu_nm pll_audio_div5_clk = {
+ .enable = BIT(27) | BIT(30) | BIT(31),
+ .lock = BIT(28),
+ .n = _SUNXI_CCU_MULT(8, 8),
+ .m = _SUNXI_CCU_DIV(20, 3),
+ .sdm = _SUNXI_CCU_SDM(pll_audio_div5_sdm_table,
+ BIT(24), 0x0178, BIT(31)),
+ .common = {
+ .reg = 0x0078,
+ .features = CCU_FEATURE_SIGMA_DELTA_MOD,
+ .hw.init = CLK_HW_INIT_PARENTS_DATA("pll-audio-div5", osc24M,
+ &ccu_nm_ops,
+ CLK_SET_RATE_UNGATE),
+ },
+};
+static SUNXI_CCU_M(pll_audio_1x_clk, "pll-audio-1x", "pll-audio-div5",
+ 0xe00, 0, 5, CLK_SET_RATE_PARENT);
+
+/* pll-audio-div2 and pll-aduio-4x not used, because audio-1x can cover 22.5792M and 24.576M */
+static SUNXI_CCU_M(pll_audio_div2_clk, "pll-audio-div2", "pll-audio",
+ 0x078, 16, 3, 0);
+static SUNXI_CCU_M(pll_audio_4x_clk, "pll-audio-4x", "pll-audio-div2",
+ 0xe00, 5, 5, 0);
+
+/*
+ * For the NPU PLL, the output divider is described as "only for testing"
+ * in the user manual. So it's not modelled and forced to 0.
+ */
+#define SUN8I_V853_PLL_NPU_REG 0x080
+static struct ccu_nm pll_npu_4x_clk = {
+ .enable = BIT(27) | BIT(30) | BIT(31),
+ .lock = BIT(28),
+ .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
+ .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
+ .common = {
+ .reg = 0x080,
+ .hw.init = CLK_HW_INIT_PARENTS_DATA("pll-npu-4x", osc24M,
+ &ccu_nm_ops,
+ CLK_SET_RATE_UNGATE),
+ },
+};
+
+/*
+ * The CPU gate is not modelled - it is in a separate register (0x504)
+ * and has a special key field. The clock does not need to be ungated anyway.
+ */
+static const struct clk_parent_data cpu_parents[] = {
+ { .fw_name = "hosc" },
+ { .fw_name = "losc" },
+ { .fw_name = "iosc" },
+ { .hw = &pll_cpu_clk.common.hw },
+ { .hw = &pll_periph_600M_clk.hw },
+ { .hw = &pll_periph_800M_clk.common.hw },
+};
+
+static SUNXI_CCU_MUX_DATA(cpu_clk, "cpu", cpu_parents,
+ 0x500, 24, 3, CLK_SET_RATE_PARENT | CLK_IS_CRITICAL);
+
+static SUNXI_CCU_M(cpu_axi_clk, "cpu-axi", "cpu",
+ 0x500, 0, 2, 0);
+static SUNXI_CCU_M(cpu_apb_clk, "cpu-apb", "cpu",
+ 0x500, 8, 2, 0);
+
+static const struct clk_parent_data ahb_parents[] = {
+ { .fw_name = "hosc" },
+ { .fw_name = "losc" },
+ { .fw_name = "iosc" },
+ { .hw = &pll_periph_600M_clk.hw },
+};
+static SUNXI_CCU_MP_DATA_WITH_MUX(ahb_clk, "ahb", ahb_parents, 0x510,
+ 0, 5, /* M */
+ 8, 2, /* P */
+ 24, 2, /* mux */
+ 0);
+
+static SUNXI_CCU_MP_DATA_WITH_MUX(apb0_clk, "apb0", ahb_parents, 0x520,
+ 0, 5, /* M */
+ 8, 2, /* P */
+ 24, 2, /* mux */
+ 0);
+
+static SUNXI_CCU_MP_DATA_WITH_MUX(apb1_clk, "apb1", ahb_parents, 0x524,
+ 0, 5, /* M */
+ 8, 2, /* P */
+ 24, 2, /* mux */
+ 0);
+
+static const struct clk_hw *ahb_hws[] = { &ahb_clk.common.hw };
+static const struct clk_hw *apb0_hws[] = { &apb0_clk.common.hw };
+static const struct clk_hw *apb1_hws[] = { &apb1_clk.common.hw };
+
+
+
+static const struct clk_hw *de_g2d_parents[] = {
+ &pll_periph_300M_clk.hw,
+ &pll_video_1x_clk.hw,
+};
+static SUNXI_CCU_M_HW_WITH_MUX_GATE(de_clk, "de", de_g2d_parents, 0x600,
+ 0, 5, /* M */
+ 24, 1, /* mux */
+ BIT(31), /* gate */
+ CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_GATE_HWS(bus_de_clk, "bus-de", ahb_hws,
+ 0x60c, BIT(0), 0);
+
+static SUNXI_CCU_M_HW_WITH_MUX_GATE(g2d_clk, "g2d", de_g2d_parents, 0x630,
+ 0, 5, /* M */
+ 24, 1, /* mux */
+ BIT(31), /* gate */
+ CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_GATE_HWS(bus_g2d_clk, "bus-g2d", ahb_hws,
+ 0x63c, BIT(0), 0);
+
+
+static const struct clk_parent_data ce_parents[] = {
+ { .fw_name = "hosc" },
+ { .hw = &pll_periph_400M_clk.hw, },
+ { .hw = &pll_periph_300M_clk.hw, }
+};
+static SUNXI_CCU_M_DATA_WITH_MUX_GATE(ce_clk, "ce", ce_parents, 0x680,
+ 0, 4, /* M */
+ 24, 3, /* mux */
+ BIT(31), /* gate */
+ CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_GATE_HWS(bus_ce_clk, "bus-ce", ahb_hws,
+ 0x68c, BIT(0) | BIT(1), 0);
+
+static const struct clk_hw *ve_parents[] = {
+ &pll_periph_300M_clk.hw,
+ &pll_periph_400M_clk.hw,
+ &pll_periph_480M_clk.common.hw,
+ &pll_npu_4x_clk.common.hw,
+ &pll_video_4x_clk.common.hw,
+ &pll_csi_4x_clk.common.hw,
+};
+static SUNXI_CCU_M_HW_WITH_MUX_GATE(ve_clk, "ve", ve_parents, 0x690,
+ 0, 5, /* M */
+ 24, 3, /* mux */
+ BIT(31), /* gate */
+ CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_GATE_HWS(bus_ve_clk, "bus-ve", ahb_hws,
+ 0x69c, BIT(0), 0);
+
+
+static const struct clk_hw *npu_parents[] = {
+ &pll_periph_480M_clk.common.hw,
+ &pll_periph_600M_clk.hw,
+ &pll_periph_800M_clk.common.hw,
+ &pll_npu_4x_clk.common.hw,
+};
+static SUNXI_CCU_M_HW_WITH_MUX_GATE(npu_clk, "npu", npu_parents, 0x6e0,
+ 0, 5, /* M */
+ 24, 3, /* mux */
+ BIT(31), /* gate */
+ 0);
+
+static SUNXI_CCU_GATE_HWS(bus_npu_clk, "bus-npu", ahb_hws,
+ 0x6ec, BIT(0), 0);
+
+static SUNXI_CCU_GATE_HWS(bus_dma_clk, "bus-dma", ahb_hws,
+ 0x70c, BIT(0), 0);
+
+static SUNXI_CCU_GATE_HWS(bus_msgbox0_clk, "bus-msgbox0", ahb_hws,
+ 0x71c, BIT(0), 0);
+static SUNXI_CCU_GATE_HWS(bus_msgbox1_clk, "bus-msgbox1", ahb_hws,
+ 0x71c, BIT(1), 0);
+
+static SUNXI_CCU_GATE_HWS(bus_spinlock_clk, "bus-spinlock", ahb_hws,
+ 0x72c, BIT(0), 0);
+
+static SUNXI_CCU_GATE_HWS(bus_hstimer_clk, "bus-hstimer", ahb_hws,
+ 0x73c, BIT(0), 0);
+
+static SUNXI_CCU_GATE_DATA(avs_clk, "avs", osc24M,
+ 0x740, BIT(31), 0);
+
+static SUNXI_CCU_GATE_HWS(bus_dbg_clk, "bus-dbg", ahb_hws,
+ 0x78c, BIT(0), 0);
+
+static SUNXI_CCU_GATE_HWS(bus_pwm_clk, "bus-pwm", apb0_hws,
+ 0x7ac, BIT(0), 0);
+
+static SUNXI_CCU_GATE_HWS(bus_iommu_clk, "bus-iommu", ahb_hws,
+ 0x7bc, BIT(0), 0);
+
+static const struct clk_hw *dram_parents[] = {
+ &pll_ddr_clk.common.hw,
+ &pll_periph_2x_clk.common.hw,
+ &pll_periph_800M_clk.common.hw,
+};
+static SUNXI_CCU_MP_HW_WITH_MUX_GATE(dram_clk, "dram", dram_parents, 0x800,
+ 0, 5, /* M */
+ 8, 2, /* P */
+ 24, 3, /* mux */
+ BIT(31), CLK_IS_CRITICAL);
+
+static CLK_FIXED_FACTOR_HW(mbus_clk, "mbus",
+ &dram_clk.common.hw, 4, 1, 0);
+
+static const struct clk_hw *mbus_hws[] = { &mbus_clk.hw };
+
+static SUNXI_CCU_GATE_HWS(mbus_dma_clk, "mbus-dma", mbus_hws,
+ 0x804, BIT(0), 0);
+static SUNXI_CCU_GATE_HWS(mbus_ve_clk, "mbus-ve", mbus_hws,
+ 0x804, BIT(1), 0);
+static SUNXI_CCU_GATE_HWS(mbus_ce_clk, "mbus-ce", mbus_hws,
+ 0x804, BIT(2), 0);
+static SUNXI_CCU_GATE_HWS(mbus_csi_clk, "mbus-csi", mbus_hws,
+ 0x804, BIT(8), 0);
+static SUNXI_CCU_GATE_HWS(mbus_isp_clk, "mbus-isp", mbus_hws,
+ 0x804, BIT(9), 0);
+static SUNXI_CCU_GATE_HWS(mbus_g2d_clk, "mbus-g2d", mbus_hws,
+ 0x804, BIT(10), 0);
+
+static SUNXI_CCU_GATE_HWS(bus_dram_clk, "bus-dram", ahb_hws,
+ 0x80c, BIT(0), CLK_IS_CRITICAL);
+
+
+static const struct clk_parent_data mmc0_mmc1_parents[] = {
+ { .fw_name = "hosc" },
+ { .hw = &pll_periph_400M_clk.hw, },
+ { .hw = &pll_periph_300M_clk.hw, },
+};
+static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(mmc0_clk, "mmc0", mmc0_mmc1_parents, 0x830,
+ 0, 4, /* M */
+ 8, 2, /* P */
+ 24, 3, /* mux */
+ BIT(31), /* gate */
+ 0);
+
+static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(mmc1_clk, "mmc1", mmc0_mmc1_parents, 0x834,
+ 0, 4, /* M */
+ 8, 2, /* P */
+ 24, 3, /* mux */
+ BIT(31), /* gate */
+ 0);
+
+static const struct clk_parent_data mmc2_parents[] = {
+ { .fw_name = "hosc" },
+ { .hw = &pll_periph_600M_clk.hw, },
+ { .hw = &pll_periph_400M_clk.hw, },
+};
+static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(mmc2_clk, "mmc2", mmc2_parents, 0x838,
+ 0, 4, /* M */
+ 8, 2, /* P */
+ 24, 3, /* mux */
+ BIT(31), /* gate */
+ 0);
+
+static SUNXI_CCU_GATE_HWS(bus_mmc0_clk, "bus-mmc0", ahb_hws,
+ 0x84c, BIT(0), 0);
+static SUNXI_CCU_GATE_HWS(bus_mmc1_clk, "bus-mmc1", ahb_hws,
+ 0x84c, BIT(1), 0);
+static SUNXI_CCU_GATE_HWS(bus_mmc2_clk, "bus-mmc2", ahb_hws,
+ 0x84c, BIT(2), 0);
+
+static SUNXI_CCU_GATE_HWS(bus_uart0_clk, "bus-uart0", apb1_hws,
+ 0x90c, BIT(0), 0);
+static SUNXI_CCU_GATE_HWS(bus_uart1_clk, "bus-uart1", apb1_hws,
+ 0x90c, BIT(1), 0);
+static SUNXI_CCU_GATE_HWS(bus_uart2_clk, "bus-uart2", apb1_hws,
+ 0x90c, BIT(2), 0);
+static SUNXI_CCU_GATE_HWS(bus_uart3_clk, "bus-uart3", apb1_hws,
+ 0x90c, BIT(3), 0);
+
+static SUNXI_CCU_GATE_HWS(bus_i2c0_clk, "bus-i2c0", apb1_hws,
+ 0x91c, BIT(0), 0);
+static SUNXI_CCU_GATE_HWS(bus_i2c1_clk, "bus-i2c1", apb1_hws,
+ 0x91c, BIT(1), 0);
+static SUNXI_CCU_GATE_HWS(bus_i2c2_clk, "bus-i2c2", apb1_hws,
+ 0x91c, BIT(2), 0);
+static SUNXI_CCU_GATE_HWS(bus_i2c3_clk, "bus-i2c3", apb1_hws,
+ 0x91c, BIT(3), 0);
+static SUNXI_CCU_GATE_HWS(bus_i2c4_clk, "bus-i2c4", apb1_hws,
+ 0x91c, BIT(4), 0);
+
+static const struct clk_parent_data spi_parents[] = {
+ { .fw_name = "hosc" },
+ { .hw = &pll_periph_300M_clk.hw, },
+ { .hw = &pll_periph_200M_clk.hw, },
+};
+
+static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(spi0_clk, "spi0", spi_parents, 0x940,
+ 0, 4, /* M */
+ 8, 2, /* P */
+ 24, 3, /* mux */
+ BIT(31), /* gate */
+ 0);
+
+static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(spi1_clk, "spi1", spi_parents, 0x944,
+ 0, 4, /* M */
+ 8, 2, /* P */
+ 24, 3, /* mux */
+ BIT(31), /* gate */
+ 0);
+
+static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(spi2_clk, "spi2", spi_parents, 0x948,
+ 0, 4, /* M */
+ 8, 2, /* P */
+ 24, 3, /* mux */
+ BIT(31), /* gate */
+ 0);
+
+static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(spi3_clk, "spi3", spi_parents, 0x94c,
+ 0, 4, /* M */
+ 8, 2, /* P */
+ 24, 3, /* mux */
+ BIT(31), /* gate */
+ 0);
+
+static SUNXI_CCU_GATE_HWS(bus_spi0_clk, "bus-spi0", ahb_hws,
+ 0x96c, BIT(0), 0);
+static SUNXI_CCU_GATE_HWS(bus_spi1_clk, "bus-spi1", ahb_hws,
+ 0x96c, BIT(1), 0);
+static SUNXI_CCU_GATE_HWS(bus_spi2_clk, "bus-spi2", ahb_hws,
+ 0x96c, BIT(2), 0);
+static SUNXI_CCU_GATE_HWS(bus_spi3_clk, "bus-spi3", ahb_hws,
+ 0x96c, BIT(3), 0);
+
+
+static const struct clk_parent_data spif_parents[] = {
+ { .fw_name = "hosc" },
+ { .hw = &pll_periph_400M_clk.hw, },
+ { .hw = &pll_periph_300M_clk.hw, },
+};
+
+static SUNXI_CCU_M_DATA_WITH_MUX_GATE(spif_clk, "spif", spif_parents, 0x0950,
+ 0, 4, /* M */
+ 24, 3, /* mux */
+ BIT(31), /* gate */
+ CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_GATE_HWS(bus_spif_clk, "bus-spif", ahb_hws,
+ 0x096c, BIT(4), 0);
+
+
+static const struct clk_hw *pll_periph_150M_hws[] = { &pll_periph_150M_clk.hw };
+static SUNXI_CCU_GATE_HWS_WITH_PREDIV(emac_25M_clk, "emac-25M", pll_periph_150M_hws,
+ 0x970, BIT(31) | BIT(30), 6, 0);
+
+static SUNXI_CCU_GATE_HWS(bus_emac_clk, "bus-emac", ahb_hws,
+ 0x97c, BIT(0), 0);
+
+static SUNXI_CCU_GATE_HWS(bus_gpadc_clk, "bus-gpadc", apb0_hws,
+ 0x9ec, BIT(0), 0);
+
+static SUNXI_CCU_GATE_HWS(bus_ths_clk, "bus-ths", ahb_hws,
+ 0x9fc, BIT(0), 0);
+
+
+static const struct clk_hw *audio_parents[] = {
+ &pll_audio_1x_clk.common.hw,
+ &pll_audio_4x_clk.common.hw,
+};
+
+static SUNXI_CCU_M_HW_WITH_MUX_GATE(i2s0_clk, "i2s0", audio_parents, 0xa10,
+ 0, 4, /* M */
+ 24, 1, /* mux */
+ BIT(31), /* gate */
+ CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_M_HW_WITH_MUX_GATE(i2s1_clk, "i2s1", audio_parents, 0xa14,
+ 0, 4, /* M */
+ 24, 1, /* mux */
+ BIT(31), /* gate */
+ CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_GATE_HWS(bus_i2s1_clk, "bus-i2s1", ahb_hws,
+ 0xa20, BIT(1), 0);
+
+static SUNXI_CCU_GATE_HWS(bus_i2s0_clk, "bus-i2s0", ahb_hws,
+ 0xa20, BIT(0), 0);
+
+static SUNXI_CCU_M_HW_WITH_MUX_GATE(dmic_clk, "dmic", audio_parents, 0xa40,
+ 0, 4, /* M */
+ 24, 1, /* mux */
+ BIT(31), /* gate */
+ CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_GATE_HWS(bus_dmic_clk, "bus-dmic", ahb_hws,
+ 0xa4c, BIT(0), 0);
+
+static SUNXI_CCU_M_HW_WITH_MUX_GATE(audio_codec_dac_clk, "audio-codec-dac", audio_parents, 0xa50,
+ 0, 4, /* M */
+ 24, 1, /* mux */
+ BIT(31), /* gate */
+ CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_M_HW_WITH_MUX_GATE(audio_codec_adc_clk, "audio-codec-adc", audio_parents, 0xa54,
+ 0, 4, /* M */
+ 24, 1, /* mux */
+ BIT(31), /* gate */
+ CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_GATE_HWS(bus_audio_codec_clk, "bus-audio-codec", apb0_hws,
+ 0xa5c, BIT(0), 0);
+
+/*
+ * There are OHCI 12M clock source selection bits for the USB 2.0 port.
+ * We will force them to 0 (12M divided from 48M).
+ */
+static CLK_FIXED_FACTOR_FW_NAME(osc12M_clk, "osc12M", "hosc", 2, 1, 0);
+
+#define SUN8I_V853_USB_CLK_REG 0xa70
+
+static SUNXI_CCU_GATE(usb_ohci_clk, "usb", "osc12M", 0x0a70, BIT(31), 0);
+
+static SUNXI_CCU_GATE_HWS(bus_ohci_clk, "bus-ohci", ahb_hws, 0xa8c, BIT(0), 0);
+static SUNXI_CCU_GATE_HWS(bus_ehci_clk, "bus-ehci", ahb_hws, 0xa8c, BIT(4), 0);
+static SUNXI_CCU_GATE_HWS(bus_otg_clk, "bus-otg", ahb_hws, 0xa8c, BIT(8), 0);
+
+static SUNXI_CCU_GATE_HWS(bus_dpss_top_clk, "bus-dpss-top", ahb_hws,
+ 0xabc, BIT(0), 0);
+
+
+static const struct clk_parent_data mipi_dsi_parents[] = {
+ { .fw_name = "hosc" },
+ { .hw = &pll_periph_200M_clk.hw },
+ { .hw = &pll_periph_150M_clk.hw },
+};
+static SUNXI_CCU_M_DATA_WITH_MUX_GATE(mipi_dsi_clk, "mipi-dsi", mipi_dsi_parents, 0xb24,
+ 0, 4, /* M */
+ 24, 3, /* mux */
+ BIT(31), /* gate */
+ CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_GATE_HWS(bus_mipi_dsi_clk, "bus-mipi-dsi", ahb_hws,
+ 0xb4c, BIT(0), 0);
+
+
+static const struct clk_hw *tcon_lcd_parents[] = {
+ &pll_video_4x_clk.common.hw,
+ &pll_periph_2x_clk.common.hw,
+ &pll_csi_4x_clk.common.hw,
+};
+static SUNXI_CCU_MP_HW_WITH_MUX_GATE(tcon_lcd_clk, "tcon-lcd", tcon_lcd_parents, 0xb60,
+ 0, 4, /* M */
+ 8, 2, /* P */
+ 24, 3, /* mux */
+ BIT(31), /* gate */
+ CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_GATE_HWS(bus_tcon_lcd_clk, "bus-tcon-lcd", ahb_hws,
+ 0xb7c, BIT(0), 0);
+
+
+static const struct clk_hw *csi_top_parents[] = {
+ &pll_periph_300M_clk.hw,
+ &pll_periph_400M_clk.hw,
+ &pll_video_4x_clk.common.hw,
+ &pll_csi_4x_clk.common.hw,
+};
+static SUNXI_CCU_M_HW_WITH_MUX_GATE(csi_top_clk, "csi-top", csi_top_parents, 0xc04,
+ 0, 5, /* M */
+ 24, 3, /* mux */
+ BIT(31), /* gate */
+ 0);
+
+
+static const struct clk_parent_data csi_mclk_parents[] = {
+ { .fw_name = "hosc" },
+ { .hw = &pll_csi_4x_clk.common.hw },
+ { .hw = &pll_video_4x_clk.common.hw },
+ { .hw = &pll_periph_2x_clk.common.hw },
+};
+static SUNXI_CCU_M_DATA_WITH_MUX_GATE(csi_mclk0_clk, "csi-mclk0", csi_mclk_parents, 0xc08,
+ 0, 5, /* M */
+ 24, 3, /* mux */
+ BIT(31), /* gate */
+ 0);
+
+static SUNXI_CCU_M_DATA_WITH_MUX_GATE(csi_mclk1_clk, "csi-mclk1", csi_mclk_parents, 0xc0c,
+ 0, 5, /* M */
+ 24, 3, /* mux */
+ BIT(31), /* gate */
+ 0);
+
+static SUNXI_CCU_M_DATA_WITH_MUX_GATE(csi_mclk2_clk, "csi-mclk2", csi_mclk_parents, 0xc10,
+ 0, 5, /* M */
+ 24, 3, /* mux */
+ BIT(31), /* gate */
+ 0);
+
+static SUNXI_CCU_GATE_HWS(bus_csi_clk, "bus-csi", ahb_hws,
+ 0xc2c, BIT(0), 0);
+
+
+static SUNXI_CCU_GATE_HWS(bus_wiegand_clk, "bus-wiegand", ahb_hws,
+ 0xc7c, BIT(0), 0);
+
+
+static const struct clk_parent_data riscv_parents[] = {
+ { .fw_name = "hosc" },
+ { .fw_name = "losc" },
+ { .fw_name = "iosc" },
+ { .hw = &pll_periph_600M_clk.hw },
+ { .hw = &pll_periph_480M_clk.common.hw },
+ { .hw = &pll_cpu_clk.common.hw },
+};
+static SUNXI_CCU_M_DATA_WITH_MUX(riscv_clk, "riscv-cpu", riscv_parents, 0xd00,
+ 0, 5, /* M */
+ 24, 3, /* mux */
+ CLK_SET_RATE_PARENT);
+
+/* The riscv-axi clk must be divided by at least 2. */
+static struct clk_div_table riscv_axi_table[] = {
+ { .val = 1, .div = 2 },
+ { .val = 2, .div = 3 },
+ { .val = 3, .div = 4 },
+ { /* Sentinel */ }
+};
+static SUNXI_CCU_DIV_TABLE_HW(riscv_axi_clk, "riscv-axi", &riscv_clk.common.hw,
+ 0xd00, 8, 2, riscv_axi_table, 0);
+
+
+static SUNXI_CCU_GATE_HWS(riscv_cfg, "riscv-cfg", ahb_hws,
+ 0xd0c, BIT(0), 0);
+
+static const struct clk_hw *pll_periph_160M_hws[] = {
+ &pll_periph_160M_clk.hw,
+};
+
+static SUNXI_CCU_GATE_DATA(fanout_24M_clk, "fanout-24M", osc24M,
+ 0xf30, BIT(0), 0);
+static SUNXI_CCU_GATE_DATA_WITH_PREDIV(fanout_12M_clk, "fanout-12M", osc24M,
+ 0xf30, BIT(1), 2, 0);
+static SUNXI_CCU_GATE_HWS_WITH_PREDIV(fanout_16M_clk, "fanout-16M", pll_periph_160M_hws,
+ 0xf30, BIT(2), 10, 0);
+static SUNXI_CCU_GATE_HWS_WITH_PREDIV(fanout_25M_clk, "fanout-25M", pll_periph_150M_hws,
+ 0xf30, BIT(3), 6, 0);
+
+
+
+/* This clock has a second divider that is not modelled and forced to 0. */
+#define SUN8I_V853_FANOUT_27M_REG 0xf34
+static const struct clk_hw *fanout_27M_parents[] = {
+ &pll_video_1x_clk.hw,
+ &pll_csi_clk.hw,
+ &pll_periph_300M_clk.hw,
+};
+static SUNXI_CCU_M_HW_WITH_MUX_GATE(fanout_27M_clk, "fanout-27M", fanout_27M_parents, 0xf34,
+ 0, 5, /* M */
+ 24, 2, /* mux */
+ BIT(31), /* gate */
+ 0);
+static SUNXI_CCU_M_HWS_WITH_GATE(fanout_pclk_clk, "fanout-pclk", apb0_hws, 0xf38,
+ 0, 5, /* M */
+ BIT(31), /* gate */
+ 0);
+
+static const struct clk_parent_data fanout_parents[] = {
+ { .fw_name = "losc" },
+ { .hw = &fanout_12M_clk.common.hw },
+ { .hw = &fanout_16M_clk.common.hw },
+ { .hw = &fanout_24M_clk.common.hw },
+ { .hw = &fanout_25M_clk.common.hw },
+ { .hw = &fanout_27M_clk.common.hw },
+ { .hw = &fanout_pclk_clk.common.hw },
+};
+
+static SUNXI_CCU_MUX_DATA_WITH_GATE(fanout0_clk, "fanout0", fanout_parents, 0xf3c,
+ 0, 3, /* mux */
+ BIT(21), /* gate */
+ 0);
+static SUNXI_CCU_MUX_DATA_WITH_GATE(fanout1_clk, "fanout1", fanout_parents, 0xf3c,
+ 3, 3, /* mux */
+ BIT(22), /* gate */
+ 0);
+static SUNXI_CCU_MUX_DATA_WITH_GATE(fanout2_clk, "fanout2", fanout_parents, 0xf3c,
+ 6, 3, /* mux */
+ BIT(23), /* gate */
+ 0);
+
+
+static struct ccu_common *sun8i_v853_ccu_clks[] = {
+ &pll_cpu_clk.common,
+ &pll_ddr_clk.common,
+ &pll_periph_4x_clk.common,
+ &pll_periph_2x_clk.common,
+ &pll_periph_800M_clk.common,
+ &pll_periph_480M_clk.common,
+ &pll_video_4x_clk.common,
+ &pll_csi_4x_clk.common,
+ &pll_audio_div2_clk.common,
+ &pll_audio_div5_clk.common,
+ &pll_audio_4x_clk.common,
+ &pll_audio_1x_clk.common,
+ &pll_npu_4x_clk.common,
+ &cpu_clk.common,
+ &cpu_axi_clk.common,
+ &cpu_apb_clk.common,
+ &ahb_clk.common,
+ &apb0_clk.common,
+ &apb1_clk.common,
+ &de_clk.common,
+ &bus_de_clk.common,
+ &g2d_clk.common,
+ &bus_g2d_clk.common,
+ &ce_clk.common,
+ &bus_ce_clk.common,
+ &ve_clk.common,
+ &bus_ve_clk.common,
+ &npu_clk.common,
+ &bus_npu_clk.common,
+ &bus_dma_clk.common,
+ &bus_msgbox0_clk.common,
+ &bus_msgbox1_clk.common,
+ &bus_spinlock_clk.common,
+ &bus_hstimer_clk.common,
+ &avs_clk.common,
+ &bus_dbg_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_csi_clk.common,
+ &mbus_isp_clk.common,
+ &mbus_g2d_clk.common,
+ &bus_dram_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_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,
+ &spi2_clk.common,
+ &spi3_clk.common,
+ &bus_spi0_clk.common,
+ &bus_spi1_clk.common,
+ &bus_spi2_clk.common,
+ &bus_spi3_clk.common,
+ &spif_clk.common,
+ &bus_spif_clk.common,
+ &emac_25M_clk.common,
+ &bus_emac_clk.common,
+ &bus_gpadc_clk.common,
+ &bus_ths_clk.common,
+ &usb_ohci_clk.common,
+ &bus_ohci_clk.common,
+ &bus_ehci_clk.common,
+ &bus_otg_clk.common,
+ &i2s0_clk.common,
+ &i2s1_clk.common,
+ &bus_i2s0_clk.common,
+ &bus_i2s1_clk.common,
+ &dmic_clk.common,
+ &bus_dmic_clk.common,
+ &audio_codec_dac_clk.common,
+ &audio_codec_adc_clk.common,
+ &bus_audio_codec_clk.common,
+ &bus_dpss_top_clk.common,
+ &mipi_dsi_clk.common,
+ &bus_mipi_dsi_clk.common,
+ &tcon_lcd_clk.common,
+ &bus_tcon_lcd_clk.common,
+ &csi_top_clk.common,
+ &csi_mclk0_clk.common,
+ &csi_mclk1_clk.common,
+ &csi_mclk2_clk.common,
+ &bus_csi_clk.common,
+ &bus_wiegand_clk.common,
+ &riscv_clk.common,
+ &riscv_axi_clk.common,
+ &riscv_cfg.common,
+ &fanout_24M_clk.common,
+ &fanout_12M_clk.common,
+ &fanout_16M_clk.common,
+ &fanout_25M_clk.common,
+ &fanout_27M_clk.common,
+ &fanout_pclk_clk.common,
+ &fanout0_clk.common,
+ &fanout1_clk.common,
+ &fanout2_clk.common,
+};
+
+static struct clk_hw_onecell_data sun8i_v853_hw_clks = {
+ .num = CLK_NUMBER,
+ .hws = {
+ [CLK_OSC12M] = &osc12M_clk.hw,
+ [CLK_PLL_CPU] = &pll_cpu_clk.common.hw,
+ [CLK_PLL_DDR] = &pll_ddr_clk.common.hw,
+ [CLK_PLL_PERIPH_4X] = &pll_periph_4x_clk.common.hw,
+ [CLK_PLL_PERIPH_2X] = &pll_periph_2x_clk.common.hw,
+ [CLK_PLL_PERIPH_800M] = &pll_periph_800M_clk.common.hw,
+ [CLK_PLL_PERIPH_480M] = &pll_periph_480M_clk.common.hw,
+ [CLK_PLL_PERIPH_600M] = &pll_periph_600M_clk.hw,
+ [CLK_PLL_PERIPH_400M] = &pll_periph_400M_clk.hw,
+ [CLK_PLL_PERIPH_300M] = &pll_periph_300M_clk.hw,
+ [CLK_PLL_PERIPH_200M] = &pll_periph_200M_clk.hw,
+ [CLK_PLL_PERIPH_160M] = &pll_periph_160M_clk.hw,
+ [CLK_PLL_PERIPH_150M] = &pll_periph_150M_clk.hw,
+ [CLK_PLL_VIDEO_4X] = &pll_video_4x_clk.common.hw,
+ [CLK_PLL_VIDEO_2X] = &pll_video_2x_clk.hw,
+ [CLK_PLL_VIDEO_1X] = &pll_video_1x_clk.hw,
+ [CLK_PLL_CSI_4X] = &pll_csi_4x_clk.common.hw,
+ [CLK_PLL_AUDIO_DIV2] = &pll_audio_div2_clk.common.hw,
+ [CLK_PLL_AUDIO_DIV5] = &pll_audio_div5_clk.common.hw,
+ [CLK_PLL_AUDIO_4X] = &pll_audio_4x_clk.common.hw,
+ [CLK_PLL_AUDIO_1X] = &pll_audio_1x_clk.common.hw,
+ [CLK_PLL_NPU_4X] = &pll_npu_4x_clk.common.hw,
+ [CLK_CPU] = &cpu_clk.common.hw,
+ [CLK_CPU_AXI] = &cpu_axi_clk.common.hw,
+ [CLK_CPU_APB] = &cpu_apb_clk.common.hw,
+ [CLK_AHB] = &ahb_clk.common.hw,
+ [CLK_APB0] = &apb0_clk.common.hw,
+ [CLK_APB1] = &apb1_clk.common.hw,
+ [CLK_MBUS] = &mbus_clk.hw,
+ [CLK_DE] = &de_clk.common.hw,
+ [CLK_BUS_DE] = &bus_de_clk.common.hw,
+ [CLK_G2D] = &g2d_clk.common.hw,
+ [CLK_BUS_G2D] = &bus_g2d_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_NPU] = &npu_clk.common.hw,
+ [CLK_BUS_NPU] = &bus_npu_clk.common.hw,
+ [CLK_BUS_DMA] = &bus_dma_clk.common.hw,
+ [CLK_BUS_MSGBOX0] = &bus_msgbox0_clk.common.hw,
+ [CLK_BUS_MSGBOX1] = &bus_msgbox1_clk.common.hw,
+ [CLK_BUS_SPINLOCK] = &bus_spinlock_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_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_CSI] = &mbus_csi_clk.common.hw,
+ [CLK_MBUS_ISP] = &mbus_isp_clk.common.hw,
+ [CLK_MBUS_G2D] = &mbus_g2d_clk.common.hw,
+ [CLK_BUS_DRAM] = &bus_dram_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_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_SPI2] = &spi2_clk.common.hw,
+ [CLK_SPI3] = &spi3_clk.common.hw,
+ [CLK_BUS_SPI0] = &bus_spi0_clk.common.hw,
+ [CLK_BUS_SPI1] = &bus_spi1_clk.common.hw,
+ [CLK_BUS_SPI2] = &bus_spi2_clk.common.hw,
+ [CLK_BUS_SPI3] = &bus_spi3_clk.common.hw,
+ [CLK_SPIF] = &spif_clk.common.hw,
+ [CLK_BUS_SPIF] = &bus_spif_clk.common.hw,
+ [CLK_EMAC_25M] = &emac_25M_clk.common.hw,
+ [CLK_BUS_EMAC] = &bus_emac_clk.common.hw,
+ [CLK_BUS_GPADC] = &bus_gpadc_clk.common.hw,
+ [CLK_BUS_THS] = &bus_ths_clk.common.hw,
+ [CLK_I2S0] = &i2s0_clk.common.hw,
+ [CLK_I2S1] = &i2s1_clk.common.hw,
+ [CLK_BUS_I2S0] = &bus_i2s0_clk.common.hw,
+ [CLK_BUS_I2S1] = &bus_i2s1_clk.common.hw,
+ [CLK_DMIC] = &dmic_clk.common.hw,
+ [CLK_BUS_DMIC] = &bus_dmic_clk.common.hw,
+ [CLK_AUDIO_CODEC_DAC] = &audio_codec_dac_clk.common.hw,
+ [CLK_AUDIO_CODEC_ADC] = &audio_codec_adc_clk.common.hw,
+ [CLK_BUS_AUDIO_CODEC] = &bus_audio_codec_clk.common.hw,
+ [CLK_USB_OHCI] = &usb_ohci_clk.common.hw,
+ [CLK_BUS_OHCI] = &bus_ohci_clk.common.hw,
+ [CLK_BUS_EHCI] = &bus_ehci_clk.common.hw,
+ [CLK_BUS_OTG] = &bus_otg_clk.common.hw,
+ [CLK_BUS_DPSS_TOP] = &bus_dpss_top_clk.common.hw,
+ [CLK_MIPI_DSI] = &mipi_dsi_clk.common.hw,
+ [CLK_BUS_MIPI_DSI] = &bus_mipi_dsi_clk.common.hw,
+ [CLK_TCON_LCD] = &tcon_lcd_clk.common.hw,
+ [CLK_BUS_TCON_LCD] = &bus_tcon_lcd_clk.common.hw,
+ [CLK_CSI_TOP] = &csi_top_clk.common.hw,
+ [CLK_CSI_MCLK0] = &csi_mclk0_clk.common.hw,
+ [CLK_CSI_MCLK1] = &csi_mclk1_clk.common.hw,
+ [CLK_CSI_MCLK2] = &csi_mclk2_clk.common.hw,
+ [CLK_BUS_CSI] = &bus_csi_clk.common.hw,
+ [CLK_BUS_WIEGAND] = &bus_wiegand_clk.common.hw,
+ [CLK_RISCV] = &riscv_clk.common.hw,
+ [CLK_RISCV_AXI] = &riscv_axi_clk.common.hw,
+ [CLK_RISCV_CFG] = &riscv_cfg.common.hw,
+ [CLK_FANOUT_24M] = &fanout_24M_clk.common.hw,
+ [CLK_FANOUT_16M] = &fanout_16M_clk.common.hw,
+ [CLK_FANOUT_12M] = &fanout_12M_clk.common.hw,
+ [CLK_FANOUT_25M] = &fanout_25M_clk.common.hw,
+ [CLK_FANOUT_27M] = &fanout_27M_clk.common.hw,
+ [CLK_FANOUT_PCLK] = &fanout_pclk_clk.common.hw,
+ [CLK_FANOUT0] = &fanout0_clk.common.hw,
+ [CLK_FANOUT1] = &fanout1_clk.common.hw,
+ [CLK_FANOUT2] = &fanout2_clk.common.hw,
+ },
+};
+
+static struct ccu_reset_map sun8i_v853_ccu_resets[] = {
+ [RST_MBUS] = { 0x540, BIT(30) },
+ [RST_BUS_DE] = { 0x60c, BIT(16) },
+ [RST_BUS_G2D] = { 0x63c, BIT(16) },
+ [RST_BUS_CE] = { 0x68c, BIT(16) | BIT(17)},
+ [RST_BUS_VE] = { 0x69c, BIT(16) },
+ [RST_BUS_NPU] = { 0x6ec, BIT(16) },
+ [RST_BUS_DMA] = { 0x70c, BIT(16) },
+ [RST_BUS_MSGBOX0] = { 0x71c, BIT(16) },
+ [RST_BUS_MSGBOX1] = { 0x71c, BIT(17) },
+ [RST_BUS_SPINLOCK] = { 0x72c, BIT(16) },
+ [RST_BUS_HSTIMER] = { 0x73c, BIT(16) },
+ [RST_BUS_DBG] = { 0x78c, BIT(16) },
+ [RST_BUS_PWM] = { 0x7ac, BIT(16) },
+ [RST_BUS_DRAM] = { 0x80c, 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_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_SPIF] = { 0x96c, BIT(20) },
+ [RST_BUS_SPI0] = { 0x96c, BIT(16) },
+ [RST_BUS_SPI1] = { 0x96c, BIT(17) },
+ [RST_BUS_SPI2] = { 0x96c, BIT(18) },
+ [RST_BUS_SPI3] = { 0x96c, BIT(19) },
+ [RST_BUS_EMAC] = { 0x97c, BIT(16) },
+ [RST_BUS_GPADC] = { 0x9ec, BIT(16) },
+ [RST_BUS_THS] = { 0x9fc, BIT(16) },
+ [RST_BUS_I2S0] = { 0xa20, BIT(16) },
+ [RST_BUS_I2S1] = { 0xa20, BIT(17) },
+ [RST_BUS_DMIC] = { 0xa4c, BIT(16) },
+ [RST_BUS_AUDIO_CODEC] = { 0xa5c, BIT(16) },
+ [RST_USB_PHY] = { 0xa70, BIT(30) },
+ [RST_BUS_OHCI] = { 0xa8c, BIT(16) },
+ [RST_BUS_EHCI] = { 0xa8c, BIT(20) },
+ [RST_BUS_OTG] = { 0xa8c, BIT(24) },
+ [RST_BUS_DPSS_TOP] = { 0xabc, BIT(16) },
+ [RST_BUS_MIPI_DSI] = { 0xb4c, BIT(16) },
+ [RST_BUS_TCON_LCD] = { 0xb7c, BIT(16) },
+ [RST_BUS_CSI] = { 0xc2c, BIT(16) },
+ [RST_BUS_WIEGAND] = { 0xc7c, BIT(16) },
+ [RST_RISCV_SYS_APB] = { 0xd04, BIT(2), CCU_FEATURE_KEY_FIELD },
+ [RST_RISCV_SOFT] = { 0xd04, BIT(1), CCU_FEATURE_KEY_FIELD },
+ [RST_RISCV_CLK_GATING] = { 0xd04, BIT(0), CCU_FEATURE_KEY_FIELD },
+ [RST_RISCV_CFG] = { 0xd0c, BIT(16) }
+};
+
+static const struct sunxi_ccu_desc sun8i_v853_ccu_desc = {
+ .ccu_clks = sun8i_v853_ccu_clks,
+ .num_ccu_clks = ARRAY_SIZE(sun8i_v853_ccu_clks),
+
+ .hw_clks = &sun8i_v853_hw_clks,
+
+ .resets = sun8i_v853_ccu_resets,
+ .num_resets = ARRAY_SIZE(sun8i_v853_ccu_resets),
+};
+
+static const u32 pll_regs[] = {
+ SUN8I_V853_PLL_CPU_REG,
+ SUN8I_V853_PLL_DDR_REG,
+ SUN8I_V853_PLL_PERIPH_REG,
+ SUN8I_V853_PLL_VIDEO_REG,
+ SUN8I_V853_PLL_CSI_REG,
+ SUN8I_V853_PLL_AUDIO_REG,
+ SUN8I_V853_PLL_NPU_REG,
+};
+
+static int sun8i_v853_ccu_probe(struct platform_device *pdev)
+{
+ void __iomem *reg;
+ u32 val;
+ int i, ret;
+
+ reg = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(reg))
+ return PTR_ERR(reg);
+
+ /* Enable the enable, LDO, and lock bits on all PLLs. */
+ for (i = 0; i < ARRAY_SIZE(pll_regs); i++) {
+ val = readl(reg + pll_regs[i]);
+ val |= BIT(31) | BIT(30) | BIT(29);
+ writel(val, reg + pll_regs[i]);
+ }
+
+ /* Force PLL_CPU factor M to 0. */
+ val = readl(reg + SUN8I_V853_PLL_CPU_REG);
+ val &= ~GENMASK(1, 0);
+ writel(val, reg + SUN8I_V853_PLL_CPU_REG);
+
+ /*
+ * Force the output divider of video PLL to 0.
+ *
+ * See the comment before pll-video0 definition for the reason.
+ */
+ val = readl(reg + SUN8I_V853_PLL_VIDEO_REG);
+ val &= ~BIT(0);
+ writel(val, reg + SUN8I_V853_PLL_VIDEO_REG);
+
+ /*
+ * Force the output divider of CSI PLL to 0.
+ *
+ * See the comment before pll-csi definition for the reason.
+ */
+ val = readl(reg + SUN8I_V853_PLL_CSI_REG);
+ val &= ~BIT(0);
+ writel(val, reg + SUN8I_V853_PLL_CSI_REG);
+
+ /*
+ * Force the output divider of NPU PLL to 0.
+ *
+ * See the comment before pll-npu definition for the reason.
+ */
+ val = readl(reg + SUN8I_V853_PLL_NPU_REG);
+ val &= ~BIT(0);
+ writel(val, reg + SUN8I_V853_PLL_NPU_REG);
+
+ /*
+ * Force OHCI 12M clock source to 00 (12MHz divided from 48MHz)
+ *
+ * This clock mux is still mysterious, and the code just enforces
+ * it to have a valid clock parent.
+ */
+ val = readl(reg + SUN8I_V853_USB_CLK_REG);
+ val &= ~GENMASK(25, 24);
+ writel(val, reg + SUN8I_V853_USB_CLK_REG);
+
+ /* Force fanout-27M factor N to 0. */
+ val = readl(reg + SUN8I_V853_FANOUT_27M_REG);
+ val &= ~GENMASK(9, 8);
+ writel(val, reg + SUN8I_V853_FANOUT_27M_REG);
+
+ ret = devm_sunxi_ccu_probe(&pdev->dev, reg, &sun8i_v853_ccu_desc);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static const struct of_device_id sun8i_v853_ccu_ids[] = {
+ { .compatible = "allwinner,sun8i-v853-ccu" },
+ { }
+};
+
+static struct platform_driver sun8i_v853_ccu_driver = {
+ .probe = sun8i_v853_ccu_probe,
+ .driver = {
+ .name = "sun8i-v853-ccu",
+ .suppress_bind_attrs = true,
+ .of_match_table = sun8i_v853_ccu_ids,
+ },
+};
+module_platform_driver(sun8i_v853_ccu_driver);
+
+MODULE_IMPORT_NS("SUNXI_CCU");
+MODULE_LICENSE("GPL");
diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-v853.h b/drivers/clk/sunxi-ng/ccu-sun8i-v853.h
new file mode 100644
index 000000000000..b6ee1764fe5e
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu-sun8i-v853.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2024 Andras Szemzo <szemzo.andras@gmail.com>
+ */
+
+#ifndef _CCU_SUN8I_V853_H_
+#define _CCU_SUN8I_V853_H_
+
+#include <dt-bindings/clock/sun8i-v853-ccu.h>
+#include <dt-bindings/reset/sun8i-v853-ccu.h>
+
+#define CLK_NUMBER (CLK_FANOUT2 + 1)
+
+#endif /* _CCU_SUN8I_V853_H_ */
--
2.39.5
^ permalink raw reply related [flat|nested] 50+ messages in thread
* [PATCH 06/12] dt-bindings: clk: sunxi-ng: add V853 CCU clock/reset
2025-01-10 12:39 [PATCH 00/12] Support for Allwinner V853 SoC Andras Szemzo
` (4 preceding siblings ...)
2025-01-10 12:39 ` [PATCH 05/12] clk: sunxi-ng: add CCU drivers " Andras Szemzo
@ 2025-01-10 12:39 ` Andras Szemzo
2025-01-10 13:56 ` Krzysztof Kozlowski
2025-01-11 10:34 ` Krzysztof Kozlowski
2025-01-10 12:39 ` [PATCH 07/12] devicetree: bindings: power: add v853 ppu Andras Szemzo
` (5 subsequent siblings)
11 siblings, 2 replies; 50+ messages in thread
From: Andras Szemzo @ 2025-01-10 12:39 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
Linus Walleij, Philipp Zabel, Maxime Ripard
Cc: Vinod Koul, Kishon Vijay Abraham I, Ulf Hansson, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Uwe Kleine-König,
Florian Fainelli, linux-clk, devicetree, linux-arm-kernel,
linux-sunxi, linux-kernel, linux-phy, linux-gpio, linux-pm,
linux-riscv
As the device tree needs the clock/reset indices, add them to DT binding
headers.
Signed-off-by: Andras Szemzo <szemzo.andras@gmail.com>
---
include/dt-bindings/clock/sun8i-v853-ccu.h | 132 +++++++++++++++++++
include/dt-bindings/clock/sun8i-v853-r-ccu.h | 16 +++
include/dt-bindings/reset/sun8i-v853-ccu.h | 62 +++++++++
include/dt-bindings/reset/sun8i-v853-r-ccu.h | 14 ++
4 files changed, 224 insertions(+)
create mode 100644 include/dt-bindings/clock/sun8i-v853-ccu.h
create mode 100644 include/dt-bindings/clock/sun8i-v853-r-ccu.h
create mode 100644 include/dt-bindings/reset/sun8i-v853-ccu.h
create mode 100644 include/dt-bindings/reset/sun8i-v853-r-ccu.h
diff --git a/include/dt-bindings/clock/sun8i-v853-ccu.h b/include/dt-bindings/clock/sun8i-v853-ccu.h
new file mode 100644
index 000000000000..a405b982f914
--- /dev/null
+++ b/include/dt-bindings/clock/sun8i-v853-ccu.h
@@ -0,0 +1,132 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
+/*
+ * Copyright (C) 2020 huangzhenwei@allwinnertech.com
+ * Copyright (C) 2023 Andras Szemzo <szemzo.andras@gmail.com.com>
+ */
+
+#ifndef _DT_BINDINGS_CLK_SUN8I_V85X_CCU_H_
+#define _DT_BINDINGS_CLK_SUN8I_V85X_CCU_H_
+
+#define CLK_OSC12M 0
+#define CLK_PLL_CPU 1
+#define CLK_PLL_DDR 2
+#define CLK_PLL_PERIPH_4X 3
+#define CLK_PLL_PERIPH_2X 4
+#define CLK_PLL_PERIPH_800M 5
+#define CLK_PLL_PERIPH_480M 6
+#define CLK_PLL_PERIPH_600M 7
+#define CLK_PLL_PERIPH_400M 8
+#define CLK_PLL_PERIPH_300M 9
+#define CLK_PLL_PERIPH_200M 10
+#define CLK_PLL_PERIPH_160M 11
+#define CLK_PLL_PERIPH_150M 12
+#define CLK_PLL_VIDEO_4X 13
+#define CLK_PLL_VIDEO_2X 14
+#define CLK_PLL_VIDEO_1X 15
+#define CLK_PLL_CSI_4X 16
+#define CLK_PLL_AUDIO_DIV2 17
+#define CLK_PLL_AUDIO_DIV5 18
+#define CLK_PLL_AUDIO_4X 19
+#define CLK_PLL_AUDIO_1X 20
+#define CLK_PLL_NPU_4X 21
+#define CLK_CPU 22
+#define CLK_CPU_AXI 23
+#define CLK_CPU_APB 24
+#define CLK_AHB 25
+#define CLK_APB0 26
+#define CLK_APB1 27
+#define CLK_MBUS 28
+#define CLK_DE 29
+#define CLK_BUS_DE 30
+#define CLK_G2D 31
+#define CLK_BUS_G2D 32
+#define CLK_CE 33
+#define CLK_BUS_CE 34
+#define CLK_VE 35
+#define CLK_BUS_VE 36
+#define CLK_NPU 37
+#define CLK_BUS_NPU 38
+#define CLK_BUS_DMA 39
+#define CLK_BUS_MSGBOX0 40
+#define CLK_BUS_MSGBOX1 41
+#define CLK_BUS_SPINLOCK 42
+#define CLK_BUS_HSTIMER 43
+#define CLK_AVS 44
+#define CLK_BUS_DBG 45
+#define CLK_BUS_PWM 46
+#define CLK_BUS_IOMMU 47
+#define CLK_DRAM 48
+#define CLK_MBUS_DMA 49
+#define CLK_MBUS_VE 50
+#define CLK_MBUS_CE 51
+#define CLK_MBUS_CSI 52
+#define CLK_MBUS_ISP 53
+#define CLK_MBUS_G2D 54
+#define CLK_BUS_DRAM 55
+#define CLK_MMC0 56
+#define CLK_MMC1 57
+#define CLK_MMC2 58
+#define CLK_BUS_MMC0 59
+#define CLK_BUS_MMC1 60
+#define CLK_BUS_MMC2 61
+#define CLK_BUS_UART0 62
+#define CLK_BUS_UART1 63
+#define CLK_BUS_UART2 64
+#define CLK_BUS_UART3 65
+#define CLK_BUS_I2C0 66
+#define CLK_BUS_I2C1 67
+#define CLK_BUS_I2C2 68
+#define CLK_BUS_I2C3 69
+#define CLK_BUS_I2C4 70
+#define CLK_SPI0 71
+#define CLK_SPI1 72
+#define CLK_SPI2 73
+#define CLK_SPI3 74
+#define CLK_BUS_SPI0 75
+#define CLK_BUS_SPI1 76
+#define CLK_BUS_SPI2 77
+#define CLK_BUS_SPI3 78
+#define CLK_SPIF 79
+#define CLK_BUS_SPIF 80
+#define CLK_EMAC_25M 81
+#define CLK_BUS_EMAC 82
+#define CLK_BUS_GPADC 83
+#define CLK_BUS_THS 84
+#define CLK_I2S0 85
+#define CLK_I2S1 86
+#define CLK_BUS_I2S0 87
+#define CLK_BUS_I2S1 88
+#define CLK_DMIC 89
+#define CLK_BUS_DMIC 90
+#define CLK_AUDIO_CODEC_DAC 91
+#define CLK_AUDIO_CODEC_ADC 92
+#define CLK_BUS_AUDIO_CODEC 93
+#define CLK_USB_OHCI 94
+#define CLK_BUS_OHCI 95
+#define CLK_BUS_EHCI 96
+#define CLK_BUS_OTG 97
+#define CLK_BUS_DPSS_TOP 98
+#define CLK_MIPI_DSI 99
+#define CLK_BUS_MIPI_DSI 100
+#define CLK_TCON_LCD 101
+#define CLK_BUS_TCON_LCD 102
+#define CLK_CSI_TOP 103
+#define CLK_CSI_MCLK0 104
+#define CLK_CSI_MCLK1 105
+#define CLK_CSI_MCLK2 106
+#define CLK_BUS_CSI 107
+#define CLK_BUS_WIEGAND 108
+#define CLK_RISCV 109
+#define CLK_RISCV_AXI 110
+#define CLK_RISCV_CFG 111
+#define CLK_FANOUT_24M 112
+#define CLK_FANOUT_12M 113
+#define CLK_FANOUT_16M 114
+#define CLK_FANOUT_25M 115
+#define CLK_FANOUT_27M 116
+#define CLK_FANOUT_PCLK 117
+#define CLK_FANOUT0 118
+#define CLK_FANOUT1 119
+#define CLK_FANOUT2 120
+
+#endif /* _DT_BINDINGS_CLK_SUN8I_V85X_CCU_H_ */
diff --git a/include/dt-bindings/clock/sun8i-v853-r-ccu.h b/include/dt-bindings/clock/sun8i-v853-r-ccu.h
new file mode 100644
index 000000000000..0c10295c6d9c
--- /dev/null
+++ b/include/dt-bindings/clock/sun8i-v853-r-ccu.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
+/* Copyright(c) 2020 - 2023 Allwinner Technology Co.,Ltd. All rights reserved.
+ *
+ * Copyright (C) 2023 rengaomin@allwinnertech.com
+ */
+#ifndef _DT_BINDINGS_CLK_SUN8I_V85X_R_CCU_H_
+#define _DT_BINDINGS_CLK_SUN8I_V85X_R_CCU_H_
+
+#define CLK_R_TWD 0
+#define CLK_R_PPU 1
+#define CLK_R_RTC 2
+#define CLK_R_CPUCFG 3
+
+#define CLK_R_MAX_NO (CLK_R_CPUCFG + 1)
+
+#endif
diff --git a/include/dt-bindings/reset/sun8i-v853-ccu.h b/include/dt-bindings/reset/sun8i-v853-ccu.h
new file mode 100644
index 000000000000..89d94fcbdb55
--- /dev/null
+++ b/include/dt-bindings/reset/sun8i-v853-ccu.h
@@ -0,0 +1,62 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
+/*
+ * Copyright (c) 2020 huangzhenwei@allwinnertech.com
+ * Copyright (C) 2023 Andras Szemzo <szemzo.andras@gmail.com>
+ */
+
+#ifndef _DT_BINDINGS_RST_SUN8I_V85X_CCU_H_
+#define _DT_BINDINGS_RST_SUN8I_V85X_CCU_H_
+
+#define RST_MBUS 0
+#define RST_BUS_DE 1
+#define RST_BUS_G2D 2
+#define RST_BUS_CE 3
+#define RST_BUS_VE 4
+#define RST_BUS_NPU 5
+#define RST_BUS_DMA 6
+#define RST_BUS_MSGBOX0 7
+#define RST_BUS_MSGBOX1 8
+#define RST_BUS_SPINLOCK 9
+#define RST_BUS_HSTIMER 10
+#define RST_BUS_DBG 11
+#define RST_BUS_PWM 12
+#define RST_BUS_DRAM 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_I2C0 21
+#define RST_BUS_I2C1 22
+#define RST_BUS_I2C2 23
+#define RST_BUS_I2C3 24
+#define RST_BUS_I2C4 25
+#define RST_BUS_SPIF 26
+#define RST_BUS_SPI0 27
+#define RST_BUS_SPI1 28
+#define RST_BUS_SPI2 29
+#define RST_BUS_SPI3 30
+#define RST_BUS_EMAC 31
+#define RST_BUS_GPADC 32
+#define RST_BUS_THS 33
+#define RST_BUS_I2S0 34
+#define RST_BUS_I2S1 35
+#define RST_BUS_DMIC 36
+#define RST_BUS_AUDIO_CODEC 37
+#define RST_USB_PHY 38
+#define RST_BUS_OHCI 39
+#define RST_BUS_EHCI 40
+#define RST_BUS_OTG 41
+#define RST_BUS_DPSS_TOP 42
+#define RST_BUS_MIPI_DSI 43
+#define RST_BUS_TCON_LCD 44
+#define RST_BUS_CSI 45
+#define RST_BUS_WIEGAND 46
+#define RST_RISCV_SYS_APB 47
+#define RST_RISCV_SOFT 48
+#define RST_RISCV_CLK_GATING 49
+#define RST_RISCV_CFG 50
+
+#endif /* _DT_BINDINGS_RST_SUN8I_V85X_CCU_H_ */
diff --git a/include/dt-bindings/reset/sun8i-v853-r-ccu.h b/include/dt-bindings/reset/sun8i-v853-r-ccu.h
new file mode 100644
index 000000000000..4420f7dbbcdc
--- /dev/null
+++ b/include/dt-bindings/reset/sun8i-v853-r-ccu.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
+/* Copyright(c) 2020 - 2023 Allwinner Technology Co.,Ltd. All rights reserved.
+ *
+ * Copyright (c) 2023 rengaomin@allwinnertech.com
+ */
+
+#ifndef _DT_BINDINGS_RESET_SUN8IW21_R_CCU_H_
+#define _DT_BINDINGS_RESET_SUN8IW21_R_CCU_H_
+
+#define RST_BUS_R_PPU 0
+#define RST_BUS_R_RTC 1
+#define RST_BUS_R_CPUCFG 2
+
+#endif /* _DT_BINDINGS_RESET_SUN8IW21_R_CCU_H_ */
--
2.39.5
^ permalink raw reply related [flat|nested] 50+ messages in thread
* [PATCH 07/12] devicetree: bindings: power: add v853 ppu
2025-01-10 12:39 [PATCH 00/12] Support for Allwinner V853 SoC Andras Szemzo
` (5 preceding siblings ...)
2025-01-10 12:39 ` [PATCH 06/12] dt-bindings: clk: sunxi-ng: add V853 CCU clock/reset Andras Szemzo
@ 2025-01-10 12:39 ` Andras Szemzo
2025-01-10 13:54 ` Krzysztof Kozlowski
2025-01-10 12:39 ` [PATCH 08/12] pmdomain: sunxi: add V853 ppu support Andras Szemzo
` (4 subsequent siblings)
11 siblings, 1 reply; 50+ messages in thread
From: Andras Szemzo @ 2025-01-10 12:39 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
Linus Walleij, Philipp Zabel, Maxime Ripard
Cc: Vinod Koul, Kishon Vijay Abraham I, Ulf Hansson, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Uwe Kleine-König,
Florian Fainelli, linux-clk, devicetree, linux-arm-kernel,
linux-sunxi, linux-kernel, linux-phy, linux-gpio, linux-pm,
linux-riscv
Document V853 PPU compatible.
Signed-off-by: Andras Szemzo <szemzo.andras@gmail.com>
---
.../devicetree/bindings/power/allwinner,sun20i-d1-ppu.yaml | 1 +
1 file changed, 1 insertion(+)
diff --git a/Documentation/devicetree/bindings/power/allwinner,sun20i-d1-ppu.yaml b/Documentation/devicetree/bindings/power/allwinner,sun20i-d1-ppu.yaml
index 46e2647a5d72..f578be6a3bc8 100644
--- a/Documentation/devicetree/bindings/power/allwinner,sun20i-d1-ppu.yaml
+++ b/Documentation/devicetree/bindings/power/allwinner,sun20i-d1-ppu.yaml
@@ -17,6 +17,7 @@ properties:
compatible:
enum:
- allwinner,sun20i-d1-ppu
+ - allwinner,sun8i-v853-ppu
reg:
maxItems: 1
--
2.39.5
^ permalink raw reply related [flat|nested] 50+ messages in thread
* [PATCH 08/12] pmdomain: sunxi: add V853 ppu support
2025-01-10 12:39 [PATCH 00/12] Support for Allwinner V853 SoC Andras Szemzo
` (6 preceding siblings ...)
2025-01-10 12:39 ` [PATCH 07/12] devicetree: bindings: power: add v853 ppu Andras Szemzo
@ 2025-01-10 12:39 ` Andras Szemzo
2025-01-10 12:39 ` [PATCH 09/12] dt-bindings: power: add V853 ppu bindings Andras Szemzo
` (3 subsequent siblings)
11 siblings, 0 replies; 50+ messages in thread
From: Andras Szemzo @ 2025-01-10 12:39 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
Linus Walleij, Philipp Zabel, Maxime Ripard
Cc: Vinod Koul, Kishon Vijay Abraham I, Ulf Hansson, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Uwe Kleine-König,
Florian Fainelli, linux-clk, devicetree, linux-arm-kernel,
linux-sunxi, linux-kernel, linux-phy, linux-gpio, linux-pm,
linux-riscv
V853 has a similar ppu like Allwinner D1, add compatible and the available pd names.
Signed-off-by: Andras Szemzo <szemzo.andras@gmail.com>
---
drivers/pmdomain/sunxi/sun20i-ppu.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/drivers/pmdomain/sunxi/sun20i-ppu.c b/drivers/pmdomain/sunxi/sun20i-ppu.c
index 8700f9dd5f75..9f002748d224 100644
--- a/drivers/pmdomain/sunxi/sun20i-ppu.c
+++ b/drivers/pmdomain/sunxi/sun20i-ppu.c
@@ -182,11 +182,26 @@ static const struct sun20i_ppu_desc sun20i_d1_ppu_desc = {
.num_domains = ARRAY_SIZE(sun20i_d1_ppu_pd_names),
};
+static const char *const sun8i_v853_ppu_pd_names[] = {
+ "RISCV",
+ "NPU",
+ "VE",
+};
+
+static const struct sun20i_ppu_desc sun8i_v853_ppu_desc = {
+ .names = sun8i_v853_ppu_pd_names,
+ .num_domains = ARRAY_SIZE(sun8i_v853_ppu_pd_names),
+};
+
static const struct of_device_id sun20i_ppu_of_match[] = {
{
.compatible = "allwinner,sun20i-d1-ppu",
.data = &sun20i_d1_ppu_desc,
},
+ {
+ .compatible = "allwinner,sun8i-v853-ppu",
+ .data = &sun8i_v853_ppu_desc,
+ },
{ }
};
MODULE_DEVICE_TABLE(of, sun20i_ppu_of_match);
--
2.39.5
^ permalink raw reply related [flat|nested] 50+ messages in thread
* [PATCH 09/12] dt-bindings: power: add V853 ppu bindings
2025-01-10 12:39 [PATCH 00/12] Support for Allwinner V853 SoC Andras Szemzo
` (7 preceding siblings ...)
2025-01-10 12:39 ` [PATCH 08/12] pmdomain: sunxi: add V853 ppu support Andras Szemzo
@ 2025-01-10 12:39 ` Andras Szemzo
2025-01-10 13:53 ` Krzysztof Kozlowski
2025-01-10 12:39 ` [PATCH 10/12] dt-bindings: phy: allwinner: add v853 usb phy Andras Szemzo
` (2 subsequent siblings)
11 siblings, 1 reply; 50+ messages in thread
From: Andras Szemzo @ 2025-01-10 12:39 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
Linus Walleij, Philipp Zabel, Maxime Ripard
Cc: Vinod Koul, Kishon Vijay Abraham I, Ulf Hansson, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Uwe Kleine-König,
Florian Fainelli, linux-clk, devicetree, linux-arm-kernel,
linux-sunxi, linux-kernel, linux-phy, linux-gpio, linux-pm,
linux-riscv
The device-tree needs ppu indexes, add it.
Signed-off-by: Andras Szemzo <szemzo.andras@gmail.com>
---
include/dt-bindings/power/allwinner,sun8i-v853-ppu.h | 10 ++++++++++
1 file changed, 10 insertions(+)
create mode 100644 include/dt-bindings/power/allwinner,sun8i-v853-ppu.h
diff --git a/include/dt-bindings/power/allwinner,sun8i-v853-ppu.h b/include/dt-bindings/power/allwinner,sun8i-v853-ppu.h
new file mode 100644
index 000000000000..b1c18a490613
--- /dev/null
+++ b/include/dt-bindings/power/allwinner,sun8i-v853-ppu.h
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+
+#ifndef _DT_BINDINGS_POWER_SUN8I_V853_PPU_H_
+#define _DT_BINDINGS_POWER_SUN8I_V853_PPU_H_
+
+#define PD_RISCV 0
+#define PD_NPU 1
+#define PD_VE 2
+
+#endif
--
2.39.5
^ permalink raw reply related [flat|nested] 50+ messages in thread
* [PATCH 10/12] dt-bindings: phy: allwinner: add v853 usb phy
2025-01-10 12:39 [PATCH 00/12] Support for Allwinner V853 SoC Andras Szemzo
` (8 preceding siblings ...)
2025-01-10 12:39 ` [PATCH 09/12] dt-bindings: power: add V853 ppu bindings Andras Szemzo
@ 2025-01-10 12:39 ` Andras Szemzo
2025-01-10 13:39 ` Rob Herring (Arm)
` (2 more replies)
2025-01-10 12:39 ` [PATCH 11/12] phy: allwinner: add v853 usb phy compatible Andras Szemzo
2025-01-10 12:39 ` [PATCH 12/12] ARM: dts: sun8i: add DTSI file for V853 Andras Szemzo
11 siblings, 3 replies; 50+ messages in thread
From: Andras Szemzo @ 2025-01-10 12:39 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
Linus Walleij, Philipp Zabel, Maxime Ripard
Cc: Vinod Koul, Kishon Vijay Abraham I, Ulf Hansson, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Uwe Kleine-König,
Florian Fainelli, linux-clk, devicetree, linux-arm-kernel,
linux-sunxi, linux-kernel, linux-phy, linux-gpio, linux-pm,
linux-riscv
Document Allwinner v853 USB phy.
Signed-off-by: Andras Szemzo <szemzo.andras@gmail.com>
---
.../phy/allwinner,sun8i-v853-usb-phy.yaml | 89 +++++++++++++++++++
1 file changed, 89 insertions(+)
create mode 100644 Documentation/devicetree/bindings/phy/allwinner,sun8i-v853-usb-phy.yaml
diff --git a/Documentation/devicetree/bindings/phy/allwinner,sun8i-v853-usb-phy.yaml b/Documentation/devicetree/bindings/phy/allwinner,sun8i-v853-usb-phy.yaml
new file mode 100644
index 000000000000..773c3f476db8
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/allwinner,sun8i-v853-usb-phy.yaml
@@ -0,0 +1,89 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/phy/allwinner,sun8i-v853-usb-phy.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Allwinner V853 USB PHY
+
+maintainers:
+ - Chen-Yu Tsai <wens@csie.org>
+ - Maxime Ripard <mripard@kernel.org>
+
+properties:
+ "#phy-cells":
+ const: 1
+
+ compatible:
+ const:
+ - allwinner,sun8i-v853-usb-phy
+
+ reg:
+ items:
+ - description: PHY Control registers
+ - description: PHY PMU0 registers
+
+ reg-names:
+ items:
+ - const: phy_ctrl
+ - const: pmu0
+
+ clocks:
+ maxItems: 1
+ description: USB OHCI PHY bus clock
+
+ clock-names:
+ const: usb0_phy
+
+ resets:
+ maxItems: 1
+ description: USB OHCI reset
+
+ reset-names:
+ const: usb0_reset
+
+ usb0_id_det-gpios:
+ maxItems: 1
+ description: GPIO to the USB OTG ID pin
+
+ usb0_vbus_det-gpios:
+ maxItems: 1
+ description: GPIO to the USB OTG VBUS detect pin
+
+ usb0_vbus_power-supply:
+ description: Power supply to detect the USB OTG VBUS
+
+ usb0_vbus-supply:
+ description: Regulator controlling USB OTG VBUS
+
+required:
+ - "#phy-cells"
+ - compatible
+ - clocks
+ - clock-names
+ - reg
+ - reg-names
+ - resets
+ - reset-names
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+ #include <dt-bindings/clock/sun8i-v853-ccu.h>
+ #include <dt-bindings/reset/sun8i-v853-ccu.h>
+
+ usbphy: phy@4100400 {
+ #phy-cells = <1>;
+ compatible = "allwinner,sun8i-v853-usb-phy";
+ reg = <0x4100400 0x100>,
+ <0x4101800 0x100>;
+ reg-names = "phy_ctrl",
+ "pmu0";
+ clocks = <&ccu CLK_USB_OHCI>;
+ clock-names = "usb0_phy";
+ resets = <&ccu RST_USB_PHY>;
+ reset-names = "usb0_reset";
+ usb0_id_det-gpios = <&pio 5 6 GPIO_ACTIVE_HIGH>;
+ };
--
2.39.5
^ permalink raw reply related [flat|nested] 50+ messages in thread
* [PATCH 11/12] phy: allwinner: add v853 usb phy compatible
2025-01-10 12:39 [PATCH 00/12] Support for Allwinner V853 SoC Andras Szemzo
` (9 preceding siblings ...)
2025-01-10 12:39 ` [PATCH 10/12] dt-bindings: phy: allwinner: add v853 usb phy Andras Szemzo
@ 2025-01-10 12:39 ` Andras Szemzo
2025-01-10 12:39 ` [PATCH 12/12] ARM: dts: sun8i: add DTSI file for V853 Andras Szemzo
11 siblings, 0 replies; 50+ messages in thread
From: Andras Szemzo @ 2025-01-10 12:39 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
Linus Walleij, Philipp Zabel, Maxime Ripard
Cc: Vinod Koul, Kishon Vijay Abraham I, Ulf Hansson, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Uwe Kleine-König,
Florian Fainelli, linux-clk, devicetree, linux-arm-kernel,
linux-sunxi, linux-kernel, linux-phy, linux-gpio, linux-pm,
linux-riscv
V853 has a dual role USB phy, similar to other Allwinner devices, but with
only one phy. Add a compatible for it.
Signed-off-by: Andras Szemzo <szemzo.andras@gmail.com>
---
drivers/phy/allwinner/phy-sun4i-usb.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/drivers/phy/allwinner/phy-sun4i-usb.c b/drivers/phy/allwinner/phy-sun4i-usb.c
index cd159a71b23c..e126a0dcc19b 100644
--- a/drivers/phy/allwinner/phy-sun4i-usb.c
+++ b/drivers/phy/allwinner/phy-sun4i-usb.c
@@ -1006,6 +1006,15 @@ static const struct sun4i_usb_phy_cfg sun50i_a64_cfg = {
.phy0_dual_route = true,
};
+static const struct sun4i_usb_phy_cfg sun8i_v853_cfg = {
+ .num_phys = 1,
+ .phyctl_offset = REG_PHYCTL_A33,
+ .dedicated_clocks = true,
+ .hci_phy_ctl_clear = PHY_CTL_SIDDQ,
+ .phy0_dual_route = true,
+ .siddq_in_base = true,
+};
+
static const struct sun4i_usb_phy_cfg sun50i_h6_cfg = {
.num_phys = 4,
.phyctl_offset = REG_PHYCTL_A33,
@@ -1042,6 +1051,7 @@ static const struct of_device_id sun4i_usb_phy_of_match[] = {
.data = &sun50i_a64_cfg},
{ .compatible = "allwinner,sun50i-h6-usb-phy", .data = &sun50i_h6_cfg },
{ .compatible = "allwinner,sun50i-h616-usb-phy", .data = &sun50i_h616_cfg },
+ { .compatible = "allwinner,sun8i-v853-usb-phy", .data = &sun8i_v853_cfg },
{ .compatible = "allwinner,suniv-f1c100s-usb-phy",
.data = &suniv_f1c100s_cfg },
{ },
--
2.39.5
^ permalink raw reply related [flat|nested] 50+ messages in thread
* [PATCH 12/12] ARM: dts: sun8i: add DTSI file for V853
2025-01-10 12:39 [PATCH 00/12] Support for Allwinner V853 SoC Andras Szemzo
` (10 preceding siblings ...)
2025-01-10 12:39 ` [PATCH 11/12] phy: allwinner: add v853 usb phy compatible Andras Szemzo
@ 2025-01-10 12:39 ` Andras Szemzo
2025-01-10 13:58 ` Krzysztof Kozlowski
11 siblings, 1 reply; 50+ messages in thread
From: Andras Szemzo @ 2025-01-10 12:39 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
Linus Walleij, Philipp Zabel, Maxime Ripard
Cc: Vinod Koul, Kishon Vijay Abraham I, Ulf Hansson, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Uwe Kleine-König,
Florian Fainelli, linux-clk, devicetree, linux-arm-kernel,
linux-sunxi, linux-kernel, linux-phy, linux-gpio, linux-pm,
linux-riscv
V853/V851 is a new SoC by Allwinner. Add a basic dtsi file for it.
Signed-off-by: Andras Szemzo <szemzo.andras@gmail.com>
---
arch/arm/boot/dts/allwinner/sun8i-v853.dtsi | 673 ++++++++++++++++++++
1 file changed, 673 insertions(+)
create mode 100644 arch/arm/boot/dts/allwinner/sun8i-v853.dtsi
diff --git a/arch/arm/boot/dts/allwinner/sun8i-v853.dtsi b/arch/arm/boot/dts/allwinner/sun8i-v853.dtsi
new file mode 100644
index 000000000000..4ecc97c7e7c0
--- /dev/null
+++ b/arch/arm/boot/dts/allwinner/sun8i-v853.dtsi
@@ -0,0 +1,673 @@
+// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+// Copyright (C) 2024 Andras Szemzo <szemzo.andras@gmail.com>
+
+#include <dt-bindings/clock/sun6i-rtc.h>
+#include <dt-bindings/clock/sun8i-v853-r-ccu.h>
+#include <dt-bindings/reset/sun8i-v853-r-ccu.h>
+#include <dt-bindings/clock/sun8i-v853-ccu.h>
+#include <dt-bindings/reset/sun8i-v853-ccu.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/power/allwinner,sun8i-v853-ppu.h>
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ osc24M: osc24M-clk {
+ compatible = "fixed-clock";
+ clock-frequency = <24000000>;
+ clock-output-names = "osc24M";
+ #clock-cells = <0>;
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu0: cpu@0 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a7","arm,armv7";
+ reg = <0>;
+ clocks = <&ccu CLK_CPU>;
+ clock-names = "cpu";
+ clock-frequency = <912000000>;
+ clock-latency = <2000000>;
+ cooling-min-level = <5>;
+ cooling-max-level = <0>;
+ #cooling-cells = <2>; /* min followed by max */
+ dynamic-power-coefficient = <142>;
+ };
+ };
+
+ pmu {
+ compatible = "arm,cortex-a7-pmu";
+ interrupts = <GIC_SPI 172 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 173 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-parent = <&gic>;
+ };
+
+ timer {
+ compatible = "arm,armv7-timer";
+ interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>, /* Secure Phys IRQ */
+ <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>, /* Non-secure Phys IRQ */
+ <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>, /* Virt IRQ */
+ <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>; /* Hyp IRQ */
+ clock-frequency = <24000000>;
+ interrupt-parent = <&gic>;
+ arm,cpu-registers-not-fw-configured;
+ arm,no-tick-in-suspend;
+ };
+
+ soc {
+ compatible = "simple-bus";
+ ranges;
+ interrupt-parent = <&gic>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ dma-noncoherent;
+
+ pio: pinctrl@2000000 {
+ compatible = "allwinner,sun8i-v853-pinctrl";
+ reg = <0x2000000 0x800>;
+ interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_APB0>, <&osc24M>, <&rtc CLK_OSC32K>;
+ clock-names = "apb", "hosc", "losc";
+ gpio-controller;
+ interrupt-controller;
+ #gpio-cells = <3>;
+ #interrupt-cells = <3>;
+
+ /omit-if-no-ref/
+ uart0_ph9_pins: uart0-ph9-pins {
+ pins = "PH9", "PH10";
+ function = "uart0";
+ };
+
+ /omit-if-no-ref/
+ uart2_pe12_pins: uart2-pe12-pins {
+ pins = "PE12", "PE13";
+ function = "uart2";
+ };
+
+ /omit-if-no-ref/
+ dsi_2lane_pins: dsi-2lane-pins {
+ pins = "PD1", "PD2", "PD3", "PD4", "PD5", "PD6";
+ drive-strength = <30>;
+ function = "dsi";
+ };
+
+ /omit-if-no-ref/
+ spi0_pins: spi0-pins {
+ pins = "PC0", "PC1", "PC2", "PC3", "PC4", "PC5";
+ function = "spi0";
+ };
+
+ /omit-if-no-ref/
+ spi3_pins: spi3-pins {
+ pins = "PH11", "PH12", "PH13", "PH14";
+ function = "spi3";
+ };
+
+ /omit-if-no-ref/
+ i2c2_ph11_pins: i2c2-ph11-pins {
+ pins = "PH11", "PH12";
+ function = "i2c2";
+ };
+
+ /omit-if-no-ref/
+ i2c3_ph13_pins: i2c3-ph13-pins {
+ pins = "PH13", "PH14";
+ function = "i2c3";
+ };
+
+ /omit-if-no-ref/
+ mmc0_pins: mmc0-pins {
+ pins = "PF0", "PF1", "PF2", "PF3", "PF4", "PF5";
+ function = "sdc0";
+ };
+
+ /omit-if-no-ref/
+ mmc1_pins: mmc1-pins {
+ pins = "PE0", "PE1", "PE2", "PE3", "PE4", "PE5";
+ function = "sdc1";
+ };
+
+ /omit-if-no-ref/
+ rmii_pe_pins: rmii-pe-pins {
+ pins = "PE0", "PE1", "PE2", "PE3", "PE4",
+ "PE5", "PE6", "PE7", "PE8", "PE9";
+ function = "emac";
+ };
+
+ /omit-if-no-ref/
+ rmii_pd_pins: rmii-pd-pins {
+ pins = "PD1", "PD2", "PD3", "PD4", "PD5",
+ "PD6", "PD7", "PD8", "PD20", "PD21";
+ function = "emac";
+ };
+
+ /omit-if-no-ref/
+ dmic_ph9_pins: dmic-ph9-pins {
+ pins = "PH9", "PH10";
+ function = "dmic";
+ };
+ };
+
+ pwm: pwm@2000c00 {
+ compatible = "allwinner,sun20i-d1-pwm";
+ reg = <0x02000c00 0x400>;
+ clocks = <&osc24M>,
+ <&ccu CLK_BUS_PWM>,
+ <&ccu CLK_APB0>;
+ clock-names = "hosc", "bus", "apb";
+ resets = <&ccu RST_BUS_PWM>;
+ status = "disabled";
+ allwinner,pwm-channels = <12>;
+ #pwm-cells = <0x3>;
+ };
+
+ ccu: clock-controller@2001000 {
+ compatible = "allwinner,sun8i-v853-ccu";
+ reg = <0x2001000 0x1000>;
+ clocks = <&osc24M>,
+ <&rtc CLK_IOSC>,
+ <&rtc CLK_OSC32K>;
+ clock-names = "hosc", "iosc", "losc";
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ };
+
+ gpadc: adc@2009000 {
+ compatible = "allwinner,sun20i-d1-gpadc";
+ reg = <0x2009000 0x0400>;
+ clocks = <&ccu CLK_BUS_GPADC>;
+ resets = <&ccu RST_BUS_GPADC>;
+ interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ #io-channel-cells = <1>;
+ };
+
+ i2s0: i2s@2032000 {
+ compatible = "allwinner,sun50i-r329-i2s";
+ reg = <0x2032000 0x1000>;
+ interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_I2S0>,
+ <&ccu CLK_I2S0>;
+ clock-names = "apb", "mod";
+ resets = <&ccu RST_BUS_I2S0>;
+ dmas = <&dma 3>, <&dma 3>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ #sound-dai-cells = <0>;
+ };
+
+ i2s1: i2s@2033000 {
+ compatible = "allwinner,sun50i-r329-i2s";
+ reg = <0x2033000 0x1000>;
+ interrupts = <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_I2S1>,
+ <&ccu CLK_I2S1>;
+ clock-names = "apb", "mod";
+ resets = <&ccu RST_BUS_I2S1>;
+ dmas = <&dma 4>, <&dma 4>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ #sound-dai-cells = <0>;
+ };
+
+ timer: timer@2050000 {
+ compatible = "allwinner,sun20i-d1-timer",
+ "allwinner,sun8i-a23-timer";
+ reg = <0x2050000 0xa0>;
+ interrupts = <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&osc24M>;
+ };
+
+ wdt: watchdog@20500a0 {
+ compatible = "allwinner,sun20i-d1-wdt-reset",
+ "allwinner,sun20i-d1-wdt";
+ reg = <0x20500a0 0x20>;
+ interrupts = <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&osc24M>, <&rtc CLK_OSC32K>;
+ clock-names = "hosc", "losc";
+ status = "reserved";
+ };
+
+ uart0: serial@2500000 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x2500000 0x400>;
+ reg-io-width = <4>;
+ reg-shift = <2>;
+ interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_UART0>;
+ resets = <&ccu RST_BUS_UART0>;
+ dmas = <&dma 14>, <&dma 14>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ };
+
+ uart1: serial@2500400 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x2500400 0x400>;
+ reg-io-width = <4>;
+ reg-shift = <2>;
+ interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_UART1>;
+ resets = <&ccu RST_BUS_UART1>;
+ dmas = <&dma 15>, <&dma 15>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ };
+
+ uart2: serial@2500800 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x2500800 0x400>;
+ reg-io-width = <4>;
+ reg-shift = <2>;
+ interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_UART2>;
+ resets = <&ccu RST_BUS_UART2>;
+ dmas = <&dma 16>, <&dma 16>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ };
+
+ uart3: serial@2500c00 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x2500c00 0x400>;
+ reg-io-width = <4>;
+ reg-shift = <2>;
+ interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_UART3>;
+ resets = <&ccu RST_BUS_UART3>;
+ dmas = <&dma 17>, <&dma 17>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ };
+
+ i2c0: i2c@2502000 {
+ compatible = "allwinner,sun8i-v536-i2c",
+ "allwinner,sun6i-a31-i2c";
+ reg = <0x2502000 0x400>;
+ interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_I2C0>;
+ resets = <&ccu RST_BUS_I2C0>;
+ dmas = <&dma 43>, <&dma 43>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ i2c1: i2c@2502400 {
+ compatible = "allwinner,sun8i-v536-i2c",
+ "allwinner,sun6i-a31-i2c";
+ reg = <0x2502400 0x400>;
+ interrupts = <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_I2C1>;
+ resets = <&ccu RST_BUS_I2C1>;
+ dmas = <&dma 44>, <&dma 44>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ i2c2: i2c@2502800 {
+ compatible = "allwinner,sun8i-v536-i2c",
+ "allwinner,sun6i-a31-i2c";
+ reg = <0x2502800 0x400>;
+ interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_I2C2>;
+ resets = <&ccu RST_BUS_I2C2>;
+ dmas = <&dma 45>, <&dma 45>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ i2c3: i2c@2502c00 {
+ compatible = "allwinner,sun8i-v536-i2c",
+ "allwinner,sun6i-a31-i2c";
+ reg = <0x2502c00 0x400>;
+ interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_I2C3>;
+ resets = <&ccu RST_BUS_I2C3>;
+ dmas = <&dma 46>, <&dma 46>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ i2c4: i2c@2503000 {
+ compatible = "allwinner,sun8i-v536-i2c",
+ "allwinner,sun6i-a31-i2c";
+ reg = <0x2503000 0x400>;
+ interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_I2C4>;
+ resets = <&ccu RST_BUS_I2C4>;
+ dmas = <&dma 47>, <&dma 47>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ syscon: syscon@3000000 {
+ compatible = "allwinner,sun8i-h3-system-control";
+ reg = <0x3000000 0x1000>;
+ ranges;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ sram_c: sram@20000 {
+ compatible = "mmio-sram";
+ reg = <0x00020000 0x21000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 0x00020000 0x21000>;
+
+ ve_sram: sram-section@0 {
+ compatible = "allwinner,sun8i-v3s-sram-c", "allwinner,sun4i-a10-sram-c1";
+ reg = <0x000000 0xa000>;
+ };
+ };
+ };
+
+ dma: dma-controller@3002000 {
+ compatible = "allwinner,sun20i-d1-dma";
+ reg = <0x3002000 0x1000>;
+ interrupts = <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_DMA>, <&ccu CLK_MBUS_DMA>;
+ clock-names = "bus", "mbus";
+ resets = <&ccu RST_BUS_DMA>;
+ dma-channels = <16>;
+ dma-requests = <48>;
+ #dma-cells = <1>;
+ };
+
+ hwspinlock: hwlock@3005000 {
+ compatible = "allwinner,sun6i-a31-hwspinlock";
+ reg = <0x3005000 0x1000>;
+ clocks = <&ccu CLK_BUS_SPINLOCK>;
+ clock-names = "ahb";
+ resets = <&ccu RST_BUS_SPINLOCK>;
+ reset-names = "ahb";
+ interrupts = <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ sid: efuse@3006000 {
+ compatible = "allwinner,sun20i-d1-sid";
+ reg = <0x3006000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ ths_calib: ths-calib@14 {
+ reg = <0x14 0x8>;
+ };
+ };
+
+ hstimer@3008000 {
+ compatible = "allwinner,sun7i-a20-hstimer";
+ reg = <0x03008000 0x1000>;
+ interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_HSTIMER>;
+ };
+
+ gic: interrupt-controller@3021000 {
+ compatible = "arm,gic-400";
+ reg = <0x03021000 0x1000>, /* GIC Dist */
+ <0x03022000 0x2000>, /* GIC CPU */
+ <0x03024000 0x2000>, /* GIC VCPU Control */
+ <0x03026000 0x2000>; /* GIC VCPU */
+ interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>; /* GIC Maintenence IRQ */
+ interrupt-controller;
+ #interrupt-cells = <3>;
+ };
+
+ npu: npu@3050000 {
+ compatible = "vivante,gc";
+ reg = <0x03050000 0x1000>;
+ interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "npu";
+ clocks = <&ccu CLK_BUS_NPU>, <&ccu CLK_NPU>;
+ clock-names = "bus", "core";
+ assigned-clocks = <&ccu CLK_PLL_NPU_4X>, <&ccu CLK_NPU>;
+ assigned-clock-parents = <&osc24M>, <&ccu CLK_PLL_NPU_4X>;
+ assigned-clock-rates = <1392000000>, <348000000>;
+ resets = <&ccu RST_BUS_NPU>;
+ power-domains = <&ppu PD_NPU>;
+ };
+
+ mbus: dram-controller@3102000 {
+ compatible = "allwinner,sun20i-d1-mbus";
+ reg = <0x3102000 0x1000>,
+ <0x3103000 0x1000>;
+ reg-names = "mbus", "dram";
+ interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_MBUS>,
+ <&ccu CLK_DRAM>,
+ <&ccu CLK_BUS_DRAM>;
+ clock-names = "mbus", "dram", "bus";
+ dma-ranges = <0 0x40000000 0x80000000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ #interconnect-cells = <1>;
+ };
+
+ mmc0: mmc@4020000 {
+ compatible = "allwinner,sun20i-d1-mmc";
+ reg = <0x4020000 0x1000>;
+ interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_MMC0>, <&ccu CLK_MMC0>;
+ clock-names = "ahb", "mmc";
+ resets = <&ccu RST_BUS_MMC0>;
+ reset-names = "ahb";
+ no-sdio;
+ no-mmc;
+ cap-sd-highspeed;
+ max-frequency = <150000000>;
+ mmc-ddr-1_8v;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ mmc1: mmc@4021000 {
+ compatible = "allwinner,sun20i-d1-mmc";
+ reg = <0x4021000 0x1000>;
+ interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_MMC1>, <&ccu CLK_MMC1>;
+ clock-names = "ahb", "mmc";
+ resets = <&ccu RST_BUS_MMC1>;
+ reset-names = "ahb";
+ cap-sd-highspeed;
+ cap-mmc-highspeed;
+ max-frequency = <150000000>;
+ mmc-ddr-1_8v;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ mmc2: mmc@4022000 {
+ compatible = "allwinner,sun20i-d1-mmc";
+ reg = <0x4022000 0x1000>;
+ interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_MMC2>, <&ccu CLK_MMC2>;
+ clock-names = "ahb", "mmc";
+ resets = <&ccu RST_BUS_MMC2>;
+ reset-names = "ahb";
+ no-sdio;
+ no-sd;
+ cap-mmc-highspeed;
+ max-frequency = <150000000>;
+ mmc-ddr-1_8v;
+ mmc-ddr-3_3v;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ spi0: spi@4025000 {
+ compatible = "allwinner,sun50i-r329-spi";
+ reg = <0x4025000 0x1000>;
+ interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_SPI0>, <&ccu CLK_SPI0>;
+ clock-names = "ahb", "mod";
+ resets = <&ccu RST_BUS_SPI0>;
+ dmas = <&dma 22>, <&dma 22>;
+ dma-names = "rx", "tx";
+ num-cs = <1>;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ spi1: spi@4026000 {
+ compatible = "allwinner,sun50i-r329-spi-dbi",
+ "allwinner,sun50i-r329-spi";
+ reg = <0x4026000 0x1000>;
+ interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_SPI1>, <&ccu CLK_SPI1>;
+ clock-names = "ahb", "mod";
+ resets = <&ccu RST_BUS_SPI1>;
+ dmas = <&dma 23>, <&dma 23>;
+ dma-names = "rx", "tx";
+ num-cs = <1>;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ spi2: spi@4027000 {
+ compatible = "allwinner,sun50i-r329-spi";
+ reg = <0x4027000 0x1000>;
+ interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_SPI2>, <&ccu CLK_SPI2>;
+ clock-names = "ahb", "mod";
+ resets = <&ccu RST_BUS_SPI2>;
+ dmas = <&dma 24>, <&dma 24>;
+ dma-names = "rx", "tx";
+ num-cs = <1>;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ spi3: spi@4028000 {
+ compatible = "allwinner,sun50i-r329-spi";
+ reg = <0x4028000 0x1000>;
+ interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_SPI3>, <&ccu CLK_SPI3>;
+ clock-names = "ahb", "mod";
+ resets = <&ccu RST_BUS_SPI3>;
+ dmas = <&dma 25>, <&dma 25>;
+ dma-names = "rx", "tx";
+ num-cs = <1>;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ usb_otg: usb@4100000 {
+ compatible = "allwinner,sun8i-a33-musb";
+ reg = <0x4100000 0x400>;
+ interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "mc";
+ clocks = <&ccu CLK_BUS_OTG>;
+ resets = <&ccu RST_BUS_OTG>;
+ extcon = <&usbphy 0>;
+ phys = <&usbphy 0>;
+ phy-names = "usb";
+ status = "disabled";
+ };
+
+ usbphy: phy@4100400 {
+ compatible = "allwinner,sun8i-v853-usb-phy";
+ reg = <0x4100400 0x100>,
+ <0x4101800 0x100>;
+ reg-names = "phy_ctrl",
+ "pmu0";
+ clocks = <&ccu CLK_USB_OHCI>;
+ clock-names = "usb0_phy";
+ resets = <&ccu RST_USB_PHY>;
+ reset-names = "usb0_reset";
+ status = "disabled";
+ #phy-cells = <1>;
+ };
+
+ ehci0: usb@4101000 {
+ compatible = "generic-ehci";
+ reg = <0x4101000 0x100>;
+ interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_OHCI>,
+ <&ccu CLK_BUS_EHCI>,
+ <&ccu CLK_USB_OHCI>;
+ resets = <&ccu RST_BUS_OHCI>,
+ <&ccu RST_BUS_EHCI>;
+ phys = <&usbphy 0>;
+ phy-names = "usb";
+ status = "disabled";
+ };
+
+ ohci0: usb@4101400 {
+ compatible = "generic-ohci";
+ reg = <0x4101400 0x100>;
+ interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_OHCI>,
+ <&ccu CLK_USB_OHCI>;
+ resets = <&ccu RST_BUS_OHCI>;
+ phys = <&usbphy 0>;
+ phy-names = "usb";
+ status = "disabled";
+ };
+
+ ppu: power-controller@7001000 {
+ compatible = "allwinner,sun8i-v853-ppu";
+ reg = <0x7001000 0x400>;
+ clocks = <&r_ccu CLK_R_PPU>;
+ resets = <&r_ccu RST_BUS_R_PPU>;
+ #power-domain-cells = <1>;
+ };
+
+ r_ccu: clock-controller@7010000 {
+ compatible = "allwinner,sun8i-v853-r-ccu";
+ reg = <0x7010000 0x230>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ };
+
+ nmi_intc: intc-nmi@7010320 {
+ compatible = "allwinner,sun9i-a80-nmi";
+ interrupt-parent = <&gic>;
+ #interrupt-cells = <2>;
+ #address-cells = <0>;
+ interrupt-controller;
+ reg = <0x07010320 0xc>;
+ interrupts = <GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ rtc: rtc@7090000 {
+ compatible = "allwinner,sun50i-r329-rtc";
+ reg = <0x7090000 0x400>;
+ interrupts = <GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&r_ccu CLK_R_RTC>;
+ clock-names = "bus";
+ resets = <&r_ccu RST_BUS_R_RTC>;
+ wakeup-source;
+ #clock-cells = <1>;
+ };
+ };
+};
--
2.39.5
^ permalink raw reply related [flat|nested] 50+ messages in thread
* Re: [PATCH 10/12] dt-bindings: phy: allwinner: add v853 usb phy
2025-01-10 12:39 ` [PATCH 10/12] dt-bindings: phy: allwinner: add v853 usb phy Andras Szemzo
@ 2025-01-10 13:39 ` Rob Herring (Arm)
2025-01-10 13:53 ` Krzysztof Kozlowski
2025-01-15 7:51 ` Vinod Koul
2 siblings, 0 replies; 50+ messages in thread
From: Rob Herring (Arm) @ 2025-01-10 13:39 UTC (permalink / raw)
To: Andras Szemzo
Cc: devicetree, linux-phy, Vinod Koul, linux-sunxi, Philipp Zabel,
linux-riscv, Albert Ou, linux-gpio, Linus Walleij, Ulf Hansson,
Stephen Boyd, Florian Fainelli, Conor Dooley, Jernej Skrabec,
Paul Walmsley, Chen-Yu Tsai, linux-pm, Samuel Holland,
Maxime Ripard, Kishon Vijay Abraham I, linux-clk,
Michael Turquette, linux-kernel, Uwe Kleine-König,
Krzysztof Kozlowski, linux-arm-kernel, Palmer Dabbelt
On Fri, 10 Jan 2025 13:39:21 +0100, Andras Szemzo wrote:
> Document Allwinner v853 USB phy.
>
> Signed-off-by: Andras Szemzo <szemzo.andras@gmail.com>
> ---
> .../phy/allwinner,sun8i-v853-usb-phy.yaml | 89 +++++++++++++++++++
> 1 file changed, 89 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/phy/allwinner,sun8i-v853-usb-phy.yaml
>
My bot found errors running 'make dt_binding_check' on your patch:
yamllint warnings/errors:
./Documentation/devicetree/bindings/phy/allwinner,sun8i-v853-usb-phy.yaml:19:1: [error] syntax error: found character '\t' that cannot start any token (syntax)
dtschema/dtc warnings/errors:
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/phy/allwinner,sun8i-v853-usb-phy.yaml: ignoring, error parsing file
make[2]: *** Deleting file 'Documentation/devicetree/bindings/phy/allwinner,sun8i-v853-usb-phy.example.dts'
Documentation/devicetree/bindings/phy/allwinner,sun8i-v853-usb-phy.yaml:19:1: found character '\t' that cannot start any token
make[2]: *** [Documentation/devicetree/bindings/Makefile:26: Documentation/devicetree/bindings/phy/allwinner,sun8i-v853-usb-phy.example.dts] Error 1
make[2]: *** Waiting for unfinished jobs....
./Documentation/devicetree/bindings/phy/allwinner,sun8i-v853-usb-phy.yaml:19:1: found character '\t' that cannot start any token
make[1]: *** [/builds/robherring/dt-review-ci/linux/Makefile:1506: dt_binding_check] Error 2
make: *** [Makefile:251: __sub-make] Error 2
doc reference errors (make refcheckdocs):
See https://patchwork.ozlabs.org/project/devicetree-bindings/patch/20250110123923.270626-11-szemzo.andras@gmail.com
The base for the series is generally the latest rc1. A different dependency
should be noted in *this* patch.
If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:
pip3 install dtschema --upgrade
Please check and re-submit after running the above command yourself. Note
that DT_SCHEMA_FILES can be set to your schema file to speed up checking
your schema. However, it must be unset to test all examples with your schema.
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH 10/12] dt-bindings: phy: allwinner: add v853 usb phy
2025-01-10 12:39 ` [PATCH 10/12] dt-bindings: phy: allwinner: add v853 usb phy Andras Szemzo
2025-01-10 13:39 ` Rob Herring (Arm)
@ 2025-01-10 13:53 ` Krzysztof Kozlowski
2025-01-15 7:51 ` Vinod Koul
2 siblings, 0 replies; 50+ messages in thread
From: Krzysztof Kozlowski @ 2025-01-10 13:53 UTC (permalink / raw)
To: Andras Szemzo, Michael Turquette, Stephen Boyd, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Chen-Yu Tsai, Jernej Skrabec,
Samuel Holland, Linus Walleij, Philipp Zabel, Maxime Ripard
Cc: Vinod Koul, Kishon Vijay Abraham I, Ulf Hansson, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Uwe Kleine-König,
Florian Fainelli, linux-clk, devicetree, linux-arm-kernel,
linux-sunxi, linux-kernel, linux-phy, linux-gpio, linux-pm,
linux-riscv
On 10/01/2025 13:39, Andras Szemzo wrote:
> +
> +properties:
> + "#phy-cells":
> + const: 1
> +
> + compatible:
> + const:
> + - allwinner,sun8i-v853-usb-phy
Wrong indentation, never tested.
Compatible is always the first property.
> +
> + reg:
> + items:
> + - description: PHY Control registers
> + - description: PHY PMU0 registers
> +
> + reg-names:
> + items:
> + - const: phy_ctrl
> + - const: pmu0
> +
> + clocks:
> + maxItems: 1
> + description: USB OHCI PHY bus clock
Redundant description really...
> +
> + clock-names:
> + const: usb0_phy
Drop clock-names, not really helpful.
> +
> + resets:
> + maxItems: 1
> + description: USB OHCI reset
> +
> + reset-names:
> + const: usb0_reset
Drop names, also not really helping.
> +
> + usb0_id_det-gpios:
There are no properties with underscores.
I don't get why you are using "usb0" prefix. Document all pins, so
"usb1" as well, assuming it exists.
It anyway looks questionable - aren't these properties of connector?
> + maxItems: 1
> + description: GPIO to the USB OTG ID pin
> +
> + usb0_vbus_det-gpios:
> + maxItems: 1
> + description: GPIO to the USB OTG VBUS detect pin
> +
> + usb0_vbus_power-supply:
> + description: Power supply to detect the USB OTG VBUS
> +
> + usb0_vbus-supply:
> + description: Regulator controlling USB OTG VBUS
Regulator and power supply are here synonyms, so I don't understand
these two properties.
> +
> +required:
> + - "#phy-cells"
> + - compatible
> + - clocks
> + - clock-names
> + - reg
> + - reg-names
> + - resets
> + - reset-names
> +
> +additionalProperties: false
> +
> +examples:
> + - |
> + #include <dt-bindings/gpio/gpio.h>
> + #include <dt-bindings/clock/sun8i-v853-ccu.h>
> + #include <dt-bindings/reset/sun8i-v853-ccu.h>
> +
> + usbphy: phy@4100400 {
> + #phy-cells = <1>;
Please follow DTS coding style.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH 09/12] dt-bindings: power: add V853 ppu bindings
2025-01-10 12:39 ` [PATCH 09/12] dt-bindings: power: add V853 ppu bindings Andras Szemzo
@ 2025-01-10 13:53 ` Krzysztof Kozlowski
0 siblings, 0 replies; 50+ messages in thread
From: Krzysztof Kozlowski @ 2025-01-10 13:53 UTC (permalink / raw)
To: Andras Szemzo, Michael Turquette, Stephen Boyd, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Chen-Yu Tsai, Jernej Skrabec,
Samuel Holland, Linus Walleij, Philipp Zabel, Maxime Ripard
Cc: Vinod Koul, Kishon Vijay Abraham I, Ulf Hansson, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Uwe Kleine-König,
Florian Fainelli, linux-clk, devicetree, linux-arm-kernel,
linux-sunxi, linux-kernel, linux-phy, linux-gpio, linux-pm,
linux-riscv
On 10/01/2025 13:39, Andras Szemzo wrote:
> The device-tree needs ppu indexes, add it.
This belongs to the commit introducing binding. Squash it.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH 07/12] devicetree: bindings: power: add v853 ppu
2025-01-10 12:39 ` [PATCH 07/12] devicetree: bindings: power: add v853 ppu Andras Szemzo
@ 2025-01-10 13:54 ` Krzysztof Kozlowski
0 siblings, 0 replies; 50+ messages in thread
From: Krzysztof Kozlowski @ 2025-01-10 13:54 UTC (permalink / raw)
To: Andras Szemzo, Michael Turquette, Stephen Boyd, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Chen-Yu Tsai, Jernej Skrabec,
Samuel Holland, Linus Walleij, Philipp Zabel, Maxime Ripard
Cc: Vinod Koul, Kishon Vijay Abraham I, Ulf Hansson, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Uwe Kleine-König,
Florian Fainelli, linux-clk, devicetree, linux-arm-kernel,
linux-sunxi, linux-kernel, linux-phy, linux-gpio, linux-pm,
linux-riscv
On 10/01/2025 13:39, Andras Szemzo wrote:
> Document V853 PPU compatible.
>
> Signed-off-by: Andras Szemzo <szemzo.andras@gmail.com>
Why different subject prefix?
Please use subject prefixes matching the subsystem. You can get them for
example with `git log --oneline -- DIRECTORY_OR_FILE` on the directory
your patch is touching. For bindings, the preferred subjects are
explained here:
https://www.kernel.org/doc/html/latest/devicetree/bindings/submitting-patches.html#i-for-patch-submitters
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH 04/12] dt-bindings: clock: sunxi-ng: add compatibles for V853
2025-01-10 12:39 ` [PATCH 04/12] dt-bindings: clock: sunxi-ng: add compatibles for V853 Andras Szemzo
@ 2025-01-10 13:55 ` Krzysztof Kozlowski
0 siblings, 0 replies; 50+ messages in thread
From: Krzysztof Kozlowski @ 2025-01-10 13:55 UTC (permalink / raw)
To: Andras Szemzo, Michael Turquette, Stephen Boyd, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Chen-Yu Tsai, Jernej Skrabec,
Samuel Holland, Linus Walleij, Philipp Zabel, Maxime Ripard
Cc: Vinod Koul, Kishon Vijay Abraham I, Ulf Hansson, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Uwe Kleine-König,
Florian Fainelli, linux-clk, devicetree, linux-arm-kernel,
linux-sunxi, linux-kernel, linux-phy, linux-gpio, linux-pm,
linux-riscv
On 10/01/2025 13:39, Andras Szemzo wrote:
> V853 has 2 CCUs, add compatible strings for it.
>
> Signed-off-by: Andras Szemzo <szemzo.andras@gmail.com>
> ---
> .../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 1690b9d99c3d..bb1fa032e789 100644
> --- a/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-ccu.yaml
> +++ b/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-ccu.yaml
> @@ -36,6 +36,8 @@ properties:
> - allwinner,sun9i-a80-ccu
> - allwinner,sun20i-d1-ccu
> - allwinner,sun20i-d1-r-ccu
> + - allwinner,sun8i-v853-ccu
> + - allwinner,sun8i-v853-r-ccu
Where are the clock headers?
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH 06/12] dt-bindings: clk: sunxi-ng: add V853 CCU clock/reset
2025-01-10 12:39 ` [PATCH 06/12] dt-bindings: clk: sunxi-ng: add V853 CCU clock/reset Andras Szemzo
@ 2025-01-10 13:56 ` Krzysztof Kozlowski
2025-01-13 8:06 ` Chen-Yu Tsai
2025-01-11 10:34 ` Krzysztof Kozlowski
1 sibling, 1 reply; 50+ messages in thread
From: Krzysztof Kozlowski @ 2025-01-10 13:56 UTC (permalink / raw)
To: Andras Szemzo, Michael Turquette, Stephen Boyd, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Chen-Yu Tsai, Jernej Skrabec,
Samuel Holland, Linus Walleij, Philipp Zabel, Maxime Ripard
Cc: Vinod Koul, Kishon Vijay Abraham I, Ulf Hansson, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Uwe Kleine-König,
Florian Fainelli, linux-clk, devicetree, linux-arm-kernel,
linux-sunxi, linux-kernel, linux-phy, linux-gpio, linux-pm,
linux-riscv
On 10/01/2025 13:39, Andras Szemzo wrote:
> As the device tree needs the clock/reset indices, add them to DT binding
> headers.
>
> Signed-off-by: Andras Szemzo <szemzo.andras@gmail.com>
That's never a separate commit from the binding.
...
> --- /dev/null
> +++ b/include/dt-bindings/clock/sun8i-v853-r-ccu.h
> @@ -0,0 +1,16 @@
> +/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
> +/* Copyright(c) 2020 - 2023 Allwinner Technology Co.,Ltd. All rights reserved.
> + *
> + * Copyright (C) 2023 rengaomin@allwinnertech.com
> + */
> +#ifndef _DT_BINDINGS_CLK_SUN8I_V85X_R_CCU_H_
> +#define _DT_BINDINGS_CLK_SUN8I_V85X_R_CCU_H_
> +
> +#define CLK_R_TWD 0
> +#define CLK_R_PPU 1
> +#define CLK_R_RTC 2
> +#define CLK_R_CPUCFG 3
> +
> +#define CLK_R_MAX_NO (CLK_R_CPUCFG + 1)
Nope, drop. Not a binding.
> +
> +#endif
> diff --git a/include/dt-bindings/reset/sun8i-v853-ccu.h b/include/dt-bindings/reset/sun8i-v853-ccu.h
> new file mode 100644
> index 000000000000..89d94fcbdb55
> --- /dev/null
> +++ b/include/dt-bindings/reset/sun8i-v853-ccu.h
> @@ -0,0 +1,62 @@
> +/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
Odd license. Did you copy the file with such license from the downstream?
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH 12/12] ARM: dts: sun8i: add DTSI file for V853
2025-01-10 12:39 ` [PATCH 12/12] ARM: dts: sun8i: add DTSI file for V853 Andras Szemzo
@ 2025-01-10 13:58 ` Krzysztof Kozlowski
2025-01-15 9:09 ` Csókás Bence
0 siblings, 1 reply; 50+ messages in thread
From: Krzysztof Kozlowski @ 2025-01-10 13:58 UTC (permalink / raw)
To: Andras Szemzo, Michael Turquette, Stephen Boyd, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Chen-Yu Tsai, Jernej Skrabec,
Samuel Holland, Linus Walleij, Philipp Zabel, Maxime Ripard
Cc: Vinod Koul, Kishon Vijay Abraham I, Ulf Hansson, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Uwe Kleine-König,
Florian Fainelli, linux-clk, devicetree, linux-arm-kernel,
linux-sunxi, linux-kernel, linux-phy, linux-gpio, linux-pm,
linux-riscv
On 10/01/2025 13:39, Andras Szemzo wrote:
> V853/V851 is a new SoC by Allwinner. Add a basic dtsi file for it.
>
> Signed-off-by: Andras Szemzo <szemzo.andras@gmail.com>
> ---
> arch/arm/boot/dts/allwinner/sun8i-v853.dtsi | 673 ++++++++++++++++++++
> 1 file changed, 673 insertions(+)
> create mode 100644 arch/arm/boot/dts/allwinner/sun8i-v853.dtsi
>
> diff --git a/arch/arm/boot/dts/allwinner/sun8i-v853.dtsi b/arch/arm/boot/dts/allwinner/sun8i-v853.dtsi
> new file mode 100644
> index 000000000000..4ecc97c7e7c0
> --- /dev/null
> +++ b/arch/arm/boot/dts/allwinner/sun8i-v853.dtsi
Impossible to build and test.
Please submit complete work, so one which can be actually built (DTSI,
DTS and bindings).
> @@ -0,0 +1,673 @@
> +// SPDX-License-Identifier: (GPL-2.0+ or MIT)
Odd license, why would we ever want GPLv3 or even GPLv4?
> +// Copyright (C) 2024 Andras Szemzo <szemzo.andras@gmail.com>
> +
> +#include <dt-bindings/clock/sun6i-rtc.h>
> +#include <dt-bindings/clock/sun8i-v853-r-ccu.h>
> +#include <dt-bindings/reset/sun8i-v853-r-ccu.h>
> +#include <dt-bindings/clock/sun8i-v853-ccu.h>
> +#include <dt-bindings/reset/sun8i-v853-ccu.h>
> +#include <dt-bindings/interrupt-controller/arm-gic.h>
> +#include <dt-bindings/power/allwinner,sun8i-v853-ppu.h>
> +
> +/ {
> + #address-cells = <1>;
> + #size-cells = <1>;
> +
> + osc24M: osc24M-clk {
Only lowercase node names.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH 06/12] dt-bindings: clk: sunxi-ng: add V853 CCU clock/reset
2025-01-10 12:39 ` [PATCH 06/12] dt-bindings: clk: sunxi-ng: add V853 CCU clock/reset Andras Szemzo
2025-01-10 13:56 ` Krzysztof Kozlowski
@ 2025-01-11 10:34 ` Krzysztof Kozlowski
2025-01-13 7:02 ` András Szemző
1 sibling, 1 reply; 50+ messages in thread
From: Krzysztof Kozlowski @ 2025-01-11 10:34 UTC (permalink / raw)
To: Andras Szemzo
Cc: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
Linus Walleij, Philipp Zabel, Maxime Ripard, Vinod Koul,
Kishon Vijay Abraham I, Ulf Hansson, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Uwe Kleine-König,
Florian Fainelli, linux-clk, devicetree, linux-arm-kernel,
linux-sunxi, linux-kernel, linux-phy, linux-gpio, linux-pm,
linux-riscv
On Fri, Jan 10, 2025 at 01:39:17PM +0100, Andras Szemzo wrote:
> As the device tree needs the clock/reset indices, add them to DT binding
> headers.
>
> Signed-off-by: Andras Szemzo <szemzo.andras@gmail.com>
> ---
> include/dt-bindings/clock/sun8i-v853-ccu.h | 132 +++++++++++++++++++
Please use full compatible as filename.
> include/dt-bindings/clock/sun8i-v853-r-ccu.h | 16 +++
> include/dt-bindings/reset/sun8i-v853-ccu.h | 62 +++++++++
> include/dt-bindings/reset/sun8i-v853-r-ccu.h | 14 ++
> 4 files changed, 224 insertions(+)
> create mode 100644 include/dt-bindings/clock/sun8i-v853-ccu.h
> create mode 100644 include/dt-bindings/clock/sun8i-v853-r-ccu.h
> create mode 100644 include/dt-bindings/reset/sun8i-v853-ccu.h
> create mode 100644 include/dt-bindings/reset/sun8i-v853-r-ccu.h
>
> diff --git a/include/dt-bindings/clock/sun8i-v853-ccu.h b/include/dt-bindings/clock/sun8i-v853-ccu.h
> new file mode 100644
> index 000000000000..a405b982f914
> --- /dev/null
> +++ b/include/dt-bindings/clock/sun8i-v853-ccu.h
> @@ -0,0 +1,132 @@
> +/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
BTW, also checkpatch warns about this...
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH 06/12] dt-bindings: clk: sunxi-ng: add V853 CCU clock/reset
2025-01-11 10:34 ` Krzysztof Kozlowski
@ 2025-01-13 7:02 ` András Szemző
0 siblings, 0 replies; 50+ messages in thread
From: András Szemző @ 2025-01-13 7:02 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
Linus Walleij, Philipp Zabel, Maxime Ripard, Vinod Koul,
Kishon Vijay Abraham I, Ulf Hansson, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Uwe Kleine-König,
Florian Fainelli, linux-clk, devicetree, linux-arm-kernel,
linux-sunxi, linux-kernel, linux-phy, linux-gpio, linux-pm,
linux-riscv
Thanks for your comments for the whole series!
Not everything is clear for me yet, but I’ll clarify with sunxi community, and
fix it based on your suggestions.
> On 11 Jan 2025, at 11:34, Krzysztof Kozlowski <krzk@kernel.org> wrote:
>
> On Fri, Jan 10, 2025 at 01:39:17PM +0100, Andras Szemzo wrote:
>> As the device tree needs the clock/reset indices, add them to DT binding
>> headers.
>>
>> Signed-off-by: Andras Szemzo <szemzo.andras@gmail.com>
>> ---
>> include/dt-bindings/clock/sun8i-v853-ccu.h | 132 +++++++++++++++++++
>
> Please use full compatible as filename.
>
>> include/dt-bindings/clock/sun8i-v853-r-ccu.h | 16 +++
>> include/dt-bindings/reset/sun8i-v853-ccu.h | 62 +++++++++
>> include/dt-bindings/reset/sun8i-v853-r-ccu.h | 14 ++
>> 4 files changed, 224 insertions(+)
>> create mode 100644 include/dt-bindings/clock/sun8i-v853-ccu.h
>> create mode 100644 include/dt-bindings/clock/sun8i-v853-r-ccu.h
>> create mode 100644 include/dt-bindings/reset/sun8i-v853-ccu.h
>> create mode 100644 include/dt-bindings/reset/sun8i-v853-r-ccu.h
>>
>> diff --git a/include/dt-bindings/clock/sun8i-v853-ccu.h b/include/dt-bindings/clock/sun8i-v853-ccu.h
>> new file mode 100644
>> index 000000000000..a405b982f914
>> --- /dev/null
>> +++ b/include/dt-bindings/clock/sun8i-v853-ccu.h
>> @@ -0,0 +1,132 @@
>> +/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
>
> BTW, also checkpatch warns about this...
>
> Best regards,
> Krzysztof
>
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH 06/12] dt-bindings: clk: sunxi-ng: add V853 CCU clock/reset
2025-01-10 13:56 ` Krzysztof Kozlowski
@ 2025-01-13 8:06 ` Chen-Yu Tsai
2025-01-13 8:21 ` Krzysztof Kozlowski
0 siblings, 1 reply; 50+ messages in thread
From: Chen-Yu Tsai @ 2025-01-13 8:06 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: Andras Szemzo, Michael Turquette, Stephen Boyd, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Jernej Skrabec, Samuel Holland,
Linus Walleij, Philipp Zabel, Maxime Ripard, Vinod Koul,
Kishon Vijay Abraham I, Ulf Hansson, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Uwe Kleine-König,
Florian Fainelli, linux-clk, devicetree, linux-arm-kernel,
linux-sunxi, linux-kernel, linux-phy, linux-gpio, linux-pm,
linux-riscv
On Fri, Jan 10, 2025 at 9:56 PM Krzysztof Kozlowski <krzk@kernel.org> wrote:
>
> On 10/01/2025 13:39, Andras Szemzo wrote:
> > As the device tree needs the clock/reset indices, add them to DT binding
> > headers.
> >
> > Signed-off-by: Andras Szemzo <szemzo.andras@gmail.com>
>
> That's never a separate commit from the binding.
>
>
> ...
>
> > --- /dev/null
> > +++ b/include/dt-bindings/clock/sun8i-v853-r-ccu.h
> > @@ -0,0 +1,16 @@
> > +/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
> > +/* Copyright(c) 2020 - 2023 Allwinner Technology Co.,Ltd. All rights reserved.
> > + *
> > + * Copyright (C) 2023 rengaomin@allwinnertech.com
> > + */
> > +#ifndef _DT_BINDINGS_CLK_SUN8I_V85X_R_CCU_H_
> > +#define _DT_BINDINGS_CLK_SUN8I_V85X_R_CCU_H_
> > +
> > +#define CLK_R_TWD 0
> > +#define CLK_R_PPU 1
> > +#define CLK_R_RTC 2
> > +#define CLK_R_CPUCFG 3
> > +
> > +#define CLK_R_MAX_NO (CLK_R_CPUCFG + 1)
>
> Nope, drop. Not a binding.
>
> > +
> > +#endif
> > diff --git a/include/dt-bindings/reset/sun8i-v853-ccu.h b/include/dt-bindings/reset/sun8i-v853-ccu.h
> > new file mode 100644
> > index 000000000000..89d94fcbdb55
> > --- /dev/null
> > +++ b/include/dt-bindings/reset/sun8i-v853-ccu.h
> > @@ -0,0 +1,62 @@
> > +/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
>
> Odd license. Did you copy the file with such license from the downstream?
AFAIK all the existing sunxi clock / reset binding header files are
dual licensed. OOTH all the YAML files are GPL 2.0 only.
IIRC we started out GPL 2.0 only, but then figured that the header files
couldn't be shared with non-GPL projects, so we changed those to dual
license.
Hope that explains the current situation. Relicensing the whole lot
to just MIT or BSD is probably doable.
ChenYu
>
> Best regards,
> Krzysztof
>
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH 06/12] dt-bindings: clk: sunxi-ng: add V853 CCU clock/reset
2025-01-13 8:06 ` Chen-Yu Tsai
@ 2025-01-13 8:21 ` Krzysztof Kozlowski
2025-01-13 8:45 ` Chen-Yu Tsai
0 siblings, 1 reply; 50+ messages in thread
From: Krzysztof Kozlowski @ 2025-01-13 8:21 UTC (permalink / raw)
To: wens
Cc: Andras Szemzo, Michael Turquette, Stephen Boyd, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Jernej Skrabec, Samuel Holland,
Linus Walleij, Philipp Zabel, Maxime Ripard, Vinod Koul,
Kishon Vijay Abraham I, Ulf Hansson, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Uwe Kleine-König,
Florian Fainelli, linux-clk, devicetree, linux-arm-kernel,
linux-sunxi, linux-kernel, linux-phy, linux-gpio, linux-pm,
linux-riscv
On 13/01/2025 09:06, Chen-Yu Tsai wrote:
> On Fri, Jan 10, 2025 at 9:56 PM Krzysztof Kozlowski <krzk@kernel.org> wrote:
>>
>> On 10/01/2025 13:39, Andras Szemzo wrote:
>>> As the device tree needs the clock/reset indices, add them to DT binding
>>> headers.
>>>
>>> Signed-off-by: Andras Szemzo <szemzo.andras@gmail.com>
>>
>> That's never a separate commit from the binding.
>>
>>
>> ...
>>
>>> --- /dev/null
>>> +++ b/include/dt-bindings/clock/sun8i-v853-r-ccu.h
>>> @@ -0,0 +1,16 @@
>>> +/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
>>> +/* Copyright(c) 2020 - 2023 Allwinner Technology Co.,Ltd. All rights reserved.
>>> + *
>>> + * Copyright (C) 2023 rengaomin@allwinnertech.com
>>> + */
>>> +#ifndef _DT_BINDINGS_CLK_SUN8I_V85X_R_CCU_H_
>>> +#define _DT_BINDINGS_CLK_SUN8I_V85X_R_CCU_H_
>>> +
>>> +#define CLK_R_TWD 0
>>> +#define CLK_R_PPU 1
>>> +#define CLK_R_RTC 2
>>> +#define CLK_R_CPUCFG 3
>>> +
>>> +#define CLK_R_MAX_NO (CLK_R_CPUCFG + 1)
>>
>> Nope, drop. Not a binding.
>>
>>> +
>>> +#endif
>>> diff --git a/include/dt-bindings/reset/sun8i-v853-ccu.h b/include/dt-bindings/reset/sun8i-v853-ccu.h
>>> new file mode 100644
>>> index 000000000000..89d94fcbdb55
>>> --- /dev/null
>>> +++ b/include/dt-bindings/reset/sun8i-v853-ccu.h
>>> @@ -0,0 +1,62 @@
>>> +/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
>>
>> Odd license. Did you copy the file with such license from the downstream?
>
> AFAIK all the existing sunxi clock / reset binding header files are
> dual licensed. OOTH all the YAML files are GPL 2.0 only.
>
> IIRC we started out GPL 2.0 only, but then figured that the header files
> couldn't be shared with non-GPL projects, so we changed those to dual
> license.
>
> Hope that explains the current situation. Relicensing the whole lot
> to just MIT or BSD is probably doable.
That's not what the comment is about. Dual license, as expressed by
submitting bindings/patches and enforced by checkpatch are expected. But
not GPLv3, GPLv4 and GPLv10.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH 06/12] dt-bindings: clk: sunxi-ng: add V853 CCU clock/reset
2025-01-13 8:21 ` Krzysztof Kozlowski
@ 2025-01-13 8:45 ` Chen-Yu Tsai
2025-01-13 10:57 ` Andre Przywara
2025-01-13 11:15 ` Krzysztof Kozlowski
0 siblings, 2 replies; 50+ messages in thread
From: Chen-Yu Tsai @ 2025-01-13 8:45 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: Andras Szemzo, Michael Turquette, Stephen Boyd, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Jernej Skrabec, Samuel Holland,
Linus Walleij, Philipp Zabel, Maxime Ripard, Vinod Koul,
Kishon Vijay Abraham I, Ulf Hansson, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Uwe Kleine-König,
Florian Fainelli, linux-clk, devicetree, linux-arm-kernel,
linux-sunxi, linux-kernel, linux-phy, linux-gpio, linux-pm,
linux-riscv
On Mon, Jan 13, 2025 at 4:21 PM Krzysztof Kozlowski <krzk@kernel.org> wrote:
>
> On 13/01/2025 09:06, Chen-Yu Tsai wrote:
> > On Fri, Jan 10, 2025 at 9:56 PM Krzysztof Kozlowski <krzk@kernel.org> wrote:
> >>
> >> On 10/01/2025 13:39, Andras Szemzo wrote:
> >>> As the device tree needs the clock/reset indices, add them to DT binding
> >>> headers.
> >>>
> >>> Signed-off-by: Andras Szemzo <szemzo.andras@gmail.com>
> >>
> >> That's never a separate commit from the binding.
> >>
> >>
> >> ...
> >>
> >>> --- /dev/null
> >>> +++ b/include/dt-bindings/clock/sun8i-v853-r-ccu.h
> >>> @@ -0,0 +1,16 @@
> >>> +/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
> >>> +/* Copyright(c) 2020 - 2023 Allwinner Technology Co.,Ltd. All rights reserved.
> >>> + *
> >>> + * Copyright (C) 2023 rengaomin@allwinnertech.com
> >>> + */
> >>> +#ifndef _DT_BINDINGS_CLK_SUN8I_V85X_R_CCU_H_
> >>> +#define _DT_BINDINGS_CLK_SUN8I_V85X_R_CCU_H_
> >>> +
> >>> +#define CLK_R_TWD 0
> >>> +#define CLK_R_PPU 1
> >>> +#define CLK_R_RTC 2
> >>> +#define CLK_R_CPUCFG 3
> >>> +
> >>> +#define CLK_R_MAX_NO (CLK_R_CPUCFG + 1)
> >>
> >> Nope, drop. Not a binding.
> >>
> >>> +
> >>> +#endif
> >>> diff --git a/include/dt-bindings/reset/sun8i-v853-ccu.h b/include/dt-bindings/reset/sun8i-v853-ccu.h
> >>> new file mode 100644
> >>> index 000000000000..89d94fcbdb55
> >>> --- /dev/null
> >>> +++ b/include/dt-bindings/reset/sun8i-v853-ccu.h
> >>> @@ -0,0 +1,62 @@
> >>> +/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
> >>
> >> Odd license. Did you copy the file with such license from the downstream?
> >
> > AFAIK all the existing sunxi clock / reset binding header files are
> > dual licensed. OOTH all the YAML files are GPL 2.0 only.
> >
> > IIRC we started out GPL 2.0 only, but then figured that the header files
> > couldn't be shared with non-GPL projects, so we changed those to dual
> > license.
> >
> > Hope that explains the current situation. Relicensing the whole lot
> > to just MIT or BSD is probably doable.
> That's not what the comment is about. Dual license, as expressed by
> submitting bindings/patches and enforced by checkpatch are expected. But
> not GPLv3, GPLv4 and GPLv10.
I take back my statement. It seems we have a lot of GPLv2 or later going on.
include/dt-bindings/clock/sun20i-d1-ccu.h:/* SPDX-License-Identifier:
(GPL-2.0+ OR MIT) */
include/dt-bindings/clock/sun20i-d1-r-ccu.h:/*
SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
include/dt-bindings/clock/sun50i-a100-ccu.h:/*
SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
include/dt-bindings/clock/sun50i-a100-r-ccu.h:/*
SPDX-License-Identifier: GPL-2.0 */
include/dt-bindings/clock/sun50i-h6-ccu.h:/* SPDX-License-Identifier:
(GPL-2.0+ OR MIT) */
include/dt-bindings/clock/sun50i-h6-r-ccu.h:/*
SPDX-License-Identifier: GPL-2.0 */
include/dt-bindings/clock/sun50i-h616-ccu.h:/*
SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
include/dt-bindings/clock/sun5i-ccu.h:/* SPDX-License-Identifier:
GPL-2.0-or-later */
include/dt-bindings/clock/sun6i-rtc.h:/* SPDX-License-Identifier:
(GPL-2.0+ OR MIT) */
include/dt-bindings/clock/sun8i-de2.h: * SPDX-License-Identifier:
(GPL-2.0+ OR MIT)
include/dt-bindings/clock/sun8i-tcon-top.h:/* SPDX-License-Identifier:
(GPL-2.0+ OR MIT) */
include/dt-bindings/clock/suniv-ccu-f1c100s.h:/*
SPDX-License-Identifier: (GPL-2.0+ OR MIT)
include/dt-bindings/reset/sun20i-d1-ccu.h:/* SPDX-License-Identifier:
(GPL-2.0+ OR MIT) */
include/dt-bindings/reset/sun20i-d1-r-ccu.h:/*
SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
include/dt-bindings/reset/sun50i-a100-ccu.h:/*
SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
include/dt-bindings/reset/sun50i-a100-r-ccu.h:/*
SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
include/dt-bindings/reset/sun50i-h6-ccu.h:/* SPDX-License-Identifier:
(GPL-2.0+ OR MIT) */
include/dt-bindings/reset/sun50i-h6-r-ccu.h:/*
SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
include/dt-bindings/reset/sun50i-h616-ccu.h:/*
SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
include/dt-bindings/reset/sun5i-ccu.h:/* SPDX-License-Identifier:
GPL-2.0-or-later */
include/dt-bindings/reset/sun8i-de2.h: * SPDX-License-Identifier:
(GPL-2.0+ OR MIT)
include/dt-bindings/reset/suniv-ccu-f1c100s.h:/*
SPDX-License-Identifier: (GPL-2.0+ OR MIT)
Is there a requirement that new files have to be GPL 2.0 only, not
GPL 2.0 or later?
Documentation/process/license-rules.rst says:
The license described in the COPYING file applies to the kernel source
as a whole, though individual source files can have a different license
which is required to be compatible with the GPL-2.0::
GPL-1.0+ : GNU General Public License v1.0 or later
GPL-2.0+ : GNU General Public License v2.0 or later
...
Aside from that, individual files can be provided under a dual license,
e.g. one of the compatible GPL variants and alternatively under a
permissive license like BSD, MIT etc.
ChenYu
> Best regards,
> Krzysztof
>
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH 06/12] dt-bindings: clk: sunxi-ng: add V853 CCU clock/reset
2025-01-13 8:45 ` Chen-Yu Tsai
@ 2025-01-13 10:57 ` Andre Przywara
2025-01-13 11:15 ` Krzysztof Kozlowski
1 sibling, 0 replies; 50+ messages in thread
From: Andre Przywara @ 2025-01-13 10:57 UTC (permalink / raw)
To: Chen-Yu Tsai
Cc: Krzysztof Kozlowski, Andras Szemzo, Michael Turquette,
Stephen Boyd, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Jernej Skrabec, Samuel Holland, Linus Walleij, Philipp Zabel,
Maxime Ripard, Vinod Koul, Kishon Vijay Abraham I, Ulf Hansson,
Paul Walmsley, Palmer Dabbelt, Albert Ou, Uwe Kleine-König,
Florian Fainelli, linux-clk, devicetree, linux-arm-kernel,
linux-sunxi, linux-kernel, linux-phy, linux-gpio, linux-pm,
linux-riscv
On Mon, 13 Jan 2025 16:45:10 +0800
Chen-Yu Tsai <wens@csie.org> wrote:
> On Mon, Jan 13, 2025 at 4:21 PM Krzysztof Kozlowski <krzk@kernel.org> wrote:
> >
> > On 13/01/2025 09:06, Chen-Yu Tsai wrote:
> > > On Fri, Jan 10, 2025 at 9:56 PM Krzysztof Kozlowski <krzk@kernel.org> wrote:
> > >>
> > >> On 10/01/2025 13:39, Andras Szemzo wrote:
> > >>> As the device tree needs the clock/reset indices, add them to DT binding
> > >>> headers.
> > >>>
> > >>> Signed-off-by: Andras Szemzo <szemzo.andras@gmail.com>
> > >>
> > >> That's never a separate commit from the binding.
> > >>
> > >>
> > >> ...
> > >>
> > >>> --- /dev/null
> > >>> +++ b/include/dt-bindings/clock/sun8i-v853-r-ccu.h
> > >>> @@ -0,0 +1,16 @@
> > >>> +/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
> > >>> +/* Copyright(c) 2020 - 2023 Allwinner Technology Co.,Ltd. All rights reserved.
> > >>> + *
> > >>> + * Copyright (C) 2023 rengaomin@allwinnertech.com
> > >>> + */
> > >>> +#ifndef _DT_BINDINGS_CLK_SUN8I_V85X_R_CCU_H_
> > >>> +#define _DT_BINDINGS_CLK_SUN8I_V85X_R_CCU_H_
> > >>> +
> > >>> +#define CLK_R_TWD 0
> > >>> +#define CLK_R_PPU 1
> > >>> +#define CLK_R_RTC 2
> > >>> +#define CLK_R_CPUCFG 3
> > >>> +
> > >>> +#define CLK_R_MAX_NO (CLK_R_CPUCFG + 1)
> > >>
> > >> Nope, drop. Not a binding.
> > >>
> > >>> +
> > >>> +#endif
> > >>> diff --git a/include/dt-bindings/reset/sun8i-v853-ccu.h b/include/dt-bindings/reset/sun8i-v853-ccu.h
> > >>> new file mode 100644
> > >>> index 000000000000..89d94fcbdb55
> > >>> --- /dev/null
> > >>> +++ b/include/dt-bindings/reset/sun8i-v853-ccu.h
> > >>> @@ -0,0 +1,62 @@
> > >>> +/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
> > >>
> > >> Odd license. Did you copy the file with such license from the downstream?
> > >
> > > AFAIK all the existing sunxi clock / reset binding header files are
> > > dual licensed. OOTH all the YAML files are GPL 2.0 only.
> > >
> > > IIRC we started out GPL 2.0 only, but then figured that the header files
> > > couldn't be shared with non-GPL projects, so we changed those to dual
> > > license.
> > >
> > > Hope that explains the current situation. Relicensing the whole lot
> > > to just MIT or BSD is probably doable.
> > That's not what the comment is about. Dual license, as expressed by
> > submitting bindings/patches and enforced by checkpatch are expected. But
> > not GPLv3, GPLv4 and GPLv10.
>
> I take back my statement. It seems we have a lot of GPLv2 or later going on.
>
> include/dt-bindings/clock/sun20i-d1-ccu.h:/* SPDX-License-Identifier:
> (GPL-2.0+ OR MIT) */
> include/dt-bindings/clock/sun20i-d1-r-ccu.h:/*
> SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
> include/dt-bindings/clock/sun50i-a100-ccu.h:/*
> SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
> include/dt-bindings/clock/sun50i-a100-r-ccu.h:/*
> SPDX-License-Identifier: GPL-2.0 */
> include/dt-bindings/clock/sun50i-h6-ccu.h:/* SPDX-License-Identifier:
> (GPL-2.0+ OR MIT) */
> include/dt-bindings/clock/sun50i-h6-r-ccu.h:/*
> SPDX-License-Identifier: GPL-2.0 */
> include/dt-bindings/clock/sun50i-h616-ccu.h:/*
> SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
> include/dt-bindings/clock/sun5i-ccu.h:/* SPDX-License-Identifier:
> GPL-2.0-or-later */
> include/dt-bindings/clock/sun6i-rtc.h:/* SPDX-License-Identifier:
> (GPL-2.0+ OR MIT) */
> include/dt-bindings/clock/sun8i-de2.h: * SPDX-License-Identifier:
> (GPL-2.0+ OR MIT)
> include/dt-bindings/clock/sun8i-tcon-top.h:/* SPDX-License-Identifier:
> (GPL-2.0+ OR MIT) */
> include/dt-bindings/clock/suniv-ccu-f1c100s.h:/*
> SPDX-License-Identifier: (GPL-2.0+ OR MIT)
> include/dt-bindings/reset/sun20i-d1-ccu.h:/* SPDX-License-Identifier:
> (GPL-2.0+ OR MIT) */
> include/dt-bindings/reset/sun20i-d1-r-ccu.h:/*
> SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
> include/dt-bindings/reset/sun50i-a100-ccu.h:/*
> SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
> include/dt-bindings/reset/sun50i-a100-r-ccu.h:/*
> SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
> include/dt-bindings/reset/sun50i-h6-ccu.h:/* SPDX-License-Identifier:
> (GPL-2.0+ OR MIT) */
> include/dt-bindings/reset/sun50i-h6-r-ccu.h:/*
> SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
> include/dt-bindings/reset/sun50i-h616-ccu.h:/*
> SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
> include/dt-bindings/reset/sun5i-ccu.h:/* SPDX-License-Identifier:
> GPL-2.0-or-later */
> include/dt-bindings/reset/sun8i-de2.h: * SPDX-License-Identifier:
> (GPL-2.0+ OR MIT)
> include/dt-bindings/reset/suniv-ccu-f1c100s.h:/*
> SPDX-License-Identifier: (GPL-2.0+ OR MIT)
>
> Is there a requirement that new files have to be GPL 2.0 only, not
> GPL 2.0 or later?
>
> Documentation/process/license-rules.rst says:
> The license described in the COPYING file applies to the kernel source
> as a whole, though individual source files can have a different license
> which is required to be compatible with the GPL-2.0::
>
> GPL-1.0+ : GNU General Public License v1.0 or later
> GPL-2.0+ : GNU General Public License v2.0 or later
> ...
>
> Aside from that, individual files can be provided under a dual license,
> e.g. one of the compatible GPL variants and alternatively under a
> permissive license like BSD, MIT etc.
Documentation/devicetree/bindings/submitting-patches.rst overrides the
general rule, for binding files, and it says (GPL-2.0-only OR BSD-2-Clause)
is preferred. Also when I checked checkpatch indeed warned about this. As
for the existing files: yes, many of them are not compliant atm:
$ git grep -h SPDX include/dt-bindings | sort | uniq -c | sort -n | tail -13
10 /* SPDX-License-Identifier: GPL-2.0 OR MIT */
13 /* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */
13 /* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */
14 /* SPDX-License-Identifier: GPL-2.0+
19 /* SPDX-License-Identifier: GPL-2.0
27 /* SPDX-License-Identifier: (GPL-2.0 OR MIT) */
31 /* SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause */
31 /* SPDX-License-Identifier: GPL-2.0-or-later */
33 /* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
36 /* SPDX-License-Identifier: GPL-2.0+ */
176 /* SPDX-License-Identifier: GPL-2.0-only */
192 /* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
281 /* SPDX-License-Identifier: GPL-2.0 */
But for new patches we should definitely aim to be correct. Differing
license requirements are one price we pay for not having a separate DT
repository.
Cheers,
Andre
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH 06/12] dt-bindings: clk: sunxi-ng: add V853 CCU clock/reset
2025-01-13 8:45 ` Chen-Yu Tsai
2025-01-13 10:57 ` Andre Przywara
@ 2025-01-13 11:15 ` Krzysztof Kozlowski
1 sibling, 0 replies; 50+ messages in thread
From: Krzysztof Kozlowski @ 2025-01-13 11:15 UTC (permalink / raw)
To: wens
Cc: Andras Szemzo, Michael Turquette, Stephen Boyd, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Jernej Skrabec, Samuel Holland,
Linus Walleij, Philipp Zabel, Maxime Ripard, Vinod Koul,
Kishon Vijay Abraham I, Ulf Hansson, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Uwe Kleine-König,
Florian Fainelli, linux-clk, devicetree, linux-arm-kernel,
linux-sunxi, linux-kernel, linux-phy, linux-gpio, linux-pm,
linux-riscv
On 13/01/2025 09:45, Chen-Yu Tsai wrote:
> On Mon, Jan 13, 2025 at 4:21 PM Krzysztof Kozlowski <krzk@kernel.org> wrote:
>>
>> On 13/01/2025 09:06, Chen-Yu Tsai wrote:
>>> On Fri, Jan 10, 2025 at 9:56 PM Krzysztof Kozlowski <krzk@kernel.org> wrote:
>>>>
>>>> On 10/01/2025 13:39, Andras Szemzo wrote:
>>>>> As the device tree needs the clock/reset indices, add them to DT binding
>>>>> headers.
>>>>>
>>>>> Signed-off-by: Andras Szemzo <szemzo.andras@gmail.com>
>>>>
>>>> That's never a separate commit from the binding.
>>>>
>>>>
>>>> ...
>>>>
>>>>> --- /dev/null
>>>>> +++ b/include/dt-bindings/clock/sun8i-v853-r-ccu.h
>>>>> @@ -0,0 +1,16 @@
>>>>> +/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
>>>>> +/* Copyright(c) 2020 - 2023 Allwinner Technology Co.,Ltd. All rights reserved.
>>>>> + *
>>>>> + * Copyright (C) 2023 rengaomin@allwinnertech.com
>>>>> + */
>>>>> +#ifndef _DT_BINDINGS_CLK_SUN8I_V85X_R_CCU_H_
>>>>> +#define _DT_BINDINGS_CLK_SUN8I_V85X_R_CCU_H_
>>>>> +
>>>>> +#define CLK_R_TWD 0
>>>>> +#define CLK_R_PPU 1
>>>>> +#define CLK_R_RTC 2
>>>>> +#define CLK_R_CPUCFG 3
>>>>> +
>>>>> +#define CLK_R_MAX_NO (CLK_R_CPUCFG + 1)
>>>>
>>>> Nope, drop. Not a binding.
>>>>
>>>>> +
>>>>> +#endif
>>>>> diff --git a/include/dt-bindings/reset/sun8i-v853-ccu.h b/include/dt-bindings/reset/sun8i-v853-ccu.h
>>>>> new file mode 100644
>>>>> index 000000000000..89d94fcbdb55
>>>>> --- /dev/null
>>>>> +++ b/include/dt-bindings/reset/sun8i-v853-ccu.h
>>>>> @@ -0,0 +1,62 @@
>>>>> +/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
>>>>
>>>> Odd license. Did you copy the file with such license from the downstream?
>>>
>>> AFAIK all the existing sunxi clock / reset binding header files are
>>> dual licensed. OOTH all the YAML files are GPL 2.0 only.
>>>
>>> IIRC we started out GPL 2.0 only, but then figured that the header files
>>> couldn't be shared with non-GPL projects, so we changed those to dual
>>> license.
>>>
>>> Hope that explains the current situation. Relicensing the whole lot
>>> to just MIT or BSD is probably doable.
>> That's not what the comment is about. Dual license, as expressed by
>> submitting bindings/patches and enforced by checkpatch are expected. But
>> not GPLv3, GPLv4 and GPLv10.
>
> I take back my statement. It seems we have a lot of GPLv2 or later going on.
There are a lot of bugs, so we can add them as well?
>
> include/dt-bindings/clock/sun20i-d1-ccu.h:/* SPDX-License-Identifier:
> (GPL-2.0+ OR MIT) */
> include/dt-bindings/clock/sun20i-d1-r-ccu.h:/*
> SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
> include/dt-bindings/clock/sun50i-a100-ccu.h:/*
> SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
> include/dt-bindings/clock/sun50i-a100-r-ccu.h:/*
> SPDX-License-Identifier: GPL-2.0 */
> include/dt-bindings/clock/sun50i-h6-ccu.h:/* SPDX-License-Identifier:
> (GPL-2.0+ OR MIT) */
> include/dt-bindings/clock/sun50i-h6-r-ccu.h:/*
> SPDX-License-Identifier: GPL-2.0 */
> include/dt-bindings/clock/sun50i-h616-ccu.h:/*
> SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
> include/dt-bindings/clock/sun5i-ccu.h:/* SPDX-License-Identifier:
> GPL-2.0-or-later */
> include/dt-bindings/clock/sun6i-rtc.h:/* SPDX-License-Identifier:
> (GPL-2.0+ OR MIT) */
> include/dt-bindings/clock/sun8i-de2.h: * SPDX-License-Identifier:
> (GPL-2.0+ OR MIT)
> include/dt-bindings/clock/sun8i-tcon-top.h:/* SPDX-License-Identifier:
> (GPL-2.0+ OR MIT) */
> include/dt-bindings/clock/suniv-ccu-f1c100s.h:/*
> SPDX-License-Identifier: (GPL-2.0+ OR MIT)
> include/dt-bindings/reset/sun20i-d1-ccu.h:/* SPDX-License-Identifier:
> (GPL-2.0+ OR MIT) */
> include/dt-bindings/reset/sun20i-d1-r-ccu.h:/*
> SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
> include/dt-bindings/reset/sun50i-a100-ccu.h:/*
> SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
> include/dt-bindings/reset/sun50i-a100-r-ccu.h:/*
> SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
> include/dt-bindings/reset/sun50i-h6-ccu.h:/* SPDX-License-Identifier:
> (GPL-2.0+ OR MIT) */
> include/dt-bindings/reset/sun50i-h6-r-ccu.h:/*
> SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
> include/dt-bindings/reset/sun50i-h616-ccu.h:/*
> SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
> include/dt-bindings/reset/sun5i-ccu.h:/* SPDX-License-Identifier:
> GPL-2.0-or-later */
> include/dt-bindings/reset/sun8i-de2.h: * SPDX-License-Identifier:
> (GPL-2.0+ OR MIT)
> include/dt-bindings/reset/suniv-ccu-f1c100s.h:/*
> SPDX-License-Identifier: (GPL-2.0+ OR MIT)
>
> Is there a requirement that new files have to be GPL 2.0 only, not
> GPL 2.0 or later?
I think that's obvious preference and brought to the list multiple times
already. And that's easy to justify reversing the question: why would
GPLv4 be okay here? If you can find the reason, sure we can go with
2.0+. If you cannot find the reason, well, it's obvious, right?
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH 03/12] pinctrl: sunxi: add driver for Allwinner V853.
2025-01-10 12:39 ` [PATCH 03/12] pinctrl: sunxi: add driver for Allwinner V853 Andras Szemzo
@ 2025-01-14 14:14 ` Linus Walleij
2025-01-14 14:19 ` Andre Przywara
1 sibling, 0 replies; 50+ messages in thread
From: Linus Walleij @ 2025-01-14 14:14 UTC (permalink / raw)
To: Andras Szemzo
Cc: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
Philipp Zabel, Maxime Ripard, Vinod Koul, Kishon Vijay Abraham I,
Ulf Hansson, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Uwe Kleine-König, Florian Fainelli, linux-clk, devicetree,
linux-arm-kernel, linux-sunxi, linux-kernel, linux-phy,
linux-gpio, linux-pm, linux-riscv
On Fri, Jan 10, 2025 at 1:39 PM Andras Szemzo <szemzo.andras@gmail.com> wrote:
> The V853 family has multiple package variants, from BGA to QFN88.
> The latter has co-packaged DRAM and fewer pins, and less features (pin muxes).
> All family members can be supported by a single driver, as the available pins
> with allowed muxes is the same across the devices.
>
> Signed-off-by: Andras Szemzo <szemzo.andras@gmail.com>
Looks good to me, waiting for a review of the bindings before applying,
but I see no problem with the patch as it's just using the core sunxi
infrastructure and any minor issues can be fixed in-tree.
Yours,
Linus Walleij
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH 03/12] pinctrl: sunxi: add driver for Allwinner V853.
2025-01-10 12:39 ` [PATCH 03/12] pinctrl: sunxi: add driver for Allwinner V853 Andras Szemzo
2025-01-14 14:14 ` Linus Walleij
@ 2025-01-14 14:19 ` Andre Przywara
2025-01-14 14:30 ` Andre Przywara
2025-01-15 10:23 ` Linus Walleij
1 sibling, 2 replies; 50+ messages in thread
From: Andre Przywara @ 2025-01-14 14:19 UTC (permalink / raw)
To: Andras Szemzo
Cc: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
Linus Walleij, Philipp Zabel, Maxime Ripard, Vinod Koul,
Kishon Vijay Abraham I, Ulf Hansson, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Uwe Kleine-König,
Florian Fainelli, linux-clk, devicetree, linux-arm-kernel,
linux-sunxi, linux-kernel, linux-phy, linux-gpio, linux-pm,
linux-riscv
On Fri, 10 Jan 2025 13:39:14 +0100
Andras Szemzo <szemzo.andras@gmail.com> wrote:
Hi,
> The V853 family has multiple package variants, from BGA to QFN88.
> The latter has co-packaged DRAM and fewer pins, and less features (pin muxes).
> All family members can be supported by a single driver, as the available pins
> with allowed muxes is the same across the devices.
It depends a bit on the outcome of the discussion on the A523 pinctrl
driver [1], but I think we should use the same approach here (and for
every "new" Allwinner SoC coming up, really): put the pinmux value in the
DT, and get rid of this entire table altogether:
[1]
The SoC specific pinctrl driver would then be very small ([2]), so this
pinctrl support patch here would actually become much smaller.
Just feel a bit sorry for you having created this table, in a tedious and
eye-straining exercise - been there, done that ;-)
Cheers,
Andre
> Signed-off-by: Andras Szemzo <szemzo.andras@gmail.com>
> ---
> drivers/pinctrl/sunxi/Kconfig | 5 +
> drivers/pinctrl/sunxi/Makefile | 1 +
> drivers/pinctrl/sunxi/pinctrl-sun8i-v853.c | 980 +++++++++++++++++++++
> drivers/pinctrl/sunxi/pinctrl-sunxi.h | 1 +
> 4 files changed, 987 insertions(+)
> create mode 100644 drivers/pinctrl/sunxi/pinctrl-sun8i-v853.c
>
> diff --git a/drivers/pinctrl/sunxi/Kconfig b/drivers/pinctrl/sunxi/Kconfig
> index a78fdbbdfc0c..df67310672ac 100644
> --- a/drivers/pinctrl/sunxi/Kconfig
> +++ b/drivers/pinctrl/sunxi/Kconfig
> @@ -86,6 +86,11 @@ config PINCTRL_SUN20I_D1
> default MACH_SUN8I || (RISCV && ARCH_SUNXI)
> select PINCTRL_SUNXI
>
> +config PINCTRL_SUN8I_V853
> + bool "Support for the Allwinner V853 PIO"
> + default MACH_SUN8I
> + select PINCTRL_SUNXI
> +
> config PINCTRL_SUN50I_A64
> bool "Support for the Allwinner A64 PIO"
> default ARM64 && ARCH_SUNXI
> diff --git a/drivers/pinctrl/sunxi/Makefile b/drivers/pinctrl/sunxi/Makefile
> index 2ff5a55927ad..2042276e85d6 100644
> --- a/drivers/pinctrl/sunxi/Makefile
> +++ b/drivers/pinctrl/sunxi/Makefile
> @@ -28,3 +28,4 @@ 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
> +obj-$(CONFIG_PINCTRL_SUN8I_V853) += pinctrl-sun8i-v853.o
> diff --git a/drivers/pinctrl/sunxi/pinctrl-sun8i-v853.c b/drivers/pinctrl/sunxi/pinctrl-sun8i-v853.c
> new file mode 100644
> index 000000000000..62b84404bd14
> --- /dev/null
> +++ b/drivers/pinctrl/sunxi/pinctrl-sun8i-v853.c
> @@ -0,0 +1,980 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Allwinner V853 SoC pinctrl driver.
> + *
> + * Copyright (c) 2016-2021 weidonghui <weidonghui@allwinnertech.com>
> + * Copyright (c) 2023 Andras Szemzo <szemzo.andras@gmail.com>
> + */
> +
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/of.h>
> +#include <linux/of_device.h>
> +#include <linux/pinctrl/pinctrl.h>
> +#include <linux/io.h>
> +
> +#include "pinctrl-sunxi.h"
> +
> +/* Pin banks are: A C D E F G H I */
> +static const struct sunxi_desc_pin sun8i_v853_pins[] = {
> +
> + /* bank A */
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 0),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "csi"), /* CKOP */
> + SUNXI_FUNCTION(0x3, "ncsi"), /* D8 */
> + SUNXI_FUNCTION(0x5, "test"),
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 0)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 1),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "csi"), /* CKON */
> + SUNXI_FUNCTION(0x3, "ncsi"), /* D9 */
> + SUNXI_FUNCTION(0x5, "test"), /* test */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 1)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 2),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "csi"), /* D1N */
> + SUNXI_FUNCTION(0x3, "ncsi"), /* D10 */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 2)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 3),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "csi"), /* D1P */
> + SUNXI_FUNCTION(0x3, "ncsi"), /* D11 */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 3)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 4),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "csi"), /* D0P */
> + SUNXI_FUNCTION(0x3, "ncsi"), /* D12 */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 4)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 5),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "csi"), /* D0N */
> + SUNXI_FUNCTION(0x3, "ncsi"), /* D13 */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 5)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 6),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "csi"), /* D0N/D2N */
> + SUNXI_FUNCTION(0x3, "ncsi"), /* D14 */
> + SUNXI_FUNCTION(0x4, "i2c1"), /* SCK */
> + SUNXI_FUNCTION(0x5, "pwm0"),
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 6)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 7),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "csi"), /* D0P/D2P */
> + SUNXI_FUNCTION(0x3, "ncsi"), /* D15 */
> + SUNXI_FUNCTION(0x4, "i2c1"), /* SDA */
> + SUNXI_FUNCTION(0x5, "pwm1"),
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 7)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 8),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "csi"), /* D1N/D3N */
> + SUNXI_FUNCTION(0x3, "i2c4"), /* SCK */
> + SUNXI_FUNCTION(0x4, "i2c3"), /* SCK */
> + SUNXI_FUNCTION(0x5, "pwm2"),
> + SUNXI_FUNCTION(0x6, "uart2"), /* TX */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 8)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 9),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "csi"), /* D1P/D3P */
> + SUNXI_FUNCTION(0x3, "i2c4"), /* SDA */
> + SUNXI_FUNCTION(0x4, "i2c3"), /* SDA */
> + SUNXI_FUNCTION(0x5, "pwm3"),
> + SUNXI_FUNCTION(0x6, "uart2"), /* RX */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 9)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 10),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "csi"), /* CKON */
> + SUNXI_FUNCTION(0x3, "ncsi"), /* HSYNC */
> + SUNXI_FUNCTION(0x4, "csi_mclk"), /* MCLK0 */
> + SUNXI_FUNCTION(0x5, "i2c0"), /* SCK */
> + SUNXI_FUNCTION(0x6, "clk"), /* FANOUT0 */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 10)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 11),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "csi"), /* CKOP */
> + SUNXI_FUNCTION(0x3, "ncsi"), /* VSYNC */
> + SUNXI_FUNCTION(0x4, "csi_mclk"), /* MCLK1 */
> + SUNXI_FUNCTION(0x5, "i2c0"), /* SDA */
> + SUNXI_FUNCTION(0x6, "clk"), /* FANOUT1 */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 11)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 12),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x3, "ncsi"), /* D0 */
> + SUNXI_FUNCTION(0x4, "csi_mclk"), /* MCLK0 */
> + SUNXI_FUNCTION(0x5, "uart0"), /* TX */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 12)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 13),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x3, "ncsi"), /* D1 */
> + SUNXI_FUNCTION(0x4, "csi_mclk"), /* MCLK1 */
> + SUNXI_FUNCTION(0x5, "uart0"), /* RX */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 13)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 14),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x3, "ncsi"), /* D2 */
> + SUNXI_FUNCTION(0x4, "i2c1"), /* SCK */
> + SUNXI_FUNCTION(0x5, "clk"), /* FANOUT0 */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 14)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 15),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x3, "ncsi"), /* D3 */
> + SUNXI_FUNCTION(0x4, "i2c1"), /* SDA */
> + SUNXI_FUNCTION(0x5, "clk"), /* FANOUT1 */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 15)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 16),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x3, "ncsi"), /* D4 */
> + SUNXI_FUNCTION(0x4, "i2c0"), /* SCK */
> + SUNXI_FUNCTION(0x5, "uart3"), /* TX */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 16)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 17),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x3, "ncsi"), /* D5 */
> + SUNXI_FUNCTION(0x4, "i2c0"), /* SDA */
> + SUNXI_FUNCTION(0x5, "uart3"), /* RX */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 17)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 18),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x3, "ncsi"), /* D6 */
> + SUNXI_FUNCTION(0x4, "wiegand"), /* D0 */
> + SUNXI_FUNCTION(0x5, "uart3"), /* RTS */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 18)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 19),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x3, "ncsi"), /* D7 */
> + SUNXI_FUNCTION(0x4, "wiegand"), /* D1 */
> + SUNXI_FUNCTION(0x5, "uart3"), /* CTS */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 19)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 20),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x3, "ncsi"), /* MCLK */
> + SUNXI_FUNCTION(0x4, "csi"), /* SM_VS */
> + SUNXI_FUNCTION(0x5, "tcon"), /* TRIG */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 20)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 21),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x3, "ncsi"), /* PCLK */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 21)),
> + /* bank C */
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 0),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "spif"), /* CLK */
> + SUNXI_FUNCTION(0x3, "sdc2"), /* CLK */
> + SUNXI_FUNCTION(0x4, "spi0"), /* CLK */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 0)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 1),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "spif"), /* CS0 */
> + SUNXI_FUNCTION(0x3, "sdc2"), /* CMD */
> + SUNXI_FUNCTION(0x4, "spi0"), /* CS0 */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 1)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 2),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "spif"), /* MOSI_IO0 */
> + SUNXI_FUNCTION(0x3, "sdc2"), /* D2 */
> + SUNXI_FUNCTION(0x4, "spi0"), /* MOSI */
> + SUNXI_FUNCTION(0x5, "boot_sel0"), /* SEL0 */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 2)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 3),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "spif"), /* MOSI_IO1 */
> + SUNXI_FUNCTION(0x3, "sdc2"), /* D1 */
> + SUNXI_FUNCTION(0x4, "spi0"), /* MISO */
> + SUNXI_FUNCTION(0x5, "boot_sel1"), /* SEL1 */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 3)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 4),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "spif"), /* WP_IO2 */
> + SUNXI_FUNCTION(0x3, "sdc2"), /* D0 */
> + SUNXI_FUNCTION(0x4, "spi0"), /* WP */
> + SUNXI_FUNCTION(0x5, "pwm4"),
> + SUNXI_FUNCTION(0x6, "i2c1"), /* SCK */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 4)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 5),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "spif"), /* HOLD_IO3 */
> + SUNXI_FUNCTION(0x3, "sdc2"), /* D3 */
> + SUNXI_FUNCTION(0x4, "spi0"), /* HOLD */
> + SUNXI_FUNCTION(0x5, "pwm4"),
> + SUNXI_FUNCTION(0x6, "i2c1"), /* SDA */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 5)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 6),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "spif"), /* IO4 */
> + SUNXI_FUNCTION(0x3, "sdc2"), /* D4 */
> + SUNXI_FUNCTION(0x4, "spi0"), /* CSI */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 6)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 7),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "spif"), /* IO5 */
> + SUNXI_FUNCTION(0x3, "sdc2"), /* D5 */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 7)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 8),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "spif"), /* IO6 */
> + SUNXI_FUNCTION(0x3, "sdc2"), /* D6 */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 8)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 9),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "spif"), /* IO7 */
> + SUNXI_FUNCTION(0x3, "sdc2"), /* D7 */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 9)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 10),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "spif"), /* DQS */
> + SUNXI_FUNCTION(0x3, "sdc2"), /* DS */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 10)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 11),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x3, "sdc2"), /* RTS */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 11)),
> + /* bank D */
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 0),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "lcd"), /* D2 */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 0)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 1),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "lcd"), /* D3 */
> + SUNXI_FUNCTION(0x3, "pwm0"),
> + SUNXI_FUNCTION(0x4, "emac"), /* RXD1 */
> + SUNXI_FUNCTION(0x5, "dsi"), /* D0N */
> + SUNXI_FUNCTION(0x6, "spi1"), /* CS0/CSX */
> + SUNXI_FUNCTION(0x7, "emac"), /* TXD0 */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 1)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 2),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "lcd"), /* D4 */
> + SUNXI_FUNCTION(0x3, "pwm1"),
> + SUNXI_FUNCTION(0x4, "emac"), /* RXD0 */
> + SUNXI_FUNCTION(0x5, "dsi"), /* D1P */
> + SUNXI_FUNCTION(0x6, "spi1"), /* CLK/SCLK */
> + SUNXI_FUNCTION(0x7, "emac"), /* TXD1 */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 2)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 3),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "lcd"), /* D5 */
> + SUNXI_FUNCTION(0x3, "pwm2"),
> + SUNXI_FUNCTION(0x4, "emac"), /* CRS_DV */
> + SUNXI_FUNCTION(0x5, "dsi"), /* D1N */
> + SUNXI_FUNCTION(0x6, "spi1"), /* MOSI/SDO */
> + SUNXI_FUNCTION(0x7, "emac"), /* RXER */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 3)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 4),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "lcd"), /* D6 */
> + SUNXI_FUNCTION(0x3, "pwm3"),
> + SUNXI_FUNCTION(0x4, "emac"), /* RXER */
> + SUNXI_FUNCTION(0x5, "dsi"), /* D1P */
> + SUNXI_FUNCTION(0x6, "spi1"), /* MISO/SDI/TE/DCX */
> + SUNXI_FUNCTION(0x7, "emac"), /* CRS_DV */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 4)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 5),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "lcd"), /* D7 */
> + SUNXI_FUNCTION(0x3, "pwm4"),
> + SUNXI_FUNCTION(0x4, "emac"), /* TXD1 */
> + SUNXI_FUNCTION(0x5, "dsi"), /* CKN */
> + SUNXI_FUNCTION(0x6, "spi1"), /* HOLD/DCX/WRX */
> + SUNXI_FUNCTION(0x7, "emac"), /* RXD1 */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 5)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 6),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "lcd"), /* D10 */
> + SUNXI_FUNCTION(0x3, "pwm5"),
> + SUNXI_FUNCTION(0x4, "emac"), /* TXD0 */
> + SUNXI_FUNCTION(0x5, "dsi"), /* CKP */
> + SUNXI_FUNCTION(0x6, "spi1"), /* WP/TE */
> + SUNXI_FUNCTION(0x7, "emac"), /* RXD */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 6)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 7),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "lcd"), /* D11 */
> + SUNXI_FUNCTION(0x3, "pwm6"),
> + SUNXI_FUNCTION(0x4, "emac"), /* TXCK */
> + SUNXI_FUNCTION(0x5, "dsi"), /* D2N */
> + SUNXI_FUNCTION(0x6, "spi1"), /* CS1 */
> + SUNXI_FUNCTION(0x7, "emac"), /* MDC */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 7)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 8),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "lcd"), /* D12 */
> + SUNXI_FUNCTION(0x3, "pwm7"),
> + SUNXI_FUNCTION(0x4, "emac"), /* TXEN */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 8)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 9),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "lcd"), /* D13 */
> + SUNXI_FUNCTION(0x3, "pwm8"),
> + SUNXI_FUNCTION(0x5, "dsi"), /* D2P */
> + SUNXI_FUNCTION(0x7, "emac"), /* MDIO */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 9)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 10),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "lcd"), /* D14 */
> + SUNXI_FUNCTION(0x3, "i2s1"), /* MCLK */
> + SUNXI_FUNCTION(0x5, "dsi"), /* D3N */
> + SUNXI_FUNCTION(0x7, "emac"), /* TXEN */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 10)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 11),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "lcd"), /* D15 */
> + SUNXI_FUNCTION(0x3, "i2s1"), /* BCLK */
> + SUNXI_FUNCTION(0x5, "dsi"), /* D3P */
> + SUNXI_FUNCTION(0x7, "emac"), /* TXCKk */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 11)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 12),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "lcd"), /* D18 */
> + SUNXI_FUNCTION(0x3, "i2s1"), /* LCLK */
> + SUNXI_FUNCTION(0x5, "dmic"), /* DATA3 */
> + SUNXI_FUNCTION(0x7, "pwm11"),
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 12)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 13),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "lcd"), /* D19 */
> + SUNXI_FUNCTION(0x3, "i2s1"), /* DOUT0 */
> + SUNXI_FUNCTION(0x5, "dmic"), /* DATA2 */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 13)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 14),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "lcd"), /* D20 */
> + SUNXI_FUNCTION(0x3, "i2s1"), /* DOUT1 */
> + SUNXI_FUNCTION(0x4, "i2s1"), /* DIN1 */
> + SUNXI_FUNCTION(0x5, "dmic"), /* DATA1 */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 14)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 15),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "lcd"), /* D21 */
> + SUNXI_FUNCTION(0x3, "i2s1"), /* DOUT2 */
> + SUNXI_FUNCTION(0x4, "i2s1"), /* DIN2 */
> + SUNXI_FUNCTION(0x5, "dmic"), /* DATA0 */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 15)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 16),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "lcd"), /* D22 */
> + SUNXI_FUNCTION(0x3, "i2s1"), /* DOUT3 */
> + SUNXI_FUNCTION(0x4, "i2s1"), /* DIN3 */
> + SUNXI_FUNCTION(0x5, "dmic"), /* CLK */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 16)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 17),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "lcd"), /* D23 */
> + SUNXI_FUNCTION(0x3, "i2s1"), /* DIN0 */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 17)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 18),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "lcd"), /* CLK */
> + SUNXI_FUNCTION(0x4, "emac"), /* EPHY_25M */
> + SUNXI_FUNCTION(0x5, "spi2"), /* CLK */
> + SUNXI_FUNCTION(0x6, "i2c3"), /* SCK */
> + SUNXI_FUNCTION(0x7, "uart2"), /* TX */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 18)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 19),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "lcd"), /* DE */
> + SUNXI_FUNCTION(0x3, "pwm9"),
> + SUNXI_FUNCTION(0x4, "tcon"), /* TRIG */
> + SUNXI_FUNCTION(0x5, "spi2"), /* MOSI */
> + SUNXI_FUNCTION(0x6, "i2c3"), /* SDA */
> + SUNXI_FUNCTION(0x7, "uart2"), /* RX */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 19)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 20),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "lcd"), /* HSYNC */
> + SUNXI_FUNCTION(0x3, "pwm10"),
> + SUNXI_FUNCTION(0x4, "emac"), /* MDC */
> + SUNXI_FUNCTION(0x5, "spi2"), /* MISO */
> + SUNXI_FUNCTION(0x6, "i2c2"), /* SCK */
> + SUNXI_FUNCTION(0x7, "uart2"), /* RTS */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 20)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 21),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "lcd"), /* VSYNC */
> + SUNXI_FUNCTION(0x4, "emac"), /* MDIO */
> + SUNXI_FUNCTION(0x5, "spi2"), /* CS0 */
> + SUNXI_FUNCTION(0x6, "i2c2"), /* SDA */
> + SUNXI_FUNCTION(0x7, "uart2"), /* CTS */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 21)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 22),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "pwm9"),
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 22)),
> + /* bank E */
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 0),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "ncsi"), /* PCLK */
> + SUNXI_FUNCTION(0x3, "emac"), /* RXD/RXD1 */
> + SUNXI_FUNCTION(0x4, "i2s1"), /* MCLK */
> + SUNXI_FUNCTION(0x5, "pwm0"),
> + SUNXI_FUNCTION(0x6, "sdc1"), /* CLK */
> + SUNXI_FUNCTION(0x7, "uart3"), /* TX */
> + SUNXI_FUNCTION(0x8, "i2c3"), /* SCK */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 0)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 1),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "ncsi"), /* MCLK */
> + SUNXI_FUNCTION(0x3, "emac"), /* RXCK/TXCK */
> + SUNXI_FUNCTION(0x4, "i2s1"), /* BCLK */
> + SUNXI_FUNCTION(0x5, "pwm1"),
> + SUNXI_FUNCTION(0x6, "sdc1"), /* CMD */
> + SUNXI_FUNCTION(0x7, "uart3"), /* RX */
> + SUNXI_FUNCTION(0x8, "i2c3"), /* SDA */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 1)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 2),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "ncsi"), /* HSYNC */
> + SUNXI_FUNCTION(0x3, "emac"), /* RXCTL/CRS_DV */
> + SUNXI_FUNCTION(0x4, "i2s1"), /* LCLK */
> + SUNXI_FUNCTION(0x5, "pwm2"),
> + SUNXI_FUNCTION(0x6, "sdc1"), /* D0 */
> + SUNXI_FUNCTION(0x7, "uart3"), /* CTS */
> + SUNXI_FUNCTION(0x8, "i2c1"), /* SCK */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 2)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 3),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "ncsi"), /* VSYNC */
> + SUNXI_FUNCTION(0x3, "emac"), /* RXD0 */
> + SUNXI_FUNCTION(0x4, "i2s1"), /* DIN0 */
> + SUNXI_FUNCTION(0x5, "pwm3"),
> + SUNXI_FUNCTION(0x6, "sdc1"), /* D1 */
> + SUNXI_FUNCTION(0x7, "uart3"), /* RTS */
> + SUNXI_FUNCTION(0x8, "i2c1"), /* SDA */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 3)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 4),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "ncsi"), /* D0 */
> + SUNXI_FUNCTION(0x3, "emac"), /* TXD0 */
> + SUNXI_FUNCTION(0x4, "i2s1"), /* DOUT0 */
> + SUNXI_FUNCTION(0x5, "pwm4"),
> + SUNXI_FUNCTION(0x6, "sdc1"), /* D2 */
> + SUNXI_FUNCTION(0x7, "i2c3"), /* SCK */
> + SUNXI_FUNCTION(0x8, "i2c0"), /* SCK */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 4)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 5),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "ncsi"), /* D1 */
> + SUNXI_FUNCTION(0x3, "emac"), /* TXD1 */
> + SUNXI_FUNCTION(0x5, "pwm5"),
> + SUNXI_FUNCTION(0x6, "sdc1"), /* D3 */
> + SUNXI_FUNCTION(0x7, "i2c3"), /* SDA */
> + SUNXI_FUNCTION(0x8, "i2c0"), /* SDA */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 5)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 6),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "ncsi"), /* D2 */
> + SUNXI_FUNCTION(0x3, "emac"), /* TXCTL/TXEN */
> + SUNXI_FUNCTION(0x4, "lcd"), /* D2 */
> + SUNXI_FUNCTION(0x5, "pwm6"),
> + SUNXI_FUNCTION(0x6, "uart1"), /* TX */
> + SUNXI_FUNCTION(0x8, "i2c4"), /* SCK */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 6)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 7),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "ncsi"), /* D3 */
> + SUNXI_FUNCTION(0x3, "emac"), /* CLKIN/RXER */
> + SUNXI_FUNCTION(0x4, "lcd"), /* D15 */
> + SUNXI_FUNCTION(0x5, "pwm7"),
> + SUNXI_FUNCTION(0x6, "uart1"), /* TX */
> + SUNXI_FUNCTION(0x7, "i2s1"), /* DOUT0 */
> + SUNXI_FUNCTION(0x8, "i2c4"), /* SDA */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 7)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 8),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "ncsi"), /* D4 */
> + SUNXI_FUNCTION(0x3, "emac"), /* MDC */
> + SUNXI_FUNCTION(0x4, "lcd"), /* D18 */
> + SUNXI_FUNCTION(0x5, "pwm8"),
> + SUNXI_FUNCTION(0x6, "wiegand"), /* D0 */
> + SUNXI_FUNCTION(0x7, "i2s1"), /* DIN0 */
> + SUNXI_FUNCTION(0x8, "i2c1"), /* SCK */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 8)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 9),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "ncsi"), /* D5 */
> + SUNXI_FUNCTION(0x3, "emac"), /* MDIO */
> + SUNXI_FUNCTION(0x4, "lcd"), /* D19 */
> + SUNXI_FUNCTION(0x5, "pwm9"),
> + SUNXI_FUNCTION(0x6, "wiegand"), /* D1 */
> + SUNXI_FUNCTION(0x7, "i2s1"), /* LRCK */
> + SUNXI_FUNCTION(0x8, "i2c1"), /* SDA */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 9)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 10),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "ncsi"), /* D6 */
> + SUNXI_FUNCTION(0x3, "emac"), /* EPHY_25M */
> + SUNXI_FUNCTION(0x4, "lcd"), /* D20 */
> + SUNXI_FUNCTION(0x5, "pwm10"),
> + SUNXI_FUNCTION(0x6, "uart2"), /* RTS */
> + SUNXI_FUNCTION(0x7, "i2s1"), /* BCLK */
> + SUNXI_FUNCTION(0x8, "wiegand"), /* D0 */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 10)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 11),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "ncsi"), /* D7 */
> + SUNXI_FUNCTION(0x3, "emac"), /* RXD3 */
> + SUNXI_FUNCTION(0x4, "lcd"), /* D21 */
> + SUNXI_FUNCTION(0x5, "csi"), /* SM_VS */
> + SUNXI_FUNCTION(0x6, "uart2"), /* CTS */
> + SUNXI_FUNCTION(0x7, "i2s1"), /* MCLK */
> + SUNXI_FUNCTION(0x8, "wiegand"), /* D1 */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 11)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 12),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "ncsi"), /* D8 */
> + SUNXI_FUNCTION(0x3, "emac"), /* RXD2 */
> + SUNXI_FUNCTION(0x4, "lcd"), /* D22 */
> + SUNXI_FUNCTION(0x5, "csi"), /* MCLK0 */
> + SUNXI_FUNCTION(0x6, "uart2"), /* TX */
> + SUNXI_FUNCTION(0x7, "uart3"), /* TX */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 12)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 13),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "ncsi"), /* D9 */
> + SUNXI_FUNCTION(0x3, "emac"), /* RXCK */
> + SUNXI_FUNCTION(0x4, "lcd"), /* D23 */
> + SUNXI_FUNCTION(0x5, "csi"), /* MCLK1 */
> + SUNXI_FUNCTION(0x6, "uart2"), /* RX */
> + SUNXI_FUNCTION(0x7, "uart3"), /* RX */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 13)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 14),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "ncsi"), /* D10 */
> + SUNXI_FUNCTION(0x3, "emac"), /* TXD3 */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 14)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 15),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "ncsi"), /* D11 */
> + SUNXI_FUNCTION(0x3, "emac"), /* TXD2 */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 15)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 16),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "i2c0"), /* SCK */
> + SUNXI_FUNCTION(0x3, "i2c4"), /* SCK */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 16)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 17),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "i2c0"), /* SDA */
> + SUNXI_FUNCTION(0x3, "i2c4"), /* SDA */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 17)),
> + /* bank F */
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 0),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "sdc0"), /* D1 */
> + SUNXI_FUNCTION(0x3, "jtag"), /* MS */
> + SUNXI_FUNCTION(0x4, "spi0"), /* CLK */
> + SUNXI_FUNCTION(0x5, "spi2"), /* CLK */
> + SUNXI_FUNCTION(0x6, "r_jtag"), /* MS */
> + SUNXI_FUNCTION(0x7, "cpu"), /* BIST0 */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 0)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 1),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "sdc0"), /* D0 */
> + SUNXI_FUNCTION(0x3, "jtag"), /* DI */
> + SUNXI_FUNCTION(0x4, "spi0"), /* MOSI */
> + SUNXI_FUNCTION(0x5, "spi2"), /* MOSI */
> + SUNXI_FUNCTION(0x6, "r_jtag"), /* DI */
> + SUNXI_FUNCTION(0x7, "cpu"), /* BIST1 */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 1)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 2),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "sdc0"), /* CLK */
> + SUNXI_FUNCTION(0x3, "uart0"), /* TX */
> + SUNXI_FUNCTION(0x4, "spi0"), /* MISO */
> + SUNXI_FUNCTION(0x5, "spi2"), /* MISO */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 2)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 3),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "sdc0"), /* CMD */
> + SUNXI_FUNCTION(0x3, "jtag"), /* DO */
> + SUNXI_FUNCTION(0x4, "spi0"), /* CSO */
> + SUNXI_FUNCTION(0x5, "spi2"), /* CS0 */
> + SUNXI_FUNCTION(0x6, "r_jtag"), /* DO */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 3)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 4),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "sdc0"), /* D3 */
> + SUNXI_FUNCTION(0x3, "uart0"), /* RX */
> + SUNXI_FUNCTION(0x4, "spi0"), /* CS1 */
> + SUNXI_FUNCTION(0x5, "spi2"), /* CS1 */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 4)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 5),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "sdc0"), /* D2 */
> + SUNXI_FUNCTION(0x3, "jtag"), /* CK */
> + SUNXI_FUNCTION(0x6, "r_jtag"), /* CK */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 5)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 6),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "dbg_clk"),
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 6)),
> + /* bank G */
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 0),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "sdc1"), /* CLK */
> + SUNXI_FUNCTION(0x3, "lcd"), /* D0 */
> + SUNXI_FUNCTION(0x4, "uart3"), /* TX */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 0)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 1),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "sdc1"), /* CMD */
> + SUNXI_FUNCTION(0x3, "lcd"), /* D1 */
> + SUNXI_FUNCTION(0x4, "uart3"), /* RX */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 1)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 2),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "sdc1"), /* D0 */
> + SUNXI_FUNCTION(0x3, "lcd"), /* D8 */
> + SUNXI_FUNCTION(0x4, "uart3"), /* CTS */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 2)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 3),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "sdc1"), /* D1 */
> + SUNXI_FUNCTION(0x3, "lcd"), /* D9 */
> + SUNXI_FUNCTION(0x4, "uart3"), /* RTS */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 3)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 4),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "sdc1"), /* D2 */
> + SUNXI_FUNCTION(0x3, "lcd"), /* D16 */
> + SUNXI_FUNCTION(0x4, "uart1"), /* RTS */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 4)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 5),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "sdc1"), /* D3 */
> + SUNXI_FUNCTION(0x3, "lcd"), /* D17 */
> + SUNXI_FUNCTION(0x4, "uart1"), /* CTS */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 5)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 6),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "i2c4"), /* SCK */
> + SUNXI_FUNCTION(0x3, "clk"), /* FANOUT0 */
> + SUNXI_FUNCTION(0x4, "uart1"), /* TX */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 6)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 7),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "i2c4"), /* SDA */
> + SUNXI_FUNCTION(0x3, "clk"), /* FANOUT1 */
> + SUNXI_FUNCTION(0x4, "uart1"), /* RX */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 7)),
> + /* bank H */
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 0),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "pwm0"),
> + SUNXI_FUNCTION(0x3, "i2s0"), /* MCLK */
> + SUNXI_FUNCTION(0x4, "spi1"), /* CLK */
> + SUNXI_FUNCTION(0x5, "uart3"), /* TX */
> + SUNXI_FUNCTION(0x6, "dmic"), /* DATA3 */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 0)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 1),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "pwm1"),
> + SUNXI_FUNCTION(0x3, "i2s0"), /* BCLK */
> + SUNXI_FUNCTION(0x4, "spi1"), /* MOSI */
> + SUNXI_FUNCTION(0x5, "uart3"), /* RX */
> + SUNXI_FUNCTION(0x6, "dmic"), /* DATA2 */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 1)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 2),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "pwm2"),
> + SUNXI_FUNCTION(0x3, "i2s0"), /* LRCK */
> + SUNXI_FUNCTION(0x4, "spi1"), /* MISO */
> + SUNXI_FUNCTION(0x5, "uart3"), /* CTS */
> + SUNXI_FUNCTION(0x6, "dmic"), /* DATA1 */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 2)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 3),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "pwm3"),
> + SUNXI_FUNCTION(0x3, "i2s0"), /* DOUT0 */
> + SUNXI_FUNCTION(0x4, "spi1"), /* CS0 */
> + SUNXI_FUNCTION(0x5, "uart3"), /* RTS */
> + SUNXI_FUNCTION(0x6, "dmic"), /* DATA0 */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 3)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 4),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "pwm4"),
> + SUNXI_FUNCTION(0x3, "i2s0"), /* DIN0 */
> + SUNXI_FUNCTION(0x4, "spi1"), /* CS1 */
> + SUNXI_FUNCTION(0x5, "clk"), /* FANOUT2 */
> + SUNXI_FUNCTION(0x6, "dmic"), /* CLK */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 4)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 5),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "pwm5"),
> + SUNXI_FUNCTION(0x3, "emac"), /* RXD1 */
> + SUNXI_FUNCTION(0x4, "i2c2"), /* SCK */
> + SUNXI_FUNCTION(0x5, "uart2"), /* TX */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 5)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 6),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "pwm6"),
> + SUNXI_FUNCTION(0x3, "emac"), /* RXD0 */
> + SUNXI_FUNCTION(0x4, "i2c2"), /* SDA */
> + SUNXI_FUNCTION(0x5, "uart2"), /* RX */
> + SUNXI_FUNCTION(0x6, "i2s1"), /* MCLK */
> + SUNXI_FUNCTION(0x7, "dmic"), /* DATA3 */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 6)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 7),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "pwm7"),
> + SUNXI_FUNCTION(0x3, "emac"), /* CRS_DV */
> + SUNXI_FUNCTION(0x4, "uart0"), /* TX */
> + SUNXI_FUNCTION(0x5, "uart2"), /* RTS */
> + SUNXI_FUNCTION(0x6, "i2s1"), /* BCLK */
> + SUNXI_FUNCTION(0x7, "dmic"), /* DATA2 */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 7)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 8),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "pwm8"),
> + SUNXI_FUNCTION(0x3, "emac"), /* RXER */
> + SUNXI_FUNCTION(0x4, "uart0"), /* RX */
> + SUNXI_FUNCTION(0x5, "uart2"), /* CTS */
> + SUNXI_FUNCTION(0x6, "i2s1"), /* LRCK */
> + SUNXI_FUNCTION(0x7, "dmic"), /* DATA1 */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 8)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 9),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "pwm9"),
> + SUNXI_FUNCTION(0x3, "emac"), /* TXD1 */
> + SUNXI_FUNCTION(0x4, "i2c3"), /* SCK */
> + SUNXI_FUNCTION(0x5, "uart0"), /* TX */
> + SUNXI_FUNCTION(0x6, "i2s1"), /* DIN0 */
> + SUNXI_FUNCTION(0x7, "dmic"), /* DATA0 */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 9)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 10),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "pwm10"),
> + SUNXI_FUNCTION(0x3, "emac"), /* TXD0 */
> + SUNXI_FUNCTION(0x4, "i2c3"), /* SDA */
> + SUNXI_FUNCTION(0x5, "uart0"), /* RX */
> + SUNXI_FUNCTION(0x6, "i2s1"), /* DOUT0 */
> + SUNXI_FUNCTION(0x7, "dmic"), /* CLK */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 10)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 11),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "jtag"), /* MS */
> + SUNXI_FUNCTION(0x3, "emac"), /* TXCK */
> + SUNXI_FUNCTION(0x4, "r_jtag"), /* MS */
> + SUNXI_FUNCTION(0x5, "i2c2"), /* SCK */
> + SUNXI_FUNCTION(0x6, "spi3"), /* CLK */
> + SUNXI_FUNCTION(0x7, "clk"), /* FANOUT0 */
> + SUNXI_FUNCTION(0x8, "pwm4"),
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 11)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 12),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "jtag"), /* CK */
> + SUNXI_FUNCTION(0x3, "emac"), /* TXEN */
> + SUNXI_FUNCTION(0x4, "r_jtag"), /* CK */
> + SUNXI_FUNCTION(0x5, "i2c2"), /* SDA */
> + SUNXI_FUNCTION(0x6, "spi3"), /* MOSI */
> + SUNXI_FUNCTION(0x7, "clk"), /* FANOUT1 */
> + SUNXI_FUNCTION(0x8, "pwm5"),
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 12)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 13),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "jtag"), /* DO */
> + SUNXI_FUNCTION(0x3, "emac"), /* MDC */
> + SUNXI_FUNCTION(0x4, "r_jtag"), /* DO */
> + SUNXI_FUNCTION(0x5, "i2c3"), /* SCK */
> + SUNXI_FUNCTION(0x6, "spi3"), /* MISO */
> + SUNXI_FUNCTION(0x7, "wiegand"), /* D0 */
> + SUNXI_FUNCTION(0x8, "pwm6"),
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 13)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 14),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "jtag"), /* DI */
> + SUNXI_FUNCTION(0x3, "emac"), /* MDIO */
> + SUNXI_FUNCTION(0x4, "r_jtag"), /* DI */
> + SUNXI_FUNCTION(0x5, "i2c3"), /* SDA */
> + SUNXI_FUNCTION(0x6, "spi3"), /* CS0 */
> + SUNXI_FUNCTION(0x7, "wiegand"), /* D1 */
> + SUNXI_FUNCTION(0x8, "pwm7"),
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 14)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 15),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "clk"), /* FANOUT2 */
> + SUNXI_FUNCTION(0x3, "ephy_25m"), /* EPHY_25M */
> + SUNXI_FUNCTION(0x6, "spi3"), /* CS1 */
> + SUNXI_FUNCTION(0x8, "pwm8"),
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 15)),
> + /* bank I */
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 0),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "csi"), /* MCLK0 */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 7, 0)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 1),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "csi"), /* SM_HS */
> + SUNXI_FUNCTION(0x4, "spi2"), /* CLK */
> + SUNXI_FUNCTION(0x5, "i2c1"), /* SCK */
> + SUNXI_FUNCTION(0x6, "i2c4"), /* SCK */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 7, 1)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 2),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x2, "csi"), /* SM_VS */
> + SUNXI_FUNCTION(0x3, "tcon"), /* TRIG */
> + SUNXI_FUNCTION(0x4, "spi2"), /* MOSI */
> + SUNXI_FUNCTION(0x5, "i2c1"), /* SDA */
> + SUNXI_FUNCTION(0x6, "i2c4"), /* SDA */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 7, 2)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 3),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x4, "spi2"), /* MISO */
> + SUNXI_FUNCTION(0x5, "i2c0"), /* SCA */
> + SUNXI_FUNCTION(0x6, "i2c3"), /* SCK */
> + SUNXI_FUNCTION(0x7, "clk"), /* FANOUT0 */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 7, 3)),
> + SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 4),
> + SUNXI_FUNCTION(0x0, "gpio_in"),
> + SUNXI_FUNCTION(0x1, "gpio_out"),
> + SUNXI_FUNCTION(0x4, "spi2"), /* CS0 */
> + SUNXI_FUNCTION(0x5, "i2c0"), /* SDA */
> + SUNXI_FUNCTION(0x6, "i2c3"), /* SDA */
> + SUNXI_FUNCTION(0x7, "clk"), /* FANOUT1 */
> + SUNXI_FUNCTION_IRQ_BANK(0xe, 7, 4)),
> +};
> +
> +static const unsigned int sun8i_v853_irq_bank_map[] = { 0, 2, 3, 4, 5, 6, 7, 8 };
> +
> +static const struct sunxi_pinctrl_desc sun8i_v853_pinctrl_data = {
> + .pins = sun8i_v853_pins,
> + .npins = ARRAY_SIZE(sun8i_v853_pins),
> + .pin_base = 0,
> + .irq_banks = ARRAY_SIZE(sun8i_v853_irq_bank_map),
> + .irq_bank_map = sun8i_v853_irq_bank_map,
> + .io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_CTL,
> +};
> +
> +static int sun8i_v853_pinctrl_probe(struct platform_device *pdev)
> +{
> + unsigned long variant = (unsigned long)of_device_get_match_data(&pdev->dev);
> +
> + return sunxi_pinctrl_init_with_variant(pdev, &sun8i_v853_pinctrl_data, variant);
> +}
> +
> +static const struct of_device_id sun8i_v853_pinctrl_match[] = {
> + {
> + .compatible = "allwinner,sun8i-v853-pinctrl",
> + .data = (void *)PINCTRL_SUN8I_V853
> + },
> + {}
> +};
> +
> +static struct platform_driver sun8i_v853_pinctrl_driver = {
> + .probe = sun8i_v853_pinctrl_probe,
> + .driver = {
> + .name = "sun8i-v853-pinctrl",
> + .of_match_table = sun8i_v853_pinctrl_match,
> + },
> +};
> +builtin_platform_driver(sun8i_v853_pinctrl_driver);
> diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.h b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
> index a87a2f944d60..f4b64f9156f1 100644
> --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.h
> +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
> @@ -94,6 +94,7 @@
> #define PINCTRL_SUN8I_V3S BIT(10)
> /* Variants below here have an updated register layout. */
> #define PINCTRL_SUN20I_D1 BIT(11)
> +#define PINCTRL_SUN8I_V853 BIT(12)
>
> #define PIO_POW_MOD_SEL_REG 0x340
> #define PIO_POW_MOD_CTL_REG 0x344
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH 03/12] pinctrl: sunxi: add driver for Allwinner V853.
2025-01-14 14:19 ` Andre Przywara
@ 2025-01-14 14:30 ` Andre Przywara
2025-01-15 10:23 ` Linus Walleij
1 sibling, 0 replies; 50+ messages in thread
From: Andre Przywara @ 2025-01-14 14:30 UTC (permalink / raw)
To: Andras Szemzo
Cc: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
Linus Walleij, Philipp Zabel, Maxime Ripard, Vinod Koul,
Kishon Vijay Abraham I, Ulf Hansson, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Uwe Kleine-König,
Florian Fainelli, linux-clk, devicetree, linux-arm-kernel,
linux-sunxi, linux-kernel, linux-phy, linux-gpio, linux-pm,
linux-riscv
On Tue, 14 Jan 2025 14:19:54 +0000
Andre Przywara <andre.przywara@arm.com> wrote:
Hi,
adding the actual references I hinted at ....
> On Fri, 10 Jan 2025 13:39:14 +0100
> Andras Szemzo <szemzo.andras@gmail.com> wrote:
>
> Hi,
>
> > The V853 family has multiple package variants, from BGA to QFN88.
> > The latter has co-packaged DRAM and fewer pins, and less features (pin muxes).
> > All family members can be supported by a single driver, as the available pins
> > with allowed muxes is the same across the devices.
>
> It depends a bit on the outcome of the discussion on the A523 pinctrl
> driver [1], but I think we should use the same approach here (and for
> every "new" Allwinner SoC coming up, really): put the pinmux value in the
> DT, and get rid of this entire table altogether:
> [1]
[1]
https://lore.kernel.org/linux-sunxi/20241111005750.13071-5-andre.przywara@arm.com/T/#u
> The SoC specific pinctrl driver would then be very small ([2]), so this
> pinctrl support patch here would actually become much smaller.
[2]
https://lore.kernel.org/linux-sunxi/20241111005750.13071-7-andre.przywara@arm.com/T/#u
Cheers,
Andre
>
> Just feel a bit sorry for you having created this table, in a tedious and
> eye-straining exercise - been there, done that ;-)
>
> Cheers,
> Andre
>
> > Signed-off-by: Andras Szemzo <szemzo.andras@gmail.com>
> > ---
> > drivers/pinctrl/sunxi/Kconfig | 5 +
> > drivers/pinctrl/sunxi/Makefile | 1 +
> > drivers/pinctrl/sunxi/pinctrl-sun8i-v853.c | 980 +++++++++++++++++++++
> > drivers/pinctrl/sunxi/pinctrl-sunxi.h | 1 +
> > 4 files changed, 987 insertions(+)
> > create mode 100644 drivers/pinctrl/sunxi/pinctrl-sun8i-v853.c
> >
> > diff --git a/drivers/pinctrl/sunxi/Kconfig b/drivers/pinctrl/sunxi/Kconfig
> > index a78fdbbdfc0c..df67310672ac 100644
> > --- a/drivers/pinctrl/sunxi/Kconfig
> > +++ b/drivers/pinctrl/sunxi/Kconfig
> > @@ -86,6 +86,11 @@ config PINCTRL_SUN20I_D1
> > default MACH_SUN8I || (RISCV && ARCH_SUNXI)
> > select PINCTRL_SUNXI
> >
> > +config PINCTRL_SUN8I_V853
> > + bool "Support for the Allwinner V853 PIO"
> > + default MACH_SUN8I
> > + select PINCTRL_SUNXI
> > +
> > config PINCTRL_SUN50I_A64
> > bool "Support for the Allwinner A64 PIO"
> > default ARM64 && ARCH_SUNXI
> > diff --git a/drivers/pinctrl/sunxi/Makefile b/drivers/pinctrl/sunxi/Makefile
> > index 2ff5a55927ad..2042276e85d6 100644
> > --- a/drivers/pinctrl/sunxi/Makefile
> > +++ b/drivers/pinctrl/sunxi/Makefile
> > @@ -28,3 +28,4 @@ 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
> > +obj-$(CONFIG_PINCTRL_SUN8I_V853) += pinctrl-sun8i-v853.o
> > diff --git a/drivers/pinctrl/sunxi/pinctrl-sun8i-v853.c b/drivers/pinctrl/sunxi/pinctrl-sun8i-v853.c
> > new file mode 100644
> > index 000000000000..62b84404bd14
> > --- /dev/null
> > +++ b/drivers/pinctrl/sunxi/pinctrl-sun8i-v853.c
> > @@ -0,0 +1,980 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * Allwinner V853 SoC pinctrl driver.
> > + *
> > + * Copyright (c) 2016-2021 weidonghui <weidonghui@allwinnertech.com>
> > + * Copyright (c) 2023 Andras Szemzo <szemzo.andras@gmail.com>
> > + */
> > +
> > +#include <linux/module.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/of.h>
> > +#include <linux/of_device.h>
> > +#include <linux/pinctrl/pinctrl.h>
> > +#include <linux/io.h>
> > +
> > +#include "pinctrl-sunxi.h"
> > +
> > +/* Pin banks are: A C D E F G H I */
> > +static const struct sunxi_desc_pin sun8i_v853_pins[] = {
> > +
> > + /* bank A */
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 0),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "csi"), /* CKOP */
> > + SUNXI_FUNCTION(0x3, "ncsi"), /* D8 */
> > + SUNXI_FUNCTION(0x5, "test"),
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 0)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 1),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "csi"), /* CKON */
> > + SUNXI_FUNCTION(0x3, "ncsi"), /* D9 */
> > + SUNXI_FUNCTION(0x5, "test"), /* test */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 1)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 2),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "csi"), /* D1N */
> > + SUNXI_FUNCTION(0x3, "ncsi"), /* D10 */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 2)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 3),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "csi"), /* D1P */
> > + SUNXI_FUNCTION(0x3, "ncsi"), /* D11 */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 3)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 4),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "csi"), /* D0P */
> > + SUNXI_FUNCTION(0x3, "ncsi"), /* D12 */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 4)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 5),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "csi"), /* D0N */
> > + SUNXI_FUNCTION(0x3, "ncsi"), /* D13 */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 5)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 6),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "csi"), /* D0N/D2N */
> > + SUNXI_FUNCTION(0x3, "ncsi"), /* D14 */
> > + SUNXI_FUNCTION(0x4, "i2c1"), /* SCK */
> > + SUNXI_FUNCTION(0x5, "pwm0"),
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 6)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 7),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "csi"), /* D0P/D2P */
> > + SUNXI_FUNCTION(0x3, "ncsi"), /* D15 */
> > + SUNXI_FUNCTION(0x4, "i2c1"), /* SDA */
> > + SUNXI_FUNCTION(0x5, "pwm1"),
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 7)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 8),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "csi"), /* D1N/D3N */
> > + SUNXI_FUNCTION(0x3, "i2c4"), /* SCK */
> > + SUNXI_FUNCTION(0x4, "i2c3"), /* SCK */
> > + SUNXI_FUNCTION(0x5, "pwm2"),
> > + SUNXI_FUNCTION(0x6, "uart2"), /* TX */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 8)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 9),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "csi"), /* D1P/D3P */
> > + SUNXI_FUNCTION(0x3, "i2c4"), /* SDA */
> > + SUNXI_FUNCTION(0x4, "i2c3"), /* SDA */
> > + SUNXI_FUNCTION(0x5, "pwm3"),
> > + SUNXI_FUNCTION(0x6, "uart2"), /* RX */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 9)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 10),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "csi"), /* CKON */
> > + SUNXI_FUNCTION(0x3, "ncsi"), /* HSYNC */
> > + SUNXI_FUNCTION(0x4, "csi_mclk"), /* MCLK0 */
> > + SUNXI_FUNCTION(0x5, "i2c0"), /* SCK */
> > + SUNXI_FUNCTION(0x6, "clk"), /* FANOUT0 */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 10)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 11),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "csi"), /* CKOP */
> > + SUNXI_FUNCTION(0x3, "ncsi"), /* VSYNC */
> > + SUNXI_FUNCTION(0x4, "csi_mclk"), /* MCLK1 */
> > + SUNXI_FUNCTION(0x5, "i2c0"), /* SDA */
> > + SUNXI_FUNCTION(0x6, "clk"), /* FANOUT1 */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 11)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 12),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x3, "ncsi"), /* D0 */
> > + SUNXI_FUNCTION(0x4, "csi_mclk"), /* MCLK0 */
> > + SUNXI_FUNCTION(0x5, "uart0"), /* TX */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 12)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 13),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x3, "ncsi"), /* D1 */
> > + SUNXI_FUNCTION(0x4, "csi_mclk"), /* MCLK1 */
> > + SUNXI_FUNCTION(0x5, "uart0"), /* RX */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 13)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 14),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x3, "ncsi"), /* D2 */
> > + SUNXI_FUNCTION(0x4, "i2c1"), /* SCK */
> > + SUNXI_FUNCTION(0x5, "clk"), /* FANOUT0 */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 14)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 15),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x3, "ncsi"), /* D3 */
> > + SUNXI_FUNCTION(0x4, "i2c1"), /* SDA */
> > + SUNXI_FUNCTION(0x5, "clk"), /* FANOUT1 */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 15)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 16),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x3, "ncsi"), /* D4 */
> > + SUNXI_FUNCTION(0x4, "i2c0"), /* SCK */
> > + SUNXI_FUNCTION(0x5, "uart3"), /* TX */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 16)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 17),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x3, "ncsi"), /* D5 */
> > + SUNXI_FUNCTION(0x4, "i2c0"), /* SDA */
> > + SUNXI_FUNCTION(0x5, "uart3"), /* RX */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 17)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 18),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x3, "ncsi"), /* D6 */
> > + SUNXI_FUNCTION(0x4, "wiegand"), /* D0 */
> > + SUNXI_FUNCTION(0x5, "uart3"), /* RTS */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 18)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 19),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x3, "ncsi"), /* D7 */
> > + SUNXI_FUNCTION(0x4, "wiegand"), /* D1 */
> > + SUNXI_FUNCTION(0x5, "uart3"), /* CTS */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 19)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 20),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x3, "ncsi"), /* MCLK */
> > + SUNXI_FUNCTION(0x4, "csi"), /* SM_VS */
> > + SUNXI_FUNCTION(0x5, "tcon"), /* TRIG */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 20)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 21),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x3, "ncsi"), /* PCLK */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 21)),
> > + /* bank C */
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 0),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "spif"), /* CLK */
> > + SUNXI_FUNCTION(0x3, "sdc2"), /* CLK */
> > + SUNXI_FUNCTION(0x4, "spi0"), /* CLK */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 0)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 1),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "spif"), /* CS0 */
> > + SUNXI_FUNCTION(0x3, "sdc2"), /* CMD */
> > + SUNXI_FUNCTION(0x4, "spi0"), /* CS0 */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 1)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 2),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "spif"), /* MOSI_IO0 */
> > + SUNXI_FUNCTION(0x3, "sdc2"), /* D2 */
> > + SUNXI_FUNCTION(0x4, "spi0"), /* MOSI */
> > + SUNXI_FUNCTION(0x5, "boot_sel0"), /* SEL0 */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 2)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 3),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "spif"), /* MOSI_IO1 */
> > + SUNXI_FUNCTION(0x3, "sdc2"), /* D1 */
> > + SUNXI_FUNCTION(0x4, "spi0"), /* MISO */
> > + SUNXI_FUNCTION(0x5, "boot_sel1"), /* SEL1 */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 3)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 4),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "spif"), /* WP_IO2 */
> > + SUNXI_FUNCTION(0x3, "sdc2"), /* D0 */
> > + SUNXI_FUNCTION(0x4, "spi0"), /* WP */
> > + SUNXI_FUNCTION(0x5, "pwm4"),
> > + SUNXI_FUNCTION(0x6, "i2c1"), /* SCK */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 4)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 5),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "spif"), /* HOLD_IO3 */
> > + SUNXI_FUNCTION(0x3, "sdc2"), /* D3 */
> > + SUNXI_FUNCTION(0x4, "spi0"), /* HOLD */
> > + SUNXI_FUNCTION(0x5, "pwm4"),
> > + SUNXI_FUNCTION(0x6, "i2c1"), /* SDA */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 5)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 6),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "spif"), /* IO4 */
> > + SUNXI_FUNCTION(0x3, "sdc2"), /* D4 */
> > + SUNXI_FUNCTION(0x4, "spi0"), /* CSI */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 6)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 7),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "spif"), /* IO5 */
> > + SUNXI_FUNCTION(0x3, "sdc2"), /* D5 */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 7)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 8),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "spif"), /* IO6 */
> > + SUNXI_FUNCTION(0x3, "sdc2"), /* D6 */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 8)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 9),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "spif"), /* IO7 */
> > + SUNXI_FUNCTION(0x3, "sdc2"), /* D7 */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 9)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 10),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "spif"), /* DQS */
> > + SUNXI_FUNCTION(0x3, "sdc2"), /* DS */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 10)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 11),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x3, "sdc2"), /* RTS */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 11)),
> > + /* bank D */
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 0),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "lcd"), /* D2 */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 0)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 1),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "lcd"), /* D3 */
> > + SUNXI_FUNCTION(0x3, "pwm0"),
> > + SUNXI_FUNCTION(0x4, "emac"), /* RXD1 */
> > + SUNXI_FUNCTION(0x5, "dsi"), /* D0N */
> > + SUNXI_FUNCTION(0x6, "spi1"), /* CS0/CSX */
> > + SUNXI_FUNCTION(0x7, "emac"), /* TXD0 */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 1)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 2),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "lcd"), /* D4 */
> > + SUNXI_FUNCTION(0x3, "pwm1"),
> > + SUNXI_FUNCTION(0x4, "emac"), /* RXD0 */
> > + SUNXI_FUNCTION(0x5, "dsi"), /* D1P */
> > + SUNXI_FUNCTION(0x6, "spi1"), /* CLK/SCLK */
> > + SUNXI_FUNCTION(0x7, "emac"), /* TXD1 */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 2)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 3),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "lcd"), /* D5 */
> > + SUNXI_FUNCTION(0x3, "pwm2"),
> > + SUNXI_FUNCTION(0x4, "emac"), /* CRS_DV */
> > + SUNXI_FUNCTION(0x5, "dsi"), /* D1N */
> > + SUNXI_FUNCTION(0x6, "spi1"), /* MOSI/SDO */
> > + SUNXI_FUNCTION(0x7, "emac"), /* RXER */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 3)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 4),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "lcd"), /* D6 */
> > + SUNXI_FUNCTION(0x3, "pwm3"),
> > + SUNXI_FUNCTION(0x4, "emac"), /* RXER */
> > + SUNXI_FUNCTION(0x5, "dsi"), /* D1P */
> > + SUNXI_FUNCTION(0x6, "spi1"), /* MISO/SDI/TE/DCX */
> > + SUNXI_FUNCTION(0x7, "emac"), /* CRS_DV */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 4)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 5),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "lcd"), /* D7 */
> > + SUNXI_FUNCTION(0x3, "pwm4"),
> > + SUNXI_FUNCTION(0x4, "emac"), /* TXD1 */
> > + SUNXI_FUNCTION(0x5, "dsi"), /* CKN */
> > + SUNXI_FUNCTION(0x6, "spi1"), /* HOLD/DCX/WRX */
> > + SUNXI_FUNCTION(0x7, "emac"), /* RXD1 */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 5)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 6),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "lcd"), /* D10 */
> > + SUNXI_FUNCTION(0x3, "pwm5"),
> > + SUNXI_FUNCTION(0x4, "emac"), /* TXD0 */
> > + SUNXI_FUNCTION(0x5, "dsi"), /* CKP */
> > + SUNXI_FUNCTION(0x6, "spi1"), /* WP/TE */
> > + SUNXI_FUNCTION(0x7, "emac"), /* RXD */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 6)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 7),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "lcd"), /* D11 */
> > + SUNXI_FUNCTION(0x3, "pwm6"),
> > + SUNXI_FUNCTION(0x4, "emac"), /* TXCK */
> > + SUNXI_FUNCTION(0x5, "dsi"), /* D2N */
> > + SUNXI_FUNCTION(0x6, "spi1"), /* CS1 */
> > + SUNXI_FUNCTION(0x7, "emac"), /* MDC */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 7)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 8),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "lcd"), /* D12 */
> > + SUNXI_FUNCTION(0x3, "pwm7"),
> > + SUNXI_FUNCTION(0x4, "emac"), /* TXEN */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 8)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 9),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "lcd"), /* D13 */
> > + SUNXI_FUNCTION(0x3, "pwm8"),
> > + SUNXI_FUNCTION(0x5, "dsi"), /* D2P */
> > + SUNXI_FUNCTION(0x7, "emac"), /* MDIO */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 9)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 10),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "lcd"), /* D14 */
> > + SUNXI_FUNCTION(0x3, "i2s1"), /* MCLK */
> > + SUNXI_FUNCTION(0x5, "dsi"), /* D3N */
> > + SUNXI_FUNCTION(0x7, "emac"), /* TXEN */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 10)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 11),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "lcd"), /* D15 */
> > + SUNXI_FUNCTION(0x3, "i2s1"), /* BCLK */
> > + SUNXI_FUNCTION(0x5, "dsi"), /* D3P */
> > + SUNXI_FUNCTION(0x7, "emac"), /* TXCKk */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 11)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 12),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "lcd"), /* D18 */
> > + SUNXI_FUNCTION(0x3, "i2s1"), /* LCLK */
> > + SUNXI_FUNCTION(0x5, "dmic"), /* DATA3 */
> > + SUNXI_FUNCTION(0x7, "pwm11"),
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 12)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 13),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "lcd"), /* D19 */
> > + SUNXI_FUNCTION(0x3, "i2s1"), /* DOUT0 */
> > + SUNXI_FUNCTION(0x5, "dmic"), /* DATA2 */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 13)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 14),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "lcd"), /* D20 */
> > + SUNXI_FUNCTION(0x3, "i2s1"), /* DOUT1 */
> > + SUNXI_FUNCTION(0x4, "i2s1"), /* DIN1 */
> > + SUNXI_FUNCTION(0x5, "dmic"), /* DATA1 */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 14)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 15),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "lcd"), /* D21 */
> > + SUNXI_FUNCTION(0x3, "i2s1"), /* DOUT2 */
> > + SUNXI_FUNCTION(0x4, "i2s1"), /* DIN2 */
> > + SUNXI_FUNCTION(0x5, "dmic"), /* DATA0 */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 15)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 16),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "lcd"), /* D22 */
> > + SUNXI_FUNCTION(0x3, "i2s1"), /* DOUT3 */
> > + SUNXI_FUNCTION(0x4, "i2s1"), /* DIN3 */
> > + SUNXI_FUNCTION(0x5, "dmic"), /* CLK */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 16)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 17),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "lcd"), /* D23 */
> > + SUNXI_FUNCTION(0x3, "i2s1"), /* DIN0 */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 17)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 18),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "lcd"), /* CLK */
> > + SUNXI_FUNCTION(0x4, "emac"), /* EPHY_25M */
> > + SUNXI_FUNCTION(0x5, "spi2"), /* CLK */
> > + SUNXI_FUNCTION(0x6, "i2c3"), /* SCK */
> > + SUNXI_FUNCTION(0x7, "uart2"), /* TX */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 18)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 19),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "lcd"), /* DE */
> > + SUNXI_FUNCTION(0x3, "pwm9"),
> > + SUNXI_FUNCTION(0x4, "tcon"), /* TRIG */
> > + SUNXI_FUNCTION(0x5, "spi2"), /* MOSI */
> > + SUNXI_FUNCTION(0x6, "i2c3"), /* SDA */
> > + SUNXI_FUNCTION(0x7, "uart2"), /* RX */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 19)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 20),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "lcd"), /* HSYNC */
> > + SUNXI_FUNCTION(0x3, "pwm10"),
> > + SUNXI_FUNCTION(0x4, "emac"), /* MDC */
> > + SUNXI_FUNCTION(0x5, "spi2"), /* MISO */
> > + SUNXI_FUNCTION(0x6, "i2c2"), /* SCK */
> > + SUNXI_FUNCTION(0x7, "uart2"), /* RTS */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 20)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 21),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "lcd"), /* VSYNC */
> > + SUNXI_FUNCTION(0x4, "emac"), /* MDIO */
> > + SUNXI_FUNCTION(0x5, "spi2"), /* CS0 */
> > + SUNXI_FUNCTION(0x6, "i2c2"), /* SDA */
> > + SUNXI_FUNCTION(0x7, "uart2"), /* CTS */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 21)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 22),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "pwm9"),
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 22)),
> > + /* bank E */
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 0),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "ncsi"), /* PCLK */
> > + SUNXI_FUNCTION(0x3, "emac"), /* RXD/RXD1 */
> > + SUNXI_FUNCTION(0x4, "i2s1"), /* MCLK */
> > + SUNXI_FUNCTION(0x5, "pwm0"),
> > + SUNXI_FUNCTION(0x6, "sdc1"), /* CLK */
> > + SUNXI_FUNCTION(0x7, "uart3"), /* TX */
> > + SUNXI_FUNCTION(0x8, "i2c3"), /* SCK */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 0)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 1),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "ncsi"), /* MCLK */
> > + SUNXI_FUNCTION(0x3, "emac"), /* RXCK/TXCK */
> > + SUNXI_FUNCTION(0x4, "i2s1"), /* BCLK */
> > + SUNXI_FUNCTION(0x5, "pwm1"),
> > + SUNXI_FUNCTION(0x6, "sdc1"), /* CMD */
> > + SUNXI_FUNCTION(0x7, "uart3"), /* RX */
> > + SUNXI_FUNCTION(0x8, "i2c3"), /* SDA */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 1)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 2),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "ncsi"), /* HSYNC */
> > + SUNXI_FUNCTION(0x3, "emac"), /* RXCTL/CRS_DV */
> > + SUNXI_FUNCTION(0x4, "i2s1"), /* LCLK */
> > + SUNXI_FUNCTION(0x5, "pwm2"),
> > + SUNXI_FUNCTION(0x6, "sdc1"), /* D0 */
> > + SUNXI_FUNCTION(0x7, "uart3"), /* CTS */
> > + SUNXI_FUNCTION(0x8, "i2c1"), /* SCK */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 2)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 3),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "ncsi"), /* VSYNC */
> > + SUNXI_FUNCTION(0x3, "emac"), /* RXD0 */
> > + SUNXI_FUNCTION(0x4, "i2s1"), /* DIN0 */
> > + SUNXI_FUNCTION(0x5, "pwm3"),
> > + SUNXI_FUNCTION(0x6, "sdc1"), /* D1 */
> > + SUNXI_FUNCTION(0x7, "uart3"), /* RTS */
> > + SUNXI_FUNCTION(0x8, "i2c1"), /* SDA */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 3)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 4),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "ncsi"), /* D0 */
> > + SUNXI_FUNCTION(0x3, "emac"), /* TXD0 */
> > + SUNXI_FUNCTION(0x4, "i2s1"), /* DOUT0 */
> > + SUNXI_FUNCTION(0x5, "pwm4"),
> > + SUNXI_FUNCTION(0x6, "sdc1"), /* D2 */
> > + SUNXI_FUNCTION(0x7, "i2c3"), /* SCK */
> > + SUNXI_FUNCTION(0x8, "i2c0"), /* SCK */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 4)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 5),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "ncsi"), /* D1 */
> > + SUNXI_FUNCTION(0x3, "emac"), /* TXD1 */
> > + SUNXI_FUNCTION(0x5, "pwm5"),
> > + SUNXI_FUNCTION(0x6, "sdc1"), /* D3 */
> > + SUNXI_FUNCTION(0x7, "i2c3"), /* SDA */
> > + SUNXI_FUNCTION(0x8, "i2c0"), /* SDA */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 5)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 6),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "ncsi"), /* D2 */
> > + SUNXI_FUNCTION(0x3, "emac"), /* TXCTL/TXEN */
> > + SUNXI_FUNCTION(0x4, "lcd"), /* D2 */
> > + SUNXI_FUNCTION(0x5, "pwm6"),
> > + SUNXI_FUNCTION(0x6, "uart1"), /* TX */
> > + SUNXI_FUNCTION(0x8, "i2c4"), /* SCK */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 6)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 7),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "ncsi"), /* D3 */
> > + SUNXI_FUNCTION(0x3, "emac"), /* CLKIN/RXER */
> > + SUNXI_FUNCTION(0x4, "lcd"), /* D15 */
> > + SUNXI_FUNCTION(0x5, "pwm7"),
> > + SUNXI_FUNCTION(0x6, "uart1"), /* TX */
> > + SUNXI_FUNCTION(0x7, "i2s1"), /* DOUT0 */
> > + SUNXI_FUNCTION(0x8, "i2c4"), /* SDA */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 7)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 8),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "ncsi"), /* D4 */
> > + SUNXI_FUNCTION(0x3, "emac"), /* MDC */
> > + SUNXI_FUNCTION(0x4, "lcd"), /* D18 */
> > + SUNXI_FUNCTION(0x5, "pwm8"),
> > + SUNXI_FUNCTION(0x6, "wiegand"), /* D0 */
> > + SUNXI_FUNCTION(0x7, "i2s1"), /* DIN0 */
> > + SUNXI_FUNCTION(0x8, "i2c1"), /* SCK */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 8)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 9),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "ncsi"), /* D5 */
> > + SUNXI_FUNCTION(0x3, "emac"), /* MDIO */
> > + SUNXI_FUNCTION(0x4, "lcd"), /* D19 */
> > + SUNXI_FUNCTION(0x5, "pwm9"),
> > + SUNXI_FUNCTION(0x6, "wiegand"), /* D1 */
> > + SUNXI_FUNCTION(0x7, "i2s1"), /* LRCK */
> > + SUNXI_FUNCTION(0x8, "i2c1"), /* SDA */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 9)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 10),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "ncsi"), /* D6 */
> > + SUNXI_FUNCTION(0x3, "emac"), /* EPHY_25M */
> > + SUNXI_FUNCTION(0x4, "lcd"), /* D20 */
> > + SUNXI_FUNCTION(0x5, "pwm10"),
> > + SUNXI_FUNCTION(0x6, "uart2"), /* RTS */
> > + SUNXI_FUNCTION(0x7, "i2s1"), /* BCLK */
> > + SUNXI_FUNCTION(0x8, "wiegand"), /* D0 */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 10)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 11),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "ncsi"), /* D7 */
> > + SUNXI_FUNCTION(0x3, "emac"), /* RXD3 */
> > + SUNXI_FUNCTION(0x4, "lcd"), /* D21 */
> > + SUNXI_FUNCTION(0x5, "csi"), /* SM_VS */
> > + SUNXI_FUNCTION(0x6, "uart2"), /* CTS */
> > + SUNXI_FUNCTION(0x7, "i2s1"), /* MCLK */
> > + SUNXI_FUNCTION(0x8, "wiegand"), /* D1 */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 11)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 12),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "ncsi"), /* D8 */
> > + SUNXI_FUNCTION(0x3, "emac"), /* RXD2 */
> > + SUNXI_FUNCTION(0x4, "lcd"), /* D22 */
> > + SUNXI_FUNCTION(0x5, "csi"), /* MCLK0 */
> > + SUNXI_FUNCTION(0x6, "uart2"), /* TX */
> > + SUNXI_FUNCTION(0x7, "uart3"), /* TX */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 12)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 13),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "ncsi"), /* D9 */
> > + SUNXI_FUNCTION(0x3, "emac"), /* RXCK */
> > + SUNXI_FUNCTION(0x4, "lcd"), /* D23 */
> > + SUNXI_FUNCTION(0x5, "csi"), /* MCLK1 */
> > + SUNXI_FUNCTION(0x6, "uart2"), /* RX */
> > + SUNXI_FUNCTION(0x7, "uart3"), /* RX */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 13)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 14),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "ncsi"), /* D10 */
> > + SUNXI_FUNCTION(0x3, "emac"), /* TXD3 */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 14)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 15),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "ncsi"), /* D11 */
> > + SUNXI_FUNCTION(0x3, "emac"), /* TXD2 */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 15)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 16),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "i2c0"), /* SCK */
> > + SUNXI_FUNCTION(0x3, "i2c4"), /* SCK */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 16)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 17),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "i2c0"), /* SDA */
> > + SUNXI_FUNCTION(0x3, "i2c4"), /* SDA */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 17)),
> > + /* bank F */
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 0),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "sdc0"), /* D1 */
> > + SUNXI_FUNCTION(0x3, "jtag"), /* MS */
> > + SUNXI_FUNCTION(0x4, "spi0"), /* CLK */
> > + SUNXI_FUNCTION(0x5, "spi2"), /* CLK */
> > + SUNXI_FUNCTION(0x6, "r_jtag"), /* MS */
> > + SUNXI_FUNCTION(0x7, "cpu"), /* BIST0 */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 0)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 1),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "sdc0"), /* D0 */
> > + SUNXI_FUNCTION(0x3, "jtag"), /* DI */
> > + SUNXI_FUNCTION(0x4, "spi0"), /* MOSI */
> > + SUNXI_FUNCTION(0x5, "spi2"), /* MOSI */
> > + SUNXI_FUNCTION(0x6, "r_jtag"), /* DI */
> > + SUNXI_FUNCTION(0x7, "cpu"), /* BIST1 */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 1)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 2),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "sdc0"), /* CLK */
> > + SUNXI_FUNCTION(0x3, "uart0"), /* TX */
> > + SUNXI_FUNCTION(0x4, "spi0"), /* MISO */
> > + SUNXI_FUNCTION(0x5, "spi2"), /* MISO */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 2)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 3),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "sdc0"), /* CMD */
> > + SUNXI_FUNCTION(0x3, "jtag"), /* DO */
> > + SUNXI_FUNCTION(0x4, "spi0"), /* CSO */
> > + SUNXI_FUNCTION(0x5, "spi2"), /* CS0 */
> > + SUNXI_FUNCTION(0x6, "r_jtag"), /* DO */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 3)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 4),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "sdc0"), /* D3 */
> > + SUNXI_FUNCTION(0x3, "uart0"), /* RX */
> > + SUNXI_FUNCTION(0x4, "spi0"), /* CS1 */
> > + SUNXI_FUNCTION(0x5, "spi2"), /* CS1 */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 4)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 5),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "sdc0"), /* D2 */
> > + SUNXI_FUNCTION(0x3, "jtag"), /* CK */
> > + SUNXI_FUNCTION(0x6, "r_jtag"), /* CK */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 5)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 6),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "dbg_clk"),
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 6)),
> > + /* bank G */
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 0),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "sdc1"), /* CLK */
> > + SUNXI_FUNCTION(0x3, "lcd"), /* D0 */
> > + SUNXI_FUNCTION(0x4, "uart3"), /* TX */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 0)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 1),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "sdc1"), /* CMD */
> > + SUNXI_FUNCTION(0x3, "lcd"), /* D1 */
> > + SUNXI_FUNCTION(0x4, "uart3"), /* RX */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 1)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 2),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "sdc1"), /* D0 */
> > + SUNXI_FUNCTION(0x3, "lcd"), /* D8 */
> > + SUNXI_FUNCTION(0x4, "uart3"), /* CTS */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 2)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 3),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "sdc1"), /* D1 */
> > + SUNXI_FUNCTION(0x3, "lcd"), /* D9 */
> > + SUNXI_FUNCTION(0x4, "uart3"), /* RTS */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 3)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 4),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "sdc1"), /* D2 */
> > + SUNXI_FUNCTION(0x3, "lcd"), /* D16 */
> > + SUNXI_FUNCTION(0x4, "uart1"), /* RTS */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 4)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 5),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "sdc1"), /* D3 */
> > + SUNXI_FUNCTION(0x3, "lcd"), /* D17 */
> > + SUNXI_FUNCTION(0x4, "uart1"), /* CTS */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 5)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 6),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "i2c4"), /* SCK */
> > + SUNXI_FUNCTION(0x3, "clk"), /* FANOUT0 */
> > + SUNXI_FUNCTION(0x4, "uart1"), /* TX */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 6)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 7),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "i2c4"), /* SDA */
> > + SUNXI_FUNCTION(0x3, "clk"), /* FANOUT1 */
> > + SUNXI_FUNCTION(0x4, "uart1"), /* RX */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 7)),
> > + /* bank H */
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 0),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "pwm0"),
> > + SUNXI_FUNCTION(0x3, "i2s0"), /* MCLK */
> > + SUNXI_FUNCTION(0x4, "spi1"), /* CLK */
> > + SUNXI_FUNCTION(0x5, "uart3"), /* TX */
> > + SUNXI_FUNCTION(0x6, "dmic"), /* DATA3 */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 0)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 1),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "pwm1"),
> > + SUNXI_FUNCTION(0x3, "i2s0"), /* BCLK */
> > + SUNXI_FUNCTION(0x4, "spi1"), /* MOSI */
> > + SUNXI_FUNCTION(0x5, "uart3"), /* RX */
> > + SUNXI_FUNCTION(0x6, "dmic"), /* DATA2 */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 1)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 2),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "pwm2"),
> > + SUNXI_FUNCTION(0x3, "i2s0"), /* LRCK */
> > + SUNXI_FUNCTION(0x4, "spi1"), /* MISO */
> > + SUNXI_FUNCTION(0x5, "uart3"), /* CTS */
> > + SUNXI_FUNCTION(0x6, "dmic"), /* DATA1 */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 2)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 3),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "pwm3"),
> > + SUNXI_FUNCTION(0x3, "i2s0"), /* DOUT0 */
> > + SUNXI_FUNCTION(0x4, "spi1"), /* CS0 */
> > + SUNXI_FUNCTION(0x5, "uart3"), /* RTS */
> > + SUNXI_FUNCTION(0x6, "dmic"), /* DATA0 */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 3)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 4),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "pwm4"),
> > + SUNXI_FUNCTION(0x3, "i2s0"), /* DIN0 */
> > + SUNXI_FUNCTION(0x4, "spi1"), /* CS1 */
> > + SUNXI_FUNCTION(0x5, "clk"), /* FANOUT2 */
> > + SUNXI_FUNCTION(0x6, "dmic"), /* CLK */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 4)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 5),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "pwm5"),
> > + SUNXI_FUNCTION(0x3, "emac"), /* RXD1 */
> > + SUNXI_FUNCTION(0x4, "i2c2"), /* SCK */
> > + SUNXI_FUNCTION(0x5, "uart2"), /* TX */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 5)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 6),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "pwm6"),
> > + SUNXI_FUNCTION(0x3, "emac"), /* RXD0 */
> > + SUNXI_FUNCTION(0x4, "i2c2"), /* SDA */
> > + SUNXI_FUNCTION(0x5, "uart2"), /* RX */
> > + SUNXI_FUNCTION(0x6, "i2s1"), /* MCLK */
> > + SUNXI_FUNCTION(0x7, "dmic"), /* DATA3 */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 6)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 7),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "pwm7"),
> > + SUNXI_FUNCTION(0x3, "emac"), /* CRS_DV */
> > + SUNXI_FUNCTION(0x4, "uart0"), /* TX */
> > + SUNXI_FUNCTION(0x5, "uart2"), /* RTS */
> > + SUNXI_FUNCTION(0x6, "i2s1"), /* BCLK */
> > + SUNXI_FUNCTION(0x7, "dmic"), /* DATA2 */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 7)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 8),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "pwm8"),
> > + SUNXI_FUNCTION(0x3, "emac"), /* RXER */
> > + SUNXI_FUNCTION(0x4, "uart0"), /* RX */
> > + SUNXI_FUNCTION(0x5, "uart2"), /* CTS */
> > + SUNXI_FUNCTION(0x6, "i2s1"), /* LRCK */
> > + SUNXI_FUNCTION(0x7, "dmic"), /* DATA1 */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 8)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 9),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "pwm9"),
> > + SUNXI_FUNCTION(0x3, "emac"), /* TXD1 */
> > + SUNXI_FUNCTION(0x4, "i2c3"), /* SCK */
> > + SUNXI_FUNCTION(0x5, "uart0"), /* TX */
> > + SUNXI_FUNCTION(0x6, "i2s1"), /* DIN0 */
> > + SUNXI_FUNCTION(0x7, "dmic"), /* DATA0 */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 9)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 10),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "pwm10"),
> > + SUNXI_FUNCTION(0x3, "emac"), /* TXD0 */
> > + SUNXI_FUNCTION(0x4, "i2c3"), /* SDA */
> > + SUNXI_FUNCTION(0x5, "uart0"), /* RX */
> > + SUNXI_FUNCTION(0x6, "i2s1"), /* DOUT0 */
> > + SUNXI_FUNCTION(0x7, "dmic"), /* CLK */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 10)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 11),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "jtag"), /* MS */
> > + SUNXI_FUNCTION(0x3, "emac"), /* TXCK */
> > + SUNXI_FUNCTION(0x4, "r_jtag"), /* MS */
> > + SUNXI_FUNCTION(0x5, "i2c2"), /* SCK */
> > + SUNXI_FUNCTION(0x6, "spi3"), /* CLK */
> > + SUNXI_FUNCTION(0x7, "clk"), /* FANOUT0 */
> > + SUNXI_FUNCTION(0x8, "pwm4"),
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 11)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 12),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "jtag"), /* CK */
> > + SUNXI_FUNCTION(0x3, "emac"), /* TXEN */
> > + SUNXI_FUNCTION(0x4, "r_jtag"), /* CK */
> > + SUNXI_FUNCTION(0x5, "i2c2"), /* SDA */
> > + SUNXI_FUNCTION(0x6, "spi3"), /* MOSI */
> > + SUNXI_FUNCTION(0x7, "clk"), /* FANOUT1 */
> > + SUNXI_FUNCTION(0x8, "pwm5"),
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 12)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 13),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "jtag"), /* DO */
> > + SUNXI_FUNCTION(0x3, "emac"), /* MDC */
> > + SUNXI_FUNCTION(0x4, "r_jtag"), /* DO */
> > + SUNXI_FUNCTION(0x5, "i2c3"), /* SCK */
> > + SUNXI_FUNCTION(0x6, "spi3"), /* MISO */
> > + SUNXI_FUNCTION(0x7, "wiegand"), /* D0 */
> > + SUNXI_FUNCTION(0x8, "pwm6"),
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 13)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 14),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "jtag"), /* DI */
> > + SUNXI_FUNCTION(0x3, "emac"), /* MDIO */
> > + SUNXI_FUNCTION(0x4, "r_jtag"), /* DI */
> > + SUNXI_FUNCTION(0x5, "i2c3"), /* SDA */
> > + SUNXI_FUNCTION(0x6, "spi3"), /* CS0 */
> > + SUNXI_FUNCTION(0x7, "wiegand"), /* D1 */
> > + SUNXI_FUNCTION(0x8, "pwm7"),
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 14)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 15),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "clk"), /* FANOUT2 */
> > + SUNXI_FUNCTION(0x3, "ephy_25m"), /* EPHY_25M */
> > + SUNXI_FUNCTION(0x6, "spi3"), /* CS1 */
> > + SUNXI_FUNCTION(0x8, "pwm8"),
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 15)),
> > + /* bank I */
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 0),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "csi"), /* MCLK0 */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 7, 0)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 1),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "csi"), /* SM_HS */
> > + SUNXI_FUNCTION(0x4, "spi2"), /* CLK */
> > + SUNXI_FUNCTION(0x5, "i2c1"), /* SCK */
> > + SUNXI_FUNCTION(0x6, "i2c4"), /* SCK */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 7, 1)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 2),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x2, "csi"), /* SM_VS */
> > + SUNXI_FUNCTION(0x3, "tcon"), /* TRIG */
> > + SUNXI_FUNCTION(0x4, "spi2"), /* MOSI */
> > + SUNXI_FUNCTION(0x5, "i2c1"), /* SDA */
> > + SUNXI_FUNCTION(0x6, "i2c4"), /* SDA */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 7, 2)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 3),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x4, "spi2"), /* MISO */
> > + SUNXI_FUNCTION(0x5, "i2c0"), /* SCA */
> > + SUNXI_FUNCTION(0x6, "i2c3"), /* SCK */
> > + SUNXI_FUNCTION(0x7, "clk"), /* FANOUT0 */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 7, 3)),
> > + SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 4),
> > + SUNXI_FUNCTION(0x0, "gpio_in"),
> > + SUNXI_FUNCTION(0x1, "gpio_out"),
> > + SUNXI_FUNCTION(0x4, "spi2"), /* CS0 */
> > + SUNXI_FUNCTION(0x5, "i2c0"), /* SDA */
> > + SUNXI_FUNCTION(0x6, "i2c3"), /* SDA */
> > + SUNXI_FUNCTION(0x7, "clk"), /* FANOUT1 */
> > + SUNXI_FUNCTION_IRQ_BANK(0xe, 7, 4)),
> > +};
> > +
> > +static const unsigned int sun8i_v853_irq_bank_map[] = { 0, 2, 3, 4, 5, 6, 7, 8 };
> > +
> > +static const struct sunxi_pinctrl_desc sun8i_v853_pinctrl_data = {
> > + .pins = sun8i_v853_pins,
> > + .npins = ARRAY_SIZE(sun8i_v853_pins),
> > + .pin_base = 0,
> > + .irq_banks = ARRAY_SIZE(sun8i_v853_irq_bank_map),
> > + .irq_bank_map = sun8i_v853_irq_bank_map,
> > + .io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_CTL,
> > +};
> > +
> > +static int sun8i_v853_pinctrl_probe(struct platform_device *pdev)
> > +{
> > + unsigned long variant = (unsigned long)of_device_get_match_data(&pdev->dev);
> > +
> > + return sunxi_pinctrl_init_with_variant(pdev, &sun8i_v853_pinctrl_data, variant);
> > +}
> > +
> > +static const struct of_device_id sun8i_v853_pinctrl_match[] = {
> > + {
> > + .compatible = "allwinner,sun8i-v853-pinctrl",
> > + .data = (void *)PINCTRL_SUN8I_V853
> > + },
> > + {}
> > +};
> > +
> > +static struct platform_driver sun8i_v853_pinctrl_driver = {
> > + .probe = sun8i_v853_pinctrl_probe,
> > + .driver = {
> > + .name = "sun8i-v853-pinctrl",
> > + .of_match_table = sun8i_v853_pinctrl_match,
> > + },
> > +};
> > +builtin_platform_driver(sun8i_v853_pinctrl_driver);
> > diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.h b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
> > index a87a2f944d60..f4b64f9156f1 100644
> > --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.h
> > +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
> > @@ -94,6 +94,7 @@
> > #define PINCTRL_SUN8I_V3S BIT(10)
> > /* Variants below here have an updated register layout. */
> > #define PINCTRL_SUN20I_D1 BIT(11)
> > +#define PINCTRL_SUN8I_V853 BIT(12)
> >
> > #define PIO_POW_MOD_SEL_REG 0x340
> > #define PIO_POW_MOD_CTL_REG 0x344
>
>
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH 02/12] dt-bindings: pinctrl: sunxi: add compatible for V853
2025-01-10 12:39 ` [PATCH 02/12] dt-bindings: pinctrl: sunxi: add compatible for V853 Andras Szemzo
@ 2025-01-14 19:52 ` Rob Herring (Arm)
2025-01-16 9:08 ` Linus Walleij
1 sibling, 0 replies; 50+ messages in thread
From: Rob Herring (Arm) @ 2025-01-14 19:52 UTC (permalink / raw)
To: Andras Szemzo
Cc: Stephen Boyd, Florian Fainelli, linux-sunxi, Krzysztof Kozlowski,
Michael Turquette, linux-arm-kernel, devicetree,
Uwe Kleine-König, Palmer Dabbelt, Paul Walmsley,
Conor Dooley, linux-gpio, Maxime Ripard, Kishon Vijay Abraham I,
Ulf Hansson, Linus Walleij, linux-phy, Albert Ou, linux-pm,
Vinod Koul, linux-clk, Philipp Zabel, Chen-Yu Tsai,
Samuel Holland, linux-kernel, Jernej Skrabec, linux-riscv
On Fri, 10 Jan 2025 13:39:13 +0100, Andras Szemzo wrote:
> Add compatible strings for V853 family pinctrl.
>
> Signed-off-by: Andras Szemzo <szemzo.andras@gmail.com>
> ---
> .../pinctrl/allwinner,sun4i-a10-pinctrl.yaml | 13 +++++++++++++
> 1 file changed, 13 insertions(+)
>
Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH 10/12] dt-bindings: phy: allwinner: add v853 usb phy
2025-01-10 12:39 ` [PATCH 10/12] dt-bindings: phy: allwinner: add v853 usb phy Andras Szemzo
2025-01-10 13:39 ` Rob Herring (Arm)
2025-01-10 13:53 ` Krzysztof Kozlowski
@ 2025-01-15 7:51 ` Vinod Koul
2025-01-17 7:26 ` András Szemző
2025-01-17 10:39 ` Andre Przywara
2 siblings, 2 replies; 50+ messages in thread
From: Vinod Koul @ 2025-01-15 7:51 UTC (permalink / raw)
To: Andras Szemzo
Cc: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
Linus Walleij, Philipp Zabel, Maxime Ripard,
Kishon Vijay Abraham I, Ulf Hansson, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Uwe Kleine-König,
Florian Fainelli, linux-clk, devicetree, linux-arm-kernel,
linux-sunxi, linux-kernel, linux-phy, linux-gpio, linux-pm,
linux-riscv
On 10-01-25, 13:39, Andras Szemzo wrote:
> Document Allwinner v853 USB phy.
>
> Signed-off-by: Andras Szemzo <szemzo.andras@gmail.com>
> ---
> .../phy/allwinner,sun8i-v853-usb-phy.yaml | 89 +++++++++++++++++++
> 1 file changed, 89 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/phy/allwinner,sun8i-v853-usb-phy.yaml
>
> diff --git a/Documentation/devicetree/bindings/phy/allwinner,sun8i-v853-usb-phy.yaml b/Documentation/devicetree/bindings/phy/allwinner,sun8i-v853-usb-phy.yaml
> new file mode 100644
> index 000000000000..773c3f476db8
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/phy/allwinner,sun8i-v853-usb-phy.yaml
> @@ -0,0 +1,89 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/phy/allwinner,sun8i-v853-usb-phy.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Allwinner V853 USB PHY
> +
> +maintainers:
> + - Chen-Yu Tsai <wens@csie.org>
> + - Maxime Ripard <mripard@kernel.org>
> +
> +properties:
> + "#phy-cells":
> + const: 1
> +
> + compatible:
> + const:
> + - allwinner,sun8i-v853-usb-phy
Does this really need a new binding document, if so why... Cant this be
added to one of the existing docs which driver uses?
--
~Vinod
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH 12/12] ARM: dts: sun8i: add DTSI file for V853
2025-01-10 13:58 ` Krzysztof Kozlowski
@ 2025-01-15 9:09 ` Csókás Bence
2025-01-15 9:43 ` Krzysztof Kozlowski
0 siblings, 1 reply; 50+ messages in thread
From: Csókás Bence @ 2025-01-15 9:09 UTC (permalink / raw)
To: Krzysztof Kozlowski, Andras Szemzo, Michael Turquette,
Stephen Boyd, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Chen-Yu Tsai, Jernej Skrabec, Samuel Holland, Linus Walleij,
Philipp Zabel, Maxime Ripard
Cc: Vinod Koul, Kishon Vijay Abraham I, Ulf Hansson, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Uwe Kleine-König,
Florian Fainelli, linux-clk, devicetree, linux-arm-kernel,
linux-sunxi, linux-kernel, linux-phy, linux-gpio, linux-pm,
linux-riscv
Hi,
On 2025. 01. 10. 14:58, Krzysztof Kozlowski wrote:
> On 10/01/2025 13:39, Andras Szemzo wrote:
>> +// Copyright (C) 2024 Andras Szemzo <szemzo.andras@gmail.com>
>> +
>> +#include <dt-bindings/clock/sun6i-rtc.h>
>> +#include <dt-bindings/clock/sun8i-v853-r-ccu.h>
>> +#include <dt-bindings/reset/sun8i-v853-r-ccu.h>
>> +#include <dt-bindings/clock/sun8i-v853-ccu.h>
>> +#include <dt-bindings/reset/sun8i-v853-ccu.h>
>> +#include <dt-bindings/interrupt-controller/arm-gic.h>
>> +#include <dt-bindings/power/allwinner,sun8i-v853-ppu.h>
>> +
>> +/ {
>> + #address-cells = <1>;
>> + #size-cells = <1>;
>> +
>> + osc24M: osc24M-clk {
>
> Only lowercase node names.
I don't agree. It is customary to write oscillator names with casing in
line with the SI prefixes of their frequency, i.e. lowercase k,
uppercase M/G/etc. (even though a millihertz oscillator rarely makes
sense, it is best to stay consistent).
Bence
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH 12/12] ARM: dts: sun8i: add DTSI file for V853
2025-01-15 9:09 ` Csókás Bence
@ 2025-01-15 9:43 ` Krzysztof Kozlowski
0 siblings, 0 replies; 50+ messages in thread
From: Krzysztof Kozlowski @ 2025-01-15 9:43 UTC (permalink / raw)
To: Csókás Bence, Andras Szemzo, Michael Turquette,
Stephen Boyd, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Chen-Yu Tsai, Jernej Skrabec, Samuel Holland, Linus Walleij,
Philipp Zabel, Maxime Ripard
Cc: Vinod Koul, Kishon Vijay Abraham I, Ulf Hansson, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Uwe Kleine-König,
Florian Fainelli, linux-clk, devicetree, linux-arm-kernel,
linux-sunxi, linux-kernel, linux-phy, linux-gpio, linux-pm,
linux-riscv
On 15/01/2025 10:09, Csókás Bence wrote:
> Hi,
>
> On 2025. 01. 10. 14:58, Krzysztof Kozlowski wrote:
>> On 10/01/2025 13:39, Andras Szemzo wrote:
>>> +// Copyright (C) 2024 Andras Szemzo <szemzo.andras@gmail.com>
>>> +
>>> +#include <dt-bindings/clock/sun6i-rtc.h>
>>> +#include <dt-bindings/clock/sun8i-v853-r-ccu.h>
>>> +#include <dt-bindings/reset/sun8i-v853-r-ccu.h>
>>> +#include <dt-bindings/clock/sun8i-v853-ccu.h>
>>> +#include <dt-bindings/reset/sun8i-v853-ccu.h>
>>> +#include <dt-bindings/interrupt-controller/arm-gic.h>
>>> +#include <dt-bindings/power/allwinner,sun8i-v853-ppu.h>
>>> +
>>> +/ {
>>> + #address-cells = <1>;
>>> + #size-cells = <1>;
>>> +
>>> + osc24M: osc24M-clk {
>>
>> Only lowercase node names.
>
> I don't agree. It is customary to write oscillator names with casing in
It is not customary in Linux kernel and DT bindings/DTS. See DTS coding
style, see the clock bindings and preferred node naming.
This is the DTS submitted to Linux kernel, thus it is bound by the rules
expressed in the kernel.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH 03/12] pinctrl: sunxi: add driver for Allwinner V853.
2025-01-14 14:19 ` Andre Przywara
2025-01-14 14:30 ` Andre Przywara
@ 2025-01-15 10:23 ` Linus Walleij
2025-01-15 15:26 ` Andre Przywara
1 sibling, 1 reply; 50+ messages in thread
From: Linus Walleij @ 2025-01-15 10:23 UTC (permalink / raw)
To: Andre Przywara
Cc: Andras Szemzo, Michael Turquette, Stephen Boyd, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Chen-Yu Tsai, Jernej Skrabec,
Samuel Holland, Philipp Zabel, Maxime Ripard, Vinod Koul,
Kishon Vijay Abraham I, Ulf Hansson, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Uwe Kleine-König,
Florian Fainelli, linux-clk, devicetree, linux-arm-kernel,
linux-sunxi, linux-kernel, linux-phy, linux-gpio, linux-pm,
linux-riscv
On Tue, Jan 14, 2025 at 3:20 PM Andre Przywara <andre.przywara@arm.com> wrote:
> Andras Szemzo <szemzo.andras@gmail.com> wrote:
> > The V853 family has multiple package variants, from BGA to QFN88.
> > The latter has co-packaged DRAM and fewer pins, and less features (pin muxes).
> > All family members can be supported by a single driver, as the available pins
> > with allowed muxes is the same across the devices.
>
> It depends a bit on the outcome of the discussion on the A523 pinctrl
> driver [1], but I think we should use the same approach here (and for
> every "new" Allwinner SoC coming up, really): put the pinmux value in the
> DT, and get rid of this entire table altogether:
> [1]
>
> The SoC specific pinctrl driver would then be very small ([2]), so this
> pinctrl support patch here would actually become much smaller.
>
> Just feel a bit sorry for you having created this table, in a tedious and
> eye-straining exercise - been there, done that ;-)
It's pretty stressful for the pin control maintainer as well.
From the subsystems point of view, groups matches to functions by
strings is the best. ("fun1") + ("group1", "group2"):
pio: pinctrl@1c20800 {
compatible = "allwinner,sun8i-r40-pinctrl";
(...)
i2c0_pins: i2c0-pins {
pins = "PB0", "PB1";
function = "i2c0";
};
abstract, strings, nice. The driver handles the particulars.
That is like so because we are designing for users which are
let's say customization engineers. If these engineers jump from
project to project matching function strings to group strings will
be a common way to set up pins, and easy to understand and
grasp, and it makes the DTS very readable.
Then there are the engineers creating the pin control drivers,
and they want everything to be convinient for *them*, and they
think an opaque hex digit in the DTS is perfect at times, thus
pinmux = <0xdeadbeef>;
Mediatek and STM32 made a compromise by using pinmux
and adding some macros to define them so it looks more
pleasant:
i2c0_pins_a: i2c0-default {
pins-i2c0 {
pinmux = <MT7623_PIN_75_SDA0_FUNC_SDA0>,
<MT7623_PIN_76_SCL0_FUNC_SCL0>;
bias-disable;
};
};
At least the bias control is using strings, this is nice.
So I'm mostly fine with that as well, but it can be pretty
heavy on people coming from the outside, asking us questions
like "on MT7689 how do you mux pin nnnn to function yyy"???
Well I don't know? Some MT7689_PIN* macro I guess?
If it was just strings I would know what the
expected behaviour and looks would be at least, then the driver
could be buggy or missing things but that's clearly cut. That's
why I prefer the strings.
Yours,
Linus Walleij
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH 03/12] pinctrl: sunxi: add driver for Allwinner V853.
2025-01-15 10:23 ` Linus Walleij
@ 2025-01-15 15:26 ` Andre Przywara
2025-01-16 9:34 ` Linus Walleij
0 siblings, 1 reply; 50+ messages in thread
From: Andre Przywara @ 2025-01-15 15:26 UTC (permalink / raw)
To: Linus Walleij
Cc: Andras Szemzo, Michael Turquette, Stephen Boyd, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Chen-Yu Tsai, Jernej Skrabec,
Samuel Holland, Philipp Zabel, Maxime Ripard, Vinod Koul,
Kishon Vijay Abraham I, Ulf Hansson, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Uwe Kleine-König,
Florian Fainelli, linux-clk, devicetree, linux-arm-kernel,
linux-sunxi, linux-kernel, linux-phy, linux-gpio, linux-pm,
linux-riscv
On Wed, 15 Jan 2025 11:23:50 +0100
Linus Walleij <linus.walleij@linaro.org> wrote:
Hi Linus,
thanks for the reply, I was hoping to get some insight and discuss this!
> On Tue, Jan 14, 2025 at 3:20 PM Andre Przywara <andre.przywara@arm.com> wrote:
> > Andras Szemzo <szemzo.andras@gmail.com> wrote:
>
> > > The V853 family has multiple package variants, from BGA to QFN88.
> > > The latter has co-packaged DRAM and fewer pins, and less features (pin muxes).
> > > All family members can be supported by a single driver, as the available pins
> > > with allowed muxes is the same across the devices.
> >
> > It depends a bit on the outcome of the discussion on the A523 pinctrl
> > driver [1], but I think we should use the same approach here (and for
> > every "new" Allwinner SoC coming up, really): put the pinmux value in the
> > DT, and get rid of this entire table altogether:
> > [1]
> >
> > The SoC specific pinctrl driver would then be very small ([2]), so this
> > pinctrl support patch here would actually become much smaller.
> >
> > Just feel a bit sorry for you having created this table, in a tedious and
> > eye-straining exercise - been there, done that ;-)
>
> It's pretty stressful for the pin control maintainer as well.
>
> From the subsystems point of view, groups matches to functions by
> strings is the best. ("fun1") + ("group1", "group2"):
>
> pio: pinctrl@1c20800 {
> compatible = "allwinner,sun8i-r40-pinctrl";
> (...)
> i2c0_pins: i2c0-pins {
> pins = "PB0", "PB1";
> function = "i2c0";
> };
>
> abstract, strings, nice. The driver handles the particulars.
What bugs me about this it that this has quite some seemingly redundant
information (Who would have thought that the i2c0 pins use function
"i2c0"?), but misses out on the actual 4 bits(!) of information.
So the A523 version [1] just *adds* this one property:
allwinner,pinmux = <2>;
[1]https://lore.kernel.org/linux-sunxi/20241111005750.13071-5-andre.przywara@arm.com/
And we keep all your beloved strings ;-)
> That is like so because we are designing for users which are
> let's say customization engineers. If these engineers jump from
> project to project matching function strings to group strings will
> be a common way to set up pins, and easy to understand and
> grasp, and it makes the DTS very readable.
That's an interesting view, and I see the point of it being easy to read,
but this is partly because it doesn't convey too much actual information,
does it, as it requires another lookup or two.
And the pinctrl group nodes are actually in the .dtsi file, which are
typically written once during the initial SoC enablement, and new board
.dts files normally just reference the existing pingroup nodes. So anyone
dealing with just a new board is not bothered by this.
Also in my experience most people have no problems in understanding the
concept of pinmuxing and that there is a selector number, also where to
find this.
> Then there are the engineers creating the pin control drivers,
> and they want everything to be convinient for *them*, and they
> think an opaque hex digit in the DTS is perfect at times, thus
> pinmux = <0xdeadbeef>;
>
> Mediatek and STM32 made a compromise by using pinmux
> and adding some macros to define them so it looks more
> pleasant:
>
> i2c0_pins_a: i2c0-default {
> pins-i2c0 {
> pinmux = <MT7623_PIN_75_SDA0_FUNC_SDA0>,
> <MT7623_PIN_76_SCL0_FUNC_SCL0>;
Well, I don't really get why they don't use the (MTK_PIN_NO(75) | 1)
definition directly, seems to be more telling to me?
So the plan for sunxi would be: <SUNXI_PINMUX(PORTC, 23, MUX_1)>, ...
And this would not be really "opaque", since it has a fixed known mapping:
(port << 16) | (pin << 8) | (mux << 0))
I find this both technically elegant, because it combines all the
information into just one compact cell, but also readable by outsiders,
thanks to the macro.
But please note that using the generic pinmux is just an idea at this
point, last time I checked this would require significant rework in the
sunxi pinctrl driver.
Just adding the "allwinner,pinmux" property on the other hand is a
comparably easy addition, hence my patch, as a compromise.
> bias-disable;
> };
> };
>
> At least the bias control is using strings, this is nice.
>
> So I'm mostly fine with that as well, but it can be pretty
> heavy on people coming from the outside, asking us questions
> like "on MT7689 how do you mux pin nnnn to function yyy"???
> Well I don't know? Some MT7689_PIN* macro I guess?
MTK_PIN_NO(nnn, yyy)?
> If it was just strings I would know what the
> expected behaviour and looks would be at least, then the driver
> could be buggy or missing things but that's clearly cut. That's
> why I prefer the strings.
My main arguments against the current (string-based) approach:
- They require the mapping table to be in every DT user, so not only the
Linux kernel, but also U-Boot, FreeBSD, you name it...
https://source.denx.de/u-boot/u-boot/-/blob/master/drivers/pinctrl/sunxi/pinctrl-sunxi.c?ref_type=heads#L236-768
https://cgit.freebsd.org/src/tree/sys/arm/allwinner/h6/h6_padconf.c
- The tables are getting quite large, and they pollute the single image
Linux kernel, with tons of very specific information for a number of very
pitiful Allwinner SoCs. At the moment the tally is at 145KB of code+data
for the existing arm64 SoCs, with the newer SoCs ever growing (H616 alone
is 27KB, A523 would be quite larger even, I guess 40K). The new A523
specific pinctrl support adds 872 Bytes.
- Most of the mappings are untested at pinctrl driver commit time, since we
don't have the device drivers ready yet - by a margin. The new approach
would add the pinmux values when we need them and can test them.
- The comments in the table give away that something is not quite right:
SUNXI_FUNCTION(0x2, "i2c0")), /* SDA */
This is just a comment, so has no relevance for the code, but it's not
meant for humans either. Yet we try to make this correct and maintain
it. Odd.
Cheers,
Andre
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH 02/12] dt-bindings: pinctrl: sunxi: add compatible for V853
2025-01-10 12:39 ` [PATCH 02/12] dt-bindings: pinctrl: sunxi: add compatible for V853 Andras Szemzo
2025-01-14 19:52 ` Rob Herring (Arm)
@ 2025-01-16 9:08 ` Linus Walleij
1 sibling, 0 replies; 50+ messages in thread
From: Linus Walleij @ 2025-01-16 9:08 UTC (permalink / raw)
To: Andras Szemzo
Cc: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
Philipp Zabel, Maxime Ripard, Vinod Koul, Kishon Vijay Abraham I,
Ulf Hansson, Paul Walmsley, Palmer Dabbelt, Albert Ou,
Uwe Kleine-König, Florian Fainelli, linux-clk, devicetree,
linux-arm-kernel, linux-sunxi, linux-kernel, linux-phy,
linux-gpio, linux-pm, linux-riscv
On Fri, Jan 10, 2025 at 1:39 PM Andras Szemzo <szemzo.andras@gmail.com> wrote:
> Add compatible strings for V853 family pinctrl.
>
> Signed-off-by: Andras Szemzo <szemzo.andras@gmail.com>
Patch applied because stand-alone, clear cut and reviewed.
Yours,
Linus Walleij
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH 03/12] pinctrl: sunxi: add driver for Allwinner V853.
2025-01-15 15:26 ` Andre Przywara
@ 2025-01-16 9:34 ` Linus Walleij
2025-01-17 7:25 ` András Szemző
` (2 more replies)
0 siblings, 3 replies; 50+ messages in thread
From: Linus Walleij @ 2025-01-16 9:34 UTC (permalink / raw)
To: Andre Przywara
Cc: Andras Szemzo, Michael Turquette, Stephen Boyd, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Chen-Yu Tsai, Jernej Skrabec,
Samuel Holland, Philipp Zabel, Maxime Ripard, Vinod Koul,
Kishon Vijay Abraham I, Ulf Hansson, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Uwe Kleine-König,
Florian Fainelli, linux-clk, devicetree, linux-arm-kernel,
linux-sunxi, linux-kernel, linux-phy, linux-gpio, linux-pm,
linux-riscv
Hi Andre,
some nice talk here, actually the following is just opinions, I will
be likely happy with whatever approach is taken eventually.
On Wed, Jan 15, 2025 at 4:26 PM Andre Przywara <andre.przywara@arm.com> wrote:
> > pio: pinctrl@1c20800 {
> > compatible = "allwinner,sun8i-r40-pinctrl";
> > (...)
> > i2c0_pins: i2c0-pins {
> > pins = "PB0", "PB1";
> > function = "i2c0";
> > };
> >
> > abstract, strings, nice. The driver handles the particulars.
>
> What bugs me about this it that this has quite some seemingly redundant
> information (Who would have thought that the i2c0 pins use function
> "i2c0"?), but misses out on the actual 4 bits(!) of information.
the pins in this example are called PB0 and PB1 though. The designation
on the package. And often pins actually named "i2c0_1" "i2c0_2" are
for that primary function, but muxable to a few other functions,
at least GPIO in most cases. So it's just some name for the pin
really.
> > That is like so because we are designing for users which are
> > let's say customization engineers. If these engineers jump from
> > project to project matching function strings to group strings will
> > be a common way to set up pins, and easy to understand and
> > grasp, and it makes the DTS very readable.
>
> That's an interesting view, and I see the point of it being easy to read,
> but this is partly because it doesn't convey too much actual information,
> does it, as it requires another lookup or two.
> And the pinctrl group nodes are actually in the .dtsi file, which are
> typically written once during the initial SoC enablement, and new board
> .dts files normally just reference the existing pingroup nodes. So anyone
> dealing with just a new board is not bothered by this.
You have a point, and when working with a system the application
engineer often finds bugs in the pin control driver, and has to go
and fix the actual driver and then all the information hiding and
simplification is moot.
This can become an expensive lesson for the current attempts
to push pin control into firmware where the configuration is
mostly "dead simple" (and just using strings) - the bugs will be
in the firmware instead, and impossible or really hard to fix.
> Also in my experience most people have no problems in understanding the
> concept of pinmuxing and that there is a selector number, also where to
> find this.
Yeah the ambition with the strings was to avoid forcing application
engineers to know all about that. If they do, they are then
developing the driver, not just using it.
> > Mediatek and STM32 made a compromise by using pinmux
> > and adding some macros to define them so it looks more
> > pleasant:
> >
> > i2c0_pins_a: i2c0-default {
> > pins-i2c0 {
> > pinmux = <MT7623_PIN_75_SDA0_FUNC_SDA0>,
> > <MT7623_PIN_76_SCL0_FUNC_SCL0>;
>
> Well, I don't really get why they don't use the (MTK_PIN_NO(75) | 1)
> definition directly, seems to be more telling to me?
That's what STM32 does as well and it's usable.
But of course it drives a truck through the initial ambition that pins
on all systems be configured the same way, with strings. So now
there are some families of drivers all "necessarily different" which
is not so nice for people jumping between different SoCs, but
very compelling for people focusing on just one SoC.
Well, unless this way of doing things becomes so prevalent that
it's the new black.
> So the plan for sunxi would be: <SUNXI_PINMUX(PORTC, 23, MUX_1)>, ...
> And this would not be really "opaque", since it has a fixed known mapping:
> (port << 16) | (pin << 8) | (mux << 0))
> I find this both technically elegant, because it combines all the
> information into just one compact cell, but also readable by outsiders,
> thanks to the macro.
And a new standard, to add to the other standards, so that
is my problem as maintainer. It makes sense on its own, and it
complicates the bigger picture.
> My main arguments against the current (string-based) approach:
> - They require the mapping table to be in every DT user, so not only the
> Linux kernel, but also U-Boot, FreeBSD, you name it...
That's true.
This comes from the DT ambition to describe hardware and config,
but not *define* hardware, i.e. to stop device tree to turn into
Verilog or SystemC, which is what will happen if we take the
1:1 reflection of hardware to device tree too far.
I don't think anyone really knows where to cut the line.
> - The tables are getting quite large, and they pollute the single image
> Linux kernel, with tons of very specific information for a number of very
> pitiful Allwinner SoCs. At the moment the tally is at 145KB of code+data
> for the existing arm64 SoCs, with the newer SoCs ever growing (H616 alone
> is 27KB, A523 would be quite larger even, I guess 40K). The new A523
> specific pinctrl support adds 872 Bytes.
This is a generic problem though, look at GPU drivers.
The community (especially Android) seem set on fixing this by using
modules.
> - Most of the mappings are untested at pinctrl driver commit time, since we
> don't have the device drivers ready yet - by a margin. The new approach
> would add the pinmux values when we need them and can test them.
I like this argument the best.
However this also reads "upfront firmware to handle pin control is a
dead end" yet there are people dedicatedly working on exactly that.
(Not that its' the Allwinner developers' problem...)
> - The comments in the table give away that something is not quite right:
> SUNXI_FUNCTION(0x2, "i2c0")), /* SDA */
> This is just a comment, so has no relevance for the code, but it's not
> meant for humans either. Yet we try to make this correct and maintain
> it. Odd.
So i2c0 is SDA and i2c1 is SCL or something?
It seems common, but yeah it can be confusing.
Yours,
Linus Walleij
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH 03/12] pinctrl: sunxi: add driver for Allwinner V853.
2025-01-16 9:34 ` Linus Walleij
@ 2025-01-17 7:25 ` András Szemző
2025-01-17 14:52 ` Andre Przywara
2025-01-17 15:43 ` Chen-Yu Tsai
2 siblings, 0 replies; 50+ messages in thread
From: András Szemző @ 2025-01-17 7:25 UTC (permalink / raw)
To: Linus Walleij
Cc: Andre Przywara, Michael Turquette, Stephen Boyd, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Chen-Yu Tsai, Jernej Skrabec,
Samuel Holland, Philipp Zabel, Maxime Ripard, Vinod Koul,
Kishon Vijay Abraham I, Ulf Hansson, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Uwe Kleine-König,
Florian Fainelli, linux-clk, devicetree, linux-arm-kernel,
linux-sunxi, linux-kernel, linux-phy, linux-gpio, linux-pm,
linux-riscv
I’ve actually already converted the pinctrl driver to the new dt based pinmux, as Andre
suggested. It’s simple, get rid of those huge pinmux tables, and easy to understand to
add the mux settings to the dtsi.
> On 16 Jan 2025, at 10:34, Linus Walleij <linus.walleij@linaro.org> wrote:
>
> Hi Andre,
>
> some nice talk here, actually the following is just opinions, I will
> be likely happy with whatever approach is taken eventually.
>
> On Wed, Jan 15, 2025 at 4:26 PM Andre Przywara <andre.przywara@arm.com> wrote:
>
>>> pio: pinctrl@1c20800 {
>>> compatible = "allwinner,sun8i-r40-pinctrl";
>>> (...)
>>> i2c0_pins: i2c0-pins {
>>> pins = "PB0", "PB1";
>>> function = "i2c0";
>>> };
>>>
>>> abstract, strings, nice. The driver handles the particulars.
>>
>> What bugs me about this it that this has quite some seemingly redundant
>> information (Who would have thought that the i2c0 pins use function
>> "i2c0"?), but misses out on the actual 4 bits(!) of information.
>
> the pins in this example are called PB0 and PB1 though. The designation
> on the package. And often pins actually named "i2c0_1" "i2c0_2" are
> for that primary function, but muxable to a few other functions,
> at least GPIO in most cases. So it's just some name for the pin
> really.
>
>>> That is like so because we are designing for users which are
>>> let's say customization engineers. If these engineers jump from
>>> project to project matching function strings to group strings will
>>> be a common way to set up pins, and easy to understand and
>>> grasp, and it makes the DTS very readable.
>>
>> That's an interesting view, and I see the point of it being easy to read,
>> but this is partly because it doesn't convey too much actual information,
>> does it, as it requires another lookup or two.
>> And the pinctrl group nodes are actually in the .dtsi file, which are
>> typically written once during the initial SoC enablement, and new board
>> .dts files normally just reference the existing pingroup nodes. So anyone
>> dealing with just a new board is not bothered by this.
>
> You have a point, and when working with a system the application
> engineer often finds bugs in the pin control driver, and has to go
> and fix the actual driver and then all the information hiding and
> simplification is moot.
>
> This can become an expensive lesson for the current attempts
> to push pin control into firmware where the configuration is
> mostly "dead simple" (and just using strings) - the bugs will be
> in the firmware instead, and impossible or really hard to fix.
>
>> Also in my experience most people have no problems in understanding the
>> concept of pinmuxing and that there is a selector number, also where to
>> find this.
>
> Yeah the ambition with the strings was to avoid forcing application
> engineers to know all about that. If they do, they are then
> developing the driver, not just using it.
>
>>> Mediatek and STM32 made a compromise by using pinmux
>>> and adding some macros to define them so it looks more
>>> pleasant:
>>>
>>> i2c0_pins_a: i2c0-default {
>>> pins-i2c0 {
>>> pinmux = <MT7623_PIN_75_SDA0_FUNC_SDA0>,
>>> <MT7623_PIN_76_SCL0_FUNC_SCL0>;
>>
>> Well, I don't really get why they don't use the (MTK_PIN_NO(75) | 1)
>> definition directly, seems to be more telling to me?
>
> That's what STM32 does as well and it's usable.
>
> But of course it drives a truck through the initial ambition that pins
> on all systems be configured the same way, with strings. So now
> there are some families of drivers all "necessarily different" which
> is not so nice for people jumping between different SoCs, but
> very compelling for people focusing on just one SoC.
>
> Well, unless this way of doing things becomes so prevalent that
> it's the new black.
>
>> So the plan for sunxi would be: <SUNXI_PINMUX(PORTC, 23, MUX_1)>, ...
>> And this would not be really "opaque", since it has a fixed known mapping:
>> (port << 16) | (pin << 8) | (mux << 0))
>> I find this both technically elegant, because it combines all the
>> information into just one compact cell, but also readable by outsiders,
>> thanks to the macro.
>
> And a new standard, to add to the other standards, so that
> is my problem as maintainer. It makes sense on its own, and it
> complicates the bigger picture.
>
>> My main arguments against the current (string-based) approach:
>> - They require the mapping table to be in every DT user, so not only the
>> Linux kernel, but also U-Boot, FreeBSD, you name it...
>
> That's true.
>
> This comes from the DT ambition to describe hardware and config,
> but not *define* hardware, i.e. to stop device tree to turn into
> Verilog or SystemC, which is what will happen if we take the
> 1:1 reflection of hardware to device tree too far.
>
> I don't think anyone really knows where to cut the line.
>
>> - The tables are getting quite large, and they pollute the single image
>> Linux kernel, with tons of very specific information for a number of very
>> pitiful Allwinner SoCs. At the moment the tally is at 145KB of code+data
>> for the existing arm64 SoCs, with the newer SoCs ever growing (H616 alone
>> is 27KB, A523 would be quite larger even, I guess 40K). The new A523
>> specific pinctrl support adds 872 Bytes.
>
> This is a generic problem though, look at GPU drivers.
>
> The community (especially Android) seem set on fixing this by using
> modules.
>
>> - Most of the mappings are untested at pinctrl driver commit time, since we
>> don't have the device drivers ready yet - by a margin. The new approach
>> would add the pinmux values when we need them and can test them.
>
> I like this argument the best.
>
> However this also reads "upfront firmware to handle pin control is a
> dead end" yet there are people dedicatedly working on exactly that.
> (Not that its' the Allwinner developers' problem...)
>
>> - The comments in the table give away that something is not quite right:
>> SUNXI_FUNCTION(0x2, "i2c0")), /* SDA */
>> This is just a comment, so has no relevance for the code, but it's not
>> meant for humans either. Yet we try to make this correct and maintain
>> it. Odd.
>
> So i2c0 is SDA and i2c1 is SCL or something?
> It seems common, but yeah it can be confusing.
>
> Yours,
> Linus Walleij
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH 10/12] dt-bindings: phy: allwinner: add v853 usb phy
2025-01-15 7:51 ` Vinod Koul
@ 2025-01-17 7:26 ` András Szemző
2025-01-17 10:39 ` Andre Przywara
1 sibling, 0 replies; 50+ messages in thread
From: András Szemző @ 2025-01-17 7:26 UTC (permalink / raw)
To: Vinod Koul
Cc: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
Linus Walleij, Philipp Zabel, Maxime Ripard,
Kishon Vijay Abraham I, Ulf Hansson, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Uwe Kleine-König,
Florian Fainelli, linux-clk, devicetree, linux-arm-kernel,
linux-sunxi, linux-kernel, linux-phy, linux-gpio, linux-pm,
linux-riscv
> On 15 Jan 2025, at 08:51, Vinod Koul <vkoul@kernel.org> wrote:
>
> On 10-01-25, 13:39, Andras Szemzo wrote:
>> Document Allwinner v853 USB phy.
>>
>> Signed-off-by: Andras Szemzo <szemzo.andras@gmail.com>
>> ---
>> .../phy/allwinner,sun8i-v853-usb-phy.yaml | 89 +++++++++++++++++++
>> 1 file changed, 89 insertions(+)
>> create mode 100644 Documentation/devicetree/bindings/phy/allwinner,sun8i-v853-usb-phy.yaml
>>
>> diff --git a/Documentation/devicetree/bindings/phy/allwinner,sun8i-v853-usb-phy.yaml b/Documentation/devicetree/bindings/phy/allwinner,sun8i-v853-usb-phy.yaml
>> new file mode 100644
>> index 000000000000..773c3f476db8
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/phy/allwinner,sun8i-v853-usb-phy.yaml
>> @@ -0,0 +1,89 @@
>> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
>> +%YAML 1.2
>> +---
>> +$id: http://devicetree.org/schemas/phy/allwinner,sun8i-v853-usb-phy.yaml#
>> +$schema: http://devicetree.org/meta-schemas/core.yaml#
>> +
>> +title: Allwinner V853 USB PHY
>> +
>> +maintainers:
>> + - Chen-Yu Tsai <wens@csie.org>
>> + - Maxime Ripard <mripard@kernel.org>
>> +
>> +properties:
>> + "#phy-cells":
>> + const: 1
>> +
>> + compatible:
>> + const:
>> + - allwinner,sun8i-v853-usb-phy
>
> Does this really need a new binding document, if so why... Cant this be
> added to one of the existing docs which driver uses?
>
Yes, that was my first intention too, but didn’t know how to do it propery, but I’ll remove it
and add to one of the existing doc.
> --
> ~Vinod
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH 10/12] dt-bindings: phy: allwinner: add v853 usb phy
2025-01-15 7:51 ` Vinod Koul
2025-01-17 7:26 ` András Szemző
@ 2025-01-17 10:39 ` Andre Przywara
1 sibling, 0 replies; 50+ messages in thread
From: Andre Przywara @ 2025-01-17 10:39 UTC (permalink / raw)
To: Vinod Koul
Cc: Andras Szemzo, Michael Turquette, Stephen Boyd, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Chen-Yu Tsai, Jernej Skrabec,
Samuel Holland, Linus Walleij, Philipp Zabel, Maxime Ripard,
Kishon Vijay Abraham I, Ulf Hansson, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Uwe Kleine-König,
Florian Fainelli, linux-clk, devicetree, linux-arm-kernel,
linux-sunxi, linux-kernel, linux-phy, linux-gpio, linux-pm,
linux-riscv
On Wed, 15 Jan 2025 07:51:50 +0000
Vinod Koul <vkoul@kernel.org> wrote:
> On 10-01-25, 13:39, Andras Szemzo wrote:
> > Document Allwinner v853 USB phy.
> >
> > Signed-off-by: Andras Szemzo <szemzo.andras@gmail.com>
> > ---
> > .../phy/allwinner,sun8i-v853-usb-phy.yaml | 89 +++++++++++++++++++
> > 1 file changed, 89 insertions(+)
> > create mode 100644 Documentation/devicetree/bindings/phy/allwinner,sun8i-v853-usb-phy.yaml
> >
> > diff --git a/Documentation/devicetree/bindings/phy/allwinner,sun8i-v853-usb-phy.yaml b/Documentation/devicetree/bindings/phy/allwinner,sun8i-v853-usb-phy.yaml
> > new file mode 100644
> > index 000000000000..773c3f476db8
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/phy/allwinner,sun8i-v853-usb-phy.yaml
> > @@ -0,0 +1,89 @@
> > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> > +%YAML 1.2
> > +---
> > +$id: http://devicetree.org/schemas/phy/allwinner,sun8i-v853-usb-phy.yaml#
> > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > +
> > +title: Allwinner V853 USB PHY
> > +
> > +maintainers:
> > + - Chen-Yu Tsai <wens@csie.org>
> > + - Maxime Ripard <mripard@kernel.org>
> > +
> > +properties:
> > + "#phy-cells":
> > + const: 1
> > +
> > + compatible:
> > + const:
> > + - allwinner,sun8i-v853-usb-phy
>
> Does this really need a new binding document, if so why... Cant this be
> added to one of the existing docs which driver uses?
The USB-PHY bindings don't differ too much on a first glance, but still
enough in nasty details (number of PHYs supported, number of clocks
required, etc.) to make a joint binding basically unreadable (we tried
that). That's why we opted to have separate bindings.
Now I believe it's worth to look for the closest existing binding, and
just put the compatible in there, in the hope we don't need much else, and
that it still stays readable.
Cheers,
Andre
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH 03/12] pinctrl: sunxi: add driver for Allwinner V853.
2025-01-16 9:34 ` Linus Walleij
2025-01-17 7:25 ` András Szemző
@ 2025-01-17 14:52 ` Andre Przywara
2025-01-22 13:30 ` Linus Walleij
2025-01-17 15:43 ` Chen-Yu Tsai
2 siblings, 1 reply; 50+ messages in thread
From: Andre Przywara @ 2025-01-17 14:52 UTC (permalink / raw)
To: Linus Walleij
Cc: Andras Szemzo, Michael Turquette, Stephen Boyd, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Chen-Yu Tsai, Jernej Skrabec,
Samuel Holland, Philipp Zabel, Maxime Ripard, Vinod Koul,
Kishon Vijay Abraham I, Ulf Hansson, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Uwe Kleine-König,
Florian Fainelli, linux-clk, devicetree, linux-arm-kernel,
linux-sunxi, linux-kernel, linux-phy, linux-gpio, linux-pm,
linux-riscv
On Thu, 16 Jan 2025 10:34:26 +0100
Linus Walleij <linus.walleij@linaro.org> wrote:
Hi Linus,
> some nice talk here, actually the following is just opinions, I will
> be likely happy with whatever approach is taken eventually.
it's indeed an intriguing discussion, made me think a bit ...
And thanks for describing your maintainer's view, that's definitely
helpful.
> On Wed, Jan 15, 2025 at 4:26 PM Andre Przywara <andre.przywara@arm.com> wrote:
>
> > > pio: pinctrl@1c20800 {
> > > compatible = "allwinner,sun8i-r40-pinctrl";
> > > (...)
> > > i2c0_pins: i2c0-pins {
> > > pins = "PB0", "PB1";
> > > function = "i2c0";
> > > };
> > >
> > > abstract, strings, nice. The driver handles the particulars.
> >
> > What bugs me about this it that this has quite some seemingly redundant
> > information (Who would have thought that the i2c0 pins use function
> > "i2c0"?), but misses out on the actual 4 bits(!) of information.
>
> the pins in this example are called PB0 and PB1 though. The designation
> on the package. And often pins actually named "i2c0_1" "i2c0_2" are
> for that primary function, but muxable to a few other functions,
> at least GPIO in most cases. So it's just some name for the pin
> really.
Sure, there is information in the form that marks those two pins for
being usable as I2C pins. But I feel like the function parameter is not
living up to its promise (see below).
> > > That is like so because we are designing for users which are
> > > let's say customization engineers. If these engineers jump from
> > > project to project matching function strings to group strings will
> > > be a common way to set up pins, and easy to understand and
> > > grasp, and it makes the DTS very readable.
> >
> > That's an interesting view, and I see the point of it being easy to read,
> > but this is partly because it doesn't convey too much actual information,
> > does it, as it requires another lookup or two.
> > And the pinctrl group nodes are actually in the .dtsi file, which are
> > typically written once during the initial SoC enablement, and new board
> > .dts files normally just reference the existing pingroup nodes. So anyone
> > dealing with just a new board is not bothered by this.
>
> You have a point, and when working with a system the application
> engineer often finds bugs in the pin control driver, and has to go
> and fix the actual driver and then all the information hiding and
> simplification is moot.
>
> This can become an expensive lesson for the current attempts
> to push pin control into firmware where the configuration is
> mostly "dead simple" (and just using strings) - the bugs will be
> in the firmware instead, and impossible or really hard to fix.
... in that old embedded world where firmware is an opaque closed source
unfixable blob. Mainline Allwinner is all "organic": we have upstreamed
U-Boot and TF-A support, actively maintained, plus an Open Source
management firmware. Updating the firmware is a matter of "dd" or
"flashcp" - at least in theory. And I'd rather think of the kernel being
not easy to change - think Debian installer image, or getting it upstream
first, then backported, then picked up by a distro.
But I think this discussion slightly digresses here - at least following it
would double the length of this email ;-)
> > Also in my experience most people have no problems in understanding the
> > concept of pinmuxing and that there is a selector number, also where to
> > find this.
>
> Yeah the ambition with the strings was to avoid forcing application
> engineers to know all about that. If they do, they are then
> developing the driver, not just using it.
I'd argue that an application engineer just has to choose the right
pingroup DT node:
pinctrl-0 = <&i2c2_pb_pins>;
In the worst case they go ahead and ask their hardware buddy, and create
a new pingroup node. In my experience the typical Allwinner users are more
on the hardware side, so are no strangers to looking up data sheets.
> > > Mediatek and STM32 made a compromise by using pinmux
> > > and adding some macros to define them so it looks more
> > > pleasant:
> > >
> > > i2c0_pins_a: i2c0-default {
> > > pins-i2c0 {
> > > pinmux = <MT7623_PIN_75_SDA0_FUNC_SDA0>,
> > > <MT7623_PIN_76_SCL0_FUNC_SCL0>;
> >
> > Well, I don't really get why they don't use the (MTK_PIN_NO(75) | 1)
> > definition directly, seems to be more telling to me?
>
> That's what STM32 does as well and it's usable.
>
> But of course it drives a truck through the initial ambition that pins
> on all systems be configured the same way, with strings. So now
> there are some families of drivers all "necessarily different" which
> is not so nice for people jumping between different SoCs, but
> very compelling for people focusing on just one SoC.
Ah, I think I get your point.
> Well, unless this way of doing things becomes so prevalent that
> it's the new black.
That is actually a good argument: At the moment I am happy with my
proposal (the allwinner,pinmux = <number>; property), but that seems like
standard #15 then.
So would biting the bullet and adopting the Apple/STM32 way then be more
sustainable?
On the other hand: the allwinner,pinmux solution has the advantage of being
already written and proven working, also it stays very close to the
existing description/binding - so implementations like U-Boot could just
keep on using the "function" string.
I am a bit torn here... I don't think I will find the solitude to
implement this "Apple" approach in the next few weeks.
> > So the plan for sunxi would be: <SUNXI_PINMUX(PORTC, 23, MUX_1)>, ...
> > And this would not be really "opaque", since it has a fixed known mapping:
> > (port << 16) | (pin << 8) | (mux << 0))
> > I find this both technically elegant, because it combines all the
> > information into just one compact cell, but also readable by outsiders,
> > thanks to the macro.
>
> And a new standard, to add to the other standards, so that
> is my problem as maintainer. It makes sense on its own, and it
> complicates the bigger picture.
I see your point - xkcd 927.
> > My main arguments against the current (string-based) approach:
> > - They require the mapping table to be in every DT user, so not only the
> > Linux kernel, but also U-Boot, FreeBSD, you name it...
>
> That's true.
>
> This comes from the DT ambition to describe hardware and config,
> but not *define* hardware, i.e. to stop device tree to turn into
> Verilog or SystemC, which is what will happen if we take the
> 1:1 reflection of hardware to device tree too far.
>
> I don't think anyone really knows where to cut the line.
That's true, and I learned to step back from this ambition - it's
tempting, but indeed out of scope.
One thing to consider, though: the function names are effectively part of
the binding, since they must match exactly between the driver and DT - it's
not just a name. But they are documented nowhere. Names like "i2c0" or
"uart2" seem obvious, but there are ambiguities like "twi" vs "i2c" (the
former used in the vendor BSP), or "owa" vs "spdif" (same situation).
Also, is it "emac" or "emac0"? For some SoCs we discover a second
interface later: A523 just exposes one EMAC, but the A527 package (same
die) provides the pins for the second MAC as well. So I am afraid strings
are not as unique or straight-forward as we hope for.
So for creating a new pingroup, an application engineer would need to
check the Linux driver (or U-Boot? Or FreeBSD?) for the name to use - that
sounds somewhat wrong to me.
In the new model they just create a unique function name and enter the
pinmux from the datasheet - I think that's not too much to ask?
> > - The tables are getting quite large, and they pollute the single image
> > Linux kernel, with tons of very specific information for a number of very
> > pitiful Allwinner SoCs. At the moment the tally is at 145KB of code+data
> > for the existing arm64 SoCs, with the newer SoCs ever growing (H616 alone
> > is 27KB, A523 would be quite larger even, I guess 40K). The new A523
> > specific pinctrl support adds 872 Bytes.
>
> This is a generic problem though, look at GPU drivers.
Yes, but for GPUs there is good rationale (because they are big
complicated pieces of hardware), and they are easily put into modules.
Pinctrl on the other hand is essential for *any* device to come up
(UART!), so having them in the image makes things much easier. Also
Allwinner pinctrl devices are not nearly as sexy as a Radeon or Geforce ;-)
> The community (especially Android) seem set on fixing this by using
> modules.
>
> > - Most of the mappings are untested at pinctrl driver commit time, since we
> > don't have the device drivers ready yet - by a margin. The new approach
> > would add the pinmux values when we need them and can test them.
>
> I like this argument the best.
>
> However this also reads "upfront firmware to handle pin control is a
> dead end" yet there are people dedicatedly working on exactly that.
> (Not that its' the Allwinner developers' problem...)
I see, but I feel it's an orthogonal problem, and relies on the a
pessimistic firmware view (see above).
Having those gory SoC specific details in firmware (which is by
definition device specific) solves one big problem, though: there is a
chance that existing kernels would already run on new SoCs/boards.
But again: different discussion thread, I guess, and not what I ask for.
> > - The comments in the table give away that something is not quite right:
> > SUNXI_FUNCTION(0x2, "i2c0")), /* SDA */
> > This is just a comment, so has no relevance for the code, but it's not
> > meant for humans either. Yet we try to make this correct and maintain
> > it. Odd.
>
> So i2c0 is SDA and i2c1 is SCL or something?
No, sorry, I cut out too much, it looks like this:
SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 5),
SUNXI_FUNCTION(0x5, "i2c0"), /* SCK */
...
SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 6),
SUNXI_FUNCTION(0x5, "i2c0"), /* SDA */
...
SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 7),
SUNXI_FUNCTION(0x5, "i2c1"), /* SCK */
...
SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 8),
SUNXI_FUNCTION(0x5, "i2c1"), /* SDA */
So the function just selects the group, and the actual pin name is
completely irrelevant to the software side - hence the comment.
But this "put something not meant for the human reader into a comment"
typically points to something not being quite right.
Cheers,
Andre
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH 03/12] pinctrl: sunxi: add driver for Allwinner V853.
2025-01-16 9:34 ` Linus Walleij
2025-01-17 7:25 ` András Szemző
2025-01-17 14:52 ` Andre Przywara
@ 2025-01-17 15:43 ` Chen-Yu Tsai
2 siblings, 0 replies; 50+ messages in thread
From: Chen-Yu Tsai @ 2025-01-17 15:43 UTC (permalink / raw)
To: Linus Walleij
Cc: Andre Przywara, Andras Szemzo, Michael Turquette, Stephen Boyd,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Jernej Skrabec,
Samuel Holland, Philipp Zabel, Maxime Ripard, Vinod Koul,
Kishon Vijay Abraham I, Ulf Hansson, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Uwe Kleine-König,
Florian Fainelli, linux-clk, devicetree, linux-arm-kernel,
linux-sunxi, linux-kernel, linux-phy, linux-gpio, linux-pm,
linux-riscv
On Thu, Jan 16, 2025 at 5:34 PM Linus Walleij <linus.walleij@linaro.org> wrote:
>
> Hi Andre,
>
> some nice talk here, actually the following is just opinions, I will
> be likely happy with whatever approach is taken eventually.
>
> On Wed, Jan 15, 2025 at 4:26 PM Andre Przywara <andre.przywara@arm.com> wrote:
>
> > > pio: pinctrl@1c20800 {
> > > compatible = "allwinner,sun8i-r40-pinctrl";
> > > (...)
> > > i2c0_pins: i2c0-pins {
> > > pins = "PB0", "PB1";
> > > function = "i2c0";
> > > };
> > >
> > > abstract, strings, nice. The driver handles the particulars.
> >
> > What bugs me about this it that this has quite some seemingly redundant
> > information (Who would have thought that the i2c0 pins use function
> > "i2c0"?), but misses out on the actual 4 bits(!) of information.
>
> the pins in this example are called PB0 and PB1 though. The designation
> on the package. And often pins actually named "i2c0_1" "i2c0_2" are
> for that primary function, but muxable to a few other functions,
> at least GPIO in most cases. So it's just some name for the pin
> really.
No. Allwinner actually names their pins like this, kind of like Rockchip
which provides standardized names such as "GPIO0_B2", but unlike MediaTek
which just names the pins after their designated primary function such as
"EINT22" or "TDM_BCLK". The ball names are a separate thing.
Even though the pin names seem a bit random, there's actually a grouping
logic underneath:
- PC pins are always for the bootable internal storage (NAND, SPI-NOR, eMMC)
- PF pins are always the external SD card / debug UART / JTAG
> > > That is like so because we are designing for users which are
> > > let's say customization engineers. If these engineers jump from
> > > project to project matching function strings to group strings will
> > > be a common way to set up pins, and easy to understand and
> > > grasp, and it makes the DTS very readable.
> >
> > That's an interesting view, and I see the point of it being easy to read,
> > but this is partly because it doesn't convey too much actual information,
> > does it, as it requires another lookup or two.
> > And the pinctrl group nodes are actually in the .dtsi file, which are
> > typically written once during the initial SoC enablement, and new board
> > .dts files normally just reference the existing pingroup nodes. So anyone
> > dealing with just a new board is not bothered by this.
>
> You have a point, and when working with a system the application
> engineer often finds bugs in the pin control driver, and has to go
> and fix the actual driver and then all the information hiding and
> simplification is moot.
>
> This can become an expensive lesson for the current attempts
> to push pin control into firmware where the configuration is
> mostly "dead simple" (and just using strings) - the bugs will be
> in the firmware instead, and impossible or really hard to fix.
>
> > Also in my experience most people have no problems in understanding the
> > concept of pinmuxing and that there is a selector number, also where to
> > find this.
>
> Yeah the ambition with the strings was to avoid forcing application
> engineers to know all about that. If they do, they are then
> developing the driver, not just using it.
>
> > > Mediatek and STM32 made a compromise by using pinmux
> > > and adding some macros to define them so it looks more
> > > pleasant:
> > >
> > > i2c0_pins_a: i2c0-default {
> > > pins-i2c0 {
> > > pinmux = <MT7623_PIN_75_SDA0_FUNC_SDA0>,
> > > <MT7623_PIN_76_SCL0_FUNC_SCL0>;
> >
> > Well, I don't really get why they don't use the (MTK_PIN_NO(75) | 1)
> > definition directly, seems to be more telling to me?
>
> That's what STM32 does as well and it's usable.
>
> But of course it drives a truck through the initial ambition that pins
> on all systems be configured the same way, with strings. So now
> there are some families of drivers all "necessarily different" which
> is not so nice for people jumping between different SoCs, but
> very compelling for people focusing on just one SoC.
>
> Well, unless this way of doing things becomes so prevalent that
> it's the new black.
>
> > So the plan for sunxi would be: <SUNXI_PINMUX(PORTC, 23, MUX_1)>, ...
> > And this would not be really "opaque", since it has a fixed known mapping:
> > (port << 16) | (pin << 8) | (mux << 0))
> > I find this both technically elegant, because it combines all the
> > information into just one compact cell, but also readable by outsiders,
> > thanks to the macro.
>
> And a new standard, to add to the other standards, so that
> is my problem as maintainer. It makes sense on its own, and it
> complicates the bigger picture.
>
> > My main arguments against the current (string-based) approach:
> > - They require the mapping table to be in every DT user, so not only the
> > Linux kernel, but also U-Boot, FreeBSD, you name it...
>
> That's true.
>
> This comes from the DT ambition to describe hardware and config,
> but not *define* hardware, i.e. to stop device tree to turn into
> Verilog or SystemC, which is what will happen if we take the
> 1:1 reflection of hardware to device tree too far.
>
> I don't think anyone really knows where to cut the line.
>
> > - The tables are getting quite large, and they pollute the single image
> > Linux kernel, with tons of very specific information for a number of very
> > pitiful Allwinner SoCs. At the moment the tally is at 145KB of code+data
> > for the existing arm64 SoCs, with the newer SoCs ever growing (H616 alone
> > is 27KB, A523 would be quite larger even, I guess 40K). The new A523
> > specific pinctrl support adds 872 Bytes.
>
> This is a generic problem though, look at GPU drivers.
>
> The community (especially Android) seem set on fixing this by using
> modules.
>
> > - Most of the mappings are untested at pinctrl driver commit time, since we
> > don't have the device drivers ready yet - by a margin. The new approach
> > would add the pinmux values when we need them and can test them.
>
> I like this argument the best.
>
> However this also reads "upfront firmware to handle pin control is a
> dead end" yet there are people dedicatedly working on exactly that.
> (Not that its' the Allwinner developers' problem...)
>
> > - The comments in the table give away that something is not quite right:
> > SUNXI_FUNCTION(0x2, "i2c0")), /* SDA */
> > This is just a comment, so has no relevance for the code, but it's not
> > meant for humans either. Yet we try to make this correct and maintain
> > it. Odd.
>
> So i2c0 is SDA and i2c1 is SCL or something?
> It seems common, but yeah it can be confusing.
No. i2c0 is the actual peripheral that gets muxed in. The SDA / SCL
comments are simply denoting which signal from the peripheral this
pin & mux value carry.
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH 03/12] pinctrl: sunxi: add driver for Allwinner V853.
2025-01-17 14:52 ` Andre Przywara
@ 2025-01-22 13:30 ` Linus Walleij
0 siblings, 0 replies; 50+ messages in thread
From: Linus Walleij @ 2025-01-22 13:30 UTC (permalink / raw)
To: Andre Przywara
Cc: Andras Szemzo, Michael Turquette, Stephen Boyd, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Chen-Yu Tsai, Jernej Skrabec,
Samuel Holland, Philipp Zabel, Maxime Ripard, Vinod Koul,
Kishon Vijay Abraham I, Ulf Hansson, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Uwe Kleine-König,
Florian Fainelli, linux-clk, devicetree, linux-arm-kernel,
linux-sunxi, linux-kernel, linux-phy, linux-gpio, linux-pm,
linux-riscv
On Fri, Jan 17, 2025 at 3:52 PM Andre Przywara <andre.przywara@arm.com> wrote:
> That is actually a good argument: At the moment I am happy with my
> proposal (the allwinner,pinmux = <number>; property), but that seems like
> standard #15 then.
> So would biting the bullet and adopting the Apple/STM32 way then be more
> sustainable?
I suppose...
> On the other hand: the allwinner,pinmux solution has the advantage of being
> already written and proven working, also it stays very close to the
> existing description/binding - so implementations like U-Boot could just
> keep on using the "function" string.
>
> I am a bit torn here... I don't think I will find the solitude to
> implement this "Apple" approach in the next few weeks.
I think whatever the Allwinner maintainers agree is the best should
be what you go for. It is a lot of hobbyist maintainers in this space
and for them the bar should be lower.
If you have buy-in from the other maintainers, then go for that
solution.
Yours,
Linus Walleij
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH 05/12] clk: sunxi-ng: add CCU drivers for V853
2025-01-10 12:39 ` [PATCH 05/12] clk: sunxi-ng: add CCU drivers " Andras Szemzo
@ 2025-01-22 23:23 ` Jeff Johnson
2025-01-23 8:58 ` András Szemző
2025-01-28 0:42 ` Andre Przywara
1 sibling, 1 reply; 50+ messages in thread
From: Jeff Johnson @ 2025-01-22 23:23 UTC (permalink / raw)
To: Andras Szemzo, Michael Turquette, Stephen Boyd, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Chen-Yu Tsai, Jernej Skrabec,
Samuel Holland, Linus Walleij, Philipp Zabel, Maxime Ripard
Cc: Vinod Koul, Kishon Vijay Abraham I, Ulf Hansson, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Uwe Kleine-König,
Florian Fainelli, linux-clk, devicetree, linux-arm-kernel,
linux-sunxi, linux-kernel, linux-phy, linux-gpio, linux-pm,
linux-riscv
On 1/10/25 04:39, Andras Szemzo wrote:> +module_platform_driver(sun8i_v853_r_ccu_driver);
> +
> +MODULE_IMPORT_NS("SUNXI_CCU");
> +MODULE_LICENSE("GPL");
Since commit 1fffe7a34c89 ("script: modpost: emit a warning when the
description is missing"), a module without a MODULE_DESCRIPTION() will
result in a warning with make W=1. Please add a MODULE_DESCRIPTION()
to avoid this warning in all of your new modules.
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH 05/12] clk: sunxi-ng: add CCU drivers for V853
2025-01-22 23:23 ` Jeff Johnson
@ 2025-01-23 8:58 ` András Szemző
0 siblings, 0 replies; 50+ messages in thread
From: András Szemző @ 2025-01-23 8:58 UTC (permalink / raw)
To: Jeff Johnson
Cc: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
Linus Walleij, Philipp Zabel, Maxime Ripard, Vinod Koul,
Kishon Vijay Abraham I, Ulf Hansson, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Uwe Kleine-König,
Florian Fainelli, linux-clk, devicetree, linux-arm-kernel,
linux-sunxi, linux-kernel, linux-phy, linux-gpio, linux-pm,
linux-riscv
> On 23 Jan 2025, at 00:23, Jeff Johnson <quic_jjohnson@quicinc.com> wrote:
>
> On 1/10/25 04:39, Andras Szemzo wrote:> +module_platform_driver(sun8i_v853_r_ccu_driver);
>> +
>> +MODULE_IMPORT_NS("SUNXI_CCU");
>> +MODULE_LICENSE("GPL");
>
> Since commit 1fffe7a34c89 ("script: modpost: emit a warning when the
> description is missing"), a module without a MODULE_DESCRIPTION() will
> result in a warning with make W=1. Please add a MODULE_DESCRIPTION()
> to avoid this warning in all of your new modules.
>
Thanks for pointing it out, I’ll add it.
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH 05/12] clk: sunxi-ng: add CCU drivers for V853
2025-01-10 12:39 ` [PATCH 05/12] clk: sunxi-ng: add CCU drivers " Andras Szemzo
2025-01-22 23:23 ` Jeff Johnson
@ 2025-01-28 0:42 ` Andre Przywara
2025-01-28 9:06 ` András Szemző
1 sibling, 1 reply; 50+ messages in thread
From: Andre Przywara @ 2025-01-28 0:42 UTC (permalink / raw)
To: Andras Szemzo
Cc: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
Linus Walleij, Philipp Zabel, Maxime Ripard, Vinod Koul,
Kishon Vijay Abraham I, Ulf Hansson, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Uwe Kleine-König,
Florian Fainelli, linux-clk, devicetree, linux-arm-kernel,
linux-sunxi, linux-kernel, linux-phy, linux-gpio, linux-pm,
linux-riscv
On Fri, 10 Jan 2025 13:39:16 +0100
Andras Szemzo <szemzo.andras@gmail.com> wrote:
Hi Andras,
oh dear, that's a code line and a half!
First very much for sending this, I know from (recent) experience that
those clock drivers can be very daunting and tedious to write
...which is unfortunately true for the review as well ;-)
So this is the first round, as I was keeping and updating this in my
Drafts folder for almost two weeks now.
> V853 has similar gates/resets like existing Allwinner SOCs. Add support for it's CCU and PRCM CCU.
>
> Signed-off-by: Andras Szemzo <szemzo.andras@gmail.com>
> ---
> drivers/clk/sunxi-ng/Kconfig | 10 +
> drivers/clk/sunxi-ng/Makefile | 4 +
> drivers/clk/sunxi-ng/ccu-sun8i-v853-r.c | 95 ++
> drivers/clk/sunxi-ng/ccu-sun8i-v853-r.h | 15 +
> drivers/clk/sunxi-ng/ccu-sun8i-v853.c | 1145 +++++++++++++++++++++++
> drivers/clk/sunxi-ng/ccu-sun8i-v853.h | 14 +
> 6 files changed, 1283 insertions(+)
> create mode 100644 drivers/clk/sunxi-ng/ccu-sun8i-v853-r.c
> create mode 100644 drivers/clk/sunxi-ng/ccu-sun8i-v853-r.h
> create mode 100644 drivers/clk/sunxi-ng/ccu-sun8i-v853.c
> create mode 100644 drivers/clk/sunxi-ng/ccu-sun8i-v853.h
>
> diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig
> index b547198a2c65..c43002246b22 100644
> --- a/drivers/clk/sunxi-ng/Kconfig
> +++ b/drivers/clk/sunxi-ng/Kconfig
> @@ -22,6 +22,16 @@ config SUN20I_D1_R_CCU
> default y
> depends on MACH_SUN8I || RISCV || COMPILE_TEST
>
> +config SUN8I_V853_CCU
> + tristate "Support for the Allwinner V853 CCU"
> + default MACH_SUN8I
> + depends on MACH_SUN8I || COMPILE_TEST
> +
> +config SUN8I_V853_R_CCU
> + tristate "Support for the Allwinner V853 PRCM CCU"
> + default MACH_SUN8I
> + depends on MACH_SUN8I || COMPILE_TEST
> +
> config SUN50I_A64_CCU
> tristate "Support for the Allwinner A64 CCU"
> default y
> diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
> index 6b3ae2b620db..c32430d874ea 100644
> --- a/drivers/clk/sunxi-ng/Makefile
> +++ b/drivers/clk/sunxi-ng/Makefile
> @@ -27,6 +27,8 @@ sunxi-ccu-y += ccu_mp.o
> obj-$(CONFIG_SUNIV_F1C100S_CCU) += suniv-f1c100s-ccu.o
> obj-$(CONFIG_SUN20I_D1_CCU) += sun20i-d1-ccu.o
> obj-$(CONFIG_SUN20I_D1_R_CCU) += sun20i-d1-r-ccu.o
> +obj-$(CONFIG_SUN8I_V853_CCU) += sun8i-v853-ccu.o
> +obj-$(CONFIG_SUN8I_V853_R_CCU) += sun8i-v853-r-ccu.o
> obj-$(CONFIG_SUN50I_A64_CCU) += sun50i-a64-ccu.o
> obj-$(CONFIG_SUN50I_A100_CCU) += sun50i-a100-ccu.o
> obj-$(CONFIG_SUN50I_A100_R_CCU) += sun50i-a100-r-ccu.o
> @@ -50,6 +52,8 @@ obj-$(CONFIG_SUN9I_A80_CCU) += sun9i-a80-de-ccu.o
> obj-$(CONFIG_SUN9I_A80_CCU) += sun9i-a80-usb-ccu.o
>
> suniv-f1c100s-ccu-y += ccu-suniv-f1c100s.o
> +sun8i-v853-ccu-y += ccu-sun8i-v853.o
> +sun8i-v853-r-ccu-y += ccu-sun8i-v853-r.o
> sun20i-d1-ccu-y += ccu-sun20i-d1.o
> sun20i-d1-r-ccu-y += ccu-sun20i-d1-r.o
> sun50i-a64-ccu-y += ccu-sun50i-a64.o
> diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-v853-r.c b/drivers/clk/sunxi-ng/ccu-sun8i-v853-r.c
> new file mode 100644
> index 000000000000..19a8ba587793
> --- /dev/null
> +++ b/drivers/clk/sunxi-ng/ccu-sun8i-v853-r.c
> @@ -0,0 +1,95 @@
> +// SPDX-License-Identifier: GPL-3.0
> +/* Copyright(c) 2020 - 2023 Allwinner Technology Co.,Ltd. All rights reserved.
So does that mean you copied that from the BSP? How much is your own
work then? Should "rengaomin" be then the author?
But more importantly: As far as I know, GPL-3 is NOT compatible with
the kernel. You definitely cannot add code with that license, and from
my understanding cannot copy GPL-3 code without keeping the license,
which means copying is a no-go.
You would need to ask the original author to change the license. I have
seen license changes in github repos mirroring Allwinner's SDK in the
last few months (someone must have told them?), so it's worth checking
back there to see if the license has changed.
But with that header, and with that source (subject to clarification)
this cannot be merged as such.
> + *
> + * Copyright (c) 2023 rengaomin@allwinnertech.com
> + */
> +
> +#include <linux/clk-provider.h>
> +#include <linux/io.h>
> +#include <linux/module.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-sun8i-v853-r.h"
> +
> +
> +static SUNXI_CCU_GATE(r_twd_clk, "r-twd", "osc24M", 0x012C, BIT(0), 0);
> +static SUNXI_CCU_GATE(r_ppu_clk, "r-ppu", "osc24M", 0x01AC, BIT(0), 0);
> +static SUNXI_CCU_GATE(r_rtc_clk, "r-rtc", "osc24M", 0x020C, BIT(0), 0);
> +static SUNXI_CCU_GATE(r_cpucfg_clk, "r-cpucfg", "osc24M",
> + 0x022C, BIT(0), 0);
> +
> +static struct ccu_reset_map sun8i_v853_r_ccu_resets[] = {
> + [RST_BUS_R_PPU] = { 0x01ac, BIT(16) },
> + [RST_BUS_R_RTC] = { 0x020c, BIT(16) },
> + [RST_BUS_R_CPUCFG] = { 0x022c, BIT(16) },
> +};
> +
> +static struct clk_hw_onecell_data sun8i_v853_r_hw_clks = {
> + .hws = {
> + [CLK_R_TWD] = &r_twd_clk.common.hw,
> + [CLK_R_PPU] = &r_ppu_clk.common.hw,
> + [CLK_R_RTC] = &r_rtc_clk.common.hw,
> + [CLK_R_CPUCFG] = &r_cpucfg_clk.common.hw,
> + },
> + .num = CLK_NUMBER,
> +};
> +
> +static struct ccu_common *sun8i_v853_r_ccu_clks[] = {
> + &r_twd_clk.common,
> + &r_ppu_clk.common,
> + &r_rtc_clk.common,
> + &r_cpucfg_clk.common,
> +};
> +
> +
> +static const struct sunxi_ccu_desc sun8i_v853_r_ccu_desc = {
> + .ccu_clks = sun8i_v853_r_ccu_clks,
> + .num_ccu_clks = ARRAY_SIZE(sun8i_v853_r_ccu_clks),
> +
> + .hw_clks = &sun8i_v853_r_hw_clks,
> +
> + .resets = sun8i_v853_r_ccu_resets,
> + .num_resets = ARRAY_SIZE(sun8i_v853_r_ccu_resets),
> +};
> +
> +static int sun8i_v853_r_ccu_probe(struct platform_device *pdev)
> +{
> + void __iomem *reg;
> +
> + reg = devm_platform_ioremap_resource(pdev, 0);
> + if (IS_ERR(reg))
> + return PTR_ERR(reg);
> +
> + return devm_sunxi_ccu_probe(&pdev->dev, reg, &sun8i_v853_r_ccu_desc);
> +}
> +
> +static const struct of_device_id sun8i_v853_r_ccu_ids[] = {
> + { .compatible = "allwinner,sun8i-v853-r-ccu" },
> + { }
> +};
> +
> +static struct platform_driver sun8i_v853_r_ccu_driver = {
> + .probe = sun8i_v853_r_ccu_probe,
> + .driver = {
> + .name = "sun8i-v853-r-ccu",
> + .suppress_bind_attrs = true,
> + .of_match_table = sun8i_v853_r_ccu_ids,
> + },
> +};
> +module_platform_driver(sun8i_v853_r_ccu_driver);
> +
> +MODULE_IMPORT_NS("SUNXI_CCU");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-v853-r.h b/drivers/clk/sunxi-ng/ccu-sun8i-v853-r.h
> new file mode 100644
> index 000000000000..156ca15e8208
> --- /dev/null
> +++ b/drivers/clk/sunxi-ng/ccu-sun8i-v853-r.h
> @@ -0,0 +1,15 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
Here the license looks right, but the authorship and source are still
in question. Looks like the only real code in here is CLK_NUMBER, so if
that is your line, drop all those bogus copyrights, and put in your own.
> +/* Copyright(c) 2020 - 2023 Allwinner Technology Co.,Ltd. All rights reserved.
> + *
> + * Copyright (c) 2023 rengaomin@allwinnertech.com
> + */
> +
> +#ifndef _CCU_SUN8I_V853_R_H
> +#define _CCU_SUN8I_V853_R_H
> +
> +#include <dt-bindings/clock/sun8i-v853-r-ccu.h>
> +#include <dt-bindings/reset/sun8i-v853-r-ccu.h>
> +
> +#define CLK_NUMBER CLK_R_MAX_NO
What's "CLK_R_MAX_NO"? I think we put in the actual last clock name in,
traditionally?
> +
> +#endif
> diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-v853.c b/drivers/clk/sunxi-ng/ccu-sun8i-v853.c
> new file mode 100644
> index 000000000000..a1947357a08e
> --- /dev/null
> +++ b/drivers/clk/sunxi-ng/ccu-sun8i-v853.c
> @@ -0,0 +1,1145 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (C) 2024 Andras Szemzo <szemzo.andras@gmail.com>
> + *
> + * Based on ccu-sun20i-d1.c, which is:
> + * Copyright (C) 2021 Samuel Holland. All rights reserved.
All rights reserved? Where does that come from? Please remove that.
> + */
> +
> +#include <linux/clk-provider.h>
> +#include <linux/io.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +
> +#include "../clk.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-sun8i-v853.h"
> +
> +static const struct clk_parent_data osc24M[] = {
> + { .fw_name = "hosc" }
> +};
> +
> +/*
> + * For the CPU PLL, the output divider is described as "only for testing"
> + * in the user manual. So it's not modelled and forced to 0.
> + */
> +#define SUN8I_V853_PLL_CPU_REG 0x000
> +
> +static struct ccu_mult pll_cpu_clk = {
> + .enable = BIT(27) | BIT(30) | BIT(31),
But bit 30 and 31 are set already by the PLL loop in the probe routine
below, so we just need bit 27 to gate the output.
> + .lock = BIT(28),
> + .mult = _SUNXI_CCU_MULT_MIN(8, 8, 12),
technically the manual says the minimum is 11, though this doesn't
really matter, as we will never go that low anyway.
> + .common = {
> + .reg = 0x000,
> + .hw.init = CLK_HW_INIT_PARENTS_DATA("pll-cpu", osc24M,
> + &ccu_mult_ops,
> + CLK_SET_RATE_UNGATE),
This must be CLK_SET_RATE_GATE, as we figured some weeks ago. The manual
says that for changing the frequency you must leave the PLL enabled
(bits 31 and 30 = 1), but gate the output (bit 27 = 0). The "GATE" in
that flag name here refers to the .enable mask above.
So CLK_SET_RATE_UNGATE would mean: don't touch the enable bit, but keep
it running, which would be correct if the enable bit would be about the
real enable bit (bit 31). But since we model this like "enable means not
gated", we must gate the output, by setting the enable bit to 0.
CLK_SET_RATE_GATE does exactly that.
> + },
> +};
> +
> +/* Some PLLs are input * N / div1 / P. Model them as NKMP with no K */
> +#define SUN8I_V853_PLL_DDR_REG 0x010
> +static struct ccu_nkmp pll_ddr_clk = {
> + .enable = BIT(27) | BIT(30) | BIT(31),
same here, only bit 27 please.
> + .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_PARENTS_DATA("pll-ddr", osc24M,
> + &ccu_nkmp_ops,
> + CLK_SET_RATE_UNGATE),
CLK_SET_RATE_GATE, as above.
> + },
> +};
> +
> +#define SUN8I_V853_PLL_PERIPH_REG 0x020
> +static struct ccu_nm pll_periph_4x_clk = {
> + .enable = BIT(27) | BIT(30) | BIT(31),
BIT(27), as above, and further down as well
> + .lock = BIT(28),
> + .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
> + .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
> + .common = {
> + .reg = 0x020,
> + .hw.init = CLK_HW_INIT_PARENTS_DATA("pll-periph-4x", osc24M,
> + &ccu_nm_ops,
> + CLK_SET_RATE_UNGATE),
you guessed it: CLK_SET_RATE_GATE, here and further below, please
> + },
> +};
> +
> +static SUNXI_CCU_M(pll_periph_2x_clk, "pll-periph-2x", "pll-periph-4x",
> + 0x020, 16, 3, 0);
So is there a recommendation about how we reference other clocks? This
one here is using the clock name, which requires a look-up, where we
could use the pointer directly as well, as done down below.
static const struct clk_hw *pll_periph0_4x_hws[] = {
&pll_periph0_4x_clk.common.hw
};
static SUNXI_CCU_M_HWS(pll_periph0_2x_clk, "pll-periph0-2x",
pll_periph0_4x_hws, 0x020, 16, 3, 0);
I have seen both, sun20i-d1 for instance uses this, and I copied from
there for the A523 clock code.
Would be glad to hear some maintainer's opinion.
> +
> +static SUNXI_CCU_M(pll_periph_800M_clk, "pll-periph-800M", "pll-periph-4x",
> + 0x020, 20, 3, 0);
> +
> +static SUNXI_CCU_M(pll_periph_480M_clk, "pll-periph-480M", "pll-periph-4x",
> + 0x020, 2, 3, 0);
> +
> +static CLK_FIXED_FACTOR_HW(pll_periph_600M_clk, "pll-periph-600M",
> + &pll_periph_2x_clk.common.hw, 2, 1, 0);
> +
> +static CLK_FIXED_FACTOR_HW(pll_periph_400M_clk, "pll-periph-400M",
> + &pll_periph_2x_clk.common.hw, 3, 1, 0);
> +
> +static CLK_FIXED_FACTOR_HW(pll_periph_300M_clk, "pll-periph-300M",
> + &pll_periph_600M_clk.hw, 2, 1, 0);
> +
> +static CLK_FIXED_FACTOR_HW(pll_periph_200M_clk, "pll-periph-200M",
> + &pll_periph_400M_clk.hw, 2, 1, 0);
> +
> +static CLK_FIXED_FACTOR_HW(pll_periph_160M_clk, "pll-periph-160M",
> + &pll_periph_480M_clk.common.hw, 3, 1, 0);
> +
> +static CLK_FIXED_FACTOR_HW(pll_periph_150M_clk, "pll-periph-150M",
> + &pll_periph_300M_clk.hw, 2, 1, 0);
> +
> +
> +/*
> + * For Video PLLs, the output divider is described as "only for testing"
> + * in the user manual. So it's not modelled and forced to 0.
That's a bit confusing: the manual says that the default value for bit 0
is 0x1, and that it's "only for testing", which would mean we should
leave it like this, always dividing by 2? In the main description (bit
31) it says:
VIDEOPLL4X = InputFreq*N/M
but below (bit 0) it's
VIDEOPLL4X = 24MHz*N/M/D
(with D being "PLL_OUTPUT_DIV_D + 1", so 2 in our case)
Do you have any indication how fast the video PLL really is? If it is
divided by 2 (as we force that bit to 1 down in the probe routine), then
we would need to model this with that CCU_FEATURE_FIXED_POSTDIV flag,
and either leave that bit alone or force it to 1 instead.
Also would be good to see what the BSP does.
> + */
> +#define SUN8I_V853_PLL_VIDEO_REG 0x040
> +static struct ccu_nm pll_video_4x_clk = {
> + .enable = BIT(27) | BIT(30) | BIT(31),
> + .lock = BIT(28),
> + .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
The manual says 11 (but again doesn't matter).
> + .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
> + .common = {
> + .reg = 0x040,
> + .hw.init = CLK_HW_INIT_PARENTS_DATA("pll-video-4x", osc24M,
> + &ccu_nm_ops,
> + CLK_SET_RATE_UNGATE),
> + },
> +};
> +
> +static const struct clk_hw *pll_video_4x_hws[] = {
> + &pll_video_4x_clk.common.hw
> +};
> +static CLK_FIXED_FACTOR_HWS(pll_video_2x_clk, "pll-video-2x",
> + pll_video_4x_hws, 2, 1, CLK_SET_RATE_PARENT);
> +static CLK_FIXED_FACTOR_HWS(pll_video_1x_clk, "pll-video-1x",
> + pll_video_4x_hws, 4, 1, CLK_SET_RATE_PARENT);
Ah, here you are using the pointer reference to the base clock, not the
string, as above. I think we should stick to one method?
> +/*
> + * For CSI PLLs, the output divider is described as "only for testing"
> + * in the user manual. So it's not modelled and forced to 0.
Same situation as for the video PLL: what is the recommended setting of
bit 0, really?
> + */
> +#define SUN8I_V853_PLL_CSI_REG 0x048
> +static struct ccu_nm pll_csi_4x_clk = {
> + .enable = BIT(27) | BIT(30) | BIT(31),
> + .lock = BIT(28),
> + .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
> + .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
> + .common = {
> + .reg = 0x048,
> + .hw.init = CLK_HW_INIT_PARENTS_DATA("pll-csi-4x", osc24M,
> + &ccu_nm_ops,
> + CLK_SET_RATE_UNGATE),
> + },
> +};
> +
> +static CLK_FIXED_FACTOR_HW(pll_csi_clk, "pll-csi",
> + &pll_csi_4x_clk.common.hw, 4, 1, CLK_SET_RATE_PARENT);
> +
> +
> +#define SUN8I_V853_PLL_AUDIO_REG 0x78
> +static struct ccu_sdm_setting pll_audio_div5_sdm_table[] = {
> + { .rate = 196608000, .pattern = 0xc001eb85, .m = 5, .n = 40 }, /* 24.576 */
> + { .rate = 67737600, .pattern = 0xc001288d, .m = 8, .n = 22 }, /* 22.5792 */
> +};
> +
> +static struct ccu_nm pll_audio_div5_clk = {
> + .enable = BIT(27) | BIT(30) | BIT(31),
> + .lock = BIT(28),
> + .n = _SUNXI_CCU_MULT(8, 8),
> + .m = _SUNXI_CCU_DIV(20, 3),
> + .sdm = _SUNXI_CCU_SDM(pll_audio_div5_sdm_table,
> + BIT(24), 0x0178, BIT(31)),
> + .common = {
> + .reg = 0x0078,
> + .features = CCU_FEATURE_SIGMA_DELTA_MOD,
> + .hw.init = CLK_HW_INIT_PARENTS_DATA("pll-audio-div5", osc24M,
> + &ccu_nm_ops,
> + CLK_SET_RATE_UNGATE),
> + },
> +};
> +static SUNXI_CCU_M(pll_audio_1x_clk, "pll-audio-1x", "pll-audio-div5",
> + 0xe00, 0, 5, CLK_SET_RATE_PARENT);
> +
> +/* pll-audio-div2 and pll-aduio-4x not used, because audio-1x can cover 22.5792M and 24.576M */
> +static SUNXI_CCU_M(pll_audio_div2_clk, "pll-audio-div2", "pll-audio",
> + 0x078, 16, 3, 0);
> +static SUNXI_CCU_M(pll_audio_4x_clk, "pll-audio-4x", "pll-audio-div2",
> + 0xe00, 5, 5, 0);
> +
> +/*
> + * For the NPU PLL, the output divider is described as "only for testing"
> + * in the user manual. So it's not modelled and forced to 0.
> + */
> +#define SUN8I_V853_PLL_NPU_REG 0x080
> +static struct ccu_nm pll_npu_4x_clk = {
> + .enable = BIT(27) | BIT(30) | BIT(31),
> + .lock = BIT(28),
> + .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
> + .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
> + .common = {
> + .reg = 0x080,
> + .hw.init = CLK_HW_INIT_PARENTS_DATA("pll-npu-4x", osc24M,
> + &ccu_nm_ops,
> + CLK_SET_RATE_UNGATE),
> + },
> +};
> +
> +/*
> + * The CPU gate is not modelled - it is in a separate register (0x504)
> + * and has a special key field. The clock does not need to be ungated anyway.
I would believe it should read: "The clock must not be gated anyway by
the kernel". (As it would stop execution on the Arm cores, so it's only
something for the management core).
> + */
> +static const struct clk_parent_data cpu_parents[] = {
> + { .fw_name = "hosc" },
> + { .fw_name = "losc" },
> + { .fw_name = "iosc" },
> + { .hw = &pll_cpu_clk.common.hw },
The manual says there is a divider (PLL_CPU_OUT_EXT_DIVP[17:16]),
though the description suggests it should stay as 0. I guess this is
the intention here, but can you please add comment here?
> + { .hw = &pll_periph_600M_clk.hw },
> + { .hw = &pll_periph_800M_clk.common.hw },
> +};
> +
> +static SUNXI_CCU_MUX_DATA(cpu_clk, "cpu", cpu_parents,
> + 0x500, 24, 3, CLK_SET_RATE_PARENT | CLK_IS_CRITICAL);
> +
> +static SUNXI_CCU_M(cpu_axi_clk, "cpu-axi", "cpu",
I wonder if it's more efficient to use a pointer to the CPU clock, and
not a string?
> + 0x500, 0, 2, 0);
> +static SUNXI_CCU_M(cpu_apb_clk, "cpu-apb", "cpu",
> + 0x500, 8, 2, 0);
> +
> +static const struct clk_parent_data ahb_parents[] = {
> + { .fw_name = "hosc" },
> + { .fw_name = "losc" },
> + { .fw_name = "iosc" },
> + { .hw = &pll_periph_600M_clk.hw },
> +};
> +static SUNXI_CCU_MP_DATA_WITH_MUX(ahb_clk, "ahb", ahb_parents, 0x510,
> + 0, 5, /* M */
> + 8, 2, /* P */
> + 24, 2, /* mux */
> + 0);
> +
> +static SUNXI_CCU_MP_DATA_WITH_MUX(apb0_clk, "apb0", ahb_parents, 0x520,
> + 0, 5, /* M */
> + 8, 2, /* P */
> + 24, 2, /* mux */
> + 0);
> +
> +static SUNXI_CCU_MP_DATA_WITH_MUX(apb1_clk, "apb1", ahb_parents, 0x524,
> + 0, 5, /* M */
> + 8, 2, /* P */
> + 24, 2, /* mux */
> + 0);
> +
> +static const struct clk_hw *ahb_hws[] = { &ahb_clk.common.hw };
> +static const struct clk_hw *apb0_hws[] = { &apb0_clk.common.hw };
> +static const struct clk_hw *apb1_hws[] = { &apb1_clk.common.hw };
> +
> +
> +
> +static const struct clk_hw *de_g2d_parents[] = {
> + &pll_periph_300M_clk.hw,
> + &pll_video_1x_clk.hw,
> +};
> +static SUNXI_CCU_M_HW_WITH_MUX_GATE(de_clk, "de", de_g2d_parents, 0x600,
> + 0, 5, /* M */
> + 24, 1, /* mux */
> + BIT(31), /* gate */
> + CLK_SET_RATE_PARENT);
> +
> +static SUNXI_CCU_GATE_HWS(bus_de_clk, "bus-de", ahb_hws,
> + 0x60c, BIT(0), 0);
> +
> +static SUNXI_CCU_M_HW_WITH_MUX_GATE(g2d_clk, "g2d", de_g2d_parents, 0x630,
> + 0, 5, /* M */
> + 24, 1, /* mux */
> + BIT(31), /* gate */
> + CLK_SET_RATE_PARENT);
> +
> +static SUNXI_CCU_GATE_HWS(bus_g2d_clk, "bus-g2d", ahb_hws,
> + 0x63c, BIT(0), 0);
> +
> +
> +static const struct clk_parent_data ce_parents[] = {
> + { .fw_name = "hosc" },
That parent is not mentioned in the manual, though it looks like an
omission. Did you find the HOSC mentioned somewhere else?
> + { .hw = &pll_periph_400M_clk.hw, },
> + { .hw = &pll_periph_300M_clk.hw, }
> +};
> +static SUNXI_CCU_M_DATA_WITH_MUX_GATE(ce_clk, "ce", ce_parents, 0x680,
> + 0, 4, /* M */
looks like the indentation here is a bit off, can you check this? And
for the other clocks as well?
> + 24, 3, /* mux */
> + BIT(31), /* gate */
> + CLK_SET_RATE_PARENT);
> +
> +static SUNXI_CCU_GATE_HWS(bus_ce_clk, "bus-ce", ahb_hws,
> + 0x68c, BIT(0) | BIT(1), 0);
(reviewed till here, for now, to keep my sanity. Skipping down to
below, where there are more low-hanging fruits and bits that can be
checked more systematically)
> +
> +static const struct clk_hw *ve_parents[] = {
> + &pll_periph_300M_clk.hw,
> + &pll_periph_400M_clk.hw,
> + &pll_periph_480M_clk.common.hw,
> + &pll_npu_4x_clk.common.hw,
> + &pll_video_4x_clk.common.hw,
> + &pll_csi_4x_clk.common.hw,
> +};
> +static SUNXI_CCU_M_HW_WITH_MUX_GATE(ve_clk, "ve", ve_parents, 0x690,
> + 0, 5, /* M */
> + 24, 3, /* mux */
> + BIT(31), /* gate */
> + CLK_SET_RATE_PARENT);
> +
> +static SUNXI_CCU_GATE_HWS(bus_ve_clk, "bus-ve", ahb_hws,
> + 0x69c, BIT(0), 0);
> +
> +
> +static const struct clk_hw *npu_parents[] = {
> + &pll_periph_480M_clk.common.hw,
> + &pll_periph_600M_clk.hw,
> + &pll_periph_800M_clk.common.hw,
> + &pll_npu_4x_clk.common.hw,
> +};
> +static SUNXI_CCU_M_HW_WITH_MUX_GATE(npu_clk, "npu", npu_parents, 0x6e0,
> + 0, 5, /* M */
> + 24, 3, /* mux */
> + BIT(31), /* gate */
> + 0);
> +
> +static SUNXI_CCU_GATE_HWS(bus_npu_clk, "bus-npu", ahb_hws,
> + 0x6ec, BIT(0), 0);
> +
> +static SUNXI_CCU_GATE_HWS(bus_dma_clk, "bus-dma", ahb_hws,
> + 0x70c, BIT(0), 0);
> +
> +static SUNXI_CCU_GATE_HWS(bus_msgbox0_clk, "bus-msgbox0", ahb_hws,
> + 0x71c, BIT(0), 0);
> +static SUNXI_CCU_GATE_HWS(bus_msgbox1_clk, "bus-msgbox1", ahb_hws,
> + 0x71c, BIT(1), 0);
> +
> +static SUNXI_CCU_GATE_HWS(bus_spinlock_clk, "bus-spinlock", ahb_hws,
> + 0x72c, BIT(0), 0);
> +
> +static SUNXI_CCU_GATE_HWS(bus_hstimer_clk, "bus-hstimer", ahb_hws,
> + 0x73c, BIT(0), 0);
> +
> +static SUNXI_CCU_GATE_DATA(avs_clk, "avs", osc24M,
> + 0x740, BIT(31), 0);
> +
> +static SUNXI_CCU_GATE_HWS(bus_dbg_clk, "bus-dbg", ahb_hws,
> + 0x78c, BIT(0), 0);
> +
> +static SUNXI_CCU_GATE_HWS(bus_pwm_clk, "bus-pwm", apb0_hws,
> + 0x7ac, BIT(0), 0);
> +
> +static SUNXI_CCU_GATE_HWS(bus_iommu_clk, "bus-iommu", ahb_hws,
> + 0x7bc, BIT(0), 0);
> +
> +static const struct clk_hw *dram_parents[] = {
> + &pll_ddr_clk.common.hw,
> + &pll_periph_2x_clk.common.hw,
> + &pll_periph_800M_clk.common.hw,
> +};
> +static SUNXI_CCU_MP_HW_WITH_MUX_GATE(dram_clk, "dram", dram_parents, 0x800,
> + 0, 5, /* M */
> + 8, 2, /* P */
> + 24, 3, /* mux */
> + BIT(31), CLK_IS_CRITICAL);
> +
> +static CLK_FIXED_FACTOR_HW(mbus_clk, "mbus",
> + &dram_clk.common.hw, 4, 1, 0);
> +
> +static const struct clk_hw *mbus_hws[] = { &mbus_clk.hw };
> +
> +static SUNXI_CCU_GATE_HWS(mbus_dma_clk, "mbus-dma", mbus_hws,
> + 0x804, BIT(0), 0);
> +static SUNXI_CCU_GATE_HWS(mbus_ve_clk, "mbus-ve", mbus_hws,
> + 0x804, BIT(1), 0);
> +static SUNXI_CCU_GATE_HWS(mbus_ce_clk, "mbus-ce", mbus_hws,
> + 0x804, BIT(2), 0);
> +static SUNXI_CCU_GATE_HWS(mbus_csi_clk, "mbus-csi", mbus_hws,
> + 0x804, BIT(8), 0);
> +static SUNXI_CCU_GATE_HWS(mbus_isp_clk, "mbus-isp", mbus_hws,
> + 0x804, BIT(9), 0);
> +static SUNXI_CCU_GATE_HWS(mbus_g2d_clk, "mbus-g2d", mbus_hws,
> + 0x804, BIT(10), 0);
> +
> +static SUNXI_CCU_GATE_HWS(bus_dram_clk, "bus-dram", ahb_hws,
> + 0x80c, BIT(0), CLK_IS_CRITICAL);
> +
> +
> +static const struct clk_parent_data mmc0_mmc1_parents[] = {
> + { .fw_name = "hosc" },
> + { .hw = &pll_periph_400M_clk.hw, },
> + { .hw = &pll_periph_300M_clk.hw, },
> +};
> +static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(mmc0_clk, "mmc0", mmc0_mmc1_parents, 0x830,
> + 0, 4, /* M */
> + 8, 2, /* P */
> + 24, 3, /* mux */
> + BIT(31), /* gate */
> + 0);
> +
> +static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(mmc1_clk, "mmc1", mmc0_mmc1_parents, 0x834,
> + 0, 4, /* M */
> + 8, 2, /* P */
> + 24, 3, /* mux */
> + BIT(31), /* gate */
> + 0);
> +
> +static const struct clk_parent_data mmc2_parents[] = {
> + { .fw_name = "hosc" },
> + { .hw = &pll_periph_600M_clk.hw, },
> + { .hw = &pll_periph_400M_clk.hw, },
> +};
> +static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(mmc2_clk, "mmc2", mmc2_parents, 0x838,
> + 0, 4, /* M */
> + 8, 2, /* P */
> + 24, 3, /* mux */
> + BIT(31), /* gate */
> + 0);
> +
> +static SUNXI_CCU_GATE_HWS(bus_mmc0_clk, "bus-mmc0", ahb_hws,
> + 0x84c, BIT(0), 0);
> +static SUNXI_CCU_GATE_HWS(bus_mmc1_clk, "bus-mmc1", ahb_hws,
> + 0x84c, BIT(1), 0);
> +static SUNXI_CCU_GATE_HWS(bus_mmc2_clk, "bus-mmc2", ahb_hws,
> + 0x84c, BIT(2), 0);
> +
> +static SUNXI_CCU_GATE_HWS(bus_uart0_clk, "bus-uart0", apb1_hws,
> + 0x90c, BIT(0), 0);
> +static SUNXI_CCU_GATE_HWS(bus_uart1_clk, "bus-uart1", apb1_hws,
> + 0x90c, BIT(1), 0);
> +static SUNXI_CCU_GATE_HWS(bus_uart2_clk, "bus-uart2", apb1_hws,
> + 0x90c, BIT(2), 0);
> +static SUNXI_CCU_GATE_HWS(bus_uart3_clk, "bus-uart3", apb1_hws,
> + 0x90c, BIT(3), 0);
> +
> +static SUNXI_CCU_GATE_HWS(bus_i2c0_clk, "bus-i2c0", apb1_hws,
> + 0x91c, BIT(0), 0);
> +static SUNXI_CCU_GATE_HWS(bus_i2c1_clk, "bus-i2c1", apb1_hws,
> + 0x91c, BIT(1), 0);
> +static SUNXI_CCU_GATE_HWS(bus_i2c2_clk, "bus-i2c2", apb1_hws,
> + 0x91c, BIT(2), 0);
> +static SUNXI_CCU_GATE_HWS(bus_i2c3_clk, "bus-i2c3", apb1_hws,
> + 0x91c, BIT(3), 0);
> +static SUNXI_CCU_GATE_HWS(bus_i2c4_clk, "bus-i2c4", apb1_hws,
> + 0x91c, BIT(4), 0);
> +
> +static const struct clk_parent_data spi_parents[] = {
> + { .fw_name = "hosc" },
> + { .hw = &pll_periph_300M_clk.hw, },
> + { .hw = &pll_periph_200M_clk.hw, },
> +};
> +
> +static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(spi0_clk, "spi0", spi_parents, 0x940,
> + 0, 4, /* M */
> + 8, 2, /* P */
> + 24, 3, /* mux */
> + BIT(31), /* gate */
> + 0);
> +
> +static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(spi1_clk, "spi1", spi_parents, 0x944,
> + 0, 4, /* M */
> + 8, 2, /* P */
> + 24, 3, /* mux */
> + BIT(31), /* gate */
> + 0);
> +
> +static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(spi2_clk, "spi2", spi_parents, 0x948,
> + 0, 4, /* M */
> + 8, 2, /* P */
> + 24, 3, /* mux */
> + BIT(31), /* gate */
> + 0);
> +
> +static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(spi3_clk, "spi3", spi_parents, 0x94c,
> + 0, 4, /* M */
> + 8, 2, /* P */
> + 24, 3, /* mux */
> + BIT(31), /* gate */
> + 0);
> +
> +static SUNXI_CCU_GATE_HWS(bus_spi0_clk, "bus-spi0", ahb_hws,
> + 0x96c, BIT(0), 0);
> +static SUNXI_CCU_GATE_HWS(bus_spi1_clk, "bus-spi1", ahb_hws,
> + 0x96c, BIT(1), 0);
> +static SUNXI_CCU_GATE_HWS(bus_spi2_clk, "bus-spi2", ahb_hws,
> + 0x96c, BIT(2), 0);
> +static SUNXI_CCU_GATE_HWS(bus_spi3_clk, "bus-spi3", ahb_hws,
> + 0x96c, BIT(3), 0);
> +
> +
> +static const struct clk_parent_data spif_parents[] = {
> + { .fw_name = "hosc" },
> + { .hw = &pll_periph_400M_clk.hw, },
> + { .hw = &pll_periph_300M_clk.hw, },
> +};
> +
> +static SUNXI_CCU_M_DATA_WITH_MUX_GATE(spif_clk, "spif", spif_parents, 0x0950,
> + 0, 4, /* M */
> + 24, 3, /* mux */
> + BIT(31), /* gate */
> + CLK_SET_RATE_PARENT);
> +
> +static SUNXI_CCU_GATE_HWS(bus_spif_clk, "bus-spif", ahb_hws,
> + 0x096c, BIT(4), 0);
> +
> +
> +static const struct clk_hw *pll_periph_150M_hws[] = { &pll_periph_150M_clk.hw };
> +static SUNXI_CCU_GATE_HWS_WITH_PREDIV(emac_25M_clk, "emac-25M", pll_periph_150M_hws,
> + 0x970, BIT(31) | BIT(30), 6, 0);
> +
> +static SUNXI_CCU_GATE_HWS(bus_emac_clk, "bus-emac", ahb_hws,
> + 0x97c, BIT(0), 0);
> +
> +static SUNXI_CCU_GATE_HWS(bus_gpadc_clk, "bus-gpadc", apb0_hws,
> + 0x9ec, BIT(0), 0);
> +
> +static SUNXI_CCU_GATE_HWS(bus_ths_clk, "bus-ths", ahb_hws,
> + 0x9fc, BIT(0), 0);
> +
> +
> +static const struct clk_hw *audio_parents[] = {
> + &pll_audio_1x_clk.common.hw,
> + &pll_audio_4x_clk.common.hw,
> +};
> +
> +static SUNXI_CCU_M_HW_WITH_MUX_GATE(i2s0_clk, "i2s0", audio_parents, 0xa10,
> + 0, 4, /* M */
> + 24, 1, /* mux */
> + BIT(31), /* gate */
> + CLK_SET_RATE_PARENT);
> +
> +static SUNXI_CCU_M_HW_WITH_MUX_GATE(i2s1_clk, "i2s1", audio_parents, 0xa14,
> + 0, 4, /* M */
> + 24, 1, /* mux */
> + BIT(31), /* gate */
> + CLK_SET_RATE_PARENT);
> +
> +static SUNXI_CCU_GATE_HWS(bus_i2s1_clk, "bus-i2s1", ahb_hws,
> + 0xa20, BIT(1), 0);
> +
Just a nit, but those two here v and ^ seem to be swapped.
For the records: I extracted the bus gates and massaged them with some
regexps to bring them into a shape where review is more feasible.
They look alright to me. I didn't look at the respective mod clocks in
detail, though.
> +static SUNXI_CCU_GATE_HWS(bus_i2s0_clk, "bus-i2s0", ahb_hws,
> + 0xa20, BIT(0), 0);
> +
> +static SUNXI_CCU_M_HW_WITH_MUX_GATE(dmic_clk, "dmic", audio_parents, 0xa40,
> + 0, 4, /* M */
> + 24, 1, /* mux */
> + BIT(31), /* gate */
> + CLK_SET_RATE_PARENT);
> +
> +static SUNXI_CCU_GATE_HWS(bus_dmic_clk, "bus-dmic", ahb_hws,
> + 0xa4c, BIT(0), 0);
> +
> +static SUNXI_CCU_M_HW_WITH_MUX_GATE(audio_codec_dac_clk, "audio-codec-dac", audio_parents, 0xa50,
I think you should break the line above, to stay within the 80 char
limit.
Fast forwarding to the ccu_resets array ...
> + 0, 4, /* M */
> + 24, 1, /* mux */
> + BIT(31), /* gate */
> + CLK_SET_RATE_PARENT);
> +
> +static SUNXI_CCU_M_HW_WITH_MUX_GATE(audio_codec_adc_clk, "audio-codec-adc", audio_parents, 0xa54,
> + 0, 4, /* M */
> + 24, 1, /* mux */
> + BIT(31), /* gate */
> + CLK_SET_RATE_PARENT);
> +
> +static SUNXI_CCU_GATE_HWS(bus_audio_codec_clk, "bus-audio-codec", apb0_hws,
> + 0xa5c, BIT(0), 0);
> +
> +/*
> + * There are OHCI 12M clock source selection bits for the USB 2.0 port.
> + * We will force them to 0 (12M divided from 48M).
> + */
> +static CLK_FIXED_FACTOR_FW_NAME(osc12M_clk, "osc12M", "hosc", 2, 1, 0);
> +
> +#define SUN8I_V853_USB_CLK_REG 0xa70
> +
> +static SUNXI_CCU_GATE(usb_ohci_clk, "usb", "osc12M", 0x0a70, BIT(31), 0);
> +
> +static SUNXI_CCU_GATE_HWS(bus_ohci_clk, "bus-ohci", ahb_hws, 0xa8c, BIT(0), 0);
> +static SUNXI_CCU_GATE_HWS(bus_ehci_clk, "bus-ehci", ahb_hws, 0xa8c, BIT(4), 0);
> +static SUNXI_CCU_GATE_HWS(bus_otg_clk, "bus-otg", ahb_hws, 0xa8c, BIT(8), 0);
> +
> +static SUNXI_CCU_GATE_HWS(bus_dpss_top_clk, "bus-dpss-top", ahb_hws,
> + 0xabc, BIT(0), 0);
> +
> +
> +static const struct clk_parent_data mipi_dsi_parents[] = {
> + { .fw_name = "hosc" },
> + { .hw = &pll_periph_200M_clk.hw },
> + { .hw = &pll_periph_150M_clk.hw },
> +};
> +static SUNXI_CCU_M_DATA_WITH_MUX_GATE(mipi_dsi_clk, "mipi-dsi", mipi_dsi_parents, 0xb24,
> + 0, 4, /* M */
> + 24, 3, /* mux */
> + BIT(31), /* gate */
> + CLK_SET_RATE_PARENT);
> +
> +static SUNXI_CCU_GATE_HWS(bus_mipi_dsi_clk, "bus-mipi-dsi", ahb_hws,
> + 0xb4c, BIT(0), 0);
> +
> +
> +static const struct clk_hw *tcon_lcd_parents[] = {
> + &pll_video_4x_clk.common.hw,
> + &pll_periph_2x_clk.common.hw,
> + &pll_csi_4x_clk.common.hw,
> +};
> +static SUNXI_CCU_MP_HW_WITH_MUX_GATE(tcon_lcd_clk, "tcon-lcd", tcon_lcd_parents, 0xb60,
> + 0, 4, /* M */
> + 8, 2, /* P */
> + 24, 3, /* mux */
> + BIT(31), /* gate */
> + CLK_SET_RATE_PARENT);
> +
> +static SUNXI_CCU_GATE_HWS(bus_tcon_lcd_clk, "bus-tcon-lcd", ahb_hws,
> + 0xb7c, BIT(0), 0);
> +
> +
> +static const struct clk_hw *csi_top_parents[] = {
> + &pll_periph_300M_clk.hw,
> + &pll_periph_400M_clk.hw,
> + &pll_video_4x_clk.common.hw,
> + &pll_csi_4x_clk.common.hw,
> +};
> +static SUNXI_CCU_M_HW_WITH_MUX_GATE(csi_top_clk, "csi-top", csi_top_parents, 0xc04,
> + 0, 5, /* M */
> + 24, 3, /* mux */
> + BIT(31), /* gate */
> + 0);
> +
> +
> +static const struct clk_parent_data csi_mclk_parents[] = {
> + { .fw_name = "hosc" },
> + { .hw = &pll_csi_4x_clk.common.hw },
> + { .hw = &pll_video_4x_clk.common.hw },
> + { .hw = &pll_periph_2x_clk.common.hw },
> +};
> +static SUNXI_CCU_M_DATA_WITH_MUX_GATE(csi_mclk0_clk, "csi-mclk0", csi_mclk_parents, 0xc08,
> + 0, 5, /* M */
> + 24, 3, /* mux */
> + BIT(31), /* gate */
> + 0);
> +
> +static SUNXI_CCU_M_DATA_WITH_MUX_GATE(csi_mclk1_clk, "csi-mclk1", csi_mclk_parents, 0xc0c,
> + 0, 5, /* M */
> + 24, 3, /* mux */
> + BIT(31), /* gate */
> + 0);
> +
> +static SUNXI_CCU_M_DATA_WITH_MUX_GATE(csi_mclk2_clk, "csi-mclk2", csi_mclk_parents, 0xc10,
> + 0, 5, /* M */
> + 24, 3, /* mux */
> + BIT(31), /* gate */
> + 0);
> +
> +static SUNXI_CCU_GATE_HWS(bus_csi_clk, "bus-csi", ahb_hws,
> + 0xc2c, BIT(0), 0);
> +
> +
> +static SUNXI_CCU_GATE_HWS(bus_wiegand_clk, "bus-wiegand", ahb_hws,
> + 0xc7c, BIT(0), 0);
> +
> +
> +static const struct clk_parent_data riscv_parents[] = {
> + { .fw_name = "hosc" },
> + { .fw_name = "losc" },
> + { .fw_name = "iosc" },
> + { .hw = &pll_periph_600M_clk.hw },
> + { .hw = &pll_periph_480M_clk.common.hw },
> + { .hw = &pll_cpu_clk.common.hw },
> +};
> +static SUNXI_CCU_M_DATA_WITH_MUX(riscv_clk, "riscv-cpu", riscv_parents, 0xd00,
> + 0, 5, /* M */
> + 24, 3, /* mux */
> + CLK_SET_RATE_PARENT);
> +
> +/* The riscv-axi clk must be divided by at least 2. */
> +static struct clk_div_table riscv_axi_table[] = {
> + { .val = 1, .div = 2 },
> + { .val = 2, .div = 3 },
> + { .val = 3, .div = 4 },
> + { /* Sentinel */ }
> +};
> +static SUNXI_CCU_DIV_TABLE_HW(riscv_axi_clk, "riscv-axi", &riscv_clk.common.hw,
> + 0xd00, 8, 2, riscv_axi_table, 0);
> +
> +
> +static SUNXI_CCU_GATE_HWS(riscv_cfg, "riscv-cfg", ahb_hws,
> + 0xd0c, BIT(0), 0);
> +
> +static const struct clk_hw *pll_periph_160M_hws[] = {
> + &pll_periph_160M_clk.hw,
> +};
> +
> +static SUNXI_CCU_GATE_DATA(fanout_24M_clk, "fanout-24M", osc24M,
> + 0xf30, BIT(0), 0);
> +static SUNXI_CCU_GATE_DATA_WITH_PREDIV(fanout_12M_clk, "fanout-12M", osc24M,
> + 0xf30, BIT(1), 2, 0);
> +static SUNXI_CCU_GATE_HWS_WITH_PREDIV(fanout_16M_clk, "fanout-16M", pll_periph_160M_hws,
> + 0xf30, BIT(2), 10, 0);
> +static SUNXI_CCU_GATE_HWS_WITH_PREDIV(fanout_25M_clk, "fanout-25M", pll_periph_150M_hws,
> + 0xf30, BIT(3), 6, 0);
> +
> +
> +
> +/* This clock has a second divider that is not modelled and forced to 0. */
> +#define SUN8I_V853_FANOUT_27M_REG 0xf34
> +static const struct clk_hw *fanout_27M_parents[] = {
> + &pll_video_1x_clk.hw,
> + &pll_csi_clk.hw,
> + &pll_periph_300M_clk.hw,
> +};
> +static SUNXI_CCU_M_HW_WITH_MUX_GATE(fanout_27M_clk, "fanout-27M", fanout_27M_parents, 0xf34,
> + 0, 5, /* M */
> + 24, 2, /* mux */
> + BIT(31), /* gate */
> + 0);
> +static SUNXI_CCU_M_HWS_WITH_GATE(fanout_pclk_clk, "fanout-pclk", apb0_hws, 0xf38,
> + 0, 5, /* M */
> + BIT(31), /* gate */
> + 0);
> +
> +static const struct clk_parent_data fanout_parents[] = {
> + { .fw_name = "losc" },
> + { .hw = &fanout_12M_clk.common.hw },
> + { .hw = &fanout_16M_clk.common.hw },
> + { .hw = &fanout_24M_clk.common.hw },
> + { .hw = &fanout_25M_clk.common.hw },
> + { .hw = &fanout_27M_clk.common.hw },
> + { .hw = &fanout_pclk_clk.common.hw },
> +};
> +
> +static SUNXI_CCU_MUX_DATA_WITH_GATE(fanout0_clk, "fanout0", fanout_parents, 0xf3c,
> + 0, 3, /* mux */
> + BIT(21), /* gate */
> + 0);
> +static SUNXI_CCU_MUX_DATA_WITH_GATE(fanout1_clk, "fanout1", fanout_parents, 0xf3c,
> + 3, 3, /* mux */
> + BIT(22), /* gate */
> + 0);
> +static SUNXI_CCU_MUX_DATA_WITH_GATE(fanout2_clk, "fanout2", fanout_parents, 0xf3c,
> + 6, 3, /* mux */
> + BIT(23), /* gate */
> + 0);
> +
> +
> +static struct ccu_common *sun8i_v853_ccu_clks[] = {
> + &pll_cpu_clk.common,
> + &pll_ddr_clk.common,
> + &pll_periph_4x_clk.common,
> + &pll_periph_2x_clk.common,
> + &pll_periph_800M_clk.common,
> + &pll_periph_480M_clk.common,
> + &pll_video_4x_clk.common,
> + &pll_csi_4x_clk.common,
> + &pll_audio_div2_clk.common,
> + &pll_audio_div5_clk.common,
> + &pll_audio_4x_clk.common,
> + &pll_audio_1x_clk.common,
> + &pll_npu_4x_clk.common,
> + &cpu_clk.common,
> + &cpu_axi_clk.common,
> + &cpu_apb_clk.common,
> + &ahb_clk.common,
> + &apb0_clk.common,
> + &apb1_clk.common,
> + &de_clk.common,
> + &bus_de_clk.common,
> + &g2d_clk.common,
> + &bus_g2d_clk.common,
> + &ce_clk.common,
> + &bus_ce_clk.common,
> + &ve_clk.common,
> + &bus_ve_clk.common,
> + &npu_clk.common,
> + &bus_npu_clk.common,
> + &bus_dma_clk.common,
> + &bus_msgbox0_clk.common,
> + &bus_msgbox1_clk.common,
> + &bus_spinlock_clk.common,
> + &bus_hstimer_clk.common,
> + &avs_clk.common,
> + &bus_dbg_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_csi_clk.common,
> + &mbus_isp_clk.common,
> + &mbus_g2d_clk.common,
> + &bus_dram_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_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,
> + &spi2_clk.common,
> + &spi3_clk.common,
> + &bus_spi0_clk.common,
> + &bus_spi1_clk.common,
> + &bus_spi2_clk.common,
> + &bus_spi3_clk.common,
> + &spif_clk.common,
> + &bus_spif_clk.common,
> + &emac_25M_clk.common,
> + &bus_emac_clk.common,
> + &bus_gpadc_clk.common,
> + &bus_ths_clk.common,
> + &usb_ohci_clk.common,
> + &bus_ohci_clk.common,
> + &bus_ehci_clk.common,
> + &bus_otg_clk.common,
> + &i2s0_clk.common,
> + &i2s1_clk.common,
> + &bus_i2s0_clk.common,
> + &bus_i2s1_clk.common,
> + &dmic_clk.common,
> + &bus_dmic_clk.common,
> + &audio_codec_dac_clk.common,
> + &audio_codec_adc_clk.common,
> + &bus_audio_codec_clk.common,
> + &bus_dpss_top_clk.common,
> + &mipi_dsi_clk.common,
> + &bus_mipi_dsi_clk.common,
> + &tcon_lcd_clk.common,
> + &bus_tcon_lcd_clk.common,
> + &csi_top_clk.common,
> + &csi_mclk0_clk.common,
> + &csi_mclk1_clk.common,
> + &csi_mclk2_clk.common,
> + &bus_csi_clk.common,
> + &bus_wiegand_clk.common,
> + &riscv_clk.common,
> + &riscv_axi_clk.common,
> + &riscv_cfg.common,
> + &fanout_24M_clk.common,
> + &fanout_12M_clk.common,
> + &fanout_16M_clk.common,
> + &fanout_25M_clk.common,
> + &fanout_27M_clk.common,
> + &fanout_pclk_clk.common,
> + &fanout0_clk.common,
> + &fanout1_clk.common,
> + &fanout2_clk.common,
> +};
> +
> +static struct clk_hw_onecell_data sun8i_v853_hw_clks = {
> + .num = CLK_NUMBER,
> + .hws = {
> + [CLK_OSC12M] = &osc12M_clk.hw,
> + [CLK_PLL_CPU] = &pll_cpu_clk.common.hw,
> + [CLK_PLL_DDR] = &pll_ddr_clk.common.hw,
> + [CLK_PLL_PERIPH_4X] = &pll_periph_4x_clk.common.hw,
> + [CLK_PLL_PERIPH_2X] = &pll_periph_2x_clk.common.hw,
> + [CLK_PLL_PERIPH_800M] = &pll_periph_800M_clk.common.hw,
> + [CLK_PLL_PERIPH_480M] = &pll_periph_480M_clk.common.hw,
> + [CLK_PLL_PERIPH_600M] = &pll_periph_600M_clk.hw,
> + [CLK_PLL_PERIPH_400M] = &pll_periph_400M_clk.hw,
> + [CLK_PLL_PERIPH_300M] = &pll_periph_300M_clk.hw,
> + [CLK_PLL_PERIPH_200M] = &pll_periph_200M_clk.hw,
> + [CLK_PLL_PERIPH_160M] = &pll_periph_160M_clk.hw,
> + [CLK_PLL_PERIPH_150M] = &pll_periph_150M_clk.hw,
> + [CLK_PLL_VIDEO_4X] = &pll_video_4x_clk.common.hw,
> + [CLK_PLL_VIDEO_2X] = &pll_video_2x_clk.hw,
> + [CLK_PLL_VIDEO_1X] = &pll_video_1x_clk.hw,
> + [CLK_PLL_CSI_4X] = &pll_csi_4x_clk.common.hw,
> + [CLK_PLL_AUDIO_DIV2] = &pll_audio_div2_clk.common.hw,
> + [CLK_PLL_AUDIO_DIV5] = &pll_audio_div5_clk.common.hw,
> + [CLK_PLL_AUDIO_4X] = &pll_audio_4x_clk.common.hw,
> + [CLK_PLL_AUDIO_1X] = &pll_audio_1x_clk.common.hw,
> + [CLK_PLL_NPU_4X] = &pll_npu_4x_clk.common.hw,
> + [CLK_CPU] = &cpu_clk.common.hw,
> + [CLK_CPU_AXI] = &cpu_axi_clk.common.hw,
> + [CLK_CPU_APB] = &cpu_apb_clk.common.hw,
> + [CLK_AHB] = &ahb_clk.common.hw,
> + [CLK_APB0] = &apb0_clk.common.hw,
> + [CLK_APB1] = &apb1_clk.common.hw,
> + [CLK_MBUS] = &mbus_clk.hw,
> + [CLK_DE] = &de_clk.common.hw,
> + [CLK_BUS_DE] = &bus_de_clk.common.hw,
> + [CLK_G2D] = &g2d_clk.common.hw,
> + [CLK_BUS_G2D] = &bus_g2d_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_NPU] = &npu_clk.common.hw,
> + [CLK_BUS_NPU] = &bus_npu_clk.common.hw,
> + [CLK_BUS_DMA] = &bus_dma_clk.common.hw,
> + [CLK_BUS_MSGBOX0] = &bus_msgbox0_clk.common.hw,
> + [CLK_BUS_MSGBOX1] = &bus_msgbox1_clk.common.hw,
> + [CLK_BUS_SPINLOCK] = &bus_spinlock_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_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_CSI] = &mbus_csi_clk.common.hw,
> + [CLK_MBUS_ISP] = &mbus_isp_clk.common.hw,
> + [CLK_MBUS_G2D] = &mbus_g2d_clk.common.hw,
> + [CLK_BUS_DRAM] = &bus_dram_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_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_SPI2] = &spi2_clk.common.hw,
> + [CLK_SPI3] = &spi3_clk.common.hw,
> + [CLK_BUS_SPI0] = &bus_spi0_clk.common.hw,
> + [CLK_BUS_SPI1] = &bus_spi1_clk.common.hw,
> + [CLK_BUS_SPI2] = &bus_spi2_clk.common.hw,
> + [CLK_BUS_SPI3] = &bus_spi3_clk.common.hw,
> + [CLK_SPIF] = &spif_clk.common.hw,
> + [CLK_BUS_SPIF] = &bus_spif_clk.common.hw,
> + [CLK_EMAC_25M] = &emac_25M_clk.common.hw,
> + [CLK_BUS_EMAC] = &bus_emac_clk.common.hw,
> + [CLK_BUS_GPADC] = &bus_gpadc_clk.common.hw,
> + [CLK_BUS_THS] = &bus_ths_clk.common.hw,
> + [CLK_I2S0] = &i2s0_clk.common.hw,
> + [CLK_I2S1] = &i2s1_clk.common.hw,
> + [CLK_BUS_I2S0] = &bus_i2s0_clk.common.hw,
> + [CLK_BUS_I2S1] = &bus_i2s1_clk.common.hw,
> + [CLK_DMIC] = &dmic_clk.common.hw,
> + [CLK_BUS_DMIC] = &bus_dmic_clk.common.hw,
> + [CLK_AUDIO_CODEC_DAC] = &audio_codec_dac_clk.common.hw,
> + [CLK_AUDIO_CODEC_ADC] = &audio_codec_adc_clk.common.hw,
> + [CLK_BUS_AUDIO_CODEC] = &bus_audio_codec_clk.common.hw,
> + [CLK_USB_OHCI] = &usb_ohci_clk.common.hw,
> + [CLK_BUS_OHCI] = &bus_ohci_clk.common.hw,
> + [CLK_BUS_EHCI] = &bus_ehci_clk.common.hw,
> + [CLK_BUS_OTG] = &bus_otg_clk.common.hw,
> + [CLK_BUS_DPSS_TOP] = &bus_dpss_top_clk.common.hw,
> + [CLK_MIPI_DSI] = &mipi_dsi_clk.common.hw,
> + [CLK_BUS_MIPI_DSI] = &bus_mipi_dsi_clk.common.hw,
> + [CLK_TCON_LCD] = &tcon_lcd_clk.common.hw,
> + [CLK_BUS_TCON_LCD] = &bus_tcon_lcd_clk.common.hw,
> + [CLK_CSI_TOP] = &csi_top_clk.common.hw,
> + [CLK_CSI_MCLK0] = &csi_mclk0_clk.common.hw,
> + [CLK_CSI_MCLK1] = &csi_mclk1_clk.common.hw,
> + [CLK_CSI_MCLK2] = &csi_mclk2_clk.common.hw,
> + [CLK_BUS_CSI] = &bus_csi_clk.common.hw,
> + [CLK_BUS_WIEGAND] = &bus_wiegand_clk.common.hw,
> + [CLK_RISCV] = &riscv_clk.common.hw,
> + [CLK_RISCV_AXI] = &riscv_axi_clk.common.hw,
> + [CLK_RISCV_CFG] = &riscv_cfg.common.hw,
> + [CLK_FANOUT_24M] = &fanout_24M_clk.common.hw,
> + [CLK_FANOUT_16M] = &fanout_16M_clk.common.hw,
> + [CLK_FANOUT_12M] = &fanout_12M_clk.common.hw,
> + [CLK_FANOUT_25M] = &fanout_25M_clk.common.hw,
> + [CLK_FANOUT_27M] = &fanout_27M_clk.common.hw,
> + [CLK_FANOUT_PCLK] = &fanout_pclk_clk.common.hw,
> + [CLK_FANOUT0] = &fanout0_clk.common.hw,
> + [CLK_FANOUT1] = &fanout1_clk.common.hw,
> + [CLK_FANOUT2] = &fanout2_clk.common.hw,
> + },
> +};
> +
> +static struct ccu_reset_map sun8i_v853_ccu_resets[] = {
> + [RST_MBUS] = { 0x540, BIT(30) },
> + [RST_BUS_DE] = { 0x60c, BIT(16) },
> + [RST_BUS_G2D] = { 0x63c, BIT(16) },
> + [RST_BUS_CE] = { 0x68c, BIT(16) | BIT(17)},
> + [RST_BUS_VE] = { 0x69c, BIT(16) },
> + [RST_BUS_NPU] = { 0x6ec, BIT(16) },
> + [RST_BUS_DMA] = { 0x70c, BIT(16) },
> + [RST_BUS_MSGBOX0] = { 0x71c, BIT(16) },
> + [RST_BUS_MSGBOX1] = { 0x71c, BIT(17) },
> + [RST_BUS_SPINLOCK] = { 0x72c, BIT(16) },
> + [RST_BUS_HSTIMER] = { 0x73c, BIT(16) },
> + [RST_BUS_DBG] = { 0x78c, BIT(16) },
> + [RST_BUS_PWM] = { 0x7ac, BIT(16) },
> + [RST_BUS_DRAM] = { 0x80c, 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_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_SPIF] = { 0x96c, BIT(20) },
That entry ^^^^ seems out of order.
> + [RST_BUS_SPI0] = { 0x96c, BIT(16) },
> + [RST_BUS_SPI1] = { 0x96c, BIT(17) },
> + [RST_BUS_SPI2] = { 0x96c, BIT(18) },
> + [RST_BUS_SPI3] = { 0x96c, BIT(19) },
> + [RST_BUS_EMAC] = { 0x97c, BIT(16) },
> + [RST_BUS_GPADC] = { 0x9ec, BIT(16) },
> + [RST_BUS_THS] = { 0x9fc, BIT(16) },
> + [RST_BUS_I2S0] = { 0xa20, BIT(16) },
> + [RST_BUS_I2S1] = { 0xa20, BIT(17) },
> + [RST_BUS_DMIC] = { 0xa4c, BIT(16) },
> + [RST_BUS_AUDIO_CODEC] = { 0xa5c, BIT(16) },
> + [RST_USB_PHY] = { 0xa70, BIT(30) },
> + [RST_BUS_OHCI] = { 0xa8c, BIT(16) },
> + [RST_BUS_EHCI] = { 0xa8c, BIT(20) },
> + [RST_BUS_OTG] = { 0xa8c, BIT(24) },
> + [RST_BUS_DPSS_TOP] = { 0xabc, BIT(16) },
> + [RST_BUS_MIPI_DSI] = { 0xb4c, BIT(16) },
> + [RST_BUS_TCON_LCD] = { 0xb7c, BIT(16) },
> + [RST_BUS_CSI] = { 0xc2c, BIT(16) },
> + [RST_BUS_WIEGAND] = { 0xc7c, BIT(16) },
> + [RST_RISCV_SYS_APB] = { 0xd04, BIT(2), CCU_FEATURE_KEY_FIELD },
> + [RST_RISCV_SOFT] = { 0xd04, BIT(1), CCU_FEATURE_KEY_FIELD },
> + [RST_RISCV_CLK_GATING] = { 0xd04, BIT(0), CCU_FEATURE_KEY_FIELD },
But that's a clock gate, not a reset, right?
> + [RST_RISCV_CFG] = { 0xd0c, BIT(16) }
The rest of the reset bits match the manual.
> +};
> +
> +static const struct sunxi_ccu_desc sun8i_v853_ccu_desc = {
> + .ccu_clks = sun8i_v853_ccu_clks,
> + .num_ccu_clks = ARRAY_SIZE(sun8i_v853_ccu_clks),
> +
> + .hw_clks = &sun8i_v853_hw_clks,
> +
> + .resets = sun8i_v853_ccu_resets,
> + .num_resets = ARRAY_SIZE(sun8i_v853_ccu_resets),
> +};
> +
> +static const u32 pll_regs[] = {
> + SUN8I_V853_PLL_CPU_REG,
> + SUN8I_V853_PLL_DDR_REG,
> + SUN8I_V853_PLL_PERIPH_REG,
> + SUN8I_V853_PLL_VIDEO_REG,
> + SUN8I_V853_PLL_CSI_REG,
> + SUN8I_V853_PLL_AUDIO_REG,
> + SUN8I_V853_PLL_NPU_REG,
> +};
> +
> +static int sun8i_v853_ccu_probe(struct platform_device *pdev)
> +{
> + void __iomem *reg;
> + u32 val;
> + int i, ret;
> +
> + reg = devm_platform_ioremap_resource(pdev, 0);
> + if (IS_ERR(reg))
> + return PTR_ERR(reg);
> +
> + /* Enable the enable, LDO, and lock bits on all PLLs. */
> + for (i = 0; i < ARRAY_SIZE(pll_regs); i++) {
> + val = readl(reg + pll_regs[i]);
> + val |= BIT(31) | BIT(30) | BIT(29);
> + writel(val, reg + pll_regs[i]);
> + }
> +
> + /* Force PLL_CPU factor M to 0. */
> + val = readl(reg + SUN8I_V853_PLL_CPU_REG);
> + val &= ~GENMASK(1, 0);
> + writel(val, reg + SUN8I_V853_PLL_CPU_REG);
Let's just hope it was 0 already, as I guess a sudden jump of
CPU frequency might not be too healthy.
> + /*
> + * Force the output divider of video PLL to 0.
Just a nit, but a "divider of 0" does not sound too healthy. Maybe:
"Force the output divider to 1, by clearing bit 0."
Cheers,
Andre
> + *
> + * See the comment before pll-video0 definition for the reason.
> + */
> + val = readl(reg + SUN8I_V853_PLL_VIDEO_REG);
> + val &= ~BIT(0);
> + writel(val, reg + SUN8I_V853_PLL_VIDEO_REG);
> +
> + /*
> + * Force the output divider of CSI PLL to 0.
> + *
> + * See the comment before pll-csi definition for the reason.
> + */
> + val = readl(reg + SUN8I_V853_PLL_CSI_REG);
> + val &= ~BIT(0);
> + writel(val, reg + SUN8I_V853_PLL_CSI_REG);
> +
> + /*
> + * Force the output divider of NPU PLL to 0.
> + *
> + * See the comment before pll-npu definition for the reason.
> + */
> + val = readl(reg + SUN8I_V853_PLL_NPU_REG);
> + val &= ~BIT(0);
> + writel(val, reg + SUN8I_V853_PLL_NPU_REG);
> +
> + /*
> + * Force OHCI 12M clock source to 00 (12MHz divided from 48MHz)
> + *
> + * This clock mux is still mysterious, and the code just enforces
> + * it to have a valid clock parent.
> + */
> + val = readl(reg + SUN8I_V853_USB_CLK_REG);
> + val &= ~GENMASK(25, 24);
> + writel(val, reg + SUN8I_V853_USB_CLK_REG);
> +
> + /* Force fanout-27M factor N to 0. */
> + val = readl(reg + SUN8I_V853_FANOUT_27M_REG);
> + val &= ~GENMASK(9, 8);
> + writel(val, reg + SUN8I_V853_FANOUT_27M_REG);
> +
> + ret = devm_sunxi_ccu_probe(&pdev->dev, reg, &sun8i_v853_ccu_desc);
> + if (ret)
> + return ret;
> +
> + return 0;
> +}
> +
> +static const struct of_device_id sun8i_v853_ccu_ids[] = {
> + { .compatible = "allwinner,sun8i-v853-ccu" },
> + { }
> +};
> +
> +static struct platform_driver sun8i_v853_ccu_driver = {
> + .probe = sun8i_v853_ccu_probe,
> + .driver = {
> + .name = "sun8i-v853-ccu",
> + .suppress_bind_attrs = true,
> + .of_match_table = sun8i_v853_ccu_ids,
> + },
> +};
> +module_platform_driver(sun8i_v853_ccu_driver);
> +
> +MODULE_IMPORT_NS("SUNXI_CCU");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-v853.h b/drivers/clk/sunxi-ng/ccu-sun8i-v853.h
> new file mode 100644
> index 000000000000..b6ee1764fe5e
> --- /dev/null
> +++ b/drivers/clk/sunxi-ng/ccu-sun8i-v853.h
> @@ -0,0 +1,14 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (C) 2024 Andras Szemzo <szemzo.andras@gmail.com>
> + */
> +
> +#ifndef _CCU_SUN8I_V853_H_
> +#define _CCU_SUN8I_V853_H_
> +
> +#include <dt-bindings/clock/sun8i-v853-ccu.h>
> +#include <dt-bindings/reset/sun8i-v853-ccu.h>
> +
> +#define CLK_NUMBER (CLK_FANOUT2 + 1)
> +
> +#endif /* _CCU_SUN8I_V853_H_ */
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH 05/12] clk: sunxi-ng: add CCU drivers for V853
2025-01-28 0:42 ` Andre Przywara
@ 2025-01-28 9:06 ` András Szemző
2025-01-28 11:22 ` Andre Przywara
0 siblings, 1 reply; 50+ messages in thread
From: András Szemző @ 2025-01-28 9:06 UTC (permalink / raw)
To: Andre Przywara
Cc: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
Linus Walleij, Philipp Zabel, Maxime Ripard, Vinod Koul,
Kishon Vijay Abraham I, Ulf Hansson, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Uwe Kleine-König,
Florian Fainelli, linux-clk, devicetree, linux-arm-kernel,
linux-sunxi, linux-kernel, linux-phy, linux-gpio, linux-pm,
linux-riscv
Hi Andre,
> On 28 Jan 2025, at 01:42, Andre Przywara <andre.przywara@arm.com> wrote:
>
> On Fri, 10 Jan 2025 13:39:16 +0100
> Andras Szemzo <szemzo.andras@gmail.com> wrote:
>
> Hi Andras,
>
> oh dear, that's a code line and a half!
>
> First very much for sending this, I know from (recent) experience that
> those clock drivers can be very daunting and tedious to write
> ...which is unfortunately true for the review as well ;-)
>
> So this is the first round, as I was keeping and updating this in my
> Drafts folder for almost two weeks now.
>
>> V853 has similar gates/resets like existing Allwinner SOCs. Add support for it's CCU and PRCM CCU.
>>
>> Signed-off-by: Andras Szemzo <szemzo.andras@gmail.com>
>> ---
>> drivers/clk/sunxi-ng/Kconfig | 10 +
>> drivers/clk/sunxi-ng/Makefile | 4 +
>> drivers/clk/sunxi-ng/ccu-sun8i-v853-r.c | 95 ++
>> drivers/clk/sunxi-ng/ccu-sun8i-v853-r.h | 15 +
>> drivers/clk/sunxi-ng/ccu-sun8i-v853.c | 1145 +++++++++++++++++++++++
>> drivers/clk/sunxi-ng/ccu-sun8i-v853.h | 14 +
>> 6 files changed, 1283 insertions(+)
>> create mode 100644 drivers/clk/sunxi-ng/ccu-sun8i-v853-r.c
>> create mode 100644 drivers/clk/sunxi-ng/ccu-sun8i-v853-r.h
>> create mode 100644 drivers/clk/sunxi-ng/ccu-sun8i-v853.c
>> create mode 100644 drivers/clk/sunxi-ng/ccu-sun8i-v853.h
>>
>> diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig
>> index b547198a2c65..c43002246b22 100644
>> --- a/drivers/clk/sunxi-ng/Kconfig
>> +++ b/drivers/clk/sunxi-ng/Kconfig
>> @@ -22,6 +22,16 @@ config SUN20I_D1_R_CCU
>> default y
>> depends on MACH_SUN8I || RISCV || COMPILE_TEST
>>
>> +config SUN8I_V853_CCU
>> + tristate "Support for the Allwinner V853 CCU"
>> + default MACH_SUN8I
>> + depends on MACH_SUN8I || COMPILE_TEST
>> +
>> +config SUN8I_V853_R_CCU
>> + tristate "Support for the Allwinner V853 PRCM CCU"
>> + default MACH_SUN8I
>> + depends on MACH_SUN8I || COMPILE_TEST
>> +
>> config SUN50I_A64_CCU
>> tristate "Support for the Allwinner A64 CCU"
>> default y
>> diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
>> index 6b3ae2b620db..c32430d874ea 100644
>> --- a/drivers/clk/sunxi-ng/Makefile
>> +++ b/drivers/clk/sunxi-ng/Makefile
>> @@ -27,6 +27,8 @@ sunxi-ccu-y += ccu_mp.o
>> obj-$(CONFIG_SUNIV_F1C100S_CCU) += suniv-f1c100s-ccu.o
>> obj-$(CONFIG_SUN20I_D1_CCU) += sun20i-d1-ccu.o
>> obj-$(CONFIG_SUN20I_D1_R_CCU) += sun20i-d1-r-ccu.o
>> +obj-$(CONFIG_SUN8I_V853_CCU) += sun8i-v853-ccu.o
>> +obj-$(CONFIG_SUN8I_V853_R_CCU) += sun8i-v853-r-ccu.o
>> obj-$(CONFIG_SUN50I_A64_CCU) += sun50i-a64-ccu.o
>> obj-$(CONFIG_SUN50I_A100_CCU) += sun50i-a100-ccu.o
>> obj-$(CONFIG_SUN50I_A100_R_CCU) += sun50i-a100-r-ccu.o
>> @@ -50,6 +52,8 @@ obj-$(CONFIG_SUN9I_A80_CCU) += sun9i-a80-de-ccu.o
>> obj-$(CONFIG_SUN9I_A80_CCU) += sun9i-a80-usb-ccu.o
>>
>> suniv-f1c100s-ccu-y += ccu-suniv-f1c100s.o
>> +sun8i-v853-ccu-y += ccu-sun8i-v853.o
>> +sun8i-v853-r-ccu-y += ccu-sun8i-v853-r.o
>> sun20i-d1-ccu-y += ccu-sun20i-d1.o
>> sun20i-d1-r-ccu-y += ccu-sun20i-d1-r.o
>> sun50i-a64-ccu-y += ccu-sun50i-a64.o
>> diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-v853-r.c b/drivers/clk/sunxi-ng/ccu-sun8i-v853-r.c
>> new file mode 100644
>> index 000000000000..19a8ba587793
>> --- /dev/null
>> +++ b/drivers/clk/sunxi-ng/ccu-sun8i-v853-r.c
>> @@ -0,0 +1,95 @@
>> +// SPDX-License-Identifier: GPL-3.0
>> +/* Copyright(c) 2020 - 2023 Allwinner Technology Co.,Ltd. All rights reserved.
>
> So does that mean you copied that from the BSP? How much is your own
> work then? Should "rengaomin" be then the author?
>
> But more importantly: As far as I know, GPL-3 is NOT compatible with
> the kernel. You definitely cannot add code with that license, and from
> my understanding cannot copy GPL-3 code without keeping the license,
> which means copying is a no-go.
> You would need to ask the original author to change the license. I have
> seen license changes in github repos mirroring Allwinner's SDK in the
> last few months (someone must have told them?), so it's worth checking
> back there to see if the license has changed.
>
> But with that header, and with that source (subject to clarification)
> this cannot be merged as such.
>
In the datasheet what I have, all this R_PRCM block is mentioned only at the memory mapping.
I did't found any other documentation about this IP.
There is a driver [1] based on the more or less mainline'ish sunxi-ng clk
framework, so I took that and made it work with this v853-ccu driver.
I don’t know what should/can I do with the Licence or how should it done properly,
as it’s basically a few registers/bits, but without documentation it’s hard to write it from scratch.
[1]: https://github.com/YuzukiHD/TinyVision/blob/main/kernel/bsp/drivers/clk/sunxi-ng/ccu-sun8iw21-r.c
>> + *
>> + * Copyright (c) 2023 rengaomin@allwinnertech.com
>> + */
>> +
>> +#include <linux/clk-provider.h>
>> +#include <linux/io.h>
>> +#include <linux/module.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-sun8i-v853-r.h"
>> +
>> +
>> +static SUNXI_CCU_GATE(r_twd_clk, "r-twd", "osc24M", 0x012C, BIT(0), 0);
>> +static SUNXI_CCU_GATE(r_ppu_clk, "r-ppu", "osc24M", 0x01AC, BIT(0), 0);
>> +static SUNXI_CCU_GATE(r_rtc_clk, "r-rtc", "osc24M", 0x020C, BIT(0), 0);
>> +static SUNXI_CCU_GATE(r_cpucfg_clk, "r-cpucfg", "osc24M",
>> + 0x022C, BIT(0), 0);
>> +
>> +static struct ccu_reset_map sun8i_v853_r_ccu_resets[] = {
>> + [RST_BUS_R_PPU] = { 0x01ac, BIT(16) },
>> + [RST_BUS_R_RTC] = { 0x020c, BIT(16) },
>> + [RST_BUS_R_CPUCFG] = { 0x022c, BIT(16) },
>> +};
>> +
>> +static struct clk_hw_onecell_data sun8i_v853_r_hw_clks = {
>> + .hws = {
>> + [CLK_R_TWD] = &r_twd_clk.common.hw,
>> + [CLK_R_PPU] = &r_ppu_clk.common.hw,
>> + [CLK_R_RTC] = &r_rtc_clk.common.hw,
>> + [CLK_R_CPUCFG] = &r_cpucfg_clk.common.hw,
>> + },
>> + .num = CLK_NUMBER,
>> +};
>> +
>> +static struct ccu_common *sun8i_v853_r_ccu_clks[] = {
>> + &r_twd_clk.common,
>> + &r_ppu_clk.common,
>> + &r_rtc_clk.common,
>> + &r_cpucfg_clk.common,
>> +};
>> +
>> +
>> +static const struct sunxi_ccu_desc sun8i_v853_r_ccu_desc = {
>> + .ccu_clks = sun8i_v853_r_ccu_clks,
>> + .num_ccu_clks = ARRAY_SIZE(sun8i_v853_r_ccu_clks),
>> +
>> + .hw_clks = &sun8i_v853_r_hw_clks,
>> +
>> + .resets = sun8i_v853_r_ccu_resets,
>> + .num_resets = ARRAY_SIZE(sun8i_v853_r_ccu_resets),
>> +};
>> +
>> +static int sun8i_v853_r_ccu_probe(struct platform_device *pdev)
>> +{
>> + void __iomem *reg;
>> +
>> + reg = devm_platform_ioremap_resource(pdev, 0);
>> + if (IS_ERR(reg))
>> + return PTR_ERR(reg);
>> +
>> + return devm_sunxi_ccu_probe(&pdev->dev, reg, &sun8i_v853_r_ccu_desc);
>> +}
>> +
>> +static const struct of_device_id sun8i_v853_r_ccu_ids[] = {
>> + { .compatible = "allwinner,sun8i-v853-r-ccu" },
>> + { }
>> +};
>> +
>> +static struct platform_driver sun8i_v853_r_ccu_driver = {
>> + .probe = sun8i_v853_r_ccu_probe,
>> + .driver = {
>> + .name = "sun8i-v853-r-ccu",
>> + .suppress_bind_attrs = true,
>> + .of_match_table = sun8i_v853_r_ccu_ids,
>> + },
>> +};
>> +module_platform_driver(sun8i_v853_r_ccu_driver);
>> +
>> +MODULE_IMPORT_NS("SUNXI_CCU");
>> +MODULE_LICENSE("GPL");
>> diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-v853-r.h b/drivers/clk/sunxi-ng/ccu-sun8i-v853-r.h
>> new file mode 100644
>> index 000000000000..156ca15e8208
>> --- /dev/null
>> +++ b/drivers/clk/sunxi-ng/ccu-sun8i-v853-r.h
>> @@ -0,0 +1,15 @@
>> +/* SPDX-License-Identifier: GPL-2.0 */
>
> Here the license looks right, but the authorship and source are still
> in question. Looks like the only real code in here is CLK_NUMBER, so if
> that is your line, drop all those bogus copyrights, and put in your own.
Ok, I’ll.
>
>> +/* Copyright(c) 2020 - 2023 Allwinner Technology Co.,Ltd. All rights reserved.
>> + *
>> + * Copyright (c) 2023 rengaomin@allwinnertech.com
>> + */
>> +
>> +#ifndef _CCU_SUN8I_V853_R_H
>> +#define _CCU_SUN8I_V853_R_H
>> +
>> +#include <dt-bindings/clock/sun8i-v853-r-ccu.h>
>> +#include <dt-bindings/reset/sun8i-v853-r-ccu.h>
>> +
>> +#define CLK_NUMBER CLK_R_MAX_NO
>
> What's "CLK_R_MAX_NO"? I think we put in the actual last clock name in,
> traditionally?
>
Yes, you are right.
>> +
>> +#endif
>> diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-v853.c b/drivers/clk/sunxi-ng/ccu-sun8i-v853.c
>> new file mode 100644
>> index 000000000000..a1947357a08e
>> --- /dev/null
>> +++ b/drivers/clk/sunxi-ng/ccu-sun8i-v853.c
>> @@ -0,0 +1,1145 @@
>> +// SPDX-License-Identifier: GPL-2.0-only
>> +/*
>> + * Copyright (C) 2024 Andras Szemzo <szemzo.andras@gmail.com>
>> + *
>> + * Based on ccu-sun20i-d1.c, which is:
>> + * Copyright (C) 2021 Samuel Holland. All rights reserved.
>
> All rights reserved? Where does that come from? Please remove that.
>
Starting to write the first ccu driver without prior knowledge is not an easy task, so I started from the d1 ccu driver. I don’t know
how much from that remains actually, but I don’t wanted to remove that comment. I looked around how should it be done
correctly, and copied the remark from the ccu-sun8i-v3s.c
It has exactly the same copyright.
..
* Based on ccu-sun8i-h3.c, which is:
* Copyright (c) 2016 Maxime Ripard. All rights reserved.
..
I’ll remove that.
>> + */
>> +
>> +#include <linux/clk-provider.h>
>> +#include <linux/io.h>
>> +#include <linux/module.h>
>> +#include <linux/platform_device.h>
>> +
>> +#include "../clk.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-sun8i-v853.h"
>> +
>> +static const struct clk_parent_data osc24M[] = {
>> + { .fw_name = "hosc" }
>> +};
>> +
>> +/*
>> + * For the CPU PLL, the output divider is described as "only for testing"
>> + * in the user manual. So it's not modelled and forced to 0.
>> + */
>> +#define SUN8I_V853_PLL_CPU_REG 0x000
>> +
>> +static struct ccu_mult pll_cpu_clk = {
>> + .enable = BIT(27) | BIT(30) | BIT(31),
>
> But bit 30 and 31 are set already by the PLL loop in the probe routine
> below, so we just need bit 27 to gate the output.
>
>> + .lock = BIT(28),
>> + .mult = _SUNXI_CCU_MULT_MIN(8, 8, 12),
>
> technically the manual says the minimum is 11, though this doesn't
> really matter, as we will never go that low anyway.
>
>> + .common = {
>> + .reg = 0x000,
>> + .hw.init = CLK_HW_INIT_PARENTS_DATA("pll-cpu", osc24M,
>> + &ccu_mult_ops,
>> + CLK_SET_RATE_UNGATE),
>
> This must be CLK_SET_RATE_GATE, as we figured some weeks ago. The manual
> says that for changing the frequency you must leave the PLL enabled
> (bits 31 and 30 = 1), but gate the output (bit 27 = 0). The "GATE" in
> that flag name here refers to the .enable mask above.
> So CLK_SET_RATE_UNGATE would mean: don't touch the enable bit, but keep
> it running, which would be correct if the enable bit would be about the
> real enable bit (bit 31). But since we model this like "enable means not
> gated", we must gate the output, by setting the enable bit to 0.
> CLK_SET_RATE_GATE does exactly that.
>
All this BIT (30, 31, 27) and MULT_MIN 12 are comes from the mistake that I tried to follow the BSP
driver [2] too closely.
As the cpu freq. scaling are working [3] with this settings too, I missed that.
I’ll fix it.
[2]: https://github.com/YuzukiHD/TinyVision/blob/main/kernel/bsp/drivers/clk/sunxi-ng/ccu-sun8iw21.c
[3]: v851s:~# cat /sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state
408000 177620
600000 10099
720000 2593
912000 338
1008000 3
1200000 5675617
v851s:~#
>> + },
>> +};
>> +
>> +/* Some PLLs are input * N / div1 / P. Model them as NKMP with no K */
>> +#define SUN8I_V853_PLL_DDR_REG 0x010
>> +static struct ccu_nkmp pll_ddr_clk = {
>> + .enable = BIT(27) | BIT(30) | BIT(31),
>
> same here, only bit 27 please.
>
>> + .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_PARENTS_DATA("pll-ddr", osc24M,
>> + &ccu_nkmp_ops,
>> + CLK_SET_RATE_UNGATE),
>
> CLK_SET_RATE_GATE, as above.
>
>> + },
>> +};
>> +
>> +#define SUN8I_V853_PLL_PERIPH_REG 0x020
>> +static struct ccu_nm pll_periph_4x_clk = {
>> + .enable = BIT(27) | BIT(30) | BIT(31),
>
> BIT(27), as above, and further down as well
>
>> + .lock = BIT(28),
>> + .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
>> + .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
>> + .common = {
>> + .reg = 0x020,
>> + .hw.init = CLK_HW_INIT_PARENTS_DATA("pll-periph-4x", osc24M,
>> + &ccu_nm_ops,
>> + CLK_SET_RATE_UNGATE),
>
> you guessed it: CLK_SET_RATE_GATE, here and further below, please
>
>> + },
>> +};
>> +
>> +static SUNXI_CCU_M(pll_periph_2x_clk, "pll-periph-2x", "pll-periph-4x",
>> + 0x020, 16, 3, 0);
>
> So is there a recommendation about how we reference other clocks? This
> one here is using the clock name, which requires a look-up, where we
> could use the pointer directly as well, as done down below.
>
> static const struct clk_hw *pll_periph0_4x_hws[] = {
> &pll_periph0_4x_clk.common.hw
> };
> static SUNXI_CCU_M_HWS(pll_periph0_2x_clk, "pll-periph0-2x",
> pll_periph0_4x_hws, 0x020, 16, 3, 0);
>
> I have seen both, sun20i-d1 for instance uses this, and I copied from
> there for the A523 clock code.
>
> Would be glad to hear some maintainer's opinion.
>
>> +
>> +static SUNXI_CCU_M(pll_periph_800M_clk, "pll-periph-800M", "pll-periph-4x",
>> + 0x020, 20, 3, 0);
>> +
>> +static SUNXI_CCU_M(pll_periph_480M_clk, "pll-periph-480M", "pll-periph-4x",
>> + 0x020, 2, 3, 0);
>> +
>> +static CLK_FIXED_FACTOR_HW(pll_periph_600M_clk, "pll-periph-600M",
>> + &pll_periph_2x_clk.common.hw, 2, 1, 0);
>> +
>> +static CLK_FIXED_FACTOR_HW(pll_periph_400M_clk, "pll-periph-400M",
>> + &pll_periph_2x_clk.common.hw, 3, 1, 0);
>> +
>> +static CLK_FIXED_FACTOR_HW(pll_periph_300M_clk, "pll-periph-300M",
>> + &pll_periph_600M_clk.hw, 2, 1, 0);
>> +
>> +static CLK_FIXED_FACTOR_HW(pll_periph_200M_clk, "pll-periph-200M",
>> + &pll_periph_400M_clk.hw, 2, 1, 0);
>> +
>> +static CLK_FIXED_FACTOR_HW(pll_periph_160M_clk, "pll-periph-160M",
>> + &pll_periph_480M_clk.common.hw, 3, 1, 0);
>> +
>> +static CLK_FIXED_FACTOR_HW(pll_periph_150M_clk, "pll-periph-150M",
>> + &pll_periph_300M_clk.hw, 2, 1, 0);
>> +
>> +
>> +/*
>> + * For Video PLLs, the output divider is described as "only for testing"
>> + * in the user manual. So it's not modelled and forced to 0.
>
> That's a bit confusing: the manual says that the default value for bit 0
> is 0x1, and that it's "only for testing", which would mean we should
> leave it like this, always dividing by 2? In the main description (bit
> 31) it says:
> VIDEOPLL4X = InputFreq*N/M
> but below (bit 0) it's
> VIDEOPLL4X = 24MHz*N/M/D
> (with D being "PLL_OUTPUT_DIV_D + 1", so 2 in our case)
>
> Do you have any indication how fast the video PLL really is? If it is
> divided by 2 (as we force that bit to 1 down in the probe routine), then
> we would need to model this with that CCU_FEATURE_FIXED_POSTDIV flag,
> and either leave that bit alone or force it to 1 instead.
> Also would be good to see what the BSP does.
>
The [2] BSP driver model it as a ccu_nkmp type, so i’ll double check it.
>> + */
>> +#define SUN8I_V853_PLL_VIDEO_REG 0x040
>> +static struct ccu_nm pll_video_4x_clk = {
>> + .enable = BIT(27) | BIT(30) | BIT(31),
>> + .lock = BIT(28),
>> + .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
>
> The manual says 11 (but again doesn't matter).
>
>> + .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
>> + .common = {
>> + .reg = 0x040,
>> + .hw.init = CLK_HW_INIT_PARENTS_DATA("pll-video-4x", osc24M,
>> + &ccu_nm_ops,
>> + CLK_SET_RATE_UNGATE),
>> + },
>> +};
>> +
>> +static const struct clk_hw *pll_video_4x_hws[] = {
>> + &pll_video_4x_clk.common.hw
>> +};
>> +static CLK_FIXED_FACTOR_HWS(pll_video_2x_clk, "pll-video-2x",
>> + pll_video_4x_hws, 2, 1, CLK_SET_RATE_PARENT);
>> +static CLK_FIXED_FACTOR_HWS(pll_video_1x_clk, "pll-video-1x",
>> + pll_video_4x_hws, 4, 1, CLK_SET_RATE_PARENT);
>
> Ah, here you are using the pointer reference to the base clock, not the
> string, as above. I think we should stick to one method?
Ok.
>
>> +/*
>> + * For CSI PLLs, the output divider is described as "only for testing"
>> + * in the user manual. So it's not modelled and forced to 0.
>
> Same situation as for the video PLL: what is the recommended setting of
> bit 0, really?
>
Same as with the PLL_VIDEO. I’ll check it again, and modify both.
>> + */
>> +#define SUN8I_V853_PLL_CSI_REG 0x048
>> +static struct ccu_nm pll_csi_4x_clk = {
>> + .enable = BIT(27) | BIT(30) | BIT(31),
>> + .lock = BIT(28),
>> + .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
>> + .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
>> + .common = {
>> + .reg = 0x048,
>> + .hw.init = CLK_HW_INIT_PARENTS_DATA("pll-csi-4x", osc24M,
>> + &ccu_nm_ops,
>> + CLK_SET_RATE_UNGATE),
>> + },
>> +};
>> +
>> +static CLK_FIXED_FACTOR_HW(pll_csi_clk, "pll-csi",
>> + &pll_csi_4x_clk.common.hw, 4, 1, CLK_SET_RATE_PARENT);
>> +
>> +
>> +#define SUN8I_V853_PLL_AUDIO_REG 0x78
>> +static struct ccu_sdm_setting pll_audio_div5_sdm_table[] = {
>> + { .rate = 196608000, .pattern = 0xc001eb85, .m = 5, .n = 40 }, /* 24.576 */
>> + { .rate = 67737600, .pattern = 0xc001288d, .m = 8, .n = 22 }, /* 22.5792 */
>> +};
>> +
>> +static struct ccu_nm pll_audio_div5_clk = {
>> + .enable = BIT(27) | BIT(30) | BIT(31),
>> + .lock = BIT(28),
>> + .n = _SUNXI_CCU_MULT(8, 8),
>> + .m = _SUNXI_CCU_DIV(20, 3),
>> + .sdm = _SUNXI_CCU_SDM(pll_audio_div5_sdm_table,
>> + BIT(24), 0x0178, BIT(31)),
>> + .common = {
>> + .reg = 0x0078,
>> + .features = CCU_FEATURE_SIGMA_DELTA_MOD,
>> + .hw.init = CLK_HW_INIT_PARENTS_DATA("pll-audio-div5", osc24M,
>> + &ccu_nm_ops,
>> + CLK_SET_RATE_UNGATE),
>> + },
>> +};
>> +static SUNXI_CCU_M(pll_audio_1x_clk, "pll-audio-1x", "pll-audio-div5",
>> + 0xe00, 0, 5, CLK_SET_RATE_PARENT);
>> +
>> +/* pll-audio-div2 and pll-aduio-4x not used, because audio-1x can cover 22.5792M and 24.576M */
>> +static SUNXI_CCU_M(pll_audio_div2_clk, "pll-audio-div2", "pll-audio",
>> + 0x078, 16, 3, 0);
>> +static SUNXI_CCU_M(pll_audio_4x_clk, "pll-audio-4x", "pll-audio-div2",
>> + 0xe00, 5, 5, 0);
>> +
>> +/*
>> + * For the NPU PLL, the output divider is described as "only for testing"
>> + * in the user manual. So it's not modelled and forced to 0.
>> + */
>> +#define SUN8I_V853_PLL_NPU_REG 0x080
>> +static struct ccu_nm pll_npu_4x_clk = {
>> + .enable = BIT(27) | BIT(30) | BIT(31),
>> + .lock = BIT(28),
>> + .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
>> + .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
>> + .common = {
>> + .reg = 0x080,
>> + .hw.init = CLK_HW_INIT_PARENTS_DATA("pll-npu-4x", osc24M,
>> + &ccu_nm_ops,
>> + CLK_SET_RATE_UNGATE),
>> + },
>> +};
>> +
>> +/*
>> + * The CPU gate is not modelled - it is in a separate register (0x504)
>> + * and has a special key field. The clock does not need to be ungated anyway.
>
> I would believe it should read: "The clock must not be gated anyway by
> the kernel". (As it would stop execution on the Arm cores, so it's only
> something for the management core).
>
ok.
>> + */
>> +static const struct clk_parent_data cpu_parents[] = {
>> + { .fw_name = "hosc" },
>> + { .fw_name = "losc" },
>> + { .fw_name = "iosc" },
>> + { .hw = &pll_cpu_clk.common.hw },
>
> The manual says there is a divider (PLL_CPU_OUT_EXT_DIVP[17:16]),
> though the description suggests it should stay as 0. I guess this is
> the intention here, but can you please add comment here?
>
ok.
>> + { .hw = &pll_periph_600M_clk.hw },
>> + { .hw = &pll_periph_800M_clk.common.hw },
>> +};
>> +
>> +static SUNXI_CCU_MUX_DATA(cpu_clk, "cpu", cpu_parents,
>> + 0x500, 24, 3, CLK_SET_RATE_PARENT | CLK_IS_CRITICAL);
>> +
>> +static SUNXI_CCU_M(cpu_axi_clk, "cpu-axi", "cpu",
>
> I wonder if it's more efficient to use a pointer to the CPU clock, and
> not a string?
>
I’ll fix that.
>> + 0x500, 0, 2, 0);
>> +static SUNXI_CCU_M(cpu_apb_clk, "cpu-apb", "cpu",
>> + 0x500, 8, 2, 0);
>> +
>> +static const struct clk_parent_data ahb_parents[] = {
>> + { .fw_name = "hosc" },
>> + { .fw_name = "losc" },
>> + { .fw_name = "iosc" },
>> + { .hw = &pll_periph_600M_clk.hw },
>> +};
>> +static SUNXI_CCU_MP_DATA_WITH_MUX(ahb_clk, "ahb", ahb_parents, 0x510,
>> + 0, 5, /* M */
>> + 8, 2, /* P */
>> + 24, 2, /* mux */
>> + 0);
>> +
>> +static SUNXI_CCU_MP_DATA_WITH_MUX(apb0_clk, "apb0", ahb_parents, 0x520,
>> + 0, 5, /* M */
>> + 8, 2, /* P */
>> + 24, 2, /* mux */
>> + 0);
>> +
>> +static SUNXI_CCU_MP_DATA_WITH_MUX(apb1_clk, "apb1", ahb_parents, 0x524,
>> + 0, 5, /* M */
>> + 8, 2, /* P */
>> + 24, 2, /* mux */
>> + 0);
>> +
>> +static const struct clk_hw *ahb_hws[] = { &ahb_clk.common.hw };
>> +static const struct clk_hw *apb0_hws[] = { &apb0_clk.common.hw };
>> +static const struct clk_hw *apb1_hws[] = { &apb1_clk.common.hw };
>> +
>> +
>> +
>> +static const struct clk_hw *de_g2d_parents[] = {
>> + &pll_periph_300M_clk.hw,
>> + &pll_video_1x_clk.hw,
>> +};
>> +static SUNXI_CCU_M_HW_WITH_MUX_GATE(de_clk, "de", de_g2d_parents, 0x600,
>> + 0, 5, /* M */
>> + 24, 1, /* mux */
>> + BIT(31), /* gate */
>> + CLK_SET_RATE_PARENT);
>> +
>> +static SUNXI_CCU_GATE_HWS(bus_de_clk, "bus-de", ahb_hws,
>> + 0x60c, BIT(0), 0);
>> +
>> +static SUNXI_CCU_M_HW_WITH_MUX_GATE(g2d_clk, "g2d", de_g2d_parents, 0x630,
>> + 0, 5, /* M */
>> + 24, 1, /* mux */
>> + BIT(31), /* gate */
>> + CLK_SET_RATE_PARENT);
>> +
>> +static SUNXI_CCU_GATE_HWS(bus_g2d_clk, "bus-g2d", ahb_hws,
>> + 0x63c, BIT(0), 0);
>> +
>> +
>> +static const struct clk_parent_data ce_parents[] = {
>> + { .fw_name = "hosc" },
>
> That parent is not mentioned in the manual, though it looks like an
> omission. Did you find the HOSC mentioned somewhere else?
The [2] BSP driver declares the CE parents in the same way.
>
>> + { .hw = &pll_periph_400M_clk.hw, },
>> + { .hw = &pll_periph_300M_clk.hw, }
>> +};
>> +static SUNXI_CCU_M_DATA_WITH_MUX_GATE(ce_clk, "ce", ce_parents, 0x680,
>> + 0, 4, /* M */
>
> looks like the indentation here is a bit off, can you check this? And
> for the other clocks as well?
>
Sure.
>> + 24, 3, /* mux */
>> + BIT(31), /* gate */
>> + CLK_SET_RATE_PARENT);
>> +
>> +static SUNXI_CCU_GATE_HWS(bus_ce_clk, "bus-ce", ahb_hws,
>> + 0x68c, BIT(0) | BIT(1), 0);
>
>
> (reviewed till here, for now, to keep my sanity. Skipping down to
> below, where there are more low-hanging fruits and bits that can be
> checked more systematically)
>
>> +
>> +static const struct clk_hw *ve_parents[] = {
>> + &pll_periph_300M_clk.hw,
>> + &pll_periph_400M_clk.hw,
>> + &pll_periph_480M_clk.common.hw,
>> + &pll_npu_4x_clk.common.hw,
>> + &pll_video_4x_clk.common.hw,
>> + &pll_csi_4x_clk.common.hw,
>> +};
>> +static SUNXI_CCU_M_HW_WITH_MUX_GATE(ve_clk, "ve", ve_parents, 0x690,
>> + 0, 5, /* M */
>> + 24, 3, /* mux */
>> + BIT(31), /* gate */
>> + CLK_SET_RATE_PARENT);
>> +
>> +static SUNXI_CCU_GATE_HWS(bus_ve_clk, "bus-ve", ahb_hws,
>> + 0x69c, BIT(0), 0);
>> +
>> +
>> +static const struct clk_hw *npu_parents[] = {
>> + &pll_periph_480M_clk.common.hw,
>> + &pll_periph_600M_clk.hw,
>> + &pll_periph_800M_clk.common.hw,
>> + &pll_npu_4x_clk.common.hw,
>> +};
>> +static SUNXI_CCU_M_HW_WITH_MUX_GATE(npu_clk, "npu", npu_parents, 0x6e0,
>> + 0, 5, /* M */
>> + 24, 3, /* mux */
>> + BIT(31), /* gate */
>> + 0);
>> +
>> +static SUNXI_CCU_GATE_HWS(bus_npu_clk, "bus-npu", ahb_hws,
>> + 0x6ec, BIT(0), 0);
>> +
>> +static SUNXI_CCU_GATE_HWS(bus_dma_clk, "bus-dma", ahb_hws,
>> + 0x70c, BIT(0), 0);
>> +
>> +static SUNXI_CCU_GATE_HWS(bus_msgbox0_clk, "bus-msgbox0", ahb_hws,
>> + 0x71c, BIT(0), 0);
>> +static SUNXI_CCU_GATE_HWS(bus_msgbox1_clk, "bus-msgbox1", ahb_hws,
>> + 0x71c, BIT(1), 0);
>> +
>> +static SUNXI_CCU_GATE_HWS(bus_spinlock_clk, "bus-spinlock", ahb_hws,
>> + 0x72c, BIT(0), 0);
>> +
>> +static SUNXI_CCU_GATE_HWS(bus_hstimer_clk, "bus-hstimer", ahb_hws,
>> + 0x73c, BIT(0), 0);
>> +
>> +static SUNXI_CCU_GATE_DATA(avs_clk, "avs", osc24M,
>> + 0x740, BIT(31), 0);
>> +
>> +static SUNXI_CCU_GATE_HWS(bus_dbg_clk, "bus-dbg", ahb_hws,
>> + 0x78c, BIT(0), 0);
>> +
>> +static SUNXI_CCU_GATE_HWS(bus_pwm_clk, "bus-pwm", apb0_hws,
>> + 0x7ac, BIT(0), 0);
>> +
>> +static SUNXI_CCU_GATE_HWS(bus_iommu_clk, "bus-iommu", ahb_hws,
>> + 0x7bc, BIT(0), 0);
>> +
>> +static const struct clk_hw *dram_parents[] = {
>> + &pll_ddr_clk.common.hw,
>> + &pll_periph_2x_clk.common.hw,
>> + &pll_periph_800M_clk.common.hw,
>> +};
>> +static SUNXI_CCU_MP_HW_WITH_MUX_GATE(dram_clk, "dram", dram_parents, 0x800,
>> + 0, 5, /* M */
>> + 8, 2, /* P */
>> + 24, 3, /* mux */
>> + BIT(31), CLK_IS_CRITICAL);
>> +
>> +static CLK_FIXED_FACTOR_HW(mbus_clk, "mbus",
>> + &dram_clk.common.hw, 4, 1, 0);
>> +
>> +static const struct clk_hw *mbus_hws[] = { &mbus_clk.hw };
>> +
>> +static SUNXI_CCU_GATE_HWS(mbus_dma_clk, "mbus-dma", mbus_hws,
>> + 0x804, BIT(0), 0);
>> +static SUNXI_CCU_GATE_HWS(mbus_ve_clk, "mbus-ve", mbus_hws,
>> + 0x804, BIT(1), 0);
>> +static SUNXI_CCU_GATE_HWS(mbus_ce_clk, "mbus-ce", mbus_hws,
>> + 0x804, BIT(2), 0);
>> +static SUNXI_CCU_GATE_HWS(mbus_csi_clk, "mbus-csi", mbus_hws,
>> + 0x804, BIT(8), 0);
>> +static SUNXI_CCU_GATE_HWS(mbus_isp_clk, "mbus-isp", mbus_hws,
>> + 0x804, BIT(9), 0);
>> +static SUNXI_CCU_GATE_HWS(mbus_g2d_clk, "mbus-g2d", mbus_hws,
>> + 0x804, BIT(10), 0);
>> +
>> +static SUNXI_CCU_GATE_HWS(bus_dram_clk, "bus-dram", ahb_hws,
>> + 0x80c, BIT(0), CLK_IS_CRITICAL);
>> +
>> +
>> +static const struct clk_parent_data mmc0_mmc1_parents[] = {
>> + { .fw_name = "hosc" },
>> + { .hw = &pll_periph_400M_clk.hw, },
>> + { .hw = &pll_periph_300M_clk.hw, },
>> +};
>> +static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(mmc0_clk, "mmc0", mmc0_mmc1_parents, 0x830,
>> + 0, 4, /* M */
>> + 8, 2, /* P */
>> + 24, 3, /* mux */
>> + BIT(31), /* gate */
>> + 0);
>> +
>> +static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(mmc1_clk, "mmc1", mmc0_mmc1_parents, 0x834,
>> + 0, 4, /* M */
>> + 8, 2, /* P */
>> + 24, 3, /* mux */
>> + BIT(31), /* gate */
>> + 0);
>> +
>> +static const struct clk_parent_data mmc2_parents[] = {
>> + { .fw_name = "hosc" },
>> + { .hw = &pll_periph_600M_clk.hw, },
>> + { .hw = &pll_periph_400M_clk.hw, },
>> +};
>> +static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(mmc2_clk, "mmc2", mmc2_parents, 0x838,
>> + 0, 4, /* M */
>> + 8, 2, /* P */
>> + 24, 3, /* mux */
>> + BIT(31), /* gate */
>> + 0);
>> +
>> +static SUNXI_CCU_GATE_HWS(bus_mmc0_clk, "bus-mmc0", ahb_hws,
>> + 0x84c, BIT(0), 0);
>> +static SUNXI_CCU_GATE_HWS(bus_mmc1_clk, "bus-mmc1", ahb_hws,
>> + 0x84c, BIT(1), 0);
>> +static SUNXI_CCU_GATE_HWS(bus_mmc2_clk, "bus-mmc2", ahb_hws,
>> + 0x84c, BIT(2), 0);
>> +
>> +static SUNXI_CCU_GATE_HWS(bus_uart0_clk, "bus-uart0", apb1_hws,
>> + 0x90c, BIT(0), 0);
>> +static SUNXI_CCU_GATE_HWS(bus_uart1_clk, "bus-uart1", apb1_hws,
>> + 0x90c, BIT(1), 0);
>> +static SUNXI_CCU_GATE_HWS(bus_uart2_clk, "bus-uart2", apb1_hws,
>> + 0x90c, BIT(2), 0);
>> +static SUNXI_CCU_GATE_HWS(bus_uart3_clk, "bus-uart3", apb1_hws,
>> + 0x90c, BIT(3), 0);
>> +
>> +static SUNXI_CCU_GATE_HWS(bus_i2c0_clk, "bus-i2c0", apb1_hws,
>> + 0x91c, BIT(0), 0);
>> +static SUNXI_CCU_GATE_HWS(bus_i2c1_clk, "bus-i2c1", apb1_hws,
>> + 0x91c, BIT(1), 0);
>> +static SUNXI_CCU_GATE_HWS(bus_i2c2_clk, "bus-i2c2", apb1_hws,
>> + 0x91c, BIT(2), 0);
>> +static SUNXI_CCU_GATE_HWS(bus_i2c3_clk, "bus-i2c3", apb1_hws,
>> + 0x91c, BIT(3), 0);
>> +static SUNXI_CCU_GATE_HWS(bus_i2c4_clk, "bus-i2c4", apb1_hws,
>> + 0x91c, BIT(4), 0);
>> +
>> +static const struct clk_parent_data spi_parents[] = {
>> + { .fw_name = "hosc" },
>> + { .hw = &pll_periph_300M_clk.hw, },
>> + { .hw = &pll_periph_200M_clk.hw, },
>> +};
>> +
>> +static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(spi0_clk, "spi0", spi_parents, 0x940,
>> + 0, 4, /* M */
>> + 8, 2, /* P */
>> + 24, 3, /* mux */
>> + BIT(31), /* gate */
>> + 0);
>> +
>> +static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(spi1_clk, "spi1", spi_parents, 0x944,
>> + 0, 4, /* M */
>> + 8, 2, /* P */
>> + 24, 3, /* mux */
>> + BIT(31), /* gate */
>> + 0);
>> +
>> +static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(spi2_clk, "spi2", spi_parents, 0x948,
>> + 0, 4, /* M */
>> + 8, 2, /* P */
>> + 24, 3, /* mux */
>> + BIT(31), /* gate */
>> + 0);
>> +
>> +static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(spi3_clk, "spi3", spi_parents, 0x94c,
>> + 0, 4, /* M */
>> + 8, 2, /* P */
>> + 24, 3, /* mux */
>> + BIT(31), /* gate */
>> + 0);
>> +
>> +static SUNXI_CCU_GATE_HWS(bus_spi0_clk, "bus-spi0", ahb_hws,
>> + 0x96c, BIT(0), 0);
>> +static SUNXI_CCU_GATE_HWS(bus_spi1_clk, "bus-spi1", ahb_hws,
>> + 0x96c, BIT(1), 0);
>> +static SUNXI_CCU_GATE_HWS(bus_spi2_clk, "bus-spi2", ahb_hws,
>> + 0x96c, BIT(2), 0);
>> +static SUNXI_CCU_GATE_HWS(bus_spi3_clk, "bus-spi3", ahb_hws,
>> + 0x96c, BIT(3), 0);
>> +
>> +
>> +static const struct clk_parent_data spif_parents[] = {
>> + { .fw_name = "hosc" },
>> + { .hw = &pll_periph_400M_clk.hw, },
>> + { .hw = &pll_periph_300M_clk.hw, },
>> +};
>> +
>> +static SUNXI_CCU_M_DATA_WITH_MUX_GATE(spif_clk, "spif", spif_parents, 0x0950,
>> + 0, 4, /* M */
>> + 24, 3, /* mux */
>> + BIT(31), /* gate */
>> + CLK_SET_RATE_PARENT);
>> +
>> +static SUNXI_CCU_GATE_HWS(bus_spif_clk, "bus-spif", ahb_hws,
>> + 0x096c, BIT(4), 0);
>> +
>> +
>> +static const struct clk_hw *pll_periph_150M_hws[] = { &pll_periph_150M_clk.hw };
>> +static SUNXI_CCU_GATE_HWS_WITH_PREDIV(emac_25M_clk, "emac-25M", pll_periph_150M_hws,
>> + 0x970, BIT(31) | BIT(30), 6, 0);
>> +
>> +static SUNXI_CCU_GATE_HWS(bus_emac_clk, "bus-emac", ahb_hws,
>> + 0x97c, BIT(0), 0);
>> +
>> +static SUNXI_CCU_GATE_HWS(bus_gpadc_clk, "bus-gpadc", apb0_hws,
>> + 0x9ec, BIT(0), 0);
>> +
>> +static SUNXI_CCU_GATE_HWS(bus_ths_clk, "bus-ths", ahb_hws,
>> + 0x9fc, BIT(0), 0);
>> +
>> +
>> +static const struct clk_hw *audio_parents[] = {
>> + &pll_audio_1x_clk.common.hw,
>> + &pll_audio_4x_clk.common.hw,
>> +};
>> +
>> +static SUNXI_CCU_M_HW_WITH_MUX_GATE(i2s0_clk, "i2s0", audio_parents, 0xa10,
>> + 0, 4, /* M */
>> + 24, 1, /* mux */
>> + BIT(31), /* gate */
>> + CLK_SET_RATE_PARENT);
>> +
>> +static SUNXI_CCU_M_HW_WITH_MUX_GATE(i2s1_clk, "i2s1", audio_parents, 0xa14,
>> + 0, 4, /* M */
>> + 24, 1, /* mux */
>> + BIT(31), /* gate */
>> + CLK_SET_RATE_PARENT);
>> +
>> +static SUNXI_CCU_GATE_HWS(bus_i2s1_clk, "bus-i2s1", ahb_hws,
>> + 0xa20, BIT(1), 0);
>> +
>
> Just a nit, but those two here v and ^ seem to be swapped.
>
Thanks.
> For the records: I extracted the bus gates and massaged them with some
> regexps to bring them into a shape where review is more feasible.
> They look alright to me. I didn't look at the respective mod clocks in
> detail, though.
>
>
>> +static SUNXI_CCU_GATE_HWS(bus_i2s0_clk, "bus-i2s0", ahb_hws,
>> + 0xa20, BIT(0), 0);
>> +
>> +static SUNXI_CCU_M_HW_WITH_MUX_GATE(dmic_clk, "dmic", audio_parents, 0xa40,
>> + 0, 4, /* M */
>> + 24, 1, /* mux */
>> + BIT(31), /* gate */
>> + CLK_SET_RATE_PARENT);
>> +
>> +static SUNXI_CCU_GATE_HWS(bus_dmic_clk, "bus-dmic", ahb_hws,
>> + 0xa4c, BIT(0), 0);
>> +
>> +static SUNXI_CCU_M_HW_WITH_MUX_GATE(audio_codec_dac_clk, "audio-codec-dac", audio_parents, 0xa50,
>
> I think you should break the line above, to stay within the 80 char
> limit.
>
Ok.
> Fast forwarding to the ccu_resets array ...
>
>> + 0, 4, /* M */
>> + 24, 1, /* mux */
>> + BIT(31), /* gate */
>> + CLK_SET_RATE_PARENT);
>> +
>> +static SUNXI_CCU_M_HW_WITH_MUX_GATE(audio_codec_adc_clk, "audio-codec-adc", audio_parents, 0xa54,
>> + 0, 4, /* M */
>> + 24, 1, /* mux */
>> + BIT(31), /* gate */
>> + CLK_SET_RATE_PARENT);
>> +
>> +static SUNXI_CCU_GATE_HWS(bus_audio_codec_clk, "bus-audio-codec", apb0_hws,
>> + 0xa5c, BIT(0), 0);
>> +
>> +/*
>> + * There are OHCI 12M clock source selection bits for the USB 2.0 port.
>> + * We will force them to 0 (12M divided from 48M).
>> + */
>> +static CLK_FIXED_FACTOR_FW_NAME(osc12M_clk, "osc12M", "hosc", 2, 1, 0);
>> +
>> +#define SUN8I_V853_USB_CLK_REG 0xa70
>> +
>> +static SUNXI_CCU_GATE(usb_ohci_clk, "usb", "osc12M", 0x0a70, BIT(31), 0);
>> +
>> +static SUNXI_CCU_GATE_HWS(bus_ohci_clk, "bus-ohci", ahb_hws, 0xa8c, BIT(0), 0);
>> +static SUNXI_CCU_GATE_HWS(bus_ehci_clk, "bus-ehci", ahb_hws, 0xa8c, BIT(4), 0);
>> +static SUNXI_CCU_GATE_HWS(bus_otg_clk, "bus-otg", ahb_hws, 0xa8c, BIT(8), 0);
>> +
>> +static SUNXI_CCU_GATE_HWS(bus_dpss_top_clk, "bus-dpss-top", ahb_hws,
>> + 0xabc, BIT(0), 0);
>> +
>> +
>> +static const struct clk_parent_data mipi_dsi_parents[] = {
>> + { .fw_name = "hosc" },
>> + { .hw = &pll_periph_200M_clk.hw },
>> + { .hw = &pll_periph_150M_clk.hw },
>> +};
>> +static SUNXI_CCU_M_DATA_WITH_MUX_GATE(mipi_dsi_clk, "mipi-dsi", mipi_dsi_parents, 0xb24,
>> + 0, 4, /* M */
>> + 24, 3, /* mux */
>> + BIT(31), /* gate */
>> + CLK_SET_RATE_PARENT);
>> +
>> +static SUNXI_CCU_GATE_HWS(bus_mipi_dsi_clk, "bus-mipi-dsi", ahb_hws,
>> + 0xb4c, BIT(0), 0);
>> +
>> +
>> +static const struct clk_hw *tcon_lcd_parents[] = {
>> + &pll_video_4x_clk.common.hw,
>> + &pll_periph_2x_clk.common.hw,
>> + &pll_csi_4x_clk.common.hw,
>> +};
>> +static SUNXI_CCU_MP_HW_WITH_MUX_GATE(tcon_lcd_clk, "tcon-lcd", tcon_lcd_parents, 0xb60,
>> + 0, 4, /* M */
>> + 8, 2, /* P */
>> + 24, 3, /* mux */
>> + BIT(31), /* gate */
>> + CLK_SET_RATE_PARENT);
>> +
>> +static SUNXI_CCU_GATE_HWS(bus_tcon_lcd_clk, "bus-tcon-lcd", ahb_hws,
>> + 0xb7c, BIT(0), 0);
>> +
>> +
>> +static const struct clk_hw *csi_top_parents[] = {
>> + &pll_periph_300M_clk.hw,
>> + &pll_periph_400M_clk.hw,
>> + &pll_video_4x_clk.common.hw,
>> + &pll_csi_4x_clk.common.hw,
>> +};
>> +static SUNXI_CCU_M_HW_WITH_MUX_GATE(csi_top_clk, "csi-top", csi_top_parents, 0xc04,
>> + 0, 5, /* M */
>> + 24, 3, /* mux */
>> + BIT(31), /* gate */
>> + 0);
>> +
>> +
>> +static const struct clk_parent_data csi_mclk_parents[] = {
>> + { .fw_name = "hosc" },
>> + { .hw = &pll_csi_4x_clk.common.hw },
>> + { .hw = &pll_video_4x_clk.common.hw },
>> + { .hw = &pll_periph_2x_clk.common.hw },
>> +};
>> +static SUNXI_CCU_M_DATA_WITH_MUX_GATE(csi_mclk0_clk, "csi-mclk0", csi_mclk_parents, 0xc08,
>> + 0, 5, /* M */
>> + 24, 3, /* mux */
>> + BIT(31), /* gate */
>> + 0);
>> +
>> +static SUNXI_CCU_M_DATA_WITH_MUX_GATE(csi_mclk1_clk, "csi-mclk1", csi_mclk_parents, 0xc0c,
>> + 0, 5, /* M */
>> + 24, 3, /* mux */
>> + BIT(31), /* gate */
>> + 0);
>> +
>> +static SUNXI_CCU_M_DATA_WITH_MUX_GATE(csi_mclk2_clk, "csi-mclk2", csi_mclk_parents, 0xc10,
>> + 0, 5, /* M */
>> + 24, 3, /* mux */
>> + BIT(31), /* gate */
>> + 0);
>> +
>> +static SUNXI_CCU_GATE_HWS(bus_csi_clk, "bus-csi", ahb_hws,
>> + 0xc2c, BIT(0), 0);
>> +
>> +
>> +static SUNXI_CCU_GATE_HWS(bus_wiegand_clk, "bus-wiegand", ahb_hws,
>> + 0xc7c, BIT(0), 0);
>> +
>> +
>> +static const struct clk_parent_data riscv_parents[] = {
>> + { .fw_name = "hosc" },
>> + { .fw_name = "losc" },
>> + { .fw_name = "iosc" },
>> + { .hw = &pll_periph_600M_clk.hw },
>> + { .hw = &pll_periph_480M_clk.common.hw },
>> + { .hw = &pll_cpu_clk.common.hw },
>> +};
>> +static SUNXI_CCU_M_DATA_WITH_MUX(riscv_clk, "riscv-cpu", riscv_parents, 0xd00,
>> + 0, 5, /* M */
>> + 24, 3, /* mux */
>> + CLK_SET_RATE_PARENT);
>> +
>> +/* The riscv-axi clk must be divided by at least 2. */
>> +static struct clk_div_table riscv_axi_table[] = {
>> + { .val = 1, .div = 2 },
>> + { .val = 2, .div = 3 },
>> + { .val = 3, .div = 4 },
>> + { /* Sentinel */ }
>> +};
>> +static SUNXI_CCU_DIV_TABLE_HW(riscv_axi_clk, "riscv-axi", &riscv_clk.common.hw,
>> + 0xd00, 8, 2, riscv_axi_table, 0);
>> +
>> +
>> +static SUNXI_CCU_GATE_HWS(riscv_cfg, "riscv-cfg", ahb_hws,
>> + 0xd0c, BIT(0), 0);
>> +
>> +static const struct clk_hw *pll_periph_160M_hws[] = {
>> + &pll_periph_160M_clk.hw,
>> +};
>> +
>> +static SUNXI_CCU_GATE_DATA(fanout_24M_clk, "fanout-24M", osc24M,
>> + 0xf30, BIT(0), 0);
>> +static SUNXI_CCU_GATE_DATA_WITH_PREDIV(fanout_12M_clk, "fanout-12M", osc24M,
>> + 0xf30, BIT(1), 2, 0);
>> +static SUNXI_CCU_GATE_HWS_WITH_PREDIV(fanout_16M_clk, "fanout-16M", pll_periph_160M_hws,
>> + 0xf30, BIT(2), 10, 0);
>> +static SUNXI_CCU_GATE_HWS_WITH_PREDIV(fanout_25M_clk, "fanout-25M", pll_periph_150M_hws,
>> + 0xf30, BIT(3), 6, 0);
>> +
>> +
>> +
>> +/* This clock has a second divider that is not modelled and forced to 0. */
>> +#define SUN8I_V853_FANOUT_27M_REG 0xf34
>> +static const struct clk_hw *fanout_27M_parents[] = {
>> + &pll_video_1x_clk.hw,
>> + &pll_csi_clk.hw,
>> + &pll_periph_300M_clk.hw,
>> +};
>> +static SUNXI_CCU_M_HW_WITH_MUX_GATE(fanout_27M_clk, "fanout-27M", fanout_27M_parents, 0xf34,
>> + 0, 5, /* M */
>> + 24, 2, /* mux */
>> + BIT(31), /* gate */
>> + 0);
>> +static SUNXI_CCU_M_HWS_WITH_GATE(fanout_pclk_clk, "fanout-pclk", apb0_hws, 0xf38,
>> + 0, 5, /* M */
>> + BIT(31), /* gate */
>> + 0);
>> +
>> +static const struct clk_parent_data fanout_parents[] = {
>> + { .fw_name = "losc" },
>> + { .hw = &fanout_12M_clk.common.hw },
>> + { .hw = &fanout_16M_clk.common.hw },
>> + { .hw = &fanout_24M_clk.common.hw },
>> + { .hw = &fanout_25M_clk.common.hw },
>> + { .hw = &fanout_27M_clk.common.hw },
>> + { .hw = &fanout_pclk_clk.common.hw },
>> +};
>> +
>> +static SUNXI_CCU_MUX_DATA_WITH_GATE(fanout0_clk, "fanout0", fanout_parents, 0xf3c,
>> + 0, 3, /* mux */
>> + BIT(21), /* gate */
>> + 0);
>> +static SUNXI_CCU_MUX_DATA_WITH_GATE(fanout1_clk, "fanout1", fanout_parents, 0xf3c,
>> + 3, 3, /* mux */
>> + BIT(22), /* gate */
>> + 0);
>> +static SUNXI_CCU_MUX_DATA_WITH_GATE(fanout2_clk, "fanout2", fanout_parents, 0xf3c,
>> + 6, 3, /* mux */
>> + BIT(23), /* gate */
>> + 0);
>> +
>> +
>> +static struct ccu_common *sun8i_v853_ccu_clks[] = {
>> + &pll_cpu_clk.common,
>> + &pll_ddr_clk.common,
>> + &pll_periph_4x_clk.common,
>> + &pll_periph_2x_clk.common,
>> + &pll_periph_800M_clk.common,
>> + &pll_periph_480M_clk.common,
>> + &pll_video_4x_clk.common,
>> + &pll_csi_4x_clk.common,
>> + &pll_audio_div2_clk.common,
>> + &pll_audio_div5_clk.common,
>> + &pll_audio_4x_clk.common,
>> + &pll_audio_1x_clk.common,
>> + &pll_npu_4x_clk.common,
>> + &cpu_clk.common,
>> + &cpu_axi_clk.common,
>> + &cpu_apb_clk.common,
>> + &ahb_clk.common,
>> + &apb0_clk.common,
>> + &apb1_clk.common,
>> + &de_clk.common,
>> + &bus_de_clk.common,
>> + &g2d_clk.common,
>> + &bus_g2d_clk.common,
>> + &ce_clk.common,
>> + &bus_ce_clk.common,
>> + &ve_clk.common,
>> + &bus_ve_clk.common,
>> + &npu_clk.common,
>> + &bus_npu_clk.common,
>> + &bus_dma_clk.common,
>> + &bus_msgbox0_clk.common,
>> + &bus_msgbox1_clk.common,
>> + &bus_spinlock_clk.common,
>> + &bus_hstimer_clk.common,
>> + &avs_clk.common,
>> + &bus_dbg_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_csi_clk.common,
>> + &mbus_isp_clk.common,
>> + &mbus_g2d_clk.common,
>> + &bus_dram_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_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,
>> + &spi2_clk.common,
>> + &spi3_clk.common,
>> + &bus_spi0_clk.common,
>> + &bus_spi1_clk.common,
>> + &bus_spi2_clk.common,
>> + &bus_spi3_clk.common,
>> + &spif_clk.common,
>> + &bus_spif_clk.common,
>> + &emac_25M_clk.common,
>> + &bus_emac_clk.common,
>> + &bus_gpadc_clk.common,
>> + &bus_ths_clk.common,
>> + &usb_ohci_clk.common,
>> + &bus_ohci_clk.common,
>> + &bus_ehci_clk.common,
>> + &bus_otg_clk.common,
>> + &i2s0_clk.common,
>> + &i2s1_clk.common,
>> + &bus_i2s0_clk.common,
>> + &bus_i2s1_clk.common,
>> + &dmic_clk.common,
>> + &bus_dmic_clk.common,
>> + &audio_codec_dac_clk.common,
>> + &audio_codec_adc_clk.common,
>> + &bus_audio_codec_clk.common,
>> + &bus_dpss_top_clk.common,
>> + &mipi_dsi_clk.common,
>> + &bus_mipi_dsi_clk.common,
>> + &tcon_lcd_clk.common,
>> + &bus_tcon_lcd_clk.common,
>> + &csi_top_clk.common,
>> + &csi_mclk0_clk.common,
>> + &csi_mclk1_clk.common,
>> + &csi_mclk2_clk.common,
>> + &bus_csi_clk.common,
>> + &bus_wiegand_clk.common,
>> + &riscv_clk.common,
>> + &riscv_axi_clk.common,
>> + &riscv_cfg.common,
>> + &fanout_24M_clk.common,
>> + &fanout_12M_clk.common,
>> + &fanout_16M_clk.common,
>> + &fanout_25M_clk.common,
>> + &fanout_27M_clk.common,
>> + &fanout_pclk_clk.common,
>> + &fanout0_clk.common,
>> + &fanout1_clk.common,
>> + &fanout2_clk.common,
>> +};
>> +
>> +static struct clk_hw_onecell_data sun8i_v853_hw_clks = {
>> + .num = CLK_NUMBER,
>> + .hws = {
>> + [CLK_OSC12M] = &osc12M_clk.hw,
>> + [CLK_PLL_CPU] = &pll_cpu_clk.common.hw,
>> + [CLK_PLL_DDR] = &pll_ddr_clk.common.hw,
>> + [CLK_PLL_PERIPH_4X] = &pll_periph_4x_clk.common.hw,
>> + [CLK_PLL_PERIPH_2X] = &pll_periph_2x_clk.common.hw,
>> + [CLK_PLL_PERIPH_800M] = &pll_periph_800M_clk.common.hw,
>> + [CLK_PLL_PERIPH_480M] = &pll_periph_480M_clk.common.hw,
>> + [CLK_PLL_PERIPH_600M] = &pll_periph_600M_clk.hw,
>> + [CLK_PLL_PERIPH_400M] = &pll_periph_400M_clk.hw,
>> + [CLK_PLL_PERIPH_300M] = &pll_periph_300M_clk.hw,
>> + [CLK_PLL_PERIPH_200M] = &pll_periph_200M_clk.hw,
>> + [CLK_PLL_PERIPH_160M] = &pll_periph_160M_clk.hw,
>> + [CLK_PLL_PERIPH_150M] = &pll_periph_150M_clk.hw,
>> + [CLK_PLL_VIDEO_4X] = &pll_video_4x_clk.common.hw,
>> + [CLK_PLL_VIDEO_2X] = &pll_video_2x_clk.hw,
>> + [CLK_PLL_VIDEO_1X] = &pll_video_1x_clk.hw,
>> + [CLK_PLL_CSI_4X] = &pll_csi_4x_clk.common.hw,
>> + [CLK_PLL_AUDIO_DIV2] = &pll_audio_div2_clk.common.hw,
>> + [CLK_PLL_AUDIO_DIV5] = &pll_audio_div5_clk.common.hw,
>> + [CLK_PLL_AUDIO_4X] = &pll_audio_4x_clk.common.hw,
>> + [CLK_PLL_AUDIO_1X] = &pll_audio_1x_clk.common.hw,
>> + [CLK_PLL_NPU_4X] = &pll_npu_4x_clk.common.hw,
>> + [CLK_CPU] = &cpu_clk.common.hw,
>> + [CLK_CPU_AXI] = &cpu_axi_clk.common.hw,
>> + [CLK_CPU_APB] = &cpu_apb_clk.common.hw,
>> + [CLK_AHB] = &ahb_clk.common.hw,
>> + [CLK_APB0] = &apb0_clk.common.hw,
>> + [CLK_APB1] = &apb1_clk.common.hw,
>> + [CLK_MBUS] = &mbus_clk.hw,
>> + [CLK_DE] = &de_clk.common.hw,
>> + [CLK_BUS_DE] = &bus_de_clk.common.hw,
>> + [CLK_G2D] = &g2d_clk.common.hw,
>> + [CLK_BUS_G2D] = &bus_g2d_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_NPU] = &npu_clk.common.hw,
>> + [CLK_BUS_NPU] = &bus_npu_clk.common.hw,
>> + [CLK_BUS_DMA] = &bus_dma_clk.common.hw,
>> + [CLK_BUS_MSGBOX0] = &bus_msgbox0_clk.common.hw,
>> + [CLK_BUS_MSGBOX1] = &bus_msgbox1_clk.common.hw,
>> + [CLK_BUS_SPINLOCK] = &bus_spinlock_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_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_CSI] = &mbus_csi_clk.common.hw,
>> + [CLK_MBUS_ISP] = &mbus_isp_clk.common.hw,
>> + [CLK_MBUS_G2D] = &mbus_g2d_clk.common.hw,
>> + [CLK_BUS_DRAM] = &bus_dram_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_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_SPI2] = &spi2_clk.common.hw,
>> + [CLK_SPI3] = &spi3_clk.common.hw,
>> + [CLK_BUS_SPI0] = &bus_spi0_clk.common.hw,
>> + [CLK_BUS_SPI1] = &bus_spi1_clk.common.hw,
>> + [CLK_BUS_SPI2] = &bus_spi2_clk.common.hw,
>> + [CLK_BUS_SPI3] = &bus_spi3_clk.common.hw,
>> + [CLK_SPIF] = &spif_clk.common.hw,
>> + [CLK_BUS_SPIF] = &bus_spif_clk.common.hw,
>> + [CLK_EMAC_25M] = &emac_25M_clk.common.hw,
>> + [CLK_BUS_EMAC] = &bus_emac_clk.common.hw,
>> + [CLK_BUS_GPADC] = &bus_gpadc_clk.common.hw,
>> + [CLK_BUS_THS] = &bus_ths_clk.common.hw,
>> + [CLK_I2S0] = &i2s0_clk.common.hw,
>> + [CLK_I2S1] = &i2s1_clk.common.hw,
>> + [CLK_BUS_I2S0] = &bus_i2s0_clk.common.hw,
>> + [CLK_BUS_I2S1] = &bus_i2s1_clk.common.hw,
>> + [CLK_DMIC] = &dmic_clk.common.hw,
>> + [CLK_BUS_DMIC] = &bus_dmic_clk.common.hw,
>> + [CLK_AUDIO_CODEC_DAC] = &audio_codec_dac_clk.common.hw,
>> + [CLK_AUDIO_CODEC_ADC] = &audio_codec_adc_clk.common.hw,
>> + [CLK_BUS_AUDIO_CODEC] = &bus_audio_codec_clk.common.hw,
>> + [CLK_USB_OHCI] = &usb_ohci_clk.common.hw,
>> + [CLK_BUS_OHCI] = &bus_ohci_clk.common.hw,
>> + [CLK_BUS_EHCI] = &bus_ehci_clk.common.hw,
>> + [CLK_BUS_OTG] = &bus_otg_clk.common.hw,
>> + [CLK_BUS_DPSS_TOP] = &bus_dpss_top_clk.common.hw,
>> + [CLK_MIPI_DSI] = &mipi_dsi_clk.common.hw,
>> + [CLK_BUS_MIPI_DSI] = &bus_mipi_dsi_clk.common.hw,
>> + [CLK_TCON_LCD] = &tcon_lcd_clk.common.hw,
>> + [CLK_BUS_TCON_LCD] = &bus_tcon_lcd_clk.common.hw,
>> + [CLK_CSI_TOP] = &csi_top_clk.common.hw,
>> + [CLK_CSI_MCLK0] = &csi_mclk0_clk.common.hw,
>> + [CLK_CSI_MCLK1] = &csi_mclk1_clk.common.hw,
>> + [CLK_CSI_MCLK2] = &csi_mclk2_clk.common.hw,
>> + [CLK_BUS_CSI] = &bus_csi_clk.common.hw,
>> + [CLK_BUS_WIEGAND] = &bus_wiegand_clk.common.hw,
>> + [CLK_RISCV] = &riscv_clk.common.hw,
>> + [CLK_RISCV_AXI] = &riscv_axi_clk.common.hw,
>> + [CLK_RISCV_CFG] = &riscv_cfg.common.hw,
>> + [CLK_FANOUT_24M] = &fanout_24M_clk.common.hw,
>> + [CLK_FANOUT_16M] = &fanout_16M_clk.common.hw,
>> + [CLK_FANOUT_12M] = &fanout_12M_clk.common.hw,
>> + [CLK_FANOUT_25M] = &fanout_25M_clk.common.hw,
>> + [CLK_FANOUT_27M] = &fanout_27M_clk.common.hw,
>> + [CLK_FANOUT_PCLK] = &fanout_pclk_clk.common.hw,
>> + [CLK_FANOUT0] = &fanout0_clk.common.hw,
>> + [CLK_FANOUT1] = &fanout1_clk.common.hw,
>> + [CLK_FANOUT2] = &fanout2_clk.common.hw,
>> + },
>> +};
>> +
>> +static struct ccu_reset_map sun8i_v853_ccu_resets[] = {
>> + [RST_MBUS] = { 0x540, BIT(30) },
>> + [RST_BUS_DE] = { 0x60c, BIT(16) },
>> + [RST_BUS_G2D] = { 0x63c, BIT(16) },
>> + [RST_BUS_CE] = { 0x68c, BIT(16) | BIT(17)},
>> + [RST_BUS_VE] = { 0x69c, BIT(16) },
>> + [RST_BUS_NPU] = { 0x6ec, BIT(16) },
>> + [RST_BUS_DMA] = { 0x70c, BIT(16) },
>> + [RST_BUS_MSGBOX0] = { 0x71c, BIT(16) },
>> + [RST_BUS_MSGBOX1] = { 0x71c, BIT(17) },
>> + [RST_BUS_SPINLOCK] = { 0x72c, BIT(16) },
>> + [RST_BUS_HSTIMER] = { 0x73c, BIT(16) },
>> + [RST_BUS_DBG] = { 0x78c, BIT(16) },
>> + [RST_BUS_PWM] = { 0x7ac, BIT(16) },
>> + [RST_BUS_DRAM] = { 0x80c, 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_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_SPIF] = { 0x96c, BIT(20) },
>
> That entry ^^^^ seems out of order.
Opps, I’ll fix it.
>
>> + [RST_BUS_SPI0] = { 0x96c, BIT(16) },
>> + [RST_BUS_SPI1] = { 0x96c, BIT(17) },
>> + [RST_BUS_SPI2] = { 0x96c, BIT(18) },
>> + [RST_BUS_SPI3] = { 0x96c, BIT(19) },
>> + [RST_BUS_EMAC] = { 0x97c, BIT(16) },
>> + [RST_BUS_GPADC] = { 0x9ec, BIT(16) },
>> + [RST_BUS_THS] = { 0x9fc, BIT(16) },
>> + [RST_BUS_I2S0] = { 0xa20, BIT(16) },
>> + [RST_BUS_I2S1] = { 0xa20, BIT(17) },
>> + [RST_BUS_DMIC] = { 0xa4c, BIT(16) },
>> + [RST_BUS_AUDIO_CODEC] = { 0xa5c, BIT(16) },
>> + [RST_USB_PHY] = { 0xa70, BIT(30) },
>> + [RST_BUS_OHCI] = { 0xa8c, BIT(16) },
>> + [RST_BUS_EHCI] = { 0xa8c, BIT(20) },
>> + [RST_BUS_OTG] = { 0xa8c, BIT(24) },
>> + [RST_BUS_DPSS_TOP] = { 0xabc, BIT(16) },
>> + [RST_BUS_MIPI_DSI] = { 0xb4c, BIT(16) },
>> + [RST_BUS_TCON_LCD] = { 0xb7c, BIT(16) },
>> + [RST_BUS_CSI] = { 0xc2c, BIT(16) },
>> + [RST_BUS_WIEGAND] = { 0xc7c, BIT(16) },
>> + [RST_RISCV_SYS_APB] = { 0xd04, BIT(2), CCU_FEATURE_KEY_FIELD },
>> + [RST_RISCV_SOFT] = { 0xd04, BIT(1), CCU_FEATURE_KEY_FIELD },
>> + [RST_RISCV_CLK_GATING] = { 0xd04, BIT(0), CCU_FEATURE_KEY_FIELD },
>
> But that's a clock gate, not a reset, right?
Yes, I forget to fix that. Modelling this way (because of the KEY_FIELD) was faster
when I wrote the remoteproc driver.
>
>> + [RST_RISCV_CFG] = { 0xd0c, BIT(16) }
>
> The rest of the reset bits match the manual.
>
>> +};
>> +
>> +static const struct sunxi_ccu_desc sun8i_v853_ccu_desc = {
>> + .ccu_clks = sun8i_v853_ccu_clks,
>> + .num_ccu_clks = ARRAY_SIZE(sun8i_v853_ccu_clks),
>> +
>> + .hw_clks = &sun8i_v853_hw_clks,
>> +
>> + .resets = sun8i_v853_ccu_resets,
>> + .num_resets = ARRAY_SIZE(sun8i_v853_ccu_resets),
>> +};
>> +
>> +static const u32 pll_regs[] = {
>> + SUN8I_V853_PLL_CPU_REG,
>> + SUN8I_V853_PLL_DDR_REG,
>> + SUN8I_V853_PLL_PERIPH_REG,
>> + SUN8I_V853_PLL_VIDEO_REG,
>> + SUN8I_V853_PLL_CSI_REG,
>> + SUN8I_V853_PLL_AUDIO_REG,
>> + SUN8I_V853_PLL_NPU_REG,
>> +};
>> +
>> +static int sun8i_v853_ccu_probe(struct platform_device *pdev)
>> +{
>> + void __iomem *reg;
>> + u32 val;
>> + int i, ret;
>> +
>> + reg = devm_platform_ioremap_resource(pdev, 0);
>> + if (IS_ERR(reg))
>> + return PTR_ERR(reg);
>> +
>> + /* Enable the enable, LDO, and lock bits on all PLLs. */
>> + for (i = 0; i < ARRAY_SIZE(pll_regs); i++) {
>> + val = readl(reg + pll_regs[i]);
>> + val |= BIT(31) | BIT(30) | BIT(29);
>> + writel(val, reg + pll_regs[i]);
>> + }
>> +
>> + /* Force PLL_CPU factor M to 0. */
>> + val = readl(reg + SUN8I_V853_PLL_CPU_REG);
>> + val &= ~GENMASK(1, 0);
>> + writel(val, reg + SUN8I_V853_PLL_CPU_REG);
>
> Let's just hope it was 0 already, as I guess a sudden jump of
> CPU frequency might not be too healthy.
>
I’ll double check that.
>> + /*
>> + * Force the output divider of video PLL to 0.
>
> Just a nit, but a "divider of 0" does not sound too healthy. Maybe:
> "Force the output divider to 1, by clearing bit 0."
>
Thanks.
> Cheers,
> Andre
>
>> + *
>> + * See the comment before pll-video0 definition for the reason.
>> + */
>> + val = readl(reg + SUN8I_V853_PLL_VIDEO_REG);
>> + val &= ~BIT(0);
>> + writel(val, reg + SUN8I_V853_PLL_VIDEO_REG);
>> +
>> + /*
>> + * Force the output divider of CSI PLL to 0.
>> + *
>> + * See the comment before pll-csi definition for the reason.
>> + */
>> + val = readl(reg + SUN8I_V853_PLL_CSI_REG);
>> + val &= ~BIT(0);
>> + writel(val, reg + SUN8I_V853_PLL_CSI_REG);
>> +
>> + /*
>> + * Force the output divider of NPU PLL to 0.
>> + *
>> + * See the comment before pll-npu definition for the reason.
>> + */
>> + val = readl(reg + SUN8I_V853_PLL_NPU_REG);
>> + val &= ~BIT(0);
>> + writel(val, reg + SUN8I_V853_PLL_NPU_REG);
>> +
>> + /*
>> + * Force OHCI 12M clock source to 00 (12MHz divided from 48MHz)
>> + *
>> + * This clock mux is still mysterious, and the code just enforces
>> + * it to have a valid clock parent.
>> + */
>> + val = readl(reg + SUN8I_V853_USB_CLK_REG);
>> + val &= ~GENMASK(25, 24);
>> + writel(val, reg + SUN8I_V853_USB_CLK_REG);
>> +
>> + /* Force fanout-27M factor N to 0. */
>> + val = readl(reg + SUN8I_V853_FANOUT_27M_REG);
>> + val &= ~GENMASK(9, 8);
>> + writel(val, reg + SUN8I_V853_FANOUT_27M_REG);
>> +
>> + ret = devm_sunxi_ccu_probe(&pdev->dev, reg, &sun8i_v853_ccu_desc);
>> + if (ret)
>> + return ret;
>> +
>> + return 0;
>> +}
>> +
>> +static const struct of_device_id sun8i_v853_ccu_ids[] = {
>> + { .compatible = "allwinner,sun8i-v853-ccu" },
>> + { }
>> +};
>> +
>> +static struct platform_driver sun8i_v853_ccu_driver = {
>> + .probe = sun8i_v853_ccu_probe,
>> + .driver = {
>> + .name = "sun8i-v853-ccu",
>> + .suppress_bind_attrs = true,
>> + .of_match_table = sun8i_v853_ccu_ids,
>> + },
>> +};
>> +module_platform_driver(sun8i_v853_ccu_driver);
>> +
>> +MODULE_IMPORT_NS("SUNXI_CCU");
>> +MODULE_LICENSE("GPL");
>> diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-v853.h b/drivers/clk/sunxi-ng/ccu-sun8i-v853.h
>> new file mode 100644
>> index 000000000000..b6ee1764fe5e
>> --- /dev/null
>> +++ b/drivers/clk/sunxi-ng/ccu-sun8i-v853.h
>> @@ -0,0 +1,14 @@
>> +/* SPDX-License-Identifier: GPL-2.0 */
>> +/*
>> + * Copyright (C) 2024 Andras Szemzo <szemzo.andras@gmail.com>
>> + */
>> +
>> +#ifndef _CCU_SUN8I_V853_H_
>> +#define _CCU_SUN8I_V853_H_
>> +
>> +#include <dt-bindings/clock/sun8i-v853-ccu.h>
>> +#include <dt-bindings/reset/sun8i-v853-ccu.h>
>> +
>> +#define CLK_NUMBER (CLK_FANOUT2 + 1)
>> +
>> +#endif /* _CCU_SUN8I_V853_H_ */
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH 05/12] clk: sunxi-ng: add CCU drivers for V853
2025-01-28 9:06 ` András Szemző
@ 2025-01-28 11:22 ` Andre Przywara
2025-01-29 7:29 ` András Szemző
0 siblings, 1 reply; 50+ messages in thread
From: Andre Przywara @ 2025-01-28 11:22 UTC (permalink / raw)
To: András Szemző
Cc: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
Linus Walleij, Philipp Zabel, Maxime Ripard, Vinod Koul,
Kishon Vijay Abraham I, Ulf Hansson, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Uwe Kleine-König,
Florian Fainelli, linux-clk, devicetree, linux-arm-kernel,
linux-sunxi, linux-kernel, linux-phy, linux-gpio, linux-pm,
linux-riscv
On Tue, 28 Jan 2025 10:06:50 +0100
András Szemző <szemzo.andras@gmail.com> wrote:
Hi András,
thanks for the quick and thorough reply, much appreciated!
> Hi Andre,
>
> > On 28 Jan 2025, at 01:42, Andre Przywara <andre.przywara@arm.com> wrote:
> >
> > On Fri, 10 Jan 2025 13:39:16 +0100
> > Andras Szemzo <szemzo.andras@gmail.com> wrote:
> >
> > Hi Andras,
> >
> > oh dear, that's a code line and a half!
> >
> > First very much for sending this, I know from (recent) experience that
> > those clock drivers can be very daunting and tedious to write
> > ...which is unfortunately true for the review as well ;-)
> >
> > So this is the first round, as I was keeping and updating this in my
> > Drafts folder for almost two weeks now.
> >
> >> V853 has similar gates/resets like existing Allwinner SOCs. Add support for it's CCU and PRCM CCU.
> >>
> >> Signed-off-by: Andras Szemzo <szemzo.andras@gmail.com>
> >> ---
> >> drivers/clk/sunxi-ng/Kconfig | 10 +
> >> drivers/clk/sunxi-ng/Makefile | 4 +
> >> drivers/clk/sunxi-ng/ccu-sun8i-v853-r.c | 95 ++
> >> drivers/clk/sunxi-ng/ccu-sun8i-v853-r.h | 15 +
> >> drivers/clk/sunxi-ng/ccu-sun8i-v853.c | 1145 +++++++++++++++++++++++
> >> drivers/clk/sunxi-ng/ccu-sun8i-v853.h | 14 +
> >> 6 files changed, 1283 insertions(+)
> >> create mode 100644 drivers/clk/sunxi-ng/ccu-sun8i-v853-r.c
> >> create mode 100644 drivers/clk/sunxi-ng/ccu-sun8i-v853-r.h
> >> create mode 100644 drivers/clk/sunxi-ng/ccu-sun8i-v853.c
> >> create mode 100644 drivers/clk/sunxi-ng/ccu-sun8i-v853.h
> >>
> >> diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig
> >> index b547198a2c65..c43002246b22 100644
> >> --- a/drivers/clk/sunxi-ng/Kconfig
> >> +++ b/drivers/clk/sunxi-ng/Kconfig
> >> @@ -22,6 +22,16 @@ config SUN20I_D1_R_CCU
> >> default y
> >> depends on MACH_SUN8I || RISCV || COMPILE_TEST
> >>
> >> +config SUN8I_V853_CCU
> >> + tristate "Support for the Allwinner V853 CCU"
> >> + default MACH_SUN8I
> >> + depends on MACH_SUN8I || COMPILE_TEST
> >> +
> >> +config SUN8I_V853_R_CCU
> >> + tristate "Support for the Allwinner V853 PRCM CCU"
> >> + default MACH_SUN8I
> >> + depends on MACH_SUN8I || COMPILE_TEST
> >> +
> >> config SUN50I_A64_CCU
> >> tristate "Support for the Allwinner A64 CCU"
> >> default y
> >> diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
> >> index 6b3ae2b620db..c32430d874ea 100644
> >> --- a/drivers/clk/sunxi-ng/Makefile
> >> +++ b/drivers/clk/sunxi-ng/Makefile
> >> @@ -27,6 +27,8 @@ sunxi-ccu-y += ccu_mp.o
> >> obj-$(CONFIG_SUNIV_F1C100S_CCU) += suniv-f1c100s-ccu.o
> >> obj-$(CONFIG_SUN20I_D1_CCU) += sun20i-d1-ccu.o
> >> obj-$(CONFIG_SUN20I_D1_R_CCU) += sun20i-d1-r-ccu.o
> >> +obj-$(CONFIG_SUN8I_V853_CCU) += sun8i-v853-ccu.o
> >> +obj-$(CONFIG_SUN8I_V853_R_CCU) += sun8i-v853-r-ccu.o
> >> obj-$(CONFIG_SUN50I_A64_CCU) += sun50i-a64-ccu.o
> >> obj-$(CONFIG_SUN50I_A100_CCU) += sun50i-a100-ccu.o
> >> obj-$(CONFIG_SUN50I_A100_R_CCU) += sun50i-a100-r-ccu.o
> >> @@ -50,6 +52,8 @@ obj-$(CONFIG_SUN9I_A80_CCU) += sun9i-a80-de-ccu.o
> >> obj-$(CONFIG_SUN9I_A80_CCU) += sun9i-a80-usb-ccu.o
> >>
> >> suniv-f1c100s-ccu-y += ccu-suniv-f1c100s.o
> >> +sun8i-v853-ccu-y += ccu-sun8i-v853.o
> >> +sun8i-v853-r-ccu-y += ccu-sun8i-v853-r.o
> >> sun20i-d1-ccu-y += ccu-sun20i-d1.o
> >> sun20i-d1-r-ccu-y += ccu-sun20i-d1-r.o
> >> sun50i-a64-ccu-y += ccu-sun50i-a64.o
> >> diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-v853-r.c b/drivers/clk/sunxi-ng/ccu-sun8i-v853-r.c
> >> new file mode 100644
> >> index 000000000000..19a8ba587793
> >> --- /dev/null
> >> +++ b/drivers/clk/sunxi-ng/ccu-sun8i-v853-r.c
> >> @@ -0,0 +1,95 @@
> >> +// SPDX-License-Identifier: GPL-3.0
> >> +/* Copyright(c) 2020 - 2023 Allwinner Technology Co.,Ltd. All rights reserved.
> >
> > So does that mean you copied that from the BSP? How much is your own
> > work then? Should "rengaomin" be then the author?
> >
> > But more importantly: As far as I know, GPL-3 is NOT compatible with
> > the kernel. You definitely cannot add code with that license, and from
> > my understanding cannot copy GPL-3 code without keeping the license,
> > which means copying is a no-go.
> > You would need to ask the original author to change the license. I have
> > seen license changes in github repos mirroring Allwinner's SDK in the
> > last few months (someone must have told them?), so it's worth checking
> > back there to see if the license has changed.
> >
> > But with that header, and with that source (subject to clarification)
> > this cannot be merged as such.
> >
>
> In the datasheet what I have, all this R_PRCM block is mentioned only at the memory mapping.
> I did't found any other documentation about this IP.
Yeah, that's quite common, the PRCM is rarely documented. It's also quite
stable across the modern SoC, and by chance the A523 manual actually
documents that, so you can peek in there. The V853 is probably a subset of
what's in the A523.
You can also probe registers from U-Boot:
=> mw.l 0x701012c 0xffffffff
=> md.l 0x701012c
That tells you which bits are actually implemented. Feel free to probe
around other registers, especially those ending in "c", which are typically
gates and resets. This would give you some confirmation.
So can you do the following:
Delete that file here, and copy over ccu-sun20i-d1-r.c. Add your
copyright, and use "Based on ...".
Then adjust that file according to the information gathered by inspecting
the Allwinner source file you mention below. Since we are talking about a
handful of clocks only, that should be easy enough?
Then we have a clean sheet license-wise, and you copy from a much better
source anyway (just seeing capital letter hex constants below, for
instance).
> There is a driver [1] based on the more or less mainline'ish sunxi-ng clk
> framework, so I took that and made it work with this v853-ccu driver.
>
> I don’t know what should/can I do with the Licence or how should it done properly,
> as it’s basically a few registers/bits, but without documentation it’s hard to write it from scratch.
Absolutely, and normally it's a no-brainer, since even Allwinner Linux
code must be GPL, but in this special case they became overzealous and put
GPL-3.0 in :-(
>
> [1]: https://github.com/YuzukiHD/TinyVision/blob/main/kernel/bsp/drivers/clk/sunxi-ng/ccu-sun8iw21-r.c
>
> >> + *
> >> + * Copyright (c) 2023 rengaomin@allwinnertech.com
> >> + */
> >> +
> >> +#include <linux/clk-provider.h>
> >> +#include <linux/io.h>
> >> +#include <linux/module.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-sun8i-v853-r.h"
> >> +
> >> +
> >> +static SUNXI_CCU_GATE(r_twd_clk, "r-twd", "osc24M", 0x012C, BIT(0), 0);
> >> +static SUNXI_CCU_GATE(r_ppu_clk, "r-ppu", "osc24M", 0x01AC, BIT(0), 0);
> >> +static SUNXI_CCU_GATE(r_rtc_clk, "r-rtc", "osc24M", 0x020C, BIT(0), 0);
> >> +static SUNXI_CCU_GATE(r_cpucfg_clk, "r-cpucfg", "osc24M",
> >> + 0x022C, BIT(0), 0);
> >> +
> >> +static struct ccu_reset_map sun8i_v853_r_ccu_resets[] = {
> >> + [RST_BUS_R_PPU] = { 0x01ac, BIT(16) },
> >> + [RST_BUS_R_RTC] = { 0x020c, BIT(16) },
> >> + [RST_BUS_R_CPUCFG] = { 0x022c, BIT(16) },
> >> +};
> >> +
> >> +static struct clk_hw_onecell_data sun8i_v853_r_hw_clks = {
> >> + .hws = {
> >> + [CLK_R_TWD] = &r_twd_clk.common.hw,
> >> + [CLK_R_PPU] = &r_ppu_clk.common.hw,
> >> + [CLK_R_RTC] = &r_rtc_clk.common.hw,
> >> + [CLK_R_CPUCFG] = &r_cpucfg_clk.common.hw,
> >> + },
> >> + .num = CLK_NUMBER,
> >> +};
> >> +
> >> +static struct ccu_common *sun8i_v853_r_ccu_clks[] = {
> >> + &r_twd_clk.common,
> >> + &r_ppu_clk.common,
> >> + &r_rtc_clk.common,
> >> + &r_cpucfg_clk.common,
> >> +};
> >> +
> >> +
> >> +static const struct sunxi_ccu_desc sun8i_v853_r_ccu_desc = {
> >> + .ccu_clks = sun8i_v853_r_ccu_clks,
> >> + .num_ccu_clks = ARRAY_SIZE(sun8i_v853_r_ccu_clks),
> >> +
> >> + .hw_clks = &sun8i_v853_r_hw_clks,
> >> +
> >> + .resets = sun8i_v853_r_ccu_resets,
> >> + .num_resets = ARRAY_SIZE(sun8i_v853_r_ccu_resets),
> >> +};
> >> +
> >> +static int sun8i_v853_r_ccu_probe(struct platform_device *pdev)
> >> +{
> >> + void __iomem *reg;
> >> +
> >> + reg = devm_platform_ioremap_resource(pdev, 0);
> >> + if (IS_ERR(reg))
> >> + return PTR_ERR(reg);
> >> +
> >> + return devm_sunxi_ccu_probe(&pdev->dev, reg, &sun8i_v853_r_ccu_desc);
> >> +}
> >> +
> >> +static const struct of_device_id sun8i_v853_r_ccu_ids[] = {
> >> + { .compatible = "allwinner,sun8i-v853-r-ccu" },
> >> + { }
> >> +};
> >> +
> >> +static struct platform_driver sun8i_v853_r_ccu_driver = {
> >> + .probe = sun8i_v853_r_ccu_probe,
> >> + .driver = {
> >> + .name = "sun8i-v853-r-ccu",
> >> + .suppress_bind_attrs = true,
> >> + .of_match_table = sun8i_v853_r_ccu_ids,
> >> + },
> >> +};
> >> +module_platform_driver(sun8i_v853_r_ccu_driver);
> >> +
> >> +MODULE_IMPORT_NS("SUNXI_CCU");
> >> +MODULE_LICENSE("GPL");
> >> diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-v853-r.h b/drivers/clk/sunxi-ng/ccu-sun8i-v853-r.h
> >> new file mode 100644
> >> index 000000000000..156ca15e8208
> >> --- /dev/null
> >> +++ b/drivers/clk/sunxi-ng/ccu-sun8i-v853-r.h
> >> @@ -0,0 +1,15 @@
> >> +/* SPDX-License-Identifier: GPL-2.0 */
> >
> > Here the license looks right, but the authorship and source are still
> > in question. Looks like the only real code in here is CLK_NUMBER, so if
> > that is your line, drop all those bogus copyrights, and put in your own.
>
> Ok, I’ll.
>
> >
> >> +/* Copyright(c) 2020 - 2023 Allwinner Technology Co.,Ltd. All rights reserved.
> >> + *
> >> + * Copyright (c) 2023 rengaomin@allwinnertech.com
> >> + */
> >> +
> >> +#ifndef _CCU_SUN8I_V853_R_H
> >> +#define _CCU_SUN8I_V853_R_H
> >> +
> >> +#include <dt-bindings/clock/sun8i-v853-r-ccu.h>
> >> +#include <dt-bindings/reset/sun8i-v853-r-ccu.h>
> >> +
> >> +#define CLK_NUMBER CLK_R_MAX_NO
> >
> > What's "CLK_R_MAX_NO"? I think we put in the actual last clock name in,
> > traditionally?
> >
>
> Yes, you are right.
Great, now it's your patch anyway, so you can easily claim the copyright
and authorship ;-)
> >> +
> >> +#endif
> >> diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-v853.c b/drivers/clk/sunxi-ng/ccu-sun8i-v853.c
> >> new file mode 100644
> >> index 000000000000..a1947357a08e
> >> --- /dev/null
> >> +++ b/drivers/clk/sunxi-ng/ccu-sun8i-v853.c
> >> @@ -0,0 +1,1145 @@
> >> +// SPDX-License-Identifier: GPL-2.0-only
> >> +/*
> >> + * Copyright (C) 2024 Andras Szemzo <szemzo.andras@gmail.com>
> >> + *
> >> + * Based on ccu-sun20i-d1.c, which is:
> >> + * Copyright (C) 2021 Samuel Holland. All rights reserved.
> >
> > All rights reserved? Where does that come from? Please remove that.
> >
>
> Starting to write the first ccu driver without prior knowledge is not an easy task, so I started from the d1 ccu driver. I don’t know
> how much from that remains actually, but I don’t wanted to remove that comment. I looked around how should it be done
> correctly, and copied the remark from the ccu-sun8i-v3s.c
>
> It has exactly the same copyright.
> ..
> * Based on ccu-sun8i-h3.c, which is:
> * Copyright (c) 2016 Maxime Ripard. All rights reserved.
Ah, I didn't see it with Samuel's name, hence was wondering. The H3
heritage is by now quite insignificant, I'd say, and since you dropped
Maxime anyway, you can just copy Samuel's line, without the "All rights
reserved". It's probably redundant anyway.
> I’ll remove that.
So yes, just remove the "All rights reserved." Thanks.
>
> >> + */
> >> +
> >> +#include <linux/clk-provider.h>
> >> +#include <linux/io.h>
> >> +#include <linux/module.h>
> >> +#include <linux/platform_device.h>
> >> +
> >> +#include "../clk.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-sun8i-v853.h"
> >> +
> >> +static const struct clk_parent_data osc24M[] = {
> >> + { .fw_name = "hosc" }
> >> +};
> >> +
> >> +/*
> >> + * For the CPU PLL, the output divider is described as "only for testing"
> >> + * in the user manual. So it's not modelled and forced to 0.
> >> + */
> >> +#define SUN8I_V853_PLL_CPU_REG 0x000
> >> +
> >> +static struct ccu_mult pll_cpu_clk = {
> >> + .enable = BIT(27) | BIT(30) | BIT(31),
> >
> > But bit 30 and 31 are set already by the PLL loop in the probe routine
> > below, so we just need bit 27 to gate the output.
> >
> >> + .lock = BIT(28),
> >> + .mult = _SUNXI_CCU_MULT_MIN(8, 8, 12),
> >
> > technically the manual says the minimum is 11, though this doesn't
> > really matter, as we will never go that low anyway.
> >
> >> + .common = {
> >> + .reg = 0x000,
> >> + .hw.init = CLK_HW_INIT_PARENTS_DATA("pll-cpu", osc24M,
> >> + &ccu_mult_ops,
> >> + CLK_SET_RATE_UNGATE),
> >
> > This must be CLK_SET_RATE_GATE, as we figured some weeks ago. The manual
> > says that for changing the frequency you must leave the PLL enabled
> > (bits 31 and 30 = 1), but gate the output (bit 27 = 0). The "GATE" in
> > that flag name here refers to the .enable mask above.
> > So CLK_SET_RATE_UNGATE would mean: don't touch the enable bit, but keep
> > it running, which would be correct if the enable bit would be about the
> > real enable bit (bit 31). But since we model this like "enable means not
> > gated", we must gate the output, by setting the enable bit to 0.
> > CLK_SET_RATE_GATE does exactly that.
> >
>
> All this BIT (30, 31, 27) and MULT_MIN 12 are comes from the mistake that I tried to follow the BSP
> driver [2] too closely.
> As the cpu freq. scaling are working [3] with this settings too, I missed that.
Thanks for testing, it would be awesome if you could repeat that test
briefly with the changes.
Thanks for confirming the other bits, much appreciated!
Cheers,
Andre
> I’ll fix it.
>
> [2]: https://github.com/YuzukiHD/TinyVision/blob/main/kernel/bsp/drivers/clk/sunxi-ng/ccu-sun8iw21.c
>
> [3]: v851s:~# cat /sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state
> 408000 177620
> 600000 10099
> 720000 2593
> 912000 338
> 1008000 3
> 1200000 5675617
> v851s:~#
>
> >> + },
> >> +};
> >> +
> >> +/* Some PLLs are input * N / div1 / P. Model them as NKMP with no K */
> >> +#define SUN8I_V853_PLL_DDR_REG 0x010
> >> +static struct ccu_nkmp pll_ddr_clk = {
> >> + .enable = BIT(27) | BIT(30) | BIT(31),
> >
> > same here, only bit 27 please.
> >
> >> + .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_PARENTS_DATA("pll-ddr", osc24M,
> >> + &ccu_nkmp_ops,
> >> + CLK_SET_RATE_UNGATE),
> >
> > CLK_SET_RATE_GATE, as above.
> >
> >> + },
> >> +};
> >> +
> >> +#define SUN8I_V853_PLL_PERIPH_REG 0x020
> >> +static struct ccu_nm pll_periph_4x_clk = {
> >> + .enable = BIT(27) | BIT(30) | BIT(31),
> >
> > BIT(27), as above, and further down as well
> >
> >> + .lock = BIT(28),
> >> + .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
> >> + .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
> >> + .common = {
> >> + .reg = 0x020,
> >> + .hw.init = CLK_HW_INIT_PARENTS_DATA("pll-periph-4x", osc24M,
> >> + &ccu_nm_ops,
> >> + CLK_SET_RATE_UNGATE),
> >
> > you guessed it: CLK_SET_RATE_GATE, here and further below, please
> >
> >> + },
> >> +};
> >> +
> >> +static SUNXI_CCU_M(pll_periph_2x_clk, "pll-periph-2x", "pll-periph-4x",
> >> + 0x020, 16, 3, 0);
> >
> > So is there a recommendation about how we reference other clocks? This
> > one here is using the clock name, which requires a look-up, where we
> > could use the pointer directly as well, as done down below.
> >
> > static const struct clk_hw *pll_periph0_4x_hws[] = {
> > &pll_periph0_4x_clk.common.hw
> > };
> > static SUNXI_CCU_M_HWS(pll_periph0_2x_clk, "pll-periph0-2x",
> > pll_periph0_4x_hws, 0x020, 16, 3, 0);
> >
> > I have seen both, sun20i-d1 for instance uses this, and I copied from
> > there for the A523 clock code.
> >
> > Would be glad to hear some maintainer's opinion.
> >
> >> +
> >> +static SUNXI_CCU_M(pll_periph_800M_clk, "pll-periph-800M", "pll-periph-4x",
> >> + 0x020, 20, 3, 0);
> >> +
> >> +static SUNXI_CCU_M(pll_periph_480M_clk, "pll-periph-480M", "pll-periph-4x",
> >> + 0x020, 2, 3, 0);
> >> +
> >> +static CLK_FIXED_FACTOR_HW(pll_periph_600M_clk, "pll-periph-600M",
> >> + &pll_periph_2x_clk.common.hw, 2, 1, 0);
> >> +
> >> +static CLK_FIXED_FACTOR_HW(pll_periph_400M_clk, "pll-periph-400M",
> >> + &pll_periph_2x_clk.common.hw, 3, 1, 0);
> >> +
> >> +static CLK_FIXED_FACTOR_HW(pll_periph_300M_clk, "pll-periph-300M",
> >> + &pll_periph_600M_clk.hw, 2, 1, 0);
> >> +
> >> +static CLK_FIXED_FACTOR_HW(pll_periph_200M_clk, "pll-periph-200M",
> >> + &pll_periph_400M_clk.hw, 2, 1, 0);
> >> +
> >> +static CLK_FIXED_FACTOR_HW(pll_periph_160M_clk, "pll-periph-160M",
> >> + &pll_periph_480M_clk.common.hw, 3, 1, 0);
> >> +
> >> +static CLK_FIXED_FACTOR_HW(pll_periph_150M_clk, "pll-periph-150M",
> >> + &pll_periph_300M_clk.hw, 2, 1, 0);
> >> +
> >> +
> >> +/*
> >> + * For Video PLLs, the output divider is described as "only for testing"
> >> + * in the user manual. So it's not modelled and forced to 0.
> >
> > That's a bit confusing: the manual says that the default value for bit 0
> > is 0x1, and that it's "only for testing", which would mean we should
> > leave it like this, always dividing by 2? In the main description (bit
> > 31) it says:
> > VIDEOPLL4X = InputFreq*N/M
> > but below (bit 0) it's
> > VIDEOPLL4X = 24MHz*N/M/D
> > (with D being "PLL_OUTPUT_DIV_D + 1", so 2 in our case)
> >
> > Do you have any indication how fast the video PLL really is? If it is
> > divided by 2 (as we force that bit to 1 down in the probe routine), then
> > we would need to model this with that CCU_FEATURE_FIXED_POSTDIV flag,
> > and either leave that bit alone or force it to 1 instead.
> > Also would be good to see what the BSP does.
> >
>
> The [2] BSP driver model it as a ccu_nkmp type, so i’ll double check it.
>
> >> + */
> >> +#define SUN8I_V853_PLL_VIDEO_REG 0x040
> >> +static struct ccu_nm pll_video_4x_clk = {
> >> + .enable = BIT(27) | BIT(30) | BIT(31),
> >> + .lock = BIT(28),
> >> + .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
> >
> > The manual says 11 (but again doesn't matter).
> >
> >> + .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
> >> + .common = {
> >> + .reg = 0x040,
> >> + .hw.init = CLK_HW_INIT_PARENTS_DATA("pll-video-4x", osc24M,
> >> + &ccu_nm_ops,
> >> + CLK_SET_RATE_UNGATE),
> >> + },
> >> +};
> >> +
> >> +static const struct clk_hw *pll_video_4x_hws[] = {
> >> + &pll_video_4x_clk.common.hw
> >> +};
> >> +static CLK_FIXED_FACTOR_HWS(pll_video_2x_clk, "pll-video-2x",
> >> + pll_video_4x_hws, 2, 1, CLK_SET_RATE_PARENT);
> >> +static CLK_FIXED_FACTOR_HWS(pll_video_1x_clk, "pll-video-1x",
> >> + pll_video_4x_hws, 4, 1, CLK_SET_RATE_PARENT);
> >
> > Ah, here you are using the pointer reference to the base clock, not the
> > string, as above. I think we should stick to one method?
>
> Ok.
>
> >
> >> +/*
> >> + * For CSI PLLs, the output divider is described as "only for testing"
> >> + * in the user manual. So it's not modelled and forced to 0.
> >
> > Same situation as for the video PLL: what is the recommended setting of
> > bit 0, really?
> >
>
> Same as with the PLL_VIDEO. I’ll check it again, and modify both.
>
> >> + */
> >> +#define SUN8I_V853_PLL_CSI_REG 0x048
> >> +static struct ccu_nm pll_csi_4x_clk = {
> >> + .enable = BIT(27) | BIT(30) | BIT(31),
> >> + .lock = BIT(28),
> >> + .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
> >> + .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
> >> + .common = {
> >> + .reg = 0x048,
> >> + .hw.init = CLK_HW_INIT_PARENTS_DATA("pll-csi-4x", osc24M,
> >> + &ccu_nm_ops,
> >> + CLK_SET_RATE_UNGATE),
> >> + },
> >> +};
> >> +
> >> +static CLK_FIXED_FACTOR_HW(pll_csi_clk, "pll-csi",
> >> + &pll_csi_4x_clk.common.hw, 4, 1, CLK_SET_RATE_PARENT);
> >> +
> >> +
> >> +#define SUN8I_V853_PLL_AUDIO_REG 0x78
> >> +static struct ccu_sdm_setting pll_audio_div5_sdm_table[] = {
> >> + { .rate = 196608000, .pattern = 0xc001eb85, .m = 5, .n = 40 }, /* 24.576 */
> >> + { .rate = 67737600, .pattern = 0xc001288d, .m = 8, .n = 22 }, /* 22.5792 */
> >> +};
> >> +
> >> +static struct ccu_nm pll_audio_div5_clk = {
> >> + .enable = BIT(27) | BIT(30) | BIT(31),
> >> + .lock = BIT(28),
> >> + .n = _SUNXI_CCU_MULT(8, 8),
> >> + .m = _SUNXI_CCU_DIV(20, 3),
> >> + .sdm = _SUNXI_CCU_SDM(pll_audio_div5_sdm_table,
> >> + BIT(24), 0x0178, BIT(31)),
> >> + .common = {
> >> + .reg = 0x0078,
> >> + .features = CCU_FEATURE_SIGMA_DELTA_MOD,
> >> + .hw.init = CLK_HW_INIT_PARENTS_DATA("pll-audio-div5", osc24M,
> >> + &ccu_nm_ops,
> >> + CLK_SET_RATE_UNGATE),
> >> + },
> >> +};
> >> +static SUNXI_CCU_M(pll_audio_1x_clk, "pll-audio-1x", "pll-audio-div5",
> >> + 0xe00, 0, 5, CLK_SET_RATE_PARENT);
> >> +
> >> +/* pll-audio-div2 and pll-aduio-4x not used, because audio-1x can cover 22.5792M and 24.576M */
> >> +static SUNXI_CCU_M(pll_audio_div2_clk, "pll-audio-div2", "pll-audio",
> >> + 0x078, 16, 3, 0);
> >> +static SUNXI_CCU_M(pll_audio_4x_clk, "pll-audio-4x", "pll-audio-div2",
> >> + 0xe00, 5, 5, 0);
> >> +
> >> +/*
> >> + * For the NPU PLL, the output divider is described as "only for testing"
> >> + * in the user manual. So it's not modelled and forced to 0.
> >> + */
> >> +#define SUN8I_V853_PLL_NPU_REG 0x080
> >> +static struct ccu_nm pll_npu_4x_clk = {
> >> + .enable = BIT(27) | BIT(30) | BIT(31),
> >> + .lock = BIT(28),
> >> + .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
> >> + .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
> >> + .common = {
> >> + .reg = 0x080,
> >> + .hw.init = CLK_HW_INIT_PARENTS_DATA("pll-npu-4x", osc24M,
> >> + &ccu_nm_ops,
> >> + CLK_SET_RATE_UNGATE),
> >> + },
> >> +};
> >> +
> >> +/*
> >> + * The CPU gate is not modelled - it is in a separate register (0x504)
> >> + * and has a special key field. The clock does not need to be ungated anyway.
> >
> > I would believe it should read: "The clock must not be gated anyway by
> > the kernel". (As it would stop execution on the Arm cores, so it's only
> > something for the management core).
> >
>
> ok.
>
> >> + */
> >> +static const struct clk_parent_data cpu_parents[] = {
> >> + { .fw_name = "hosc" },
> >> + { .fw_name = "losc" },
> >> + { .fw_name = "iosc" },
> >> + { .hw = &pll_cpu_clk.common.hw },
> >
> > The manual says there is a divider (PLL_CPU_OUT_EXT_DIVP[17:16]),
> > though the description suggests it should stay as 0. I guess this is
> > the intention here, but can you please add comment here?
> >
>
> ok.
>
> >> + { .hw = &pll_periph_600M_clk.hw },
> >> + { .hw = &pll_periph_800M_clk.common.hw },
> >> +};
> >> +
> >> +static SUNXI_CCU_MUX_DATA(cpu_clk, "cpu", cpu_parents,
> >> + 0x500, 24, 3, CLK_SET_RATE_PARENT | CLK_IS_CRITICAL);
> >> +
> >> +static SUNXI_CCU_M(cpu_axi_clk, "cpu-axi", "cpu",
> >
> > I wonder if it's more efficient to use a pointer to the CPU clock, and
> > not a string?
> >
>
> I’ll fix that.
>
> >> + 0x500, 0, 2, 0);
> >> +static SUNXI_CCU_M(cpu_apb_clk, "cpu-apb", "cpu",
> >> + 0x500, 8, 2, 0);
> >> +
> >> +static const struct clk_parent_data ahb_parents[] = {
> >> + { .fw_name = "hosc" },
> >> + { .fw_name = "losc" },
> >> + { .fw_name = "iosc" },
> >> + { .hw = &pll_periph_600M_clk.hw },
> >> +};
> >> +static SUNXI_CCU_MP_DATA_WITH_MUX(ahb_clk, "ahb", ahb_parents, 0x510,
> >> + 0, 5, /* M */
> >> + 8, 2, /* P */
> >> + 24, 2, /* mux */
> >> + 0);
> >> +
> >> +static SUNXI_CCU_MP_DATA_WITH_MUX(apb0_clk, "apb0", ahb_parents, 0x520,
> >> + 0, 5, /* M */
> >> + 8, 2, /* P */
> >> + 24, 2, /* mux */
> >> + 0);
> >> +
> >> +static SUNXI_CCU_MP_DATA_WITH_MUX(apb1_clk, "apb1", ahb_parents, 0x524,
> >> + 0, 5, /* M */
> >> + 8, 2, /* P */
> >> + 24, 2, /* mux */
> >> + 0);
> >> +
> >> +static const struct clk_hw *ahb_hws[] = { &ahb_clk.common.hw };
> >> +static const struct clk_hw *apb0_hws[] = { &apb0_clk.common.hw };
> >> +static const struct clk_hw *apb1_hws[] = { &apb1_clk.common.hw };
> >> +
> >> +
> >> +
> >> +static const struct clk_hw *de_g2d_parents[] = {
> >> + &pll_periph_300M_clk.hw,
> >> + &pll_video_1x_clk.hw,
> >> +};
> >> +static SUNXI_CCU_M_HW_WITH_MUX_GATE(de_clk, "de", de_g2d_parents, 0x600,
> >> + 0, 5, /* M */
> >> + 24, 1, /* mux */
> >> + BIT(31), /* gate */
> >> + CLK_SET_RATE_PARENT);
> >> +
> >> +static SUNXI_CCU_GATE_HWS(bus_de_clk, "bus-de", ahb_hws,
> >> + 0x60c, BIT(0), 0);
> >> +
> >> +static SUNXI_CCU_M_HW_WITH_MUX_GATE(g2d_clk, "g2d", de_g2d_parents, 0x630,
> >> + 0, 5, /* M */
> >> + 24, 1, /* mux */
> >> + BIT(31), /* gate */
> >> + CLK_SET_RATE_PARENT);
> >> +
> >> +static SUNXI_CCU_GATE_HWS(bus_g2d_clk, "bus-g2d", ahb_hws,
> >> + 0x63c, BIT(0), 0);
> >> +
> >> +
> >> +static const struct clk_parent_data ce_parents[] = {
> >> + { .fw_name = "hosc" },
> >
> > That parent is not mentioned in the manual, though it looks like an
> > omission. Did you find the HOSC mentioned somewhere else?
>
> The [2] BSP driver declares the CE parents in the same way.
>
> >
> >> + { .hw = &pll_periph_400M_clk.hw, },
> >> + { .hw = &pll_periph_300M_clk.hw, }
> >> +};
> >> +static SUNXI_CCU_M_DATA_WITH_MUX_GATE(ce_clk, "ce", ce_parents, 0x680,
> >> + 0, 4, /* M */
> >
> > looks like the indentation here is a bit off, can you check this? And
> > for the other clocks as well?
> >
>
> Sure.
>
> >> + 24, 3, /* mux */
> >> + BIT(31), /* gate */
> >> + CLK_SET_RATE_PARENT);
> >> +
> >> +static SUNXI_CCU_GATE_HWS(bus_ce_clk, "bus-ce", ahb_hws,
> >> + 0x68c, BIT(0) | BIT(1), 0);
> >
> >
> > (reviewed till here, for now, to keep my sanity. Skipping down to
> > below, where there are more low-hanging fruits and bits that can be
> > checked more systematically)
> >
> >> +
> >> +static const struct clk_hw *ve_parents[] = {
> >> + &pll_periph_300M_clk.hw,
> >> + &pll_periph_400M_clk.hw,
> >> + &pll_periph_480M_clk.common.hw,
> >> + &pll_npu_4x_clk.common.hw,
> >> + &pll_video_4x_clk.common.hw,
> >> + &pll_csi_4x_clk.common.hw,
> >> +};
> >> +static SUNXI_CCU_M_HW_WITH_MUX_GATE(ve_clk, "ve", ve_parents, 0x690,
> >> + 0, 5, /* M */
> >> + 24, 3, /* mux */
> >> + BIT(31), /* gate */
> >> + CLK_SET_RATE_PARENT);
> >> +
> >> +static SUNXI_CCU_GATE_HWS(bus_ve_clk, "bus-ve", ahb_hws,
> >> + 0x69c, BIT(0), 0);
> >> +
> >> +
> >> +static const struct clk_hw *npu_parents[] = {
> >> + &pll_periph_480M_clk.common.hw,
> >> + &pll_periph_600M_clk.hw,
> >> + &pll_periph_800M_clk.common.hw,
> >> + &pll_npu_4x_clk.common.hw,
> >> +};
> >> +static SUNXI_CCU_M_HW_WITH_MUX_GATE(npu_clk, "npu", npu_parents, 0x6e0,
> >> + 0, 5, /* M */
> >> + 24, 3, /* mux */
> >> + BIT(31), /* gate */
> >> + 0);
> >> +
> >> +static SUNXI_CCU_GATE_HWS(bus_npu_clk, "bus-npu", ahb_hws,
> >> + 0x6ec, BIT(0), 0);
> >> +
> >> +static SUNXI_CCU_GATE_HWS(bus_dma_clk, "bus-dma", ahb_hws,
> >> + 0x70c, BIT(0), 0);
> >> +
> >> +static SUNXI_CCU_GATE_HWS(bus_msgbox0_clk, "bus-msgbox0", ahb_hws,
> >> + 0x71c, BIT(0), 0);
> >> +static SUNXI_CCU_GATE_HWS(bus_msgbox1_clk, "bus-msgbox1", ahb_hws,
> >> + 0x71c, BIT(1), 0);
> >> +
> >> +static SUNXI_CCU_GATE_HWS(bus_spinlock_clk, "bus-spinlock", ahb_hws,
> >> + 0x72c, BIT(0), 0);
> >> +
> >> +static SUNXI_CCU_GATE_HWS(bus_hstimer_clk, "bus-hstimer", ahb_hws,
> >> + 0x73c, BIT(0), 0);
> >> +
> >> +static SUNXI_CCU_GATE_DATA(avs_clk, "avs", osc24M,
> >> + 0x740, BIT(31), 0);
> >> +
> >> +static SUNXI_CCU_GATE_HWS(bus_dbg_clk, "bus-dbg", ahb_hws,
> >> + 0x78c, BIT(0), 0);
> >> +
> >> +static SUNXI_CCU_GATE_HWS(bus_pwm_clk, "bus-pwm", apb0_hws,
> >> + 0x7ac, BIT(0), 0);
> >> +
> >> +static SUNXI_CCU_GATE_HWS(bus_iommu_clk, "bus-iommu", ahb_hws,
> >> + 0x7bc, BIT(0), 0);
> >> +
> >> +static const struct clk_hw *dram_parents[] = {
> >> + &pll_ddr_clk.common.hw,
> >> + &pll_periph_2x_clk.common.hw,
> >> + &pll_periph_800M_clk.common.hw,
> >> +};
> >> +static SUNXI_CCU_MP_HW_WITH_MUX_GATE(dram_clk, "dram", dram_parents, 0x800,
> >> + 0, 5, /* M */
> >> + 8, 2, /* P */
> >> + 24, 3, /* mux */
> >> + BIT(31), CLK_IS_CRITICAL);
> >> +
> >> +static CLK_FIXED_FACTOR_HW(mbus_clk, "mbus",
> >> + &dram_clk.common.hw, 4, 1, 0);
> >> +
> >> +static const struct clk_hw *mbus_hws[] = { &mbus_clk.hw };
> >> +
> >> +static SUNXI_CCU_GATE_HWS(mbus_dma_clk, "mbus-dma", mbus_hws,
> >> + 0x804, BIT(0), 0);
> >> +static SUNXI_CCU_GATE_HWS(mbus_ve_clk, "mbus-ve", mbus_hws,
> >> + 0x804, BIT(1), 0);
> >> +static SUNXI_CCU_GATE_HWS(mbus_ce_clk, "mbus-ce", mbus_hws,
> >> + 0x804, BIT(2), 0);
> >> +static SUNXI_CCU_GATE_HWS(mbus_csi_clk, "mbus-csi", mbus_hws,
> >> + 0x804, BIT(8), 0);
> >> +static SUNXI_CCU_GATE_HWS(mbus_isp_clk, "mbus-isp", mbus_hws,
> >> + 0x804, BIT(9), 0);
> >> +static SUNXI_CCU_GATE_HWS(mbus_g2d_clk, "mbus-g2d", mbus_hws,
> >> + 0x804, BIT(10), 0);
> >> +
> >> +static SUNXI_CCU_GATE_HWS(bus_dram_clk, "bus-dram", ahb_hws,
> >> + 0x80c, BIT(0), CLK_IS_CRITICAL);
> >> +
> >> +
> >> +static const struct clk_parent_data mmc0_mmc1_parents[] = {
> >> + { .fw_name = "hosc" },
> >> + { .hw = &pll_periph_400M_clk.hw, },
> >> + { .hw = &pll_periph_300M_clk.hw, },
> >> +};
> >> +static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(mmc0_clk, "mmc0", mmc0_mmc1_parents, 0x830,
> >> + 0, 4, /* M */
> >> + 8, 2, /* P */
> >> + 24, 3, /* mux */
> >> + BIT(31), /* gate */
> >> + 0);
> >> +
> >> +static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(mmc1_clk, "mmc1", mmc0_mmc1_parents, 0x834,
> >> + 0, 4, /* M */
> >> + 8, 2, /* P */
> >> + 24, 3, /* mux */
> >> + BIT(31), /* gate */
> >> + 0);
> >> +
> >> +static const struct clk_parent_data mmc2_parents[] = {
> >> + { .fw_name = "hosc" },
> >> + { .hw = &pll_periph_600M_clk.hw, },
> >> + { .hw = &pll_periph_400M_clk.hw, },
> >> +};
> >> +static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(mmc2_clk, "mmc2", mmc2_parents, 0x838,
> >> + 0, 4, /* M */
> >> + 8, 2, /* P */
> >> + 24, 3, /* mux */
> >> + BIT(31), /* gate */
> >> + 0);
> >> +
> >> +static SUNXI_CCU_GATE_HWS(bus_mmc0_clk, "bus-mmc0", ahb_hws,
> >> + 0x84c, BIT(0), 0);
> >> +static SUNXI_CCU_GATE_HWS(bus_mmc1_clk, "bus-mmc1", ahb_hws,
> >> + 0x84c, BIT(1), 0);
> >> +static SUNXI_CCU_GATE_HWS(bus_mmc2_clk, "bus-mmc2", ahb_hws,
> >> + 0x84c, BIT(2), 0);
> >> +
> >> +static SUNXI_CCU_GATE_HWS(bus_uart0_clk, "bus-uart0", apb1_hws,
> >> + 0x90c, BIT(0), 0);
> >> +static SUNXI_CCU_GATE_HWS(bus_uart1_clk, "bus-uart1", apb1_hws,
> >> + 0x90c, BIT(1), 0);
> >> +static SUNXI_CCU_GATE_HWS(bus_uart2_clk, "bus-uart2", apb1_hws,
> >> + 0x90c, BIT(2), 0);
> >> +static SUNXI_CCU_GATE_HWS(bus_uart3_clk, "bus-uart3", apb1_hws,
> >> + 0x90c, BIT(3), 0);
> >> +
> >> +static SUNXI_CCU_GATE_HWS(bus_i2c0_clk, "bus-i2c0", apb1_hws,
> >> + 0x91c, BIT(0), 0);
> >> +static SUNXI_CCU_GATE_HWS(bus_i2c1_clk, "bus-i2c1", apb1_hws,
> >> + 0x91c, BIT(1), 0);
> >> +static SUNXI_CCU_GATE_HWS(bus_i2c2_clk, "bus-i2c2", apb1_hws,
> >> + 0x91c, BIT(2), 0);
> >> +static SUNXI_CCU_GATE_HWS(bus_i2c3_clk, "bus-i2c3", apb1_hws,
> >> + 0x91c, BIT(3), 0);
> >> +static SUNXI_CCU_GATE_HWS(bus_i2c4_clk, "bus-i2c4", apb1_hws,
> >> + 0x91c, BIT(4), 0);
> >> +
> >> +static const struct clk_parent_data spi_parents[] = {
> >> + { .fw_name = "hosc" },
> >> + { .hw = &pll_periph_300M_clk.hw, },
> >> + { .hw = &pll_periph_200M_clk.hw, },
> >> +};
> >> +
> >> +static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(spi0_clk, "spi0", spi_parents, 0x940,
> >> + 0, 4, /* M */
> >> + 8, 2, /* P */
> >> + 24, 3, /* mux */
> >> + BIT(31), /* gate */
> >> + 0);
> >> +
> >> +static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(spi1_clk, "spi1", spi_parents, 0x944,
> >> + 0, 4, /* M */
> >> + 8, 2, /* P */
> >> + 24, 3, /* mux */
> >> + BIT(31), /* gate */
> >> + 0);
> >> +
> >> +static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(spi2_clk, "spi2", spi_parents, 0x948,
> >> + 0, 4, /* M */
> >> + 8, 2, /* P */
> >> + 24, 3, /* mux */
> >> + BIT(31), /* gate */
> >> + 0);
> >> +
> >> +static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(spi3_clk, "spi3", spi_parents, 0x94c,
> >> + 0, 4, /* M */
> >> + 8, 2, /* P */
> >> + 24, 3, /* mux */
> >> + BIT(31), /* gate */
> >> + 0);
> >> +
> >> +static SUNXI_CCU_GATE_HWS(bus_spi0_clk, "bus-spi0", ahb_hws,
> >> + 0x96c, BIT(0), 0);
> >> +static SUNXI_CCU_GATE_HWS(bus_spi1_clk, "bus-spi1", ahb_hws,
> >> + 0x96c, BIT(1), 0);
> >> +static SUNXI_CCU_GATE_HWS(bus_spi2_clk, "bus-spi2", ahb_hws,
> >> + 0x96c, BIT(2), 0);
> >> +static SUNXI_CCU_GATE_HWS(bus_spi3_clk, "bus-spi3", ahb_hws,
> >> + 0x96c, BIT(3), 0);
> >> +
> >> +
> >> +static const struct clk_parent_data spif_parents[] = {
> >> + { .fw_name = "hosc" },
> >> + { .hw = &pll_periph_400M_clk.hw, },
> >> + { .hw = &pll_periph_300M_clk.hw, },
> >> +};
> >> +
> >> +static SUNXI_CCU_M_DATA_WITH_MUX_GATE(spif_clk, "spif", spif_parents, 0x0950,
> >> + 0, 4, /* M */
> >> + 24, 3, /* mux */
> >> + BIT(31), /* gate */
> >> + CLK_SET_RATE_PARENT);
> >> +
> >> +static SUNXI_CCU_GATE_HWS(bus_spif_clk, "bus-spif", ahb_hws,
> >> + 0x096c, BIT(4), 0);
> >> +
> >> +
> >> +static const struct clk_hw *pll_periph_150M_hws[] = { &pll_periph_150M_clk.hw };
> >> +static SUNXI_CCU_GATE_HWS_WITH_PREDIV(emac_25M_clk, "emac-25M", pll_periph_150M_hws,
> >> + 0x970, BIT(31) | BIT(30), 6, 0);
> >> +
> >> +static SUNXI_CCU_GATE_HWS(bus_emac_clk, "bus-emac", ahb_hws,
> >> + 0x97c, BIT(0), 0);
> >> +
> >> +static SUNXI_CCU_GATE_HWS(bus_gpadc_clk, "bus-gpadc", apb0_hws,
> >> + 0x9ec, BIT(0), 0);
> >> +
> >> +static SUNXI_CCU_GATE_HWS(bus_ths_clk, "bus-ths", ahb_hws,
> >> + 0x9fc, BIT(0), 0);
> >> +
> >> +
> >> +static const struct clk_hw *audio_parents[] = {
> >> + &pll_audio_1x_clk.common.hw,
> >> + &pll_audio_4x_clk.common.hw,
> >> +};
> >> +
> >> +static SUNXI_CCU_M_HW_WITH_MUX_GATE(i2s0_clk, "i2s0", audio_parents, 0xa10,
> >> + 0, 4, /* M */
> >> + 24, 1, /* mux */
> >> + BIT(31), /* gate */
> >> + CLK_SET_RATE_PARENT);
> >> +
> >> +static SUNXI_CCU_M_HW_WITH_MUX_GATE(i2s1_clk, "i2s1", audio_parents, 0xa14,
> >> + 0, 4, /* M */
> >> + 24, 1, /* mux */
> >> + BIT(31), /* gate */
> >> + CLK_SET_RATE_PARENT);
> >> +
> >> +static SUNXI_CCU_GATE_HWS(bus_i2s1_clk, "bus-i2s1", ahb_hws,
> >> + 0xa20, BIT(1), 0);
> >> +
> >
> > Just a nit, but those two here v and ^ seem to be swapped.
> >
>
> Thanks.
>
> > For the records: I extracted the bus gates and massaged them with some
> > regexps to bring them into a shape where review is more feasible.
> > They look alright to me. I didn't look at the respective mod clocks in
> > detail, though.
> >
> >
> >> +static SUNXI_CCU_GATE_HWS(bus_i2s0_clk, "bus-i2s0", ahb_hws,
> >> + 0xa20, BIT(0), 0);
> >> +
> >> +static SUNXI_CCU_M_HW_WITH_MUX_GATE(dmic_clk, "dmic", audio_parents, 0xa40,
> >> + 0, 4, /* M */
> >> + 24, 1, /* mux */
> >> + BIT(31), /* gate */
> >> + CLK_SET_RATE_PARENT);
> >> +
> >> +static SUNXI_CCU_GATE_HWS(bus_dmic_clk, "bus-dmic", ahb_hws,
> >> + 0xa4c, BIT(0), 0);
> >> +
> >> +static SUNXI_CCU_M_HW_WITH_MUX_GATE(audio_codec_dac_clk, "audio-codec-dac", audio_parents, 0xa50,
> >
> > I think you should break the line above, to stay within the 80 char
> > limit.
> >
>
> Ok.
>
> > Fast forwarding to the ccu_resets array ...
> >
> >> + 0, 4, /* M */
> >> + 24, 1, /* mux */
> >> + BIT(31), /* gate */
> >> + CLK_SET_RATE_PARENT);
> >> +
> >> +static SUNXI_CCU_M_HW_WITH_MUX_GATE(audio_codec_adc_clk, "audio-codec-adc", audio_parents, 0xa54,
> >> + 0, 4, /* M */
> >> + 24, 1, /* mux */
> >> + BIT(31), /* gate */
> >> + CLK_SET_RATE_PARENT);
> >> +
> >> +static SUNXI_CCU_GATE_HWS(bus_audio_codec_clk, "bus-audio-codec", apb0_hws,
> >> + 0xa5c, BIT(0), 0);
> >> +
> >> +/*
> >> + * There are OHCI 12M clock source selection bits for the USB 2.0 port.
> >> + * We will force them to 0 (12M divided from 48M).
> >> + */
> >> +static CLK_FIXED_FACTOR_FW_NAME(osc12M_clk, "osc12M", "hosc", 2, 1, 0);
> >> +
> >> +#define SUN8I_V853_USB_CLK_REG 0xa70
> >> +
> >> +static SUNXI_CCU_GATE(usb_ohci_clk, "usb", "osc12M", 0x0a70, BIT(31), 0);
> >> +
> >> +static SUNXI_CCU_GATE_HWS(bus_ohci_clk, "bus-ohci", ahb_hws, 0xa8c, BIT(0), 0);
> >> +static SUNXI_CCU_GATE_HWS(bus_ehci_clk, "bus-ehci", ahb_hws, 0xa8c, BIT(4), 0);
> >> +static SUNXI_CCU_GATE_HWS(bus_otg_clk, "bus-otg", ahb_hws, 0xa8c, BIT(8), 0);
> >> +
> >> +static SUNXI_CCU_GATE_HWS(bus_dpss_top_clk, "bus-dpss-top", ahb_hws,
> >> + 0xabc, BIT(0), 0);
> >> +
> >> +
> >> +static const struct clk_parent_data mipi_dsi_parents[] = {
> >> + { .fw_name = "hosc" },
> >> + { .hw = &pll_periph_200M_clk.hw },
> >> + { .hw = &pll_periph_150M_clk.hw },
> >> +};
> >> +static SUNXI_CCU_M_DATA_WITH_MUX_GATE(mipi_dsi_clk, "mipi-dsi", mipi_dsi_parents, 0xb24,
> >> + 0, 4, /* M */
> >> + 24, 3, /* mux */
> >> + BIT(31), /* gate */
> >> + CLK_SET_RATE_PARENT);
> >> +
> >> +static SUNXI_CCU_GATE_HWS(bus_mipi_dsi_clk, "bus-mipi-dsi", ahb_hws,
> >> + 0xb4c, BIT(0), 0);
> >> +
> >> +
> >> +static const struct clk_hw *tcon_lcd_parents[] = {
> >> + &pll_video_4x_clk.common.hw,
> >> + &pll_periph_2x_clk.common.hw,
> >> + &pll_csi_4x_clk.common.hw,
> >> +};
> >> +static SUNXI_CCU_MP_HW_WITH_MUX_GATE(tcon_lcd_clk, "tcon-lcd", tcon_lcd_parents, 0xb60,
> >> + 0, 4, /* M */
> >> + 8, 2, /* P */
> >> + 24, 3, /* mux */
> >> + BIT(31), /* gate */
> >> + CLK_SET_RATE_PARENT);
> >> +
> >> +static SUNXI_CCU_GATE_HWS(bus_tcon_lcd_clk, "bus-tcon-lcd", ahb_hws,
> >> + 0xb7c, BIT(0), 0);
> >> +
> >> +
> >> +static const struct clk_hw *csi_top_parents[] = {
> >> + &pll_periph_300M_clk.hw,
> >> + &pll_periph_400M_clk.hw,
> >> + &pll_video_4x_clk.common.hw,
> >> + &pll_csi_4x_clk.common.hw,
> >> +};
> >> +static SUNXI_CCU_M_HW_WITH_MUX_GATE(csi_top_clk, "csi-top", csi_top_parents, 0xc04,
> >> + 0, 5, /* M */
> >> + 24, 3, /* mux */
> >> + BIT(31), /* gate */
> >> + 0);
> >> +
> >> +
> >> +static const struct clk_parent_data csi_mclk_parents[] = {
> >> + { .fw_name = "hosc" },
> >> + { .hw = &pll_csi_4x_clk.common.hw },
> >> + { .hw = &pll_video_4x_clk.common.hw },
> >> + { .hw = &pll_periph_2x_clk.common.hw },
> >> +};
> >> +static SUNXI_CCU_M_DATA_WITH_MUX_GATE(csi_mclk0_clk, "csi-mclk0", csi_mclk_parents, 0xc08,
> >> + 0, 5, /* M */
> >> + 24, 3, /* mux */
> >> + BIT(31), /* gate */
> >> + 0);
> >> +
> >> +static SUNXI_CCU_M_DATA_WITH_MUX_GATE(csi_mclk1_clk, "csi-mclk1", csi_mclk_parents, 0xc0c,
> >> + 0, 5, /* M */
> >> + 24, 3, /* mux */
> >> + BIT(31), /* gate */
> >> + 0);
> >> +
> >> +static SUNXI_CCU_M_DATA_WITH_MUX_GATE(csi_mclk2_clk, "csi-mclk2", csi_mclk_parents, 0xc10,
> >> + 0, 5, /* M */
> >> + 24, 3, /* mux */
> >> + BIT(31), /* gate */
> >> + 0);
> >> +
> >> +static SUNXI_CCU_GATE_HWS(bus_csi_clk, "bus-csi", ahb_hws,
> >> + 0xc2c, BIT(0), 0);
> >> +
> >> +
> >> +static SUNXI_CCU_GATE_HWS(bus_wiegand_clk, "bus-wiegand", ahb_hws,
> >> + 0xc7c, BIT(0), 0);
> >> +
> >> +
> >> +static const struct clk_parent_data riscv_parents[] = {
> >> + { .fw_name = "hosc" },
> >> + { .fw_name = "losc" },
> >> + { .fw_name = "iosc" },
> >> + { .hw = &pll_periph_600M_clk.hw },
> >> + { .hw = &pll_periph_480M_clk.common.hw },
> >> + { .hw = &pll_cpu_clk.common.hw },
> >> +};
> >> +static SUNXI_CCU_M_DATA_WITH_MUX(riscv_clk, "riscv-cpu", riscv_parents, 0xd00,
> >> + 0, 5, /* M */
> >> + 24, 3, /* mux */
> >> + CLK_SET_RATE_PARENT);
> >> +
> >> +/* The riscv-axi clk must be divided by at least 2. */
> >> +static struct clk_div_table riscv_axi_table[] = {
> >> + { .val = 1, .div = 2 },
> >> + { .val = 2, .div = 3 },
> >> + { .val = 3, .div = 4 },
> >> + { /* Sentinel */ }
> >> +};
> >> +static SUNXI_CCU_DIV_TABLE_HW(riscv_axi_clk, "riscv-axi", &riscv_clk.common.hw,
> >> + 0xd00, 8, 2, riscv_axi_table, 0);
> >> +
> >> +
> >> +static SUNXI_CCU_GATE_HWS(riscv_cfg, "riscv-cfg", ahb_hws,
> >> + 0xd0c, BIT(0), 0);
> >> +
> >> +static const struct clk_hw *pll_periph_160M_hws[] = {
> >> + &pll_periph_160M_clk.hw,
> >> +};
> >> +
> >> +static SUNXI_CCU_GATE_DATA(fanout_24M_clk, "fanout-24M", osc24M,
> >> + 0xf30, BIT(0), 0);
> >> +static SUNXI_CCU_GATE_DATA_WITH_PREDIV(fanout_12M_clk, "fanout-12M", osc24M,
> >> + 0xf30, BIT(1), 2, 0);
> >> +static SUNXI_CCU_GATE_HWS_WITH_PREDIV(fanout_16M_clk, "fanout-16M", pll_periph_160M_hws,
> >> + 0xf30, BIT(2), 10, 0);
> >> +static SUNXI_CCU_GATE_HWS_WITH_PREDIV(fanout_25M_clk, "fanout-25M", pll_periph_150M_hws,
> >> + 0xf30, BIT(3), 6, 0);
> >> +
> >> +
> >> +
> >> +/* This clock has a second divider that is not modelled and forced to 0. */
> >> +#define SUN8I_V853_FANOUT_27M_REG 0xf34
> >> +static const struct clk_hw *fanout_27M_parents[] = {
> >> + &pll_video_1x_clk.hw,
> >> + &pll_csi_clk.hw,
> >> + &pll_periph_300M_clk.hw,
> >> +};
> >> +static SUNXI_CCU_M_HW_WITH_MUX_GATE(fanout_27M_clk, "fanout-27M", fanout_27M_parents, 0xf34,
> >> + 0, 5, /* M */
> >> + 24, 2, /* mux */
> >> + BIT(31), /* gate */
> >> + 0);
> >> +static SUNXI_CCU_M_HWS_WITH_GATE(fanout_pclk_clk, "fanout-pclk", apb0_hws, 0xf38,
> >> + 0, 5, /* M */
> >> + BIT(31), /* gate */
> >> + 0);
> >> +
> >> +static const struct clk_parent_data fanout_parents[] = {
> >> + { .fw_name = "losc" },
> >> + { .hw = &fanout_12M_clk.common.hw },
> >> + { .hw = &fanout_16M_clk.common.hw },
> >> + { .hw = &fanout_24M_clk.common.hw },
> >> + { .hw = &fanout_25M_clk.common.hw },
> >> + { .hw = &fanout_27M_clk.common.hw },
> >> + { .hw = &fanout_pclk_clk.common.hw },
> >> +};
> >> +
> >> +static SUNXI_CCU_MUX_DATA_WITH_GATE(fanout0_clk, "fanout0", fanout_parents, 0xf3c,
> >> + 0, 3, /* mux */
> >> + BIT(21), /* gate */
> >> + 0);
> >> +static SUNXI_CCU_MUX_DATA_WITH_GATE(fanout1_clk, "fanout1", fanout_parents, 0xf3c,
> >> + 3, 3, /* mux */
> >> + BIT(22), /* gate */
> >> + 0);
> >> +static SUNXI_CCU_MUX_DATA_WITH_GATE(fanout2_clk, "fanout2", fanout_parents, 0xf3c,
> >> + 6, 3, /* mux */
> >> + BIT(23), /* gate */
> >> + 0);
> >> +
> >> +
> >> +static struct ccu_common *sun8i_v853_ccu_clks[] = {
> >> + &pll_cpu_clk.common,
> >> + &pll_ddr_clk.common,
> >> + &pll_periph_4x_clk.common,
> >> + &pll_periph_2x_clk.common,
> >> + &pll_periph_800M_clk.common,
> >> + &pll_periph_480M_clk.common,
> >> + &pll_video_4x_clk.common,
> >> + &pll_csi_4x_clk.common,
> >> + &pll_audio_div2_clk.common,
> >> + &pll_audio_div5_clk.common,
> >> + &pll_audio_4x_clk.common,
> >> + &pll_audio_1x_clk.common,
> >> + &pll_npu_4x_clk.common,
> >> + &cpu_clk.common,
> >> + &cpu_axi_clk.common,
> >> + &cpu_apb_clk.common,
> >> + &ahb_clk.common,
> >> + &apb0_clk.common,
> >> + &apb1_clk.common,
> >> + &de_clk.common,
> >> + &bus_de_clk.common,
> >> + &g2d_clk.common,
> >> + &bus_g2d_clk.common,
> >> + &ce_clk.common,
> >> + &bus_ce_clk.common,
> >> + &ve_clk.common,
> >> + &bus_ve_clk.common,
> >> + &npu_clk.common,
> >> + &bus_npu_clk.common,
> >> + &bus_dma_clk.common,
> >> + &bus_msgbox0_clk.common,
> >> + &bus_msgbox1_clk.common,
> >> + &bus_spinlock_clk.common,
> >> + &bus_hstimer_clk.common,
> >> + &avs_clk.common,
> >> + &bus_dbg_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_csi_clk.common,
> >> + &mbus_isp_clk.common,
> >> + &mbus_g2d_clk.common,
> >> + &bus_dram_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_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,
> >> + &spi2_clk.common,
> >> + &spi3_clk.common,
> >> + &bus_spi0_clk.common,
> >> + &bus_spi1_clk.common,
> >> + &bus_spi2_clk.common,
> >> + &bus_spi3_clk.common,
> >> + &spif_clk.common,
> >> + &bus_spif_clk.common,
> >> + &emac_25M_clk.common,
> >> + &bus_emac_clk.common,
> >> + &bus_gpadc_clk.common,
> >> + &bus_ths_clk.common,
> >> + &usb_ohci_clk.common,
> >> + &bus_ohci_clk.common,
> >> + &bus_ehci_clk.common,
> >> + &bus_otg_clk.common,
> >> + &i2s0_clk.common,
> >> + &i2s1_clk.common,
> >> + &bus_i2s0_clk.common,
> >> + &bus_i2s1_clk.common,
> >> + &dmic_clk.common,
> >> + &bus_dmic_clk.common,
> >> + &audio_codec_dac_clk.common,
> >> + &audio_codec_adc_clk.common,
> >> + &bus_audio_codec_clk.common,
> >> + &bus_dpss_top_clk.common,
> >> + &mipi_dsi_clk.common,
> >> + &bus_mipi_dsi_clk.common,
> >> + &tcon_lcd_clk.common,
> >> + &bus_tcon_lcd_clk.common,
> >> + &csi_top_clk.common,
> >> + &csi_mclk0_clk.common,
> >> + &csi_mclk1_clk.common,
> >> + &csi_mclk2_clk.common,
> >> + &bus_csi_clk.common,
> >> + &bus_wiegand_clk.common,
> >> + &riscv_clk.common,
> >> + &riscv_axi_clk.common,
> >> + &riscv_cfg.common,
> >> + &fanout_24M_clk.common,
> >> + &fanout_12M_clk.common,
> >> + &fanout_16M_clk.common,
> >> + &fanout_25M_clk.common,
> >> + &fanout_27M_clk.common,
> >> + &fanout_pclk_clk.common,
> >> + &fanout0_clk.common,
> >> + &fanout1_clk.common,
> >> + &fanout2_clk.common,
> >> +};
> >> +
> >> +static struct clk_hw_onecell_data sun8i_v853_hw_clks = {
> >> + .num = CLK_NUMBER,
> >> + .hws = {
> >> + [CLK_OSC12M] = &osc12M_clk.hw,
> >> + [CLK_PLL_CPU] = &pll_cpu_clk.common.hw,
> >> + [CLK_PLL_DDR] = &pll_ddr_clk.common.hw,
> >> + [CLK_PLL_PERIPH_4X] = &pll_periph_4x_clk.common.hw,
> >> + [CLK_PLL_PERIPH_2X] = &pll_periph_2x_clk.common.hw,
> >> + [CLK_PLL_PERIPH_800M] = &pll_periph_800M_clk.common.hw,
> >> + [CLK_PLL_PERIPH_480M] = &pll_periph_480M_clk.common.hw,
> >> + [CLK_PLL_PERIPH_600M] = &pll_periph_600M_clk.hw,
> >> + [CLK_PLL_PERIPH_400M] = &pll_periph_400M_clk.hw,
> >> + [CLK_PLL_PERIPH_300M] = &pll_periph_300M_clk.hw,
> >> + [CLK_PLL_PERIPH_200M] = &pll_periph_200M_clk.hw,
> >> + [CLK_PLL_PERIPH_160M] = &pll_periph_160M_clk.hw,
> >> + [CLK_PLL_PERIPH_150M] = &pll_periph_150M_clk.hw,
> >> + [CLK_PLL_VIDEO_4X] = &pll_video_4x_clk.common.hw,
> >> + [CLK_PLL_VIDEO_2X] = &pll_video_2x_clk.hw,
> >> + [CLK_PLL_VIDEO_1X] = &pll_video_1x_clk.hw,
> >> + [CLK_PLL_CSI_4X] = &pll_csi_4x_clk.common.hw,
> >> + [CLK_PLL_AUDIO_DIV2] = &pll_audio_div2_clk.common.hw,
> >> + [CLK_PLL_AUDIO_DIV5] = &pll_audio_div5_clk.common.hw,
> >> + [CLK_PLL_AUDIO_4X] = &pll_audio_4x_clk.common.hw,
> >> + [CLK_PLL_AUDIO_1X] = &pll_audio_1x_clk.common.hw,
> >> + [CLK_PLL_NPU_4X] = &pll_npu_4x_clk.common.hw,
> >> + [CLK_CPU] = &cpu_clk.common.hw,
> >> + [CLK_CPU_AXI] = &cpu_axi_clk.common.hw,
> >> + [CLK_CPU_APB] = &cpu_apb_clk.common.hw,
> >> + [CLK_AHB] = &ahb_clk.common.hw,
> >> + [CLK_APB0] = &apb0_clk.common.hw,
> >> + [CLK_APB1] = &apb1_clk.common.hw,
> >> + [CLK_MBUS] = &mbus_clk.hw,
> >> + [CLK_DE] = &de_clk.common.hw,
> >> + [CLK_BUS_DE] = &bus_de_clk.common.hw,
> >> + [CLK_G2D] = &g2d_clk.common.hw,
> >> + [CLK_BUS_G2D] = &bus_g2d_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_NPU] = &npu_clk.common.hw,
> >> + [CLK_BUS_NPU] = &bus_npu_clk.common.hw,
> >> + [CLK_BUS_DMA] = &bus_dma_clk.common.hw,
> >> + [CLK_BUS_MSGBOX0] = &bus_msgbox0_clk.common.hw,
> >> + [CLK_BUS_MSGBOX1] = &bus_msgbox1_clk.common.hw,
> >> + [CLK_BUS_SPINLOCK] = &bus_spinlock_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_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_CSI] = &mbus_csi_clk.common.hw,
> >> + [CLK_MBUS_ISP] = &mbus_isp_clk.common.hw,
> >> + [CLK_MBUS_G2D] = &mbus_g2d_clk.common.hw,
> >> + [CLK_BUS_DRAM] = &bus_dram_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_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_SPI2] = &spi2_clk.common.hw,
> >> + [CLK_SPI3] = &spi3_clk.common.hw,
> >> + [CLK_BUS_SPI0] = &bus_spi0_clk.common.hw,
> >> + [CLK_BUS_SPI1] = &bus_spi1_clk.common.hw,
> >> + [CLK_BUS_SPI2] = &bus_spi2_clk.common.hw,
> >> + [CLK_BUS_SPI3] = &bus_spi3_clk.common.hw,
> >> + [CLK_SPIF] = &spif_clk.common.hw,
> >> + [CLK_BUS_SPIF] = &bus_spif_clk.common.hw,
> >> + [CLK_EMAC_25M] = &emac_25M_clk.common.hw,
> >> + [CLK_BUS_EMAC] = &bus_emac_clk.common.hw,
> >> + [CLK_BUS_GPADC] = &bus_gpadc_clk.common.hw,
> >> + [CLK_BUS_THS] = &bus_ths_clk.common.hw,
> >> + [CLK_I2S0] = &i2s0_clk.common.hw,
> >> + [CLK_I2S1] = &i2s1_clk.common.hw,
> >> + [CLK_BUS_I2S0] = &bus_i2s0_clk.common.hw,
> >> + [CLK_BUS_I2S1] = &bus_i2s1_clk.common.hw,
> >> + [CLK_DMIC] = &dmic_clk.common.hw,
> >> + [CLK_BUS_DMIC] = &bus_dmic_clk.common.hw,
> >> + [CLK_AUDIO_CODEC_DAC] = &audio_codec_dac_clk.common.hw,
> >> + [CLK_AUDIO_CODEC_ADC] = &audio_codec_adc_clk.common.hw,
> >> + [CLK_BUS_AUDIO_CODEC] = &bus_audio_codec_clk.common.hw,
> >> + [CLK_USB_OHCI] = &usb_ohci_clk.common.hw,
> >> + [CLK_BUS_OHCI] = &bus_ohci_clk.common.hw,
> >> + [CLK_BUS_EHCI] = &bus_ehci_clk.common.hw,
> >> + [CLK_BUS_OTG] = &bus_otg_clk.common.hw,
> >> + [CLK_BUS_DPSS_TOP] = &bus_dpss_top_clk.common.hw,
> >> + [CLK_MIPI_DSI] = &mipi_dsi_clk.common.hw,
> >> + [CLK_BUS_MIPI_DSI] = &bus_mipi_dsi_clk.common.hw,
> >> + [CLK_TCON_LCD] = &tcon_lcd_clk.common.hw,
> >> + [CLK_BUS_TCON_LCD] = &bus_tcon_lcd_clk.common.hw,
> >> + [CLK_CSI_TOP] = &csi_top_clk.common.hw,
> >> + [CLK_CSI_MCLK0] = &csi_mclk0_clk.common.hw,
> >> + [CLK_CSI_MCLK1] = &csi_mclk1_clk.common.hw,
> >> + [CLK_CSI_MCLK2] = &csi_mclk2_clk.common.hw,
> >> + [CLK_BUS_CSI] = &bus_csi_clk.common.hw,
> >> + [CLK_BUS_WIEGAND] = &bus_wiegand_clk.common.hw,
> >> + [CLK_RISCV] = &riscv_clk.common.hw,
> >> + [CLK_RISCV_AXI] = &riscv_axi_clk.common.hw,
> >> + [CLK_RISCV_CFG] = &riscv_cfg.common.hw,
> >> + [CLK_FANOUT_24M] = &fanout_24M_clk.common.hw,
> >> + [CLK_FANOUT_16M] = &fanout_16M_clk.common.hw,
> >> + [CLK_FANOUT_12M] = &fanout_12M_clk.common.hw,
> >> + [CLK_FANOUT_25M] = &fanout_25M_clk.common.hw,
> >> + [CLK_FANOUT_27M] = &fanout_27M_clk.common.hw,
> >> + [CLK_FANOUT_PCLK] = &fanout_pclk_clk.common.hw,
> >> + [CLK_FANOUT0] = &fanout0_clk.common.hw,
> >> + [CLK_FANOUT1] = &fanout1_clk.common.hw,
> >> + [CLK_FANOUT2] = &fanout2_clk.common.hw,
> >> + },
> >> +};
> >> +
> >> +static struct ccu_reset_map sun8i_v853_ccu_resets[] = {
> >> + [RST_MBUS] = { 0x540, BIT(30) },
> >> + [RST_BUS_DE] = { 0x60c, BIT(16) },
> >> + [RST_BUS_G2D] = { 0x63c, BIT(16) },
> >> + [RST_BUS_CE] = { 0x68c, BIT(16) | BIT(17)},
> >> + [RST_BUS_VE] = { 0x69c, BIT(16) },
> >> + [RST_BUS_NPU] = { 0x6ec, BIT(16) },
> >> + [RST_BUS_DMA] = { 0x70c, BIT(16) },
> >> + [RST_BUS_MSGBOX0] = { 0x71c, BIT(16) },
> >> + [RST_BUS_MSGBOX1] = { 0x71c, BIT(17) },
> >> + [RST_BUS_SPINLOCK] = { 0x72c, BIT(16) },
> >> + [RST_BUS_HSTIMER] = { 0x73c, BIT(16) },
> >> + [RST_BUS_DBG] = { 0x78c, BIT(16) },
> >> + [RST_BUS_PWM] = { 0x7ac, BIT(16) },
> >> + [RST_BUS_DRAM] = { 0x80c, 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_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_SPIF] = { 0x96c, BIT(20) },
> >
> > That entry ^^^^ seems out of order.
>
> Opps, I’ll fix it.
>
> >
> >> + [RST_BUS_SPI0] = { 0x96c, BIT(16) },
> >> + [RST_BUS_SPI1] = { 0x96c, BIT(17) },
> >> + [RST_BUS_SPI2] = { 0x96c, BIT(18) },
> >> + [RST_BUS_SPI3] = { 0x96c, BIT(19) },
> >> + [RST_BUS_EMAC] = { 0x97c, BIT(16) },
> >> + [RST_BUS_GPADC] = { 0x9ec, BIT(16) },
> >> + [RST_BUS_THS] = { 0x9fc, BIT(16) },
> >> + [RST_BUS_I2S0] = { 0xa20, BIT(16) },
> >> + [RST_BUS_I2S1] = { 0xa20, BIT(17) },
> >> + [RST_BUS_DMIC] = { 0xa4c, BIT(16) },
> >> + [RST_BUS_AUDIO_CODEC] = { 0xa5c, BIT(16) },
> >> + [RST_USB_PHY] = { 0xa70, BIT(30) },
> >> + [RST_BUS_OHCI] = { 0xa8c, BIT(16) },
> >> + [RST_BUS_EHCI] = { 0xa8c, BIT(20) },
> >> + [RST_BUS_OTG] = { 0xa8c, BIT(24) },
> >> + [RST_BUS_DPSS_TOP] = { 0xabc, BIT(16) },
> >> + [RST_BUS_MIPI_DSI] = { 0xb4c, BIT(16) },
> >> + [RST_BUS_TCON_LCD] = { 0xb7c, BIT(16) },
> >> + [RST_BUS_CSI] = { 0xc2c, BIT(16) },
> >> + [RST_BUS_WIEGAND] = { 0xc7c, BIT(16) },
> >> + [RST_RISCV_SYS_APB] = { 0xd04, BIT(2), CCU_FEATURE_KEY_FIELD },
> >> + [RST_RISCV_SOFT] = { 0xd04, BIT(1), CCU_FEATURE_KEY_FIELD },
> >> + [RST_RISCV_CLK_GATING] = { 0xd04, BIT(0), CCU_FEATURE_KEY_FIELD },
> >
> > But that's a clock gate, not a reset, right?
>
> Yes, I forget to fix that. Modelling this way (because of the KEY_FIELD) was faster
> when I wrote the remoteproc driver.
>
> >
> >> + [RST_RISCV_CFG] = { 0xd0c, BIT(16) }
> >
> > The rest of the reset bits match the manual.
> >
> >> +};
> >> +
> >> +static const struct sunxi_ccu_desc sun8i_v853_ccu_desc = {
> >> + .ccu_clks = sun8i_v853_ccu_clks,
> >> + .num_ccu_clks = ARRAY_SIZE(sun8i_v853_ccu_clks),
> >> +
> >> + .hw_clks = &sun8i_v853_hw_clks,
> >> +
> >> + .resets = sun8i_v853_ccu_resets,
> >> + .num_resets = ARRAY_SIZE(sun8i_v853_ccu_resets),
> >> +};
> >> +
> >> +static const u32 pll_regs[] = {
> >> + SUN8I_V853_PLL_CPU_REG,
> >> + SUN8I_V853_PLL_DDR_REG,
> >> + SUN8I_V853_PLL_PERIPH_REG,
> >> + SUN8I_V853_PLL_VIDEO_REG,
> >> + SUN8I_V853_PLL_CSI_REG,
> >> + SUN8I_V853_PLL_AUDIO_REG,
> >> + SUN8I_V853_PLL_NPU_REG,
> >> +};
> >> +
> >> +static int sun8i_v853_ccu_probe(struct platform_device *pdev)
> >> +{
> >> + void __iomem *reg;
> >> + u32 val;
> >> + int i, ret;
> >> +
> >> + reg = devm_platform_ioremap_resource(pdev, 0);
> >> + if (IS_ERR(reg))
> >> + return PTR_ERR(reg);
> >> +
> >> + /* Enable the enable, LDO, and lock bits on all PLLs. */
> >> + for (i = 0; i < ARRAY_SIZE(pll_regs); i++) {
> >> + val = readl(reg + pll_regs[i]);
> >> + val |= BIT(31) | BIT(30) | BIT(29);
> >> + writel(val, reg + pll_regs[i]);
> >> + }
> >> +
> >> + /* Force PLL_CPU factor M to 0. */
> >> + val = readl(reg + SUN8I_V853_PLL_CPU_REG);
> >> + val &= ~GENMASK(1, 0);
> >> + writel(val, reg + SUN8I_V853_PLL_CPU_REG);
> >
> > Let's just hope it was 0 already, as I guess a sudden jump of
> > CPU frequency might not be too healthy.
> >
> I’ll double check that.
>
> >> + /*
> >> + * Force the output divider of video PLL to 0.
> >
> > Just a nit, but a "divider of 0" does not sound too healthy. Maybe:
> > "Force the output divider to 1, by clearing bit 0."
> >
>
> Thanks.
>
> > Cheers,
> > Andre
> >
> >> + *
> >> + * See the comment before pll-video0 definition for the reason.
> >> + */
> >> + val = readl(reg + SUN8I_V853_PLL_VIDEO_REG);
> >> + val &= ~BIT(0);
> >> + writel(val, reg + SUN8I_V853_PLL_VIDEO_REG);
> >> +
> >> + /*
> >> + * Force the output divider of CSI PLL to 0.
> >> + *
> >> + * See the comment before pll-csi definition for the reason.
> >> + */
> >> + val = readl(reg + SUN8I_V853_PLL_CSI_REG);
> >> + val &= ~BIT(0);
> >> + writel(val, reg + SUN8I_V853_PLL_CSI_REG);
> >> +
> >> + /*
> >> + * Force the output divider of NPU PLL to 0.
> >> + *
> >> + * See the comment before pll-npu definition for the reason.
> >> + */
> >> + val = readl(reg + SUN8I_V853_PLL_NPU_REG);
> >> + val &= ~BIT(0);
> >> + writel(val, reg + SUN8I_V853_PLL_NPU_REG);
> >> +
> >> + /*
> >> + * Force OHCI 12M clock source to 00 (12MHz divided from 48MHz)
> >> + *
> >> + * This clock mux is still mysterious, and the code just enforces
> >> + * it to have a valid clock parent.
> >> + */
> >> + val = readl(reg + SUN8I_V853_USB_CLK_REG);
> >> + val &= ~GENMASK(25, 24);
> >> + writel(val, reg + SUN8I_V853_USB_CLK_REG);
> >> +
> >> + /* Force fanout-27M factor N to 0. */
> >> + val = readl(reg + SUN8I_V853_FANOUT_27M_REG);
> >> + val &= ~GENMASK(9, 8);
> >> + writel(val, reg + SUN8I_V853_FANOUT_27M_REG);
> >> +
> >> + ret = devm_sunxi_ccu_probe(&pdev->dev, reg, &sun8i_v853_ccu_desc);
> >> + if (ret)
> >> + return ret;
> >> +
> >> + return 0;
> >> +}
> >> +
> >> +static const struct of_device_id sun8i_v853_ccu_ids[] = {
> >> + { .compatible = "allwinner,sun8i-v853-ccu" },
> >> + { }
> >> +};
> >> +
> >> +static struct platform_driver sun8i_v853_ccu_driver = {
> >> + .probe = sun8i_v853_ccu_probe,
> >> + .driver = {
> >> + .name = "sun8i-v853-ccu",
> >> + .suppress_bind_attrs = true,
> >> + .of_match_table = sun8i_v853_ccu_ids,
> >> + },
> >> +};
> >> +module_platform_driver(sun8i_v853_ccu_driver);
> >> +
> >> +MODULE_IMPORT_NS("SUNXI_CCU");
> >> +MODULE_LICENSE("GPL");
> >> diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-v853.h b/drivers/clk/sunxi-ng/ccu-sun8i-v853.h
> >> new file mode 100644
> >> index 000000000000..b6ee1764fe5e
> >> --- /dev/null
> >> +++ b/drivers/clk/sunxi-ng/ccu-sun8i-v853.h
> >> @@ -0,0 +1,14 @@
> >> +/* SPDX-License-Identifier: GPL-2.0 */
> >> +/*
> >> + * Copyright (C) 2024 Andras Szemzo <szemzo.andras@gmail.com>
> >> + */
> >> +
> >> +#ifndef _CCU_SUN8I_V853_H_
> >> +#define _CCU_SUN8I_V853_H_
> >> +
> >> +#include <dt-bindings/clock/sun8i-v853-ccu.h>
> >> +#include <dt-bindings/reset/sun8i-v853-ccu.h>
> >> +
> >> +#define CLK_NUMBER (CLK_FANOUT2 + 1)
> >> +
> >> +#endif /* _CCU_SUN8I_V853_H_ */
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [PATCH 05/12] clk: sunxi-ng: add CCU drivers for V853
2025-01-28 11:22 ` Andre Przywara
@ 2025-01-29 7:29 ` András Szemző
0 siblings, 0 replies; 50+ messages in thread
From: András Szemző @ 2025-01-29 7:29 UTC (permalink / raw)
To: Andre Przywara
Cc: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
Linus Walleij, Philipp Zabel, Maxime Ripard, Vinod Koul,
Kishon Vijay Abraham I, Ulf Hansson, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Uwe Kleine-König,
Florian Fainelli, linux-clk, devicetree, linux-arm-kernel,
linux-sunxi, linux-kernel, linux-phy, linux-gpio, linux-pm,
linux-riscv
> On 28 Jan 2025, at 12:22, Andre Przywara <andre.przywara@arm.com> wrote:
>
> On Tue, 28 Jan 2025 10:06:50 +0100
> András Szemző <szemzo.andras@gmail.com> wrote:
>
> Hi András,
>
> thanks for the quick and thorough reply, much appreciated!
>
>> Hi Andre,
>>
>>> On 28 Jan 2025, at 01:42, Andre Przywara <andre.przywara@arm.com> wrote:
>>>
>>> On Fri, 10 Jan 2025 13:39:16 +0100
>>> Andras Szemzo <szemzo.andras@gmail.com> wrote:
>>>
>>> Hi Andras,
>>>
>>> oh dear, that's a code line and a half!
>>>
>>> First very much for sending this, I know from (recent) experience that
>>> those clock drivers can be very daunting and tedious to write
>>> ...which is unfortunately true for the review as well ;-)
>>>
>>> So this is the first round, as I was keeping and updating this in my
>>> Drafts folder for almost two weeks now.
>>>
>>>> V853 has similar gates/resets like existing Allwinner SOCs. Add support for it's CCU and PRCM CCU.
>>>>
>>>> Signed-off-by: Andras Szemzo <szemzo.andras@gmail.com>
>>>> ---
>>>> drivers/clk/sunxi-ng/Kconfig | 10 +
>>>> drivers/clk/sunxi-ng/Makefile | 4 +
>>>> drivers/clk/sunxi-ng/ccu-sun8i-v853-r.c | 95 ++
>>>> drivers/clk/sunxi-ng/ccu-sun8i-v853-r.h | 15 +
>>>> drivers/clk/sunxi-ng/ccu-sun8i-v853.c | 1145 +++++++++++++++++++++++
>>>> drivers/clk/sunxi-ng/ccu-sun8i-v853.h | 14 +
>>>> 6 files changed, 1283 insertions(+)
>>>> create mode 100644 drivers/clk/sunxi-ng/ccu-sun8i-v853-r.c
>>>> create mode 100644 drivers/clk/sunxi-ng/ccu-sun8i-v853-r.h
>>>> create mode 100644 drivers/clk/sunxi-ng/ccu-sun8i-v853.c
>>>> create mode 100644 drivers/clk/sunxi-ng/ccu-sun8i-v853.h
>>>>
>>>> diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig
>>>> index b547198a2c65..c43002246b22 100644
>>>> --- a/drivers/clk/sunxi-ng/Kconfig
>>>> +++ b/drivers/clk/sunxi-ng/Kconfig
>>>> @@ -22,6 +22,16 @@ config SUN20I_D1_R_CCU
>>>> default y
>>>> depends on MACH_SUN8I || RISCV || COMPILE_TEST
>>>>
>>>> +config SUN8I_V853_CCU
>>>> + tristate "Support for the Allwinner V853 CCU"
>>>> + default MACH_SUN8I
>>>> + depends on MACH_SUN8I || COMPILE_TEST
>>>> +
>>>> +config SUN8I_V853_R_CCU
>>>> + tristate "Support for the Allwinner V853 PRCM CCU"
>>>> + default MACH_SUN8I
>>>> + depends on MACH_SUN8I || COMPILE_TEST
>>>> +
>>>> config SUN50I_A64_CCU
>>>> tristate "Support for the Allwinner A64 CCU"
>>>> default y
>>>> diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
>>>> index 6b3ae2b620db..c32430d874ea 100644
>>>> --- a/drivers/clk/sunxi-ng/Makefile
>>>> +++ b/drivers/clk/sunxi-ng/Makefile
>>>> @@ -27,6 +27,8 @@ sunxi-ccu-y += ccu_mp.o
>>>> obj-$(CONFIG_SUNIV_F1C100S_CCU) += suniv-f1c100s-ccu.o
>>>> obj-$(CONFIG_SUN20I_D1_CCU) += sun20i-d1-ccu.o
>>>> obj-$(CONFIG_SUN20I_D1_R_CCU) += sun20i-d1-r-ccu.o
>>>> +obj-$(CONFIG_SUN8I_V853_CCU) += sun8i-v853-ccu.o
>>>> +obj-$(CONFIG_SUN8I_V853_R_CCU) += sun8i-v853-r-ccu.o
>>>> obj-$(CONFIG_SUN50I_A64_CCU) += sun50i-a64-ccu.o
>>>> obj-$(CONFIG_SUN50I_A100_CCU) += sun50i-a100-ccu.o
>>>> obj-$(CONFIG_SUN50I_A100_R_CCU) += sun50i-a100-r-ccu.o
>>>> @@ -50,6 +52,8 @@ obj-$(CONFIG_SUN9I_A80_CCU) += sun9i-a80-de-ccu.o
>>>> obj-$(CONFIG_SUN9I_A80_CCU) += sun9i-a80-usb-ccu.o
>>>>
>>>> suniv-f1c100s-ccu-y += ccu-suniv-f1c100s.o
>>>> +sun8i-v853-ccu-y += ccu-sun8i-v853.o
>>>> +sun8i-v853-r-ccu-y += ccu-sun8i-v853-r.o
>>>> sun20i-d1-ccu-y += ccu-sun20i-d1.o
>>>> sun20i-d1-r-ccu-y += ccu-sun20i-d1-r.o
>>>> sun50i-a64-ccu-y += ccu-sun50i-a64.o
>>>> diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-v853-r.c b/drivers/clk/sunxi-ng/ccu-sun8i-v853-r.c
>>>> new file mode 100644
>>>> index 000000000000..19a8ba587793
>>>> --- /dev/null
>>>> +++ b/drivers/clk/sunxi-ng/ccu-sun8i-v853-r.c
>>>> @@ -0,0 +1,95 @@
>>>> +// SPDX-License-Identifier: GPL-3.0
>>>> +/* Copyright(c) 2020 - 2023 Allwinner Technology Co.,Ltd. All rights reserved.
>>>
>>> So does that mean you copied that from the BSP? How much is your own
>>> work then? Should "rengaomin" be then the author?
>>>
>>> But more importantly: As far as I know, GPL-3 is NOT compatible with
>>> the kernel. You definitely cannot add code with that license, and from
>>> my understanding cannot copy GPL-3 code without keeping the license,
>>> which means copying is a no-go.
>>> You would need to ask the original author to change the license. I have
>>> seen license changes in github repos mirroring Allwinner's SDK in the
>>> last few months (someone must have told them?), so it's worth checking
>>> back there to see if the license has changed.
>>>
>>> But with that header, and with that source (subject to clarification)
>>> this cannot be merged as such.
>>>
>>
>> In the datasheet what I have, all this R_PRCM block is mentioned only at the memory mapping.
>> I did't found any other documentation about this IP.
>
> Yeah, that's quite common, the PRCM is rarely documented. It's also quite
> stable across the modern SoC, and by chance the A523 manual actually
> documents that, so you can peek in there. The V853 is probably a subset of
> what's in the A523.
> You can also probe registers from U-Boot:
> => mw.l 0x701012c 0xffffffff
> => md.l 0x701012c
>
> That tells you which bits are actually implemented. Feel free to probe
> around other registers, especially those ending in "c", which are typically
> gates and resets. This would give you some confirmation.
>
> So can you do the following:
> Delete that file here, and copy over ccu-sun20i-d1-r.c. Add your
> copyright, and use "Based on ...".
> Then adjust that file according to the information gathered by inspecting
> the Allwinner source file you mention below. Since we are talking about a
> handful of clocks only, that should be easy enough?
> Then we have a clean sheet license-wise, and you copy from a much better
> source anyway (just seeing capital letter hex constants below, for
> instance).
>
Thanks for this information, it’s very usefull! I reworked the ccu-r code based on D1 driver,
and reading/writing the implemented registers, so this licence issue is gone.
>> There is a driver [1] based on the more or less mainline'ish sunxi-ng clk
>> framework, so I took that and made it work with this v853-ccu driver.
>>
>> I don’t know what should/can I do with the Licence or how should it done properly,
>> as it’s basically a few registers/bits, but without documentation it’s hard to write it from scratch.
>
> Absolutely, and normally it's a no-brainer, since even Allwinner Linux
> code must be GPL, but in this special case they became overzealous and put
> GPL-3.0 in :-(
>
>>
>> [1]: https://github.com/YuzukiHD/TinyVision/blob/main/kernel/bsp/drivers/clk/sunxi-ng/ccu-sun8iw21-r.c
>>
>>>> + *
>>>> + * Copyright (c) 2023 rengaomin@allwinnertech.com
>>>> + */
>>>> +
>>>> +#include <linux/clk-provider.h>
>>>> +#include <linux/io.h>
>>>> +#include <linux/module.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-sun8i-v853-r.h"
>>>> +
>>>> +
>>>> +static SUNXI_CCU_GATE(r_twd_clk, "r-twd", "osc24M", 0x012C, BIT(0), 0);
>>>> +static SUNXI_CCU_GATE(r_ppu_clk, "r-ppu", "osc24M", 0x01AC, BIT(0), 0);
>>>> +static SUNXI_CCU_GATE(r_rtc_clk, "r-rtc", "osc24M", 0x020C, BIT(0), 0);
>>>> +static SUNXI_CCU_GATE(r_cpucfg_clk, "r-cpucfg", "osc24M",
>>>> + 0x022C, BIT(0), 0);
>>>> +
>>>> +static struct ccu_reset_map sun8i_v853_r_ccu_resets[] = {
>>>> + [RST_BUS_R_PPU] = { 0x01ac, BIT(16) },
>>>> + [RST_BUS_R_RTC] = { 0x020c, BIT(16) },
>>>> + [RST_BUS_R_CPUCFG] = { 0x022c, BIT(16) },
>>>> +};
>>>> +
>>>> +static struct clk_hw_onecell_data sun8i_v853_r_hw_clks = {
>>>> + .hws = {
>>>> + [CLK_R_TWD] = &r_twd_clk.common.hw,
>>>> + [CLK_R_PPU] = &r_ppu_clk.common.hw,
>>>> + [CLK_R_RTC] = &r_rtc_clk.common.hw,
>>>> + [CLK_R_CPUCFG] = &r_cpucfg_clk.common.hw,
>>>> + },
>>>> + .num = CLK_NUMBER,
>>>> +};
>>>> +
>>>> +static struct ccu_common *sun8i_v853_r_ccu_clks[] = {
>>>> + &r_twd_clk.common,
>>>> + &r_ppu_clk.common,
>>>> + &r_rtc_clk.common,
>>>> + &r_cpucfg_clk.common,
>>>> +};
>>>> +
>>>> +
>>>> +static const struct sunxi_ccu_desc sun8i_v853_r_ccu_desc = {
>>>> + .ccu_clks = sun8i_v853_r_ccu_clks,
>>>> + .num_ccu_clks = ARRAY_SIZE(sun8i_v853_r_ccu_clks),
>>>> +
>>>> + .hw_clks = &sun8i_v853_r_hw_clks,
>>>> +
>>>> + .resets = sun8i_v853_r_ccu_resets,
>>>> + .num_resets = ARRAY_SIZE(sun8i_v853_r_ccu_resets),
>>>> +};
>>>> +
>>>> +static int sun8i_v853_r_ccu_probe(struct platform_device *pdev)
>>>> +{
>>>> + void __iomem *reg;
>>>> +
>>>> + reg = devm_platform_ioremap_resource(pdev, 0);
>>>> + if (IS_ERR(reg))
>>>> + return PTR_ERR(reg);
>>>> +
>>>> + return devm_sunxi_ccu_probe(&pdev->dev, reg, &sun8i_v853_r_ccu_desc);
>>>> +}
>>>> +
>>>> +static const struct of_device_id sun8i_v853_r_ccu_ids[] = {
>>>> + { .compatible = "allwinner,sun8i-v853-r-ccu" },
>>>> + { }
>>>> +};
>>>> +
>>>> +static struct platform_driver sun8i_v853_r_ccu_driver = {
>>>> + .probe = sun8i_v853_r_ccu_probe,
>>>> + .driver = {
>>>> + .name = "sun8i-v853-r-ccu",
>>>> + .suppress_bind_attrs = true,
>>>> + .of_match_table = sun8i_v853_r_ccu_ids,
>>>> + },
>>>> +};
>>>> +module_platform_driver(sun8i_v853_r_ccu_driver);
>>>> +
>>>> +MODULE_IMPORT_NS("SUNXI_CCU");
>>>> +MODULE_LICENSE("GPL");
>>>> diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-v853-r.h b/drivers/clk/sunxi-ng/ccu-sun8i-v853-r.h
>>>> new file mode 100644
>>>> index 000000000000..156ca15e8208
>>>> --- /dev/null
>>>> +++ b/drivers/clk/sunxi-ng/ccu-sun8i-v853-r.h
>>>> @@ -0,0 +1,15 @@
>>>> +/* SPDX-License-Identifier: GPL-2.0 */
>>>
>>> Here the license looks right, but the authorship and source are still
>>> in question. Looks like the only real code in here is CLK_NUMBER, so if
>>> that is your line, drop all those bogus copyrights, and put in your own.
>>
>> Ok, I’ll.
>>
>>>
>>>> +/* Copyright(c) 2020 - 2023 Allwinner Technology Co.,Ltd. All rights reserved.
>>>> + *
>>>> + * Copyright (c) 2023 rengaomin@allwinnertech.com
>>>> + */
>>>> +
>>>> +#ifndef _CCU_SUN8I_V853_R_H
>>>> +#define _CCU_SUN8I_V853_R_H
>>>> +
>>>> +#include <dt-bindings/clock/sun8i-v853-r-ccu.h>
>>>> +#include <dt-bindings/reset/sun8i-v853-r-ccu.h>
>>>> +
>>>> +#define CLK_NUMBER CLK_R_MAX_NO
>>>
>>> What's "CLK_R_MAX_NO"? I think we put in the actual last clock name in,
>>> traditionally?
>>>
>>
>> Yes, you are right.
>
> Great, now it's your patch anyway, so you can easily claim the copyright
> and authorship ;-)
>
>>>> +
>>>> +#endif
>>>> diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-v853.c b/drivers/clk/sunxi-ng/ccu-sun8i-v853.c
>>>> new file mode 100644
>>>> index 000000000000..a1947357a08e
>>>> --- /dev/null
>>>> +++ b/drivers/clk/sunxi-ng/ccu-sun8i-v853.c
>>>> @@ -0,0 +1,1145 @@
>>>> +// SPDX-License-Identifier: GPL-2.0-only
>>>> +/*
>>>> + * Copyright (C) 2024 Andras Szemzo <szemzo.andras@gmail.com>
>>>> + *
>>>> + * Based on ccu-sun20i-d1.c, which is:
>>>> + * Copyright (C) 2021 Samuel Holland. All rights reserved.
>>>
>>> All rights reserved? Where does that come from? Please remove that.
>>>
>>
>> Starting to write the first ccu driver without prior knowledge is not an easy task, so I started from the d1 ccu driver. I don’t know
>> how much from that remains actually, but I don’t wanted to remove that comment. I looked around how should it be done
>> correctly, and copied the remark from the ccu-sun8i-v3s.c
>>
>> It has exactly the same copyright.
>> ..
>> * Based on ccu-sun8i-h3.c, which is:
>> * Copyright (c) 2016 Maxime Ripard. All rights reserved.
>
> Ah, I didn't see it with Samuel's name, hence was wondering. The H3
> heritage is by now quite insignificant, I'd say, and since you dropped
> Maxime anyway, you can just copy Samuel's line, without the "All rights
> reserved". It's probably redundant anyway.
>
>> I’ll remove that.
>
> So yes, just remove the "All rights reserved." Thanks.
>
>>
>>>> + */
>>>> +
>>>> +#include <linux/clk-provider.h>
>>>> +#include <linux/io.h>
>>>> +#include <linux/module.h>
>>>> +#include <linux/platform_device.h>
>>>> +
>>>> +#include "../clk.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-sun8i-v853.h"
>>>> +
>>>> +static const struct clk_parent_data osc24M[] = {
>>>> + { .fw_name = "hosc" }
>>>> +};
>>>> +
>>>> +/*
>>>> + * For the CPU PLL, the output divider is described as "only for testing"
>>>> + * in the user manual. So it's not modelled and forced to 0.
>>>> + */
>>>> +#define SUN8I_V853_PLL_CPU_REG 0x000
>>>> +
>>>> +static struct ccu_mult pll_cpu_clk = {
>>>> + .enable = BIT(27) | BIT(30) | BIT(31),
>>>
>>> But bit 30 and 31 are set already by the PLL loop in the probe routine
>>> below, so we just need bit 27 to gate the output.
>>>
>>>> + .lock = BIT(28),
>>>> + .mult = _SUNXI_CCU_MULT_MIN(8, 8, 12),
>>>
>>> technically the manual says the minimum is 11, though this doesn't
>>> really matter, as we will never go that low anyway.
>>>
>>>> + .common = {
>>>> + .reg = 0x000,
>>>> + .hw.init = CLK_HW_INIT_PARENTS_DATA("pll-cpu", osc24M,
>>>> + &ccu_mult_ops,
>>>> + CLK_SET_RATE_UNGATE),
>>>
>>> This must be CLK_SET_RATE_GATE, as we figured some weeks ago. The manual
>>> says that for changing the frequency you must leave the PLL enabled
>>> (bits 31 and 30 = 1), but gate the output (bit 27 = 0). The "GATE" in
>>> that flag name here refers to the .enable mask above.
>>> So CLK_SET_RATE_UNGATE would mean: don't touch the enable bit, but keep
>>> it running, which would be correct if the enable bit would be about the
>>> real enable bit (bit 31). But since we model this like "enable means not
>>> gated", we must gate the output, by setting the enable bit to 0.
>>> CLK_SET_RATE_GATE does exactly that.
>>>
>>
>> All this BIT (30, 31, 27) and MULT_MIN 12 are comes from the mistake that I tried to follow the BSP
>> driver [2] too closely.
>> As the cpu freq. scaling are working [3] with this settings too, I missed that.
>
> Thanks for testing, it would be awesome if you could repeat that test
> briefly with the changes.
>
> Thanks for confirming the other bits, much appreciated!
>
After changing the enable BITS and setting CLK_SET_RATE_GATE in PLLs the cpu freq scaling is still working,
so thanks for your comments, it works.
Regards,
Andras
> Cheers,
> Andre
>
>> I’ll fix it.
>>
>> [2]: https://github.com/YuzukiHD/TinyVision/blob/main/kernel/bsp/drivers/clk/sunxi-ng/ccu-sun8iw21.c
>>
>> [3]: v851s:~# cat /sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state
>> 408000 177620
>> 600000 10099
>> 720000 2593
>> 912000 338
>> 1008000 3
>> 1200000 5675617
>> v851s:~#
>>
>>>> + },
>>>> +};
>>>> +
>>>> +/* Some PLLs are input * N / div1 / P. Model them as NKMP with no K */
>>>> +#define SUN8I_V853_PLL_DDR_REG 0x010
>>>> +static struct ccu_nkmp pll_ddr_clk = {
>>>> + .enable = BIT(27) | BIT(30) | BIT(31),
>>>
>>> same here, only bit 27 please.
>>>
>>>> + .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_PARENTS_DATA("pll-ddr", osc24M,
>>>> + &ccu_nkmp_ops,
>>>> + CLK_SET_RATE_UNGATE),
>>>
>>> CLK_SET_RATE_GATE, as above.
>>>
>>>> + },
>>>> +};
>>>> +
>>>> +#define SUN8I_V853_PLL_PERIPH_REG 0x020
>>>> +static struct ccu_nm pll_periph_4x_clk = {
>>>> + .enable = BIT(27) | BIT(30) | BIT(31),
>>>
>>> BIT(27), as above, and further down as well
>>>
>>>> + .lock = BIT(28),
>>>> + .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
>>>> + .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
>>>> + .common = {
>>>> + .reg = 0x020,
>>>> + .hw.init = CLK_HW_INIT_PARENTS_DATA("pll-periph-4x", osc24M,
>>>> + &ccu_nm_ops,
>>>> + CLK_SET_RATE_UNGATE),
>>>
>>> you guessed it: CLK_SET_RATE_GATE, here and further below, please
>>>
>>>> + },
>>>> +};
>>>> +
>>>> +static SUNXI_CCU_M(pll_periph_2x_clk, "pll-periph-2x", "pll-periph-4x",
>>>> + 0x020, 16, 3, 0);
>>>
>>> So is there a recommendation about how we reference other clocks? This
>>> one here is using the clock name, which requires a look-up, where we
>>> could use the pointer directly as well, as done down below.
>>>
>>> static const struct clk_hw *pll_periph0_4x_hws[] = {
>>> &pll_periph0_4x_clk.common.hw
>>> };
>>> static SUNXI_CCU_M_HWS(pll_periph0_2x_clk, "pll-periph0-2x",
>>> pll_periph0_4x_hws, 0x020, 16, 3, 0);
>>>
>>> I have seen both, sun20i-d1 for instance uses this, and I copied from
>>> there for the A523 clock code.
>>>
>>> Would be glad to hear some maintainer's opinion.
>>>
>>>> +
>>>> +static SUNXI_CCU_M(pll_periph_800M_clk, "pll-periph-800M", "pll-periph-4x",
>>>> + 0x020, 20, 3, 0);
>>>> +
>>>> +static SUNXI_CCU_M(pll_periph_480M_clk, "pll-periph-480M", "pll-periph-4x",
>>>> + 0x020, 2, 3, 0);
>>>> +
>>>> +static CLK_FIXED_FACTOR_HW(pll_periph_600M_clk, "pll-periph-600M",
>>>> + &pll_periph_2x_clk.common.hw, 2, 1, 0);
>>>> +
>>>> +static CLK_FIXED_FACTOR_HW(pll_periph_400M_clk, "pll-periph-400M",
>>>> + &pll_periph_2x_clk.common.hw, 3, 1, 0);
>>>> +
>>>> +static CLK_FIXED_FACTOR_HW(pll_periph_300M_clk, "pll-periph-300M",
>>>> + &pll_periph_600M_clk.hw, 2, 1, 0);
>>>> +
>>>> +static CLK_FIXED_FACTOR_HW(pll_periph_200M_clk, "pll-periph-200M",
>>>> + &pll_periph_400M_clk.hw, 2, 1, 0);
>>>> +
>>>> +static CLK_FIXED_FACTOR_HW(pll_periph_160M_clk, "pll-periph-160M",
>>>> + &pll_periph_480M_clk.common.hw, 3, 1, 0);
>>>> +
>>>> +static CLK_FIXED_FACTOR_HW(pll_periph_150M_clk, "pll-periph-150M",
>>>> + &pll_periph_300M_clk.hw, 2, 1, 0);
>>>> +
>>>> +
>>>> +/*
>>>> + * For Video PLLs, the output divider is described as "only for testing"
>>>> + * in the user manual. So it's not modelled and forced to 0.
>>>
>>> That's a bit confusing: the manual says that the default value for bit 0
>>> is 0x1, and that it's "only for testing", which would mean we should
>>> leave it like this, always dividing by 2? In the main description (bit
>>> 31) it says:
>>> VIDEOPLL4X = InputFreq*N/M
>>> but below (bit 0) it's
>>> VIDEOPLL4X = 24MHz*N/M/D
>>> (with D being "PLL_OUTPUT_DIV_D + 1", so 2 in our case)
>>>
>>> Do you have any indication how fast the video PLL really is? If it is
>>> divided by 2 (as we force that bit to 1 down in the probe routine), then
>>> we would need to model this with that CCU_FEATURE_FIXED_POSTDIV flag,
>>> and either leave that bit alone or force it to 1 instead.
>>> Also would be good to see what the BSP does.
>>>
>>
>> The [2] BSP driver model it as a ccu_nkmp type, so i’ll double check it.
>>
>>>> + */
>>>> +#define SUN8I_V853_PLL_VIDEO_REG 0x040
>>>> +static struct ccu_nm pll_video_4x_clk = {
>>>> + .enable = BIT(27) | BIT(30) | BIT(31),
>>>> + .lock = BIT(28),
>>>> + .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
>>>
>>> The manual says 11 (but again doesn't matter).
>>>
>>>> + .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
>>>> + .common = {
>>>> + .reg = 0x040,
>>>> + .hw.init = CLK_HW_INIT_PARENTS_DATA("pll-video-4x", osc24M,
>>>> + &ccu_nm_ops,
>>>> + CLK_SET_RATE_UNGATE),
>>>> + },
>>>> +};
>>>> +
>>>> +static const struct clk_hw *pll_video_4x_hws[] = {
>>>> + &pll_video_4x_clk.common.hw
>>>> +};
>>>> +static CLK_FIXED_FACTOR_HWS(pll_video_2x_clk, "pll-video-2x",
>>>> + pll_video_4x_hws, 2, 1, CLK_SET_RATE_PARENT);
>>>> +static CLK_FIXED_FACTOR_HWS(pll_video_1x_clk, "pll-video-1x",
>>>> + pll_video_4x_hws, 4, 1, CLK_SET_RATE_PARENT);
>>>
>>> Ah, here you are using the pointer reference to the base clock, not the
>>> string, as above. I think we should stick to one method?
>>
>> Ok.
>>
>>>
>>>> +/*
>>>> + * For CSI PLLs, the output divider is described as "only for testing"
>>>> + * in the user manual. So it's not modelled and forced to 0.
>>>
>>> Same situation as for the video PLL: what is the recommended setting of
>>> bit 0, really?
>>>
>>
>> Same as with the PLL_VIDEO. I’ll check it again, and modify both.
>>
>>>> + */
>>>> +#define SUN8I_V853_PLL_CSI_REG 0x048
>>>> +static struct ccu_nm pll_csi_4x_clk = {
>>>> + .enable = BIT(27) | BIT(30) | BIT(31),
>>>> + .lock = BIT(28),
>>>> + .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
>>>> + .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
>>>> + .common = {
>>>> + .reg = 0x048,
>>>> + .hw.init = CLK_HW_INIT_PARENTS_DATA("pll-csi-4x", osc24M,
>>>> + &ccu_nm_ops,
>>>> + CLK_SET_RATE_UNGATE),
>>>> + },
>>>> +};
>>>> +
>>>> +static CLK_FIXED_FACTOR_HW(pll_csi_clk, "pll-csi",
>>>> + &pll_csi_4x_clk.common.hw, 4, 1, CLK_SET_RATE_PARENT);
>>>> +
>>>> +
>>>> +#define SUN8I_V853_PLL_AUDIO_REG 0x78
>>>> +static struct ccu_sdm_setting pll_audio_div5_sdm_table[] = {
>>>> + { .rate = 196608000, .pattern = 0xc001eb85, .m = 5, .n = 40 }, /* 24.576 */
>>>> + { .rate = 67737600, .pattern = 0xc001288d, .m = 8, .n = 22 }, /* 22.5792 */
>>>> +};
>>>> +
>>>> +static struct ccu_nm pll_audio_div5_clk = {
>>>> + .enable = BIT(27) | BIT(30) | BIT(31),
>>>> + .lock = BIT(28),
>>>> + .n = _SUNXI_CCU_MULT(8, 8),
>>>> + .m = _SUNXI_CCU_DIV(20, 3),
>>>> + .sdm = _SUNXI_CCU_SDM(pll_audio_div5_sdm_table,
>>>> + BIT(24), 0x0178, BIT(31)),
>>>> + .common = {
>>>> + .reg = 0x0078,
>>>> + .features = CCU_FEATURE_SIGMA_DELTA_MOD,
>>>> + .hw.init = CLK_HW_INIT_PARENTS_DATA("pll-audio-div5", osc24M,
>>>> + &ccu_nm_ops,
>>>> + CLK_SET_RATE_UNGATE),
>>>> + },
>>>> +};
>>>> +static SUNXI_CCU_M(pll_audio_1x_clk, "pll-audio-1x", "pll-audio-div5",
>>>> + 0xe00, 0, 5, CLK_SET_RATE_PARENT);
>>>> +
>>>> +/* pll-audio-div2 and pll-aduio-4x not used, because audio-1x can cover 22.5792M and 24.576M */
>>>> +static SUNXI_CCU_M(pll_audio_div2_clk, "pll-audio-div2", "pll-audio",
>>>> + 0x078, 16, 3, 0);
>>>> +static SUNXI_CCU_M(pll_audio_4x_clk, "pll-audio-4x", "pll-audio-div2",
>>>> + 0xe00, 5, 5, 0);
>>>> +
>>>> +/*
>>>> + * For the NPU PLL, the output divider is described as "only for testing"
>>>> + * in the user manual. So it's not modelled and forced to 0.
>>>> + */
>>>> +#define SUN8I_V853_PLL_NPU_REG 0x080
>>>> +static struct ccu_nm pll_npu_4x_clk = {
>>>> + .enable = BIT(27) | BIT(30) | BIT(31),
>>>> + .lock = BIT(28),
>>>> + .n = _SUNXI_CCU_MULT_MIN(8, 8, 12),
>>>> + .m = _SUNXI_CCU_DIV(1, 1), /* input divider */
>>>> + .common = {
>>>> + .reg = 0x080,
>>>> + .hw.init = CLK_HW_INIT_PARENTS_DATA("pll-npu-4x", osc24M,
>>>> + &ccu_nm_ops,
>>>> + CLK_SET_RATE_UNGATE),
>>>> + },
>>>> +};
>>>> +
>>>> +/*
>>>> + * The CPU gate is not modelled - it is in a separate register (0x504)
>>>> + * and has a special key field. The clock does not need to be ungated anyway.
>>>
>>> I would believe it should read: "The clock must not be gated anyway by
>>> the kernel". (As it would stop execution on the Arm cores, so it's only
>>> something for the management core).
>>>
>>
>> ok.
>>
>>>> + */
>>>> +static const struct clk_parent_data cpu_parents[] = {
>>>> + { .fw_name = "hosc" },
>>>> + { .fw_name = "losc" },
>>>> + { .fw_name = "iosc" },
>>>> + { .hw = &pll_cpu_clk.common.hw },
>>>
>>> The manual says there is a divider (PLL_CPU_OUT_EXT_DIVP[17:16]),
>>> though the description suggests it should stay as 0. I guess this is
>>> the intention here, but can you please add comment here?
>>>
>>
>> ok.
>>
>>>> + { .hw = &pll_periph_600M_clk.hw },
>>>> + { .hw = &pll_periph_800M_clk.common.hw },
>>>> +};
>>>> +
>>>> +static SUNXI_CCU_MUX_DATA(cpu_clk, "cpu", cpu_parents,
>>>> + 0x500, 24, 3, CLK_SET_RATE_PARENT | CLK_IS_CRITICAL);
>>>> +
>>>> +static SUNXI_CCU_M(cpu_axi_clk, "cpu-axi", "cpu",
>>>
>>> I wonder if it's more efficient to use a pointer to the CPU clock, and
>>> not a string?
>>>
>>
>> I’ll fix that.
>>
>>>> + 0x500, 0, 2, 0);
>>>> +static SUNXI_CCU_M(cpu_apb_clk, "cpu-apb", "cpu",
>>>> + 0x500, 8, 2, 0);
>>>> +
>>>> +static const struct clk_parent_data ahb_parents[] = {
>>>> + { .fw_name = "hosc" },
>>>> + { .fw_name = "losc" },
>>>> + { .fw_name = "iosc" },
>>>> + { .hw = &pll_periph_600M_clk.hw },
>>>> +};
>>>> +static SUNXI_CCU_MP_DATA_WITH_MUX(ahb_clk, "ahb", ahb_parents, 0x510,
>>>> + 0, 5, /* M */
>>>> + 8, 2, /* P */
>>>> + 24, 2, /* mux */
>>>> + 0);
>>>> +
>>>> +static SUNXI_CCU_MP_DATA_WITH_MUX(apb0_clk, "apb0", ahb_parents, 0x520,
>>>> + 0, 5, /* M */
>>>> + 8, 2, /* P */
>>>> + 24, 2, /* mux */
>>>> + 0);
>>>> +
>>>> +static SUNXI_CCU_MP_DATA_WITH_MUX(apb1_clk, "apb1", ahb_parents, 0x524,
>>>> + 0, 5, /* M */
>>>> + 8, 2, /* P */
>>>> + 24, 2, /* mux */
>>>> + 0);
>>>> +
>>>> +static const struct clk_hw *ahb_hws[] = { &ahb_clk.common.hw };
>>>> +static const struct clk_hw *apb0_hws[] = { &apb0_clk.common.hw };
>>>> +static const struct clk_hw *apb1_hws[] = { &apb1_clk.common.hw };
>>>> +
>>>> +
>>>> +
>>>> +static const struct clk_hw *de_g2d_parents[] = {
>>>> + &pll_periph_300M_clk.hw,
>>>> + &pll_video_1x_clk.hw,
>>>> +};
>>>> +static SUNXI_CCU_M_HW_WITH_MUX_GATE(de_clk, "de", de_g2d_parents, 0x600,
>>>> + 0, 5, /* M */
>>>> + 24, 1, /* mux */
>>>> + BIT(31), /* gate */
>>>> + CLK_SET_RATE_PARENT);
>>>> +
>>>> +static SUNXI_CCU_GATE_HWS(bus_de_clk, "bus-de", ahb_hws,
>>>> + 0x60c, BIT(0), 0);
>>>> +
>>>> +static SUNXI_CCU_M_HW_WITH_MUX_GATE(g2d_clk, "g2d", de_g2d_parents, 0x630,
>>>> + 0, 5, /* M */
>>>> + 24, 1, /* mux */
>>>> + BIT(31), /* gate */
>>>> + CLK_SET_RATE_PARENT);
>>>> +
>>>> +static SUNXI_CCU_GATE_HWS(bus_g2d_clk, "bus-g2d", ahb_hws,
>>>> + 0x63c, BIT(0), 0);
>>>> +
>>>> +
>>>> +static const struct clk_parent_data ce_parents[] = {
>>>> + { .fw_name = "hosc" },
>>>
>>> That parent is not mentioned in the manual, though it looks like an
>>> omission. Did you find the HOSC mentioned somewhere else?
>>
>> The [2] BSP driver declares the CE parents in the same way.
>>
>>>
>>>> + { .hw = &pll_periph_400M_clk.hw, },
>>>> + { .hw = &pll_periph_300M_clk.hw, }
>>>> +};
>>>> +static SUNXI_CCU_M_DATA_WITH_MUX_GATE(ce_clk, "ce", ce_parents, 0x680,
>>>> + 0, 4, /* M */
>>>
>>> looks like the indentation here is a bit off, can you check this? And
>>> for the other clocks as well?
>>>
>>
>> Sure.
>>
>>>> + 24, 3, /* mux */
>>>> + BIT(31), /* gate */
>>>> + CLK_SET_RATE_PARENT);
>>>> +
>>>> +static SUNXI_CCU_GATE_HWS(bus_ce_clk, "bus-ce", ahb_hws,
>>>> + 0x68c, BIT(0) | BIT(1), 0);
>>>
>>>
>>> (reviewed till here, for now, to keep my sanity. Skipping down to
>>> below, where there are more low-hanging fruits and bits that can be
>>> checked more systematically)
>>>
>>>> +
>>>> +static const struct clk_hw *ve_parents[] = {
>>>> + &pll_periph_300M_clk.hw,
>>>> + &pll_periph_400M_clk.hw,
>>>> + &pll_periph_480M_clk.common.hw,
>>>> + &pll_npu_4x_clk.common.hw,
>>>> + &pll_video_4x_clk.common.hw,
>>>> + &pll_csi_4x_clk.common.hw,
>>>> +};
>>>> +static SUNXI_CCU_M_HW_WITH_MUX_GATE(ve_clk, "ve", ve_parents, 0x690,
>>>> + 0, 5, /* M */
>>>> + 24, 3, /* mux */
>>>> + BIT(31), /* gate */
>>>> + CLK_SET_RATE_PARENT);
>>>> +
>>>> +static SUNXI_CCU_GATE_HWS(bus_ve_clk, "bus-ve", ahb_hws,
>>>> + 0x69c, BIT(0), 0);
>>>> +
>>>> +
>>>> +static const struct clk_hw *npu_parents[] = {
>>>> + &pll_periph_480M_clk.common.hw,
>>>> + &pll_periph_600M_clk.hw,
>>>> + &pll_periph_800M_clk.common.hw,
>>>> + &pll_npu_4x_clk.common.hw,
>>>> +};
>>>> +static SUNXI_CCU_M_HW_WITH_MUX_GATE(npu_clk, "npu", npu_parents, 0x6e0,
>>>> + 0, 5, /* M */
>>>> + 24, 3, /* mux */
>>>> + BIT(31), /* gate */
>>>> + 0);
>>>> +
>>>> +static SUNXI_CCU_GATE_HWS(bus_npu_clk, "bus-npu", ahb_hws,
>>>> + 0x6ec, BIT(0), 0);
>>>> +
>>>> +static SUNXI_CCU_GATE_HWS(bus_dma_clk, "bus-dma", ahb_hws,
>>>> + 0x70c, BIT(0), 0);
>>>> +
>>>> +static SUNXI_CCU_GATE_HWS(bus_msgbox0_clk, "bus-msgbox0", ahb_hws,
>>>> + 0x71c, BIT(0), 0);
>>>> +static SUNXI_CCU_GATE_HWS(bus_msgbox1_clk, "bus-msgbox1", ahb_hws,
>>>> + 0x71c, BIT(1), 0);
>>>> +
>>>> +static SUNXI_CCU_GATE_HWS(bus_spinlock_clk, "bus-spinlock", ahb_hws,
>>>> + 0x72c, BIT(0), 0);
>>>> +
>>>> +static SUNXI_CCU_GATE_HWS(bus_hstimer_clk, "bus-hstimer", ahb_hws,
>>>> + 0x73c, BIT(0), 0);
>>>> +
>>>> +static SUNXI_CCU_GATE_DATA(avs_clk, "avs", osc24M,
>>>> + 0x740, BIT(31), 0);
>>>> +
>>>> +static SUNXI_CCU_GATE_HWS(bus_dbg_clk, "bus-dbg", ahb_hws,
>>>> + 0x78c, BIT(0), 0);
>>>> +
>>>> +static SUNXI_CCU_GATE_HWS(bus_pwm_clk, "bus-pwm", apb0_hws,
>>>> + 0x7ac, BIT(0), 0);
>>>> +
>>>> +static SUNXI_CCU_GATE_HWS(bus_iommu_clk, "bus-iommu", ahb_hws,
>>>> + 0x7bc, BIT(0), 0);
>>>> +
>>>> +static const struct clk_hw *dram_parents[] = {
>>>> + &pll_ddr_clk.common.hw,
>>>> + &pll_periph_2x_clk.common.hw,
>>>> + &pll_periph_800M_clk.common.hw,
>>>> +};
>>>> +static SUNXI_CCU_MP_HW_WITH_MUX_GATE(dram_clk, "dram", dram_parents, 0x800,
>>>> + 0, 5, /* M */
>>>> + 8, 2, /* P */
>>>> + 24, 3, /* mux */
>>>> + BIT(31), CLK_IS_CRITICAL);
>>>> +
>>>> +static CLK_FIXED_FACTOR_HW(mbus_clk, "mbus",
>>>> + &dram_clk.common.hw, 4, 1, 0);
>>>> +
>>>> +static const struct clk_hw *mbus_hws[] = { &mbus_clk.hw };
>>>> +
>>>> +static SUNXI_CCU_GATE_HWS(mbus_dma_clk, "mbus-dma", mbus_hws,
>>>> + 0x804, BIT(0), 0);
>>>> +static SUNXI_CCU_GATE_HWS(mbus_ve_clk, "mbus-ve", mbus_hws,
>>>> + 0x804, BIT(1), 0);
>>>> +static SUNXI_CCU_GATE_HWS(mbus_ce_clk, "mbus-ce", mbus_hws,
>>>> + 0x804, BIT(2), 0);
>>>> +static SUNXI_CCU_GATE_HWS(mbus_csi_clk, "mbus-csi", mbus_hws,
>>>> + 0x804, BIT(8), 0);
>>>> +static SUNXI_CCU_GATE_HWS(mbus_isp_clk, "mbus-isp", mbus_hws,
>>>> + 0x804, BIT(9), 0);
>>>> +static SUNXI_CCU_GATE_HWS(mbus_g2d_clk, "mbus-g2d", mbus_hws,
>>>> + 0x804, BIT(10), 0);
>>>> +
>>>> +static SUNXI_CCU_GATE_HWS(bus_dram_clk, "bus-dram", ahb_hws,
>>>> + 0x80c, BIT(0), CLK_IS_CRITICAL);
>>>> +
>>>> +
>>>> +static const struct clk_parent_data mmc0_mmc1_parents[] = {
>>>> + { .fw_name = "hosc" },
>>>> + { .hw = &pll_periph_400M_clk.hw, },
>>>> + { .hw = &pll_periph_300M_clk.hw, },
>>>> +};
>>>> +static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(mmc0_clk, "mmc0", mmc0_mmc1_parents, 0x830,
>>>> + 0, 4, /* M */
>>>> + 8, 2, /* P */
>>>> + 24, 3, /* mux */
>>>> + BIT(31), /* gate */
>>>> + 0);
>>>> +
>>>> +static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(mmc1_clk, "mmc1", mmc0_mmc1_parents, 0x834,
>>>> + 0, 4, /* M */
>>>> + 8, 2, /* P */
>>>> + 24, 3, /* mux */
>>>> + BIT(31), /* gate */
>>>> + 0);
>>>> +
>>>> +static const struct clk_parent_data mmc2_parents[] = {
>>>> + { .fw_name = "hosc" },
>>>> + { .hw = &pll_periph_600M_clk.hw, },
>>>> + { .hw = &pll_periph_400M_clk.hw, },
>>>> +};
>>>> +static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(mmc2_clk, "mmc2", mmc2_parents, 0x838,
>>>> + 0, 4, /* M */
>>>> + 8, 2, /* P */
>>>> + 24, 3, /* mux */
>>>> + BIT(31), /* gate */
>>>> + 0);
>>>> +
>>>> +static SUNXI_CCU_GATE_HWS(bus_mmc0_clk, "bus-mmc0", ahb_hws,
>>>> + 0x84c, BIT(0), 0);
>>>> +static SUNXI_CCU_GATE_HWS(bus_mmc1_clk, "bus-mmc1", ahb_hws,
>>>> + 0x84c, BIT(1), 0);
>>>> +static SUNXI_CCU_GATE_HWS(bus_mmc2_clk, "bus-mmc2", ahb_hws,
>>>> + 0x84c, BIT(2), 0);
>>>> +
>>>> +static SUNXI_CCU_GATE_HWS(bus_uart0_clk, "bus-uart0", apb1_hws,
>>>> + 0x90c, BIT(0), 0);
>>>> +static SUNXI_CCU_GATE_HWS(bus_uart1_clk, "bus-uart1", apb1_hws,
>>>> + 0x90c, BIT(1), 0);
>>>> +static SUNXI_CCU_GATE_HWS(bus_uart2_clk, "bus-uart2", apb1_hws,
>>>> + 0x90c, BIT(2), 0);
>>>> +static SUNXI_CCU_GATE_HWS(bus_uart3_clk, "bus-uart3", apb1_hws,
>>>> + 0x90c, BIT(3), 0);
>>>> +
>>>> +static SUNXI_CCU_GATE_HWS(bus_i2c0_clk, "bus-i2c0", apb1_hws,
>>>> + 0x91c, BIT(0), 0);
>>>> +static SUNXI_CCU_GATE_HWS(bus_i2c1_clk, "bus-i2c1", apb1_hws,
>>>> + 0x91c, BIT(1), 0);
>>>> +static SUNXI_CCU_GATE_HWS(bus_i2c2_clk, "bus-i2c2", apb1_hws,
>>>> + 0x91c, BIT(2), 0);
>>>> +static SUNXI_CCU_GATE_HWS(bus_i2c3_clk, "bus-i2c3", apb1_hws,
>>>> + 0x91c, BIT(3), 0);
>>>> +static SUNXI_CCU_GATE_HWS(bus_i2c4_clk, "bus-i2c4", apb1_hws,
>>>> + 0x91c, BIT(4), 0);
>>>> +
>>>> +static const struct clk_parent_data spi_parents[] = {
>>>> + { .fw_name = "hosc" },
>>>> + { .hw = &pll_periph_300M_clk.hw, },
>>>> + { .hw = &pll_periph_200M_clk.hw, },
>>>> +};
>>>> +
>>>> +static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(spi0_clk, "spi0", spi_parents, 0x940,
>>>> + 0, 4, /* M */
>>>> + 8, 2, /* P */
>>>> + 24, 3, /* mux */
>>>> + BIT(31), /* gate */
>>>> + 0);
>>>> +
>>>> +static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(spi1_clk, "spi1", spi_parents, 0x944,
>>>> + 0, 4, /* M */
>>>> + 8, 2, /* P */
>>>> + 24, 3, /* mux */
>>>> + BIT(31), /* gate */
>>>> + 0);
>>>> +
>>>> +static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(spi2_clk, "spi2", spi_parents, 0x948,
>>>> + 0, 4, /* M */
>>>> + 8, 2, /* P */
>>>> + 24, 3, /* mux */
>>>> + BIT(31), /* gate */
>>>> + 0);
>>>> +
>>>> +static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(spi3_clk, "spi3", spi_parents, 0x94c,
>>>> + 0, 4, /* M */
>>>> + 8, 2, /* P */
>>>> + 24, 3, /* mux */
>>>> + BIT(31), /* gate */
>>>> + 0);
>>>> +
>>>> +static SUNXI_CCU_GATE_HWS(bus_spi0_clk, "bus-spi0", ahb_hws,
>>>> + 0x96c, BIT(0), 0);
>>>> +static SUNXI_CCU_GATE_HWS(bus_spi1_clk, "bus-spi1", ahb_hws,
>>>> + 0x96c, BIT(1), 0);
>>>> +static SUNXI_CCU_GATE_HWS(bus_spi2_clk, "bus-spi2", ahb_hws,
>>>> + 0x96c, BIT(2), 0);
>>>> +static SUNXI_CCU_GATE_HWS(bus_spi3_clk, "bus-spi3", ahb_hws,
>>>> + 0x96c, BIT(3), 0);
>>>> +
>>>> +
>>>> +static const struct clk_parent_data spif_parents[] = {
>>>> + { .fw_name = "hosc" },
>>>> + { .hw = &pll_periph_400M_clk.hw, },
>>>> + { .hw = &pll_periph_300M_clk.hw, },
>>>> +};
>>>> +
>>>> +static SUNXI_CCU_M_DATA_WITH_MUX_GATE(spif_clk, "spif", spif_parents, 0x0950,
>>>> + 0, 4, /* M */
>>>> + 24, 3, /* mux */
>>>> + BIT(31), /* gate */
>>>> + CLK_SET_RATE_PARENT);
>>>> +
>>>> +static SUNXI_CCU_GATE_HWS(bus_spif_clk, "bus-spif", ahb_hws,
>>>> + 0x096c, BIT(4), 0);
>>>> +
>>>> +
>>>> +static const struct clk_hw *pll_periph_150M_hws[] = { &pll_periph_150M_clk.hw };
>>>> +static SUNXI_CCU_GATE_HWS_WITH_PREDIV(emac_25M_clk, "emac-25M", pll_periph_150M_hws,
>>>> + 0x970, BIT(31) | BIT(30), 6, 0);
>>>> +
>>>> +static SUNXI_CCU_GATE_HWS(bus_emac_clk, "bus-emac", ahb_hws,
>>>> + 0x97c, BIT(0), 0);
>>>> +
>>>> +static SUNXI_CCU_GATE_HWS(bus_gpadc_clk, "bus-gpadc", apb0_hws,
>>>> + 0x9ec, BIT(0), 0);
>>>> +
>>>> +static SUNXI_CCU_GATE_HWS(bus_ths_clk, "bus-ths", ahb_hws,
>>>> + 0x9fc, BIT(0), 0);
>>>> +
>>>> +
>>>> +static const struct clk_hw *audio_parents[] = {
>>>> + &pll_audio_1x_clk.common.hw,
>>>> + &pll_audio_4x_clk.common.hw,
>>>> +};
>>>> +
>>>> +static SUNXI_CCU_M_HW_WITH_MUX_GATE(i2s0_clk, "i2s0", audio_parents, 0xa10,
>>>> + 0, 4, /* M */
>>>> + 24, 1, /* mux */
>>>> + BIT(31), /* gate */
>>>> + CLK_SET_RATE_PARENT);
>>>> +
>>>> +static SUNXI_CCU_M_HW_WITH_MUX_GATE(i2s1_clk, "i2s1", audio_parents, 0xa14,
>>>> + 0, 4, /* M */
>>>> + 24, 1, /* mux */
>>>> + BIT(31), /* gate */
>>>> + CLK_SET_RATE_PARENT);
>>>> +
>>>> +static SUNXI_CCU_GATE_HWS(bus_i2s1_clk, "bus-i2s1", ahb_hws,
>>>> + 0xa20, BIT(1), 0);
>>>> +
>>>
>>> Just a nit, but those two here v and ^ seem to be swapped.
>>>
>>
>> Thanks.
>>
>>> For the records: I extracted the bus gates and massaged them with some
>>> regexps to bring them into a shape where review is more feasible.
>>> They look alright to me. I didn't look at the respective mod clocks in
>>> detail, though.
>>>
>>>
>>>> +static SUNXI_CCU_GATE_HWS(bus_i2s0_clk, "bus-i2s0", ahb_hws,
>>>> + 0xa20, BIT(0), 0);
>>>> +
>>>> +static SUNXI_CCU_M_HW_WITH_MUX_GATE(dmic_clk, "dmic", audio_parents, 0xa40,
>>>> + 0, 4, /* M */
>>>> + 24, 1, /* mux */
>>>> + BIT(31), /* gate */
>>>> + CLK_SET_RATE_PARENT);
>>>> +
>>>> +static SUNXI_CCU_GATE_HWS(bus_dmic_clk, "bus-dmic", ahb_hws,
>>>> + 0xa4c, BIT(0), 0);
>>>> +
>>>> +static SUNXI_CCU_M_HW_WITH_MUX_GATE(audio_codec_dac_clk, "audio-codec-dac", audio_parents, 0xa50,
>>>
>>> I think you should break the line above, to stay within the 80 char
>>> limit.
>>>
>>
>> Ok.
>>
>>> Fast forwarding to the ccu_resets array ...
>>>
>>>> + 0, 4, /* M */
>>>> + 24, 1, /* mux */
>>>> + BIT(31), /* gate */
>>>> + CLK_SET_RATE_PARENT);
>>>> +
>>>> +static SUNXI_CCU_M_HW_WITH_MUX_GATE(audio_codec_adc_clk, "audio-codec-adc", audio_parents, 0xa54,
>>>> + 0, 4, /* M */
>>>> + 24, 1, /* mux */
>>>> + BIT(31), /* gate */
>>>> + CLK_SET_RATE_PARENT);
>>>> +
>>>> +static SUNXI_CCU_GATE_HWS(bus_audio_codec_clk, "bus-audio-codec", apb0_hws,
>>>> + 0xa5c, BIT(0), 0);
>>>> +
>>>> +/*
>>>> + * There are OHCI 12M clock source selection bits for the USB 2.0 port.
>>>> + * We will force them to 0 (12M divided from 48M).
>>>> + */
>>>> +static CLK_FIXED_FACTOR_FW_NAME(osc12M_clk, "osc12M", "hosc", 2, 1, 0);
>>>> +
>>>> +#define SUN8I_V853_USB_CLK_REG 0xa70
>>>> +
>>>> +static SUNXI_CCU_GATE(usb_ohci_clk, "usb", "osc12M", 0x0a70, BIT(31), 0);
>>>> +
>>>> +static SUNXI_CCU_GATE_HWS(bus_ohci_clk, "bus-ohci", ahb_hws, 0xa8c, BIT(0), 0);
>>>> +static SUNXI_CCU_GATE_HWS(bus_ehci_clk, "bus-ehci", ahb_hws, 0xa8c, BIT(4), 0);
>>>> +static SUNXI_CCU_GATE_HWS(bus_otg_clk, "bus-otg", ahb_hws, 0xa8c, BIT(8), 0);
>>>> +
>>>> +static SUNXI_CCU_GATE_HWS(bus_dpss_top_clk, "bus-dpss-top", ahb_hws,
>>>> + 0xabc, BIT(0), 0);
>>>> +
>>>> +
>>>> +static const struct clk_parent_data mipi_dsi_parents[] = {
>>>> + { .fw_name = "hosc" },
>>>> + { .hw = &pll_periph_200M_clk.hw },
>>>> + { .hw = &pll_periph_150M_clk.hw },
>>>> +};
>>>> +static SUNXI_CCU_M_DATA_WITH_MUX_GATE(mipi_dsi_clk, "mipi-dsi", mipi_dsi_parents, 0xb24,
>>>> + 0, 4, /* M */
>>>> + 24, 3, /* mux */
>>>> + BIT(31), /* gate */
>>>> + CLK_SET_RATE_PARENT);
>>>> +
>>>> +static SUNXI_CCU_GATE_HWS(bus_mipi_dsi_clk, "bus-mipi-dsi", ahb_hws,
>>>> + 0xb4c, BIT(0), 0);
>>>> +
>>>> +
>>>> +static const struct clk_hw *tcon_lcd_parents[] = {
>>>> + &pll_video_4x_clk.common.hw,
>>>> + &pll_periph_2x_clk.common.hw,
>>>> + &pll_csi_4x_clk.common.hw,
>>>> +};
>>>> +static SUNXI_CCU_MP_HW_WITH_MUX_GATE(tcon_lcd_clk, "tcon-lcd", tcon_lcd_parents, 0xb60,
>>>> + 0, 4, /* M */
>>>> + 8, 2, /* P */
>>>> + 24, 3, /* mux */
>>>> + BIT(31), /* gate */
>>>> + CLK_SET_RATE_PARENT);
>>>> +
>>>> +static SUNXI_CCU_GATE_HWS(bus_tcon_lcd_clk, "bus-tcon-lcd", ahb_hws,
>>>> + 0xb7c, BIT(0), 0);
>>>> +
>>>> +
>>>> +static const struct clk_hw *csi_top_parents[] = {
>>>> + &pll_periph_300M_clk.hw,
>>>> + &pll_periph_400M_clk.hw,
>>>> + &pll_video_4x_clk.common.hw,
>>>> + &pll_csi_4x_clk.common.hw,
>>>> +};
>>>> +static SUNXI_CCU_M_HW_WITH_MUX_GATE(csi_top_clk, "csi-top", csi_top_parents, 0xc04,
>>>> + 0, 5, /* M */
>>>> + 24, 3, /* mux */
>>>> + BIT(31), /* gate */
>>>> + 0);
>>>> +
>>>> +
>>>> +static const struct clk_parent_data csi_mclk_parents[] = {
>>>> + { .fw_name = "hosc" },
>>>> + { .hw = &pll_csi_4x_clk.common.hw },
>>>> + { .hw = &pll_video_4x_clk.common.hw },
>>>> + { .hw = &pll_periph_2x_clk.common.hw },
>>>> +};
>>>> +static SUNXI_CCU_M_DATA_WITH_MUX_GATE(csi_mclk0_clk, "csi-mclk0", csi_mclk_parents, 0xc08,
>>>> + 0, 5, /* M */
>>>> + 24, 3, /* mux */
>>>> + BIT(31), /* gate */
>>>> + 0);
>>>> +
>>>> +static SUNXI_CCU_M_DATA_WITH_MUX_GATE(csi_mclk1_clk, "csi-mclk1", csi_mclk_parents, 0xc0c,
>>>> + 0, 5, /* M */
>>>> + 24, 3, /* mux */
>>>> + BIT(31), /* gate */
>>>> + 0);
>>>> +
>>>> +static SUNXI_CCU_M_DATA_WITH_MUX_GATE(csi_mclk2_clk, "csi-mclk2", csi_mclk_parents, 0xc10,
>>>> + 0, 5, /* M */
>>>> + 24, 3, /* mux */
>>>> + BIT(31), /* gate */
>>>> + 0);
>>>> +
>>>> +static SUNXI_CCU_GATE_HWS(bus_csi_clk, "bus-csi", ahb_hws,
>>>> + 0xc2c, BIT(0), 0);
>>>> +
>>>> +
>>>> +static SUNXI_CCU_GATE_HWS(bus_wiegand_clk, "bus-wiegand", ahb_hws,
>>>> + 0xc7c, BIT(0), 0);
>>>> +
>>>> +
>>>> +static const struct clk_parent_data riscv_parents[] = {
>>>> + { .fw_name = "hosc" },
>>>> + { .fw_name = "losc" },
>>>> + { .fw_name = "iosc" },
>>>> + { .hw = &pll_periph_600M_clk.hw },
>>>> + { .hw = &pll_periph_480M_clk.common.hw },
>>>> + { .hw = &pll_cpu_clk.common.hw },
>>>> +};
>>>> +static SUNXI_CCU_M_DATA_WITH_MUX(riscv_clk, "riscv-cpu", riscv_parents, 0xd00,
>>>> + 0, 5, /* M */
>>>> + 24, 3, /* mux */
>>>> + CLK_SET_RATE_PARENT);
>>>> +
>>>> +/* The riscv-axi clk must be divided by at least 2. */
>>>> +static struct clk_div_table riscv_axi_table[] = {
>>>> + { .val = 1, .div = 2 },
>>>> + { .val = 2, .div = 3 },
>>>> + { .val = 3, .div = 4 },
>>>> + { /* Sentinel */ }
>>>> +};
>>>> +static SUNXI_CCU_DIV_TABLE_HW(riscv_axi_clk, "riscv-axi", &riscv_clk.common.hw,
>>>> + 0xd00, 8, 2, riscv_axi_table, 0);
>>>> +
>>>> +
>>>> +static SUNXI_CCU_GATE_HWS(riscv_cfg, "riscv-cfg", ahb_hws,
>>>> + 0xd0c, BIT(0), 0);
>>>> +
>>>> +static const struct clk_hw *pll_periph_160M_hws[] = {
>>>> + &pll_periph_160M_clk.hw,
>>>> +};
>>>> +
>>>> +static SUNXI_CCU_GATE_DATA(fanout_24M_clk, "fanout-24M", osc24M,
>>>> + 0xf30, BIT(0), 0);
>>>> +static SUNXI_CCU_GATE_DATA_WITH_PREDIV(fanout_12M_clk, "fanout-12M", osc24M,
>>>> + 0xf30, BIT(1), 2, 0);
>>>> +static SUNXI_CCU_GATE_HWS_WITH_PREDIV(fanout_16M_clk, "fanout-16M", pll_periph_160M_hws,
>>>> + 0xf30, BIT(2), 10, 0);
>>>> +static SUNXI_CCU_GATE_HWS_WITH_PREDIV(fanout_25M_clk, "fanout-25M", pll_periph_150M_hws,
>>>> + 0xf30, BIT(3), 6, 0);
>>>> +
>>>> +
>>>> +
>>>> +/* This clock has a second divider that is not modelled and forced to 0. */
>>>> +#define SUN8I_V853_FANOUT_27M_REG 0xf34
>>>> +static const struct clk_hw *fanout_27M_parents[] = {
>>>> + &pll_video_1x_clk.hw,
>>>> + &pll_csi_clk.hw,
>>>> + &pll_periph_300M_clk.hw,
>>>> +};
>>>> +static SUNXI_CCU_M_HW_WITH_MUX_GATE(fanout_27M_clk, "fanout-27M", fanout_27M_parents, 0xf34,
>>>> + 0, 5, /* M */
>>>> + 24, 2, /* mux */
>>>> + BIT(31), /* gate */
>>>> + 0);
>>>> +static SUNXI_CCU_M_HWS_WITH_GATE(fanout_pclk_clk, "fanout-pclk", apb0_hws, 0xf38,
>>>> + 0, 5, /* M */
>>>> + BIT(31), /* gate */
>>>> + 0);
>>>> +
>>>> +static const struct clk_parent_data fanout_parents[] = {
>>>> + { .fw_name = "losc" },
>>>> + { .hw = &fanout_12M_clk.common.hw },
>>>> + { .hw = &fanout_16M_clk.common.hw },
>>>> + { .hw = &fanout_24M_clk.common.hw },
>>>> + { .hw = &fanout_25M_clk.common.hw },
>>>> + { .hw = &fanout_27M_clk.common.hw },
>>>> + { .hw = &fanout_pclk_clk.common.hw },
>>>> +};
>>>> +
>>>> +static SUNXI_CCU_MUX_DATA_WITH_GATE(fanout0_clk, "fanout0", fanout_parents, 0xf3c,
>>>> + 0, 3, /* mux */
>>>> + BIT(21), /* gate */
>>>> + 0);
>>>> +static SUNXI_CCU_MUX_DATA_WITH_GATE(fanout1_clk, "fanout1", fanout_parents, 0xf3c,
>>>> + 3, 3, /* mux */
>>>> + BIT(22), /* gate */
>>>> + 0);
>>>> +static SUNXI_CCU_MUX_DATA_WITH_GATE(fanout2_clk, "fanout2", fanout_parents, 0xf3c,
>>>> + 6, 3, /* mux */
>>>> + BIT(23), /* gate */
>>>> + 0);
>>>> +
>>>> +
>>>> +static struct ccu_common *sun8i_v853_ccu_clks[] = {
>>>> + &pll_cpu_clk.common,
>>>> + &pll_ddr_clk.common,
>>>> + &pll_periph_4x_clk.common,
>>>> + &pll_periph_2x_clk.common,
>>>> + &pll_periph_800M_clk.common,
>>>> + &pll_periph_480M_clk.common,
>>>> + &pll_video_4x_clk.common,
>>>> + &pll_csi_4x_clk.common,
>>>> + &pll_audio_div2_clk.common,
>>>> + &pll_audio_div5_clk.common,
>>>> + &pll_audio_4x_clk.common,
>>>> + &pll_audio_1x_clk.common,
>>>> + &pll_npu_4x_clk.common,
>>>> + &cpu_clk.common,
>>>> + &cpu_axi_clk.common,
>>>> + &cpu_apb_clk.common,
>>>> + &ahb_clk.common,
>>>> + &apb0_clk.common,
>>>> + &apb1_clk.common,
>>>> + &de_clk.common,
>>>> + &bus_de_clk.common,
>>>> + &g2d_clk.common,
>>>> + &bus_g2d_clk.common,
>>>> + &ce_clk.common,
>>>> + &bus_ce_clk.common,
>>>> + &ve_clk.common,
>>>> + &bus_ve_clk.common,
>>>> + &npu_clk.common,
>>>> + &bus_npu_clk.common,
>>>> + &bus_dma_clk.common,
>>>> + &bus_msgbox0_clk.common,
>>>> + &bus_msgbox1_clk.common,
>>>> + &bus_spinlock_clk.common,
>>>> + &bus_hstimer_clk.common,
>>>> + &avs_clk.common,
>>>> + &bus_dbg_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_csi_clk.common,
>>>> + &mbus_isp_clk.common,
>>>> + &mbus_g2d_clk.common,
>>>> + &bus_dram_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_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,
>>>> + &spi2_clk.common,
>>>> + &spi3_clk.common,
>>>> + &bus_spi0_clk.common,
>>>> + &bus_spi1_clk.common,
>>>> + &bus_spi2_clk.common,
>>>> + &bus_spi3_clk.common,
>>>> + &spif_clk.common,
>>>> + &bus_spif_clk.common,
>>>> + &emac_25M_clk.common,
>>>> + &bus_emac_clk.common,
>>>> + &bus_gpadc_clk.common,
>>>> + &bus_ths_clk.common,
>>>> + &usb_ohci_clk.common,
>>>> + &bus_ohci_clk.common,
>>>> + &bus_ehci_clk.common,
>>>> + &bus_otg_clk.common,
>>>> + &i2s0_clk.common,
>>>> + &i2s1_clk.common,
>>>> + &bus_i2s0_clk.common,
>>>> + &bus_i2s1_clk.common,
>>>> + &dmic_clk.common,
>>>> + &bus_dmic_clk.common,
>>>> + &audio_codec_dac_clk.common,
>>>> + &audio_codec_adc_clk.common,
>>>> + &bus_audio_codec_clk.common,
>>>> + &bus_dpss_top_clk.common,
>>>> + &mipi_dsi_clk.common,
>>>> + &bus_mipi_dsi_clk.common,
>>>> + &tcon_lcd_clk.common,
>>>> + &bus_tcon_lcd_clk.common,
>>>> + &csi_top_clk.common,
>>>> + &csi_mclk0_clk.common,
>>>> + &csi_mclk1_clk.common,
>>>> + &csi_mclk2_clk.common,
>>>> + &bus_csi_clk.common,
>>>> + &bus_wiegand_clk.common,
>>>> + &riscv_clk.common,
>>>> + &riscv_axi_clk.common,
>>>> + &riscv_cfg.common,
>>>> + &fanout_24M_clk.common,
>>>> + &fanout_12M_clk.common,
>>>> + &fanout_16M_clk.common,
>>>> + &fanout_25M_clk.common,
>>>> + &fanout_27M_clk.common,
>>>> + &fanout_pclk_clk.common,
>>>> + &fanout0_clk.common,
>>>> + &fanout1_clk.common,
>>>> + &fanout2_clk.common,
>>>> +};
>>>> +
>>>> +static struct clk_hw_onecell_data sun8i_v853_hw_clks = {
>>>> + .num = CLK_NUMBER,
>>>> + .hws = {
>>>> + [CLK_OSC12M] = &osc12M_clk.hw,
>>>> + [CLK_PLL_CPU] = &pll_cpu_clk.common.hw,
>>>> + [CLK_PLL_DDR] = &pll_ddr_clk.common.hw,
>>>> + [CLK_PLL_PERIPH_4X] = &pll_periph_4x_clk.common.hw,
>>>> + [CLK_PLL_PERIPH_2X] = &pll_periph_2x_clk.common.hw,
>>>> + [CLK_PLL_PERIPH_800M] = &pll_periph_800M_clk.common.hw,
>>>> + [CLK_PLL_PERIPH_480M] = &pll_periph_480M_clk.common.hw,
>>>> + [CLK_PLL_PERIPH_600M] = &pll_periph_600M_clk.hw,
>>>> + [CLK_PLL_PERIPH_400M] = &pll_periph_400M_clk.hw,
>>>> + [CLK_PLL_PERIPH_300M] = &pll_periph_300M_clk.hw,
>>>> + [CLK_PLL_PERIPH_200M] = &pll_periph_200M_clk.hw,
>>>> + [CLK_PLL_PERIPH_160M] = &pll_periph_160M_clk.hw,
>>>> + [CLK_PLL_PERIPH_150M] = &pll_periph_150M_clk.hw,
>>>> + [CLK_PLL_VIDEO_4X] = &pll_video_4x_clk.common.hw,
>>>> + [CLK_PLL_VIDEO_2X] = &pll_video_2x_clk.hw,
>>>> + [CLK_PLL_VIDEO_1X] = &pll_video_1x_clk.hw,
>>>> + [CLK_PLL_CSI_4X] = &pll_csi_4x_clk.common.hw,
>>>> + [CLK_PLL_AUDIO_DIV2] = &pll_audio_div2_clk.common.hw,
>>>> + [CLK_PLL_AUDIO_DIV5] = &pll_audio_div5_clk.common.hw,
>>>> + [CLK_PLL_AUDIO_4X] = &pll_audio_4x_clk.common.hw,
>>>> + [CLK_PLL_AUDIO_1X] = &pll_audio_1x_clk.common.hw,
>>>> + [CLK_PLL_NPU_4X] = &pll_npu_4x_clk.common.hw,
>>>> + [CLK_CPU] = &cpu_clk.common.hw,
>>>> + [CLK_CPU_AXI] = &cpu_axi_clk.common.hw,
>>>> + [CLK_CPU_APB] = &cpu_apb_clk.common.hw,
>>>> + [CLK_AHB] = &ahb_clk.common.hw,
>>>> + [CLK_APB0] = &apb0_clk.common.hw,
>>>> + [CLK_APB1] = &apb1_clk.common.hw,
>>>> + [CLK_MBUS] = &mbus_clk.hw,
>>>> + [CLK_DE] = &de_clk.common.hw,
>>>> + [CLK_BUS_DE] = &bus_de_clk.common.hw,
>>>> + [CLK_G2D] = &g2d_clk.common.hw,
>>>> + [CLK_BUS_G2D] = &bus_g2d_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_NPU] = &npu_clk.common.hw,
>>>> + [CLK_BUS_NPU] = &bus_npu_clk.common.hw,
>>>> + [CLK_BUS_DMA] = &bus_dma_clk.common.hw,
>>>> + [CLK_BUS_MSGBOX0] = &bus_msgbox0_clk.common.hw,
>>>> + [CLK_BUS_MSGBOX1] = &bus_msgbox1_clk.common.hw,
>>>> + [CLK_BUS_SPINLOCK] = &bus_spinlock_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_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_CSI] = &mbus_csi_clk.common.hw,
>>>> + [CLK_MBUS_ISP] = &mbus_isp_clk.common.hw,
>>>> + [CLK_MBUS_G2D] = &mbus_g2d_clk.common.hw,
>>>> + [CLK_BUS_DRAM] = &bus_dram_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_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_SPI2] = &spi2_clk.common.hw,
>>>> + [CLK_SPI3] = &spi3_clk.common.hw,
>>>> + [CLK_BUS_SPI0] = &bus_spi0_clk.common.hw,
>>>> + [CLK_BUS_SPI1] = &bus_spi1_clk.common.hw,
>>>> + [CLK_BUS_SPI2] = &bus_spi2_clk.common.hw,
>>>> + [CLK_BUS_SPI3] = &bus_spi3_clk.common.hw,
>>>> + [CLK_SPIF] = &spif_clk.common.hw,
>>>> + [CLK_BUS_SPIF] = &bus_spif_clk.common.hw,
>>>> + [CLK_EMAC_25M] = &emac_25M_clk.common.hw,
>>>> + [CLK_BUS_EMAC] = &bus_emac_clk.common.hw,
>>>> + [CLK_BUS_GPADC] = &bus_gpadc_clk.common.hw,
>>>> + [CLK_BUS_THS] = &bus_ths_clk.common.hw,
>>>> + [CLK_I2S0] = &i2s0_clk.common.hw,
>>>> + [CLK_I2S1] = &i2s1_clk.common.hw,
>>>> + [CLK_BUS_I2S0] = &bus_i2s0_clk.common.hw,
>>>> + [CLK_BUS_I2S1] = &bus_i2s1_clk.common.hw,
>>>> + [CLK_DMIC] = &dmic_clk.common.hw,
>>>> + [CLK_BUS_DMIC] = &bus_dmic_clk.common.hw,
>>>> + [CLK_AUDIO_CODEC_DAC] = &audio_codec_dac_clk.common.hw,
>>>> + [CLK_AUDIO_CODEC_ADC] = &audio_codec_adc_clk.common.hw,
>>>> + [CLK_BUS_AUDIO_CODEC] = &bus_audio_codec_clk.common.hw,
>>>> + [CLK_USB_OHCI] = &usb_ohci_clk.common.hw,
>>>> + [CLK_BUS_OHCI] = &bus_ohci_clk.common.hw,
>>>> + [CLK_BUS_EHCI] = &bus_ehci_clk.common.hw,
>>>> + [CLK_BUS_OTG] = &bus_otg_clk.common.hw,
>>>> + [CLK_BUS_DPSS_TOP] = &bus_dpss_top_clk.common.hw,
>>>> + [CLK_MIPI_DSI] = &mipi_dsi_clk.common.hw,
>>>> + [CLK_BUS_MIPI_DSI] = &bus_mipi_dsi_clk.common.hw,
>>>> + [CLK_TCON_LCD] = &tcon_lcd_clk.common.hw,
>>>> + [CLK_BUS_TCON_LCD] = &bus_tcon_lcd_clk.common.hw,
>>>> + [CLK_CSI_TOP] = &csi_top_clk.common.hw,
>>>> + [CLK_CSI_MCLK0] = &csi_mclk0_clk.common.hw,
>>>> + [CLK_CSI_MCLK1] = &csi_mclk1_clk.common.hw,
>>>> + [CLK_CSI_MCLK2] = &csi_mclk2_clk.common.hw,
>>>> + [CLK_BUS_CSI] = &bus_csi_clk.common.hw,
>>>> + [CLK_BUS_WIEGAND] = &bus_wiegand_clk.common.hw,
>>>> + [CLK_RISCV] = &riscv_clk.common.hw,
>>>> + [CLK_RISCV_AXI] = &riscv_axi_clk.common.hw,
>>>> + [CLK_RISCV_CFG] = &riscv_cfg.common.hw,
>>>> + [CLK_FANOUT_24M] = &fanout_24M_clk.common.hw,
>>>> + [CLK_FANOUT_16M] = &fanout_16M_clk.common.hw,
>>>> + [CLK_FANOUT_12M] = &fanout_12M_clk.common.hw,
>>>> + [CLK_FANOUT_25M] = &fanout_25M_clk.common.hw,
>>>> + [CLK_FANOUT_27M] = &fanout_27M_clk.common.hw,
>>>> + [CLK_FANOUT_PCLK] = &fanout_pclk_clk.common.hw,
>>>> + [CLK_FANOUT0] = &fanout0_clk.common.hw,
>>>> + [CLK_FANOUT1] = &fanout1_clk.common.hw,
>>>> + [CLK_FANOUT2] = &fanout2_clk.common.hw,
>>>> + },
>>>> +};
>>>> +
>>>> +static struct ccu_reset_map sun8i_v853_ccu_resets[] = {
>>>> + [RST_MBUS] = { 0x540, BIT(30) },
>>>> + [RST_BUS_DE] = { 0x60c, BIT(16) },
>>>> + [RST_BUS_G2D] = { 0x63c, BIT(16) },
>>>> + [RST_BUS_CE] = { 0x68c, BIT(16) | BIT(17)},
>>>> + [RST_BUS_VE] = { 0x69c, BIT(16) },
>>>> + [RST_BUS_NPU] = { 0x6ec, BIT(16) },
>>>> + [RST_BUS_DMA] = { 0x70c, BIT(16) },
>>>> + [RST_BUS_MSGBOX0] = { 0x71c, BIT(16) },
>>>> + [RST_BUS_MSGBOX1] = { 0x71c, BIT(17) },
>>>> + [RST_BUS_SPINLOCK] = { 0x72c, BIT(16) },
>>>> + [RST_BUS_HSTIMER] = { 0x73c, BIT(16) },
>>>> + [RST_BUS_DBG] = { 0x78c, BIT(16) },
>>>> + [RST_BUS_PWM] = { 0x7ac, BIT(16) },
>>>> + [RST_BUS_DRAM] = { 0x80c, 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_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_SPIF] = { 0x96c, BIT(20) },
>>>
>>> That entry ^^^^ seems out of order.
>>
>> Opps, I’ll fix it.
>>
>>>
>>>> + [RST_BUS_SPI0] = { 0x96c, BIT(16) },
>>>> + [RST_BUS_SPI1] = { 0x96c, BIT(17) },
>>>> + [RST_BUS_SPI2] = { 0x96c, BIT(18) },
>>>> + [RST_BUS_SPI3] = { 0x96c, BIT(19) },
>>>> + [RST_BUS_EMAC] = { 0x97c, BIT(16) },
>>>> + [RST_BUS_GPADC] = { 0x9ec, BIT(16) },
>>>> + [RST_BUS_THS] = { 0x9fc, BIT(16) },
>>>> + [RST_BUS_I2S0] = { 0xa20, BIT(16) },
>>>> + [RST_BUS_I2S1] = { 0xa20, BIT(17) },
>>>> + [RST_BUS_DMIC] = { 0xa4c, BIT(16) },
>>>> + [RST_BUS_AUDIO_CODEC] = { 0xa5c, BIT(16) },
>>>> + [RST_USB_PHY] = { 0xa70, BIT(30) },
>>>> + [RST_BUS_OHCI] = { 0xa8c, BIT(16) },
>>>> + [RST_BUS_EHCI] = { 0xa8c, BIT(20) },
>>>> + [RST_BUS_OTG] = { 0xa8c, BIT(24) },
>>>> + [RST_BUS_DPSS_TOP] = { 0xabc, BIT(16) },
>>>> + [RST_BUS_MIPI_DSI] = { 0xb4c, BIT(16) },
>>>> + [RST_BUS_TCON_LCD] = { 0xb7c, BIT(16) },
>>>> + [RST_BUS_CSI] = { 0xc2c, BIT(16) },
>>>> + [RST_BUS_WIEGAND] = { 0xc7c, BIT(16) },
>>>> + [RST_RISCV_SYS_APB] = { 0xd04, BIT(2), CCU_FEATURE_KEY_FIELD },
>>>> + [RST_RISCV_SOFT] = { 0xd04, BIT(1), CCU_FEATURE_KEY_FIELD },
>>>> + [RST_RISCV_CLK_GATING] = { 0xd04, BIT(0), CCU_FEATURE_KEY_FIELD },
>>>
>>> But that's a clock gate, not a reset, right?
>>
>> Yes, I forget to fix that. Modelling this way (because of the KEY_FIELD) was faster
>> when I wrote the remoteproc driver.
>>
>>>
>>>> + [RST_RISCV_CFG] = { 0xd0c, BIT(16) }
>>>
>>> The rest of the reset bits match the manual.
>>>
>>>> +};
>>>> +
>>>> +static const struct sunxi_ccu_desc sun8i_v853_ccu_desc = {
>>>> + .ccu_clks = sun8i_v853_ccu_clks,
>>>> + .num_ccu_clks = ARRAY_SIZE(sun8i_v853_ccu_clks),
>>>> +
>>>> + .hw_clks = &sun8i_v853_hw_clks,
>>>> +
>>>> + .resets = sun8i_v853_ccu_resets,
>>>> + .num_resets = ARRAY_SIZE(sun8i_v853_ccu_resets),
>>>> +};
>>>> +
>>>> +static const u32 pll_regs[] = {
>>>> + SUN8I_V853_PLL_CPU_REG,
>>>> + SUN8I_V853_PLL_DDR_REG,
>>>> + SUN8I_V853_PLL_PERIPH_REG,
>>>> + SUN8I_V853_PLL_VIDEO_REG,
>>>> + SUN8I_V853_PLL_CSI_REG,
>>>> + SUN8I_V853_PLL_AUDIO_REG,
>>>> + SUN8I_V853_PLL_NPU_REG,
>>>> +};
>>>> +
>>>> +static int sun8i_v853_ccu_probe(struct platform_device *pdev)
>>>> +{
>>>> + void __iomem *reg;
>>>> + u32 val;
>>>> + int i, ret;
>>>> +
>>>> + reg = devm_platform_ioremap_resource(pdev, 0);
>>>> + if (IS_ERR(reg))
>>>> + return PTR_ERR(reg);
>>>> +
>>>> + /* Enable the enable, LDO, and lock bits on all PLLs. */
>>>> + for (i = 0; i < ARRAY_SIZE(pll_regs); i++) {
>>>> + val = readl(reg + pll_regs[i]);
>>>> + val |= BIT(31) | BIT(30) | BIT(29);
>>>> + writel(val, reg + pll_regs[i]);
>>>> + }
>>>> +
>>>> + /* Force PLL_CPU factor M to 0. */
>>>> + val = readl(reg + SUN8I_V853_PLL_CPU_REG);
>>>> + val &= ~GENMASK(1, 0);
>>>> + writel(val, reg + SUN8I_V853_PLL_CPU_REG);
>>>
>>> Let's just hope it was 0 already, as I guess a sudden jump of
>>> CPU frequency might not be too healthy.
>>>
>> I’ll double check that.
>>
>>>> + /*
>>>> + * Force the output divider of video PLL to 0.
>>>
>>> Just a nit, but a "divider of 0" does not sound too healthy. Maybe:
>>> "Force the output divider to 1, by clearing bit 0."
>>>
>>
>> Thanks.
>>
>>> Cheers,
>>> Andre
>>>
>>>> + *
>>>> + * See the comment before pll-video0 definition for the reason.
>>>> + */
>>>> + val = readl(reg + SUN8I_V853_PLL_VIDEO_REG);
>>>> + val &= ~BIT(0);
>>>> + writel(val, reg + SUN8I_V853_PLL_VIDEO_REG);
>>>> +
>>>> + /*
>>>> + * Force the output divider of CSI PLL to 0.
>>>> + *
>>>> + * See the comment before pll-csi definition for the reason.
>>>> + */
>>>> + val = readl(reg + SUN8I_V853_PLL_CSI_REG);
>>>> + val &= ~BIT(0);
>>>> + writel(val, reg + SUN8I_V853_PLL_CSI_REG);
>>>> +
>>>> + /*
>>>> + * Force the output divider of NPU PLL to 0.
>>>> + *
>>>> + * See the comment before pll-npu definition for the reason.
>>>> + */
>>>> + val = readl(reg + SUN8I_V853_PLL_NPU_REG);
>>>> + val &= ~BIT(0);
>>>> + writel(val, reg + SUN8I_V853_PLL_NPU_REG);
>>>> +
>>>> + /*
>>>> + * Force OHCI 12M clock source to 00 (12MHz divided from 48MHz)
>>>> + *
>>>> + * This clock mux is still mysterious, and the code just enforces
>>>> + * it to have a valid clock parent.
>>>> + */
>>>> + val = readl(reg + SUN8I_V853_USB_CLK_REG);
>>>> + val &= ~GENMASK(25, 24);
>>>> + writel(val, reg + SUN8I_V853_USB_CLK_REG);
>>>> +
>>>> + /* Force fanout-27M factor N to 0. */
>>>> + val = readl(reg + SUN8I_V853_FANOUT_27M_REG);
>>>> + val &= ~GENMASK(9, 8);
>>>> + writel(val, reg + SUN8I_V853_FANOUT_27M_REG);
>>>> +
>>>> + ret = devm_sunxi_ccu_probe(&pdev->dev, reg, &sun8i_v853_ccu_desc);
>>>> + if (ret)
>>>> + return ret;
>>>> +
>>>> + return 0;
>>>> +}
>>>> +
>>>> +static const struct of_device_id sun8i_v853_ccu_ids[] = {
>>>> + { .compatible = "allwinner,sun8i-v853-ccu" },
>>>> + { }
>>>> +};
>>>> +
>>>> +static struct platform_driver sun8i_v853_ccu_driver = {
>>>> + .probe = sun8i_v853_ccu_probe,
>>>> + .driver = {
>>>> + .name = "sun8i-v853-ccu",
>>>> + .suppress_bind_attrs = true,
>>>> + .of_match_table = sun8i_v853_ccu_ids,
>>>> + },
>>>> +};
>>>> +module_platform_driver(sun8i_v853_ccu_driver);
>>>> +
>>>> +MODULE_IMPORT_NS("SUNXI_CCU");
>>>> +MODULE_LICENSE("GPL");
>>>> diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-v853.h b/drivers/clk/sunxi-ng/ccu-sun8i-v853.h
>>>> new file mode 100644
>>>> index 000000000000..b6ee1764fe5e
>>>> --- /dev/null
>>>> +++ b/drivers/clk/sunxi-ng/ccu-sun8i-v853.h
>>>> @@ -0,0 +1,14 @@
>>>> +/* SPDX-License-Identifier: GPL-2.0 */
>>>> +/*
>>>> + * Copyright (C) 2024 Andras Szemzo <szemzo.andras@gmail.com>
>>>> + */
>>>> +
>>>> +#ifndef _CCU_SUN8I_V853_H_
>>>> +#define _CCU_SUN8I_V853_H_
>>>> +
>>>> +#include <dt-bindings/clock/sun8i-v853-ccu.h>
>>>> +#include <dt-bindings/reset/sun8i-v853-ccu.h>
>>>> +
>>>> +#define CLK_NUMBER (CLK_FANOUT2 + 1)
>>>> +
>>>> +#endif /* _CCU_SUN8I_V853_H_ */
>
^ permalink raw reply [flat|nested] 50+ messages in thread
end of thread, other threads:[~2025-01-29 7:31 UTC | newest]
Thread overview: 50+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-01-10 12:39 [PATCH 00/12] Support for Allwinner V853 SoC Andras Szemzo
2025-01-10 12:39 ` [PATCH 01/12] clk: sunxi-ng: allow key feature in ccu reset Andras Szemzo
2025-01-10 12:39 ` [PATCH 02/12] dt-bindings: pinctrl: sunxi: add compatible for V853 Andras Szemzo
2025-01-14 19:52 ` Rob Herring (Arm)
2025-01-16 9:08 ` Linus Walleij
2025-01-10 12:39 ` [PATCH 03/12] pinctrl: sunxi: add driver for Allwinner V853 Andras Szemzo
2025-01-14 14:14 ` Linus Walleij
2025-01-14 14:19 ` Andre Przywara
2025-01-14 14:30 ` Andre Przywara
2025-01-15 10:23 ` Linus Walleij
2025-01-15 15:26 ` Andre Przywara
2025-01-16 9:34 ` Linus Walleij
2025-01-17 7:25 ` András Szemző
2025-01-17 14:52 ` Andre Przywara
2025-01-22 13:30 ` Linus Walleij
2025-01-17 15:43 ` Chen-Yu Tsai
2025-01-10 12:39 ` [PATCH 04/12] dt-bindings: clock: sunxi-ng: add compatibles for V853 Andras Szemzo
2025-01-10 13:55 ` Krzysztof Kozlowski
2025-01-10 12:39 ` [PATCH 05/12] clk: sunxi-ng: add CCU drivers " Andras Szemzo
2025-01-22 23:23 ` Jeff Johnson
2025-01-23 8:58 ` András Szemző
2025-01-28 0:42 ` Andre Przywara
2025-01-28 9:06 ` András Szemző
2025-01-28 11:22 ` Andre Przywara
2025-01-29 7:29 ` András Szemző
2025-01-10 12:39 ` [PATCH 06/12] dt-bindings: clk: sunxi-ng: add V853 CCU clock/reset Andras Szemzo
2025-01-10 13:56 ` Krzysztof Kozlowski
2025-01-13 8:06 ` Chen-Yu Tsai
2025-01-13 8:21 ` Krzysztof Kozlowski
2025-01-13 8:45 ` Chen-Yu Tsai
2025-01-13 10:57 ` Andre Przywara
2025-01-13 11:15 ` Krzysztof Kozlowski
2025-01-11 10:34 ` Krzysztof Kozlowski
2025-01-13 7:02 ` András Szemző
2025-01-10 12:39 ` [PATCH 07/12] devicetree: bindings: power: add v853 ppu Andras Szemzo
2025-01-10 13:54 ` Krzysztof Kozlowski
2025-01-10 12:39 ` [PATCH 08/12] pmdomain: sunxi: add V853 ppu support Andras Szemzo
2025-01-10 12:39 ` [PATCH 09/12] dt-bindings: power: add V853 ppu bindings Andras Szemzo
2025-01-10 13:53 ` Krzysztof Kozlowski
2025-01-10 12:39 ` [PATCH 10/12] dt-bindings: phy: allwinner: add v853 usb phy Andras Szemzo
2025-01-10 13:39 ` Rob Herring (Arm)
2025-01-10 13:53 ` Krzysztof Kozlowski
2025-01-15 7:51 ` Vinod Koul
2025-01-17 7:26 ` András Szemző
2025-01-17 10:39 ` Andre Przywara
2025-01-10 12:39 ` [PATCH 11/12] phy: allwinner: add v853 usb phy compatible Andras Szemzo
2025-01-10 12:39 ` [PATCH 12/12] ARM: dts: sun8i: add DTSI file for V853 Andras Szemzo
2025-01-10 13:58 ` Krzysztof Kozlowski
2025-01-15 9:09 ` Csókás Bence
2025-01-15 9:43 ` Krzysztof Kozlowski
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).