linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [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).