All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 00/16] Basic StarFive JH7100 RISC-V SoC support
@ 2021-10-21 17:42 ` Emil Renner Berthing
  0 siblings, 0 replies; 143+ messages in thread
From: Emil Renner Berthing @ 2021-10-21 17:42 UTC (permalink / raw)
  To: linux-riscv, devicetree, linux-clk, linux-gpio, linux-serial
  Cc: Emil Renner Berthing, Palmer Dabbelt, Paul Walmsley, Rob Herring,
	Michael Turquette, Stephen Boyd, Thomas Gleixner, Marc Zyngier,
	Philipp Zabel, Linus Walleij, Greg Kroah-Hartman, Daniel Lezcano,
	Andy Shevchenko, Jiri Slaby, Maximilian Luz, Sagar Kadam,
	Drew Fustini, Geert Uytterhoeven, Michael Zhu, Fu Wei,
	Anup Patel, Atish Patra, Matteo Croce, linux-kernel

This series adds support for the StarFive JH7100 RISC-V SoC. The SoC has
many devices that need non-coherent dma operations to work which isn't
upstream yet[1], so this just adds basic support to boot up, get a
serial console, blink an LED and reboot itself. Unlike the Allwinner D1
this chip doesn't use any extra pagetable bits, but instead the DDR RAM
appears twice in the memory map, with and without the cache.

The JH7100 is a test chip for the upcoming JH7110 and about 300 BeagleV
Starlight Beta boards were sent out with them as part of a now cancelled
BeagleBoard.org project. However StarFive has produced more of the
JH7100s and more boards will be available[2] to buy. Hopefully before
the end of the year.

This series is also available at
https://github.com/esmil/linux/commits/starlight-minimal
..but a more complete kernel including drivers for non-coherent
peripherals based on this series can be found at
https://github.com/starfive-tech/linux/tree/starlight

[1]: https://lore.kernel.org/linux-riscv/20210723214031.3251801-2-atish.patra@wdc.com/
[2]: https://www.linkedin.com/pulse/starfive-release-open-source-single-board-platform-q3-2021-starfive/

/Emil

Changes since v1:
- Let SOC_STARFIVE select RESET_CONTROLLER but drop SERIAL_8250_DW
- Add missing Signed-of-by to clock dt-binding header
- Use builtin_platform_driver macro for the clock driver, add explicit
  comment to the determine_rate callback and other small nits from Andy
- Use reset-controller for node names in documentation and device tree
- Use readl_poll_timeout in reset driver to avoid hanging forever if a
  driver leaves the associated clock gated and sort Kconfig and Makefile
  entries properly.
- In the pinctrl driver align register names with documentation, remove
  invalid __init tag from probe function, use of_property_* functions to
  parse device tree, hoist pinmux unpacking into helper function to
  better document what's going on, bail on invalid signal group in
  device tree and fix many other nits from Andy.
- Refactor and rebase 8250_dw quirk on tty-next


Emil Renner Berthing (12):
  RISC-V: Add StarFive SoC Kconfig option
  dt-bindings: timer: Add StarFive JH7100 clint
  dt-bindings: interrupt-controller: Add StarFive JH7100 plic
  dt-bindings: reset: Add Starfive JH7100 reset bindings
  reset: starfive-jh7100: Add StarFive JH7100 reset driver
  dt-bindings: pinctrl: Add StarFive pinctrl definitions
  dt-bindings: pinctrl: Add StarFive JH7100 bindings
  pinctrl: starfive: Add pinctrl driver for StarFive SoCs
  dt-bindings: serial: snps-dw-apb-uart: Add JH7100 uarts
  serial: 8250_dw: Add skip_clk_set_rate quirk
  RISC-V: Add initial StarFive JH7100 device tree
  RISC-V: Add BeagleV Starlight Beta device tree

Geert Uytterhoeven (4):
  dt-bindings: clock: starfive: Add JH7100 clock definitions
  dt-bindings: clock: starfive: Add JH7100 bindings
  clk: starfive: Add JH7100 clock generator driver
  dt-bindings: reset: Add StarFive JH7100 reset definitions

 .../clock/starfive,jh7100-clkgen.yaml         |   56 +
 .../sifive,plic-1.0.0.yaml                    |    1 +
 .../pinctrl/starfive,jh7100-pinctrl.yaml      |  274 ++++
 .../bindings/reset/starfive,jh7100-reset.yaml |   38 +
 .../bindings/serial/snps-dw-apb-uart.yaml     |    5 +
 .../bindings/timer/sifive,clint.yaml          |    1 +
 MAINTAINERS                                   |   22 +
 arch/riscv/Kconfig.socs                       |    8 +
 arch/riscv/boot/dts/Makefile                  |    1 +
 arch/riscv/boot/dts/starfive/Makefile         |    2 +
 .../dts/starfive/jh7100-beaglev-starlight.dts |  162 ++
 arch/riscv/boot/dts/starfive/jh7100.dtsi      |  228 +++
 drivers/clk/Kconfig                           |    1 +
 drivers/clk/Makefile                          |    1 +
 drivers/clk/starfive/Kconfig                  |    9 +
 drivers/clk/starfive/Makefile                 |    3 +
 drivers/clk/starfive/clk-starfive-jh7100.c    |  776 +++++++++
 drivers/pinctrl/Kconfig                       |   16 +
 drivers/pinctrl/Makefile                      |    1 +
 drivers/pinctrl/pinctrl-starfive.c            | 1387 +++++++++++++++++
 drivers/reset/Kconfig                         |    8 +
 drivers/reset/Makefile                        |    1 +
 drivers/reset/reset-starfive-jh7100.c         |  165 ++
 drivers/tty/serial/8250/8250_dw.c             |   19 +-
 include/dt-bindings/clock/starfive-jh7100.h   |  202 +++
 .../dt-bindings/pinctrl/pinctrl-starfive.h    |  274 ++++
 include/dt-bindings/reset/starfive-jh7100.h   |  126 ++
 27 files changed, 3784 insertions(+), 3 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/starfive,jh7100-clkgen.yaml
 create mode 100644 Documentation/devicetree/bindings/pinctrl/starfive,jh7100-pinctrl.yaml
 create mode 100644 Documentation/devicetree/bindings/reset/starfive,jh7100-reset.yaml
 create mode 100644 arch/riscv/boot/dts/starfive/Makefile
 create mode 100644 arch/riscv/boot/dts/starfive/jh7100-beaglev-starlight.dts
 create mode 100644 arch/riscv/boot/dts/starfive/jh7100.dtsi
 create mode 100644 drivers/clk/starfive/Kconfig
 create mode 100644 drivers/clk/starfive/Makefile
 create mode 100644 drivers/clk/starfive/clk-starfive-jh7100.c
 create mode 100644 drivers/pinctrl/pinctrl-starfive.c
 create mode 100644 drivers/reset/reset-starfive-jh7100.c
 create mode 100644 include/dt-bindings/clock/starfive-jh7100.h
 create mode 100644 include/dt-bindings/pinctrl/pinctrl-starfive.h
 create mode 100644 include/dt-bindings/reset/starfive-jh7100.h

-- 
2.33.1


^ permalink raw reply	[flat|nested] 143+ messages in thread

* [PATCH v2 00/16] Basic StarFive JH7100 RISC-V SoC support
@ 2021-10-21 17:42 ` Emil Renner Berthing
  0 siblings, 0 replies; 143+ messages in thread
From: Emil Renner Berthing @ 2021-10-21 17:42 UTC (permalink / raw)
  To: linux-riscv, devicetree, linux-clk, linux-gpio, linux-serial
  Cc: Emil Renner Berthing, Palmer Dabbelt, Paul Walmsley, Rob Herring,
	Michael Turquette, Stephen Boyd, Thomas Gleixner, Marc Zyngier,
	Philipp Zabel, Linus Walleij, Greg Kroah-Hartman, Daniel Lezcano,
	Andy Shevchenko, Jiri Slaby, Maximilian Luz, Sagar Kadam,
	Drew Fustini, Geert Uytterhoeven, Michael Zhu, Fu Wei,
	Anup Patel, Atish Patra, Matteo Croce, linux-kernel

This series adds support for the StarFive JH7100 RISC-V SoC. The SoC has
many devices that need non-coherent dma operations to work which isn't
upstream yet[1], so this just adds basic support to boot up, get a
serial console, blink an LED and reboot itself. Unlike the Allwinner D1
this chip doesn't use any extra pagetable bits, but instead the DDR RAM
appears twice in the memory map, with and without the cache.

The JH7100 is a test chip for the upcoming JH7110 and about 300 BeagleV
Starlight Beta boards were sent out with them as part of a now cancelled
BeagleBoard.org project. However StarFive has produced more of the
JH7100s and more boards will be available[2] to buy. Hopefully before
the end of the year.

This series is also available at
https://github.com/esmil/linux/commits/starlight-minimal
..but a more complete kernel including drivers for non-coherent
peripherals based on this series can be found at
https://github.com/starfive-tech/linux/tree/starlight

[1]: https://lore.kernel.org/linux-riscv/20210723214031.3251801-2-atish.patra@wdc.com/
[2]: https://www.linkedin.com/pulse/starfive-release-open-source-single-board-platform-q3-2021-starfive/

/Emil

Changes since v1:
- Let SOC_STARFIVE select RESET_CONTROLLER but drop SERIAL_8250_DW
- Add missing Signed-of-by to clock dt-binding header
- Use builtin_platform_driver macro for the clock driver, add explicit
  comment to the determine_rate callback and other small nits from Andy
- Use reset-controller for node names in documentation and device tree
- Use readl_poll_timeout in reset driver to avoid hanging forever if a
  driver leaves the associated clock gated and sort Kconfig and Makefile
  entries properly.
- In the pinctrl driver align register names with documentation, remove
  invalid __init tag from probe function, use of_property_* functions to
  parse device tree, hoist pinmux unpacking into helper function to
  better document what's going on, bail on invalid signal group in
  device tree and fix many other nits from Andy.
- Refactor and rebase 8250_dw quirk on tty-next


Emil Renner Berthing (12):
  RISC-V: Add StarFive SoC Kconfig option
  dt-bindings: timer: Add StarFive JH7100 clint
  dt-bindings: interrupt-controller: Add StarFive JH7100 plic
  dt-bindings: reset: Add Starfive JH7100 reset bindings
  reset: starfive-jh7100: Add StarFive JH7100 reset driver
  dt-bindings: pinctrl: Add StarFive pinctrl definitions
  dt-bindings: pinctrl: Add StarFive JH7100 bindings
  pinctrl: starfive: Add pinctrl driver for StarFive SoCs
  dt-bindings: serial: snps-dw-apb-uart: Add JH7100 uarts
  serial: 8250_dw: Add skip_clk_set_rate quirk
  RISC-V: Add initial StarFive JH7100 device tree
  RISC-V: Add BeagleV Starlight Beta device tree

Geert Uytterhoeven (4):
  dt-bindings: clock: starfive: Add JH7100 clock definitions
  dt-bindings: clock: starfive: Add JH7100 bindings
  clk: starfive: Add JH7100 clock generator driver
  dt-bindings: reset: Add StarFive JH7100 reset definitions

 .../clock/starfive,jh7100-clkgen.yaml         |   56 +
 .../sifive,plic-1.0.0.yaml                    |    1 +
 .../pinctrl/starfive,jh7100-pinctrl.yaml      |  274 ++++
 .../bindings/reset/starfive,jh7100-reset.yaml |   38 +
 .../bindings/serial/snps-dw-apb-uart.yaml     |    5 +
 .../bindings/timer/sifive,clint.yaml          |    1 +
 MAINTAINERS                                   |   22 +
 arch/riscv/Kconfig.socs                       |    8 +
 arch/riscv/boot/dts/Makefile                  |    1 +
 arch/riscv/boot/dts/starfive/Makefile         |    2 +
 .../dts/starfive/jh7100-beaglev-starlight.dts |  162 ++
 arch/riscv/boot/dts/starfive/jh7100.dtsi      |  228 +++
 drivers/clk/Kconfig                           |    1 +
 drivers/clk/Makefile                          |    1 +
 drivers/clk/starfive/Kconfig                  |    9 +
 drivers/clk/starfive/Makefile                 |    3 +
 drivers/clk/starfive/clk-starfive-jh7100.c    |  776 +++++++++
 drivers/pinctrl/Kconfig                       |   16 +
 drivers/pinctrl/Makefile                      |    1 +
 drivers/pinctrl/pinctrl-starfive.c            | 1387 +++++++++++++++++
 drivers/reset/Kconfig                         |    8 +
 drivers/reset/Makefile                        |    1 +
 drivers/reset/reset-starfive-jh7100.c         |  165 ++
 drivers/tty/serial/8250/8250_dw.c             |   19 +-
 include/dt-bindings/clock/starfive-jh7100.h   |  202 +++
 .../dt-bindings/pinctrl/pinctrl-starfive.h    |  274 ++++
 include/dt-bindings/reset/starfive-jh7100.h   |  126 ++
 27 files changed, 3784 insertions(+), 3 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/starfive,jh7100-clkgen.yaml
 create mode 100644 Documentation/devicetree/bindings/pinctrl/starfive,jh7100-pinctrl.yaml
 create mode 100644 Documentation/devicetree/bindings/reset/starfive,jh7100-reset.yaml
 create mode 100644 arch/riscv/boot/dts/starfive/Makefile
 create mode 100644 arch/riscv/boot/dts/starfive/jh7100-beaglev-starlight.dts
 create mode 100644 arch/riscv/boot/dts/starfive/jh7100.dtsi
 create mode 100644 drivers/clk/starfive/Kconfig
 create mode 100644 drivers/clk/starfive/Makefile
 create mode 100644 drivers/clk/starfive/clk-starfive-jh7100.c
 create mode 100644 drivers/pinctrl/pinctrl-starfive.c
 create mode 100644 drivers/reset/reset-starfive-jh7100.c
 create mode 100644 include/dt-bindings/clock/starfive-jh7100.h
 create mode 100644 include/dt-bindings/pinctrl/pinctrl-starfive.h
 create mode 100644 include/dt-bindings/reset/starfive-jh7100.h

-- 
2.33.1


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 143+ messages in thread

* [PATCH v2 01/16] RISC-V: Add StarFive SoC Kconfig option
  2021-10-21 17:42 ` Emil Renner Berthing
@ 2021-10-21 17:42   ` Emil Renner Berthing
  -1 siblings, 0 replies; 143+ messages in thread
From: Emil Renner Berthing @ 2021-10-21 17:42 UTC (permalink / raw)
  To: linux-riscv, devicetree, linux-clk, linux-gpio, linux-serial
  Cc: Emil Renner Berthing, Palmer Dabbelt, Paul Walmsley, Rob Herring,
	Michael Turquette, Stephen Boyd, Thomas Gleixner, Marc Zyngier,
	Philipp Zabel, Linus Walleij, Greg Kroah-Hartman, Daniel Lezcano,
	Andy Shevchenko, Jiri Slaby, Maximilian Luz, Sagar Kadam,
	Drew Fustini, Geert Uytterhoeven, Michael Zhu, Fu Wei,
	Anup Patel, Atish Patra, Matteo Croce, linux-kernel

Add StarFive Kconfig option to select SoC specific and common drivers
required for these SoCs.

Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
---
 arch/riscv/Kconfig.socs | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs
index 30676ebb16eb..6ec44a22278a 100644
--- a/arch/riscv/Kconfig.socs
+++ b/arch/riscv/Kconfig.socs
@@ -19,6 +19,14 @@ config SOC_SIFIVE
 	help
 	  This enables support for SiFive SoC platform hardware.
 
+config SOC_STARFIVE
+	bool "StarFive SoCs"
+	select PINCTRL
+	select RESET_CONTROLLER
+	select SIFIVE_PLIC
+	help
+	  This enables support for StarFive SoC platform hardware.
+
 config SOC_VIRT
 	bool "QEMU Virt Machine"
 	select CLINT_TIMER if RISCV_M_MODE
-- 
2.33.1


^ permalink raw reply related	[flat|nested] 143+ messages in thread

* [PATCH v2 01/16] RISC-V: Add StarFive SoC Kconfig option
@ 2021-10-21 17:42   ` Emil Renner Berthing
  0 siblings, 0 replies; 143+ messages in thread
From: Emil Renner Berthing @ 2021-10-21 17:42 UTC (permalink / raw)
  To: linux-riscv, devicetree, linux-clk, linux-gpio, linux-serial
  Cc: Emil Renner Berthing, Palmer Dabbelt, Paul Walmsley, Rob Herring,
	Michael Turquette, Stephen Boyd, Thomas Gleixner, Marc Zyngier,
	Philipp Zabel, Linus Walleij, Greg Kroah-Hartman, Daniel Lezcano,
	Andy Shevchenko, Jiri Slaby, Maximilian Luz, Sagar Kadam,
	Drew Fustini, Geert Uytterhoeven, Michael Zhu, Fu Wei,
	Anup Patel, Atish Patra, Matteo Croce, linux-kernel

Add StarFive Kconfig option to select SoC specific and common drivers
required for these SoCs.

Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
---
 arch/riscv/Kconfig.socs | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs
index 30676ebb16eb..6ec44a22278a 100644
--- a/arch/riscv/Kconfig.socs
+++ b/arch/riscv/Kconfig.socs
@@ -19,6 +19,14 @@ config SOC_SIFIVE
 	help
 	  This enables support for SiFive SoC platform hardware.
 
+config SOC_STARFIVE
+	bool "StarFive SoCs"
+	select PINCTRL
+	select RESET_CONTROLLER
+	select SIFIVE_PLIC
+	help
+	  This enables support for StarFive SoC platform hardware.
+
 config SOC_VIRT
 	bool "QEMU Virt Machine"
 	select CLINT_TIMER if RISCV_M_MODE
-- 
2.33.1


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 143+ messages in thread

* [PATCH v2 02/16] dt-bindings: timer: Add StarFive JH7100 clint
  2021-10-21 17:42 ` Emil Renner Berthing
@ 2021-10-21 17:42   ` Emil Renner Berthing
  -1 siblings, 0 replies; 143+ messages in thread
From: Emil Renner Berthing @ 2021-10-21 17:42 UTC (permalink / raw)
  To: linux-riscv, devicetree, linux-clk, linux-gpio, linux-serial
  Cc: Emil Renner Berthing, Palmer Dabbelt, Paul Walmsley, Rob Herring,
	Michael Turquette, Stephen Boyd, Thomas Gleixner, Marc Zyngier,
	Philipp Zabel, Linus Walleij, Greg Kroah-Hartman, Daniel Lezcano,
	Andy Shevchenko, Jiri Slaby, Maximilian Luz, Sagar Kadam,
	Drew Fustini, Geert Uytterhoeven, Michael Zhu, Fu Wei,
	Anup Patel, Atish Patra, Matteo Croce, linux-kernel, Rob Herring

Add compatible string for the StarFive JH7100 clint.

Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
Reviewed-by: Geert Uytterhoeven <geert@linux-m68k.org>
Acked-by: Rob Herring <robh@kernel.org>
---
 Documentation/devicetree/bindings/timer/sifive,clint.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/timer/sifive,clint.yaml b/Documentation/devicetree/bindings/timer/sifive,clint.yaml
index a35952f48742..8d5f4687add9 100644
--- a/Documentation/devicetree/bindings/timer/sifive,clint.yaml
+++ b/Documentation/devicetree/bindings/timer/sifive,clint.yaml
@@ -25,6 +25,7 @@ properties:
     items:
       - enum:
           - sifive,fu540-c000-clint
+          - starfive,jh7100-clint
           - canaan,k210-clint
       - const: sifive,clint0
 
-- 
2.33.1


^ permalink raw reply related	[flat|nested] 143+ messages in thread

* [PATCH v2 02/16] dt-bindings: timer: Add StarFive JH7100 clint
@ 2021-10-21 17:42   ` Emil Renner Berthing
  0 siblings, 0 replies; 143+ messages in thread
From: Emil Renner Berthing @ 2021-10-21 17:42 UTC (permalink / raw)
  To: linux-riscv, devicetree, linux-clk, linux-gpio, linux-serial
  Cc: Emil Renner Berthing, Palmer Dabbelt, Paul Walmsley, Rob Herring,
	Michael Turquette, Stephen Boyd, Thomas Gleixner, Marc Zyngier,
	Philipp Zabel, Linus Walleij, Greg Kroah-Hartman, Daniel Lezcano,
	Andy Shevchenko, Jiri Slaby, Maximilian Luz, Sagar Kadam,
	Drew Fustini, Geert Uytterhoeven, Michael Zhu, Fu Wei,
	Anup Patel, Atish Patra, Matteo Croce, linux-kernel, Rob Herring

Add compatible string for the StarFive JH7100 clint.

Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
Reviewed-by: Geert Uytterhoeven <geert@linux-m68k.org>
Acked-by: Rob Herring <robh@kernel.org>
---
 Documentation/devicetree/bindings/timer/sifive,clint.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/timer/sifive,clint.yaml b/Documentation/devicetree/bindings/timer/sifive,clint.yaml
index a35952f48742..8d5f4687add9 100644
--- a/Documentation/devicetree/bindings/timer/sifive,clint.yaml
+++ b/Documentation/devicetree/bindings/timer/sifive,clint.yaml
@@ -25,6 +25,7 @@ properties:
     items:
       - enum:
           - sifive,fu540-c000-clint
+          - starfive,jh7100-clint
           - canaan,k210-clint
       - const: sifive,clint0
 
-- 
2.33.1


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 143+ messages in thread

* [PATCH v2 03/16] dt-bindings: interrupt-controller: Add StarFive JH7100 plic
  2021-10-21 17:42 ` Emil Renner Berthing
@ 2021-10-21 17:42   ` Emil Renner Berthing
  -1 siblings, 0 replies; 143+ messages in thread
From: Emil Renner Berthing @ 2021-10-21 17:42 UTC (permalink / raw)
  To: linux-riscv, devicetree, linux-clk, linux-gpio, linux-serial
  Cc: Emil Renner Berthing, Palmer Dabbelt, Paul Walmsley, Rob Herring,
	Michael Turquette, Stephen Boyd, Thomas Gleixner, Marc Zyngier,
	Philipp Zabel, Linus Walleij, Greg Kroah-Hartman, Daniel Lezcano,
	Andy Shevchenko, Jiri Slaby, Maximilian Luz, Sagar Kadam,
	Drew Fustini, Geert Uytterhoeven, Michael Zhu, Fu Wei,
	Anup Patel, Atish Patra, Matteo Croce, linux-kernel

Add compatible string for StarFive JH7100 plic.

Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
Reviewed-by: Geert Uytterhoeven <geert@linux-m68k.org>
---
 .../bindings/interrupt-controller/sifive,plic-1.0.0.yaml         | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/interrupt-controller/sifive,plic-1.0.0.yaml b/Documentation/devicetree/bindings/interrupt-controller/sifive,plic-1.0.0.yaml
index 08d5a57ce00f..28b6b17fe4b2 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/sifive,plic-1.0.0.yaml
+++ b/Documentation/devicetree/bindings/interrupt-controller/sifive,plic-1.0.0.yaml
@@ -45,6 +45,7 @@ properties:
     items:
       - enum:
           - sifive,fu540-c000-plic
+          - starfive,jh7100-plic
           - canaan,k210-plic
       - const: sifive,plic-1.0.0
 
-- 
2.33.1


^ permalink raw reply related	[flat|nested] 143+ messages in thread

* [PATCH v2 03/16] dt-bindings: interrupt-controller: Add StarFive JH7100 plic
@ 2021-10-21 17:42   ` Emil Renner Berthing
  0 siblings, 0 replies; 143+ messages in thread
From: Emil Renner Berthing @ 2021-10-21 17:42 UTC (permalink / raw)
  To: linux-riscv, devicetree, linux-clk, linux-gpio, linux-serial
  Cc: Emil Renner Berthing, Palmer Dabbelt, Paul Walmsley, Rob Herring,
	Michael Turquette, Stephen Boyd, Thomas Gleixner, Marc Zyngier,
	Philipp Zabel, Linus Walleij, Greg Kroah-Hartman, Daniel Lezcano,
	Andy Shevchenko, Jiri Slaby, Maximilian Luz, Sagar Kadam,
	Drew Fustini, Geert Uytterhoeven, Michael Zhu, Fu Wei,
	Anup Patel, Atish Patra, Matteo Croce, linux-kernel

Add compatible string for StarFive JH7100 plic.

Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
Reviewed-by: Geert Uytterhoeven <geert@linux-m68k.org>
---
 .../bindings/interrupt-controller/sifive,plic-1.0.0.yaml         | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/interrupt-controller/sifive,plic-1.0.0.yaml b/Documentation/devicetree/bindings/interrupt-controller/sifive,plic-1.0.0.yaml
index 08d5a57ce00f..28b6b17fe4b2 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/sifive,plic-1.0.0.yaml
+++ b/Documentation/devicetree/bindings/interrupt-controller/sifive,plic-1.0.0.yaml
@@ -45,6 +45,7 @@ properties:
     items:
       - enum:
           - sifive,fu540-c000-plic
+          - starfive,jh7100-plic
           - canaan,k210-plic
       - const: sifive,plic-1.0.0
 
-- 
2.33.1


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 143+ messages in thread

* [PATCH v2 04/16] dt-bindings: clock: starfive: Add JH7100 clock definitions
  2021-10-21 17:42 ` Emil Renner Berthing
@ 2021-10-21 17:42   ` Emil Renner Berthing
  -1 siblings, 0 replies; 143+ messages in thread
From: Emil Renner Berthing @ 2021-10-21 17:42 UTC (permalink / raw)
  To: linux-riscv, devicetree, linux-clk, linux-gpio, linux-serial
  Cc: Geert Uytterhoeven, Palmer Dabbelt, Paul Walmsley, Rob Herring,
	Michael Turquette, Stephen Boyd, Thomas Gleixner, Marc Zyngier,
	Philipp Zabel, Linus Walleij, Greg Kroah-Hartman, Daniel Lezcano,
	Andy Shevchenko, Jiri Slaby, Maximilian Luz, Sagar Kadam,
	Drew Fustini, Michael Zhu, Fu Wei, Anup Patel, Atish Patra,
	Matteo Croce, linux-kernel, Emil Renner Berthing

From: Geert Uytterhoeven <geert@linux-m68k.org>

Add all clock outputs for the StarFive JH7100 clock generator.

Based on work by Ahmad Fatoum for Barebox, with "JH7100_" prefixes added
to all definitions.

Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
---
 include/dt-bindings/clock/starfive-jh7100.h | 202 ++++++++++++++++++++
 1 file changed, 202 insertions(+)
 create mode 100644 include/dt-bindings/clock/starfive-jh7100.h

diff --git a/include/dt-bindings/clock/starfive-jh7100.h b/include/dt-bindings/clock/starfive-jh7100.h
new file mode 100644
index 000000000000..742f93c6dd6b
--- /dev/null
+++ b/include/dt-bindings/clock/starfive-jh7100.h
@@ -0,0 +1,202 @@
+/* SPDX-License-Identifier: GPL-2.0 OR X11 */
+/*
+ * Copyright (C) 2021 Ahmad Fatoum, Pengutronix
+ */
+
+#ifndef __DT_BINDINGS_CLOCK_STARFIVE_JH7100_H__
+#define __DT_BINDINGS_CLOCK_STARFIVE_JH7100_H__
+
+#define JH7100_CLK_CPUNDBUS_ROOT	0
+#define JH7100_CLK_DLA_ROOT		1
+#define JH7100_CLK_DSP_ROOT		2
+#define JH7100_CLK_GMACUSB_ROOT		3
+#define JH7100_CLK_PERH0_ROOT		4
+#define JH7100_CLK_PERH1_ROOT		5
+#define JH7100_CLK_VIN_ROOT		6
+#define JH7100_CLK_VOUT_ROOT		7
+#define JH7100_CLK_AUDIO_ROOT		8
+#define JH7100_CLK_CDECHIFI4_ROOT	9
+#define JH7100_CLK_CDEC_ROOT		10
+#define JH7100_CLK_VOUTBUS_ROOT		11
+#define JH7100_CLK_CPUNBUS_ROOT_DIV	12
+#define JH7100_CLK_DSP_ROOT_DIV		13
+#define JH7100_CLK_PERH0_SRC		14
+#define JH7100_CLK_PERH1_SRC		15
+#define JH7100_CLK_PLL0_TESTOUT		16
+#define JH7100_CLK_PLL1_TESTOUT		17
+#define JH7100_CLK_PLL2_TESTOUT		18
+#define JH7100_CLK_PLL2_REF		19
+#define JH7100_CLK_CPU_CORE		20
+#define JH7100_CLK_CPU_AXI		21
+#define JH7100_CLK_AHB_BUS		22
+#define JH7100_CLK_APB1_BUS		23
+#define JH7100_CLK_APB2_BUS		24
+#define JH7100_CLK_DOM3AHB_BUS		25
+#define JH7100_CLK_DOM7AHB_BUS		26
+#define JH7100_CLK_U74_CORE0		27
+#define JH7100_CLK_U74_CORE1		28
+#define JH7100_CLK_U74_AXI		29
+#define JH7100_CLK_U74RTC_TOGGLE	30
+#define JH7100_CLK_SGDMA2P_AXI		31
+#define JH7100_CLK_DMA2PNOC_AXI		32
+#define JH7100_CLK_SGDMA2P_AHB		33
+#define JH7100_CLK_DLA_BUS		34
+#define JH7100_CLK_DLA_AXI		35
+#define JH7100_CLK_DLANOC_AXI		36
+#define JH7100_CLK_DLA_APB		37
+#define JH7100_CLK_VP6_CORE		38
+#define JH7100_CLK_VP6BUS_SRC		39
+#define JH7100_CLK_VP6_AXI		40
+#define JH7100_CLK_VCDECBUS_SRC		41
+#define JH7100_CLK_VDEC_BUS		42
+#define JH7100_CLK_VDEC_AXI		43
+#define JH7100_CLK_VDECBRG_MAIN		44
+#define JH7100_CLK_VDEC_BCLK		45
+#define JH7100_CLK_VDEC_CCLK		46
+#define JH7100_CLK_VDEC_APB		47
+#define JH7100_CLK_JPEG_AXI		48
+#define JH7100_CLK_JPEG_CCLK		49
+#define JH7100_CLK_JPEG_APB		50
+#define JH7100_CLK_GC300_2X		51
+#define JH7100_CLK_GC300_AHB		52
+#define JH7100_CLK_JPCGC300_AXIBUS	53
+#define JH7100_CLK_GC300_AXI		54
+#define JH7100_CLK_JPCGC300_MAIN	55
+#define JH7100_CLK_VENC_BUS		56
+#define JH7100_CLK_VENC_AXI		57
+#define JH7100_CLK_VENCBRG_MAIN		58
+#define JH7100_CLK_VENC_BCLK		59
+#define JH7100_CLK_VENC_CCLK		60
+#define JH7100_CLK_VENC_APB		61
+#define JH7100_CLK_DDRPLL_DIV2		62
+#define JH7100_CLK_DDRPLL_DIV4		63
+#define JH7100_CLK_DDRPLL_DIV8		64
+#define JH7100_CLK_DDROSC_DIV2		65
+#define JH7100_CLK_DDRC0		66
+#define JH7100_CLK_DDRC1		67
+#define JH7100_CLK_DDRPHY_APB		68
+#define JH7100_CLK_NOC_ROB		69
+#define JH7100_CLK_NOC_COG		70
+#define JH7100_CLK_NNE_AHB		71
+#define JH7100_CLK_NNEBUS_SRC1		72
+#define JH7100_CLK_NNE_BUS		73
+#define JH7100_CLK_NNE_AXI		74
+#define JH7100_CLK_NNENOC_AXI		75
+#define JH7100_CLK_DLASLV_AXI		76
+#define JH7100_CLK_DSPX2C_AXI		77
+#define JH7100_CLK_HIFI4_SRC		78
+#define JH7100_CLK_HIFI4_COREFREE	79
+#define JH7100_CLK_HIFI4_CORE		80
+#define JH7100_CLK_HIFI4_BUS		81
+#define JH7100_CLK_HIFI4_AXI		82
+#define JH7100_CLK_HIFI4NOC_AXI		83
+#define JH7100_CLK_SGDMA1P_BUS		84
+#define JH7100_CLK_SGDMA1P_AXI		85
+#define JH7100_CLK_DMA1P_AXI		86
+#define JH7100_CLK_X2C_AXI		87
+#define JH7100_CLK_USB_BUS		88
+#define JH7100_CLK_USB_AXI		89
+#define JH7100_CLK_USBNOC_AXI		90
+#define JH7100_CLK_USBPHY_ROOTDIV	91
+#define JH7100_CLK_USBPHY_125M		92
+#define JH7100_CLK_USBPHY_PLLDIV25M	93
+#define JH7100_CLK_USBPHY_25M		94
+#define JH7100_CLK_AUDIO_DIV		95
+#define JH7100_CLK_AUDIO_SRC		96
+#define JH7100_CLK_AUDIO_12288		97
+#define JH7100_CLK_VIN_SRC		98
+#define JH7100_CLK_ISP0_BUS		99
+#define JH7100_CLK_ISP0_AXI		100
+#define JH7100_CLK_ISP0NOC_AXI		101
+#define JH7100_CLK_ISPSLV_AXI		102
+#define JH7100_CLK_ISP1_BUS		103
+#define JH7100_CLK_ISP1_AXI		104
+#define JH7100_CLK_ISP1NOC_AXI		105
+#define JH7100_CLK_VIN_BUS		106
+#define JH7100_CLK_VIN_AXI		107
+#define JH7100_CLK_VINNOC_AXI		108
+#define JH7100_CLK_VOUT_SRC		109
+#define JH7100_CLK_DISPBUS_SRC		110
+#define JH7100_CLK_DISP_BUS		111
+#define JH7100_CLK_DISP_AXI		112
+#define JH7100_CLK_DISPNOC_AXI		113
+#define JH7100_CLK_SDIO0_AHB		114
+#define JH7100_CLK_SDIO0_CCLKINT	115
+#define JH7100_CLK_SDIO0_CCLKINT_INV	116
+#define JH7100_CLK_SDIO1_AHB		117
+#define JH7100_CLK_SDIO1_CCLKINT	118
+#define JH7100_CLK_SDIO1_CCLKINT_INV	119
+#define JH7100_CLK_GMAC_AHB		120
+#define JH7100_CLK_GMAC_ROOT_DIV	121
+#define JH7100_CLK_GMAC_PTP_REF		122
+#define JH7100_CLK_GMAC_GTX		123
+#define JH7100_CLK_GMAC_RMII_TX		124
+#define JH7100_CLK_GMAC_RMII_RX		125
+#define JH7100_CLK_GMAC_TX		126
+#define JH7100_CLK_GMAC_TX_INV		127
+#define JH7100_CLK_GMAC_RX_PRE		128
+#define JH7100_CLK_GMAC_RX_INV		129
+#define JH7100_CLK_GMAC_RMII		130
+#define JH7100_CLK_GMAC_TOPHYREF	131
+#define JH7100_CLK_SPI2AHB_AHB		132
+#define JH7100_CLK_SPI2AHB_CORE		133
+#define JH7100_CLK_EZMASTER_AHB		134
+#define JH7100_CLK_E24_AHB		135
+#define JH7100_CLK_E24RTC_TOGGLE	136
+#define JH7100_CLK_QSPI_AHB		137
+#define JH7100_CLK_QSPI_APB		138
+#define JH7100_CLK_QSPI_REF		139
+#define JH7100_CLK_SEC_AHB		140
+#define JH7100_CLK_AES			141
+#define JH7100_CLK_SHA			142
+#define JH7100_CLK_PKA			143
+#define JH7100_CLK_TRNG_APB		144
+#define JH7100_CLK_OTP_APB		145
+#define JH7100_CLK_UART0_APB		146
+#define JH7100_CLK_UART0_CORE		147
+#define JH7100_CLK_UART1_APB		148
+#define JH7100_CLK_UART1_CORE		149
+#define JH7100_CLK_SPI0_APB		150
+#define JH7100_CLK_SPI0_CORE		151
+#define JH7100_CLK_SPI1_APB		152
+#define JH7100_CLK_SPI1_CORE		153
+#define JH7100_CLK_I2C0_APB		154
+#define JH7100_CLK_I2C0_CORE		155
+#define JH7100_CLK_I2C1_APB		156
+#define JH7100_CLK_I2C1_CORE		157
+#define JH7100_CLK_GPIO_APB		158
+#define JH7100_CLK_UART2_APB		159
+#define JH7100_CLK_UART2_CORE		160
+#define JH7100_CLK_UART3_APB		161
+#define JH7100_CLK_UART3_CORE		162
+#define JH7100_CLK_SPI2_APB		163
+#define JH7100_CLK_SPI2_CORE		164
+#define JH7100_CLK_SPI3_APB		165
+#define JH7100_CLK_SPI3_CORE		166
+#define JH7100_CLK_I2C2_APB		167
+#define JH7100_CLK_I2C2_CORE		168
+#define JH7100_CLK_I2C3_APB		169
+#define JH7100_CLK_I2C3_CORE		170
+#define JH7100_CLK_WDTIMER_APB		171
+#define JH7100_CLK_WDT_CORE		172
+#define JH7100_CLK_TIMER0_CORE		173
+#define JH7100_CLK_TIMER1_CORE		174
+#define JH7100_CLK_TIMER2_CORE		175
+#define JH7100_CLK_TIMER3_CORE		176
+#define JH7100_CLK_TIMER4_CORE		177
+#define JH7100_CLK_TIMER5_CORE		178
+#define JH7100_CLK_TIMER6_CORE		179
+#define JH7100_CLK_VP6INTC_APB		180
+#define JH7100_CLK_PWM_APB		181
+#define JH7100_CLK_MSI_APB		182
+#define JH7100_CLK_TEMP_APB		183
+#define JH7100_CLK_TEMP_SENSE		184
+#define JH7100_CLK_SYSERR_APB		185
+
+#define JH7100_CLK_PLL0_OUT		186
+#define JH7100_CLK_PLL1_OUT		187
+#define JH7100_CLK_PLL2_OUT		188
+
+#define JH7100_CLK_END			189
+
+#endif /* __DT_BINDINGS_CLOCK_STARFIVE_JH7100_H__ */
-- 
2.33.1


^ permalink raw reply related	[flat|nested] 143+ messages in thread

* [PATCH v2 04/16] dt-bindings: clock: starfive: Add JH7100 clock definitions
@ 2021-10-21 17:42   ` Emil Renner Berthing
  0 siblings, 0 replies; 143+ messages in thread
From: Emil Renner Berthing @ 2021-10-21 17:42 UTC (permalink / raw)
  To: linux-riscv, devicetree, linux-clk, linux-gpio, linux-serial
  Cc: Geert Uytterhoeven, Palmer Dabbelt, Paul Walmsley, Rob Herring,
	Michael Turquette, Stephen Boyd, Thomas Gleixner, Marc Zyngier,
	Philipp Zabel, Linus Walleij, Greg Kroah-Hartman, Daniel Lezcano,
	Andy Shevchenko, Jiri Slaby, Maximilian Luz, Sagar Kadam,
	Drew Fustini, Michael Zhu, Fu Wei, Anup Patel, Atish Patra,
	Matteo Croce, linux-kernel, Emil Renner Berthing

From: Geert Uytterhoeven <geert@linux-m68k.org>

Add all clock outputs for the StarFive JH7100 clock generator.

Based on work by Ahmad Fatoum for Barebox, with "JH7100_" prefixes added
to all definitions.

Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
---
 include/dt-bindings/clock/starfive-jh7100.h | 202 ++++++++++++++++++++
 1 file changed, 202 insertions(+)
 create mode 100644 include/dt-bindings/clock/starfive-jh7100.h

diff --git a/include/dt-bindings/clock/starfive-jh7100.h b/include/dt-bindings/clock/starfive-jh7100.h
new file mode 100644
index 000000000000..742f93c6dd6b
--- /dev/null
+++ b/include/dt-bindings/clock/starfive-jh7100.h
@@ -0,0 +1,202 @@
+/* SPDX-License-Identifier: GPL-2.0 OR X11 */
+/*
+ * Copyright (C) 2021 Ahmad Fatoum, Pengutronix
+ */
+
+#ifndef __DT_BINDINGS_CLOCK_STARFIVE_JH7100_H__
+#define __DT_BINDINGS_CLOCK_STARFIVE_JH7100_H__
+
+#define JH7100_CLK_CPUNDBUS_ROOT	0
+#define JH7100_CLK_DLA_ROOT		1
+#define JH7100_CLK_DSP_ROOT		2
+#define JH7100_CLK_GMACUSB_ROOT		3
+#define JH7100_CLK_PERH0_ROOT		4
+#define JH7100_CLK_PERH1_ROOT		5
+#define JH7100_CLK_VIN_ROOT		6
+#define JH7100_CLK_VOUT_ROOT		7
+#define JH7100_CLK_AUDIO_ROOT		8
+#define JH7100_CLK_CDECHIFI4_ROOT	9
+#define JH7100_CLK_CDEC_ROOT		10
+#define JH7100_CLK_VOUTBUS_ROOT		11
+#define JH7100_CLK_CPUNBUS_ROOT_DIV	12
+#define JH7100_CLK_DSP_ROOT_DIV		13
+#define JH7100_CLK_PERH0_SRC		14
+#define JH7100_CLK_PERH1_SRC		15
+#define JH7100_CLK_PLL0_TESTOUT		16
+#define JH7100_CLK_PLL1_TESTOUT		17
+#define JH7100_CLK_PLL2_TESTOUT		18
+#define JH7100_CLK_PLL2_REF		19
+#define JH7100_CLK_CPU_CORE		20
+#define JH7100_CLK_CPU_AXI		21
+#define JH7100_CLK_AHB_BUS		22
+#define JH7100_CLK_APB1_BUS		23
+#define JH7100_CLK_APB2_BUS		24
+#define JH7100_CLK_DOM3AHB_BUS		25
+#define JH7100_CLK_DOM7AHB_BUS		26
+#define JH7100_CLK_U74_CORE0		27
+#define JH7100_CLK_U74_CORE1		28
+#define JH7100_CLK_U74_AXI		29
+#define JH7100_CLK_U74RTC_TOGGLE	30
+#define JH7100_CLK_SGDMA2P_AXI		31
+#define JH7100_CLK_DMA2PNOC_AXI		32
+#define JH7100_CLK_SGDMA2P_AHB		33
+#define JH7100_CLK_DLA_BUS		34
+#define JH7100_CLK_DLA_AXI		35
+#define JH7100_CLK_DLANOC_AXI		36
+#define JH7100_CLK_DLA_APB		37
+#define JH7100_CLK_VP6_CORE		38
+#define JH7100_CLK_VP6BUS_SRC		39
+#define JH7100_CLK_VP6_AXI		40
+#define JH7100_CLK_VCDECBUS_SRC		41
+#define JH7100_CLK_VDEC_BUS		42
+#define JH7100_CLK_VDEC_AXI		43
+#define JH7100_CLK_VDECBRG_MAIN		44
+#define JH7100_CLK_VDEC_BCLK		45
+#define JH7100_CLK_VDEC_CCLK		46
+#define JH7100_CLK_VDEC_APB		47
+#define JH7100_CLK_JPEG_AXI		48
+#define JH7100_CLK_JPEG_CCLK		49
+#define JH7100_CLK_JPEG_APB		50
+#define JH7100_CLK_GC300_2X		51
+#define JH7100_CLK_GC300_AHB		52
+#define JH7100_CLK_JPCGC300_AXIBUS	53
+#define JH7100_CLK_GC300_AXI		54
+#define JH7100_CLK_JPCGC300_MAIN	55
+#define JH7100_CLK_VENC_BUS		56
+#define JH7100_CLK_VENC_AXI		57
+#define JH7100_CLK_VENCBRG_MAIN		58
+#define JH7100_CLK_VENC_BCLK		59
+#define JH7100_CLK_VENC_CCLK		60
+#define JH7100_CLK_VENC_APB		61
+#define JH7100_CLK_DDRPLL_DIV2		62
+#define JH7100_CLK_DDRPLL_DIV4		63
+#define JH7100_CLK_DDRPLL_DIV8		64
+#define JH7100_CLK_DDROSC_DIV2		65
+#define JH7100_CLK_DDRC0		66
+#define JH7100_CLK_DDRC1		67
+#define JH7100_CLK_DDRPHY_APB		68
+#define JH7100_CLK_NOC_ROB		69
+#define JH7100_CLK_NOC_COG		70
+#define JH7100_CLK_NNE_AHB		71
+#define JH7100_CLK_NNEBUS_SRC1		72
+#define JH7100_CLK_NNE_BUS		73
+#define JH7100_CLK_NNE_AXI		74
+#define JH7100_CLK_NNENOC_AXI		75
+#define JH7100_CLK_DLASLV_AXI		76
+#define JH7100_CLK_DSPX2C_AXI		77
+#define JH7100_CLK_HIFI4_SRC		78
+#define JH7100_CLK_HIFI4_COREFREE	79
+#define JH7100_CLK_HIFI4_CORE		80
+#define JH7100_CLK_HIFI4_BUS		81
+#define JH7100_CLK_HIFI4_AXI		82
+#define JH7100_CLK_HIFI4NOC_AXI		83
+#define JH7100_CLK_SGDMA1P_BUS		84
+#define JH7100_CLK_SGDMA1P_AXI		85
+#define JH7100_CLK_DMA1P_AXI		86
+#define JH7100_CLK_X2C_AXI		87
+#define JH7100_CLK_USB_BUS		88
+#define JH7100_CLK_USB_AXI		89
+#define JH7100_CLK_USBNOC_AXI		90
+#define JH7100_CLK_USBPHY_ROOTDIV	91
+#define JH7100_CLK_USBPHY_125M		92
+#define JH7100_CLK_USBPHY_PLLDIV25M	93
+#define JH7100_CLK_USBPHY_25M		94
+#define JH7100_CLK_AUDIO_DIV		95
+#define JH7100_CLK_AUDIO_SRC		96
+#define JH7100_CLK_AUDIO_12288		97
+#define JH7100_CLK_VIN_SRC		98
+#define JH7100_CLK_ISP0_BUS		99
+#define JH7100_CLK_ISP0_AXI		100
+#define JH7100_CLK_ISP0NOC_AXI		101
+#define JH7100_CLK_ISPSLV_AXI		102
+#define JH7100_CLK_ISP1_BUS		103
+#define JH7100_CLK_ISP1_AXI		104
+#define JH7100_CLK_ISP1NOC_AXI		105
+#define JH7100_CLK_VIN_BUS		106
+#define JH7100_CLK_VIN_AXI		107
+#define JH7100_CLK_VINNOC_AXI		108
+#define JH7100_CLK_VOUT_SRC		109
+#define JH7100_CLK_DISPBUS_SRC		110
+#define JH7100_CLK_DISP_BUS		111
+#define JH7100_CLK_DISP_AXI		112
+#define JH7100_CLK_DISPNOC_AXI		113
+#define JH7100_CLK_SDIO0_AHB		114
+#define JH7100_CLK_SDIO0_CCLKINT	115
+#define JH7100_CLK_SDIO0_CCLKINT_INV	116
+#define JH7100_CLK_SDIO1_AHB		117
+#define JH7100_CLK_SDIO1_CCLKINT	118
+#define JH7100_CLK_SDIO1_CCLKINT_INV	119
+#define JH7100_CLK_GMAC_AHB		120
+#define JH7100_CLK_GMAC_ROOT_DIV	121
+#define JH7100_CLK_GMAC_PTP_REF		122
+#define JH7100_CLK_GMAC_GTX		123
+#define JH7100_CLK_GMAC_RMII_TX		124
+#define JH7100_CLK_GMAC_RMII_RX		125
+#define JH7100_CLK_GMAC_TX		126
+#define JH7100_CLK_GMAC_TX_INV		127
+#define JH7100_CLK_GMAC_RX_PRE		128
+#define JH7100_CLK_GMAC_RX_INV		129
+#define JH7100_CLK_GMAC_RMII		130
+#define JH7100_CLK_GMAC_TOPHYREF	131
+#define JH7100_CLK_SPI2AHB_AHB		132
+#define JH7100_CLK_SPI2AHB_CORE		133
+#define JH7100_CLK_EZMASTER_AHB		134
+#define JH7100_CLK_E24_AHB		135
+#define JH7100_CLK_E24RTC_TOGGLE	136
+#define JH7100_CLK_QSPI_AHB		137
+#define JH7100_CLK_QSPI_APB		138
+#define JH7100_CLK_QSPI_REF		139
+#define JH7100_CLK_SEC_AHB		140
+#define JH7100_CLK_AES			141
+#define JH7100_CLK_SHA			142
+#define JH7100_CLK_PKA			143
+#define JH7100_CLK_TRNG_APB		144
+#define JH7100_CLK_OTP_APB		145
+#define JH7100_CLK_UART0_APB		146
+#define JH7100_CLK_UART0_CORE		147
+#define JH7100_CLK_UART1_APB		148
+#define JH7100_CLK_UART1_CORE		149
+#define JH7100_CLK_SPI0_APB		150
+#define JH7100_CLK_SPI0_CORE		151
+#define JH7100_CLK_SPI1_APB		152
+#define JH7100_CLK_SPI1_CORE		153
+#define JH7100_CLK_I2C0_APB		154
+#define JH7100_CLK_I2C0_CORE		155
+#define JH7100_CLK_I2C1_APB		156
+#define JH7100_CLK_I2C1_CORE		157
+#define JH7100_CLK_GPIO_APB		158
+#define JH7100_CLK_UART2_APB		159
+#define JH7100_CLK_UART2_CORE		160
+#define JH7100_CLK_UART3_APB		161
+#define JH7100_CLK_UART3_CORE		162
+#define JH7100_CLK_SPI2_APB		163
+#define JH7100_CLK_SPI2_CORE		164
+#define JH7100_CLK_SPI3_APB		165
+#define JH7100_CLK_SPI3_CORE		166
+#define JH7100_CLK_I2C2_APB		167
+#define JH7100_CLK_I2C2_CORE		168
+#define JH7100_CLK_I2C3_APB		169
+#define JH7100_CLK_I2C3_CORE		170
+#define JH7100_CLK_WDTIMER_APB		171
+#define JH7100_CLK_WDT_CORE		172
+#define JH7100_CLK_TIMER0_CORE		173
+#define JH7100_CLK_TIMER1_CORE		174
+#define JH7100_CLK_TIMER2_CORE		175
+#define JH7100_CLK_TIMER3_CORE		176
+#define JH7100_CLK_TIMER4_CORE		177
+#define JH7100_CLK_TIMER5_CORE		178
+#define JH7100_CLK_TIMER6_CORE		179
+#define JH7100_CLK_VP6INTC_APB		180
+#define JH7100_CLK_PWM_APB		181
+#define JH7100_CLK_MSI_APB		182
+#define JH7100_CLK_TEMP_APB		183
+#define JH7100_CLK_TEMP_SENSE		184
+#define JH7100_CLK_SYSERR_APB		185
+
+#define JH7100_CLK_PLL0_OUT		186
+#define JH7100_CLK_PLL1_OUT		187
+#define JH7100_CLK_PLL2_OUT		188
+
+#define JH7100_CLK_END			189
+
+#endif /* __DT_BINDINGS_CLOCK_STARFIVE_JH7100_H__ */
-- 
2.33.1


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 143+ messages in thread

* [PATCH v2 05/16] dt-bindings: clock: starfive: Add JH7100 bindings
  2021-10-21 17:42 ` Emil Renner Berthing
@ 2021-10-21 17:42   ` Emil Renner Berthing
  -1 siblings, 0 replies; 143+ messages in thread
From: Emil Renner Berthing @ 2021-10-21 17:42 UTC (permalink / raw)
  To: linux-riscv, devicetree, linux-clk, linux-gpio, linux-serial
  Cc: Geert Uytterhoeven, Palmer Dabbelt, Paul Walmsley, Rob Herring,
	Michael Turquette, Stephen Boyd, Thomas Gleixner, Marc Zyngier,
	Philipp Zabel, Linus Walleij, Greg Kroah-Hartman, Daniel Lezcano,
	Andy Shevchenko, Jiri Slaby, Maximilian Luz, Sagar Kadam,
	Drew Fustini, Michael Zhu, Fu Wei, Anup Patel, Atish Patra,
	Matteo Croce, linux-kernel, Emil Renner Berthing

From: Geert Uytterhoeven <geert@linux-m68k.org>

Add device tree bindings for the StarFive JH7100 clock generator.

Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
---
 .../clock/starfive,jh7100-clkgen.yaml         | 56 +++++++++++++++++++
 1 file changed, 56 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/starfive,jh7100-clkgen.yaml

diff --git a/Documentation/devicetree/bindings/clock/starfive,jh7100-clkgen.yaml b/Documentation/devicetree/bindings/clock/starfive,jh7100-clkgen.yaml
new file mode 100644
index 000000000000..d19f94984eab
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/starfive,jh7100-clkgen.yaml
@@ -0,0 +1,56 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/starfive,jh7100-clkgen.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: StarFive JH7100 Clock Generator
+
+maintainers:
+  - Geert Uytterhoeven <geert@linux-m68k.org>
+  - Emil Renner Berthing <kernel@esmil.dk>
+
+properties:
+  compatible:
+    const: starfive,jh7100-clkgen
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    items:
+      - description: Main clock source (25 MHz)
+      - description: Application-specific clock source (12-27 MHz)
+      - description: RMII reference clock (50 MHz)
+      - description: RGMII RX clock (125 MHz)
+
+  clock-names:
+    items:
+      - const: osc_sys
+      - const: osc_aud
+      - const: gmac_rmii_ref
+      - const: gmac_gr_mii_rxclk
+
+  '#clock-cells':
+    const: 1
+    description:
+      See <dt-bindings/clock/starfive-jh7100.h> for valid indices.
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - clock-names
+  - '#clock-cells'
+
+additionalProperties: false
+
+examples:
+  - |
+    clkgen: clock-controller@11800000 {
+            compatible = "starfive,jh7100-clkgen";
+            reg = <0x11800000 0x10000>;
+            clocks = <&osc_sys>, <&osc_aud>, <&gmac_rmii_ref>, <&gmac_gr_mii_rxclk>;
+            clock-names = "osc_sys", "osc_aud", "gmac_rmii_ref", "gmac_gr_mii_rxclk";
+            #clock-cells = <1>;
+    };
-- 
2.33.1


^ permalink raw reply related	[flat|nested] 143+ messages in thread

* [PATCH v2 05/16] dt-bindings: clock: starfive: Add JH7100 bindings
@ 2021-10-21 17:42   ` Emil Renner Berthing
  0 siblings, 0 replies; 143+ messages in thread
From: Emil Renner Berthing @ 2021-10-21 17:42 UTC (permalink / raw)
  To: linux-riscv, devicetree, linux-clk, linux-gpio, linux-serial
  Cc: Geert Uytterhoeven, Palmer Dabbelt, Paul Walmsley, Rob Herring,
	Michael Turquette, Stephen Boyd, Thomas Gleixner, Marc Zyngier,
	Philipp Zabel, Linus Walleij, Greg Kroah-Hartman, Daniel Lezcano,
	Andy Shevchenko, Jiri Slaby, Maximilian Luz, Sagar Kadam,
	Drew Fustini, Michael Zhu, Fu Wei, Anup Patel, Atish Patra,
	Matteo Croce, linux-kernel, Emil Renner Berthing

From: Geert Uytterhoeven <geert@linux-m68k.org>

Add device tree bindings for the StarFive JH7100 clock generator.

Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
---
 .../clock/starfive,jh7100-clkgen.yaml         | 56 +++++++++++++++++++
 1 file changed, 56 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/starfive,jh7100-clkgen.yaml

diff --git a/Documentation/devicetree/bindings/clock/starfive,jh7100-clkgen.yaml b/Documentation/devicetree/bindings/clock/starfive,jh7100-clkgen.yaml
new file mode 100644
index 000000000000..d19f94984eab
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/starfive,jh7100-clkgen.yaml
@@ -0,0 +1,56 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/starfive,jh7100-clkgen.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: StarFive JH7100 Clock Generator
+
+maintainers:
+  - Geert Uytterhoeven <geert@linux-m68k.org>
+  - Emil Renner Berthing <kernel@esmil.dk>
+
+properties:
+  compatible:
+    const: starfive,jh7100-clkgen
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    items:
+      - description: Main clock source (25 MHz)
+      - description: Application-specific clock source (12-27 MHz)
+      - description: RMII reference clock (50 MHz)
+      - description: RGMII RX clock (125 MHz)
+
+  clock-names:
+    items:
+      - const: osc_sys
+      - const: osc_aud
+      - const: gmac_rmii_ref
+      - const: gmac_gr_mii_rxclk
+
+  '#clock-cells':
+    const: 1
+    description:
+      See <dt-bindings/clock/starfive-jh7100.h> for valid indices.
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - clock-names
+  - '#clock-cells'
+
+additionalProperties: false
+
+examples:
+  - |
+    clkgen: clock-controller@11800000 {
+            compatible = "starfive,jh7100-clkgen";
+            reg = <0x11800000 0x10000>;
+            clocks = <&osc_sys>, <&osc_aud>, <&gmac_rmii_ref>, <&gmac_gr_mii_rxclk>;
+            clock-names = "osc_sys", "osc_aud", "gmac_rmii_ref", "gmac_gr_mii_rxclk";
+            #clock-cells = <1>;
+    };
-- 
2.33.1


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 143+ messages in thread

* [PATCH v2 06/16] clk: starfive: Add JH7100 clock generator driver
  2021-10-21 17:42 ` Emil Renner Berthing
@ 2021-10-21 17:42   ` Emil Renner Berthing
  -1 siblings, 0 replies; 143+ messages in thread
From: Emil Renner Berthing @ 2021-10-21 17:42 UTC (permalink / raw)
  To: linux-riscv, devicetree, linux-clk, linux-gpio, linux-serial
  Cc: Geert Uytterhoeven, Palmer Dabbelt, Paul Walmsley, Rob Herring,
	Michael Turquette, Stephen Boyd, Thomas Gleixner, Marc Zyngier,
	Philipp Zabel, Linus Walleij, Greg Kroah-Hartman, Daniel Lezcano,
	Andy Shevchenko, Jiri Slaby, Maximilian Luz, Sagar Kadam,
	Drew Fustini, Michael Zhu, Fu Wei, Anup Patel, Atish Patra,
	Matteo Croce, linux-kernel, Emil Renner Berthing

From: Geert Uytterhoeven <geert@linux-m68k.org>

Add a driver for the StarFive JH7100 clock generator.

Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
Co-developed-by: Emil Renner Berthing <kernel@esmil.dk>
Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
---
 MAINTAINERS                                |   7 +
 drivers/clk/Kconfig                        |   1 +
 drivers/clk/Makefile                       |   1 +
 drivers/clk/starfive/Kconfig               |   9 +
 drivers/clk/starfive/Makefile              |   3 +
 drivers/clk/starfive/clk-starfive-jh7100.c | 776 +++++++++++++++++++++
 6 files changed, 797 insertions(+)
 create mode 100644 drivers/clk/starfive/Kconfig
 create mode 100644 drivers/clk/starfive/Makefile
 create mode 100644 drivers/clk/starfive/clk-starfive-jh7100.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 8d118d7957d2..e5a19b70dfbb 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -17848,6 +17848,13 @@ M:	Ion Badulescu <ionut@badula.org>
 S:	Odd Fixes
 F:	drivers/net/ethernet/adaptec/starfire*
 
+STARFIVE JH7100 CLOCK DRIVER
+M:	Emil Renner Berthing <kernel@esmil.dk>
+S:	Maintained
+F:	Documentation/devicetree/bindings/clock/starfive,jh7100-clkgen.yaml
+F:	drivers/clk/starfive/clk-starfive-jh7100.c
+F:	include/dt-bindings/clock/starfive-jh7100.h
+
 STATIC BRANCH/CALL
 M:	Peter Zijlstra <peterz@infradead.org>
 M:	Josh Poimboeuf <jpoimboe@redhat.com>
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index c5b3dc97396a..c91931c94888 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -412,6 +412,7 @@ source "drivers/clk/samsung/Kconfig"
 source "drivers/clk/sifive/Kconfig"
 source "drivers/clk/socfpga/Kconfig"
 source "drivers/clk/sprd/Kconfig"
+source "drivers/clk/starfive/Kconfig"
 source "drivers/clk/sunxi/Kconfig"
 source "drivers/clk/sunxi-ng/Kconfig"
 source "drivers/clk/tegra/Kconfig"
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index e42312121e51..a9bb2478fbdd 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -109,6 +109,7 @@ obj-y					+= socfpga/
 obj-$(CONFIG_PLAT_SPEAR)		+= spear/
 obj-y					+= sprd/
 obj-$(CONFIG_ARCH_STI)			+= st/
+obj-$(CONFIG_SOC_STARFIVE)		+= starfive/
 obj-$(CONFIG_ARCH_SUNXI)		+= sunxi/
 obj-$(CONFIG_SUNXI_CCU)			+= sunxi-ng/
 obj-$(CONFIG_ARCH_TEGRA)		+= tegra/
diff --git a/drivers/clk/starfive/Kconfig b/drivers/clk/starfive/Kconfig
new file mode 100644
index 000000000000..c0fa9d5e641f
--- /dev/null
+++ b/drivers/clk/starfive/Kconfig
@@ -0,0 +1,9 @@
+# SPDX-License-Identifier: GPL-2.0
+
+config CLK_STARFIVE_JH7100
+	bool "StarFive JH7100 clock support"
+	depends on SOC_STARFIVE || COMPILE_TEST
+	default SOC_STARFIVE
+	help
+	  Say yes here to support the clock controller on the StarFive JH7100
+	  SoC.
diff --git a/drivers/clk/starfive/Makefile b/drivers/clk/starfive/Makefile
new file mode 100644
index 000000000000..09759cc73530
--- /dev/null
+++ b/drivers/clk/starfive/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0
+# StarFive Clock
+obj-$(CONFIG_CLK_STARFIVE_JH7100)	+= clk-starfive-jh7100.o
diff --git a/drivers/clk/starfive/clk-starfive-jh7100.c b/drivers/clk/starfive/clk-starfive-jh7100.c
new file mode 100644
index 000000000000..f109576f18c5
--- /dev/null
+++ b/drivers/clk/starfive/clk-starfive-jh7100.c
@@ -0,0 +1,776 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * StarFive JH7100 Clock Generator Driver
+ *
+ * Copyright 2021 Ahmad Fatoum, Pengutronix
+ * Copyright (C) 2021 Glider bv
+ * Copyright (C) 2021 Emil Renner Berthing <kernel@esmil.dk>
+ */
+
+#include <linux/bits.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/debugfs.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/overflow.h>
+#include <linux/platform_device.h>
+
+#include <dt-bindings/clock/starfive-jh7100.h>
+
+#define JH7100_CLK_ENABLE_SHIFT	31
+#define JH7100_CLK_INVERT_SHIFT	30
+#define JH7100_CLK_MUX_SHIFT	24
+
+#define JH7100_CLK_ENABLE	BIT(31)
+#define JH7100_CLK_INVERT	BIT(30)
+#define JH7100_CLK_MUX_MASK	GENMASK(27, 24)
+#define JH7100_CLK_DIV_MASK	GENMASK(23, 0)
+
+static const char *const cpundbus_root_sels[] __initconst = {
+	[0] = "osc_sys",
+	[1] = "pll0_out",
+	[2] = "pll1_out",
+	[3] = "pll2_out",
+};
+
+static const char *const dla_root_sels[] __initconst = {
+	[0] = "osc_sys",
+	[1] = "pll1_out",
+	[2] = "pll2_out",
+};
+
+static const char *const dsp_root_sels[] __initconst = {
+	[0] = "osc_sys",
+	[1] = "pll0_out",
+	[2] = "pll1_out",
+	[3] = "pll2_out",
+};
+
+static const char *const gmacusb_root_sels[] __initconst = {
+	[0] = "osc_sys",
+	[1] = "pll0_out",
+	[2] = "pll2_out",
+};
+
+static const char *const perh0_root_sels[] __initconst = {
+	[0] = "osc_sys",
+	[1] = "pll0_out",
+};
+
+static const char *const perh1_root_sels[] __initconst = {
+	[0] = "osc_sys",
+	[1] = "pll2_out",
+};
+
+static const char *const vin_root_sels[] __initconst = {
+	[0] = "osc_sys",
+	[1] = "pll1_out",
+	[2] = "pll2_out",
+};
+
+static const char *const vout_root_sels[] __initconst = {
+	[0] = "osc_aud",
+	[1] = "pll0_out",
+	[2] = "pll2_out",
+};
+
+static const char *const cdechifi4_root_sels[] __initconst = {
+	[0] = "osc_sys",
+	[1] = "pll1_out",
+	[2] = "pll2_out",
+};
+
+static const char *const cdec_root_sels[] __initconst = {
+	[0] = "osc_sys",
+	[1] = "pll0_out",
+	[2] = "pll1_out",
+};
+
+static const char *const voutbus_root_sels[] __initconst = {
+	[0] = "osc_aud",
+	[1] = "pll0_out",
+	[2] = "pll2_out",
+};
+
+static const char *const pll2_refclk_sels[] __initconst = {
+	[0] = "osc_sys",
+	[1] = "osc_aud",
+};
+
+static const char *const ddrc0_sels[] __initconst = {
+	[0] = "ddrosc_div2",
+	[1] = "ddrpll_div2",
+	[2] = "ddrpll_div4",
+	[3] = "ddrpll_div8",
+};
+
+static const char *const ddrc1_sels[] __initconst = {
+	[0] = "ddrosc_div2",
+	[1] = "ddrpll_div2",
+	[2] = "ddrpll_div4",
+	[3] = "ddrpll_div8",
+};
+
+static const char *const nne_bus_sels[] __initconst = {
+	[0] = "cpu_axi",
+	[1] = "nnebus_src1",
+};
+
+static const char *const usbphy_25m_sels[] __initconst = {
+	[0] = "osc_sys",
+	[1] = "usbphy_plldiv25m",
+};
+
+static const char *const gmac_tx_sels[] __initconst = {
+	[0] = "gmac_gtxclk",
+	[1] = "gmac_mii_txclk",
+	[2] = "gmac_rmii_txclk",
+};
+
+static const char *const gmac_rx_pre_sels[] __initconst = {
+	[0] = "gmac_gr_mii_rxclk",
+	[1] = "gmac_rmii_rxclk",
+};
+
+struct jh7100_clk {
+	struct clk_hw hw;
+	unsigned int idx;
+	u32 max;
+};
+
+struct clk_starfive_jh7100_priv {
+	/* protect registers against overlapping read-modify-write */
+	spinlock_t rmw_lock;
+	struct device *dev;
+	void __iomem *base;
+	struct clk_hw *pll[3];
+	struct jh7100_clk reg[JH7100_CLK_PLL0_OUT];
+};
+
+static struct jh7100_clk *jh7100_clk_from(struct clk_hw *hw)
+{
+	return container_of(hw, struct jh7100_clk, hw);
+}
+
+static struct clk_starfive_jh7100_priv *jh7100_priv_from(struct jh7100_clk *clk)
+{
+	return container_of(clk, struct clk_starfive_jh7100_priv, reg[clk->idx]);
+}
+
+static u32 jh7100_clk_reg_get(struct jh7100_clk *clk)
+{
+	struct clk_starfive_jh7100_priv *priv = jh7100_priv_from(clk);
+	void __iomem *reg = priv->base + 4 * clk->idx;
+
+	return readl_relaxed(reg);
+}
+
+static void jh7100_clk_reg_rmw(struct jh7100_clk *clk, u32 mask, u32 value)
+{
+	struct clk_starfive_jh7100_priv *priv = jh7100_priv_from(clk);
+	void __iomem *reg = priv->base + 4 * clk->idx;
+	unsigned long flags;
+
+	spin_lock_irqsave(&priv->rmw_lock, flags);
+	value |= readl_relaxed(reg) & ~mask;
+	writel_relaxed(value, reg);
+	spin_unlock_irqrestore(&priv->rmw_lock, flags);
+}
+
+static int jh7100_clk_enable(struct clk_hw *hw)
+{
+	struct jh7100_clk *clk = jh7100_clk_from(hw);
+
+	dev_dbg(jh7100_priv_from(clk)->dev, "enable(%s)\n", clk_hw_get_name(&clk->hw));
+
+	jh7100_clk_reg_rmw(clk, JH7100_CLK_ENABLE, JH7100_CLK_ENABLE);
+	return 0;
+}
+
+static void jh7100_clk_disable(struct clk_hw *hw)
+{
+	struct jh7100_clk *clk = jh7100_clk_from(hw);
+
+	dev_dbg(jh7100_priv_from(clk)->dev, "disable(%s)\n", clk_hw_get_name(&clk->hw));
+
+	jh7100_clk_reg_rmw(clk, JH7100_CLK_ENABLE, 0);
+}
+
+static int jh7100_clk_is_enabled(struct clk_hw *hw)
+{
+	struct jh7100_clk *clk = jh7100_clk_from(hw);
+
+	return !!(jh7100_clk_reg_get(clk) & JH7100_CLK_ENABLE);
+}
+
+static int jh7100_clk_is_parent_enabled(struct clk_hw *hw)
+{
+	return clk_hw_is_enabled(clk_hw_get_parent(hw));
+}
+
+static unsigned long jh7100_clk_recalc_rate(struct clk_hw *hw,
+					    unsigned long parent_rate)
+{
+	struct jh7100_clk *clk = jh7100_clk_from(hw);
+	u32 value = jh7100_clk_reg_get(clk) & JH7100_CLK_DIV_MASK;
+	unsigned long rate;
+
+	if (value)
+		rate = parent_rate / value;
+	else
+		rate = 0;
+
+	dev_dbg(jh7100_priv_from(clk)->dev, "recalc_rate(%s, %lu) = %lu (div %u)\n",
+		clk_hw_get_name(&clk->hw), parent_rate, rate, value);
+
+	return rate;
+}
+
+static unsigned long jh7100_clk_bestdiv(struct jh7100_clk *clk,
+					unsigned long rate, unsigned long parent)
+{
+	unsigned long max = clk->max & JH7100_CLK_DIV_MASK;
+	unsigned long div = DIV_ROUND_UP(parent, rate);
+
+	return min(div, max);
+}
+
+static int jh7100_clk_determine_rate(struct clk_hw *hw,
+				     struct clk_rate_request *req)
+{
+	struct jh7100_clk *clk = jh7100_clk_from(hw);
+	unsigned long parent = req->best_parent_rate;
+	unsigned long rate = clamp(req->rate, req->min_rate, req->max_rate);
+	unsigned long div = jh7100_clk_bestdiv(clk, rate, parent);
+	unsigned long result = parent / div;
+
+	/*
+	 * We want the result clamped by min_rate and max_rate if possible:
+	 * Case 1: div hits the max divider value, which means it's less than
+	 * parent / rate, so the result is greater than rate and min_rate in
+	 * particular. We can't do anything about result > max_rate because the
+	 * divider doesn't go any further.
+	 * Case 2: div = DIV_ROUND_UP(parent, rate) which means the result is
+	 * always lower or equal to rate and max_rate.  However the result may
+	 * turn out lower than min_rate, but then the next higher rate is fine:
+	 *   div - 1 = ceil(parent / rate) - 1 < parent / rate
+	 * and thus
+	 *   min_rate <= rate < parent / (div - 1)
+	 */
+	if (result < req->min_rate && div > 1) {
+		div -= 1;
+		result = parent / div;
+	}
+
+	dev_dbg(jh7100_priv_from(clk)->dev,
+		"determine_rate(%s, {%lu<=%lu<=%lu from %lu}) = %lu (div %lu)\n",
+		clk_hw_get_name(&clk->hw), req->min_rate, req->rate, req->max_rate,
+		parent, result, div);
+
+	req->rate = result;
+	return 0;
+}
+
+static int jh7100_clk_set_rate(struct clk_hw *hw,
+			       unsigned long rate,
+			       unsigned long parent_rate)
+{
+	struct jh7100_clk *clk = jh7100_clk_from(hw);
+	unsigned long div = jh7100_clk_bestdiv(clk, rate, parent_rate);
+
+	dev_dbg(jh7100_priv_from(clk)->dev,
+		"set_rate(%s, %lu, %lu) = %lu (div %lu)\n",
+		clk_hw_get_name(&clk->hw), rate, parent_rate,
+		parent_rate / div, div);
+
+	jh7100_clk_reg_rmw(clk, JH7100_CLK_DIV_MASK, div);
+	return 0;
+}
+
+static u8 jh7100_clk_get_parent(struct clk_hw *hw)
+{
+	struct jh7100_clk *clk = jh7100_clk_from(hw);
+	u32 value = jh7100_clk_reg_get(clk);
+
+	return (value & JH7100_CLK_MUX_MASK) >> JH7100_CLK_MUX_SHIFT;
+}
+
+static int jh7100_clk_set_parent(struct clk_hw *hw, u8 index)
+{
+	struct jh7100_clk *clk = jh7100_clk_from(hw);
+	u32 value = (u32)index << JH7100_CLK_MUX_SHIFT;
+
+	dev_dbg(jh7100_priv_from(clk)->dev, "set_parent(%s, %u)\n",
+		clk_hw_get_name(&clk->hw), index);
+
+	jh7100_clk_reg_rmw(clk, JH7100_CLK_MUX_MASK, value);
+	return 0;
+}
+
+static int jh7100_clk_mux_determine_rate(struct clk_hw *hw,
+					 struct clk_rate_request *req)
+{
+	struct jh7100_clk *clk = jh7100_clk_from(hw);
+	int ret = clk_mux_determine_rate_flags(&clk->hw, req, 0);
+
+	dev_dbg(jh7100_priv_from(clk)->dev, "determine_rate(%s) = %d\n",
+		clk_hw_get_name(&clk->hw), ret);
+
+	return ret;
+}
+
+static int jh7100_clk_get_phase(struct clk_hw *hw)
+{
+	struct jh7100_clk *clk = jh7100_clk_from(hw);
+	u32 value = jh7100_clk_reg_get(clk);
+
+	return (value & JH7100_CLK_INVERT) ? 180 : 0;
+}
+
+static int jh7100_clk_set_phase(struct clk_hw *hw, int degrees)
+{
+	struct jh7100_clk *clk = jh7100_clk_from(hw);
+	u32 value;
+
+	dev_dbg(jh7100_priv_from(clk)->dev, "set_phase(%s, %d)\n",
+		clk_hw_get_name(&clk->hw), degrees);
+
+	if (degrees == 0)
+		value = 0;
+	else if (degrees == 180)
+		value = JH7100_CLK_INVERT;
+	else
+		return -EINVAL;
+
+	jh7100_clk_reg_rmw(clk, JH7100_CLK_INVERT, value);
+	return 0;
+}
+
+#ifdef CONFIG_DEBUG_FS
+static void jh7100_clk_debug_init(struct clk_hw *hw, struct dentry *dentry)
+{
+	static const struct debugfs_reg32 jh7100_clk_reg = {
+		.name = "CTRL",
+		.offset = 0,
+	};
+	struct jh7100_clk *clk = jh7100_clk_from(hw);
+	struct clk_starfive_jh7100_priv *priv = jh7100_priv_from(clk);
+	struct debugfs_regset32 *regset;
+
+	regset = devm_kzalloc(priv->dev, sizeof(*regset), GFP_KERNEL);
+	if (!regset)
+		return;
+
+	regset->regs = &jh7100_clk_reg;
+	regset->nregs = 1;
+	regset->base = priv->base + 4 * clk->idx;
+
+	debugfs_create_regset32("registers", 0400, dentry, regset);
+}
+#else
+#define jh7100_clk_debug_init NULL
+#endif
+
+static const struct clk_ops jh7100_clk_gate_ops = {
+	.enable = jh7100_clk_enable,
+	.disable = jh7100_clk_disable,
+	.is_enabled = jh7100_clk_is_enabled,
+	.debug_init = jh7100_clk_debug_init,
+};
+
+static const struct clk_ops jh7100_clk_div_ops = {
+	.is_enabled = jh7100_clk_is_parent_enabled,
+	.recalc_rate = jh7100_clk_recalc_rate,
+	.determine_rate = jh7100_clk_determine_rate,
+	.set_rate = jh7100_clk_set_rate,
+	.debug_init = jh7100_clk_debug_init,
+};
+
+static const struct clk_ops jh7100_clk_gdiv_ops = {
+	.enable = jh7100_clk_enable,
+	.disable = jh7100_clk_disable,
+	.is_enabled = jh7100_clk_is_enabled,
+	.recalc_rate = jh7100_clk_recalc_rate,
+	.determine_rate = jh7100_clk_determine_rate,
+	.set_rate = jh7100_clk_set_rate,
+	.debug_init = jh7100_clk_debug_init,
+};
+
+static const struct clk_ops jh7100_clk_mux_ops = {
+	.is_enabled = jh7100_clk_is_parent_enabled,
+	.get_parent = jh7100_clk_get_parent,
+	.set_parent = jh7100_clk_set_parent,
+	.determine_rate = jh7100_clk_mux_determine_rate,
+	.debug_init = jh7100_clk_debug_init,
+};
+
+static const struct clk_ops jh7100_clk_gmux_ops = {
+	.enable = jh7100_clk_enable,
+	.disable = jh7100_clk_disable,
+	.is_enabled = jh7100_clk_is_enabled,
+	.get_parent = jh7100_clk_get_parent,
+	.set_parent = jh7100_clk_set_parent,
+	.determine_rate = jh7100_clk_mux_determine_rate,
+	.debug_init = jh7100_clk_debug_init,
+};
+
+static const struct clk_ops jh7100_clk_inv_ops = {
+	.is_enabled = jh7100_clk_is_parent_enabled,
+	.get_phase = jh7100_clk_get_phase,
+	.set_phase = jh7100_clk_set_phase,
+	.debug_init = jh7100_clk_debug_init,
+};
+
+#define JH7100_GATE(_idx, _name, _parent, _flags) [_idx] = { \
+	.name = _name, \
+	.ops = &jh7100_clk_gate_ops, \
+	.parent = _parent, \
+	.flags = CLK_SET_RATE_PARENT | (_flags), \
+	.max = JH7100_CLK_ENABLE, \
+}
+
+#define JH7100__DIV(_idx, _name, _parent, _max) [_idx] = { \
+	.name = _name, \
+	.ops = &jh7100_clk_div_ops, \
+	.parent = _parent, \
+	.flags = 0, \
+	.max = _max, \
+}
+
+#define JH7100_GDIV(_idx, _name, _parent, _max, _flags) [_idx] = { \
+	.name = _name, \
+	.ops = &jh7100_clk_gdiv_ops, \
+	.parent = _parent, \
+	.flags = (_flags), \
+	.max = JH7100_CLK_ENABLE | (_max), \
+}
+
+#define JH7100__MUX(_idx, _name, _parents) [_idx] = { \
+	.name = _name, \
+	.ops = &jh7100_clk_mux_ops, \
+	.parents = _parents, \
+	.flags = 0, \
+	.max = (ARRAY_SIZE(_parents) - 1) << JH7100_CLK_MUX_SHIFT, \
+}
+
+#define JH7100_GMUX(_idx, _name, _parents, _flags) [_idx] = { \
+	.name = _name, \
+	.ops = &jh7100_clk_gmux_ops, \
+	.parents = _parents, \
+	.flags = (_flags), \
+	.max = JH7100_CLK_ENABLE | \
+		((ARRAY_SIZE(_parents) - 1) << JH7100_CLK_MUX_SHIFT), \
+}
+
+#define JH7100__INV(_idx, _name, _parent) [_idx] = { \
+	.name = _name, \
+	.ops = &jh7100_clk_inv_ops, \
+	.parent = _parent, \
+	.flags = CLK_SET_RATE_PARENT, \
+	.max = JH7100_CLK_INVERT, \
+}
+
+static const struct {
+	const char *name;
+	const struct clk_ops *ops;
+	union {
+		const char *parent;
+		const char *const *parents;
+	};
+	unsigned long flags;
+	u32 max;
+} jh7100_clk_data[] __initconst = {
+	JH7100__MUX(JH7100_CLK_CPUNDBUS_ROOT, "cpundbus_root", cpundbus_root_sels),
+	JH7100__MUX(JH7100_CLK_DLA_ROOT, "dla_root", dla_root_sels),
+	JH7100__MUX(JH7100_CLK_DSP_ROOT, "dsp_root", dsp_root_sels),
+	JH7100__MUX(JH7100_CLK_GMACUSB_ROOT, "gmacusb_root", gmacusb_root_sels),
+	JH7100__MUX(JH7100_CLK_PERH0_ROOT, "perh0_root", perh0_root_sels),
+	JH7100__MUX(JH7100_CLK_PERH1_ROOT, "perh1_root", perh1_root_sels),
+	JH7100__MUX(JH7100_CLK_VIN_ROOT, "vin_root", vin_root_sels),
+	JH7100__MUX(JH7100_CLK_VOUT_ROOT, "vout_root", vout_root_sels),
+	JH7100_GDIV(JH7100_CLK_AUDIO_ROOT, "audio_root", "pll0_out", 8, 0),
+	JH7100__MUX(JH7100_CLK_CDECHIFI4_ROOT, "cdechifi4_root", cdechifi4_root_sels),
+	JH7100__MUX(JH7100_CLK_CDEC_ROOT, "cdec_root", cdec_root_sels),
+	JH7100__MUX(JH7100_CLK_VOUTBUS_ROOT, "voutbus_root", voutbus_root_sels),
+	JH7100__DIV(JH7100_CLK_CPUNBUS_ROOT_DIV, "cpunbus_root_div", "cpundbus_root", 2),
+	JH7100__DIV(JH7100_CLK_DSP_ROOT_DIV, "dsp_root_div", "dsp_root", 4),
+	JH7100__DIV(JH7100_CLK_PERH0_SRC, "perh0_src", "perh0_root", 4),
+	JH7100__DIV(JH7100_CLK_PERH1_SRC, "perh1_src", "perh1_root", 4),
+	JH7100_GDIV(JH7100_CLK_PLL0_TESTOUT, "pll0_testout", "perh0_src", 31, 0),
+	JH7100_GDIV(JH7100_CLK_PLL1_TESTOUT, "pll1_testout", "dla_root", 31, 0),
+	JH7100_GDIV(JH7100_CLK_PLL2_TESTOUT, "pll2_testout", "perh1_src", 31, 0),
+	JH7100__MUX(JH7100_CLK_PLL2_REF, "pll2_refclk", pll2_refclk_sels),
+	JH7100__DIV(JH7100_CLK_CPU_CORE, "cpu_core", "cpunbus_root_div", 8),
+	JH7100__DIV(JH7100_CLK_CPU_AXI, "cpu_axi", "cpu_core", 8),
+	JH7100__DIV(JH7100_CLK_AHB_BUS, "ahb_bus", "cpunbus_root_div", 8),
+	JH7100__DIV(JH7100_CLK_APB1_BUS, "apb1_bus", "ahb_bus", 8),
+	JH7100__DIV(JH7100_CLK_APB2_BUS, "apb2_bus", "ahb_bus", 8),
+	JH7100_GATE(JH7100_CLK_DOM3AHB_BUS, "dom3ahb_bus", "ahb_bus", CLK_IGNORE_UNUSED),
+	JH7100_GATE(JH7100_CLK_DOM7AHB_BUS, "dom7ahb_bus", "ahb_bus", CLK_IGNORE_UNUSED),
+	JH7100_GATE(JH7100_CLK_U74_CORE0, "u74_core0", "cpu_core", CLK_IGNORE_UNUSED),
+	JH7100_GDIV(JH7100_CLK_U74_CORE1, "u74_core1", "cpu_core", 8, CLK_IGNORE_UNUSED),
+	JH7100_GATE(JH7100_CLK_U74_AXI, "u74_axi", "cpu_axi", CLK_IGNORE_UNUSED),
+	JH7100_GATE(JH7100_CLK_U74RTC_TOGGLE, "u74rtc_toggle", "osc_sys", CLK_IGNORE_UNUSED),
+	JH7100_GATE(JH7100_CLK_SGDMA2P_AXI, "sgdma2p_axi", "cpu_axi", 0),
+	JH7100_GATE(JH7100_CLK_DMA2PNOC_AXI, "dma2pnoc_axi", "cpu_axi", 0),
+	JH7100_GATE(JH7100_CLK_SGDMA2P_AHB, "sgdma2p_ahb", "ahb_bus", 0),
+	JH7100__DIV(JH7100_CLK_DLA_BUS, "dla_bus", "dla_root", 4),
+	JH7100_GATE(JH7100_CLK_DLA_AXI, "dla_axi", "dla_bus", 0),
+	JH7100_GATE(JH7100_CLK_DLANOC_AXI, "dlanoc_axi", "dla_bus", 0),
+	JH7100_GATE(JH7100_CLK_DLA_APB, "dla_apb", "apb1_bus", 0),
+	JH7100_GDIV(JH7100_CLK_VP6_CORE, "vp6_core", "dsp_root_div", 4, 0),
+	JH7100__DIV(JH7100_CLK_VP6BUS_SRC, "vp6bus_src", "dsp_root", 4),
+	JH7100_GDIV(JH7100_CLK_VP6_AXI, "vp6_axi", "vp6bus_src", 4, 0),
+	JH7100__DIV(JH7100_CLK_VCDECBUS_SRC, "vcdecbus_src", "cdechifi4_root", 4),
+	JH7100__DIV(JH7100_CLK_VDEC_BUS, "vdec_bus", "vcdecbus_src", 8),
+	JH7100_GATE(JH7100_CLK_VDEC_AXI, "vdec_axi", "vdec_bus", 0),
+	JH7100_GATE(JH7100_CLK_VDECBRG_MAIN, "vdecbrg_mainclk", "vdec_bus", 0),
+	JH7100_GDIV(JH7100_CLK_VDEC_BCLK, "vdec_bclk", "vcdecbus_src", 8, 0),
+	JH7100_GDIV(JH7100_CLK_VDEC_CCLK, "vdec_cclk", "cdec_root", 8, 0),
+	JH7100_GATE(JH7100_CLK_VDEC_APB, "vdec_apb", "apb1_bus", 0),
+	JH7100_GDIV(JH7100_CLK_JPEG_AXI, "jpeg_axi", "cpunbus_root_div", 8, 0),
+	JH7100_GDIV(JH7100_CLK_JPEG_CCLK, "jpeg_cclk", "cpunbus_root_div", 8, 0),
+	JH7100_GATE(JH7100_CLK_JPEG_APB, "jpeg_apb", "apb1_bus", 0),
+	JH7100_GDIV(JH7100_CLK_GC300_2X, "gc300_2x", "cdechifi4_root", 8, 0),
+	JH7100_GATE(JH7100_CLK_GC300_AHB, "gc300_ahb", "ahb_bus", 0),
+	JH7100__DIV(JH7100_CLK_JPCGC300_AXIBUS, "jpcgc300_axibus", "vcdecbus_src", 8),
+	JH7100_GATE(JH7100_CLK_GC300_AXI, "gc300_axi", "jpcgc300_axibus", 0),
+	JH7100_GATE(JH7100_CLK_JPCGC300_MAIN, "jpcgc300_mainclk", "jpcgc300_axibus", 0),
+	JH7100__DIV(JH7100_CLK_VENC_BUS, "venc_bus", "vcdecbus_src", 8),
+	JH7100_GATE(JH7100_CLK_VENC_AXI, "venc_axi", "venc_bus", 0),
+	JH7100_GATE(JH7100_CLK_VENCBRG_MAIN, "vencbrg_mainclk", "venc_bus", 0),
+	JH7100_GDIV(JH7100_CLK_VENC_BCLK, "venc_bclk", "vcdecbus_src", 8, 0),
+	JH7100_GDIV(JH7100_CLK_VENC_CCLK, "venc_cclk", "cdec_root", 8, 0),
+	JH7100_GATE(JH7100_CLK_VENC_APB, "venc_apb", "apb1_bus", 0),
+	JH7100_GDIV(JH7100_CLK_DDRPLL_DIV2, "ddrpll_div2", "pll1_out", 2, CLK_IGNORE_UNUSED),
+	JH7100_GDIV(JH7100_CLK_DDRPLL_DIV4, "ddrpll_div4", "ddrpll_div2", 2, CLK_IGNORE_UNUSED),
+	JH7100_GDIV(JH7100_CLK_DDRPLL_DIV8, "ddrpll_div8", "ddrpll_div4", 2, CLK_IGNORE_UNUSED),
+	JH7100_GDIV(JH7100_CLK_DDROSC_DIV2, "ddrosc_div2", "osc_sys", 2, CLK_IGNORE_UNUSED),
+	JH7100_GMUX(JH7100_CLK_DDRC0, "ddrc0", ddrc0_sels, CLK_IGNORE_UNUSED),
+	JH7100_GMUX(JH7100_CLK_DDRC1, "ddrc1", ddrc1_sels, CLK_IGNORE_UNUSED),
+	JH7100_GATE(JH7100_CLK_DDRPHY_APB, "ddrphy_apb", "apb1_bus", CLK_IGNORE_UNUSED),
+	JH7100__DIV(JH7100_CLK_NOC_ROB, "noc_rob", "cpunbus_root_div", 8),
+	JH7100__DIV(JH7100_CLK_NOC_COG, "noc_cog", "dla_root", 8),
+	JH7100_GATE(JH7100_CLK_NNE_AHB, "nne_ahb", "ahb_bus", 0),
+	JH7100__DIV(JH7100_CLK_NNEBUS_SRC1, "nnebus_src1", "dsp_root", 4),
+	JH7100__MUX(JH7100_CLK_NNE_BUS, "nne_bus", nne_bus_sels),
+	JH7100_GATE(JH7100_CLK_NNE_AXI, "nne_axi", "nne_bus", 0),
+	JH7100_GATE(JH7100_CLK_NNENOC_AXI, "nnenoc_axi", "nne_bus", 0),
+	JH7100_GATE(JH7100_CLK_DLASLV_AXI, "dlaslv_axi", "nne_bus", 0),
+	JH7100_GATE(JH7100_CLK_DSPX2C_AXI, "dspx2c_axi", "nne_bus", CLK_IGNORE_UNUSED),
+	JH7100__DIV(JH7100_CLK_HIFI4_SRC, "hifi4_src", "cdechifi4_root", 4),
+	JH7100__DIV(JH7100_CLK_HIFI4_COREFREE, "hifi4_corefree", "hifi4_src", 8),
+	JH7100_GATE(JH7100_CLK_HIFI4_CORE, "hifi4_core", "hifi4_corefree", 0),
+	JH7100__DIV(JH7100_CLK_HIFI4_BUS, "hifi4_bus", "hifi4_corefree", 8),
+	JH7100_GATE(JH7100_CLK_HIFI4_AXI, "hifi4_axi", "hifi4_bus", 0),
+	JH7100_GATE(JH7100_CLK_HIFI4NOC_AXI, "hifi4noc_axi", "hifi4_bus", 0),
+	JH7100__DIV(JH7100_CLK_SGDMA1P_BUS, "sgdma1p_bus", "cpunbus_root_div", 8),
+	JH7100_GATE(JH7100_CLK_SGDMA1P_AXI, "sgdma1p_axi", "sgdma1p_bus", 0),
+	JH7100_GATE(JH7100_CLK_DMA1P_AXI, "dma1p_axi", "sgdma1p_bus", 0),
+	JH7100_GDIV(JH7100_CLK_X2C_AXI, "x2c_axi", "cpunbus_root_div", 8, CLK_IGNORE_UNUSED),
+	JH7100__DIV(JH7100_CLK_USB_BUS, "usb_bus", "cpunbus_root_div", 8),
+	JH7100_GATE(JH7100_CLK_USB_AXI, "usb_axi", "usb_bus", 0),
+	JH7100_GATE(JH7100_CLK_USBNOC_AXI, "usbnoc_axi", "usb_bus", 0),
+	JH7100__DIV(JH7100_CLK_USBPHY_ROOTDIV, "usbphy_rootdiv", "gmacusb_root", 4),
+	JH7100_GDIV(JH7100_CLK_USBPHY_125M, "usbphy_125m", "usbphy_rootdiv", 8, 0),
+	JH7100_GDIV(JH7100_CLK_USBPHY_PLLDIV25M, "usbphy_plldiv25m", "usbphy_rootdiv", 32, 0),
+	JH7100__MUX(JH7100_CLK_USBPHY_25M, "usbphy_25m", usbphy_25m_sels),
+	JH7100__DIV(JH7100_CLK_AUDIO_DIV, "audio_div", "audio_root", 131072),
+	JH7100_GATE(JH7100_CLK_AUDIO_SRC, "audio_src", "audio_div", 0),
+	JH7100_GATE(JH7100_CLK_AUDIO_12288, "audio_12288", "osc_aud", 0),
+	JH7100_GDIV(JH7100_CLK_VIN_SRC, "vin_src", "vin_root", 4, 0),
+	JH7100__DIV(JH7100_CLK_ISP0_BUS, "isp0_bus", "vin_src", 8),
+	JH7100_GATE(JH7100_CLK_ISP0_AXI, "isp0_axi", "isp0_bus", 0),
+	JH7100_GATE(JH7100_CLK_ISP0NOC_AXI, "isp0noc_axi", "isp0_bus", 0),
+	JH7100_GATE(JH7100_CLK_ISPSLV_AXI, "ispslv_axi", "isp0_bus", 0),
+	JH7100__DIV(JH7100_CLK_ISP1_BUS, "isp1_bus", "vin_src", 8),
+	JH7100_GATE(JH7100_CLK_ISP1_AXI, "isp1_axi", "isp1_bus", 0),
+	JH7100_GATE(JH7100_CLK_ISP1NOC_AXI, "isp1noc_axi", "isp1_bus", 0),
+	JH7100__DIV(JH7100_CLK_VIN_BUS, "vin_bus", "vin_src", 8),
+	JH7100_GATE(JH7100_CLK_VIN_AXI, "vin_axi", "vin_bus", 0),
+	JH7100_GATE(JH7100_CLK_VINNOC_AXI, "vinnoc_axi", "vin_bus", 0),
+	JH7100_GDIV(JH7100_CLK_VOUT_SRC, "vout_src", "vout_root", 4, 0),
+	JH7100__DIV(JH7100_CLK_DISPBUS_SRC, "dispbus_src", "voutbus_root", 4),
+	JH7100__DIV(JH7100_CLK_DISP_BUS, "disp_bus", "dispbus_src", 4),
+	JH7100_GATE(JH7100_CLK_DISP_AXI, "disp_axi", "disp_bus", 0),
+	JH7100_GATE(JH7100_CLK_DISPNOC_AXI, "dispnoc_axi", "disp_bus", 0),
+	JH7100_GATE(JH7100_CLK_SDIO0_AHB, "sdio0_ahb", "ahb_bus", 0),
+	JH7100_GDIV(JH7100_CLK_SDIO0_CCLKINT, "sdio0_cclkint", "perh0_src", 24, 0),
+	JH7100__INV(JH7100_CLK_SDIO0_CCLKINT_INV, "sdio0_cclkint_inv", "sdio0_cclkint"),
+	JH7100_GATE(JH7100_CLK_SDIO1_AHB, "sdio1_ahb", "ahb_bus", 0),
+	JH7100_GDIV(JH7100_CLK_SDIO1_CCLKINT, "sdio1_cclkint", "perh1_src", 24, 0),
+	JH7100__INV(JH7100_CLK_SDIO1_CCLKINT_INV, "sdio1_cclkint_inv", "sdio1_cclkint"),
+	JH7100_GATE(JH7100_CLK_GMAC_AHB, "gmac_ahb", "ahb_bus", 0),
+	JH7100__DIV(JH7100_CLK_GMAC_ROOT_DIV, "gmac_root_div", "gmacusb_root", 8),
+	JH7100_GDIV(JH7100_CLK_GMAC_PTP_REF, "gmac_ptp_refclk", "gmac_root_div", 31, 0),
+	JH7100_GDIV(JH7100_CLK_GMAC_GTX, "gmac_gtxclk", "gmac_root_div", 255, 0),
+	JH7100_GDIV(JH7100_CLK_GMAC_RMII_TX, "gmac_rmii_txclk", "gmac_rmii_ref", 8, 0),
+	JH7100_GDIV(JH7100_CLK_GMAC_RMII_RX, "gmac_rmii_rxclk", "gmac_rmii_ref", 8, 0),
+	JH7100__MUX(JH7100_CLK_GMAC_TX, "gmac_tx", gmac_tx_sels),
+	JH7100__INV(JH7100_CLK_GMAC_TX_INV, "gmac_tx_inv", "gmac_tx"),
+	JH7100__MUX(JH7100_CLK_GMAC_RX_PRE, "gmac_rx_pre", gmac_rx_pre_sels),
+	JH7100__INV(JH7100_CLK_GMAC_RX_INV, "gmac_rx_inv", "gmac_rx_pre"),
+	JH7100_GATE(JH7100_CLK_GMAC_RMII, "gmac_rmii", "gmac_rmii_ref", 0),
+	JH7100_GDIV(JH7100_CLK_GMAC_TOPHYREF, "gmac_tophyref", "gmac_root_div", 127, 0),
+	JH7100_GATE(JH7100_CLK_SPI2AHB_AHB, "spi2ahb_ahb", "ahb_bus", 0),
+	JH7100_GDIV(JH7100_CLK_SPI2AHB_CORE, "spi2ahb_core", "perh0_src", 31, 0),
+	JH7100_GATE(JH7100_CLK_EZMASTER_AHB, "ezmaster_ahb", "ahb_bus", 0),
+	JH7100_GATE(JH7100_CLK_E24_AHB, "e24_ahb", "ahb_bus", 0),
+	JH7100_GATE(JH7100_CLK_E24RTC_TOGGLE, "e24rtc_toggle", "osc_sys", 0),
+	JH7100_GATE(JH7100_CLK_QSPI_AHB, "qspi_ahb", "ahb_bus", 0),
+	JH7100_GATE(JH7100_CLK_QSPI_APB, "qspi_apb", "apb1_bus", 0),
+	JH7100_GDIV(JH7100_CLK_QSPI_REF, "qspi_refclk", "perh0_src", 31, 0),
+	JH7100_GATE(JH7100_CLK_SEC_AHB, "sec_ahb", "ahb_bus", 0),
+	JH7100_GATE(JH7100_CLK_AES, "aes_clk", "sec_ahb", 0),
+	JH7100_GATE(JH7100_CLK_SHA, "sha_clk", "sec_ahb", 0),
+	JH7100_GATE(JH7100_CLK_PKA, "pka_clk", "sec_ahb", 0),
+	JH7100_GATE(JH7100_CLK_TRNG_APB, "trng_apb", "apb1_bus", 0),
+	JH7100_GATE(JH7100_CLK_OTP_APB, "otp_apb", "apb1_bus", 0),
+	JH7100_GATE(JH7100_CLK_UART0_APB, "uart0_apb", "apb1_bus", 0),
+	JH7100_GDIV(JH7100_CLK_UART0_CORE, "uart0_core", "perh1_src", 63, 0),
+	JH7100_GATE(JH7100_CLK_UART1_APB, "uart1_apb", "apb1_bus", 0),
+	JH7100_GDIV(JH7100_CLK_UART1_CORE, "uart1_core", "perh1_src", 63, 0),
+	JH7100_GATE(JH7100_CLK_SPI0_APB, "spi0_apb", "apb1_bus", 0),
+	JH7100_GDIV(JH7100_CLK_SPI0_CORE, "spi0_core", "perh1_src", 63, 0),
+	JH7100_GATE(JH7100_CLK_SPI1_APB, "spi1_apb", "apb1_bus", 0),
+	JH7100_GDIV(JH7100_CLK_SPI1_CORE, "spi1_core", "perh1_src", 63, 0),
+	JH7100_GATE(JH7100_CLK_I2C0_APB, "i2c0_apb", "apb1_bus", 0),
+	JH7100_GDIV(JH7100_CLK_I2C0_CORE, "i2c0_core", "perh1_src", 63, 0),
+	JH7100_GATE(JH7100_CLK_I2C1_APB, "i2c1_apb", "apb1_bus", 0),
+	JH7100_GDIV(JH7100_CLK_I2C1_CORE, "i2c1_core", "perh1_src", 63, 0),
+	JH7100_GATE(JH7100_CLK_GPIO_APB, "gpio_apb", "apb1_bus", 0),
+	JH7100_GATE(JH7100_CLK_UART2_APB, "uart2_apb", "apb2_bus", 0),
+	JH7100_GDIV(JH7100_CLK_UART2_CORE, "uart2_core", "perh0_src", 63, 0),
+	JH7100_GATE(JH7100_CLK_UART3_APB, "uart3_apb", "apb2_bus", 0),
+	JH7100_GDIV(JH7100_CLK_UART3_CORE, "uart3_core", "perh0_src", 63, 0),
+	JH7100_GATE(JH7100_CLK_SPI2_APB, "spi2_apb", "apb2_bus", 0),
+	JH7100_GDIV(JH7100_CLK_SPI2_CORE, "spi2_core", "perh0_src", 63, 0),
+	JH7100_GATE(JH7100_CLK_SPI3_APB, "spi3_apb", "apb2_bus", 0),
+	JH7100_GDIV(JH7100_CLK_SPI3_CORE, "spi3_core", "perh0_src", 63, 0),
+	JH7100_GATE(JH7100_CLK_I2C2_APB, "i2c2_apb", "apb2_bus", 0),
+	JH7100_GDIV(JH7100_CLK_I2C2_CORE, "i2c2_core", "perh0_src", 63, 0),
+	JH7100_GATE(JH7100_CLK_I2C3_APB, "i2c3_apb", "apb2_bus", 0),
+	JH7100_GDIV(JH7100_CLK_I2C3_CORE, "i2c3_core", "perh0_src", 63, 0),
+	JH7100_GATE(JH7100_CLK_WDTIMER_APB, "wdtimer_apb", "apb2_bus", 0),
+	JH7100_GDIV(JH7100_CLK_WDT_CORE, "wdt_coreclk", "perh0_src", 63, 0),
+	JH7100_GDIV(JH7100_CLK_TIMER0_CORE, "timer0_coreclk", "perh0_src", 63, 0),
+	JH7100_GDIV(JH7100_CLK_TIMER1_CORE, "timer1_coreclk", "perh0_src", 63, 0),
+	JH7100_GDIV(JH7100_CLK_TIMER2_CORE, "timer2_coreclk", "perh0_src", 63, 0),
+	JH7100_GDIV(JH7100_CLK_TIMER3_CORE, "timer3_coreclk", "perh0_src", 63, 0),
+	JH7100_GDIV(JH7100_CLK_TIMER4_CORE, "timer4_coreclk", "perh0_src", 63, 0),
+	JH7100_GDIV(JH7100_CLK_TIMER5_CORE, "timer5_coreclk", "perh0_src", 63, 0),
+	JH7100_GDIV(JH7100_CLK_TIMER6_CORE, "timer6_coreclk", "perh0_src", 63, 0),
+	JH7100_GATE(JH7100_CLK_VP6INTC_APB, "vp6intc_apb", "apb2_bus", 0),
+	JH7100_GATE(JH7100_CLK_PWM_APB, "pwm_apb", "apb2_bus", 0),
+	JH7100_GATE(JH7100_CLK_MSI_APB, "msi_apb", "apb2_bus", 0),
+	JH7100_GATE(JH7100_CLK_TEMP_APB, "temp_apb", "apb2_bus", 0),
+	JH7100_GDIV(JH7100_CLK_TEMP_SENSE, "temp_sense", "osc_sys", 31, 0),
+	JH7100_GATE(JH7100_CLK_SYSERR_APB, "syserr_apb", "apb2_bus", 0),
+};
+
+static struct clk_hw *clk_starfive_jh7100_get(struct of_phandle_args *clkspec, void *data)
+{
+	struct clk_starfive_jh7100_priv *priv = data;
+	unsigned int idx = clkspec->args[0];
+
+	if (idx >= JH7100_CLK_END) {
+		dev_err(priv->dev, "invalid clock index %u\n", idx);
+		return ERR_PTR(-EINVAL);
+	}
+
+	if (idx >= JH7100_CLK_PLL0_OUT)
+		return priv->pll[idx - JH7100_CLK_PLL0_OUT];
+
+	return &priv->reg[idx].hw;
+}
+
+static int __init clk_starfive_jh7100_probe(struct platform_device *pdev)
+{
+	struct clk_starfive_jh7100_priv *priv;
+	unsigned int idx;
+	int ret;
+
+	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	spin_lock_init(&priv->rmw_lock);
+	priv->dev = &pdev->dev;
+	priv->base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(priv->base))
+		return PTR_ERR(priv->base);
+
+	priv->pll[0] = devm_clk_hw_register_fixed_factor(priv->dev, "pll0_out",
+							 "osc_sys", 0, 40, 1);
+	if (IS_ERR(priv->pll[0]))
+		return PTR_ERR(priv->pll[0]);
+
+	priv->pll[1] = devm_clk_hw_register_fixed_factor(priv->dev, "pll1_out",
+							 "osc_sys", 0, 64, 1);
+	if (IS_ERR(priv->pll[1]))
+		return PTR_ERR(priv->pll[1]);
+
+	priv->pll[2] = devm_clk_hw_register_fixed_factor(priv->dev, "pll2_out",
+							 "pll2_refclk", 0, 55, 1);
+	if (IS_ERR(priv->pll[2]))
+		return PTR_ERR(priv->pll[2]);
+
+	for (idx = 0; idx < JH7100_CLK_PLL0_OUT; idx++) {
+		u32 max_parent = (jh7100_clk_data[idx].max & JH7100_CLK_MUX_MASK) >>
+				 JH7100_CLK_MUX_SHIFT;
+		struct clk_init_data init = {
+			.name = jh7100_clk_data[idx].name,
+			.ops = jh7100_clk_data[idx].ops,
+			.num_parents = max_parent + 1,
+			.flags = jh7100_clk_data[idx].flags,
+		};
+		struct jh7100_clk *clk = &priv->reg[idx];
+
+		if (init.num_parents > 1)
+			init.parent_names = jh7100_clk_data[idx].parents;
+		else
+			init.parent_names = &jh7100_clk_data[idx].parent;
+
+		clk->hw.init = &init;
+		clk->idx = idx;
+		clk->max = jh7100_clk_data[idx].max;
+
+		ret = clk_hw_register(priv->dev, &clk->hw);
+		if (ret)
+			goto err;
+	}
+
+	ret = devm_of_clk_add_hw_provider(priv->dev, clk_starfive_jh7100_get, priv);
+	if (ret)
+		goto err;
+
+	return 0;
+err:
+	while (idx)
+		clk_hw_unregister(&priv->reg[--idx].hw);
+	return ret;
+}
+
+static const struct of_device_id clk_starfive_jh7100_match[] = {
+	{ .compatible = "starfive,jh7100-clkgen" },
+	{ /* sentinel */ }
+};
+
+static struct platform_driver clk_starfive_jh7100_driver = {
+	.probe = clk_starfive_jh7100_probe,
+	.driver = {
+		.name = "clk-starfive-jh7100",
+		.of_match_table = clk_starfive_jh7100_match,
+	},
+};
+builtin_platform_driver(clk_starfive_jh7100_driver);
+
+MODULE_DESCRIPTION("StarFive JH7100 Clock Generator Driver");
+MODULE_AUTHOR("Emil Renner Berthing <kernel@esmil.dk>");
+MODULE_AUTHOR("Geert Uytterhoeven <geert@linux-m68k.org>");
+MODULE_LICENSE("GPL v2");
-- 
2.33.1


^ permalink raw reply related	[flat|nested] 143+ messages in thread

* [PATCH v2 06/16] clk: starfive: Add JH7100 clock generator driver
@ 2021-10-21 17:42   ` Emil Renner Berthing
  0 siblings, 0 replies; 143+ messages in thread
From: Emil Renner Berthing @ 2021-10-21 17:42 UTC (permalink / raw)
  To: linux-riscv, devicetree, linux-clk, linux-gpio, linux-serial
  Cc: Geert Uytterhoeven, Palmer Dabbelt, Paul Walmsley, Rob Herring,
	Michael Turquette, Stephen Boyd, Thomas Gleixner, Marc Zyngier,
	Philipp Zabel, Linus Walleij, Greg Kroah-Hartman, Daniel Lezcano,
	Andy Shevchenko, Jiri Slaby, Maximilian Luz, Sagar Kadam,
	Drew Fustini, Michael Zhu, Fu Wei, Anup Patel, Atish Patra,
	Matteo Croce, linux-kernel, Emil Renner Berthing

From: Geert Uytterhoeven <geert@linux-m68k.org>

Add a driver for the StarFive JH7100 clock generator.

Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
Co-developed-by: Emil Renner Berthing <kernel@esmil.dk>
Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
---
 MAINTAINERS                                |   7 +
 drivers/clk/Kconfig                        |   1 +
 drivers/clk/Makefile                       |   1 +
 drivers/clk/starfive/Kconfig               |   9 +
 drivers/clk/starfive/Makefile              |   3 +
 drivers/clk/starfive/clk-starfive-jh7100.c | 776 +++++++++++++++++++++
 6 files changed, 797 insertions(+)
 create mode 100644 drivers/clk/starfive/Kconfig
 create mode 100644 drivers/clk/starfive/Makefile
 create mode 100644 drivers/clk/starfive/clk-starfive-jh7100.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 8d118d7957d2..e5a19b70dfbb 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -17848,6 +17848,13 @@ M:	Ion Badulescu <ionut@badula.org>
 S:	Odd Fixes
 F:	drivers/net/ethernet/adaptec/starfire*
 
+STARFIVE JH7100 CLOCK DRIVER
+M:	Emil Renner Berthing <kernel@esmil.dk>
+S:	Maintained
+F:	Documentation/devicetree/bindings/clock/starfive,jh7100-clkgen.yaml
+F:	drivers/clk/starfive/clk-starfive-jh7100.c
+F:	include/dt-bindings/clock/starfive-jh7100.h
+
 STATIC BRANCH/CALL
 M:	Peter Zijlstra <peterz@infradead.org>
 M:	Josh Poimboeuf <jpoimboe@redhat.com>
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index c5b3dc97396a..c91931c94888 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -412,6 +412,7 @@ source "drivers/clk/samsung/Kconfig"
 source "drivers/clk/sifive/Kconfig"
 source "drivers/clk/socfpga/Kconfig"
 source "drivers/clk/sprd/Kconfig"
+source "drivers/clk/starfive/Kconfig"
 source "drivers/clk/sunxi/Kconfig"
 source "drivers/clk/sunxi-ng/Kconfig"
 source "drivers/clk/tegra/Kconfig"
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index e42312121e51..a9bb2478fbdd 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -109,6 +109,7 @@ obj-y					+= socfpga/
 obj-$(CONFIG_PLAT_SPEAR)		+= spear/
 obj-y					+= sprd/
 obj-$(CONFIG_ARCH_STI)			+= st/
+obj-$(CONFIG_SOC_STARFIVE)		+= starfive/
 obj-$(CONFIG_ARCH_SUNXI)		+= sunxi/
 obj-$(CONFIG_SUNXI_CCU)			+= sunxi-ng/
 obj-$(CONFIG_ARCH_TEGRA)		+= tegra/
diff --git a/drivers/clk/starfive/Kconfig b/drivers/clk/starfive/Kconfig
new file mode 100644
index 000000000000..c0fa9d5e641f
--- /dev/null
+++ b/drivers/clk/starfive/Kconfig
@@ -0,0 +1,9 @@
+# SPDX-License-Identifier: GPL-2.0
+
+config CLK_STARFIVE_JH7100
+	bool "StarFive JH7100 clock support"
+	depends on SOC_STARFIVE || COMPILE_TEST
+	default SOC_STARFIVE
+	help
+	  Say yes here to support the clock controller on the StarFive JH7100
+	  SoC.
diff --git a/drivers/clk/starfive/Makefile b/drivers/clk/starfive/Makefile
new file mode 100644
index 000000000000..09759cc73530
--- /dev/null
+++ b/drivers/clk/starfive/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0
+# StarFive Clock
+obj-$(CONFIG_CLK_STARFIVE_JH7100)	+= clk-starfive-jh7100.o
diff --git a/drivers/clk/starfive/clk-starfive-jh7100.c b/drivers/clk/starfive/clk-starfive-jh7100.c
new file mode 100644
index 000000000000..f109576f18c5
--- /dev/null
+++ b/drivers/clk/starfive/clk-starfive-jh7100.c
@@ -0,0 +1,776 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * StarFive JH7100 Clock Generator Driver
+ *
+ * Copyright 2021 Ahmad Fatoum, Pengutronix
+ * Copyright (C) 2021 Glider bv
+ * Copyright (C) 2021 Emil Renner Berthing <kernel@esmil.dk>
+ */
+
+#include <linux/bits.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/debugfs.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/overflow.h>
+#include <linux/platform_device.h>
+
+#include <dt-bindings/clock/starfive-jh7100.h>
+
+#define JH7100_CLK_ENABLE_SHIFT	31
+#define JH7100_CLK_INVERT_SHIFT	30
+#define JH7100_CLK_MUX_SHIFT	24
+
+#define JH7100_CLK_ENABLE	BIT(31)
+#define JH7100_CLK_INVERT	BIT(30)
+#define JH7100_CLK_MUX_MASK	GENMASK(27, 24)
+#define JH7100_CLK_DIV_MASK	GENMASK(23, 0)
+
+static const char *const cpundbus_root_sels[] __initconst = {
+	[0] = "osc_sys",
+	[1] = "pll0_out",
+	[2] = "pll1_out",
+	[3] = "pll2_out",
+};
+
+static const char *const dla_root_sels[] __initconst = {
+	[0] = "osc_sys",
+	[1] = "pll1_out",
+	[2] = "pll2_out",
+};
+
+static const char *const dsp_root_sels[] __initconst = {
+	[0] = "osc_sys",
+	[1] = "pll0_out",
+	[2] = "pll1_out",
+	[3] = "pll2_out",
+};
+
+static const char *const gmacusb_root_sels[] __initconst = {
+	[0] = "osc_sys",
+	[1] = "pll0_out",
+	[2] = "pll2_out",
+};
+
+static const char *const perh0_root_sels[] __initconst = {
+	[0] = "osc_sys",
+	[1] = "pll0_out",
+};
+
+static const char *const perh1_root_sels[] __initconst = {
+	[0] = "osc_sys",
+	[1] = "pll2_out",
+};
+
+static const char *const vin_root_sels[] __initconst = {
+	[0] = "osc_sys",
+	[1] = "pll1_out",
+	[2] = "pll2_out",
+};
+
+static const char *const vout_root_sels[] __initconst = {
+	[0] = "osc_aud",
+	[1] = "pll0_out",
+	[2] = "pll2_out",
+};
+
+static const char *const cdechifi4_root_sels[] __initconst = {
+	[0] = "osc_sys",
+	[1] = "pll1_out",
+	[2] = "pll2_out",
+};
+
+static const char *const cdec_root_sels[] __initconst = {
+	[0] = "osc_sys",
+	[1] = "pll0_out",
+	[2] = "pll1_out",
+};
+
+static const char *const voutbus_root_sels[] __initconst = {
+	[0] = "osc_aud",
+	[1] = "pll0_out",
+	[2] = "pll2_out",
+};
+
+static const char *const pll2_refclk_sels[] __initconst = {
+	[0] = "osc_sys",
+	[1] = "osc_aud",
+};
+
+static const char *const ddrc0_sels[] __initconst = {
+	[0] = "ddrosc_div2",
+	[1] = "ddrpll_div2",
+	[2] = "ddrpll_div4",
+	[3] = "ddrpll_div8",
+};
+
+static const char *const ddrc1_sels[] __initconst = {
+	[0] = "ddrosc_div2",
+	[1] = "ddrpll_div2",
+	[2] = "ddrpll_div4",
+	[3] = "ddrpll_div8",
+};
+
+static const char *const nne_bus_sels[] __initconst = {
+	[0] = "cpu_axi",
+	[1] = "nnebus_src1",
+};
+
+static const char *const usbphy_25m_sels[] __initconst = {
+	[0] = "osc_sys",
+	[1] = "usbphy_plldiv25m",
+};
+
+static const char *const gmac_tx_sels[] __initconst = {
+	[0] = "gmac_gtxclk",
+	[1] = "gmac_mii_txclk",
+	[2] = "gmac_rmii_txclk",
+};
+
+static const char *const gmac_rx_pre_sels[] __initconst = {
+	[0] = "gmac_gr_mii_rxclk",
+	[1] = "gmac_rmii_rxclk",
+};
+
+struct jh7100_clk {
+	struct clk_hw hw;
+	unsigned int idx;
+	u32 max;
+};
+
+struct clk_starfive_jh7100_priv {
+	/* protect registers against overlapping read-modify-write */
+	spinlock_t rmw_lock;
+	struct device *dev;
+	void __iomem *base;
+	struct clk_hw *pll[3];
+	struct jh7100_clk reg[JH7100_CLK_PLL0_OUT];
+};
+
+static struct jh7100_clk *jh7100_clk_from(struct clk_hw *hw)
+{
+	return container_of(hw, struct jh7100_clk, hw);
+}
+
+static struct clk_starfive_jh7100_priv *jh7100_priv_from(struct jh7100_clk *clk)
+{
+	return container_of(clk, struct clk_starfive_jh7100_priv, reg[clk->idx]);
+}
+
+static u32 jh7100_clk_reg_get(struct jh7100_clk *clk)
+{
+	struct clk_starfive_jh7100_priv *priv = jh7100_priv_from(clk);
+	void __iomem *reg = priv->base + 4 * clk->idx;
+
+	return readl_relaxed(reg);
+}
+
+static void jh7100_clk_reg_rmw(struct jh7100_clk *clk, u32 mask, u32 value)
+{
+	struct clk_starfive_jh7100_priv *priv = jh7100_priv_from(clk);
+	void __iomem *reg = priv->base + 4 * clk->idx;
+	unsigned long flags;
+
+	spin_lock_irqsave(&priv->rmw_lock, flags);
+	value |= readl_relaxed(reg) & ~mask;
+	writel_relaxed(value, reg);
+	spin_unlock_irqrestore(&priv->rmw_lock, flags);
+}
+
+static int jh7100_clk_enable(struct clk_hw *hw)
+{
+	struct jh7100_clk *clk = jh7100_clk_from(hw);
+
+	dev_dbg(jh7100_priv_from(clk)->dev, "enable(%s)\n", clk_hw_get_name(&clk->hw));
+
+	jh7100_clk_reg_rmw(clk, JH7100_CLK_ENABLE, JH7100_CLK_ENABLE);
+	return 0;
+}
+
+static void jh7100_clk_disable(struct clk_hw *hw)
+{
+	struct jh7100_clk *clk = jh7100_clk_from(hw);
+
+	dev_dbg(jh7100_priv_from(clk)->dev, "disable(%s)\n", clk_hw_get_name(&clk->hw));
+
+	jh7100_clk_reg_rmw(clk, JH7100_CLK_ENABLE, 0);
+}
+
+static int jh7100_clk_is_enabled(struct clk_hw *hw)
+{
+	struct jh7100_clk *clk = jh7100_clk_from(hw);
+
+	return !!(jh7100_clk_reg_get(clk) & JH7100_CLK_ENABLE);
+}
+
+static int jh7100_clk_is_parent_enabled(struct clk_hw *hw)
+{
+	return clk_hw_is_enabled(clk_hw_get_parent(hw));
+}
+
+static unsigned long jh7100_clk_recalc_rate(struct clk_hw *hw,
+					    unsigned long parent_rate)
+{
+	struct jh7100_clk *clk = jh7100_clk_from(hw);
+	u32 value = jh7100_clk_reg_get(clk) & JH7100_CLK_DIV_MASK;
+	unsigned long rate;
+
+	if (value)
+		rate = parent_rate / value;
+	else
+		rate = 0;
+
+	dev_dbg(jh7100_priv_from(clk)->dev, "recalc_rate(%s, %lu) = %lu (div %u)\n",
+		clk_hw_get_name(&clk->hw), parent_rate, rate, value);
+
+	return rate;
+}
+
+static unsigned long jh7100_clk_bestdiv(struct jh7100_clk *clk,
+					unsigned long rate, unsigned long parent)
+{
+	unsigned long max = clk->max & JH7100_CLK_DIV_MASK;
+	unsigned long div = DIV_ROUND_UP(parent, rate);
+
+	return min(div, max);
+}
+
+static int jh7100_clk_determine_rate(struct clk_hw *hw,
+				     struct clk_rate_request *req)
+{
+	struct jh7100_clk *clk = jh7100_clk_from(hw);
+	unsigned long parent = req->best_parent_rate;
+	unsigned long rate = clamp(req->rate, req->min_rate, req->max_rate);
+	unsigned long div = jh7100_clk_bestdiv(clk, rate, parent);
+	unsigned long result = parent / div;
+
+	/*
+	 * We want the result clamped by min_rate and max_rate if possible:
+	 * Case 1: div hits the max divider value, which means it's less than
+	 * parent / rate, so the result is greater than rate and min_rate in
+	 * particular. We can't do anything about result > max_rate because the
+	 * divider doesn't go any further.
+	 * Case 2: div = DIV_ROUND_UP(parent, rate) which means the result is
+	 * always lower or equal to rate and max_rate.  However the result may
+	 * turn out lower than min_rate, but then the next higher rate is fine:
+	 *   div - 1 = ceil(parent / rate) - 1 < parent / rate
+	 * and thus
+	 *   min_rate <= rate < parent / (div - 1)
+	 */
+	if (result < req->min_rate && div > 1) {
+		div -= 1;
+		result = parent / div;
+	}
+
+	dev_dbg(jh7100_priv_from(clk)->dev,
+		"determine_rate(%s, {%lu<=%lu<=%lu from %lu}) = %lu (div %lu)\n",
+		clk_hw_get_name(&clk->hw), req->min_rate, req->rate, req->max_rate,
+		parent, result, div);
+
+	req->rate = result;
+	return 0;
+}
+
+static int jh7100_clk_set_rate(struct clk_hw *hw,
+			       unsigned long rate,
+			       unsigned long parent_rate)
+{
+	struct jh7100_clk *clk = jh7100_clk_from(hw);
+	unsigned long div = jh7100_clk_bestdiv(clk, rate, parent_rate);
+
+	dev_dbg(jh7100_priv_from(clk)->dev,
+		"set_rate(%s, %lu, %lu) = %lu (div %lu)\n",
+		clk_hw_get_name(&clk->hw), rate, parent_rate,
+		parent_rate / div, div);
+
+	jh7100_clk_reg_rmw(clk, JH7100_CLK_DIV_MASK, div);
+	return 0;
+}
+
+static u8 jh7100_clk_get_parent(struct clk_hw *hw)
+{
+	struct jh7100_clk *clk = jh7100_clk_from(hw);
+	u32 value = jh7100_clk_reg_get(clk);
+
+	return (value & JH7100_CLK_MUX_MASK) >> JH7100_CLK_MUX_SHIFT;
+}
+
+static int jh7100_clk_set_parent(struct clk_hw *hw, u8 index)
+{
+	struct jh7100_clk *clk = jh7100_clk_from(hw);
+	u32 value = (u32)index << JH7100_CLK_MUX_SHIFT;
+
+	dev_dbg(jh7100_priv_from(clk)->dev, "set_parent(%s, %u)\n",
+		clk_hw_get_name(&clk->hw), index);
+
+	jh7100_clk_reg_rmw(clk, JH7100_CLK_MUX_MASK, value);
+	return 0;
+}
+
+static int jh7100_clk_mux_determine_rate(struct clk_hw *hw,
+					 struct clk_rate_request *req)
+{
+	struct jh7100_clk *clk = jh7100_clk_from(hw);
+	int ret = clk_mux_determine_rate_flags(&clk->hw, req, 0);
+
+	dev_dbg(jh7100_priv_from(clk)->dev, "determine_rate(%s) = %d\n",
+		clk_hw_get_name(&clk->hw), ret);
+
+	return ret;
+}
+
+static int jh7100_clk_get_phase(struct clk_hw *hw)
+{
+	struct jh7100_clk *clk = jh7100_clk_from(hw);
+	u32 value = jh7100_clk_reg_get(clk);
+
+	return (value & JH7100_CLK_INVERT) ? 180 : 0;
+}
+
+static int jh7100_clk_set_phase(struct clk_hw *hw, int degrees)
+{
+	struct jh7100_clk *clk = jh7100_clk_from(hw);
+	u32 value;
+
+	dev_dbg(jh7100_priv_from(clk)->dev, "set_phase(%s, %d)\n",
+		clk_hw_get_name(&clk->hw), degrees);
+
+	if (degrees == 0)
+		value = 0;
+	else if (degrees == 180)
+		value = JH7100_CLK_INVERT;
+	else
+		return -EINVAL;
+
+	jh7100_clk_reg_rmw(clk, JH7100_CLK_INVERT, value);
+	return 0;
+}
+
+#ifdef CONFIG_DEBUG_FS
+static void jh7100_clk_debug_init(struct clk_hw *hw, struct dentry *dentry)
+{
+	static const struct debugfs_reg32 jh7100_clk_reg = {
+		.name = "CTRL",
+		.offset = 0,
+	};
+	struct jh7100_clk *clk = jh7100_clk_from(hw);
+	struct clk_starfive_jh7100_priv *priv = jh7100_priv_from(clk);
+	struct debugfs_regset32 *regset;
+
+	regset = devm_kzalloc(priv->dev, sizeof(*regset), GFP_KERNEL);
+	if (!regset)
+		return;
+
+	regset->regs = &jh7100_clk_reg;
+	regset->nregs = 1;
+	regset->base = priv->base + 4 * clk->idx;
+
+	debugfs_create_regset32("registers", 0400, dentry, regset);
+}
+#else
+#define jh7100_clk_debug_init NULL
+#endif
+
+static const struct clk_ops jh7100_clk_gate_ops = {
+	.enable = jh7100_clk_enable,
+	.disable = jh7100_clk_disable,
+	.is_enabled = jh7100_clk_is_enabled,
+	.debug_init = jh7100_clk_debug_init,
+};
+
+static const struct clk_ops jh7100_clk_div_ops = {
+	.is_enabled = jh7100_clk_is_parent_enabled,
+	.recalc_rate = jh7100_clk_recalc_rate,
+	.determine_rate = jh7100_clk_determine_rate,
+	.set_rate = jh7100_clk_set_rate,
+	.debug_init = jh7100_clk_debug_init,
+};
+
+static const struct clk_ops jh7100_clk_gdiv_ops = {
+	.enable = jh7100_clk_enable,
+	.disable = jh7100_clk_disable,
+	.is_enabled = jh7100_clk_is_enabled,
+	.recalc_rate = jh7100_clk_recalc_rate,
+	.determine_rate = jh7100_clk_determine_rate,
+	.set_rate = jh7100_clk_set_rate,
+	.debug_init = jh7100_clk_debug_init,
+};
+
+static const struct clk_ops jh7100_clk_mux_ops = {
+	.is_enabled = jh7100_clk_is_parent_enabled,
+	.get_parent = jh7100_clk_get_parent,
+	.set_parent = jh7100_clk_set_parent,
+	.determine_rate = jh7100_clk_mux_determine_rate,
+	.debug_init = jh7100_clk_debug_init,
+};
+
+static const struct clk_ops jh7100_clk_gmux_ops = {
+	.enable = jh7100_clk_enable,
+	.disable = jh7100_clk_disable,
+	.is_enabled = jh7100_clk_is_enabled,
+	.get_parent = jh7100_clk_get_parent,
+	.set_parent = jh7100_clk_set_parent,
+	.determine_rate = jh7100_clk_mux_determine_rate,
+	.debug_init = jh7100_clk_debug_init,
+};
+
+static const struct clk_ops jh7100_clk_inv_ops = {
+	.is_enabled = jh7100_clk_is_parent_enabled,
+	.get_phase = jh7100_clk_get_phase,
+	.set_phase = jh7100_clk_set_phase,
+	.debug_init = jh7100_clk_debug_init,
+};
+
+#define JH7100_GATE(_idx, _name, _parent, _flags) [_idx] = { \
+	.name = _name, \
+	.ops = &jh7100_clk_gate_ops, \
+	.parent = _parent, \
+	.flags = CLK_SET_RATE_PARENT | (_flags), \
+	.max = JH7100_CLK_ENABLE, \
+}
+
+#define JH7100__DIV(_idx, _name, _parent, _max) [_idx] = { \
+	.name = _name, \
+	.ops = &jh7100_clk_div_ops, \
+	.parent = _parent, \
+	.flags = 0, \
+	.max = _max, \
+}
+
+#define JH7100_GDIV(_idx, _name, _parent, _max, _flags) [_idx] = { \
+	.name = _name, \
+	.ops = &jh7100_clk_gdiv_ops, \
+	.parent = _parent, \
+	.flags = (_flags), \
+	.max = JH7100_CLK_ENABLE | (_max), \
+}
+
+#define JH7100__MUX(_idx, _name, _parents) [_idx] = { \
+	.name = _name, \
+	.ops = &jh7100_clk_mux_ops, \
+	.parents = _parents, \
+	.flags = 0, \
+	.max = (ARRAY_SIZE(_parents) - 1) << JH7100_CLK_MUX_SHIFT, \
+}
+
+#define JH7100_GMUX(_idx, _name, _parents, _flags) [_idx] = { \
+	.name = _name, \
+	.ops = &jh7100_clk_gmux_ops, \
+	.parents = _parents, \
+	.flags = (_flags), \
+	.max = JH7100_CLK_ENABLE | \
+		((ARRAY_SIZE(_parents) - 1) << JH7100_CLK_MUX_SHIFT), \
+}
+
+#define JH7100__INV(_idx, _name, _parent) [_idx] = { \
+	.name = _name, \
+	.ops = &jh7100_clk_inv_ops, \
+	.parent = _parent, \
+	.flags = CLK_SET_RATE_PARENT, \
+	.max = JH7100_CLK_INVERT, \
+}
+
+static const struct {
+	const char *name;
+	const struct clk_ops *ops;
+	union {
+		const char *parent;
+		const char *const *parents;
+	};
+	unsigned long flags;
+	u32 max;
+} jh7100_clk_data[] __initconst = {
+	JH7100__MUX(JH7100_CLK_CPUNDBUS_ROOT, "cpundbus_root", cpundbus_root_sels),
+	JH7100__MUX(JH7100_CLK_DLA_ROOT, "dla_root", dla_root_sels),
+	JH7100__MUX(JH7100_CLK_DSP_ROOT, "dsp_root", dsp_root_sels),
+	JH7100__MUX(JH7100_CLK_GMACUSB_ROOT, "gmacusb_root", gmacusb_root_sels),
+	JH7100__MUX(JH7100_CLK_PERH0_ROOT, "perh0_root", perh0_root_sels),
+	JH7100__MUX(JH7100_CLK_PERH1_ROOT, "perh1_root", perh1_root_sels),
+	JH7100__MUX(JH7100_CLK_VIN_ROOT, "vin_root", vin_root_sels),
+	JH7100__MUX(JH7100_CLK_VOUT_ROOT, "vout_root", vout_root_sels),
+	JH7100_GDIV(JH7100_CLK_AUDIO_ROOT, "audio_root", "pll0_out", 8, 0),
+	JH7100__MUX(JH7100_CLK_CDECHIFI4_ROOT, "cdechifi4_root", cdechifi4_root_sels),
+	JH7100__MUX(JH7100_CLK_CDEC_ROOT, "cdec_root", cdec_root_sels),
+	JH7100__MUX(JH7100_CLK_VOUTBUS_ROOT, "voutbus_root", voutbus_root_sels),
+	JH7100__DIV(JH7100_CLK_CPUNBUS_ROOT_DIV, "cpunbus_root_div", "cpundbus_root", 2),
+	JH7100__DIV(JH7100_CLK_DSP_ROOT_DIV, "dsp_root_div", "dsp_root", 4),
+	JH7100__DIV(JH7100_CLK_PERH0_SRC, "perh0_src", "perh0_root", 4),
+	JH7100__DIV(JH7100_CLK_PERH1_SRC, "perh1_src", "perh1_root", 4),
+	JH7100_GDIV(JH7100_CLK_PLL0_TESTOUT, "pll0_testout", "perh0_src", 31, 0),
+	JH7100_GDIV(JH7100_CLK_PLL1_TESTOUT, "pll1_testout", "dla_root", 31, 0),
+	JH7100_GDIV(JH7100_CLK_PLL2_TESTOUT, "pll2_testout", "perh1_src", 31, 0),
+	JH7100__MUX(JH7100_CLK_PLL2_REF, "pll2_refclk", pll2_refclk_sels),
+	JH7100__DIV(JH7100_CLK_CPU_CORE, "cpu_core", "cpunbus_root_div", 8),
+	JH7100__DIV(JH7100_CLK_CPU_AXI, "cpu_axi", "cpu_core", 8),
+	JH7100__DIV(JH7100_CLK_AHB_BUS, "ahb_bus", "cpunbus_root_div", 8),
+	JH7100__DIV(JH7100_CLK_APB1_BUS, "apb1_bus", "ahb_bus", 8),
+	JH7100__DIV(JH7100_CLK_APB2_BUS, "apb2_bus", "ahb_bus", 8),
+	JH7100_GATE(JH7100_CLK_DOM3AHB_BUS, "dom3ahb_bus", "ahb_bus", CLK_IGNORE_UNUSED),
+	JH7100_GATE(JH7100_CLK_DOM7AHB_BUS, "dom7ahb_bus", "ahb_bus", CLK_IGNORE_UNUSED),
+	JH7100_GATE(JH7100_CLK_U74_CORE0, "u74_core0", "cpu_core", CLK_IGNORE_UNUSED),
+	JH7100_GDIV(JH7100_CLK_U74_CORE1, "u74_core1", "cpu_core", 8, CLK_IGNORE_UNUSED),
+	JH7100_GATE(JH7100_CLK_U74_AXI, "u74_axi", "cpu_axi", CLK_IGNORE_UNUSED),
+	JH7100_GATE(JH7100_CLK_U74RTC_TOGGLE, "u74rtc_toggle", "osc_sys", CLK_IGNORE_UNUSED),
+	JH7100_GATE(JH7100_CLK_SGDMA2P_AXI, "sgdma2p_axi", "cpu_axi", 0),
+	JH7100_GATE(JH7100_CLK_DMA2PNOC_AXI, "dma2pnoc_axi", "cpu_axi", 0),
+	JH7100_GATE(JH7100_CLK_SGDMA2P_AHB, "sgdma2p_ahb", "ahb_bus", 0),
+	JH7100__DIV(JH7100_CLK_DLA_BUS, "dla_bus", "dla_root", 4),
+	JH7100_GATE(JH7100_CLK_DLA_AXI, "dla_axi", "dla_bus", 0),
+	JH7100_GATE(JH7100_CLK_DLANOC_AXI, "dlanoc_axi", "dla_bus", 0),
+	JH7100_GATE(JH7100_CLK_DLA_APB, "dla_apb", "apb1_bus", 0),
+	JH7100_GDIV(JH7100_CLK_VP6_CORE, "vp6_core", "dsp_root_div", 4, 0),
+	JH7100__DIV(JH7100_CLK_VP6BUS_SRC, "vp6bus_src", "dsp_root", 4),
+	JH7100_GDIV(JH7100_CLK_VP6_AXI, "vp6_axi", "vp6bus_src", 4, 0),
+	JH7100__DIV(JH7100_CLK_VCDECBUS_SRC, "vcdecbus_src", "cdechifi4_root", 4),
+	JH7100__DIV(JH7100_CLK_VDEC_BUS, "vdec_bus", "vcdecbus_src", 8),
+	JH7100_GATE(JH7100_CLK_VDEC_AXI, "vdec_axi", "vdec_bus", 0),
+	JH7100_GATE(JH7100_CLK_VDECBRG_MAIN, "vdecbrg_mainclk", "vdec_bus", 0),
+	JH7100_GDIV(JH7100_CLK_VDEC_BCLK, "vdec_bclk", "vcdecbus_src", 8, 0),
+	JH7100_GDIV(JH7100_CLK_VDEC_CCLK, "vdec_cclk", "cdec_root", 8, 0),
+	JH7100_GATE(JH7100_CLK_VDEC_APB, "vdec_apb", "apb1_bus", 0),
+	JH7100_GDIV(JH7100_CLK_JPEG_AXI, "jpeg_axi", "cpunbus_root_div", 8, 0),
+	JH7100_GDIV(JH7100_CLK_JPEG_CCLK, "jpeg_cclk", "cpunbus_root_div", 8, 0),
+	JH7100_GATE(JH7100_CLK_JPEG_APB, "jpeg_apb", "apb1_bus", 0),
+	JH7100_GDIV(JH7100_CLK_GC300_2X, "gc300_2x", "cdechifi4_root", 8, 0),
+	JH7100_GATE(JH7100_CLK_GC300_AHB, "gc300_ahb", "ahb_bus", 0),
+	JH7100__DIV(JH7100_CLK_JPCGC300_AXIBUS, "jpcgc300_axibus", "vcdecbus_src", 8),
+	JH7100_GATE(JH7100_CLK_GC300_AXI, "gc300_axi", "jpcgc300_axibus", 0),
+	JH7100_GATE(JH7100_CLK_JPCGC300_MAIN, "jpcgc300_mainclk", "jpcgc300_axibus", 0),
+	JH7100__DIV(JH7100_CLK_VENC_BUS, "venc_bus", "vcdecbus_src", 8),
+	JH7100_GATE(JH7100_CLK_VENC_AXI, "venc_axi", "venc_bus", 0),
+	JH7100_GATE(JH7100_CLK_VENCBRG_MAIN, "vencbrg_mainclk", "venc_bus", 0),
+	JH7100_GDIV(JH7100_CLK_VENC_BCLK, "venc_bclk", "vcdecbus_src", 8, 0),
+	JH7100_GDIV(JH7100_CLK_VENC_CCLK, "venc_cclk", "cdec_root", 8, 0),
+	JH7100_GATE(JH7100_CLK_VENC_APB, "venc_apb", "apb1_bus", 0),
+	JH7100_GDIV(JH7100_CLK_DDRPLL_DIV2, "ddrpll_div2", "pll1_out", 2, CLK_IGNORE_UNUSED),
+	JH7100_GDIV(JH7100_CLK_DDRPLL_DIV4, "ddrpll_div4", "ddrpll_div2", 2, CLK_IGNORE_UNUSED),
+	JH7100_GDIV(JH7100_CLK_DDRPLL_DIV8, "ddrpll_div8", "ddrpll_div4", 2, CLK_IGNORE_UNUSED),
+	JH7100_GDIV(JH7100_CLK_DDROSC_DIV2, "ddrosc_div2", "osc_sys", 2, CLK_IGNORE_UNUSED),
+	JH7100_GMUX(JH7100_CLK_DDRC0, "ddrc0", ddrc0_sels, CLK_IGNORE_UNUSED),
+	JH7100_GMUX(JH7100_CLK_DDRC1, "ddrc1", ddrc1_sels, CLK_IGNORE_UNUSED),
+	JH7100_GATE(JH7100_CLK_DDRPHY_APB, "ddrphy_apb", "apb1_bus", CLK_IGNORE_UNUSED),
+	JH7100__DIV(JH7100_CLK_NOC_ROB, "noc_rob", "cpunbus_root_div", 8),
+	JH7100__DIV(JH7100_CLK_NOC_COG, "noc_cog", "dla_root", 8),
+	JH7100_GATE(JH7100_CLK_NNE_AHB, "nne_ahb", "ahb_bus", 0),
+	JH7100__DIV(JH7100_CLK_NNEBUS_SRC1, "nnebus_src1", "dsp_root", 4),
+	JH7100__MUX(JH7100_CLK_NNE_BUS, "nne_bus", nne_bus_sels),
+	JH7100_GATE(JH7100_CLK_NNE_AXI, "nne_axi", "nne_bus", 0),
+	JH7100_GATE(JH7100_CLK_NNENOC_AXI, "nnenoc_axi", "nne_bus", 0),
+	JH7100_GATE(JH7100_CLK_DLASLV_AXI, "dlaslv_axi", "nne_bus", 0),
+	JH7100_GATE(JH7100_CLK_DSPX2C_AXI, "dspx2c_axi", "nne_bus", CLK_IGNORE_UNUSED),
+	JH7100__DIV(JH7100_CLK_HIFI4_SRC, "hifi4_src", "cdechifi4_root", 4),
+	JH7100__DIV(JH7100_CLK_HIFI4_COREFREE, "hifi4_corefree", "hifi4_src", 8),
+	JH7100_GATE(JH7100_CLK_HIFI4_CORE, "hifi4_core", "hifi4_corefree", 0),
+	JH7100__DIV(JH7100_CLK_HIFI4_BUS, "hifi4_bus", "hifi4_corefree", 8),
+	JH7100_GATE(JH7100_CLK_HIFI4_AXI, "hifi4_axi", "hifi4_bus", 0),
+	JH7100_GATE(JH7100_CLK_HIFI4NOC_AXI, "hifi4noc_axi", "hifi4_bus", 0),
+	JH7100__DIV(JH7100_CLK_SGDMA1P_BUS, "sgdma1p_bus", "cpunbus_root_div", 8),
+	JH7100_GATE(JH7100_CLK_SGDMA1P_AXI, "sgdma1p_axi", "sgdma1p_bus", 0),
+	JH7100_GATE(JH7100_CLK_DMA1P_AXI, "dma1p_axi", "sgdma1p_bus", 0),
+	JH7100_GDIV(JH7100_CLK_X2C_AXI, "x2c_axi", "cpunbus_root_div", 8, CLK_IGNORE_UNUSED),
+	JH7100__DIV(JH7100_CLK_USB_BUS, "usb_bus", "cpunbus_root_div", 8),
+	JH7100_GATE(JH7100_CLK_USB_AXI, "usb_axi", "usb_bus", 0),
+	JH7100_GATE(JH7100_CLK_USBNOC_AXI, "usbnoc_axi", "usb_bus", 0),
+	JH7100__DIV(JH7100_CLK_USBPHY_ROOTDIV, "usbphy_rootdiv", "gmacusb_root", 4),
+	JH7100_GDIV(JH7100_CLK_USBPHY_125M, "usbphy_125m", "usbphy_rootdiv", 8, 0),
+	JH7100_GDIV(JH7100_CLK_USBPHY_PLLDIV25M, "usbphy_plldiv25m", "usbphy_rootdiv", 32, 0),
+	JH7100__MUX(JH7100_CLK_USBPHY_25M, "usbphy_25m", usbphy_25m_sels),
+	JH7100__DIV(JH7100_CLK_AUDIO_DIV, "audio_div", "audio_root", 131072),
+	JH7100_GATE(JH7100_CLK_AUDIO_SRC, "audio_src", "audio_div", 0),
+	JH7100_GATE(JH7100_CLK_AUDIO_12288, "audio_12288", "osc_aud", 0),
+	JH7100_GDIV(JH7100_CLK_VIN_SRC, "vin_src", "vin_root", 4, 0),
+	JH7100__DIV(JH7100_CLK_ISP0_BUS, "isp0_bus", "vin_src", 8),
+	JH7100_GATE(JH7100_CLK_ISP0_AXI, "isp0_axi", "isp0_bus", 0),
+	JH7100_GATE(JH7100_CLK_ISP0NOC_AXI, "isp0noc_axi", "isp0_bus", 0),
+	JH7100_GATE(JH7100_CLK_ISPSLV_AXI, "ispslv_axi", "isp0_bus", 0),
+	JH7100__DIV(JH7100_CLK_ISP1_BUS, "isp1_bus", "vin_src", 8),
+	JH7100_GATE(JH7100_CLK_ISP1_AXI, "isp1_axi", "isp1_bus", 0),
+	JH7100_GATE(JH7100_CLK_ISP1NOC_AXI, "isp1noc_axi", "isp1_bus", 0),
+	JH7100__DIV(JH7100_CLK_VIN_BUS, "vin_bus", "vin_src", 8),
+	JH7100_GATE(JH7100_CLK_VIN_AXI, "vin_axi", "vin_bus", 0),
+	JH7100_GATE(JH7100_CLK_VINNOC_AXI, "vinnoc_axi", "vin_bus", 0),
+	JH7100_GDIV(JH7100_CLK_VOUT_SRC, "vout_src", "vout_root", 4, 0),
+	JH7100__DIV(JH7100_CLK_DISPBUS_SRC, "dispbus_src", "voutbus_root", 4),
+	JH7100__DIV(JH7100_CLK_DISP_BUS, "disp_bus", "dispbus_src", 4),
+	JH7100_GATE(JH7100_CLK_DISP_AXI, "disp_axi", "disp_bus", 0),
+	JH7100_GATE(JH7100_CLK_DISPNOC_AXI, "dispnoc_axi", "disp_bus", 0),
+	JH7100_GATE(JH7100_CLK_SDIO0_AHB, "sdio0_ahb", "ahb_bus", 0),
+	JH7100_GDIV(JH7100_CLK_SDIO0_CCLKINT, "sdio0_cclkint", "perh0_src", 24, 0),
+	JH7100__INV(JH7100_CLK_SDIO0_CCLKINT_INV, "sdio0_cclkint_inv", "sdio0_cclkint"),
+	JH7100_GATE(JH7100_CLK_SDIO1_AHB, "sdio1_ahb", "ahb_bus", 0),
+	JH7100_GDIV(JH7100_CLK_SDIO1_CCLKINT, "sdio1_cclkint", "perh1_src", 24, 0),
+	JH7100__INV(JH7100_CLK_SDIO1_CCLKINT_INV, "sdio1_cclkint_inv", "sdio1_cclkint"),
+	JH7100_GATE(JH7100_CLK_GMAC_AHB, "gmac_ahb", "ahb_bus", 0),
+	JH7100__DIV(JH7100_CLK_GMAC_ROOT_DIV, "gmac_root_div", "gmacusb_root", 8),
+	JH7100_GDIV(JH7100_CLK_GMAC_PTP_REF, "gmac_ptp_refclk", "gmac_root_div", 31, 0),
+	JH7100_GDIV(JH7100_CLK_GMAC_GTX, "gmac_gtxclk", "gmac_root_div", 255, 0),
+	JH7100_GDIV(JH7100_CLK_GMAC_RMII_TX, "gmac_rmii_txclk", "gmac_rmii_ref", 8, 0),
+	JH7100_GDIV(JH7100_CLK_GMAC_RMII_RX, "gmac_rmii_rxclk", "gmac_rmii_ref", 8, 0),
+	JH7100__MUX(JH7100_CLK_GMAC_TX, "gmac_tx", gmac_tx_sels),
+	JH7100__INV(JH7100_CLK_GMAC_TX_INV, "gmac_tx_inv", "gmac_tx"),
+	JH7100__MUX(JH7100_CLK_GMAC_RX_PRE, "gmac_rx_pre", gmac_rx_pre_sels),
+	JH7100__INV(JH7100_CLK_GMAC_RX_INV, "gmac_rx_inv", "gmac_rx_pre"),
+	JH7100_GATE(JH7100_CLK_GMAC_RMII, "gmac_rmii", "gmac_rmii_ref", 0),
+	JH7100_GDIV(JH7100_CLK_GMAC_TOPHYREF, "gmac_tophyref", "gmac_root_div", 127, 0),
+	JH7100_GATE(JH7100_CLK_SPI2AHB_AHB, "spi2ahb_ahb", "ahb_bus", 0),
+	JH7100_GDIV(JH7100_CLK_SPI2AHB_CORE, "spi2ahb_core", "perh0_src", 31, 0),
+	JH7100_GATE(JH7100_CLK_EZMASTER_AHB, "ezmaster_ahb", "ahb_bus", 0),
+	JH7100_GATE(JH7100_CLK_E24_AHB, "e24_ahb", "ahb_bus", 0),
+	JH7100_GATE(JH7100_CLK_E24RTC_TOGGLE, "e24rtc_toggle", "osc_sys", 0),
+	JH7100_GATE(JH7100_CLK_QSPI_AHB, "qspi_ahb", "ahb_bus", 0),
+	JH7100_GATE(JH7100_CLK_QSPI_APB, "qspi_apb", "apb1_bus", 0),
+	JH7100_GDIV(JH7100_CLK_QSPI_REF, "qspi_refclk", "perh0_src", 31, 0),
+	JH7100_GATE(JH7100_CLK_SEC_AHB, "sec_ahb", "ahb_bus", 0),
+	JH7100_GATE(JH7100_CLK_AES, "aes_clk", "sec_ahb", 0),
+	JH7100_GATE(JH7100_CLK_SHA, "sha_clk", "sec_ahb", 0),
+	JH7100_GATE(JH7100_CLK_PKA, "pka_clk", "sec_ahb", 0),
+	JH7100_GATE(JH7100_CLK_TRNG_APB, "trng_apb", "apb1_bus", 0),
+	JH7100_GATE(JH7100_CLK_OTP_APB, "otp_apb", "apb1_bus", 0),
+	JH7100_GATE(JH7100_CLK_UART0_APB, "uart0_apb", "apb1_bus", 0),
+	JH7100_GDIV(JH7100_CLK_UART0_CORE, "uart0_core", "perh1_src", 63, 0),
+	JH7100_GATE(JH7100_CLK_UART1_APB, "uart1_apb", "apb1_bus", 0),
+	JH7100_GDIV(JH7100_CLK_UART1_CORE, "uart1_core", "perh1_src", 63, 0),
+	JH7100_GATE(JH7100_CLK_SPI0_APB, "spi0_apb", "apb1_bus", 0),
+	JH7100_GDIV(JH7100_CLK_SPI0_CORE, "spi0_core", "perh1_src", 63, 0),
+	JH7100_GATE(JH7100_CLK_SPI1_APB, "spi1_apb", "apb1_bus", 0),
+	JH7100_GDIV(JH7100_CLK_SPI1_CORE, "spi1_core", "perh1_src", 63, 0),
+	JH7100_GATE(JH7100_CLK_I2C0_APB, "i2c0_apb", "apb1_bus", 0),
+	JH7100_GDIV(JH7100_CLK_I2C0_CORE, "i2c0_core", "perh1_src", 63, 0),
+	JH7100_GATE(JH7100_CLK_I2C1_APB, "i2c1_apb", "apb1_bus", 0),
+	JH7100_GDIV(JH7100_CLK_I2C1_CORE, "i2c1_core", "perh1_src", 63, 0),
+	JH7100_GATE(JH7100_CLK_GPIO_APB, "gpio_apb", "apb1_bus", 0),
+	JH7100_GATE(JH7100_CLK_UART2_APB, "uart2_apb", "apb2_bus", 0),
+	JH7100_GDIV(JH7100_CLK_UART2_CORE, "uart2_core", "perh0_src", 63, 0),
+	JH7100_GATE(JH7100_CLK_UART3_APB, "uart3_apb", "apb2_bus", 0),
+	JH7100_GDIV(JH7100_CLK_UART3_CORE, "uart3_core", "perh0_src", 63, 0),
+	JH7100_GATE(JH7100_CLK_SPI2_APB, "spi2_apb", "apb2_bus", 0),
+	JH7100_GDIV(JH7100_CLK_SPI2_CORE, "spi2_core", "perh0_src", 63, 0),
+	JH7100_GATE(JH7100_CLK_SPI3_APB, "spi3_apb", "apb2_bus", 0),
+	JH7100_GDIV(JH7100_CLK_SPI3_CORE, "spi3_core", "perh0_src", 63, 0),
+	JH7100_GATE(JH7100_CLK_I2C2_APB, "i2c2_apb", "apb2_bus", 0),
+	JH7100_GDIV(JH7100_CLK_I2C2_CORE, "i2c2_core", "perh0_src", 63, 0),
+	JH7100_GATE(JH7100_CLK_I2C3_APB, "i2c3_apb", "apb2_bus", 0),
+	JH7100_GDIV(JH7100_CLK_I2C3_CORE, "i2c3_core", "perh0_src", 63, 0),
+	JH7100_GATE(JH7100_CLK_WDTIMER_APB, "wdtimer_apb", "apb2_bus", 0),
+	JH7100_GDIV(JH7100_CLK_WDT_CORE, "wdt_coreclk", "perh0_src", 63, 0),
+	JH7100_GDIV(JH7100_CLK_TIMER0_CORE, "timer0_coreclk", "perh0_src", 63, 0),
+	JH7100_GDIV(JH7100_CLK_TIMER1_CORE, "timer1_coreclk", "perh0_src", 63, 0),
+	JH7100_GDIV(JH7100_CLK_TIMER2_CORE, "timer2_coreclk", "perh0_src", 63, 0),
+	JH7100_GDIV(JH7100_CLK_TIMER3_CORE, "timer3_coreclk", "perh0_src", 63, 0),
+	JH7100_GDIV(JH7100_CLK_TIMER4_CORE, "timer4_coreclk", "perh0_src", 63, 0),
+	JH7100_GDIV(JH7100_CLK_TIMER5_CORE, "timer5_coreclk", "perh0_src", 63, 0),
+	JH7100_GDIV(JH7100_CLK_TIMER6_CORE, "timer6_coreclk", "perh0_src", 63, 0),
+	JH7100_GATE(JH7100_CLK_VP6INTC_APB, "vp6intc_apb", "apb2_bus", 0),
+	JH7100_GATE(JH7100_CLK_PWM_APB, "pwm_apb", "apb2_bus", 0),
+	JH7100_GATE(JH7100_CLK_MSI_APB, "msi_apb", "apb2_bus", 0),
+	JH7100_GATE(JH7100_CLK_TEMP_APB, "temp_apb", "apb2_bus", 0),
+	JH7100_GDIV(JH7100_CLK_TEMP_SENSE, "temp_sense", "osc_sys", 31, 0),
+	JH7100_GATE(JH7100_CLK_SYSERR_APB, "syserr_apb", "apb2_bus", 0),
+};
+
+static struct clk_hw *clk_starfive_jh7100_get(struct of_phandle_args *clkspec, void *data)
+{
+	struct clk_starfive_jh7100_priv *priv = data;
+	unsigned int idx = clkspec->args[0];
+
+	if (idx >= JH7100_CLK_END) {
+		dev_err(priv->dev, "invalid clock index %u\n", idx);
+		return ERR_PTR(-EINVAL);
+	}
+
+	if (idx >= JH7100_CLK_PLL0_OUT)
+		return priv->pll[idx - JH7100_CLK_PLL0_OUT];
+
+	return &priv->reg[idx].hw;
+}
+
+static int __init clk_starfive_jh7100_probe(struct platform_device *pdev)
+{
+	struct clk_starfive_jh7100_priv *priv;
+	unsigned int idx;
+	int ret;
+
+	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	spin_lock_init(&priv->rmw_lock);
+	priv->dev = &pdev->dev;
+	priv->base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(priv->base))
+		return PTR_ERR(priv->base);
+
+	priv->pll[0] = devm_clk_hw_register_fixed_factor(priv->dev, "pll0_out",
+							 "osc_sys", 0, 40, 1);
+	if (IS_ERR(priv->pll[0]))
+		return PTR_ERR(priv->pll[0]);
+
+	priv->pll[1] = devm_clk_hw_register_fixed_factor(priv->dev, "pll1_out",
+							 "osc_sys", 0, 64, 1);
+	if (IS_ERR(priv->pll[1]))
+		return PTR_ERR(priv->pll[1]);
+
+	priv->pll[2] = devm_clk_hw_register_fixed_factor(priv->dev, "pll2_out",
+							 "pll2_refclk", 0, 55, 1);
+	if (IS_ERR(priv->pll[2]))
+		return PTR_ERR(priv->pll[2]);
+
+	for (idx = 0; idx < JH7100_CLK_PLL0_OUT; idx++) {
+		u32 max_parent = (jh7100_clk_data[idx].max & JH7100_CLK_MUX_MASK) >>
+				 JH7100_CLK_MUX_SHIFT;
+		struct clk_init_data init = {
+			.name = jh7100_clk_data[idx].name,
+			.ops = jh7100_clk_data[idx].ops,
+			.num_parents = max_parent + 1,
+			.flags = jh7100_clk_data[idx].flags,
+		};
+		struct jh7100_clk *clk = &priv->reg[idx];
+
+		if (init.num_parents > 1)
+			init.parent_names = jh7100_clk_data[idx].parents;
+		else
+			init.parent_names = &jh7100_clk_data[idx].parent;
+
+		clk->hw.init = &init;
+		clk->idx = idx;
+		clk->max = jh7100_clk_data[idx].max;
+
+		ret = clk_hw_register(priv->dev, &clk->hw);
+		if (ret)
+			goto err;
+	}
+
+	ret = devm_of_clk_add_hw_provider(priv->dev, clk_starfive_jh7100_get, priv);
+	if (ret)
+		goto err;
+
+	return 0;
+err:
+	while (idx)
+		clk_hw_unregister(&priv->reg[--idx].hw);
+	return ret;
+}
+
+static const struct of_device_id clk_starfive_jh7100_match[] = {
+	{ .compatible = "starfive,jh7100-clkgen" },
+	{ /* sentinel */ }
+};
+
+static struct platform_driver clk_starfive_jh7100_driver = {
+	.probe = clk_starfive_jh7100_probe,
+	.driver = {
+		.name = "clk-starfive-jh7100",
+		.of_match_table = clk_starfive_jh7100_match,
+	},
+};
+builtin_platform_driver(clk_starfive_jh7100_driver);
+
+MODULE_DESCRIPTION("StarFive JH7100 Clock Generator Driver");
+MODULE_AUTHOR("Emil Renner Berthing <kernel@esmil.dk>");
+MODULE_AUTHOR("Geert Uytterhoeven <geert@linux-m68k.org>");
+MODULE_LICENSE("GPL v2");
-- 
2.33.1


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 143+ messages in thread

* [PATCH v2 07/16] dt-bindings: reset: Add StarFive JH7100 reset definitions
  2021-10-21 17:42 ` Emil Renner Berthing
@ 2021-10-21 17:42   ` Emil Renner Berthing
  -1 siblings, 0 replies; 143+ messages in thread
From: Emil Renner Berthing @ 2021-10-21 17:42 UTC (permalink / raw)
  To: linux-riscv, devicetree, linux-clk, linux-gpio, linux-serial
  Cc: Geert Uytterhoeven, Palmer Dabbelt, Paul Walmsley, Rob Herring,
	Michael Turquette, Stephen Boyd, Thomas Gleixner, Marc Zyngier,
	Philipp Zabel, Linus Walleij, Greg Kroah-Hartman, Daniel Lezcano,
	Andy Shevchenko, Jiri Slaby, Maximilian Luz, Sagar Kadam,
	Drew Fustini, Michael Zhu, Fu Wei, Anup Patel, Atish Patra,
	Matteo Croce, linux-kernel, Emil Renner Berthing

From: Geert Uytterhoeven <geert@linux-m68k.org>

Add all resets for the StarFive JH7100 reset controller.

Based on work by Ahmad Fatoum for Barebox, with "JH7100_" prefixes added
to all definitions.

Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
---
 include/dt-bindings/reset/starfive-jh7100.h | 126 ++++++++++++++++++++
 1 file changed, 126 insertions(+)
 create mode 100644 include/dt-bindings/reset/starfive-jh7100.h

diff --git a/include/dt-bindings/reset/starfive-jh7100.h b/include/dt-bindings/reset/starfive-jh7100.h
new file mode 100644
index 000000000000..42dc95868efc
--- /dev/null
+++ b/include/dt-bindings/reset/starfive-jh7100.h
@@ -0,0 +1,126 @@
+/* SPDX-License-Identifier: GPL-2.0 OR X11 */
+/*
+ * Copyright (c) 2021 Ahmad Fatoum, Pengutronix
+ */
+
+#ifndef __DT_BINDINGS_RESET_STARFIVE_JH7100_H__
+#define __DT_BINDINGS_RESET_STARFIVE_JH7100_H__
+
+#define JH7100_RSTN_DOM3AHB_BUS		0
+#define JH7100_RSTN_DOM7AHB_BUS		1
+#define JH7100_RST_U74			2
+#define JH7100_RSTN_U74_AXI		3
+#define JH7100_RSTN_SGDMA2P_AHB		4
+#define JH7100_RSTN_SGDMA2P_AXI		5
+#define JH7100_RSTN_DMA2PNOC_AXI	6
+#define JH7100_RSTN_DLA_AXI		7
+#define JH7100_RSTN_DLANOC_AXI		8
+#define JH7100_RSTN_DLA_APB		9
+#define JH7100_RST_VP6_DRESET		10
+#define JH7100_RST_VP6_BRESET		11
+#define JH7100_RSTN_VP6_AXI		12
+#define JH7100_RSTN_VDECBRG_MAIN	13
+#define JH7100_RSTN_VDEC_AXI		14
+#define JH7100_RSTN_VDEC_BCLK		15
+#define JH7100_RSTN_VDEC_CCLK		16
+#define JH7100_RSTN_VDEC_APB		17
+#define JH7100_RSTN_JPEG_AXI		18
+#define JH7100_RSTN_JPEG_CCLK		19
+#define JH7100_RSTN_JPEG_APB		20
+#define JH7100_RSTN_JPCGC300_MAIN	21
+#define JH7100_RSTN_GC300_2X		22
+#define JH7100_RSTN_GC300_AXI		23
+#define JH7100_RSTN_GC300_AHB		24
+#define JH7100_RSTN_VENC_AXI		25
+#define JH7100_RSTN_VENCBRG_MAIN	26
+#define JH7100_RSTN_VENC_BCLK		27
+#define JH7100_RSTN_VENC_CCLK		28
+#define JH7100_RSTN_VENC_APB		29
+#define JH7100_RSTN_DDRPHY_APB		30
+#define JH7100_RSTN_NOC_ROB		31
+#define JH7100_RSTN_NOC_COG		32
+#define JH7100_RSTN_HIFI4_AXI		33
+#define JH7100_RSTN_HIFI4NOC_AXI	34
+#define JH7100_RST_HIFI4_DRESET		35
+#define JH7100_RST_HIFI4_BRESET		36
+#define JH7100_RSTN_USB_AXI		37
+#define JH7100_RSTN_USBNOC_AXI		38
+#define JH7100_RSTN_SGDMA1P_AXI		39
+#define JH7100_RSTN_DMA1P_AXI		40
+#define JH7100_RSTN_X2C_AXI		41
+#define JH7100_RSTN_NNE_AHB		42
+#define JH7100_RSTN_NNE_AXI		43
+#define JH7100_RSTN_NNENOC_AXI		44
+#define JH7100_RSTN_DLASLV_AXI		45
+#define JH7100_RSTN_DSPX2C_AXI		46
+#define JH7100_RSTN_VIN_SRC		47
+#define JH7100_RSTN_ISPSLV_AXI		48
+#define JH7100_RSTN_VIN_AXI		49
+#define JH7100_RSTN_VINNOC_AXI		50
+#define JH7100_RSTN_ISP0_AXI		51
+#define JH7100_RSTN_ISP0NOC_AXI		52
+#define JH7100_RSTN_ISP1_AXI		53
+#define JH7100_RSTN_ISP1NOC_AXI		54
+#define JH7100_RSTN_VOUT_SRC		55
+#define JH7100_RSTN_DISP_AXI		56
+#define JH7100_RSTN_DISPNOC_AXI		57
+#define JH7100_RSTN_SDIO0_AHB		58
+#define JH7100_RSTN_SDIO1_AHB		59
+#define JH7100_RSTN_GMAC_AHB		60
+#define JH7100_RSTN_SPI2AHB_AHB		61
+#define JH7100_RSTN_SPI2AHB_CORE	62
+#define JH7100_RSTN_EZMASTER_AHB	63
+#define JH7100_RST_E24			64
+#define JH7100_RSTN_QSPI_AHB		65
+#define JH7100_RSTN_QSPI_CORE		66
+#define JH7100_RSTN_QSPI_APB		67
+#define JH7100_RSTN_SEC_AHB		68
+#define JH7100_RSTN_AES			69
+#define JH7100_RSTN_PKA			70
+#define JH7100_RSTN_SHA			71
+#define JH7100_RSTN_TRNG_APB		72
+#define JH7100_RSTN_OTP_APB		73
+#define JH7100_RSTN_UART0_APB		74
+#define JH7100_RSTN_UART0_CORE		75
+#define JH7100_RSTN_UART1_APB		76
+#define JH7100_RSTN_UART1_CORE		77
+#define JH7100_RSTN_SPI0_APB		78
+#define JH7100_RSTN_SPI0_CORE		79
+#define JH7100_RSTN_SPI1_APB		80
+#define JH7100_RSTN_SPI1_CORE		81
+#define JH7100_RSTN_I2C0_APB		82
+#define JH7100_RSTN_I2C0_CORE		83
+#define JH7100_RSTN_I2C1_APB		84
+#define JH7100_RSTN_I2C1_CORE		85
+#define JH7100_RSTN_GPIO_APB		86
+#define JH7100_RSTN_UART2_APB		87
+#define JH7100_RSTN_UART2_CORE		88
+#define JH7100_RSTN_UART3_APB		89
+#define JH7100_RSTN_UART3_CORE		90
+#define JH7100_RSTN_SPI2_APB		91
+#define JH7100_RSTN_SPI2_CORE		92
+#define JH7100_RSTN_SPI3_APB		93
+#define JH7100_RSTN_SPI3_CORE		94
+#define JH7100_RSTN_I2C2_APB		95
+#define JH7100_RSTN_I2C2_CORE		96
+#define JH7100_RSTN_I2C3_APB		97
+#define JH7100_RSTN_I2C3_CORE		98
+#define JH7100_RSTN_WDTIMER_APB		99
+#define JH7100_RSTN_WDT			100
+#define JH7100_RSTN_TIMER0		101
+#define JH7100_RSTN_TIMER1		102
+#define JH7100_RSTN_TIMER2		103
+#define JH7100_RSTN_TIMER3		104
+#define JH7100_RSTN_TIMER4		105
+#define JH7100_RSTN_TIMER5		106
+#define JH7100_RSTN_TIMER6		107
+#define JH7100_RSTN_VP6INTC_APB		108
+#define JH7100_RSTN_PWM_APB		109
+#define JH7100_RSTN_MSI_APB		110
+#define JH7100_RSTN_TEMP_APB		111
+#define JH7100_RSTN_TEMP_SENSE		112
+#define JH7100_RSTN_SYSERR_APB		113
+
+#define JH7100_RSTN_END			114
+
+#endif /* __DT_BINDINGS_RESET_STARFIVE_JH7100_H__ */
-- 
2.33.1


^ permalink raw reply related	[flat|nested] 143+ messages in thread

* [PATCH v2 07/16] dt-bindings: reset: Add StarFive JH7100 reset definitions
@ 2021-10-21 17:42   ` Emil Renner Berthing
  0 siblings, 0 replies; 143+ messages in thread
From: Emil Renner Berthing @ 2021-10-21 17:42 UTC (permalink / raw)
  To: linux-riscv, devicetree, linux-clk, linux-gpio, linux-serial
  Cc: Geert Uytterhoeven, Palmer Dabbelt, Paul Walmsley, Rob Herring,
	Michael Turquette, Stephen Boyd, Thomas Gleixner, Marc Zyngier,
	Philipp Zabel, Linus Walleij, Greg Kroah-Hartman, Daniel Lezcano,
	Andy Shevchenko, Jiri Slaby, Maximilian Luz, Sagar Kadam,
	Drew Fustini, Michael Zhu, Fu Wei, Anup Patel, Atish Patra,
	Matteo Croce, linux-kernel, Emil Renner Berthing

From: Geert Uytterhoeven <geert@linux-m68k.org>

Add all resets for the StarFive JH7100 reset controller.

Based on work by Ahmad Fatoum for Barebox, with "JH7100_" prefixes added
to all definitions.

Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
---
 include/dt-bindings/reset/starfive-jh7100.h | 126 ++++++++++++++++++++
 1 file changed, 126 insertions(+)
 create mode 100644 include/dt-bindings/reset/starfive-jh7100.h

diff --git a/include/dt-bindings/reset/starfive-jh7100.h b/include/dt-bindings/reset/starfive-jh7100.h
new file mode 100644
index 000000000000..42dc95868efc
--- /dev/null
+++ b/include/dt-bindings/reset/starfive-jh7100.h
@@ -0,0 +1,126 @@
+/* SPDX-License-Identifier: GPL-2.0 OR X11 */
+/*
+ * Copyright (c) 2021 Ahmad Fatoum, Pengutronix
+ */
+
+#ifndef __DT_BINDINGS_RESET_STARFIVE_JH7100_H__
+#define __DT_BINDINGS_RESET_STARFIVE_JH7100_H__
+
+#define JH7100_RSTN_DOM3AHB_BUS		0
+#define JH7100_RSTN_DOM7AHB_BUS		1
+#define JH7100_RST_U74			2
+#define JH7100_RSTN_U74_AXI		3
+#define JH7100_RSTN_SGDMA2P_AHB		4
+#define JH7100_RSTN_SGDMA2P_AXI		5
+#define JH7100_RSTN_DMA2PNOC_AXI	6
+#define JH7100_RSTN_DLA_AXI		7
+#define JH7100_RSTN_DLANOC_AXI		8
+#define JH7100_RSTN_DLA_APB		9
+#define JH7100_RST_VP6_DRESET		10
+#define JH7100_RST_VP6_BRESET		11
+#define JH7100_RSTN_VP6_AXI		12
+#define JH7100_RSTN_VDECBRG_MAIN	13
+#define JH7100_RSTN_VDEC_AXI		14
+#define JH7100_RSTN_VDEC_BCLK		15
+#define JH7100_RSTN_VDEC_CCLK		16
+#define JH7100_RSTN_VDEC_APB		17
+#define JH7100_RSTN_JPEG_AXI		18
+#define JH7100_RSTN_JPEG_CCLK		19
+#define JH7100_RSTN_JPEG_APB		20
+#define JH7100_RSTN_JPCGC300_MAIN	21
+#define JH7100_RSTN_GC300_2X		22
+#define JH7100_RSTN_GC300_AXI		23
+#define JH7100_RSTN_GC300_AHB		24
+#define JH7100_RSTN_VENC_AXI		25
+#define JH7100_RSTN_VENCBRG_MAIN	26
+#define JH7100_RSTN_VENC_BCLK		27
+#define JH7100_RSTN_VENC_CCLK		28
+#define JH7100_RSTN_VENC_APB		29
+#define JH7100_RSTN_DDRPHY_APB		30
+#define JH7100_RSTN_NOC_ROB		31
+#define JH7100_RSTN_NOC_COG		32
+#define JH7100_RSTN_HIFI4_AXI		33
+#define JH7100_RSTN_HIFI4NOC_AXI	34
+#define JH7100_RST_HIFI4_DRESET		35
+#define JH7100_RST_HIFI4_BRESET		36
+#define JH7100_RSTN_USB_AXI		37
+#define JH7100_RSTN_USBNOC_AXI		38
+#define JH7100_RSTN_SGDMA1P_AXI		39
+#define JH7100_RSTN_DMA1P_AXI		40
+#define JH7100_RSTN_X2C_AXI		41
+#define JH7100_RSTN_NNE_AHB		42
+#define JH7100_RSTN_NNE_AXI		43
+#define JH7100_RSTN_NNENOC_AXI		44
+#define JH7100_RSTN_DLASLV_AXI		45
+#define JH7100_RSTN_DSPX2C_AXI		46
+#define JH7100_RSTN_VIN_SRC		47
+#define JH7100_RSTN_ISPSLV_AXI		48
+#define JH7100_RSTN_VIN_AXI		49
+#define JH7100_RSTN_VINNOC_AXI		50
+#define JH7100_RSTN_ISP0_AXI		51
+#define JH7100_RSTN_ISP0NOC_AXI		52
+#define JH7100_RSTN_ISP1_AXI		53
+#define JH7100_RSTN_ISP1NOC_AXI		54
+#define JH7100_RSTN_VOUT_SRC		55
+#define JH7100_RSTN_DISP_AXI		56
+#define JH7100_RSTN_DISPNOC_AXI		57
+#define JH7100_RSTN_SDIO0_AHB		58
+#define JH7100_RSTN_SDIO1_AHB		59
+#define JH7100_RSTN_GMAC_AHB		60
+#define JH7100_RSTN_SPI2AHB_AHB		61
+#define JH7100_RSTN_SPI2AHB_CORE	62
+#define JH7100_RSTN_EZMASTER_AHB	63
+#define JH7100_RST_E24			64
+#define JH7100_RSTN_QSPI_AHB		65
+#define JH7100_RSTN_QSPI_CORE		66
+#define JH7100_RSTN_QSPI_APB		67
+#define JH7100_RSTN_SEC_AHB		68
+#define JH7100_RSTN_AES			69
+#define JH7100_RSTN_PKA			70
+#define JH7100_RSTN_SHA			71
+#define JH7100_RSTN_TRNG_APB		72
+#define JH7100_RSTN_OTP_APB		73
+#define JH7100_RSTN_UART0_APB		74
+#define JH7100_RSTN_UART0_CORE		75
+#define JH7100_RSTN_UART1_APB		76
+#define JH7100_RSTN_UART1_CORE		77
+#define JH7100_RSTN_SPI0_APB		78
+#define JH7100_RSTN_SPI0_CORE		79
+#define JH7100_RSTN_SPI1_APB		80
+#define JH7100_RSTN_SPI1_CORE		81
+#define JH7100_RSTN_I2C0_APB		82
+#define JH7100_RSTN_I2C0_CORE		83
+#define JH7100_RSTN_I2C1_APB		84
+#define JH7100_RSTN_I2C1_CORE		85
+#define JH7100_RSTN_GPIO_APB		86
+#define JH7100_RSTN_UART2_APB		87
+#define JH7100_RSTN_UART2_CORE		88
+#define JH7100_RSTN_UART3_APB		89
+#define JH7100_RSTN_UART3_CORE		90
+#define JH7100_RSTN_SPI2_APB		91
+#define JH7100_RSTN_SPI2_CORE		92
+#define JH7100_RSTN_SPI3_APB		93
+#define JH7100_RSTN_SPI3_CORE		94
+#define JH7100_RSTN_I2C2_APB		95
+#define JH7100_RSTN_I2C2_CORE		96
+#define JH7100_RSTN_I2C3_APB		97
+#define JH7100_RSTN_I2C3_CORE		98
+#define JH7100_RSTN_WDTIMER_APB		99
+#define JH7100_RSTN_WDT			100
+#define JH7100_RSTN_TIMER0		101
+#define JH7100_RSTN_TIMER1		102
+#define JH7100_RSTN_TIMER2		103
+#define JH7100_RSTN_TIMER3		104
+#define JH7100_RSTN_TIMER4		105
+#define JH7100_RSTN_TIMER5		106
+#define JH7100_RSTN_TIMER6		107
+#define JH7100_RSTN_VP6INTC_APB		108
+#define JH7100_RSTN_PWM_APB		109
+#define JH7100_RSTN_MSI_APB		110
+#define JH7100_RSTN_TEMP_APB		111
+#define JH7100_RSTN_TEMP_SENSE		112
+#define JH7100_RSTN_SYSERR_APB		113
+
+#define JH7100_RSTN_END			114
+
+#endif /* __DT_BINDINGS_RESET_STARFIVE_JH7100_H__ */
-- 
2.33.1


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 143+ messages in thread

* [PATCH v2 08/16] dt-bindings: reset: Add Starfive JH7100 reset bindings
  2021-10-21 17:42 ` Emil Renner Berthing
@ 2021-10-21 17:42   ` Emil Renner Berthing
  -1 siblings, 0 replies; 143+ messages in thread
From: Emil Renner Berthing @ 2021-10-21 17:42 UTC (permalink / raw)
  To: linux-riscv, devicetree, linux-clk, linux-gpio, linux-serial
  Cc: Emil Renner Berthing, Palmer Dabbelt, Paul Walmsley, Rob Herring,
	Michael Turquette, Stephen Boyd, Thomas Gleixner, Marc Zyngier,
	Philipp Zabel, Linus Walleij, Greg Kroah-Hartman, Daniel Lezcano,
	Andy Shevchenko, Jiri Slaby, Maximilian Luz, Sagar Kadam,
	Drew Fustini, Geert Uytterhoeven, Michael Zhu, Fu Wei,
	Anup Patel, Atish Patra, Matteo Croce, linux-kernel

Add device tree bindings for the StarFive JH7100 reset controller.

Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
---
 .../bindings/reset/starfive,jh7100-reset.yaml | 38 +++++++++++++++++++
 1 file changed, 38 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/reset/starfive,jh7100-reset.yaml

diff --git a/Documentation/devicetree/bindings/reset/starfive,jh7100-reset.yaml b/Documentation/devicetree/bindings/reset/starfive,jh7100-reset.yaml
new file mode 100644
index 000000000000..c6ad5d7ad100
--- /dev/null
+++ b/Documentation/devicetree/bindings/reset/starfive,jh7100-reset.yaml
@@ -0,0 +1,38 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/reset/starfive,jh7100-reset.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: StarFive JH7100 SoC Reset Controller Device Tree Bindings
+
+maintainers:
+  - Emil Renner Berthing <kernel@esmil.dk>
+
+properties:
+  compatible:
+    enum:
+      - starfive,jh7100-reset
+
+  reg:
+    maxItems: 1
+
+  "#reset-cells":
+    const: 1
+
+required:
+  - compatible
+  - reg
+  - "#reset-cells"
+
+additionalProperties: false
+
+examples:
+  - |
+    rstgen: reset-controller@11840000 {
+        compatible = "starfive,jh7100-reset";
+        reg = <0x11840000 0x10000>;
+        #reset-cells = <1>;
+    };
+
+...
-- 
2.33.1


^ permalink raw reply related	[flat|nested] 143+ messages in thread

* [PATCH v2 08/16] dt-bindings: reset: Add Starfive JH7100 reset bindings
@ 2021-10-21 17:42   ` Emil Renner Berthing
  0 siblings, 0 replies; 143+ messages in thread
From: Emil Renner Berthing @ 2021-10-21 17:42 UTC (permalink / raw)
  To: linux-riscv, devicetree, linux-clk, linux-gpio, linux-serial
  Cc: Emil Renner Berthing, Palmer Dabbelt, Paul Walmsley, Rob Herring,
	Michael Turquette, Stephen Boyd, Thomas Gleixner, Marc Zyngier,
	Philipp Zabel, Linus Walleij, Greg Kroah-Hartman, Daniel Lezcano,
	Andy Shevchenko, Jiri Slaby, Maximilian Luz, Sagar Kadam,
	Drew Fustini, Geert Uytterhoeven, Michael Zhu, Fu Wei,
	Anup Patel, Atish Patra, Matteo Croce, linux-kernel

Add device tree bindings for the StarFive JH7100 reset controller.

Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
---
 .../bindings/reset/starfive,jh7100-reset.yaml | 38 +++++++++++++++++++
 1 file changed, 38 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/reset/starfive,jh7100-reset.yaml

diff --git a/Documentation/devicetree/bindings/reset/starfive,jh7100-reset.yaml b/Documentation/devicetree/bindings/reset/starfive,jh7100-reset.yaml
new file mode 100644
index 000000000000..c6ad5d7ad100
--- /dev/null
+++ b/Documentation/devicetree/bindings/reset/starfive,jh7100-reset.yaml
@@ -0,0 +1,38 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/reset/starfive,jh7100-reset.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: StarFive JH7100 SoC Reset Controller Device Tree Bindings
+
+maintainers:
+  - Emil Renner Berthing <kernel@esmil.dk>
+
+properties:
+  compatible:
+    enum:
+      - starfive,jh7100-reset
+
+  reg:
+    maxItems: 1
+
+  "#reset-cells":
+    const: 1
+
+required:
+  - compatible
+  - reg
+  - "#reset-cells"
+
+additionalProperties: false
+
+examples:
+  - |
+    rstgen: reset-controller@11840000 {
+        compatible = "starfive,jh7100-reset";
+        reg = <0x11840000 0x10000>;
+        #reset-cells = <1>;
+    };
+
+...
-- 
2.33.1


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 143+ messages in thread

* [PATCH v2 09/16] reset: starfive-jh7100: Add StarFive JH7100 reset driver
  2021-10-21 17:42 ` Emil Renner Berthing
@ 2021-10-21 17:42   ` Emil Renner Berthing
  -1 siblings, 0 replies; 143+ messages in thread
From: Emil Renner Berthing @ 2021-10-21 17:42 UTC (permalink / raw)
  To: linux-riscv, devicetree, linux-clk, linux-gpio, linux-serial
  Cc: Emil Renner Berthing, Palmer Dabbelt, Paul Walmsley, Rob Herring,
	Michael Turquette, Stephen Boyd, Thomas Gleixner, Marc Zyngier,
	Philipp Zabel, Linus Walleij, Greg Kroah-Hartman, Daniel Lezcano,
	Andy Shevchenko, Jiri Slaby, Maximilian Luz, Sagar Kadam,
	Drew Fustini, Geert Uytterhoeven, Michael Zhu, Fu Wei,
	Anup Patel, Atish Patra, Matteo Croce, linux-kernel

Add a driver for the StarFive JH7100 reset controller.

Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
---
 MAINTAINERS                           |   7 ++
 drivers/reset/Kconfig                 |   8 ++
 drivers/reset/Makefile                |   1 +
 drivers/reset/reset-starfive-jh7100.c | 165 ++++++++++++++++++++++++++
 4 files changed, 181 insertions(+)
 create mode 100644 drivers/reset/reset-starfive-jh7100.c

diff --git a/MAINTAINERS b/MAINTAINERS
index e5a19b70dfbb..b3f3a29fc91f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -17855,6 +17855,13 @@ F:	Documentation/devicetree/bindings/clock/starfive,jh7100-clkgen.yaml
 F:	drivers/clk/starfive/clk-starfive-jh7100.c
 F:	include/dt-bindings/clock/starfive-jh7100.h
 
+STARFIVE JH7100 RESET CONTROLLER DRIVER
+M:	Emil Renner Berthing <kernel@esmil.dk>
+S:	Maintained
+F:	Documentation/devicetree/bindings/reset/starfive,jh7100-reset.yaml
+F:	drivers/reset/reset-starfive-jh7100.c
+F:	include/dt-bindings/reset/starfive-jh7100.h
+
 STATIC BRANCH/CALL
 M:	Peter Zijlstra <peterz@infradead.org>
 M:	Josh Poimboeuf <jpoimboe@redhat.com>
diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index be799a5abf8a..a41fac304904 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -224,6 +224,14 @@ config RESET_SOCFPGA
 	  This enables the reset driver for the SoCFPGA ARMv7 platforms. This
 	  driver gets initialized early during platform init calls.
 
+config RESET_STARFIVE_JH7100
+	bool "StarFive JH7100 Reset Driver"
+	depends on SOC_STARFIVE || COMPILE_TEST
+	depends on OF
+	default SOC_STARFIVE
+	help
+	  This enables the reset controller driver for the StarFive JH7100 SoC.
+
 config RESET_SUNXI
 	bool "Allwinner SoCs Reset Driver" if COMPILE_TEST && !ARCH_SUNXI
 	default ARCH_SUNXI
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index 21d46d8869ff..bd0a97be18b5 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -29,6 +29,7 @@ obj-$(CONFIG_RESET_RZG2L_USBPHY_CTRL) += reset-rzg2l-usbphy-ctrl.o
 obj-$(CONFIG_RESET_SCMI) += reset-scmi.o
 obj-$(CONFIG_RESET_SIMPLE) += reset-simple.o
 obj-$(CONFIG_RESET_SOCFPGA) += reset-socfpga.o
+obj-$(CONFIG_RESET_STARFIVE_JH7100) += reset-starfive-jh7100.o
 obj-$(CONFIG_RESET_SUNXI) += reset-sunxi.o
 obj-$(CONFIG_RESET_TI_SCI) += reset-ti-sci.o
 obj-$(CONFIG_RESET_TI_SYSCON) += reset-ti-syscon.o
diff --git a/drivers/reset/reset-starfive-jh7100.c b/drivers/reset/reset-starfive-jh7100.c
new file mode 100644
index 000000000000..ae15ed5357f1
--- /dev/null
+++ b/drivers/reset/reset-starfive-jh7100.c
@@ -0,0 +1,165 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Reset driver for the StarFive JH7100 SoC
+ *
+ * Copyright (C) 2021 Emil Renner Berthing <kernel@esmil.dk>
+ *
+ */
+
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/reset-controller.h>
+#include <linux/spinlock.h>
+
+#include <dt-bindings/reset/starfive-jh7100.h>
+
+/* register offsets */
+#define JH7100_RESET_ASSERT0	0x00
+#define JH7100_RESET_ASSERT1	0x04
+#define JH7100_RESET_ASSERT2	0x08
+#define JH7100_RESET_ASSERT3	0x0c
+#define JH7100_RESET_STATUS0	0x10
+#define JH7100_RESET_STATUS1	0x14
+#define JH7100_RESET_STATUS2	0x18
+#define JH7100_RESET_STATUS3	0x1c
+
+struct jh7100_reset {
+	struct reset_controller_dev rcdev;
+	/* protect registers against overlapping read-modify-write */
+	spinlock_t lock;
+	void __iomem *base;
+};
+
+static inline struct jh7100_reset *
+jh7100_reset_from(struct reset_controller_dev *rcdev)
+{
+	return container_of(rcdev, struct jh7100_reset, rcdev);
+}
+
+static const u32 jh7100_reset_asserted[4] = {
+	BIT(JH7100_RST_U74 % 32) |
+	BIT(JH7100_RST_VP6_DRESET % 32) |
+	BIT(JH7100_RST_VP6_BRESET % 32),
+
+	BIT(JH7100_RST_HIFI4_DRESET % 32) |
+	BIT(JH7100_RST_HIFI4_BRESET % 32),
+
+	BIT(JH7100_RST_E24 % 32)
+};
+
+static int jh7100_reset_update(struct reset_controller_dev *rcdev,
+			       unsigned long id, bool assert)
+{
+	struct jh7100_reset *data = jh7100_reset_from(rcdev);
+	unsigned long offset = id / 32;
+	void __iomem *reg_assert = data->base + JH7100_RESET_ASSERT0 + 4 * offset;
+	void __iomem *reg_status = data->base + JH7100_RESET_STATUS0 + 4 * offset;
+	u32 mask = BIT(id % 32);
+	u32 done = jh7100_reset_asserted[offset] & mask;
+	unsigned long flags;
+	u32 value;
+	int ret;
+
+	if (!assert)
+		done ^= mask;
+
+	spin_lock_irqsave(&data->lock, flags);
+
+	value = readl(reg_assert);
+	if (assert)
+		value |= mask;
+	else
+		value &= ~mask;
+	writel(value, reg_assert);
+
+	/* if the associated clock is gated, deasserting might otherwise hang forever */
+	ret = readl_poll_timeout(reg_status, value, (value & mask) == done, 0, 1000);
+
+	spin_unlock_irqrestore(&data->lock, flags);
+	return ret;
+}
+
+static int jh7100_reset_assert(struct reset_controller_dev *rcdev,
+			       unsigned long id)
+{
+	dev_dbg(rcdev->dev, "assert(%lu)\n", id);
+	return jh7100_reset_update(rcdev, id, true);
+}
+
+static int jh7100_reset_deassert(struct reset_controller_dev *rcdev,
+				 unsigned long id)
+{
+	dev_dbg(rcdev->dev, "deassert(%lu)\n", id);
+	return jh7100_reset_update(rcdev, id, false);
+}
+
+static int jh7100_reset_reset(struct reset_controller_dev *rcdev,
+			      unsigned long id)
+{
+	int ret;
+
+	dev_dbg(rcdev->dev, "reset(%lu)\n", id);
+	ret = jh7100_reset_assert(rcdev, id);
+	if (ret)
+		return ret;
+
+	return jh7100_reset_deassert(rcdev, id);
+}
+
+static int jh7100_reset_status(struct reset_controller_dev *rcdev,
+			       unsigned long id)
+{
+	struct jh7100_reset *data = jh7100_reset_from(rcdev);
+	unsigned long offset = id / 32;
+	void __iomem *reg_status = data->base + JH7100_RESET_STATUS0 + 4 * offset;
+	u32 mask = BIT(id % 32);
+	u32 value = (readl(reg_status) ^ jh7100_reset_asserted[offset]) & mask;
+
+	dev_dbg(rcdev->dev, "status(%lu) = %d\n", id, !value);
+	return !value;
+}
+
+static const struct reset_control_ops jh7100_reset_ops = {
+	.assert		= jh7100_reset_assert,
+	.deassert	= jh7100_reset_deassert,
+	.reset		= jh7100_reset_reset,
+	.status		= jh7100_reset_status,
+};
+
+static int jh7100_reset_probe(struct platform_device *pdev)
+{
+	struct jh7100_reset *data;
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(data->base))
+		return PTR_ERR(data->base);
+
+	data->rcdev.ops = &jh7100_reset_ops;
+	data->rcdev.owner = THIS_MODULE;
+	data->rcdev.nr_resets = JH7100_RSTN_END;
+	data->rcdev.dev = &pdev->dev;
+	data->rcdev.of_node = pdev->dev.of_node;
+	spin_lock_init(&data->lock);
+
+	return devm_reset_controller_register(&pdev->dev, &data->rcdev);
+}
+
+static const struct of_device_id jh7100_reset_dt_ids[] = {
+	{ .compatible = "starfive,jh7100-reset" },
+	{ /* sentinel */ }
+};
+
+static struct platform_driver jh7100_reset_driver = {
+	.probe = jh7100_reset_probe,
+	.driver = {
+		.name = "jh7100-reset",
+		.of_match_table = jh7100_reset_dt_ids,
+	},
+};
+builtin_platform_driver(jh7100_reset_driver);
-- 
2.33.1


^ permalink raw reply related	[flat|nested] 143+ messages in thread

* [PATCH v2 09/16] reset: starfive-jh7100: Add StarFive JH7100 reset driver
@ 2021-10-21 17:42   ` Emil Renner Berthing
  0 siblings, 0 replies; 143+ messages in thread
From: Emil Renner Berthing @ 2021-10-21 17:42 UTC (permalink / raw)
  To: linux-riscv, devicetree, linux-clk, linux-gpio, linux-serial
  Cc: Emil Renner Berthing, Palmer Dabbelt, Paul Walmsley, Rob Herring,
	Michael Turquette, Stephen Boyd, Thomas Gleixner, Marc Zyngier,
	Philipp Zabel, Linus Walleij, Greg Kroah-Hartman, Daniel Lezcano,
	Andy Shevchenko, Jiri Slaby, Maximilian Luz, Sagar Kadam,
	Drew Fustini, Geert Uytterhoeven, Michael Zhu, Fu Wei,
	Anup Patel, Atish Patra, Matteo Croce, linux-kernel

Add a driver for the StarFive JH7100 reset controller.

Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
---
 MAINTAINERS                           |   7 ++
 drivers/reset/Kconfig                 |   8 ++
 drivers/reset/Makefile                |   1 +
 drivers/reset/reset-starfive-jh7100.c | 165 ++++++++++++++++++++++++++
 4 files changed, 181 insertions(+)
 create mode 100644 drivers/reset/reset-starfive-jh7100.c

diff --git a/MAINTAINERS b/MAINTAINERS
index e5a19b70dfbb..b3f3a29fc91f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -17855,6 +17855,13 @@ F:	Documentation/devicetree/bindings/clock/starfive,jh7100-clkgen.yaml
 F:	drivers/clk/starfive/clk-starfive-jh7100.c
 F:	include/dt-bindings/clock/starfive-jh7100.h
 
+STARFIVE JH7100 RESET CONTROLLER DRIVER
+M:	Emil Renner Berthing <kernel@esmil.dk>
+S:	Maintained
+F:	Documentation/devicetree/bindings/reset/starfive,jh7100-reset.yaml
+F:	drivers/reset/reset-starfive-jh7100.c
+F:	include/dt-bindings/reset/starfive-jh7100.h
+
 STATIC BRANCH/CALL
 M:	Peter Zijlstra <peterz@infradead.org>
 M:	Josh Poimboeuf <jpoimboe@redhat.com>
diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index be799a5abf8a..a41fac304904 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -224,6 +224,14 @@ config RESET_SOCFPGA
 	  This enables the reset driver for the SoCFPGA ARMv7 platforms. This
 	  driver gets initialized early during platform init calls.
 
+config RESET_STARFIVE_JH7100
+	bool "StarFive JH7100 Reset Driver"
+	depends on SOC_STARFIVE || COMPILE_TEST
+	depends on OF
+	default SOC_STARFIVE
+	help
+	  This enables the reset controller driver for the StarFive JH7100 SoC.
+
 config RESET_SUNXI
 	bool "Allwinner SoCs Reset Driver" if COMPILE_TEST && !ARCH_SUNXI
 	default ARCH_SUNXI
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index 21d46d8869ff..bd0a97be18b5 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -29,6 +29,7 @@ obj-$(CONFIG_RESET_RZG2L_USBPHY_CTRL) += reset-rzg2l-usbphy-ctrl.o
 obj-$(CONFIG_RESET_SCMI) += reset-scmi.o
 obj-$(CONFIG_RESET_SIMPLE) += reset-simple.o
 obj-$(CONFIG_RESET_SOCFPGA) += reset-socfpga.o
+obj-$(CONFIG_RESET_STARFIVE_JH7100) += reset-starfive-jh7100.o
 obj-$(CONFIG_RESET_SUNXI) += reset-sunxi.o
 obj-$(CONFIG_RESET_TI_SCI) += reset-ti-sci.o
 obj-$(CONFIG_RESET_TI_SYSCON) += reset-ti-syscon.o
diff --git a/drivers/reset/reset-starfive-jh7100.c b/drivers/reset/reset-starfive-jh7100.c
new file mode 100644
index 000000000000..ae15ed5357f1
--- /dev/null
+++ b/drivers/reset/reset-starfive-jh7100.c
@@ -0,0 +1,165 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Reset driver for the StarFive JH7100 SoC
+ *
+ * Copyright (C) 2021 Emil Renner Berthing <kernel@esmil.dk>
+ *
+ */
+
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/reset-controller.h>
+#include <linux/spinlock.h>
+
+#include <dt-bindings/reset/starfive-jh7100.h>
+
+/* register offsets */
+#define JH7100_RESET_ASSERT0	0x00
+#define JH7100_RESET_ASSERT1	0x04
+#define JH7100_RESET_ASSERT2	0x08
+#define JH7100_RESET_ASSERT3	0x0c
+#define JH7100_RESET_STATUS0	0x10
+#define JH7100_RESET_STATUS1	0x14
+#define JH7100_RESET_STATUS2	0x18
+#define JH7100_RESET_STATUS3	0x1c
+
+struct jh7100_reset {
+	struct reset_controller_dev rcdev;
+	/* protect registers against overlapping read-modify-write */
+	spinlock_t lock;
+	void __iomem *base;
+};
+
+static inline struct jh7100_reset *
+jh7100_reset_from(struct reset_controller_dev *rcdev)
+{
+	return container_of(rcdev, struct jh7100_reset, rcdev);
+}
+
+static const u32 jh7100_reset_asserted[4] = {
+	BIT(JH7100_RST_U74 % 32) |
+	BIT(JH7100_RST_VP6_DRESET % 32) |
+	BIT(JH7100_RST_VP6_BRESET % 32),
+
+	BIT(JH7100_RST_HIFI4_DRESET % 32) |
+	BIT(JH7100_RST_HIFI4_BRESET % 32),
+
+	BIT(JH7100_RST_E24 % 32)
+};
+
+static int jh7100_reset_update(struct reset_controller_dev *rcdev,
+			       unsigned long id, bool assert)
+{
+	struct jh7100_reset *data = jh7100_reset_from(rcdev);
+	unsigned long offset = id / 32;
+	void __iomem *reg_assert = data->base + JH7100_RESET_ASSERT0 + 4 * offset;
+	void __iomem *reg_status = data->base + JH7100_RESET_STATUS0 + 4 * offset;
+	u32 mask = BIT(id % 32);
+	u32 done = jh7100_reset_asserted[offset] & mask;
+	unsigned long flags;
+	u32 value;
+	int ret;
+
+	if (!assert)
+		done ^= mask;
+
+	spin_lock_irqsave(&data->lock, flags);
+
+	value = readl(reg_assert);
+	if (assert)
+		value |= mask;
+	else
+		value &= ~mask;
+	writel(value, reg_assert);
+
+	/* if the associated clock is gated, deasserting might otherwise hang forever */
+	ret = readl_poll_timeout(reg_status, value, (value & mask) == done, 0, 1000);
+
+	spin_unlock_irqrestore(&data->lock, flags);
+	return ret;
+}
+
+static int jh7100_reset_assert(struct reset_controller_dev *rcdev,
+			       unsigned long id)
+{
+	dev_dbg(rcdev->dev, "assert(%lu)\n", id);
+	return jh7100_reset_update(rcdev, id, true);
+}
+
+static int jh7100_reset_deassert(struct reset_controller_dev *rcdev,
+				 unsigned long id)
+{
+	dev_dbg(rcdev->dev, "deassert(%lu)\n", id);
+	return jh7100_reset_update(rcdev, id, false);
+}
+
+static int jh7100_reset_reset(struct reset_controller_dev *rcdev,
+			      unsigned long id)
+{
+	int ret;
+
+	dev_dbg(rcdev->dev, "reset(%lu)\n", id);
+	ret = jh7100_reset_assert(rcdev, id);
+	if (ret)
+		return ret;
+
+	return jh7100_reset_deassert(rcdev, id);
+}
+
+static int jh7100_reset_status(struct reset_controller_dev *rcdev,
+			       unsigned long id)
+{
+	struct jh7100_reset *data = jh7100_reset_from(rcdev);
+	unsigned long offset = id / 32;
+	void __iomem *reg_status = data->base + JH7100_RESET_STATUS0 + 4 * offset;
+	u32 mask = BIT(id % 32);
+	u32 value = (readl(reg_status) ^ jh7100_reset_asserted[offset]) & mask;
+
+	dev_dbg(rcdev->dev, "status(%lu) = %d\n", id, !value);
+	return !value;
+}
+
+static const struct reset_control_ops jh7100_reset_ops = {
+	.assert		= jh7100_reset_assert,
+	.deassert	= jh7100_reset_deassert,
+	.reset		= jh7100_reset_reset,
+	.status		= jh7100_reset_status,
+};
+
+static int jh7100_reset_probe(struct platform_device *pdev)
+{
+	struct jh7100_reset *data;
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(data->base))
+		return PTR_ERR(data->base);
+
+	data->rcdev.ops = &jh7100_reset_ops;
+	data->rcdev.owner = THIS_MODULE;
+	data->rcdev.nr_resets = JH7100_RSTN_END;
+	data->rcdev.dev = &pdev->dev;
+	data->rcdev.of_node = pdev->dev.of_node;
+	spin_lock_init(&data->lock);
+
+	return devm_reset_controller_register(&pdev->dev, &data->rcdev);
+}
+
+static const struct of_device_id jh7100_reset_dt_ids[] = {
+	{ .compatible = "starfive,jh7100-reset" },
+	{ /* sentinel */ }
+};
+
+static struct platform_driver jh7100_reset_driver = {
+	.probe = jh7100_reset_probe,
+	.driver = {
+		.name = "jh7100-reset",
+		.of_match_table = jh7100_reset_dt_ids,
+	},
+};
+builtin_platform_driver(jh7100_reset_driver);
-- 
2.33.1


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 143+ messages in thread

* [PATCH v2 10/16] dt-bindings: pinctrl: Add StarFive pinctrl definitions
  2021-10-21 17:42 ` Emil Renner Berthing
@ 2021-10-21 17:42   ` Emil Renner Berthing
  -1 siblings, 0 replies; 143+ messages in thread
From: Emil Renner Berthing @ 2021-10-21 17:42 UTC (permalink / raw)
  To: linux-riscv, devicetree, linux-clk, linux-gpio, linux-serial
  Cc: Emil Renner Berthing, Palmer Dabbelt, Paul Walmsley, Rob Herring,
	Michael Turquette, Stephen Boyd, Thomas Gleixner, Marc Zyngier,
	Philipp Zabel, Linus Walleij, Greg Kroah-Hartman, Daniel Lezcano,
	Andy Shevchenko, Jiri Slaby, Maximilian Luz, Sagar Kadam,
	Drew Fustini, Geert Uytterhoeven, Michael Zhu, Fu Wei,
	Anup Patel, Atish Patra, Matteo Croce, linux-kernel

Add definitons for pins and GPIO input, output and output enable
signals on the StarFive JH7100 SoC.

Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
---
 .../dt-bindings/pinctrl/pinctrl-starfive.h    | 274 ++++++++++++++++++
 1 file changed, 274 insertions(+)
 create mode 100644 include/dt-bindings/pinctrl/pinctrl-starfive.h

diff --git a/include/dt-bindings/pinctrl/pinctrl-starfive.h b/include/dt-bindings/pinctrl/pinctrl-starfive.h
new file mode 100644
index 000000000000..f9b6caa83558
--- /dev/null
+++ b/include/dt-bindings/pinctrl/pinctrl-starfive.h
@@ -0,0 +1,274 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2021 Emil Renner Berthing <kernel@esmil.dk>
+ */
+#ifndef _DT_BINDINGS_PINCTRL_STARFIVE_H
+#define _DT_BINDINGS_PINCTRL_STARFIVE_H
+
+#define PAD_GPIO_OFFSET		0
+#define PAD_FUNC_SHARE_OFFSET	64
+#define PAD_GPIO(x)		(PAD_GPIO_OFFSET + (x))
+#define PAD_FUNC_SHARE(x)	(PAD_FUNC_SHARE_OFFSET + (x))
+
+/*
+ * GPIOMUX bits:
+ *  | 31 - 24 | 23 - 16 | 15 - 8 |     7    |     6    |  5 - 0  |
+ *  |  dout   |  doen   |  din   | dout rev | doen rev | gpio nr |
+ *
+ * dout:     output signal
+ * doen:     output enable signal
+ * din:      optional input signal, 0xff = none
+ * dout rev: output signal reverse bit
+ * doen rev: output enable signal reverse bit
+ * gpio nr:  gpio number, 0 - 63
+ */
+#define GPIOMUX(n, dout, doen, din) ( \
+		(((dout) & 0x80000000) >> (31 - 7)) | (((dout) & 0xff) << 24) | \
+		(((doen) & 0x80000000) >> (31 - 6)) | (((doen) & 0xff) << 16) | \
+		(((din) & 0xff) << 8) | \
+		((n) & 0x3f))
+
+#define GPO_REVERSE				0x80000000
+
+#define GPO_LOW					0
+#define GPO_HIGH				1
+#define GPO_ENABLE				0
+#define GPO_DISABLE				1
+#define GPO_CLK_GMAC_PAPHYREF			2
+#define GPO_JTAG_TDO				3
+#define GPO_JTAG_TDO_OEN			4
+#define GPO_DMIC_CLK_OUT			5
+#define GPO_DSP_JTDOEN_PAD			6
+#define GPO_DSP_JTDO_PAD			7
+#define GPO_I2C0_PAD_SCK_OE			8
+#define GPO_I2C0_PAD_SCK_OEN			(GPO_I2C0_PAD_SCK_OE | GPO_REVERSE)
+#define GPO_I2C0_PAD_SDA_OE			9
+#define GPO_I2C0_PAD_SDA_OEN			(GPO_I2C0_PAD_SDA_OE | GPO_REVERSE)
+#define GPO_I2C1_PAD_SCK_OE			10
+#define GPO_I2C1_PAD_SCK_OEN			(GPO_I2C1_PAD_SCK_OE | GPO_REVERSE)
+#define GPO_I2C1_PAD_SDA_OE			11
+#define GPO_I2C1_PAD_SDA_OEN			(GPO_I2C1_PAD_SDA_OE | GPO_REVERSE)
+#define GPO_I2C2_PAD_SCK_OE			12
+#define GPO_I2C2_PAD_SCK_OEN			(GPO_I2C2_PAD_SCK_OE | GPO_REVERSE)
+#define GPO_I2C2_PAD_SDA_OE			13
+#define GPO_I2C2_PAD_SDA_OEN			(GPO_I2C2_PAD_SDA_OE | GPO_REVERSE)
+#define GPO_I2C3_PAD_SCK_OE			14
+#define GPO_I2C3_PAD_SCK_OEN			(GPO_I2C3_PAD_SCK_OE | GPO_REVERSE)
+#define GPO_I2C3_PAD_SDA_OE			15
+#define GPO_I2C3_PAD_SDA_OEN			(GPO_I2C3_PAD_SDA_OE | GPO_REVERSE)
+#define GPO_I2SRX_BCLK_OUT			16
+#define GPO_I2SRX_BCLK_OUT_OEN			17
+#define GPO_I2SRX_LRCK_OUT			18
+#define GPO_I2SRX_LRCK_OUT_OEN			19
+#define GPO_I2SRX_MCLK_OUT			20
+#define GPO_I2STX_BCLK_OUT			21
+#define GPO_I2STX_BCLK_OUT_OEN			22
+#define GPO_I2STX_LRCK_OUT			23
+#define GPO_I2STX_LRCK_OUT_OEN			24
+#define GPO_I2STX_MCLK_OUT			25
+#define GPO_I2STX_SDOUT0			26
+#define GPO_I2STX_SDOUT1			27
+#define GPO_LCD_PAD_CSM_N			28
+#define GPO_PWM_PAD_OE_N_BIT0			29
+#define GPO_PWM_PAD_OE_N_BIT1			30
+#define GPO_PWM_PAD_OE_N_BIT2			31
+#define GPO_PWM_PAD_OE_N_BIT3			32
+#define GPO_PWM_PAD_OE_N_BIT4			33
+#define GPO_PWM_PAD_OE_N_BIT5			34
+#define GPO_PWM_PAD_OE_N_BIT6			35
+#define GPO_PWM_PAD_OE_N_BIT7			36
+#define GPO_PWM_PAD_OUT_BIT0			37
+#define GPO_PWM_PAD_OUT_BIT1			38
+#define GPO_PWM_PAD_OUT_BIT2			39
+#define GPO_PWM_PAD_OUT_BIT3			40
+#define GPO_PWM_PAD_OUT_BIT4			41
+#define GPO_PWM_PAD_OUT_BIT5			42
+#define GPO_PWM_PAD_OUT_BIT6			43
+#define GPO_PWM_PAD_OUT_BIT7			44
+#define GPO_PWMDAC_LEFT_OUT			45
+#define GPO_PWMDAC_RIGHT_OUT			46
+#define GPO_QSPI_CSN1_OUT			47
+#define GPO_QSPI_CSN2_OUT			48
+#define GPO_QSPI_CSN3_OUT			49
+#define GPO_REGISTER23_SCFG_CMSENSOR_RST0	50
+#define GPO_REGISTER23_SCFG_CMSENSOR_RST1	51
+#define GPO_REGISTER32_SCFG_GMAC_PHY_RSTN	52
+#define GPO_SDIO0_PAD_CARD_POWER_EN		53
+#define GPO_SDIO0_PAD_CCLK_OUT			54
+#define GPO_SDIO0_PAD_CCMD_OE			55
+#define GPO_SDIO0_PAD_CCMD_OEN			(GPO_SDIO0_PAD_CCMD_OE | GPO_REVERSE)
+#define GPO_SDIO0_PAD_CCMD_OUT			56
+#define GPO_SDIO0_PAD_CDATA_OE_BIT0		57
+#define GPO_SDIO0_PAD_CDATA_OEN_BIT0		(GPO_SDIO0_PAD_CDATA_OE_BIT0 | GPO_REVERSE)
+#define GPO_SDIO0_PAD_CDATA_OE_BIT1		58
+#define GPO_SDIO0_PAD_CDATA_OEN_BIT1		(GPO_SDIO0_PAD_CDATA_OE_BIT1 | GPO_REVERSE)
+#define GPO_SDIO0_PAD_CDATA_OE_BIT2		59
+#define GPO_SDIO0_PAD_CDATA_OEN_BIT2		(GPO_SDIO0_PAD_CDATA_OE_BIT2 | GPO_REVERSE)
+#define GPO_SDIO0_PAD_CDATA_OE_BIT3		60
+#define GPO_SDIO0_PAD_CDATA_OEN_BIT3		(GPO_SDIO0_PAD_CDATA_OE_BIT3 | GPO_REVERSE)
+#define GPO_SDIO0_PAD_CDATA_OE_BIT4		61
+#define GPO_SDIO0_PAD_CDATA_OEN_BIT4		(GPO_SDIO0_PAD_CDATA_OE_BIT4 | GPO_REVERSE)
+#define GPO_SDIO0_PAD_CDATA_OE_BIT5		62
+#define GPO_SDIO0_PAD_CDATA_OEN_BIT5		(GPO_SDIO0_PAD_CDATA_OE_BIT5 | GPO_REVERSE)
+#define GPO_SDIO0_PAD_CDATA_OE_BIT6		63
+#define GPO_SDIO0_PAD_CDATA_OEN_BIT6		(GPO_SDIO0_PAD_CDATA_OE_BIT6 | GPO_REVERSE)
+#define GPO_SDIO0_PAD_CDATA_OE_BIT7		64
+#define GPO_SDIO0_PAD_CDATA_OEN_BIT7		(GPO_SDIO0_PAD_CDATA_OE_BIT7 | GPO_REVERSE)
+#define GPO_SDIO0_PAD_CDATA_OUT_BIT0		65
+#define GPO_SDIO0_PAD_CDATA_OUT_BIT1		66
+#define GPO_SDIO0_PAD_CDATA_OUT_BIT2		67
+#define GPO_SDIO0_PAD_CDATA_OUT_BIT3		68
+#define GPO_SDIO0_PAD_CDATA_OUT_BIT4		69
+#define GPO_SDIO0_PAD_CDATA_OUT_BIT5		70
+#define GPO_SDIO0_PAD_CDATA_OUT_BIT6		71
+#define GPO_SDIO0_PAD_CDATA_OUT_BIT7		72
+#define GPO_SDIO0_PAD_RST_N			73
+#define GPO_SDIO1_PAD_CARD_POWER_EN		74
+#define GPO_SDIO1_PAD_CCLK_OUT			75
+#define GPO_SDIO1_PAD_CCMD_OE			76
+#define GPO_SDIO1_PAD_CCMD_OEN			(GPO_SDIO1_PAD_CCMD_OE | GPO_REVERSE)
+#define GPO_SDIO1_PAD_CCMD_OUT			77
+#define GPO_SDIO1_PAD_CDATA_OE_BIT0		78
+#define GPO_SDIO1_PAD_CDATA_OEN_BIT0		(GPO_SDIO1_PAD_CDATA_OE_BIT0 | GPO_REVERSE)
+#define GPO_SDIO1_PAD_CDATA_OE_BIT1		79
+#define GPO_SDIO1_PAD_CDATA_OEN_BIT1		(GPO_SDIO1_PAD_CDATA_OE_BIT1 | GPO_REVERSE)
+#define GPO_SDIO1_PAD_CDATA_OE_BIT2		80
+#define GPO_SDIO1_PAD_CDATA_OEN_BIT2		(GPO_SDIO1_PAD_CDATA_OE_BIT2 | GPO_REVERSE)
+#define GPO_SDIO1_PAD_CDATA_OE_BIT3		81
+#define GPO_SDIO1_PAD_CDATA_OEN_BIT3		(GPO_SDIO1_PAD_CDATA_OE_BIT3 | GPO_REVERSE)
+#define GPO_SDIO1_PAD_CDATA_OE_BIT4		82
+#define GPO_SDIO1_PAD_CDATA_OEN_BIT4		(GPO_SDIO1_PAD_CDATA_OE_BIT4 | GPO_REVERSE)
+#define GPO_SDIO1_PAD_CDATA_OE_BIT5		83
+#define GPO_SDIO1_PAD_CDATA_OEN_BIT5		(GPO_SDIO1_PAD_CDATA_OE_BIT5 | GPO_REVERSE)
+#define GPO_SDIO1_PAD_CDATA_OE_BIT6		84
+#define GPO_SDIO1_PAD_CDATA_OEN_BIT6		(GPO_SDIO1_PAD_CDATA_OE_BIT6 | GPO_REVERSE)
+#define GPO_SDIO1_PAD_CDATA_OE_BIT7		85
+#define GPO_SDIO1_PAD_CDATA_OEN_BIT7		(GPO_SDIO1_PAD_CDATA_OE_BIT7 | GPO_REVERSE)
+#define GPO_SDIO1_PAD_CDATA_OUT_BIT0		86
+#define GPO_SDIO1_PAD_CDATA_OUT_BIT1		87
+#define GPO_SDIO1_PAD_CDATA_OUT_BIT2		88
+#define GPO_SDIO1_PAD_CDATA_OUT_BIT3		89
+#define GPO_SDIO1_PAD_CDATA_OUT_BIT4		90
+#define GPO_SDIO1_PAD_CDATA_OUT_BIT5		91
+#define GPO_SDIO1_PAD_CDATA_OUT_BIT6		92
+#define GPO_SDIO1_PAD_CDATA_OUT_BIT7		93
+#define GPO_SDIO1_PAD_RST_N			94
+#define GPO_SPDIF_TX_SDOUT			95
+#define GPO_SPDIF_TX_SDOUT_OEN			96
+#define GPO_SPI0_PAD_OE_N			97
+#define GPO_SPI0_PAD_SCK_OUT			98
+#define GPO_SPI0_PAD_SS_0_N			99
+#define GPO_SPI0_PAD_SS_1_N			100
+#define GPO_SPI0_PAD_TXD			101
+#define GPO_SPI1_PAD_OE_N			102
+#define GPO_SPI1_PAD_SCK_OUT			103
+#define GPO_SPI1_PAD_SS_0_N			104
+#define GPO_SPI1_PAD_SS_1_N			105
+#define GPO_SPI1_PAD_TXD			106
+#define GPO_SPI2_PAD_OE_N			107
+#define GPO_SPI2_PAD_SCK_OUT			108
+#define GPO_SPI2_PAD_SS_0_N			109
+#define GPO_SPI2_PAD_SS_1_N			110
+#define GPO_SPI2_PAD_TXD			111
+#define GPO_SPI2AHB_PAD_OE_N_BIT0		112
+#define GPO_SPI2AHB_PAD_OE_N_BIT1		113
+#define GPO_SPI2AHB_PAD_OE_N_BIT2		114
+#define GPO_SPI2AHB_PAD_OE_N_BIT3		115
+#define GPO_SPI2AHB_PAD_TXD_BIT0		116
+#define GPO_SPI2AHB_PAD_TXD_BIT1		117
+#define GPO_SPI2AHB_PAD_TXD_BIT2		118
+#define GPO_SPI2AHB_PAD_TXD_BIT3		119
+#define GPO_SPI3_PAD_OE_N			120
+#define GPO_SPI3_PAD_SCK_OUT			121
+#define GPO_SPI3_PAD_SS_0_N			122
+#define GPO_SPI3_PAD_SS_1_N			123
+#define GPO_SPI3_PAD_TXD			124
+#define GPO_UART0_PAD_DTRN			125
+#define GPO_UART0_PAD_RTSN			126
+#define GPO_UART0_PAD_SOUT			127
+#define GPO_UART1_PAD_SOUT			128
+#define GPO_UART2_PAD_DTR_N			129
+#define GPO_UART2_PAD_RTS_N			130
+#define GPO_UART2_PAD_SOUT			131
+#define GPO_UART3_PAD_SOUT			132
+#define GPO_USB_DRV_BUS				133
+
+#define GPI_CPU_JTAG_TCK			0
+#define GPI_CPU_JTAG_TDI			1
+#define GPI_CPU_JTAG_TMS			2
+#define GPI_CPU_JTAG_TRST			3
+#define GPI_DMIC_SDIN_BIT0			4
+#define GPI_DMIC_SDIN_BIT1			5
+#define GPI_DSP_JTCK_PAD			6
+#define GPI_DSP_JTDI_PAD			7
+#define GPI_DSP_JTMS_PAD			8
+#define GPI_DSP_TRST_PAD			9
+#define GPI_I2C0_PAD_SCK_IN			10
+#define GPI_I2C0_PAD_SDA_IN			11
+#define GPI_I2C1_PAD_SCK_IN			12
+#define GPI_I2C1_PAD_SDA_IN			13
+#define GPI_I2C2_PAD_SCK_IN			14
+#define GPI_I2C2_PAD_SDA_IN			15
+#define GPI_I2C3_PAD_SCK_IN			16
+#define GPI_I2C3_PAD_SDA_IN			17
+#define GPI_I2SRX_BCLK_IN			18
+#define GPI_I2SRX_LRCK_IN			19
+#define GPI_I2SRX_SDIN_BIT0			20
+#define GPI_I2SRX_SDIN_BIT1			21
+#define GPI_I2SRX_SDIN_BIT2			22
+#define GPI_I2STX_BCLK_IN			23
+#define GPI_I2STX_LRCK_IN			24
+#define GPI_SDIO0_PAD_CARD_DETECT_N		25
+#define GPI_SDIO0_PAD_CARD_WRITE_PRT		26
+#define GPI_SDIO0_PAD_CCMD_IN			27
+#define GPI_SDIO0_PAD_CDATA_IN_BIT0		28
+#define GPI_SDIO0_PAD_CDATA_IN_BIT1		29
+#define GPI_SDIO0_PAD_CDATA_IN_BIT2		30
+#define GPI_SDIO0_PAD_CDATA_IN_BIT3		31
+#define GPI_SDIO0_PAD_CDATA_IN_BIT4		32
+#define GPI_SDIO0_PAD_CDATA_IN_BIT5		33
+#define GPI_SDIO0_PAD_CDATA_IN_BIT6		34
+#define GPI_SDIO0_PAD_CDATA_IN_BIT7		35
+#define GPI_SDIO1_PAD_CARD_DETECT_N		36
+#define GPI_SDIO1_PAD_CARD_WRITE_PRT		37
+#define GPI_SDIO1_PAD_CCMD_IN			38
+#define GPI_SDIO1_PAD_CDATA_IN_BIT0		39
+#define GPI_SDIO1_PAD_CDATA_IN_BIT1		40
+#define GPI_SDIO1_PAD_CDATA_IN_BIT2		41
+#define GPI_SDIO1_PAD_CDATA_IN_BIT3		42
+#define GPI_SDIO1_PAD_CDATA_IN_BIT4		43
+#define GPI_SDIO1_PAD_CDATA_IN_BIT5		44
+#define GPI_SDIO1_PAD_CDATA_IN_BIT6		45
+#define GPI_SDIO1_PAD_CDATA_IN_BIT7		46
+#define GPI_SPDIF_RX_SDIN			47
+#define GPI_SPI0_PAD_RXD			48
+#define GPI_SPI0_PAD_SS_IN_N			49
+#define GPI_SPI1_PAD_RXD			50
+#define GPI_SPI1_PAD_SS_IN_N			51
+#define GPI_SPI2_PAD_RXD			52
+#define GPI_SPI2_PAD_SS_IN_N			53
+#define GPI_SPI2AHB_PAD_RXD_BIT0		54
+#define GPI_SPI2AHB_PAD_RXD_BIT1		55
+#define GPI_SPI2AHB_PAD_RXD_BIT2		56
+#define GPI_SPI2AHB_PAD_RXD_BIT3		57
+#define GPI_SPI2AHB_PAD_SS_N			58
+#define GPI_SPI2AHB_SLV_SCLKIN			59
+#define GPI_SPI3_PAD_RXD			60
+#define GPI_SPI3_PAD_SS_IN_N			61
+#define GPI_UART0_PAD_CTSN			62
+#define GPI_UART0_PAD_DCDN			63
+#define GPI_UART0_PAD_DSRN			64
+#define GPI_UART0_PAD_RIN			65
+#define GPI_UART0_PAD_SIN			66
+#define GPI_UART1_PAD_SIN			67
+#define GPI_UART2_PAD_CTS_N			68
+#define GPI_UART2_PAD_DCD_N			69
+#define GPI_UART2_PAD_DSR_N			70
+#define GPI_UART2_PAD_RI_N			71
+#define GPI_UART2_PAD_SIN			72
+#define GPI_UART3_PAD_SIN			73
+#define GPI_USB_OVER_CURRENT			74
+
+#define GPI_NONE				0xff
+
+#endif
-- 
2.33.1


^ permalink raw reply related	[flat|nested] 143+ messages in thread

* [PATCH v2 10/16] dt-bindings: pinctrl: Add StarFive pinctrl definitions
@ 2021-10-21 17:42   ` Emil Renner Berthing
  0 siblings, 0 replies; 143+ messages in thread
From: Emil Renner Berthing @ 2021-10-21 17:42 UTC (permalink / raw)
  To: linux-riscv, devicetree, linux-clk, linux-gpio, linux-serial
  Cc: Emil Renner Berthing, Palmer Dabbelt, Paul Walmsley, Rob Herring,
	Michael Turquette, Stephen Boyd, Thomas Gleixner, Marc Zyngier,
	Philipp Zabel, Linus Walleij, Greg Kroah-Hartman, Daniel Lezcano,
	Andy Shevchenko, Jiri Slaby, Maximilian Luz, Sagar Kadam,
	Drew Fustini, Geert Uytterhoeven, Michael Zhu, Fu Wei,
	Anup Patel, Atish Patra, Matteo Croce, linux-kernel

Add definitons for pins and GPIO input, output and output enable
signals on the StarFive JH7100 SoC.

Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
---
 .../dt-bindings/pinctrl/pinctrl-starfive.h    | 274 ++++++++++++++++++
 1 file changed, 274 insertions(+)
 create mode 100644 include/dt-bindings/pinctrl/pinctrl-starfive.h

diff --git a/include/dt-bindings/pinctrl/pinctrl-starfive.h b/include/dt-bindings/pinctrl/pinctrl-starfive.h
new file mode 100644
index 000000000000..f9b6caa83558
--- /dev/null
+++ b/include/dt-bindings/pinctrl/pinctrl-starfive.h
@@ -0,0 +1,274 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2021 Emil Renner Berthing <kernel@esmil.dk>
+ */
+#ifndef _DT_BINDINGS_PINCTRL_STARFIVE_H
+#define _DT_BINDINGS_PINCTRL_STARFIVE_H
+
+#define PAD_GPIO_OFFSET		0
+#define PAD_FUNC_SHARE_OFFSET	64
+#define PAD_GPIO(x)		(PAD_GPIO_OFFSET + (x))
+#define PAD_FUNC_SHARE(x)	(PAD_FUNC_SHARE_OFFSET + (x))
+
+/*
+ * GPIOMUX bits:
+ *  | 31 - 24 | 23 - 16 | 15 - 8 |     7    |     6    |  5 - 0  |
+ *  |  dout   |  doen   |  din   | dout rev | doen rev | gpio nr |
+ *
+ * dout:     output signal
+ * doen:     output enable signal
+ * din:      optional input signal, 0xff = none
+ * dout rev: output signal reverse bit
+ * doen rev: output enable signal reverse bit
+ * gpio nr:  gpio number, 0 - 63
+ */
+#define GPIOMUX(n, dout, doen, din) ( \
+		(((dout) & 0x80000000) >> (31 - 7)) | (((dout) & 0xff) << 24) | \
+		(((doen) & 0x80000000) >> (31 - 6)) | (((doen) & 0xff) << 16) | \
+		(((din) & 0xff) << 8) | \
+		((n) & 0x3f))
+
+#define GPO_REVERSE				0x80000000
+
+#define GPO_LOW					0
+#define GPO_HIGH				1
+#define GPO_ENABLE				0
+#define GPO_DISABLE				1
+#define GPO_CLK_GMAC_PAPHYREF			2
+#define GPO_JTAG_TDO				3
+#define GPO_JTAG_TDO_OEN			4
+#define GPO_DMIC_CLK_OUT			5
+#define GPO_DSP_JTDOEN_PAD			6
+#define GPO_DSP_JTDO_PAD			7
+#define GPO_I2C0_PAD_SCK_OE			8
+#define GPO_I2C0_PAD_SCK_OEN			(GPO_I2C0_PAD_SCK_OE | GPO_REVERSE)
+#define GPO_I2C0_PAD_SDA_OE			9
+#define GPO_I2C0_PAD_SDA_OEN			(GPO_I2C0_PAD_SDA_OE | GPO_REVERSE)
+#define GPO_I2C1_PAD_SCK_OE			10
+#define GPO_I2C1_PAD_SCK_OEN			(GPO_I2C1_PAD_SCK_OE | GPO_REVERSE)
+#define GPO_I2C1_PAD_SDA_OE			11
+#define GPO_I2C1_PAD_SDA_OEN			(GPO_I2C1_PAD_SDA_OE | GPO_REVERSE)
+#define GPO_I2C2_PAD_SCK_OE			12
+#define GPO_I2C2_PAD_SCK_OEN			(GPO_I2C2_PAD_SCK_OE | GPO_REVERSE)
+#define GPO_I2C2_PAD_SDA_OE			13
+#define GPO_I2C2_PAD_SDA_OEN			(GPO_I2C2_PAD_SDA_OE | GPO_REVERSE)
+#define GPO_I2C3_PAD_SCK_OE			14
+#define GPO_I2C3_PAD_SCK_OEN			(GPO_I2C3_PAD_SCK_OE | GPO_REVERSE)
+#define GPO_I2C3_PAD_SDA_OE			15
+#define GPO_I2C3_PAD_SDA_OEN			(GPO_I2C3_PAD_SDA_OE | GPO_REVERSE)
+#define GPO_I2SRX_BCLK_OUT			16
+#define GPO_I2SRX_BCLK_OUT_OEN			17
+#define GPO_I2SRX_LRCK_OUT			18
+#define GPO_I2SRX_LRCK_OUT_OEN			19
+#define GPO_I2SRX_MCLK_OUT			20
+#define GPO_I2STX_BCLK_OUT			21
+#define GPO_I2STX_BCLK_OUT_OEN			22
+#define GPO_I2STX_LRCK_OUT			23
+#define GPO_I2STX_LRCK_OUT_OEN			24
+#define GPO_I2STX_MCLK_OUT			25
+#define GPO_I2STX_SDOUT0			26
+#define GPO_I2STX_SDOUT1			27
+#define GPO_LCD_PAD_CSM_N			28
+#define GPO_PWM_PAD_OE_N_BIT0			29
+#define GPO_PWM_PAD_OE_N_BIT1			30
+#define GPO_PWM_PAD_OE_N_BIT2			31
+#define GPO_PWM_PAD_OE_N_BIT3			32
+#define GPO_PWM_PAD_OE_N_BIT4			33
+#define GPO_PWM_PAD_OE_N_BIT5			34
+#define GPO_PWM_PAD_OE_N_BIT6			35
+#define GPO_PWM_PAD_OE_N_BIT7			36
+#define GPO_PWM_PAD_OUT_BIT0			37
+#define GPO_PWM_PAD_OUT_BIT1			38
+#define GPO_PWM_PAD_OUT_BIT2			39
+#define GPO_PWM_PAD_OUT_BIT3			40
+#define GPO_PWM_PAD_OUT_BIT4			41
+#define GPO_PWM_PAD_OUT_BIT5			42
+#define GPO_PWM_PAD_OUT_BIT6			43
+#define GPO_PWM_PAD_OUT_BIT7			44
+#define GPO_PWMDAC_LEFT_OUT			45
+#define GPO_PWMDAC_RIGHT_OUT			46
+#define GPO_QSPI_CSN1_OUT			47
+#define GPO_QSPI_CSN2_OUT			48
+#define GPO_QSPI_CSN3_OUT			49
+#define GPO_REGISTER23_SCFG_CMSENSOR_RST0	50
+#define GPO_REGISTER23_SCFG_CMSENSOR_RST1	51
+#define GPO_REGISTER32_SCFG_GMAC_PHY_RSTN	52
+#define GPO_SDIO0_PAD_CARD_POWER_EN		53
+#define GPO_SDIO0_PAD_CCLK_OUT			54
+#define GPO_SDIO0_PAD_CCMD_OE			55
+#define GPO_SDIO0_PAD_CCMD_OEN			(GPO_SDIO0_PAD_CCMD_OE | GPO_REVERSE)
+#define GPO_SDIO0_PAD_CCMD_OUT			56
+#define GPO_SDIO0_PAD_CDATA_OE_BIT0		57
+#define GPO_SDIO0_PAD_CDATA_OEN_BIT0		(GPO_SDIO0_PAD_CDATA_OE_BIT0 | GPO_REVERSE)
+#define GPO_SDIO0_PAD_CDATA_OE_BIT1		58
+#define GPO_SDIO0_PAD_CDATA_OEN_BIT1		(GPO_SDIO0_PAD_CDATA_OE_BIT1 | GPO_REVERSE)
+#define GPO_SDIO0_PAD_CDATA_OE_BIT2		59
+#define GPO_SDIO0_PAD_CDATA_OEN_BIT2		(GPO_SDIO0_PAD_CDATA_OE_BIT2 | GPO_REVERSE)
+#define GPO_SDIO0_PAD_CDATA_OE_BIT3		60
+#define GPO_SDIO0_PAD_CDATA_OEN_BIT3		(GPO_SDIO0_PAD_CDATA_OE_BIT3 | GPO_REVERSE)
+#define GPO_SDIO0_PAD_CDATA_OE_BIT4		61
+#define GPO_SDIO0_PAD_CDATA_OEN_BIT4		(GPO_SDIO0_PAD_CDATA_OE_BIT4 | GPO_REVERSE)
+#define GPO_SDIO0_PAD_CDATA_OE_BIT5		62
+#define GPO_SDIO0_PAD_CDATA_OEN_BIT5		(GPO_SDIO0_PAD_CDATA_OE_BIT5 | GPO_REVERSE)
+#define GPO_SDIO0_PAD_CDATA_OE_BIT6		63
+#define GPO_SDIO0_PAD_CDATA_OEN_BIT6		(GPO_SDIO0_PAD_CDATA_OE_BIT6 | GPO_REVERSE)
+#define GPO_SDIO0_PAD_CDATA_OE_BIT7		64
+#define GPO_SDIO0_PAD_CDATA_OEN_BIT7		(GPO_SDIO0_PAD_CDATA_OE_BIT7 | GPO_REVERSE)
+#define GPO_SDIO0_PAD_CDATA_OUT_BIT0		65
+#define GPO_SDIO0_PAD_CDATA_OUT_BIT1		66
+#define GPO_SDIO0_PAD_CDATA_OUT_BIT2		67
+#define GPO_SDIO0_PAD_CDATA_OUT_BIT3		68
+#define GPO_SDIO0_PAD_CDATA_OUT_BIT4		69
+#define GPO_SDIO0_PAD_CDATA_OUT_BIT5		70
+#define GPO_SDIO0_PAD_CDATA_OUT_BIT6		71
+#define GPO_SDIO0_PAD_CDATA_OUT_BIT7		72
+#define GPO_SDIO0_PAD_RST_N			73
+#define GPO_SDIO1_PAD_CARD_POWER_EN		74
+#define GPO_SDIO1_PAD_CCLK_OUT			75
+#define GPO_SDIO1_PAD_CCMD_OE			76
+#define GPO_SDIO1_PAD_CCMD_OEN			(GPO_SDIO1_PAD_CCMD_OE | GPO_REVERSE)
+#define GPO_SDIO1_PAD_CCMD_OUT			77
+#define GPO_SDIO1_PAD_CDATA_OE_BIT0		78
+#define GPO_SDIO1_PAD_CDATA_OEN_BIT0		(GPO_SDIO1_PAD_CDATA_OE_BIT0 | GPO_REVERSE)
+#define GPO_SDIO1_PAD_CDATA_OE_BIT1		79
+#define GPO_SDIO1_PAD_CDATA_OEN_BIT1		(GPO_SDIO1_PAD_CDATA_OE_BIT1 | GPO_REVERSE)
+#define GPO_SDIO1_PAD_CDATA_OE_BIT2		80
+#define GPO_SDIO1_PAD_CDATA_OEN_BIT2		(GPO_SDIO1_PAD_CDATA_OE_BIT2 | GPO_REVERSE)
+#define GPO_SDIO1_PAD_CDATA_OE_BIT3		81
+#define GPO_SDIO1_PAD_CDATA_OEN_BIT3		(GPO_SDIO1_PAD_CDATA_OE_BIT3 | GPO_REVERSE)
+#define GPO_SDIO1_PAD_CDATA_OE_BIT4		82
+#define GPO_SDIO1_PAD_CDATA_OEN_BIT4		(GPO_SDIO1_PAD_CDATA_OE_BIT4 | GPO_REVERSE)
+#define GPO_SDIO1_PAD_CDATA_OE_BIT5		83
+#define GPO_SDIO1_PAD_CDATA_OEN_BIT5		(GPO_SDIO1_PAD_CDATA_OE_BIT5 | GPO_REVERSE)
+#define GPO_SDIO1_PAD_CDATA_OE_BIT6		84
+#define GPO_SDIO1_PAD_CDATA_OEN_BIT6		(GPO_SDIO1_PAD_CDATA_OE_BIT6 | GPO_REVERSE)
+#define GPO_SDIO1_PAD_CDATA_OE_BIT7		85
+#define GPO_SDIO1_PAD_CDATA_OEN_BIT7		(GPO_SDIO1_PAD_CDATA_OE_BIT7 | GPO_REVERSE)
+#define GPO_SDIO1_PAD_CDATA_OUT_BIT0		86
+#define GPO_SDIO1_PAD_CDATA_OUT_BIT1		87
+#define GPO_SDIO1_PAD_CDATA_OUT_BIT2		88
+#define GPO_SDIO1_PAD_CDATA_OUT_BIT3		89
+#define GPO_SDIO1_PAD_CDATA_OUT_BIT4		90
+#define GPO_SDIO1_PAD_CDATA_OUT_BIT5		91
+#define GPO_SDIO1_PAD_CDATA_OUT_BIT6		92
+#define GPO_SDIO1_PAD_CDATA_OUT_BIT7		93
+#define GPO_SDIO1_PAD_RST_N			94
+#define GPO_SPDIF_TX_SDOUT			95
+#define GPO_SPDIF_TX_SDOUT_OEN			96
+#define GPO_SPI0_PAD_OE_N			97
+#define GPO_SPI0_PAD_SCK_OUT			98
+#define GPO_SPI0_PAD_SS_0_N			99
+#define GPO_SPI0_PAD_SS_1_N			100
+#define GPO_SPI0_PAD_TXD			101
+#define GPO_SPI1_PAD_OE_N			102
+#define GPO_SPI1_PAD_SCK_OUT			103
+#define GPO_SPI1_PAD_SS_0_N			104
+#define GPO_SPI1_PAD_SS_1_N			105
+#define GPO_SPI1_PAD_TXD			106
+#define GPO_SPI2_PAD_OE_N			107
+#define GPO_SPI2_PAD_SCK_OUT			108
+#define GPO_SPI2_PAD_SS_0_N			109
+#define GPO_SPI2_PAD_SS_1_N			110
+#define GPO_SPI2_PAD_TXD			111
+#define GPO_SPI2AHB_PAD_OE_N_BIT0		112
+#define GPO_SPI2AHB_PAD_OE_N_BIT1		113
+#define GPO_SPI2AHB_PAD_OE_N_BIT2		114
+#define GPO_SPI2AHB_PAD_OE_N_BIT3		115
+#define GPO_SPI2AHB_PAD_TXD_BIT0		116
+#define GPO_SPI2AHB_PAD_TXD_BIT1		117
+#define GPO_SPI2AHB_PAD_TXD_BIT2		118
+#define GPO_SPI2AHB_PAD_TXD_BIT3		119
+#define GPO_SPI3_PAD_OE_N			120
+#define GPO_SPI3_PAD_SCK_OUT			121
+#define GPO_SPI3_PAD_SS_0_N			122
+#define GPO_SPI3_PAD_SS_1_N			123
+#define GPO_SPI3_PAD_TXD			124
+#define GPO_UART0_PAD_DTRN			125
+#define GPO_UART0_PAD_RTSN			126
+#define GPO_UART0_PAD_SOUT			127
+#define GPO_UART1_PAD_SOUT			128
+#define GPO_UART2_PAD_DTR_N			129
+#define GPO_UART2_PAD_RTS_N			130
+#define GPO_UART2_PAD_SOUT			131
+#define GPO_UART3_PAD_SOUT			132
+#define GPO_USB_DRV_BUS				133
+
+#define GPI_CPU_JTAG_TCK			0
+#define GPI_CPU_JTAG_TDI			1
+#define GPI_CPU_JTAG_TMS			2
+#define GPI_CPU_JTAG_TRST			3
+#define GPI_DMIC_SDIN_BIT0			4
+#define GPI_DMIC_SDIN_BIT1			5
+#define GPI_DSP_JTCK_PAD			6
+#define GPI_DSP_JTDI_PAD			7
+#define GPI_DSP_JTMS_PAD			8
+#define GPI_DSP_TRST_PAD			9
+#define GPI_I2C0_PAD_SCK_IN			10
+#define GPI_I2C0_PAD_SDA_IN			11
+#define GPI_I2C1_PAD_SCK_IN			12
+#define GPI_I2C1_PAD_SDA_IN			13
+#define GPI_I2C2_PAD_SCK_IN			14
+#define GPI_I2C2_PAD_SDA_IN			15
+#define GPI_I2C3_PAD_SCK_IN			16
+#define GPI_I2C3_PAD_SDA_IN			17
+#define GPI_I2SRX_BCLK_IN			18
+#define GPI_I2SRX_LRCK_IN			19
+#define GPI_I2SRX_SDIN_BIT0			20
+#define GPI_I2SRX_SDIN_BIT1			21
+#define GPI_I2SRX_SDIN_BIT2			22
+#define GPI_I2STX_BCLK_IN			23
+#define GPI_I2STX_LRCK_IN			24
+#define GPI_SDIO0_PAD_CARD_DETECT_N		25
+#define GPI_SDIO0_PAD_CARD_WRITE_PRT		26
+#define GPI_SDIO0_PAD_CCMD_IN			27
+#define GPI_SDIO0_PAD_CDATA_IN_BIT0		28
+#define GPI_SDIO0_PAD_CDATA_IN_BIT1		29
+#define GPI_SDIO0_PAD_CDATA_IN_BIT2		30
+#define GPI_SDIO0_PAD_CDATA_IN_BIT3		31
+#define GPI_SDIO0_PAD_CDATA_IN_BIT4		32
+#define GPI_SDIO0_PAD_CDATA_IN_BIT5		33
+#define GPI_SDIO0_PAD_CDATA_IN_BIT6		34
+#define GPI_SDIO0_PAD_CDATA_IN_BIT7		35
+#define GPI_SDIO1_PAD_CARD_DETECT_N		36
+#define GPI_SDIO1_PAD_CARD_WRITE_PRT		37
+#define GPI_SDIO1_PAD_CCMD_IN			38
+#define GPI_SDIO1_PAD_CDATA_IN_BIT0		39
+#define GPI_SDIO1_PAD_CDATA_IN_BIT1		40
+#define GPI_SDIO1_PAD_CDATA_IN_BIT2		41
+#define GPI_SDIO1_PAD_CDATA_IN_BIT3		42
+#define GPI_SDIO1_PAD_CDATA_IN_BIT4		43
+#define GPI_SDIO1_PAD_CDATA_IN_BIT5		44
+#define GPI_SDIO1_PAD_CDATA_IN_BIT6		45
+#define GPI_SDIO1_PAD_CDATA_IN_BIT7		46
+#define GPI_SPDIF_RX_SDIN			47
+#define GPI_SPI0_PAD_RXD			48
+#define GPI_SPI0_PAD_SS_IN_N			49
+#define GPI_SPI1_PAD_RXD			50
+#define GPI_SPI1_PAD_SS_IN_N			51
+#define GPI_SPI2_PAD_RXD			52
+#define GPI_SPI2_PAD_SS_IN_N			53
+#define GPI_SPI2AHB_PAD_RXD_BIT0		54
+#define GPI_SPI2AHB_PAD_RXD_BIT1		55
+#define GPI_SPI2AHB_PAD_RXD_BIT2		56
+#define GPI_SPI2AHB_PAD_RXD_BIT3		57
+#define GPI_SPI2AHB_PAD_SS_N			58
+#define GPI_SPI2AHB_SLV_SCLKIN			59
+#define GPI_SPI3_PAD_RXD			60
+#define GPI_SPI3_PAD_SS_IN_N			61
+#define GPI_UART0_PAD_CTSN			62
+#define GPI_UART0_PAD_DCDN			63
+#define GPI_UART0_PAD_DSRN			64
+#define GPI_UART0_PAD_RIN			65
+#define GPI_UART0_PAD_SIN			66
+#define GPI_UART1_PAD_SIN			67
+#define GPI_UART2_PAD_CTS_N			68
+#define GPI_UART2_PAD_DCD_N			69
+#define GPI_UART2_PAD_DSR_N			70
+#define GPI_UART2_PAD_RI_N			71
+#define GPI_UART2_PAD_SIN			72
+#define GPI_UART3_PAD_SIN			73
+#define GPI_USB_OVER_CURRENT			74
+
+#define GPI_NONE				0xff
+
+#endif
-- 
2.33.1


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 143+ messages in thread

* [PATCH v2 11/16] dt-bindings: pinctrl: Add StarFive JH7100 bindings
  2021-10-21 17:42 ` Emil Renner Berthing
@ 2021-10-21 17:42   ` Emil Renner Berthing
  -1 siblings, 0 replies; 143+ messages in thread
From: Emil Renner Berthing @ 2021-10-21 17:42 UTC (permalink / raw)
  To: linux-riscv, devicetree, linux-clk, linux-gpio, linux-serial
  Cc: Emil Renner Berthing, Palmer Dabbelt, Paul Walmsley, Rob Herring,
	Michael Turquette, Stephen Boyd, Thomas Gleixner, Marc Zyngier,
	Philipp Zabel, Linus Walleij, Greg Kroah-Hartman, Daniel Lezcano,
	Andy Shevchenko, Jiri Slaby, Maximilian Luz, Sagar Kadam,
	Drew Fustini, Geert Uytterhoeven, Michael Zhu, Fu Wei,
	Anup Patel, Atish Patra, Matteo Croce, linux-kernel

Add bindings for the StarFive JH7100 GPIO/pin controller.

Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
---
 .../pinctrl/starfive,jh7100-pinctrl.yaml      | 274 ++++++++++++++++++
 1 file changed, 274 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/pinctrl/starfive,jh7100-pinctrl.yaml

diff --git a/Documentation/devicetree/bindings/pinctrl/starfive,jh7100-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/starfive,jh7100-pinctrl.yaml
new file mode 100644
index 000000000000..342ecd91a3b0
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/starfive,jh7100-pinctrl.yaml
@@ -0,0 +1,274 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pinctrl/starfive,jh7100-pinctrl.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: StarFive JH7100 Pin Controller Device Tree Bindings
+
+maintainers:
+  - Emil Renner Berthing <kernel@esmil.dk>
+  - Drew Fustini <drew@beagleboard.org>
+
+properties:
+  compatible:
+    const: starfive,jh7100-pinctrl
+
+  reg:
+    minItems: 2
+    maxItems: 2
+
+  reg-names:
+    items:
+      - const: "gpio"
+      - const: "padctl"
+
+  clocks:
+    maxItems: 1
+
+  resets:
+    maxItems: 1
+
+  gpio-controller: true
+
+  "#gpio-cells":
+    const: 2
+    description: |
+      Number of cells in GPIO specifier. Since the generic GPIO
+      binding is used, the amount of cells must be specified as 2.
+
+  interrupts:
+    maxItems: 1
+    description: The GPIO parent interrupt.
+
+  interrupt-controller: true
+
+  "#interrupt-cells":
+    const: 2
+
+  starfive,signal-group:
+    description: |
+      The SoC has a global setting selecting one of 7 different pinmux
+      configurations of the pads named GPIO[0:63] and FUNC_SHARE[0:141]. After
+      this global setting is chosen only the 64 "GPIO" pins can be further
+      muxed by configuring them to be controlled by certain peripherals rather
+      than software.
+      Note that in configuration 0 none of GPIOs are routed to pads, and only
+      in configuration 1 are the GPIOs routed to the pads named GPIO[0:63].
+      If this property is not set it defaults to the configuration already
+      chosen by the earlier boot stages.
+    $ref: /schemas/types.yaml#/definitions/uint32
+    enum: [0, 1, 2, 3, 4, 5, 6]
+
+required:
+  - compatible
+  - reg
+  - reg-names
+  - clocks
+  - gpio-controller
+  - "#gpio-cells"
+  - interrupts
+  - interrupt-controller
+  - "#interrupt-cells"
+
+patternProperties:
+  '-[0-9]*$':
+    type: object
+    patternProperties:
+      '-pins*$':
+        type: object
+        description: |
+          A pinctrl node should contain at least one subnode representing the
+          pinctrl groups available on the machine. Each subnode will list the
+          pins it needs, and how they should be configured, with regard to
+          muxer configuration, bias, input enable/disable, input schmitt
+          trigger enable/disable, slew-rate and drive strength.
+        $ref: "/schemas/pinctrl/pincfg-node.yaml"
+
+        properties:
+          pins:
+            description: |
+              The list of pin identifiers that properties in the node apply to.
+              This should be set using either the PAD_GPIO or PAD_FUNC_SHARE
+              macro. Either this or "pinmux" has to be specified.
+
+          pinmux:
+            description: |
+              The list of GPIO identifiers and their mux settings that
+              properties in the node apply to. This should be set using the
+              GPIOMUX macro. Either this or "pins" has to be specified.
+
+          bias-disable: true
+
+          bias-pull-up:
+            type: boolean
+
+          bias-pull-down:
+            type: boolean
+
+          drive-strength:
+            enum: [ 14, 21, 28, 35, 42, 49, 56, 63 ]
+
+          input-enable: true
+
+          input-disable: true
+
+          input-schmitt-enable: true
+
+          input-schmitt-disable: true
+
+          slew-rate:
+            maximum: 7
+
+          starfive,strong-pull-up:
+            description: enable strong pull-up.
+            type: boolean
+
+        additionalProperties: false
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/starfive-jh7100.h>
+    #include <dt-bindings/reset/starfive-jh7100.h>
+    #include <dt-bindings/pinctrl/pinctrl-starfive.h>
+
+    soc {
+        #address-cells = <2>;
+        #size-cells = <2>;
+
+        gpio: pinctrl@11910000 {
+            compatible = "starfive,jh7100-pinctrl";
+            reg = <0x0 0x11910000 0x0 0x10000>,
+                  <0x0 0x11858000 0x0 0x1000>;
+            reg-names = "gpio", "padctl";
+            clocks = <&clkgen JH7100_CLK_GPIO_APB>;
+            resets = <&clkgen JH7100_RSTN_GPIO_APB>;
+            interrupts = <32>;
+            gpio-controller;
+            #gpio-cells = <2>;
+            interrupt-controller;
+            #interrupt-cells = <2>;
+            starfive,signal-group = <6>;
+
+            gmac_pins_default: gmac-0 {
+                gtxclk-pins {
+                    pins = <PAD_FUNC_SHARE(115)>;
+                    bias-pull-up;
+                    drive-strength = <35>;
+                    input-enable;
+                    input-schmitt-enable;
+                    slew-rate = <0>;
+                };
+                miitxclk-pins {
+                    pins = <PAD_FUNC_SHARE(116)>;
+                    bias-pull-up;
+                    drive-strength = <14>;
+                    input-enable;
+                    input-schmitt-disable;
+                    slew-rate = <0>;
+                };
+                tx-pins {
+                    pins = <PAD_FUNC_SHARE(117)>,
+                           <PAD_FUNC_SHARE(119)>,
+                           <PAD_FUNC_SHARE(120)>,
+                           <PAD_FUNC_SHARE(121)>,
+                           <PAD_FUNC_SHARE(122)>,
+                           <PAD_FUNC_SHARE(123)>,
+                           <PAD_FUNC_SHARE(124)>,
+                           <PAD_FUNC_SHARE(125)>,
+                           <PAD_FUNC_SHARE(126)>;
+                    bias-disable;
+                    drive-strength = <35>;
+                    input-disable;
+                    input-schmitt-disable;
+                    slew-rate = <0>;
+                };
+                rxclk-pins {
+                    pins = <PAD_FUNC_SHARE(127)>;
+                    bias-pull-up;
+                    drive-strength = <14>;
+                    input-enable;
+                    input-schmitt-disable;
+                    slew-rate = <6>;
+                };
+                rxer-pins {
+                    pins = <PAD_FUNC_SHARE(129)>;
+                    bias-pull-up;
+                    drive-strength = <14>;
+                    input-enable;
+                    input-schmitt-disable;
+                    slew-rate = <0>;
+                };
+                rx-pins {
+                    pins = <PAD_FUNC_SHARE(128)>,
+                           <PAD_FUNC_SHARE(130)>,
+                           <PAD_FUNC_SHARE(131)>,
+                           <PAD_FUNC_SHARE(132)>,
+                           <PAD_FUNC_SHARE(133)>,
+                           <PAD_FUNC_SHARE(134)>,
+                           <PAD_FUNC_SHARE(135)>,
+                           <PAD_FUNC_SHARE(136)>,
+                           <PAD_FUNC_SHARE(137)>,
+                           <PAD_FUNC_SHARE(138)>,
+                           <PAD_FUNC_SHARE(139)>,
+                           <PAD_FUNC_SHARE(140)>,
+                           <PAD_FUNC_SHARE(141)>;
+                    bias-pull-up;
+                    drive-strength = <14>;
+                    input-enable;
+                    input-schmitt-enable;
+                    slew-rate = <0>;
+                };
+            };
+
+            i2c0_pins_default: i2c0-0 {
+                i2c-pins {
+                    pinmux = <GPIOMUX(62, GPO_LOW,
+                              GPO_I2C0_PAD_SCK_OEN,
+                              GPI_I2C0_PAD_SCK_IN)>,
+                             <GPIOMUX(61, GPO_LOW,
+                              GPO_I2C0_PAD_SDA_OEN,
+                              GPI_I2C0_PAD_SDA_IN)>;
+                    bias-disable; /* external pull-up */
+                    input-enable;
+                    input-schmitt-enable;
+                };
+            };
+
+            uart3_pins_default: uart3-0 {
+                rx-pin {
+                    pinmux = <GPIOMUX(13, GPO_LOW, GPO_DISABLE,
+                              GPI_UART3_PAD_SIN)>;
+                    bias-pull-up;
+                    input-enable;
+                    input-schmitt-enable;
+                };
+                tx-pin {
+                    pinmux = <GPIOMUX(14, GPO_UART3_PAD_SOUT,
+                              GPO_ENABLE, GPI_NONE)>;
+                    bias-disable;
+                    input-disable;
+                    input-schmitt-disable;
+                };
+            };
+        };
+
+        gmac {
+            pinctrl-0 = <&gmac_pins_default>;
+            pinctrl-names = "default";
+        };
+
+        i2c0 {
+            pinctrl-0 = <&i2c0_pins_default>;
+            pinctrl-names = "default";
+        };
+
+        uart3 {
+            pinctrl-0 = <&uart3_pins_default>;
+            pinctrl-names = "default";
+        };
+    };
+
+...
-- 
2.33.1


^ permalink raw reply related	[flat|nested] 143+ messages in thread

* [PATCH v2 11/16] dt-bindings: pinctrl: Add StarFive JH7100 bindings
@ 2021-10-21 17:42   ` Emil Renner Berthing
  0 siblings, 0 replies; 143+ messages in thread
From: Emil Renner Berthing @ 2021-10-21 17:42 UTC (permalink / raw)
  To: linux-riscv, devicetree, linux-clk, linux-gpio, linux-serial
  Cc: Emil Renner Berthing, Palmer Dabbelt, Paul Walmsley, Rob Herring,
	Michael Turquette, Stephen Boyd, Thomas Gleixner, Marc Zyngier,
	Philipp Zabel, Linus Walleij, Greg Kroah-Hartman, Daniel Lezcano,
	Andy Shevchenko, Jiri Slaby, Maximilian Luz, Sagar Kadam,
	Drew Fustini, Geert Uytterhoeven, Michael Zhu, Fu Wei,
	Anup Patel, Atish Patra, Matteo Croce, linux-kernel

Add bindings for the StarFive JH7100 GPIO/pin controller.

Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
---
 .../pinctrl/starfive,jh7100-pinctrl.yaml      | 274 ++++++++++++++++++
 1 file changed, 274 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/pinctrl/starfive,jh7100-pinctrl.yaml

diff --git a/Documentation/devicetree/bindings/pinctrl/starfive,jh7100-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/starfive,jh7100-pinctrl.yaml
new file mode 100644
index 000000000000..342ecd91a3b0
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/starfive,jh7100-pinctrl.yaml
@@ -0,0 +1,274 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pinctrl/starfive,jh7100-pinctrl.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: StarFive JH7100 Pin Controller Device Tree Bindings
+
+maintainers:
+  - Emil Renner Berthing <kernel@esmil.dk>
+  - Drew Fustini <drew@beagleboard.org>
+
+properties:
+  compatible:
+    const: starfive,jh7100-pinctrl
+
+  reg:
+    minItems: 2
+    maxItems: 2
+
+  reg-names:
+    items:
+      - const: "gpio"
+      - const: "padctl"
+
+  clocks:
+    maxItems: 1
+
+  resets:
+    maxItems: 1
+
+  gpio-controller: true
+
+  "#gpio-cells":
+    const: 2
+    description: |
+      Number of cells in GPIO specifier. Since the generic GPIO
+      binding is used, the amount of cells must be specified as 2.
+
+  interrupts:
+    maxItems: 1
+    description: The GPIO parent interrupt.
+
+  interrupt-controller: true
+
+  "#interrupt-cells":
+    const: 2
+
+  starfive,signal-group:
+    description: |
+      The SoC has a global setting selecting one of 7 different pinmux
+      configurations of the pads named GPIO[0:63] and FUNC_SHARE[0:141]. After
+      this global setting is chosen only the 64 "GPIO" pins can be further
+      muxed by configuring them to be controlled by certain peripherals rather
+      than software.
+      Note that in configuration 0 none of GPIOs are routed to pads, and only
+      in configuration 1 are the GPIOs routed to the pads named GPIO[0:63].
+      If this property is not set it defaults to the configuration already
+      chosen by the earlier boot stages.
+    $ref: /schemas/types.yaml#/definitions/uint32
+    enum: [0, 1, 2, 3, 4, 5, 6]
+
+required:
+  - compatible
+  - reg
+  - reg-names
+  - clocks
+  - gpio-controller
+  - "#gpio-cells"
+  - interrupts
+  - interrupt-controller
+  - "#interrupt-cells"
+
+patternProperties:
+  '-[0-9]*$':
+    type: object
+    patternProperties:
+      '-pins*$':
+        type: object
+        description: |
+          A pinctrl node should contain at least one subnode representing the
+          pinctrl groups available on the machine. Each subnode will list the
+          pins it needs, and how they should be configured, with regard to
+          muxer configuration, bias, input enable/disable, input schmitt
+          trigger enable/disable, slew-rate and drive strength.
+        $ref: "/schemas/pinctrl/pincfg-node.yaml"
+
+        properties:
+          pins:
+            description: |
+              The list of pin identifiers that properties in the node apply to.
+              This should be set using either the PAD_GPIO or PAD_FUNC_SHARE
+              macro. Either this or "pinmux" has to be specified.
+
+          pinmux:
+            description: |
+              The list of GPIO identifiers and their mux settings that
+              properties in the node apply to. This should be set using the
+              GPIOMUX macro. Either this or "pins" has to be specified.
+
+          bias-disable: true
+
+          bias-pull-up:
+            type: boolean
+
+          bias-pull-down:
+            type: boolean
+
+          drive-strength:
+            enum: [ 14, 21, 28, 35, 42, 49, 56, 63 ]
+
+          input-enable: true
+
+          input-disable: true
+
+          input-schmitt-enable: true
+
+          input-schmitt-disable: true
+
+          slew-rate:
+            maximum: 7
+
+          starfive,strong-pull-up:
+            description: enable strong pull-up.
+            type: boolean
+
+        additionalProperties: false
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/starfive-jh7100.h>
+    #include <dt-bindings/reset/starfive-jh7100.h>
+    #include <dt-bindings/pinctrl/pinctrl-starfive.h>
+
+    soc {
+        #address-cells = <2>;
+        #size-cells = <2>;
+
+        gpio: pinctrl@11910000 {
+            compatible = "starfive,jh7100-pinctrl";
+            reg = <0x0 0x11910000 0x0 0x10000>,
+                  <0x0 0x11858000 0x0 0x1000>;
+            reg-names = "gpio", "padctl";
+            clocks = <&clkgen JH7100_CLK_GPIO_APB>;
+            resets = <&clkgen JH7100_RSTN_GPIO_APB>;
+            interrupts = <32>;
+            gpio-controller;
+            #gpio-cells = <2>;
+            interrupt-controller;
+            #interrupt-cells = <2>;
+            starfive,signal-group = <6>;
+
+            gmac_pins_default: gmac-0 {
+                gtxclk-pins {
+                    pins = <PAD_FUNC_SHARE(115)>;
+                    bias-pull-up;
+                    drive-strength = <35>;
+                    input-enable;
+                    input-schmitt-enable;
+                    slew-rate = <0>;
+                };
+                miitxclk-pins {
+                    pins = <PAD_FUNC_SHARE(116)>;
+                    bias-pull-up;
+                    drive-strength = <14>;
+                    input-enable;
+                    input-schmitt-disable;
+                    slew-rate = <0>;
+                };
+                tx-pins {
+                    pins = <PAD_FUNC_SHARE(117)>,
+                           <PAD_FUNC_SHARE(119)>,
+                           <PAD_FUNC_SHARE(120)>,
+                           <PAD_FUNC_SHARE(121)>,
+                           <PAD_FUNC_SHARE(122)>,
+                           <PAD_FUNC_SHARE(123)>,
+                           <PAD_FUNC_SHARE(124)>,
+                           <PAD_FUNC_SHARE(125)>,
+                           <PAD_FUNC_SHARE(126)>;
+                    bias-disable;
+                    drive-strength = <35>;
+                    input-disable;
+                    input-schmitt-disable;
+                    slew-rate = <0>;
+                };
+                rxclk-pins {
+                    pins = <PAD_FUNC_SHARE(127)>;
+                    bias-pull-up;
+                    drive-strength = <14>;
+                    input-enable;
+                    input-schmitt-disable;
+                    slew-rate = <6>;
+                };
+                rxer-pins {
+                    pins = <PAD_FUNC_SHARE(129)>;
+                    bias-pull-up;
+                    drive-strength = <14>;
+                    input-enable;
+                    input-schmitt-disable;
+                    slew-rate = <0>;
+                };
+                rx-pins {
+                    pins = <PAD_FUNC_SHARE(128)>,
+                           <PAD_FUNC_SHARE(130)>,
+                           <PAD_FUNC_SHARE(131)>,
+                           <PAD_FUNC_SHARE(132)>,
+                           <PAD_FUNC_SHARE(133)>,
+                           <PAD_FUNC_SHARE(134)>,
+                           <PAD_FUNC_SHARE(135)>,
+                           <PAD_FUNC_SHARE(136)>,
+                           <PAD_FUNC_SHARE(137)>,
+                           <PAD_FUNC_SHARE(138)>,
+                           <PAD_FUNC_SHARE(139)>,
+                           <PAD_FUNC_SHARE(140)>,
+                           <PAD_FUNC_SHARE(141)>;
+                    bias-pull-up;
+                    drive-strength = <14>;
+                    input-enable;
+                    input-schmitt-enable;
+                    slew-rate = <0>;
+                };
+            };
+
+            i2c0_pins_default: i2c0-0 {
+                i2c-pins {
+                    pinmux = <GPIOMUX(62, GPO_LOW,
+                              GPO_I2C0_PAD_SCK_OEN,
+                              GPI_I2C0_PAD_SCK_IN)>,
+                             <GPIOMUX(61, GPO_LOW,
+                              GPO_I2C0_PAD_SDA_OEN,
+                              GPI_I2C0_PAD_SDA_IN)>;
+                    bias-disable; /* external pull-up */
+                    input-enable;
+                    input-schmitt-enable;
+                };
+            };
+
+            uart3_pins_default: uart3-0 {
+                rx-pin {
+                    pinmux = <GPIOMUX(13, GPO_LOW, GPO_DISABLE,
+                              GPI_UART3_PAD_SIN)>;
+                    bias-pull-up;
+                    input-enable;
+                    input-schmitt-enable;
+                };
+                tx-pin {
+                    pinmux = <GPIOMUX(14, GPO_UART3_PAD_SOUT,
+                              GPO_ENABLE, GPI_NONE)>;
+                    bias-disable;
+                    input-disable;
+                    input-schmitt-disable;
+                };
+            };
+        };
+
+        gmac {
+            pinctrl-0 = <&gmac_pins_default>;
+            pinctrl-names = "default";
+        };
+
+        i2c0 {
+            pinctrl-0 = <&i2c0_pins_default>;
+            pinctrl-names = "default";
+        };
+
+        uart3 {
+            pinctrl-0 = <&uart3_pins_default>;
+            pinctrl-names = "default";
+        };
+    };
+
+...
-- 
2.33.1


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 143+ messages in thread

* [PATCH v2 12/16] pinctrl: starfive: Add pinctrl driver for StarFive SoCs
  2021-10-21 17:42 ` Emil Renner Berthing
@ 2021-10-21 17:42   ` Emil Renner Berthing
  -1 siblings, 0 replies; 143+ messages in thread
From: Emil Renner Berthing @ 2021-10-21 17:42 UTC (permalink / raw)
  To: linux-riscv, devicetree, linux-clk, linux-gpio, linux-serial
  Cc: Emil Renner Berthing, Palmer Dabbelt, Paul Walmsley, Rob Herring,
	Michael Turquette, Stephen Boyd, Thomas Gleixner, Marc Zyngier,
	Philipp Zabel, Linus Walleij, Greg Kroah-Hartman, Daniel Lezcano,
	Andy Shevchenko, Jiri Slaby, Maximilian Luz, Sagar Kadam,
	Drew Fustini, Geert Uytterhoeven, Michael Zhu, Fu Wei,
	Anup Patel, Atish Patra, Matteo Croce, linux-kernel, Huan Feng

Add a combined pinctrl and GPIO driver for the StarFive JH7100 SoC.

For each "GPIO" there are two registers for configuring the output and
output enable signals which may come from other peripherals. Among these
are two special signals that are constant 0 and constant 1 respectively.
Controlling the GPIOs from software is done by choosing one of these
signals. In other words the same registers are used for both pinmuxing
and controlling the GPIOs, which makes it easier to combine the pinctrl
and GPIO driver in one.

I wrote the pinconf and pinmux parts, but the GPIO part of the code is
based on the GPIO driver in the vendor tree written by Huan Feng with
cleanups and fixes by Drew and me.

Datasheet: https://github.com/starfive-tech/JH7100_Docs/blob/main/JH7100%20Data%20Sheet%20V01.01.04-EN%20(4-21-2021).pdf
Co-developed-by: Huan Feng <huan.feng@starfivetech.com>
Signed-off-by: Huan Feng <huan.feng@starfivetech.com>
Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
Co-developed-by: Drew Fustini <drew@beagleboard.org>
Signed-off-by: Drew Fustini <drew@beagleboard.org>
---
 MAINTAINERS                        |    8 +
 drivers/pinctrl/Kconfig            |   16 +
 drivers/pinctrl/Makefile           |    1 +
 drivers/pinctrl/pinctrl-starfive.c | 1387 ++++++++++++++++++++++++++++
 4 files changed, 1412 insertions(+)
 create mode 100644 drivers/pinctrl/pinctrl-starfive.c

diff --git a/MAINTAINERS b/MAINTAINERS
index b3f3a29fc91f..1f122f93a5a5 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -17855,6 +17855,14 @@ F:	Documentation/devicetree/bindings/clock/starfive,jh7100-clkgen.yaml
 F:	drivers/clk/starfive/clk-starfive-jh7100.c
 F:	include/dt-bindings/clock/starfive-jh7100.h
 
+STARFIVE JH7100 PINCTRL DRIVER
+M:	Emil Renner Berthing <kernel@esmil.dk>
+L:	linux-gpio@vger.kernel.org
+S:	Maintained
+F:	Documentation/devicetree/bindings/pinctrl/starfive,jh7100-pinctrl.yaml
+F:	drivers/pinctrl/pinctrl-starfive.c
+F:	include/dt-bindings/pinctrl/pinctrl-starfive.h
+
 STARFIVE JH7100 RESET CONTROLLER DRIVER
 M:	Emil Renner Berthing <kernel@esmil.dk>
 S:	Maintained
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index 31921108e456..98caa94acf9e 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -265,6 +265,22 @@ config PINCTRL_ST
 	select PINCONF
 	select GPIOLIB_IRQCHIP
 
+config PINCTRL_STARFIVE
+	tristate "Pinctrl and GPIO driver for the StarFive JH7100 SoC"
+	depends on SOC_STARFIVE || COMPILE_TEST
+	default SOC_STARFIVE
+	select GENERIC_PINCTRL_GROUPS
+	select GENERIC_PINMUX_FUNCTIONS
+	select GENERIC_PINCONF
+	select GPIOLIB
+	select GPIOLIB_IRQCHIP
+	select OF_GPIO
+	help
+	  Say yes here to support pin control on the StarFive JH7100 SoC.
+	  This also provides an interface to the GPIO pins not used by other
+	  peripherals supporting inputs, outputs, configuring pull-up/pull-down
+	  and interrupts on input changes.
+
 config PINCTRL_STMFX
 	tristate "STMicroelectronics STMFX GPIO expander pinctrl driver"
 	depends on I2C
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index 200073bcc2c1..9c258047f11c 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -38,6 +38,7 @@ obj-$(CONFIG_PINCTRL_LANTIQ)	+= pinctrl-lantiq.o
 obj-$(CONFIG_PINCTRL_LPC18XX)	+= pinctrl-lpc18xx.o
 obj-$(CONFIG_PINCTRL_TB10X)	+= pinctrl-tb10x.o
 obj-$(CONFIG_PINCTRL_ST) 	+= pinctrl-st.o
+obj-$(CONFIG_PINCTRL_STARFIVE)	+= pinctrl-starfive.o
 obj-$(CONFIG_PINCTRL_STMFX) 	+= pinctrl-stmfx.o
 obj-$(CONFIG_PINCTRL_ZYNQ)	+= pinctrl-zynq.o
 obj-$(CONFIG_PINCTRL_ZYNQMP)	+= pinctrl-zynqmp.o
diff --git a/drivers/pinctrl/pinctrl-starfive.c b/drivers/pinctrl/pinctrl-starfive.c
new file mode 100644
index 000000000000..ca99fad883e6
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-starfive.c
@@ -0,0 +1,1387 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Pinctrl / GPIO driver for StarFive JH7100 SoC
+ *
+ * Copyright (C) 2020 Shanghai StarFive Technology Co., Ltd.
+ * Copyright (C) 2021 Emil Renner Berthing <kernel@esmil.dk>
+ */
+
+#include <linux/bits.h>
+#include <linux/clk.h>
+#include <linux/gpio/driver.h>
+#include <linux/io.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+#include <linux/spinlock.h>
+
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+
+#include <dt-bindings/pinctrl/pinctrl-starfive.h>
+
+#include "core.h"
+#include "pinctrl-utils.h"
+#include "pinmux.h"
+#include "pinconf.h"
+
+#define DRIVER_NAME "pinctrl-starfive"
+
+/*
+ * Refer to Section 12. GPIO Registers in the JH7100 data sheet:
+ * https://github.com/starfive-tech/JH7100_Docs
+ */
+#define NR_GPIOS	64
+
+/*
+ * Global enable for GPIO interrupts. If bit 0 is set to 1 the GPIO interrupts
+ * are enabled. If set to 0 the GPIO interrupts are disabled.
+ */
+#define GPIOEN		0x000
+
+/*
+ * The following 32-bit registers come in pairs, but only the offset of the
+ * first register is defined. The first controls (interrupts for) GPIO 0-31 and
+ * the second GPIO 32-63.
+ */
+
+/*
+ * Interrupt Type. If set to 1 the interrupt is edge-triggered. If set to 0 the
+ * interrupt is level-triggered.
+ */
+#define GPIOIS		0x010
+
+/*
+ * Edge-Trigger Interrupt Type.  If set to 1 the interrupt gets triggered on
+ * both positive and negative edges. If set to 0 the interrupt is triggered by a
+ * single edge.
+ */
+#define GPIOIBE		0x018
+
+/*
+ * Interrupt Trigger Polarity. If set to 1 the interrupt is triggered on a
+ * rising edge (edge-triggered) or high level (level-triggered). If set to 0 the
+ * interrupt is triggered on a falling edge (edge-triggered) or low level
+ * (level-triggered).
+ */
+#define GPIOIEV		0x020
+
+/*
+ * Interrupt Mask. If set to 1 the interrupt is disabled (masked). If set to 0
+ * the interrupt is enabled (unmasked).
+ */
+#define GPIOIE		0x028
+
+/*
+ * Clear Edge-Triggered Interrupts. Write a 1 to clear the edge-triggered
+ * interrupt.
+ */
+#define GPIOIC		0x030
+
+/*
+ * Edge-Triggered Interrupt Status. A 1 means the configured edge was detected.
+ */
+#define GPIORIS		0x038
+
+/*
+ * Interrupt Status after Masking. A 1 means the configured edge or level was
+ * detected and not masked.
+ */
+#define GPIOMIS		0x040
+
+/*
+ * Data Value. Dynamically reflects the value of the GPIO pin. If 1 the pin is
+ * a digital 1 and if 0 the pin is a digital 0.
+ */
+#define GPIODIN		0x048
+
+/*
+ * From the data sheet section 12.2, there are 64 32-bit output data registers
+ * and 64 output enable registers. Output data and output enable registers for
+ * a given GPIO are contiguous. Eg. GPO0_DOUT_CFG is 0x50 and GPO0_DOEN_CFG is
+ * 0x54 while GPO1_DOUT_CFG is 0x58 and GPO1_DOEN_CFG is 0x5c.  The stride
+ * between GPIO registers is effectively 8, thus: GPOn_DOUT_CFG is 0x50 + 8n
+ * and GPOn_DOEN_CFG is 0x54 + 8n.
+ */
+#define GPON_DOUT_CFG	0x050
+#define GPON_DOEN_CFG	0x054
+
+/*
+ * From Section 12.3, there are 75 input signal configuration registers which
+ * are 4 bytes wide starting with GPI_CPU_JTAG_TCK_CFG at 0x250 and ending with
+ * GPI_USB_OVER_CURRENT_CFG 0x378
+ */
+#define GPI_CFG_OFFSET	0x250
+
+/*
+ * Pad Control Bits. There are 16 pad control bits for each pin located in 103
+ * 32-bit registers controlling PAD_GPIO[0] to PAD_GPIO[63] followed by
+ * PAD_FUNC_SHARE[0] to PAD_FUNC_SHARE[141]. Odd numbered pins use the upper 16
+ * bit of each register.
+ */
+#define PAD_SLEW_RATE_MASK		GENMASK(11, 9)
+#define PAD_SLEW_RATE_POS		9
+#define PAD_BIAS_STRONG_PULL_UP		BIT(8)
+#define PAD_INPUT_ENABLE		BIT(7)
+#define PAD_INPUT_SCHMITT_ENABLE	BIT(6)
+#define PAD_BIAS_DISABLE		BIT(5)
+#define PAD_BIAS_PULL_DOWN		BIT(4)
+#define PAD_BIAS_MASK			(PAD_BIAS_STRONG_PULL_UP | \
+					 PAD_BIAS_DISABLE | \
+					 PAD_BIAS_PULL_DOWN)
+#define PAD_DRIVE_STRENGTH_MASK		GENMASK(3, 0)
+#define PAD_DRIVE_STRENGTH_POS		0
+
+/*
+ * From Section 11, the IO_PADSHARE_SEL register can be programmed to select
+ * one of seven pre-defined multiplexed signal groups on PAD_FUNC_SHARE and
+ * PAD_GPIO pads. This is a global setting.
+ */
+#define IO_PADSHARE_SEL			0x1a0
+
+/*
+ * This just needs to be some number such that when
+ * sfp->gpio.pin_base = PAD_INVALID_GPIO then
+ * starfive_pin_to_gpio(sfp, validpin) is never a valid GPIO number.
+ * That is it should underflow and return something >= NR_GPIOS.
+ */
+#define PAD_INVALID_GPIO		0x10000
+
+/*
+ * The packed pinmux values from the device tree look like this:
+ *
+ *  | 31 - 24 | 23 - 16 | 15 - 8 |     7    |     6    |  5 - 0  |
+ *  |  dout   |  doen   |  din   | dout rev | doen rev | gpio nr |
+ *
+ * ..but the GPOn_DOUT_CFG and GPOn_DOEN_CFG registers look like this:
+ *
+ *  |      31       | 30 - 8 |   7 - 0   |
+ *  | dout/doen rev | unused | dout/doen |
+ */
+static unsigned int starfive_pinmux_to_gpio(u32 v)
+{
+	return v & (NR_GPIOS - 1);
+}
+
+static u32 starfive_pinmux_to_dout(u32 v)
+{
+	return ((v & BIT(7)) << (31 - 7)) | ((v >> 24) & GENMASK(7, 0));
+}
+
+static u32 starfive_pinmux_to_doen(u32 v)
+{
+	return ((v & BIT(6)) << (31 - 6)) | ((v >> 16) & GENMASK(7, 0));
+}
+
+static u32 starfive_pinmux_to_din(u32 v)
+{
+	return (v >> 8) & GENMASK(7, 0);
+}
+
+/*
+ * The maximum GPIO output current depends on the chosen drive strength:
+ *
+ *  DS:   0     1     2     3     4     5     6     7
+ *  mA:  14.2  21.2  28.2  35.2  42.2  49.1  56.0  62.8
+ *
+ * After rounding that is 7*DS + 14 mA
+ */
+static u32 starfive_drive_strength_to_max_mA(u16 ds)
+{
+	return 7 * ds + 14;
+}
+
+static u16 starfive_drive_strength_from_max_mA(u32 i)
+{
+	return (clamp(i, 14U, 63U) - 14) / 7;
+}
+
+struct starfive_pinctrl {
+	struct gpio_chip gc;
+	struct pinctrl_gpio_range gpios;
+	raw_spinlock_t lock;
+	void __iomem *base;
+	void __iomem *padctl;
+	struct pinctrl_dev *pctl;
+};
+
+static struct device *starfive_dev(const struct starfive_pinctrl *sfp)
+{
+	return sfp->gc.parent;
+}
+
+static unsigned int starfive_pin_to_gpio(const struct starfive_pinctrl *sfp,
+					 unsigned int pin)
+{
+	return pin - sfp->gpios.pin_base;
+}
+
+static unsigned int starfive_gpio_to_pin(const struct starfive_pinctrl *sfp,
+					 unsigned int gpio)
+{
+	return sfp->gpios.pin_base + gpio;
+}
+
+static struct starfive_pinctrl *starfive_from_gc(struct gpio_chip *gc)
+{
+	return container_of(gc, struct starfive_pinctrl, gc);
+}
+
+static struct starfive_pinctrl *starfive_from_irq_data(struct irq_data *d)
+{
+	return starfive_from_gc(irq_data_get_irq_chip_data(d));
+}
+
+static struct starfive_pinctrl *starfive_from_irq_desc(struct irq_desc *desc)
+{
+	return starfive_from_gc(irq_desc_get_handler_data(desc));
+}
+
+static const struct pinctrl_pin_desc starfive_pins[] = {
+	PINCTRL_PIN(PAD_GPIO(0), "GPIO[0]"),
+	PINCTRL_PIN(PAD_GPIO(1), "GPIO[1]"),
+	PINCTRL_PIN(PAD_GPIO(2), "GPIO[2]"),
+	PINCTRL_PIN(PAD_GPIO(3), "GPIO[3]"),
+	PINCTRL_PIN(PAD_GPIO(4), "GPIO[4]"),
+	PINCTRL_PIN(PAD_GPIO(5), "GPIO[5]"),
+	PINCTRL_PIN(PAD_GPIO(6), "GPIO[6]"),
+	PINCTRL_PIN(PAD_GPIO(7), "GPIO[7]"),
+	PINCTRL_PIN(PAD_GPIO(8), "GPIO[8]"),
+	PINCTRL_PIN(PAD_GPIO(9), "GPIO[9]"),
+	PINCTRL_PIN(PAD_GPIO(10), "GPIO[10]"),
+	PINCTRL_PIN(PAD_GPIO(11), "GPIO[11]"),
+	PINCTRL_PIN(PAD_GPIO(12), "GPIO[12]"),
+	PINCTRL_PIN(PAD_GPIO(13), "GPIO[13]"),
+	PINCTRL_PIN(PAD_GPIO(14), "GPIO[14]"),
+	PINCTRL_PIN(PAD_GPIO(15), "GPIO[15]"),
+	PINCTRL_PIN(PAD_GPIO(16), "GPIO[16]"),
+	PINCTRL_PIN(PAD_GPIO(17), "GPIO[17]"),
+	PINCTRL_PIN(PAD_GPIO(18), "GPIO[18]"),
+	PINCTRL_PIN(PAD_GPIO(19), "GPIO[19]"),
+	PINCTRL_PIN(PAD_GPIO(20), "GPIO[20]"),
+	PINCTRL_PIN(PAD_GPIO(21), "GPIO[21]"),
+	PINCTRL_PIN(PAD_GPIO(22), "GPIO[22]"),
+	PINCTRL_PIN(PAD_GPIO(23), "GPIO[23]"),
+	PINCTRL_PIN(PAD_GPIO(24), "GPIO[24]"),
+	PINCTRL_PIN(PAD_GPIO(25), "GPIO[25]"),
+	PINCTRL_PIN(PAD_GPIO(26), "GPIO[26]"),
+	PINCTRL_PIN(PAD_GPIO(27), "GPIO[27]"),
+	PINCTRL_PIN(PAD_GPIO(28), "GPIO[28]"),
+	PINCTRL_PIN(PAD_GPIO(29), "GPIO[29]"),
+	PINCTRL_PIN(PAD_GPIO(30), "GPIO[30]"),
+	PINCTRL_PIN(PAD_GPIO(31), "GPIO[31]"),
+	PINCTRL_PIN(PAD_GPIO(32), "GPIO[32]"),
+	PINCTRL_PIN(PAD_GPIO(33), "GPIO[33]"),
+	PINCTRL_PIN(PAD_GPIO(34), "GPIO[34]"),
+	PINCTRL_PIN(PAD_GPIO(35), "GPIO[35]"),
+	PINCTRL_PIN(PAD_GPIO(36), "GPIO[36]"),
+	PINCTRL_PIN(PAD_GPIO(37), "GPIO[37]"),
+	PINCTRL_PIN(PAD_GPIO(38), "GPIO[38]"),
+	PINCTRL_PIN(PAD_GPIO(39), "GPIO[39]"),
+	PINCTRL_PIN(PAD_GPIO(40), "GPIO[40]"),
+	PINCTRL_PIN(PAD_GPIO(41), "GPIO[41]"),
+	PINCTRL_PIN(PAD_GPIO(42), "GPIO[42]"),
+	PINCTRL_PIN(PAD_GPIO(43), "GPIO[43]"),
+	PINCTRL_PIN(PAD_GPIO(44), "GPIO[44]"),
+	PINCTRL_PIN(PAD_GPIO(45), "GPIO[45]"),
+	PINCTRL_PIN(PAD_GPIO(46), "GPIO[46]"),
+	PINCTRL_PIN(PAD_GPIO(47), "GPIO[47]"),
+	PINCTRL_PIN(PAD_GPIO(48), "GPIO[48]"),
+	PINCTRL_PIN(PAD_GPIO(49), "GPIO[49]"),
+	PINCTRL_PIN(PAD_GPIO(50), "GPIO[50]"),
+	PINCTRL_PIN(PAD_GPIO(51), "GPIO[51]"),
+	PINCTRL_PIN(PAD_GPIO(52), "GPIO[52]"),
+	PINCTRL_PIN(PAD_GPIO(53), "GPIO[53]"),
+	PINCTRL_PIN(PAD_GPIO(54), "GPIO[54]"),
+	PINCTRL_PIN(PAD_GPIO(55), "GPIO[55]"),
+	PINCTRL_PIN(PAD_GPIO(56), "GPIO[56]"),
+	PINCTRL_PIN(PAD_GPIO(57), "GPIO[57]"),
+	PINCTRL_PIN(PAD_GPIO(58), "GPIO[58]"),
+	PINCTRL_PIN(PAD_GPIO(59), "GPIO[59]"),
+	PINCTRL_PIN(PAD_GPIO(60), "GPIO[60]"),
+	PINCTRL_PIN(PAD_GPIO(61), "GPIO[61]"),
+	PINCTRL_PIN(PAD_GPIO(62), "GPIO[62]"),
+	PINCTRL_PIN(PAD_GPIO(63), "GPIO[63]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(0), "FUNC_SHARE[0]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(1), "FUNC_SHARE[1]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(2), "FUNC_SHARE[2]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(3), "FUNC_SHARE[3]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(4), "FUNC_SHARE[4]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(5), "FUNC_SHARE[5]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(6), "FUNC_SHARE[6]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(7), "FUNC_SHARE[7]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(8), "FUNC_SHARE[8]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(9), "FUNC_SHARE[9]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(10), "FUNC_SHARE[10]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(11), "FUNC_SHARE[11]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(12), "FUNC_SHARE[12]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(13), "FUNC_SHARE[13]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(14), "FUNC_SHARE[14]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(15), "FUNC_SHARE[15]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(16), "FUNC_SHARE[16]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(17), "FUNC_SHARE[17]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(18), "FUNC_SHARE[18]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(19), "FUNC_SHARE[19]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(20), "FUNC_SHARE[20]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(21), "FUNC_SHARE[21]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(22), "FUNC_SHARE[22]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(23), "FUNC_SHARE[23]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(24), "FUNC_SHARE[24]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(25), "FUNC_SHARE[25]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(26), "FUNC_SHARE[26]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(27), "FUNC_SHARE[27]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(28), "FUNC_SHARE[28]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(29), "FUNC_SHARE[29]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(30), "FUNC_SHARE[30]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(31), "FUNC_SHARE[31]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(32), "FUNC_SHARE[32]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(33), "FUNC_SHARE[33]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(34), "FUNC_SHARE[34]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(35), "FUNC_SHARE[35]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(36), "FUNC_SHARE[36]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(37), "FUNC_SHARE[37]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(38), "FUNC_SHARE[38]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(39), "FUNC_SHARE[39]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(40), "FUNC_SHARE[40]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(41), "FUNC_SHARE[41]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(42), "FUNC_SHARE[42]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(43), "FUNC_SHARE[43]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(44), "FUNC_SHARE[44]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(45), "FUNC_SHARE[45]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(46), "FUNC_SHARE[46]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(47), "FUNC_SHARE[47]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(48), "FUNC_SHARE[48]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(49), "FUNC_SHARE[49]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(50), "FUNC_SHARE[50]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(51), "FUNC_SHARE[51]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(52), "FUNC_SHARE[52]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(53), "FUNC_SHARE[53]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(54), "FUNC_SHARE[54]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(55), "FUNC_SHARE[55]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(56), "FUNC_SHARE[56]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(57), "FUNC_SHARE[57]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(58), "FUNC_SHARE[58]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(59), "FUNC_SHARE[59]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(60), "FUNC_SHARE[60]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(61), "FUNC_SHARE[61]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(62), "FUNC_SHARE[62]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(63), "FUNC_SHARE[63]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(64), "FUNC_SHARE[64]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(65), "FUNC_SHARE[65]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(66), "FUNC_SHARE[66]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(67), "FUNC_SHARE[67]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(68), "FUNC_SHARE[68]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(69), "FUNC_SHARE[69]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(70), "FUNC_SHARE[70]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(71), "FUNC_SHARE[71]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(72), "FUNC_SHARE[72]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(73), "FUNC_SHARE[73]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(74), "FUNC_SHARE[74]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(75), "FUNC_SHARE[75]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(76), "FUNC_SHARE[76]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(77), "FUNC_SHARE[77]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(78), "FUNC_SHARE[78]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(79), "FUNC_SHARE[79]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(80), "FUNC_SHARE[80]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(81), "FUNC_SHARE[81]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(82), "FUNC_SHARE[82]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(83), "FUNC_SHARE[83]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(84), "FUNC_SHARE[84]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(85), "FUNC_SHARE[85]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(86), "FUNC_SHARE[86]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(87), "FUNC_SHARE[87]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(88), "FUNC_SHARE[88]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(89), "FUNC_SHARE[89]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(90), "FUNC_SHARE[90]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(91), "FUNC_SHARE[91]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(92), "FUNC_SHARE[92]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(93), "FUNC_SHARE[93]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(94), "FUNC_SHARE[94]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(95), "FUNC_SHARE[95]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(96), "FUNC_SHARE[96]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(97), "FUNC_SHARE[97]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(98), "FUNC_SHARE[98]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(99), "FUNC_SHARE[99]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(100), "FUNC_SHARE[100]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(101), "FUNC_SHARE[101]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(102), "FUNC_SHARE[102]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(103), "FUNC_SHARE[103]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(104), "FUNC_SHARE[104]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(105), "FUNC_SHARE[105]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(106), "FUNC_SHARE[106]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(107), "FUNC_SHARE[107]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(108), "FUNC_SHARE[108]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(109), "FUNC_SHARE[109]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(110), "FUNC_SHARE[110]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(111), "FUNC_SHARE[111]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(112), "FUNC_SHARE[112]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(113), "FUNC_SHARE[113]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(114), "FUNC_SHARE[114]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(115), "FUNC_SHARE[115]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(116), "FUNC_SHARE[116]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(117), "FUNC_SHARE[117]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(118), "FUNC_SHARE[118]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(119), "FUNC_SHARE[119]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(120), "FUNC_SHARE[120]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(121), "FUNC_SHARE[121]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(122), "FUNC_SHARE[122]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(123), "FUNC_SHARE[123]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(124), "FUNC_SHARE[124]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(125), "FUNC_SHARE[125]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(126), "FUNC_SHARE[126]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(127), "FUNC_SHARE[127]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(128), "FUNC_SHARE[128]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(129), "FUNC_SHARE[129]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(130), "FUNC_SHARE[130]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(131), "FUNC_SHARE[131]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(132), "FUNC_SHARE[132]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(133), "FUNC_SHARE[133]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(134), "FUNC_SHARE[134]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(135), "FUNC_SHARE[135]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(136), "FUNC_SHARE[136]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(137), "FUNC_SHARE[137]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(138), "FUNC_SHARE[138]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(139), "FUNC_SHARE[139]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(140), "FUNC_SHARE[140]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(141), "FUNC_SHARE[141]"),
+};
+
+#ifdef CONFIG_DEBUG_FS
+static void starfive_pin_dbg_show(struct pinctrl_dev *pctldev,
+				  struct seq_file *s,
+				  unsigned int pin)
+{
+	struct starfive_pinctrl *sfp = pinctrl_dev_get_drvdata(pctldev);
+	unsigned int gpio = starfive_pin_to_gpio(sfp, pin);
+	void __iomem *reg;
+	u32 dout, doen;
+
+	if (gpio >= NR_GPIOS)
+		return;
+
+	reg = sfp->base + GPON_DOUT_CFG + 8 * gpio;
+	dout = readl_relaxed(reg + 0x000);
+	doen = readl_relaxed(reg + 0x004);
+
+	seq_printf(s, "dout=%u%s doen=%u%s",
+		   dout & (u32)GENMASK(7, 0), (dout & BIT(31)) ? "r" : "",
+		   doen & (u32)GENMASK(7, 0), (doen & BIT(31)) ? "r" : "");
+}
+#else
+#define starfive_pin_dbg_show NULL
+#endif
+
+static int starfive_dt_node_to_map(struct pinctrl_dev *pctldev,
+				   struct device_node *np,
+				   struct pinctrl_map **maps,
+				   unsigned int *num_maps)
+{
+	struct starfive_pinctrl *sfp = pinctrl_dev_get_drvdata(pctldev);
+	struct device *dev = starfive_dev(sfp);
+	const char **pgnames;
+	struct pinctrl_map *map;
+	struct device_node *child;
+	const char *grpname;
+	int *pins;
+	u32 *pinmux;
+	int nmaps;
+	int ngroups;
+	int ret;
+
+	nmaps = 0;
+	ngroups = 0;
+	for_each_child_of_node(np, child) {
+		int npinmux = of_property_count_u32_elems(child, "pinmux");
+		int npins   = of_property_count_u32_elems(child, "pins");
+
+		if (npinmux > 0 && npins > 0) {
+			dev_err(dev, "invalid pinctrl group %pOFn.%pOFn: %s\n",
+				np, child, "both pinmux and pins set");
+			of_node_put(child);
+			return -EINVAL;
+		}
+
+		if (npinmux > 0) {
+			nmaps += 2;
+		} else if (npins > 0) {
+			nmaps += 1;
+		} else {
+			dev_err(dev, "invalid pinctrl group %pOFn.%pOFn: %s\n",
+				np, child, "neither pinmux nor pins set");
+			of_node_put(child);
+			return -EINVAL;
+		}
+		ngroups += 1;
+	}
+
+	ret = -ENOMEM;
+	pgnames = devm_kcalloc(dev, ngroups, sizeof(*pgnames), GFP_KERNEL);
+	if (!pgnames)
+		return ret;
+
+	map = kcalloc(nmaps, sizeof(*map), GFP_KERNEL);
+	if (!map)
+		goto free_pgnames;
+
+	nmaps = 0;
+	ngroups = 0;
+	for_each_child_of_node(np, child) {
+		int npins;
+		int i;
+
+		ret = -ENOMEM;
+		grpname = devm_kasprintf(dev, GFP_KERNEL, "%s.%s", np->name, child->name);
+		if (!grpname)
+			goto put_child;
+
+		pgnames[ngroups++] = grpname;
+
+		if ((npins = of_property_count_u32_elems(child, "pinmux")) > 0) {
+			pins = devm_kcalloc(dev, npins, sizeof(*pins), GFP_KERNEL);
+			if (!pins)
+				goto free_grpname;
+
+			pinmux = devm_kcalloc(dev, npins, sizeof(*pinmux), GFP_KERNEL);
+			if (!pinmux)
+				goto free_pins;
+
+			for (i = 0; i < npins; i++) {
+				u32 v;
+
+				ret = of_property_read_u32_index(child, "pinmux", i, &v);
+				if (ret)
+					goto free_pinmux;
+				pins[i] = starfive_gpio_to_pin(sfp, starfive_pinmux_to_gpio(v));
+				pinmux[i] = v;
+			}
+
+			map[nmaps].type = PIN_MAP_TYPE_MUX_GROUP;
+			map[nmaps].data.mux.function = np->name;
+			map[nmaps].data.mux.group = grpname;
+			nmaps += 1;
+		} else if ((npins = of_property_count_u32_elems(child, "pins")) > 0) {
+			pins = devm_kcalloc(dev, npins, sizeof(*pins), GFP_KERNEL);
+			if (!pins)
+				goto free_grpname;
+
+			pinmux = NULL;
+
+			for (i = 0; i < npins; i++) {
+				u32 v;
+
+				ret = of_property_read_u32_index(child, "pins", i, &v);
+				if (ret)
+					goto free_pins;
+				pins[i] = v;
+			}
+		} else {
+			ret = -EINVAL;
+			goto free_grpname;
+		}
+
+		ret = pinctrl_generic_add_group(pctldev, grpname, pins, npins, pinmux);
+		if (ret < 0) {
+			dev_err(dev, "error adding group %pOFn.%pOFn: %d\n",
+				np, child, ret);
+			goto free_pinmux;
+		}
+
+		ret = pinconf_generic_parse_dt_config(child, pctldev,
+						      &map[nmaps].data.configs.configs,
+						      &map[nmaps].data.configs.num_configs);
+		if (ret) {
+			dev_err(dev, "invalid pinctrl group %pOFn.%pOFn: %s\n",
+				np, child, "error parsing pin config");
+			goto put_child;
+		}
+
+		/* don't create a map if there are no pinconf settings */
+		if (map[nmaps].data.configs.num_configs == 0)
+			continue;
+
+		map[nmaps].type = PIN_MAP_TYPE_CONFIGS_GROUP;
+		map[nmaps].data.configs.group_or_pin = grpname;
+		nmaps += 1;
+	}
+
+	ret = pinmux_generic_add_function(pctldev, np->name, pgnames, ngroups, NULL);
+	if (ret < 0) {
+		dev_err(dev, "error adding function %pOFn: %d\n", np, ret);
+		goto free_map;
+	}
+
+	*maps = map;
+	*num_maps = nmaps;
+	return 0;
+
+free_pinmux:
+	devm_kfree(dev, pinmux);
+free_pins:
+	devm_kfree(dev, pins);
+free_grpname:
+	devm_kfree(dev, grpname);
+put_child:
+	of_node_put(child);
+free_map:
+	pinctrl_utils_free_map(pctldev, map, nmaps);
+free_pgnames:
+	devm_kfree(dev, pgnames);
+	return ret;
+}
+
+static const struct pinctrl_ops starfive_pinctrl_ops = {
+	.get_groups_count = pinctrl_generic_get_group_count,
+	.get_group_name = pinctrl_generic_get_group_name,
+	.get_group_pins = pinctrl_generic_get_group_pins,
+	.pin_dbg_show = starfive_pin_dbg_show,
+	.dt_node_to_map = starfive_dt_node_to_map,
+	.dt_free_map = pinctrl_utils_free_map,
+};
+
+static int starfive_set_mux(struct pinctrl_dev *pctldev,
+			    unsigned int fsel, unsigned int gsel)
+{
+	struct starfive_pinctrl *sfp = pinctrl_dev_get_drvdata(pctldev);
+	struct device *dev = starfive_dev(sfp);
+	const struct group_desc *group;
+	const u32 *pinmux;
+	unsigned int i;
+
+	group = pinctrl_generic_get_group(pctldev, gsel);
+	if (!group)
+		return -EINVAL;
+
+	pinmux = group->data;
+	for (i = 0; i < group->num_pins; i++) {
+		u32 v = pinmux[i];
+		unsigned int gpio = starfive_pinmux_to_gpio(v);
+		u32 dout = starfive_pinmux_to_dout(v);
+		u32 doen = starfive_pinmux_to_doen(v);
+		u32 din = starfive_pinmux_to_din(v);
+		void __iomem *reg_dout;
+		void __iomem *reg_doen;
+		void __iomem *reg_din;
+		unsigned long flags;
+
+		dev_dbg(dev, "GPIO%u: dout=0x%x doen=0x%x din=0x%x\n",
+			gpio, dout, doen, din);
+
+		reg_dout = sfp->base + GPON_DOUT_CFG + 8 * gpio;
+		reg_doen = sfp->base + GPON_DOEN_CFG + 8 * gpio;
+		if (din != GPI_NONE)
+			reg_din = sfp->base + GPI_CFG_OFFSET + 4 * din;
+		else
+			reg_din = NULL;
+
+		raw_spin_lock_irqsave(&sfp->lock, flags);
+		writel_relaxed(dout, reg_dout);
+		writel_relaxed(doen, reg_doen);
+		if (reg_din)
+			writel_relaxed(gpio + 2, reg_din);
+		raw_spin_unlock_irqrestore(&sfp->lock, flags);
+	}
+
+	return 0;
+}
+
+static const struct pinmux_ops starfive_pinmux_ops = {
+	.get_functions_count = pinmux_generic_get_function_count,
+	.get_function_name = pinmux_generic_get_function_name,
+	.get_function_groups = pinmux_generic_get_function_groups,
+	.set_mux = starfive_set_mux,
+	.strict = true,
+};
+
+static u16 starfive_padctl_get(struct starfive_pinctrl *sfp,
+			       unsigned int pin)
+{
+	void __iomem *reg = sfp->padctl + 4 * (pin / 2);
+	int shift = 16 * (pin % 2);
+
+	return readl_relaxed(reg) >> shift;
+}
+
+static void starfive_padctl_rmw(struct starfive_pinctrl *sfp,
+				unsigned int pin,
+				u16 _mask, u16 _value)
+{
+	void __iomem *reg = sfp->padctl + 4 * (pin / 2);
+	int shift = 16 * (pin % 2);
+	u32 mask = (u32)_mask << shift;
+	u32 value = (u32)_value << shift;
+	unsigned long flags;
+
+	dev_dbg(starfive_dev(sfp),
+		"padctl_rmw(%u, 0x%03x, 0x%03x)\n", pin, _mask, _value);
+
+	raw_spin_lock_irqsave(&sfp->lock, flags);
+	value |= readl_relaxed(reg) & ~mask;
+	writel_relaxed(value, reg);
+	raw_spin_unlock_irqrestore(&sfp->lock, flags);
+}
+
+#define PIN_CONFIG_STARFIVE_STRONG_PULL_UP	(PIN_CONFIG_END + 1)
+
+static const struct pinconf_generic_params starfive_pinconf_custom_params[] = {
+	{ "starfive,strong-pull-up", PIN_CONFIG_STARFIVE_STRONG_PULL_UP, 1 },
+};
+
+#ifdef CONFIG_DEBUG_FS
+static const struct pin_config_item starfive_pinconf_custom_conf_items[] = {
+	PCONFDUMP(PIN_CONFIG_STARFIVE_STRONG_PULL_UP, "input bias strong pull-up", NULL, false),
+};
+
+static_assert(ARRAY_SIZE(starfive_pinconf_custom_conf_items) ==
+	      ARRAY_SIZE(starfive_pinconf_custom_params));
+#else
+#define starfive_pinconf_custom_conf_items NULL
+#endif
+
+static int starfive_pinconf_get(struct pinctrl_dev *pctldev,
+				unsigned int pin, unsigned long *config)
+{
+	struct starfive_pinctrl *sfp = pinctrl_dev_get_drvdata(pctldev);
+	u16 value = starfive_padctl_get(sfp, pin);
+	int param = pinconf_to_config_param(*config);
+	u32 arg;
+	bool enabled;
+
+	switch (param) {
+	case PIN_CONFIG_BIAS_DISABLE:
+		enabled = value & PAD_BIAS_DISABLE;
+		arg = 0;
+		break;
+	case PIN_CONFIG_BIAS_PULL_DOWN:
+		enabled = value & PAD_BIAS_PULL_DOWN;
+		arg = 1;
+		break;
+	case PIN_CONFIG_BIAS_PULL_UP:
+		enabled = !(value & PAD_BIAS_MASK);
+		arg = 1;
+		break;
+	case PIN_CONFIG_DRIVE_STRENGTH:
+		enabled = value & PAD_DRIVE_STRENGTH_MASK;
+		arg = starfive_drive_strength_to_max_mA(value & PAD_DRIVE_STRENGTH_MASK);
+		break;
+	case PIN_CONFIG_INPUT_ENABLE:
+		enabled = value & PAD_INPUT_ENABLE;
+		arg = enabled;
+		break;
+	case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
+		enabled = value & PAD_INPUT_SCHMITT_ENABLE;
+		arg = enabled;
+		break;
+	case PIN_CONFIG_SLEW_RATE:
+		enabled = value & PAD_SLEW_RATE_MASK;
+		arg = (value & PAD_SLEW_RATE_MASK) >> PAD_SLEW_RATE_POS;
+		break;
+	case PIN_CONFIG_STARFIVE_STRONG_PULL_UP:
+		enabled = value & PAD_BIAS_STRONG_PULL_UP;
+		arg = enabled;
+		break;
+	default:
+		return -ENOTSUPP;
+	}
+
+	*config = pinconf_to_config_packed(param, arg);
+	return enabled ? 0 : -EINVAL;
+}
+
+static int starfive_pinconf_group_get(struct pinctrl_dev *pctldev,
+				      unsigned int gsel, unsigned long *config)
+{
+	const struct group_desc *group;
+
+	group = pinctrl_generic_get_group(pctldev, gsel);
+	if (!group)
+		return -EINVAL;
+
+	return starfive_pinconf_get(pctldev, group->pins[0], config);
+}
+
+static int starfive_pinconf_group_set(struct pinctrl_dev *pctldev,
+				      unsigned int gsel,
+				      unsigned long *configs,
+				      unsigned int num_configs)
+{
+	struct starfive_pinctrl *sfp = pinctrl_dev_get_drvdata(pctldev);
+	const struct group_desc *group;
+	u16 mask, value;
+	int i;
+
+	group = pinctrl_generic_get_group(pctldev, gsel);
+	if (!group)
+		return -EINVAL;
+
+	mask = 0;
+	value = 0;
+	for (i = 0; i < num_configs; i++) {
+		int param = pinconf_to_config_param(configs[i]);
+		u32 arg = pinconf_to_config_argument(configs[i]);
+
+		switch (param) {
+		case PIN_CONFIG_BIAS_DISABLE:
+			mask |= PAD_BIAS_MASK;
+			value = (value & ~PAD_BIAS_MASK) | PAD_BIAS_DISABLE;
+			break;
+		case PIN_CONFIG_BIAS_PULL_DOWN:
+			if (arg == 0)
+				return -ENOTSUPP;
+			mask |= PAD_BIAS_MASK;
+			value = (value & ~PAD_BIAS_MASK) | PAD_BIAS_PULL_DOWN;
+			break;
+		case PIN_CONFIG_BIAS_PULL_UP:
+			if (arg == 0)
+				return -ENOTSUPP;
+			mask |= PAD_BIAS_MASK;
+			value = value & ~PAD_BIAS_MASK;
+			break;
+		case PIN_CONFIG_DRIVE_STRENGTH:
+			mask |= PAD_DRIVE_STRENGTH_MASK;
+			value = (value & ~PAD_DRIVE_STRENGTH_MASK) |
+				starfive_drive_strength_from_max_mA(arg);
+			break;
+		case PIN_CONFIG_INPUT_ENABLE:
+			mask |= PAD_INPUT_ENABLE;
+			if (arg)
+				value |= PAD_INPUT_ENABLE;
+			else
+				value &= ~PAD_INPUT_ENABLE;
+			break;
+		case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
+			mask |= PAD_INPUT_SCHMITT_ENABLE;
+			if (arg)
+				value |= PAD_INPUT_SCHMITT_ENABLE;
+			else
+				value &= ~PAD_INPUT_SCHMITT_ENABLE;
+			break;
+		case PIN_CONFIG_SLEW_RATE:
+			mask |= PAD_SLEW_RATE_MASK;
+			value = (value & ~PAD_SLEW_RATE_MASK) |
+				((arg << PAD_SLEW_RATE_POS) & PAD_SLEW_RATE_MASK);
+			break;
+		case PIN_CONFIG_STARFIVE_STRONG_PULL_UP:
+			if (arg) {
+				mask |= PAD_BIAS_MASK;
+				value = (value & ~PAD_BIAS_MASK) |
+					PAD_BIAS_STRONG_PULL_UP;
+			} else {
+				mask |= PAD_BIAS_STRONG_PULL_UP;
+				value = value & ~PAD_BIAS_STRONG_PULL_UP;
+			}
+			break;
+		default:
+			return -ENOTSUPP;
+		}
+	}
+
+	for (i = 0; i < group->num_pins; i++)
+		starfive_padctl_rmw(sfp, group->pins[i], mask, value);
+
+	return 0;
+}
+
+#ifdef CONFIG_DEBUG_FS
+static void starfive_pinconf_dbg_show(struct pinctrl_dev *pctldev,
+				      struct seq_file *s, unsigned int pin)
+{
+	struct starfive_pinctrl *sfp = pinctrl_dev_get_drvdata(pctldev);
+	u16 value = starfive_padctl_get(sfp, pin);
+
+	seq_printf(s, " (0x%03x)", value);
+}
+#else
+#define starfive_pinconf_dbg_show NULL
+#endif
+
+static const struct pinconf_ops starfive_pinconf_ops = {
+	.pin_config_get = starfive_pinconf_get,
+	.pin_config_group_get = starfive_pinconf_group_get,
+	.pin_config_group_set = starfive_pinconf_group_set,
+	.pin_config_dbg_show = starfive_pinconf_dbg_show,
+	.is_generic = true,
+};
+
+static struct pinctrl_desc starfive_desc = {
+	.name = DRIVER_NAME,
+	.pins = starfive_pins,
+	.npins = ARRAY_SIZE(starfive_pins),
+	.pctlops = &starfive_pinctrl_ops,
+	.pmxops = &starfive_pinmux_ops,
+	.confops = &starfive_pinconf_ops,
+	.owner = THIS_MODULE,
+	.num_custom_params = ARRAY_SIZE(starfive_pinconf_custom_params),
+	.custom_params = starfive_pinconf_custom_params,
+	.custom_conf_items = starfive_pinconf_custom_conf_items,
+};
+
+static int starfive_gpio_request(struct gpio_chip *gc, unsigned int gpio)
+{
+	return pinctrl_gpio_request(gc->base + gpio);
+}
+
+static void starfive_gpio_free(struct gpio_chip *gc, unsigned int gpio)
+{
+	pinctrl_gpio_free(gc->base + gpio);
+}
+
+static int starfive_gpio_get_direction(struct gpio_chip *gc, unsigned int gpio)
+{
+	struct starfive_pinctrl *sfp = starfive_from_gc(gc);
+
+	if (gpio >= NR_GPIOS)
+		return -EINVAL;
+
+	/* return GPIO_LINE_DIRECTION_OUT (0) only if doen == GPO_ENABLE (0) */
+	return readl_relaxed(sfp->base + GPON_DOEN_CFG + 8 * gpio) != GPO_ENABLE;
+}
+
+static int starfive_gpio_direction_input(struct gpio_chip *gc,
+					 unsigned int gpio)
+{
+	struct starfive_pinctrl *sfp = starfive_from_gc(gc);
+	void __iomem *doen;
+	unsigned long flags;
+
+	if (gpio >= NR_GPIOS)
+		return -EINVAL;
+
+	/* enable input and schmitt trigger */
+	starfive_padctl_rmw(sfp, starfive_gpio_to_pin(sfp, gpio),
+			    PAD_INPUT_ENABLE | PAD_INPUT_SCHMITT_ENABLE,
+			    PAD_INPUT_ENABLE | PAD_INPUT_SCHMITT_ENABLE);
+
+	doen = sfp->base + GPON_DOEN_CFG + 8 * gpio;
+	raw_spin_lock_irqsave(&sfp->lock, flags);
+	writel_relaxed(GPO_DISABLE, doen);
+	raw_spin_unlock_irqrestore(&sfp->lock, flags);
+	return 0;
+}
+
+static int starfive_gpio_direction_output(struct gpio_chip *gc,
+					  unsigned int gpio, int value)
+{
+	struct starfive_pinctrl *sfp = starfive_from_gc(gc);
+	void __iomem *dout;
+	void __iomem *doen;
+	unsigned long flags;
+
+	if (gpio >= NR_GPIOS)
+		return -EINVAL;
+
+	dout = sfp->base + GPON_DOUT_CFG + 8 * gpio;
+	doen = sfp->base + GPON_DOEN_CFG + 8 * gpio;
+	raw_spin_lock_irqsave(&sfp->lock, flags);
+	writel_relaxed(value, dout);
+	writel_relaxed(GPO_ENABLE, doen);
+	raw_spin_unlock_irqrestore(&sfp->lock, flags);
+
+	/* disable input, schmitt trigger and bias */
+	starfive_padctl_rmw(sfp, starfive_gpio_to_pin(sfp, gpio),
+			    PAD_BIAS_MASK | PAD_INPUT_ENABLE | PAD_INPUT_SCHMITT_ENABLE,
+			    PAD_BIAS_DISABLE);
+
+	return 0;
+}
+
+static int starfive_gpio_get(struct gpio_chip *gc, unsigned int gpio)
+{
+	struct starfive_pinctrl *sfp = starfive_from_gc(gc);
+	void __iomem *din;
+
+	if (gpio >= NR_GPIOS)
+		return -EINVAL;
+
+	din = sfp->base + GPIODIN + 4 * (gpio / 32);
+	return !!(readl_relaxed(din) & BIT(gpio % 32));
+}
+
+static void starfive_gpio_set(struct gpio_chip *gc, unsigned int gpio,
+			      int value)
+{
+	struct starfive_pinctrl *sfp = starfive_from_gc(gc);
+	void __iomem *dout;
+	unsigned long flags;
+
+	if (gpio >= NR_GPIOS)
+		return;
+
+	dout = sfp->base + GPON_DOUT_CFG + 8 * gpio;
+	raw_spin_lock_irqsave(&sfp->lock, flags);
+	writel_relaxed(value, dout);
+	raw_spin_unlock_irqrestore(&sfp->lock, flags);
+}
+
+static int starfive_gpio_set_config(struct gpio_chip *gc, unsigned int gpio,
+				    unsigned long config)
+{
+	struct starfive_pinctrl *sfp = starfive_from_gc(gc);
+	u32 arg = pinconf_to_config_argument(config);
+	u16 mask;
+	u16 value;
+
+	switch (pinconf_to_config_param(config)) {
+	case PIN_CONFIG_BIAS_DISABLE:
+		mask  = PAD_BIAS_MASK;
+		value = PAD_BIAS_DISABLE;
+		break;
+	case PIN_CONFIG_BIAS_PULL_DOWN:
+		if (arg == 0)
+			return -ENOTSUPP;
+		mask  = PAD_BIAS_MASK;
+		value = PAD_BIAS_PULL_DOWN;
+		break;
+	case PIN_CONFIG_BIAS_PULL_UP:
+		if (arg == 0)
+			return -ENOTSUPP;
+		mask  = PAD_BIAS_MASK;
+		value = 0;
+		break;
+	case PIN_CONFIG_DRIVE_PUSH_PULL:
+		return 0;
+	case PIN_CONFIG_INPUT_ENABLE:
+		mask  = PAD_INPUT_ENABLE;
+		value = arg ? PAD_INPUT_ENABLE : 0;
+		break;
+	case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
+		mask  = PAD_INPUT_SCHMITT_ENABLE;
+		value = arg ? PAD_INPUT_SCHMITT_ENABLE : 0;
+		break;
+	default:
+		return -ENOTSUPP;
+	};
+
+	starfive_padctl_rmw(sfp, starfive_gpio_to_pin(sfp, gpio), mask, value);
+	return 0;
+}
+
+static int starfive_gpio_add_pin_ranges(struct gpio_chip *gc)
+{
+	struct starfive_pinctrl *sfp = starfive_from_gc(gc);
+
+	sfp->gpios.name = sfp->gc.label;
+	sfp->gpios.base = sfp->gc.base;
+	/*
+	 * sfp->gpios.pin_base depends on the chosen signal group
+	 * and is set in starfive_probe()
+	 */
+	sfp->gpios.npins = NR_GPIOS;
+	sfp->gpios.gc = &sfp->gc;
+	pinctrl_add_gpio_range(sfp->pctl, &sfp->gpios);
+	return 0;
+}
+
+static void starfive_irq_ack(struct irq_data *d)
+{
+	struct starfive_pinctrl *sfp = starfive_from_irq_data(d);
+	irq_hw_number_t gpio = irqd_to_hwirq(d);
+	void __iomem *ic = sfp->base + GPIOIC + 4 * (gpio / 32);
+	u32 mask = BIT(gpio % 32);
+	unsigned long flags;
+
+	raw_spin_lock_irqsave(&sfp->lock, flags);
+	writel_relaxed(mask, ic);
+	raw_spin_unlock_irqrestore(&sfp->lock, flags);
+}
+
+static void starfive_irq_mask(struct irq_data *d)
+{
+	struct starfive_pinctrl *sfp = starfive_from_irq_data(d);
+	irq_hw_number_t gpio = irqd_to_hwirq(d);
+	void __iomem *ie = sfp->base + GPIOIE + 4 * (gpio / 32);
+	u32 mask = BIT(gpio % 32);
+	unsigned long flags;
+	u32 value;
+
+	raw_spin_lock_irqsave(&sfp->lock, flags);
+	value = readl_relaxed(ie) & ~mask;
+	writel_relaxed(value, ie);
+	raw_spin_unlock_irqrestore(&sfp->lock, flags);
+}
+
+static void starfive_irq_mask_ack(struct irq_data *d)
+{
+	struct starfive_pinctrl *sfp = starfive_from_irq_data(d);
+	irq_hw_number_t gpio = irqd_to_hwirq(d);
+	void __iomem *ie = sfp->base + GPIOIE + 4 * (gpio / 32);
+	void __iomem *ic = sfp->base + GPIOIC + 4 * (gpio / 32);
+	u32 mask = BIT(gpio % 32);
+	unsigned long flags;
+	u32 value;
+
+	raw_spin_lock_irqsave(&sfp->lock, flags);
+	value = readl_relaxed(ie) & ~mask;
+	writel_relaxed(value, ie);
+	writel_relaxed(mask, ic);
+	raw_spin_unlock_irqrestore(&sfp->lock, flags);
+}
+
+static void starfive_irq_unmask(struct irq_data *d)
+{
+	struct starfive_pinctrl *sfp = starfive_from_irq_data(d);
+	irq_hw_number_t gpio = irqd_to_hwirq(d);
+	void __iomem *ie = sfp->base + GPIOIE + 4 * (gpio / 32);
+	u32 mask = BIT(gpio % 32);
+	unsigned long flags;
+	u32 value;
+
+	raw_spin_lock_irqsave(&sfp->lock, flags);
+	value = readl_relaxed(ie) | mask;
+	writel_relaxed(value, ie);
+	raw_spin_unlock_irqrestore(&sfp->lock, flags);
+}
+
+static int starfive_irq_set_type(struct irq_data *d, unsigned int trigger)
+{
+	struct starfive_pinctrl *sfp = starfive_from_irq_data(d);
+	irq_hw_number_t gpio = irqd_to_hwirq(d);
+	void __iomem *base = sfp->base + 4 * (gpio / 32);
+	u32 mask = BIT(gpio % 32);
+	u32 irq_type, edge_both, polarity;
+	irq_flow_handler_t handler;
+	unsigned long flags;
+
+	switch (trigger) {
+	case IRQ_TYPE_EDGE_RISING:
+		irq_type  = mask; /* 1: edge triggered */
+		edge_both = 0;    /* 0: single edge */
+		polarity  = mask; /* 1: rising edge */
+		handler   = handle_edge_irq;
+		break;
+	case IRQ_TYPE_EDGE_FALLING:
+		irq_type  = mask; /* 1: edge triggered */
+		edge_both = 0;    /* 0: single edge */
+		polarity  = 0;    /* 0: falling edge */
+		handler   = handle_edge_irq;
+		break;
+	case IRQ_TYPE_EDGE_BOTH:
+		irq_type  = mask; /* 1: edge triggered */
+		edge_both = mask; /* 1: both edges */
+		polarity  = 0;    /* 0: ignored */
+		handler   = handle_edge_irq;
+		break;
+	case IRQ_TYPE_LEVEL_HIGH:
+		irq_type  = 0;    /* 0: level triggered */
+		edge_both = 0;    /* 0: ignored */
+		polarity  = mask; /* 1: high level */
+		handler   = handle_level_irq;
+		break;
+	case IRQ_TYPE_LEVEL_LOW:
+		irq_type  = 0;    /* 0: level triggered */
+		edge_both = 0;    /* 0: ignored */
+		polarity  = 0;    /* 0: low level */
+		handler   = handle_level_irq;
+		break;
+	default:
+		irq_set_handler_locked(d, handle_bad_irq);
+		return -EINVAL;
+	}
+
+	irq_set_handler_locked(d, handler);
+
+	raw_spin_lock_irqsave(&sfp->lock, flags);
+	irq_type |= readl_relaxed(base + GPIOIS) & ~mask;
+	writel_relaxed(irq_type, base + GPIOIS);
+	edge_both |= readl_relaxed(base + GPIOIBE) & ~mask;
+	writel_relaxed(edge_both, base + GPIOIBE);
+	polarity |= readl_relaxed(base + GPIOIEV) & ~mask;
+	writel_relaxed(polarity, base + GPIOIEV);
+	raw_spin_unlock_irqrestore(&sfp->lock, flags);
+	return 0;
+}
+
+static struct irq_chip starfive_irq_chip = {
+	.irq_ack = starfive_irq_ack,
+	.irq_mask = starfive_irq_mask,
+	.irq_mask_ack = starfive_irq_mask_ack,
+	.irq_unmask = starfive_irq_unmask,
+	.irq_set_type = starfive_irq_set_type,
+	.flags = IRQCHIP_SET_TYPE_MASKED,
+};
+
+static void starfive_gpio_irq_handler(struct irq_desc *desc)
+{
+	struct starfive_pinctrl *sfp = starfive_from_irq_desc(desc);
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+	unsigned long mis;
+	unsigned int pin;
+
+	chained_irq_enter(chip, desc);
+
+	mis = readl_relaxed(sfp->base + GPIOMIS + 0);
+	for_each_set_bit(pin, &mis, 32)
+		generic_handle_domain_irq(sfp->gc.irq.domain, pin);
+
+	mis = readl_relaxed(sfp->base + GPIOMIS + 4);
+	for_each_set_bit(pin, &mis, 32)
+		generic_handle_domain_irq(sfp->gc.irq.domain, pin + 32);
+
+	chained_irq_exit(chip, desc);
+}
+
+static int starfive_gpio_init_hw(struct gpio_chip *gc)
+{
+	struct starfive_pinctrl *sfp = starfive_from_gc(gc);
+
+	/* mask all GPIO interrupts */
+	writel(0, sfp->base + GPIOIE + 0);
+	writel(0, sfp->base + GPIOIE + 4);
+	/* clear edge interrupt flags */
+	writel(~0U, sfp->base + GPIOIC + 0);
+	writel(~0U, sfp->base + GPIOIC + 4);
+	/* enable GPIO interrupts */
+	writel(1, sfp->base + GPIOEN);
+	return 0;
+}
+
+static void starfive_disable_clock(void *data)
+{
+	clk_disable_unprepare(data);
+}
+
+static int starfive_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct starfive_pinctrl *sfp;
+	struct clk *clk;
+	struct reset_control *rst;
+	u32 value;
+	int ret;
+
+	sfp = devm_kzalloc(dev, sizeof(*sfp), GFP_KERNEL);
+	if (!sfp)
+		return -ENOMEM;
+
+	sfp->base = devm_platform_ioremap_resource_byname(pdev, "gpio");
+	if (IS_ERR(sfp->base))
+		return PTR_ERR(sfp->base);
+
+	sfp->padctl = devm_platform_ioremap_resource_byname(pdev, "padctl");
+	if (IS_ERR(sfp->padctl))
+		return PTR_ERR(sfp->padctl);
+
+	clk = devm_clk_get(dev, NULL);
+	if (IS_ERR(clk)) {
+		ret = PTR_ERR(clk);
+		return dev_err_probe(dev, ret, "could not get clock: %d\n", ret);
+	}
+
+	rst = devm_reset_control_get_exclusive(dev, NULL);
+	if (IS_ERR(rst)) {
+		ret = PTR_ERR(rst);
+		return dev_err_probe(dev, ret, "could not get reset: %d\n", ret);
+	}
+
+	ret = clk_prepare_enable(clk);
+	if (ret)
+		return dev_err_probe(dev, ret, "could not enable clock: %d\n", ret);
+
+	ret = devm_add_action_or_reset(dev, starfive_disable_clock, clk);
+	if (ret)
+		return ret;
+
+	ret = reset_control_deassert(rst);
+	if (ret)
+		return dev_err_probe(dev, ret, "could not deassert reset: %d\n", ret);
+
+	platform_set_drvdata(pdev, sfp);
+	sfp->gc.parent = dev;
+	raw_spin_lock_init(&sfp->lock);
+
+	ret = devm_pinctrl_register_and_init(dev, &starfive_desc, sfp, &sfp->pctl);
+	if (ret)
+		return dev_err_probe(dev, ret, "could not register pinctrl driver: %d\n", ret);
+
+	if (!device_property_read_u32(dev, "starfive,signal-group", &value)) {
+		if (value > 6) {
+			dev_err(dev, "invalid signal group %u\n", value);
+			return -EINVAL;
+		}
+		writel(value, sfp->padctl + IO_PADSHARE_SEL);
+	}
+
+	value = readl(sfp->padctl + IO_PADSHARE_SEL);
+	switch (value) {
+	case 0:
+		sfp->gpios.pin_base = PAD_INVALID_GPIO;
+		goto done;
+	case 1:
+		sfp->gpios.pin_base = PAD_GPIO(0);
+		break;
+	case 2:
+		sfp->gpios.pin_base = PAD_FUNC_SHARE(72);
+		break;
+	case 3:
+		sfp->gpios.pin_base = PAD_FUNC_SHARE(70);
+		break;
+	case 4: case 5: case 6:
+		sfp->gpios.pin_base = PAD_FUNC_SHARE(0);
+		break;
+	default:
+		dev_err(dev, "invalid signal group %u\n", value);
+		return -EINVAL;
+	}
+
+	sfp->gc.label = dev_name(dev);
+	sfp->gc.owner = THIS_MODULE;
+	sfp->gc.request = starfive_gpio_request;
+	sfp->gc.free = starfive_gpio_free;
+	sfp->gc.get_direction = starfive_gpio_get_direction;
+	sfp->gc.direction_input = starfive_gpio_direction_input;
+	sfp->gc.direction_output = starfive_gpio_direction_output;
+	sfp->gc.get = starfive_gpio_get;
+	sfp->gc.set = starfive_gpio_set;
+	sfp->gc.set_config = starfive_gpio_set_config;
+	sfp->gc.add_pin_ranges = starfive_gpio_add_pin_ranges;
+	sfp->gc.base = -1;
+	sfp->gc.ngpio = NR_GPIOS;
+
+	starfive_irq_chip.parent_device = dev;
+	starfive_irq_chip.name = sfp->gc.label;
+
+	sfp->gc.irq.chip = &starfive_irq_chip;
+	sfp->gc.irq.parent_handler = starfive_gpio_irq_handler;
+	sfp->gc.irq.num_parents = 1;
+	sfp->gc.irq.parents = devm_kcalloc(dev, sfp->gc.irq.num_parents,
+					   sizeof(*sfp->gc.irq.parents), GFP_KERNEL);
+	if (!sfp->gc.irq.parents)
+		return -ENOMEM;
+	sfp->gc.irq.default_type = IRQ_TYPE_NONE;
+	sfp->gc.irq.handler = handle_bad_irq;
+	sfp->gc.irq.init_hw = starfive_gpio_init_hw;
+
+	ret = platform_get_irq(pdev, 0);
+	if (ret < 0)
+		return ret;
+	sfp->gc.irq.parents[0] = ret;
+
+	ret = devm_gpiochip_add_data(dev, &sfp->gc, sfp);
+	if (ret) {
+		dev_err(dev, "could not register gpiochip: %d\n", ret);
+		return ret;
+	}
+
+done:
+	return pinctrl_enable(sfp->pctl);
+}
+
+static const struct of_device_id starfive_of_match[] = {
+	{ .compatible = "starfive,jh7100-pinctrl" },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, starfive_of_match);
+
+static struct platform_driver starfive_pinctrl_driver = {
+	.probe = starfive_probe,
+	.driver = {
+		.name = DRIVER_NAME,
+		.of_match_table = starfive_of_match,
+	},
+};
+module_platform_driver(starfive_pinctrl_driver);
+
+MODULE_DESCRIPTION("Pinctrl driver for StarFive SoCs");
+MODULE_AUTHOR("Emil Renner Berthing <kernel@esmil.dk>");
+MODULE_LICENSE("GPL v2");
-- 
2.33.1


^ permalink raw reply related	[flat|nested] 143+ messages in thread

* [PATCH v2 12/16] pinctrl: starfive: Add pinctrl driver for StarFive SoCs
@ 2021-10-21 17:42   ` Emil Renner Berthing
  0 siblings, 0 replies; 143+ messages in thread
From: Emil Renner Berthing @ 2021-10-21 17:42 UTC (permalink / raw)
  To: linux-riscv, devicetree, linux-clk, linux-gpio, linux-serial
  Cc: Emil Renner Berthing, Palmer Dabbelt, Paul Walmsley, Rob Herring,
	Michael Turquette, Stephen Boyd, Thomas Gleixner, Marc Zyngier,
	Philipp Zabel, Linus Walleij, Greg Kroah-Hartman, Daniel Lezcano,
	Andy Shevchenko, Jiri Slaby, Maximilian Luz, Sagar Kadam,
	Drew Fustini, Geert Uytterhoeven, Michael Zhu, Fu Wei,
	Anup Patel, Atish Patra, Matteo Croce, linux-kernel, Huan Feng

Add a combined pinctrl and GPIO driver for the StarFive JH7100 SoC.

For each "GPIO" there are two registers for configuring the output and
output enable signals which may come from other peripherals. Among these
are two special signals that are constant 0 and constant 1 respectively.
Controlling the GPIOs from software is done by choosing one of these
signals. In other words the same registers are used for both pinmuxing
and controlling the GPIOs, which makes it easier to combine the pinctrl
and GPIO driver in one.

I wrote the pinconf and pinmux parts, but the GPIO part of the code is
based on the GPIO driver in the vendor tree written by Huan Feng with
cleanups and fixes by Drew and me.

Datasheet: https://github.com/starfive-tech/JH7100_Docs/blob/main/JH7100%20Data%20Sheet%20V01.01.04-EN%20(4-21-2021).pdf
Co-developed-by: Huan Feng <huan.feng@starfivetech.com>
Signed-off-by: Huan Feng <huan.feng@starfivetech.com>
Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
Co-developed-by: Drew Fustini <drew@beagleboard.org>
Signed-off-by: Drew Fustini <drew@beagleboard.org>
---
 MAINTAINERS                        |    8 +
 drivers/pinctrl/Kconfig            |   16 +
 drivers/pinctrl/Makefile           |    1 +
 drivers/pinctrl/pinctrl-starfive.c | 1387 ++++++++++++++++++++++++++++
 4 files changed, 1412 insertions(+)
 create mode 100644 drivers/pinctrl/pinctrl-starfive.c

diff --git a/MAINTAINERS b/MAINTAINERS
index b3f3a29fc91f..1f122f93a5a5 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -17855,6 +17855,14 @@ F:	Documentation/devicetree/bindings/clock/starfive,jh7100-clkgen.yaml
 F:	drivers/clk/starfive/clk-starfive-jh7100.c
 F:	include/dt-bindings/clock/starfive-jh7100.h
 
+STARFIVE JH7100 PINCTRL DRIVER
+M:	Emil Renner Berthing <kernel@esmil.dk>
+L:	linux-gpio@vger.kernel.org
+S:	Maintained
+F:	Documentation/devicetree/bindings/pinctrl/starfive,jh7100-pinctrl.yaml
+F:	drivers/pinctrl/pinctrl-starfive.c
+F:	include/dt-bindings/pinctrl/pinctrl-starfive.h
+
 STARFIVE JH7100 RESET CONTROLLER DRIVER
 M:	Emil Renner Berthing <kernel@esmil.dk>
 S:	Maintained
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index 31921108e456..98caa94acf9e 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -265,6 +265,22 @@ config PINCTRL_ST
 	select PINCONF
 	select GPIOLIB_IRQCHIP
 
+config PINCTRL_STARFIVE
+	tristate "Pinctrl and GPIO driver for the StarFive JH7100 SoC"
+	depends on SOC_STARFIVE || COMPILE_TEST
+	default SOC_STARFIVE
+	select GENERIC_PINCTRL_GROUPS
+	select GENERIC_PINMUX_FUNCTIONS
+	select GENERIC_PINCONF
+	select GPIOLIB
+	select GPIOLIB_IRQCHIP
+	select OF_GPIO
+	help
+	  Say yes here to support pin control on the StarFive JH7100 SoC.
+	  This also provides an interface to the GPIO pins not used by other
+	  peripherals supporting inputs, outputs, configuring pull-up/pull-down
+	  and interrupts on input changes.
+
 config PINCTRL_STMFX
 	tristate "STMicroelectronics STMFX GPIO expander pinctrl driver"
 	depends on I2C
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index 200073bcc2c1..9c258047f11c 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -38,6 +38,7 @@ obj-$(CONFIG_PINCTRL_LANTIQ)	+= pinctrl-lantiq.o
 obj-$(CONFIG_PINCTRL_LPC18XX)	+= pinctrl-lpc18xx.o
 obj-$(CONFIG_PINCTRL_TB10X)	+= pinctrl-tb10x.o
 obj-$(CONFIG_PINCTRL_ST) 	+= pinctrl-st.o
+obj-$(CONFIG_PINCTRL_STARFIVE)	+= pinctrl-starfive.o
 obj-$(CONFIG_PINCTRL_STMFX) 	+= pinctrl-stmfx.o
 obj-$(CONFIG_PINCTRL_ZYNQ)	+= pinctrl-zynq.o
 obj-$(CONFIG_PINCTRL_ZYNQMP)	+= pinctrl-zynqmp.o
diff --git a/drivers/pinctrl/pinctrl-starfive.c b/drivers/pinctrl/pinctrl-starfive.c
new file mode 100644
index 000000000000..ca99fad883e6
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-starfive.c
@@ -0,0 +1,1387 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Pinctrl / GPIO driver for StarFive JH7100 SoC
+ *
+ * Copyright (C) 2020 Shanghai StarFive Technology Co., Ltd.
+ * Copyright (C) 2021 Emil Renner Berthing <kernel@esmil.dk>
+ */
+
+#include <linux/bits.h>
+#include <linux/clk.h>
+#include <linux/gpio/driver.h>
+#include <linux/io.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+#include <linux/spinlock.h>
+
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+
+#include <dt-bindings/pinctrl/pinctrl-starfive.h>
+
+#include "core.h"
+#include "pinctrl-utils.h"
+#include "pinmux.h"
+#include "pinconf.h"
+
+#define DRIVER_NAME "pinctrl-starfive"
+
+/*
+ * Refer to Section 12. GPIO Registers in the JH7100 data sheet:
+ * https://github.com/starfive-tech/JH7100_Docs
+ */
+#define NR_GPIOS	64
+
+/*
+ * Global enable for GPIO interrupts. If bit 0 is set to 1 the GPIO interrupts
+ * are enabled. If set to 0 the GPIO interrupts are disabled.
+ */
+#define GPIOEN		0x000
+
+/*
+ * The following 32-bit registers come in pairs, but only the offset of the
+ * first register is defined. The first controls (interrupts for) GPIO 0-31 and
+ * the second GPIO 32-63.
+ */
+
+/*
+ * Interrupt Type. If set to 1 the interrupt is edge-triggered. If set to 0 the
+ * interrupt is level-triggered.
+ */
+#define GPIOIS		0x010
+
+/*
+ * Edge-Trigger Interrupt Type.  If set to 1 the interrupt gets triggered on
+ * both positive and negative edges. If set to 0 the interrupt is triggered by a
+ * single edge.
+ */
+#define GPIOIBE		0x018
+
+/*
+ * Interrupt Trigger Polarity. If set to 1 the interrupt is triggered on a
+ * rising edge (edge-triggered) or high level (level-triggered). If set to 0 the
+ * interrupt is triggered on a falling edge (edge-triggered) or low level
+ * (level-triggered).
+ */
+#define GPIOIEV		0x020
+
+/*
+ * Interrupt Mask. If set to 1 the interrupt is disabled (masked). If set to 0
+ * the interrupt is enabled (unmasked).
+ */
+#define GPIOIE		0x028
+
+/*
+ * Clear Edge-Triggered Interrupts. Write a 1 to clear the edge-triggered
+ * interrupt.
+ */
+#define GPIOIC		0x030
+
+/*
+ * Edge-Triggered Interrupt Status. A 1 means the configured edge was detected.
+ */
+#define GPIORIS		0x038
+
+/*
+ * Interrupt Status after Masking. A 1 means the configured edge or level was
+ * detected and not masked.
+ */
+#define GPIOMIS		0x040
+
+/*
+ * Data Value. Dynamically reflects the value of the GPIO pin. If 1 the pin is
+ * a digital 1 and if 0 the pin is a digital 0.
+ */
+#define GPIODIN		0x048
+
+/*
+ * From the data sheet section 12.2, there are 64 32-bit output data registers
+ * and 64 output enable registers. Output data and output enable registers for
+ * a given GPIO are contiguous. Eg. GPO0_DOUT_CFG is 0x50 and GPO0_DOEN_CFG is
+ * 0x54 while GPO1_DOUT_CFG is 0x58 and GPO1_DOEN_CFG is 0x5c.  The stride
+ * between GPIO registers is effectively 8, thus: GPOn_DOUT_CFG is 0x50 + 8n
+ * and GPOn_DOEN_CFG is 0x54 + 8n.
+ */
+#define GPON_DOUT_CFG	0x050
+#define GPON_DOEN_CFG	0x054
+
+/*
+ * From Section 12.3, there are 75 input signal configuration registers which
+ * are 4 bytes wide starting with GPI_CPU_JTAG_TCK_CFG at 0x250 and ending with
+ * GPI_USB_OVER_CURRENT_CFG 0x378
+ */
+#define GPI_CFG_OFFSET	0x250
+
+/*
+ * Pad Control Bits. There are 16 pad control bits for each pin located in 103
+ * 32-bit registers controlling PAD_GPIO[0] to PAD_GPIO[63] followed by
+ * PAD_FUNC_SHARE[0] to PAD_FUNC_SHARE[141]. Odd numbered pins use the upper 16
+ * bit of each register.
+ */
+#define PAD_SLEW_RATE_MASK		GENMASK(11, 9)
+#define PAD_SLEW_RATE_POS		9
+#define PAD_BIAS_STRONG_PULL_UP		BIT(8)
+#define PAD_INPUT_ENABLE		BIT(7)
+#define PAD_INPUT_SCHMITT_ENABLE	BIT(6)
+#define PAD_BIAS_DISABLE		BIT(5)
+#define PAD_BIAS_PULL_DOWN		BIT(4)
+#define PAD_BIAS_MASK			(PAD_BIAS_STRONG_PULL_UP | \
+					 PAD_BIAS_DISABLE | \
+					 PAD_BIAS_PULL_DOWN)
+#define PAD_DRIVE_STRENGTH_MASK		GENMASK(3, 0)
+#define PAD_DRIVE_STRENGTH_POS		0
+
+/*
+ * From Section 11, the IO_PADSHARE_SEL register can be programmed to select
+ * one of seven pre-defined multiplexed signal groups on PAD_FUNC_SHARE and
+ * PAD_GPIO pads. This is a global setting.
+ */
+#define IO_PADSHARE_SEL			0x1a0
+
+/*
+ * This just needs to be some number such that when
+ * sfp->gpio.pin_base = PAD_INVALID_GPIO then
+ * starfive_pin_to_gpio(sfp, validpin) is never a valid GPIO number.
+ * That is it should underflow and return something >= NR_GPIOS.
+ */
+#define PAD_INVALID_GPIO		0x10000
+
+/*
+ * The packed pinmux values from the device tree look like this:
+ *
+ *  | 31 - 24 | 23 - 16 | 15 - 8 |     7    |     6    |  5 - 0  |
+ *  |  dout   |  doen   |  din   | dout rev | doen rev | gpio nr |
+ *
+ * ..but the GPOn_DOUT_CFG and GPOn_DOEN_CFG registers look like this:
+ *
+ *  |      31       | 30 - 8 |   7 - 0   |
+ *  | dout/doen rev | unused | dout/doen |
+ */
+static unsigned int starfive_pinmux_to_gpio(u32 v)
+{
+	return v & (NR_GPIOS - 1);
+}
+
+static u32 starfive_pinmux_to_dout(u32 v)
+{
+	return ((v & BIT(7)) << (31 - 7)) | ((v >> 24) & GENMASK(7, 0));
+}
+
+static u32 starfive_pinmux_to_doen(u32 v)
+{
+	return ((v & BIT(6)) << (31 - 6)) | ((v >> 16) & GENMASK(7, 0));
+}
+
+static u32 starfive_pinmux_to_din(u32 v)
+{
+	return (v >> 8) & GENMASK(7, 0);
+}
+
+/*
+ * The maximum GPIO output current depends on the chosen drive strength:
+ *
+ *  DS:   0     1     2     3     4     5     6     7
+ *  mA:  14.2  21.2  28.2  35.2  42.2  49.1  56.0  62.8
+ *
+ * After rounding that is 7*DS + 14 mA
+ */
+static u32 starfive_drive_strength_to_max_mA(u16 ds)
+{
+	return 7 * ds + 14;
+}
+
+static u16 starfive_drive_strength_from_max_mA(u32 i)
+{
+	return (clamp(i, 14U, 63U) - 14) / 7;
+}
+
+struct starfive_pinctrl {
+	struct gpio_chip gc;
+	struct pinctrl_gpio_range gpios;
+	raw_spinlock_t lock;
+	void __iomem *base;
+	void __iomem *padctl;
+	struct pinctrl_dev *pctl;
+};
+
+static struct device *starfive_dev(const struct starfive_pinctrl *sfp)
+{
+	return sfp->gc.parent;
+}
+
+static unsigned int starfive_pin_to_gpio(const struct starfive_pinctrl *sfp,
+					 unsigned int pin)
+{
+	return pin - sfp->gpios.pin_base;
+}
+
+static unsigned int starfive_gpio_to_pin(const struct starfive_pinctrl *sfp,
+					 unsigned int gpio)
+{
+	return sfp->gpios.pin_base + gpio;
+}
+
+static struct starfive_pinctrl *starfive_from_gc(struct gpio_chip *gc)
+{
+	return container_of(gc, struct starfive_pinctrl, gc);
+}
+
+static struct starfive_pinctrl *starfive_from_irq_data(struct irq_data *d)
+{
+	return starfive_from_gc(irq_data_get_irq_chip_data(d));
+}
+
+static struct starfive_pinctrl *starfive_from_irq_desc(struct irq_desc *desc)
+{
+	return starfive_from_gc(irq_desc_get_handler_data(desc));
+}
+
+static const struct pinctrl_pin_desc starfive_pins[] = {
+	PINCTRL_PIN(PAD_GPIO(0), "GPIO[0]"),
+	PINCTRL_PIN(PAD_GPIO(1), "GPIO[1]"),
+	PINCTRL_PIN(PAD_GPIO(2), "GPIO[2]"),
+	PINCTRL_PIN(PAD_GPIO(3), "GPIO[3]"),
+	PINCTRL_PIN(PAD_GPIO(4), "GPIO[4]"),
+	PINCTRL_PIN(PAD_GPIO(5), "GPIO[5]"),
+	PINCTRL_PIN(PAD_GPIO(6), "GPIO[6]"),
+	PINCTRL_PIN(PAD_GPIO(7), "GPIO[7]"),
+	PINCTRL_PIN(PAD_GPIO(8), "GPIO[8]"),
+	PINCTRL_PIN(PAD_GPIO(9), "GPIO[9]"),
+	PINCTRL_PIN(PAD_GPIO(10), "GPIO[10]"),
+	PINCTRL_PIN(PAD_GPIO(11), "GPIO[11]"),
+	PINCTRL_PIN(PAD_GPIO(12), "GPIO[12]"),
+	PINCTRL_PIN(PAD_GPIO(13), "GPIO[13]"),
+	PINCTRL_PIN(PAD_GPIO(14), "GPIO[14]"),
+	PINCTRL_PIN(PAD_GPIO(15), "GPIO[15]"),
+	PINCTRL_PIN(PAD_GPIO(16), "GPIO[16]"),
+	PINCTRL_PIN(PAD_GPIO(17), "GPIO[17]"),
+	PINCTRL_PIN(PAD_GPIO(18), "GPIO[18]"),
+	PINCTRL_PIN(PAD_GPIO(19), "GPIO[19]"),
+	PINCTRL_PIN(PAD_GPIO(20), "GPIO[20]"),
+	PINCTRL_PIN(PAD_GPIO(21), "GPIO[21]"),
+	PINCTRL_PIN(PAD_GPIO(22), "GPIO[22]"),
+	PINCTRL_PIN(PAD_GPIO(23), "GPIO[23]"),
+	PINCTRL_PIN(PAD_GPIO(24), "GPIO[24]"),
+	PINCTRL_PIN(PAD_GPIO(25), "GPIO[25]"),
+	PINCTRL_PIN(PAD_GPIO(26), "GPIO[26]"),
+	PINCTRL_PIN(PAD_GPIO(27), "GPIO[27]"),
+	PINCTRL_PIN(PAD_GPIO(28), "GPIO[28]"),
+	PINCTRL_PIN(PAD_GPIO(29), "GPIO[29]"),
+	PINCTRL_PIN(PAD_GPIO(30), "GPIO[30]"),
+	PINCTRL_PIN(PAD_GPIO(31), "GPIO[31]"),
+	PINCTRL_PIN(PAD_GPIO(32), "GPIO[32]"),
+	PINCTRL_PIN(PAD_GPIO(33), "GPIO[33]"),
+	PINCTRL_PIN(PAD_GPIO(34), "GPIO[34]"),
+	PINCTRL_PIN(PAD_GPIO(35), "GPIO[35]"),
+	PINCTRL_PIN(PAD_GPIO(36), "GPIO[36]"),
+	PINCTRL_PIN(PAD_GPIO(37), "GPIO[37]"),
+	PINCTRL_PIN(PAD_GPIO(38), "GPIO[38]"),
+	PINCTRL_PIN(PAD_GPIO(39), "GPIO[39]"),
+	PINCTRL_PIN(PAD_GPIO(40), "GPIO[40]"),
+	PINCTRL_PIN(PAD_GPIO(41), "GPIO[41]"),
+	PINCTRL_PIN(PAD_GPIO(42), "GPIO[42]"),
+	PINCTRL_PIN(PAD_GPIO(43), "GPIO[43]"),
+	PINCTRL_PIN(PAD_GPIO(44), "GPIO[44]"),
+	PINCTRL_PIN(PAD_GPIO(45), "GPIO[45]"),
+	PINCTRL_PIN(PAD_GPIO(46), "GPIO[46]"),
+	PINCTRL_PIN(PAD_GPIO(47), "GPIO[47]"),
+	PINCTRL_PIN(PAD_GPIO(48), "GPIO[48]"),
+	PINCTRL_PIN(PAD_GPIO(49), "GPIO[49]"),
+	PINCTRL_PIN(PAD_GPIO(50), "GPIO[50]"),
+	PINCTRL_PIN(PAD_GPIO(51), "GPIO[51]"),
+	PINCTRL_PIN(PAD_GPIO(52), "GPIO[52]"),
+	PINCTRL_PIN(PAD_GPIO(53), "GPIO[53]"),
+	PINCTRL_PIN(PAD_GPIO(54), "GPIO[54]"),
+	PINCTRL_PIN(PAD_GPIO(55), "GPIO[55]"),
+	PINCTRL_PIN(PAD_GPIO(56), "GPIO[56]"),
+	PINCTRL_PIN(PAD_GPIO(57), "GPIO[57]"),
+	PINCTRL_PIN(PAD_GPIO(58), "GPIO[58]"),
+	PINCTRL_PIN(PAD_GPIO(59), "GPIO[59]"),
+	PINCTRL_PIN(PAD_GPIO(60), "GPIO[60]"),
+	PINCTRL_PIN(PAD_GPIO(61), "GPIO[61]"),
+	PINCTRL_PIN(PAD_GPIO(62), "GPIO[62]"),
+	PINCTRL_PIN(PAD_GPIO(63), "GPIO[63]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(0), "FUNC_SHARE[0]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(1), "FUNC_SHARE[1]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(2), "FUNC_SHARE[2]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(3), "FUNC_SHARE[3]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(4), "FUNC_SHARE[4]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(5), "FUNC_SHARE[5]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(6), "FUNC_SHARE[6]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(7), "FUNC_SHARE[7]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(8), "FUNC_SHARE[8]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(9), "FUNC_SHARE[9]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(10), "FUNC_SHARE[10]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(11), "FUNC_SHARE[11]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(12), "FUNC_SHARE[12]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(13), "FUNC_SHARE[13]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(14), "FUNC_SHARE[14]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(15), "FUNC_SHARE[15]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(16), "FUNC_SHARE[16]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(17), "FUNC_SHARE[17]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(18), "FUNC_SHARE[18]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(19), "FUNC_SHARE[19]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(20), "FUNC_SHARE[20]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(21), "FUNC_SHARE[21]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(22), "FUNC_SHARE[22]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(23), "FUNC_SHARE[23]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(24), "FUNC_SHARE[24]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(25), "FUNC_SHARE[25]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(26), "FUNC_SHARE[26]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(27), "FUNC_SHARE[27]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(28), "FUNC_SHARE[28]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(29), "FUNC_SHARE[29]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(30), "FUNC_SHARE[30]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(31), "FUNC_SHARE[31]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(32), "FUNC_SHARE[32]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(33), "FUNC_SHARE[33]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(34), "FUNC_SHARE[34]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(35), "FUNC_SHARE[35]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(36), "FUNC_SHARE[36]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(37), "FUNC_SHARE[37]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(38), "FUNC_SHARE[38]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(39), "FUNC_SHARE[39]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(40), "FUNC_SHARE[40]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(41), "FUNC_SHARE[41]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(42), "FUNC_SHARE[42]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(43), "FUNC_SHARE[43]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(44), "FUNC_SHARE[44]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(45), "FUNC_SHARE[45]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(46), "FUNC_SHARE[46]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(47), "FUNC_SHARE[47]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(48), "FUNC_SHARE[48]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(49), "FUNC_SHARE[49]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(50), "FUNC_SHARE[50]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(51), "FUNC_SHARE[51]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(52), "FUNC_SHARE[52]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(53), "FUNC_SHARE[53]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(54), "FUNC_SHARE[54]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(55), "FUNC_SHARE[55]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(56), "FUNC_SHARE[56]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(57), "FUNC_SHARE[57]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(58), "FUNC_SHARE[58]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(59), "FUNC_SHARE[59]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(60), "FUNC_SHARE[60]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(61), "FUNC_SHARE[61]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(62), "FUNC_SHARE[62]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(63), "FUNC_SHARE[63]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(64), "FUNC_SHARE[64]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(65), "FUNC_SHARE[65]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(66), "FUNC_SHARE[66]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(67), "FUNC_SHARE[67]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(68), "FUNC_SHARE[68]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(69), "FUNC_SHARE[69]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(70), "FUNC_SHARE[70]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(71), "FUNC_SHARE[71]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(72), "FUNC_SHARE[72]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(73), "FUNC_SHARE[73]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(74), "FUNC_SHARE[74]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(75), "FUNC_SHARE[75]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(76), "FUNC_SHARE[76]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(77), "FUNC_SHARE[77]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(78), "FUNC_SHARE[78]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(79), "FUNC_SHARE[79]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(80), "FUNC_SHARE[80]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(81), "FUNC_SHARE[81]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(82), "FUNC_SHARE[82]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(83), "FUNC_SHARE[83]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(84), "FUNC_SHARE[84]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(85), "FUNC_SHARE[85]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(86), "FUNC_SHARE[86]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(87), "FUNC_SHARE[87]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(88), "FUNC_SHARE[88]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(89), "FUNC_SHARE[89]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(90), "FUNC_SHARE[90]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(91), "FUNC_SHARE[91]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(92), "FUNC_SHARE[92]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(93), "FUNC_SHARE[93]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(94), "FUNC_SHARE[94]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(95), "FUNC_SHARE[95]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(96), "FUNC_SHARE[96]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(97), "FUNC_SHARE[97]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(98), "FUNC_SHARE[98]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(99), "FUNC_SHARE[99]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(100), "FUNC_SHARE[100]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(101), "FUNC_SHARE[101]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(102), "FUNC_SHARE[102]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(103), "FUNC_SHARE[103]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(104), "FUNC_SHARE[104]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(105), "FUNC_SHARE[105]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(106), "FUNC_SHARE[106]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(107), "FUNC_SHARE[107]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(108), "FUNC_SHARE[108]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(109), "FUNC_SHARE[109]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(110), "FUNC_SHARE[110]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(111), "FUNC_SHARE[111]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(112), "FUNC_SHARE[112]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(113), "FUNC_SHARE[113]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(114), "FUNC_SHARE[114]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(115), "FUNC_SHARE[115]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(116), "FUNC_SHARE[116]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(117), "FUNC_SHARE[117]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(118), "FUNC_SHARE[118]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(119), "FUNC_SHARE[119]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(120), "FUNC_SHARE[120]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(121), "FUNC_SHARE[121]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(122), "FUNC_SHARE[122]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(123), "FUNC_SHARE[123]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(124), "FUNC_SHARE[124]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(125), "FUNC_SHARE[125]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(126), "FUNC_SHARE[126]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(127), "FUNC_SHARE[127]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(128), "FUNC_SHARE[128]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(129), "FUNC_SHARE[129]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(130), "FUNC_SHARE[130]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(131), "FUNC_SHARE[131]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(132), "FUNC_SHARE[132]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(133), "FUNC_SHARE[133]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(134), "FUNC_SHARE[134]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(135), "FUNC_SHARE[135]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(136), "FUNC_SHARE[136]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(137), "FUNC_SHARE[137]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(138), "FUNC_SHARE[138]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(139), "FUNC_SHARE[139]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(140), "FUNC_SHARE[140]"),
+	PINCTRL_PIN(PAD_FUNC_SHARE(141), "FUNC_SHARE[141]"),
+};
+
+#ifdef CONFIG_DEBUG_FS
+static void starfive_pin_dbg_show(struct pinctrl_dev *pctldev,
+				  struct seq_file *s,
+				  unsigned int pin)
+{
+	struct starfive_pinctrl *sfp = pinctrl_dev_get_drvdata(pctldev);
+	unsigned int gpio = starfive_pin_to_gpio(sfp, pin);
+	void __iomem *reg;
+	u32 dout, doen;
+
+	if (gpio >= NR_GPIOS)
+		return;
+
+	reg = sfp->base + GPON_DOUT_CFG + 8 * gpio;
+	dout = readl_relaxed(reg + 0x000);
+	doen = readl_relaxed(reg + 0x004);
+
+	seq_printf(s, "dout=%u%s doen=%u%s",
+		   dout & (u32)GENMASK(7, 0), (dout & BIT(31)) ? "r" : "",
+		   doen & (u32)GENMASK(7, 0), (doen & BIT(31)) ? "r" : "");
+}
+#else
+#define starfive_pin_dbg_show NULL
+#endif
+
+static int starfive_dt_node_to_map(struct pinctrl_dev *pctldev,
+				   struct device_node *np,
+				   struct pinctrl_map **maps,
+				   unsigned int *num_maps)
+{
+	struct starfive_pinctrl *sfp = pinctrl_dev_get_drvdata(pctldev);
+	struct device *dev = starfive_dev(sfp);
+	const char **pgnames;
+	struct pinctrl_map *map;
+	struct device_node *child;
+	const char *grpname;
+	int *pins;
+	u32 *pinmux;
+	int nmaps;
+	int ngroups;
+	int ret;
+
+	nmaps = 0;
+	ngroups = 0;
+	for_each_child_of_node(np, child) {
+		int npinmux = of_property_count_u32_elems(child, "pinmux");
+		int npins   = of_property_count_u32_elems(child, "pins");
+
+		if (npinmux > 0 && npins > 0) {
+			dev_err(dev, "invalid pinctrl group %pOFn.%pOFn: %s\n",
+				np, child, "both pinmux and pins set");
+			of_node_put(child);
+			return -EINVAL;
+		}
+
+		if (npinmux > 0) {
+			nmaps += 2;
+		} else if (npins > 0) {
+			nmaps += 1;
+		} else {
+			dev_err(dev, "invalid pinctrl group %pOFn.%pOFn: %s\n",
+				np, child, "neither pinmux nor pins set");
+			of_node_put(child);
+			return -EINVAL;
+		}
+		ngroups += 1;
+	}
+
+	ret = -ENOMEM;
+	pgnames = devm_kcalloc(dev, ngroups, sizeof(*pgnames), GFP_KERNEL);
+	if (!pgnames)
+		return ret;
+
+	map = kcalloc(nmaps, sizeof(*map), GFP_KERNEL);
+	if (!map)
+		goto free_pgnames;
+
+	nmaps = 0;
+	ngroups = 0;
+	for_each_child_of_node(np, child) {
+		int npins;
+		int i;
+
+		ret = -ENOMEM;
+		grpname = devm_kasprintf(dev, GFP_KERNEL, "%s.%s", np->name, child->name);
+		if (!grpname)
+			goto put_child;
+
+		pgnames[ngroups++] = grpname;
+
+		if ((npins = of_property_count_u32_elems(child, "pinmux")) > 0) {
+			pins = devm_kcalloc(dev, npins, sizeof(*pins), GFP_KERNEL);
+			if (!pins)
+				goto free_grpname;
+
+			pinmux = devm_kcalloc(dev, npins, sizeof(*pinmux), GFP_KERNEL);
+			if (!pinmux)
+				goto free_pins;
+
+			for (i = 0; i < npins; i++) {
+				u32 v;
+
+				ret = of_property_read_u32_index(child, "pinmux", i, &v);
+				if (ret)
+					goto free_pinmux;
+				pins[i] = starfive_gpio_to_pin(sfp, starfive_pinmux_to_gpio(v));
+				pinmux[i] = v;
+			}
+
+			map[nmaps].type = PIN_MAP_TYPE_MUX_GROUP;
+			map[nmaps].data.mux.function = np->name;
+			map[nmaps].data.mux.group = grpname;
+			nmaps += 1;
+		} else if ((npins = of_property_count_u32_elems(child, "pins")) > 0) {
+			pins = devm_kcalloc(dev, npins, sizeof(*pins), GFP_KERNEL);
+			if (!pins)
+				goto free_grpname;
+
+			pinmux = NULL;
+
+			for (i = 0; i < npins; i++) {
+				u32 v;
+
+				ret = of_property_read_u32_index(child, "pins", i, &v);
+				if (ret)
+					goto free_pins;
+				pins[i] = v;
+			}
+		} else {
+			ret = -EINVAL;
+			goto free_grpname;
+		}
+
+		ret = pinctrl_generic_add_group(pctldev, grpname, pins, npins, pinmux);
+		if (ret < 0) {
+			dev_err(dev, "error adding group %pOFn.%pOFn: %d\n",
+				np, child, ret);
+			goto free_pinmux;
+		}
+
+		ret = pinconf_generic_parse_dt_config(child, pctldev,
+						      &map[nmaps].data.configs.configs,
+						      &map[nmaps].data.configs.num_configs);
+		if (ret) {
+			dev_err(dev, "invalid pinctrl group %pOFn.%pOFn: %s\n",
+				np, child, "error parsing pin config");
+			goto put_child;
+		}
+
+		/* don't create a map if there are no pinconf settings */
+		if (map[nmaps].data.configs.num_configs == 0)
+			continue;
+
+		map[nmaps].type = PIN_MAP_TYPE_CONFIGS_GROUP;
+		map[nmaps].data.configs.group_or_pin = grpname;
+		nmaps += 1;
+	}
+
+	ret = pinmux_generic_add_function(pctldev, np->name, pgnames, ngroups, NULL);
+	if (ret < 0) {
+		dev_err(dev, "error adding function %pOFn: %d\n", np, ret);
+		goto free_map;
+	}
+
+	*maps = map;
+	*num_maps = nmaps;
+	return 0;
+
+free_pinmux:
+	devm_kfree(dev, pinmux);
+free_pins:
+	devm_kfree(dev, pins);
+free_grpname:
+	devm_kfree(dev, grpname);
+put_child:
+	of_node_put(child);
+free_map:
+	pinctrl_utils_free_map(pctldev, map, nmaps);
+free_pgnames:
+	devm_kfree(dev, pgnames);
+	return ret;
+}
+
+static const struct pinctrl_ops starfive_pinctrl_ops = {
+	.get_groups_count = pinctrl_generic_get_group_count,
+	.get_group_name = pinctrl_generic_get_group_name,
+	.get_group_pins = pinctrl_generic_get_group_pins,
+	.pin_dbg_show = starfive_pin_dbg_show,
+	.dt_node_to_map = starfive_dt_node_to_map,
+	.dt_free_map = pinctrl_utils_free_map,
+};
+
+static int starfive_set_mux(struct pinctrl_dev *pctldev,
+			    unsigned int fsel, unsigned int gsel)
+{
+	struct starfive_pinctrl *sfp = pinctrl_dev_get_drvdata(pctldev);
+	struct device *dev = starfive_dev(sfp);
+	const struct group_desc *group;
+	const u32 *pinmux;
+	unsigned int i;
+
+	group = pinctrl_generic_get_group(pctldev, gsel);
+	if (!group)
+		return -EINVAL;
+
+	pinmux = group->data;
+	for (i = 0; i < group->num_pins; i++) {
+		u32 v = pinmux[i];
+		unsigned int gpio = starfive_pinmux_to_gpio(v);
+		u32 dout = starfive_pinmux_to_dout(v);
+		u32 doen = starfive_pinmux_to_doen(v);
+		u32 din = starfive_pinmux_to_din(v);
+		void __iomem *reg_dout;
+		void __iomem *reg_doen;
+		void __iomem *reg_din;
+		unsigned long flags;
+
+		dev_dbg(dev, "GPIO%u: dout=0x%x doen=0x%x din=0x%x\n",
+			gpio, dout, doen, din);
+
+		reg_dout = sfp->base + GPON_DOUT_CFG + 8 * gpio;
+		reg_doen = sfp->base + GPON_DOEN_CFG + 8 * gpio;
+		if (din != GPI_NONE)
+			reg_din = sfp->base + GPI_CFG_OFFSET + 4 * din;
+		else
+			reg_din = NULL;
+
+		raw_spin_lock_irqsave(&sfp->lock, flags);
+		writel_relaxed(dout, reg_dout);
+		writel_relaxed(doen, reg_doen);
+		if (reg_din)
+			writel_relaxed(gpio + 2, reg_din);
+		raw_spin_unlock_irqrestore(&sfp->lock, flags);
+	}
+
+	return 0;
+}
+
+static const struct pinmux_ops starfive_pinmux_ops = {
+	.get_functions_count = pinmux_generic_get_function_count,
+	.get_function_name = pinmux_generic_get_function_name,
+	.get_function_groups = pinmux_generic_get_function_groups,
+	.set_mux = starfive_set_mux,
+	.strict = true,
+};
+
+static u16 starfive_padctl_get(struct starfive_pinctrl *sfp,
+			       unsigned int pin)
+{
+	void __iomem *reg = sfp->padctl + 4 * (pin / 2);
+	int shift = 16 * (pin % 2);
+
+	return readl_relaxed(reg) >> shift;
+}
+
+static void starfive_padctl_rmw(struct starfive_pinctrl *sfp,
+				unsigned int pin,
+				u16 _mask, u16 _value)
+{
+	void __iomem *reg = sfp->padctl + 4 * (pin / 2);
+	int shift = 16 * (pin % 2);
+	u32 mask = (u32)_mask << shift;
+	u32 value = (u32)_value << shift;
+	unsigned long flags;
+
+	dev_dbg(starfive_dev(sfp),
+		"padctl_rmw(%u, 0x%03x, 0x%03x)\n", pin, _mask, _value);
+
+	raw_spin_lock_irqsave(&sfp->lock, flags);
+	value |= readl_relaxed(reg) & ~mask;
+	writel_relaxed(value, reg);
+	raw_spin_unlock_irqrestore(&sfp->lock, flags);
+}
+
+#define PIN_CONFIG_STARFIVE_STRONG_PULL_UP	(PIN_CONFIG_END + 1)
+
+static const struct pinconf_generic_params starfive_pinconf_custom_params[] = {
+	{ "starfive,strong-pull-up", PIN_CONFIG_STARFIVE_STRONG_PULL_UP, 1 },
+};
+
+#ifdef CONFIG_DEBUG_FS
+static const struct pin_config_item starfive_pinconf_custom_conf_items[] = {
+	PCONFDUMP(PIN_CONFIG_STARFIVE_STRONG_PULL_UP, "input bias strong pull-up", NULL, false),
+};
+
+static_assert(ARRAY_SIZE(starfive_pinconf_custom_conf_items) ==
+	      ARRAY_SIZE(starfive_pinconf_custom_params));
+#else
+#define starfive_pinconf_custom_conf_items NULL
+#endif
+
+static int starfive_pinconf_get(struct pinctrl_dev *pctldev,
+				unsigned int pin, unsigned long *config)
+{
+	struct starfive_pinctrl *sfp = pinctrl_dev_get_drvdata(pctldev);
+	u16 value = starfive_padctl_get(sfp, pin);
+	int param = pinconf_to_config_param(*config);
+	u32 arg;
+	bool enabled;
+
+	switch (param) {
+	case PIN_CONFIG_BIAS_DISABLE:
+		enabled = value & PAD_BIAS_DISABLE;
+		arg = 0;
+		break;
+	case PIN_CONFIG_BIAS_PULL_DOWN:
+		enabled = value & PAD_BIAS_PULL_DOWN;
+		arg = 1;
+		break;
+	case PIN_CONFIG_BIAS_PULL_UP:
+		enabled = !(value & PAD_BIAS_MASK);
+		arg = 1;
+		break;
+	case PIN_CONFIG_DRIVE_STRENGTH:
+		enabled = value & PAD_DRIVE_STRENGTH_MASK;
+		arg = starfive_drive_strength_to_max_mA(value & PAD_DRIVE_STRENGTH_MASK);
+		break;
+	case PIN_CONFIG_INPUT_ENABLE:
+		enabled = value & PAD_INPUT_ENABLE;
+		arg = enabled;
+		break;
+	case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
+		enabled = value & PAD_INPUT_SCHMITT_ENABLE;
+		arg = enabled;
+		break;
+	case PIN_CONFIG_SLEW_RATE:
+		enabled = value & PAD_SLEW_RATE_MASK;
+		arg = (value & PAD_SLEW_RATE_MASK) >> PAD_SLEW_RATE_POS;
+		break;
+	case PIN_CONFIG_STARFIVE_STRONG_PULL_UP:
+		enabled = value & PAD_BIAS_STRONG_PULL_UP;
+		arg = enabled;
+		break;
+	default:
+		return -ENOTSUPP;
+	}
+
+	*config = pinconf_to_config_packed(param, arg);
+	return enabled ? 0 : -EINVAL;
+}
+
+static int starfive_pinconf_group_get(struct pinctrl_dev *pctldev,
+				      unsigned int gsel, unsigned long *config)
+{
+	const struct group_desc *group;
+
+	group = pinctrl_generic_get_group(pctldev, gsel);
+	if (!group)
+		return -EINVAL;
+
+	return starfive_pinconf_get(pctldev, group->pins[0], config);
+}
+
+static int starfive_pinconf_group_set(struct pinctrl_dev *pctldev,
+				      unsigned int gsel,
+				      unsigned long *configs,
+				      unsigned int num_configs)
+{
+	struct starfive_pinctrl *sfp = pinctrl_dev_get_drvdata(pctldev);
+	const struct group_desc *group;
+	u16 mask, value;
+	int i;
+
+	group = pinctrl_generic_get_group(pctldev, gsel);
+	if (!group)
+		return -EINVAL;
+
+	mask = 0;
+	value = 0;
+	for (i = 0; i < num_configs; i++) {
+		int param = pinconf_to_config_param(configs[i]);
+		u32 arg = pinconf_to_config_argument(configs[i]);
+
+		switch (param) {
+		case PIN_CONFIG_BIAS_DISABLE:
+			mask |= PAD_BIAS_MASK;
+			value = (value & ~PAD_BIAS_MASK) | PAD_BIAS_DISABLE;
+			break;
+		case PIN_CONFIG_BIAS_PULL_DOWN:
+			if (arg == 0)
+				return -ENOTSUPP;
+			mask |= PAD_BIAS_MASK;
+			value = (value & ~PAD_BIAS_MASK) | PAD_BIAS_PULL_DOWN;
+			break;
+		case PIN_CONFIG_BIAS_PULL_UP:
+			if (arg == 0)
+				return -ENOTSUPP;
+			mask |= PAD_BIAS_MASK;
+			value = value & ~PAD_BIAS_MASK;
+			break;
+		case PIN_CONFIG_DRIVE_STRENGTH:
+			mask |= PAD_DRIVE_STRENGTH_MASK;
+			value = (value & ~PAD_DRIVE_STRENGTH_MASK) |
+				starfive_drive_strength_from_max_mA(arg);
+			break;
+		case PIN_CONFIG_INPUT_ENABLE:
+			mask |= PAD_INPUT_ENABLE;
+			if (arg)
+				value |= PAD_INPUT_ENABLE;
+			else
+				value &= ~PAD_INPUT_ENABLE;
+			break;
+		case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
+			mask |= PAD_INPUT_SCHMITT_ENABLE;
+			if (arg)
+				value |= PAD_INPUT_SCHMITT_ENABLE;
+			else
+				value &= ~PAD_INPUT_SCHMITT_ENABLE;
+			break;
+		case PIN_CONFIG_SLEW_RATE:
+			mask |= PAD_SLEW_RATE_MASK;
+			value = (value & ~PAD_SLEW_RATE_MASK) |
+				((arg << PAD_SLEW_RATE_POS) & PAD_SLEW_RATE_MASK);
+			break;
+		case PIN_CONFIG_STARFIVE_STRONG_PULL_UP:
+			if (arg) {
+				mask |= PAD_BIAS_MASK;
+				value = (value & ~PAD_BIAS_MASK) |
+					PAD_BIAS_STRONG_PULL_UP;
+			} else {
+				mask |= PAD_BIAS_STRONG_PULL_UP;
+				value = value & ~PAD_BIAS_STRONG_PULL_UP;
+			}
+			break;
+		default:
+			return -ENOTSUPP;
+		}
+	}
+
+	for (i = 0; i < group->num_pins; i++)
+		starfive_padctl_rmw(sfp, group->pins[i], mask, value);
+
+	return 0;
+}
+
+#ifdef CONFIG_DEBUG_FS
+static void starfive_pinconf_dbg_show(struct pinctrl_dev *pctldev,
+				      struct seq_file *s, unsigned int pin)
+{
+	struct starfive_pinctrl *sfp = pinctrl_dev_get_drvdata(pctldev);
+	u16 value = starfive_padctl_get(sfp, pin);
+
+	seq_printf(s, " (0x%03x)", value);
+}
+#else
+#define starfive_pinconf_dbg_show NULL
+#endif
+
+static const struct pinconf_ops starfive_pinconf_ops = {
+	.pin_config_get = starfive_pinconf_get,
+	.pin_config_group_get = starfive_pinconf_group_get,
+	.pin_config_group_set = starfive_pinconf_group_set,
+	.pin_config_dbg_show = starfive_pinconf_dbg_show,
+	.is_generic = true,
+};
+
+static struct pinctrl_desc starfive_desc = {
+	.name = DRIVER_NAME,
+	.pins = starfive_pins,
+	.npins = ARRAY_SIZE(starfive_pins),
+	.pctlops = &starfive_pinctrl_ops,
+	.pmxops = &starfive_pinmux_ops,
+	.confops = &starfive_pinconf_ops,
+	.owner = THIS_MODULE,
+	.num_custom_params = ARRAY_SIZE(starfive_pinconf_custom_params),
+	.custom_params = starfive_pinconf_custom_params,
+	.custom_conf_items = starfive_pinconf_custom_conf_items,
+};
+
+static int starfive_gpio_request(struct gpio_chip *gc, unsigned int gpio)
+{
+	return pinctrl_gpio_request(gc->base + gpio);
+}
+
+static void starfive_gpio_free(struct gpio_chip *gc, unsigned int gpio)
+{
+	pinctrl_gpio_free(gc->base + gpio);
+}
+
+static int starfive_gpio_get_direction(struct gpio_chip *gc, unsigned int gpio)
+{
+	struct starfive_pinctrl *sfp = starfive_from_gc(gc);
+
+	if (gpio >= NR_GPIOS)
+		return -EINVAL;
+
+	/* return GPIO_LINE_DIRECTION_OUT (0) only if doen == GPO_ENABLE (0) */
+	return readl_relaxed(sfp->base + GPON_DOEN_CFG + 8 * gpio) != GPO_ENABLE;
+}
+
+static int starfive_gpio_direction_input(struct gpio_chip *gc,
+					 unsigned int gpio)
+{
+	struct starfive_pinctrl *sfp = starfive_from_gc(gc);
+	void __iomem *doen;
+	unsigned long flags;
+
+	if (gpio >= NR_GPIOS)
+		return -EINVAL;
+
+	/* enable input and schmitt trigger */
+	starfive_padctl_rmw(sfp, starfive_gpio_to_pin(sfp, gpio),
+			    PAD_INPUT_ENABLE | PAD_INPUT_SCHMITT_ENABLE,
+			    PAD_INPUT_ENABLE | PAD_INPUT_SCHMITT_ENABLE);
+
+	doen = sfp->base + GPON_DOEN_CFG + 8 * gpio;
+	raw_spin_lock_irqsave(&sfp->lock, flags);
+	writel_relaxed(GPO_DISABLE, doen);
+	raw_spin_unlock_irqrestore(&sfp->lock, flags);
+	return 0;
+}
+
+static int starfive_gpio_direction_output(struct gpio_chip *gc,
+					  unsigned int gpio, int value)
+{
+	struct starfive_pinctrl *sfp = starfive_from_gc(gc);
+	void __iomem *dout;
+	void __iomem *doen;
+	unsigned long flags;
+
+	if (gpio >= NR_GPIOS)
+		return -EINVAL;
+
+	dout = sfp->base + GPON_DOUT_CFG + 8 * gpio;
+	doen = sfp->base + GPON_DOEN_CFG + 8 * gpio;
+	raw_spin_lock_irqsave(&sfp->lock, flags);
+	writel_relaxed(value, dout);
+	writel_relaxed(GPO_ENABLE, doen);
+	raw_spin_unlock_irqrestore(&sfp->lock, flags);
+
+	/* disable input, schmitt trigger and bias */
+	starfive_padctl_rmw(sfp, starfive_gpio_to_pin(sfp, gpio),
+			    PAD_BIAS_MASK | PAD_INPUT_ENABLE | PAD_INPUT_SCHMITT_ENABLE,
+			    PAD_BIAS_DISABLE);
+
+	return 0;
+}
+
+static int starfive_gpio_get(struct gpio_chip *gc, unsigned int gpio)
+{
+	struct starfive_pinctrl *sfp = starfive_from_gc(gc);
+	void __iomem *din;
+
+	if (gpio >= NR_GPIOS)
+		return -EINVAL;
+
+	din = sfp->base + GPIODIN + 4 * (gpio / 32);
+	return !!(readl_relaxed(din) & BIT(gpio % 32));
+}
+
+static void starfive_gpio_set(struct gpio_chip *gc, unsigned int gpio,
+			      int value)
+{
+	struct starfive_pinctrl *sfp = starfive_from_gc(gc);
+	void __iomem *dout;
+	unsigned long flags;
+
+	if (gpio >= NR_GPIOS)
+		return;
+
+	dout = sfp->base + GPON_DOUT_CFG + 8 * gpio;
+	raw_spin_lock_irqsave(&sfp->lock, flags);
+	writel_relaxed(value, dout);
+	raw_spin_unlock_irqrestore(&sfp->lock, flags);
+}
+
+static int starfive_gpio_set_config(struct gpio_chip *gc, unsigned int gpio,
+				    unsigned long config)
+{
+	struct starfive_pinctrl *sfp = starfive_from_gc(gc);
+	u32 arg = pinconf_to_config_argument(config);
+	u16 mask;
+	u16 value;
+
+	switch (pinconf_to_config_param(config)) {
+	case PIN_CONFIG_BIAS_DISABLE:
+		mask  = PAD_BIAS_MASK;
+		value = PAD_BIAS_DISABLE;
+		break;
+	case PIN_CONFIG_BIAS_PULL_DOWN:
+		if (arg == 0)
+			return -ENOTSUPP;
+		mask  = PAD_BIAS_MASK;
+		value = PAD_BIAS_PULL_DOWN;
+		break;
+	case PIN_CONFIG_BIAS_PULL_UP:
+		if (arg == 0)
+			return -ENOTSUPP;
+		mask  = PAD_BIAS_MASK;
+		value = 0;
+		break;
+	case PIN_CONFIG_DRIVE_PUSH_PULL:
+		return 0;
+	case PIN_CONFIG_INPUT_ENABLE:
+		mask  = PAD_INPUT_ENABLE;
+		value = arg ? PAD_INPUT_ENABLE : 0;
+		break;
+	case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
+		mask  = PAD_INPUT_SCHMITT_ENABLE;
+		value = arg ? PAD_INPUT_SCHMITT_ENABLE : 0;
+		break;
+	default:
+		return -ENOTSUPP;
+	};
+
+	starfive_padctl_rmw(sfp, starfive_gpio_to_pin(sfp, gpio), mask, value);
+	return 0;
+}
+
+static int starfive_gpio_add_pin_ranges(struct gpio_chip *gc)
+{
+	struct starfive_pinctrl *sfp = starfive_from_gc(gc);
+
+	sfp->gpios.name = sfp->gc.label;
+	sfp->gpios.base = sfp->gc.base;
+	/*
+	 * sfp->gpios.pin_base depends on the chosen signal group
+	 * and is set in starfive_probe()
+	 */
+	sfp->gpios.npins = NR_GPIOS;
+	sfp->gpios.gc = &sfp->gc;
+	pinctrl_add_gpio_range(sfp->pctl, &sfp->gpios);
+	return 0;
+}
+
+static void starfive_irq_ack(struct irq_data *d)
+{
+	struct starfive_pinctrl *sfp = starfive_from_irq_data(d);
+	irq_hw_number_t gpio = irqd_to_hwirq(d);
+	void __iomem *ic = sfp->base + GPIOIC + 4 * (gpio / 32);
+	u32 mask = BIT(gpio % 32);
+	unsigned long flags;
+
+	raw_spin_lock_irqsave(&sfp->lock, flags);
+	writel_relaxed(mask, ic);
+	raw_spin_unlock_irqrestore(&sfp->lock, flags);
+}
+
+static void starfive_irq_mask(struct irq_data *d)
+{
+	struct starfive_pinctrl *sfp = starfive_from_irq_data(d);
+	irq_hw_number_t gpio = irqd_to_hwirq(d);
+	void __iomem *ie = sfp->base + GPIOIE + 4 * (gpio / 32);
+	u32 mask = BIT(gpio % 32);
+	unsigned long flags;
+	u32 value;
+
+	raw_spin_lock_irqsave(&sfp->lock, flags);
+	value = readl_relaxed(ie) & ~mask;
+	writel_relaxed(value, ie);
+	raw_spin_unlock_irqrestore(&sfp->lock, flags);
+}
+
+static void starfive_irq_mask_ack(struct irq_data *d)
+{
+	struct starfive_pinctrl *sfp = starfive_from_irq_data(d);
+	irq_hw_number_t gpio = irqd_to_hwirq(d);
+	void __iomem *ie = sfp->base + GPIOIE + 4 * (gpio / 32);
+	void __iomem *ic = sfp->base + GPIOIC + 4 * (gpio / 32);
+	u32 mask = BIT(gpio % 32);
+	unsigned long flags;
+	u32 value;
+
+	raw_spin_lock_irqsave(&sfp->lock, flags);
+	value = readl_relaxed(ie) & ~mask;
+	writel_relaxed(value, ie);
+	writel_relaxed(mask, ic);
+	raw_spin_unlock_irqrestore(&sfp->lock, flags);
+}
+
+static void starfive_irq_unmask(struct irq_data *d)
+{
+	struct starfive_pinctrl *sfp = starfive_from_irq_data(d);
+	irq_hw_number_t gpio = irqd_to_hwirq(d);
+	void __iomem *ie = sfp->base + GPIOIE + 4 * (gpio / 32);
+	u32 mask = BIT(gpio % 32);
+	unsigned long flags;
+	u32 value;
+
+	raw_spin_lock_irqsave(&sfp->lock, flags);
+	value = readl_relaxed(ie) | mask;
+	writel_relaxed(value, ie);
+	raw_spin_unlock_irqrestore(&sfp->lock, flags);
+}
+
+static int starfive_irq_set_type(struct irq_data *d, unsigned int trigger)
+{
+	struct starfive_pinctrl *sfp = starfive_from_irq_data(d);
+	irq_hw_number_t gpio = irqd_to_hwirq(d);
+	void __iomem *base = sfp->base + 4 * (gpio / 32);
+	u32 mask = BIT(gpio % 32);
+	u32 irq_type, edge_both, polarity;
+	irq_flow_handler_t handler;
+	unsigned long flags;
+
+	switch (trigger) {
+	case IRQ_TYPE_EDGE_RISING:
+		irq_type  = mask; /* 1: edge triggered */
+		edge_both = 0;    /* 0: single edge */
+		polarity  = mask; /* 1: rising edge */
+		handler   = handle_edge_irq;
+		break;
+	case IRQ_TYPE_EDGE_FALLING:
+		irq_type  = mask; /* 1: edge triggered */
+		edge_both = 0;    /* 0: single edge */
+		polarity  = 0;    /* 0: falling edge */
+		handler   = handle_edge_irq;
+		break;
+	case IRQ_TYPE_EDGE_BOTH:
+		irq_type  = mask; /* 1: edge triggered */
+		edge_both = mask; /* 1: both edges */
+		polarity  = 0;    /* 0: ignored */
+		handler   = handle_edge_irq;
+		break;
+	case IRQ_TYPE_LEVEL_HIGH:
+		irq_type  = 0;    /* 0: level triggered */
+		edge_both = 0;    /* 0: ignored */
+		polarity  = mask; /* 1: high level */
+		handler   = handle_level_irq;
+		break;
+	case IRQ_TYPE_LEVEL_LOW:
+		irq_type  = 0;    /* 0: level triggered */
+		edge_both = 0;    /* 0: ignored */
+		polarity  = 0;    /* 0: low level */
+		handler   = handle_level_irq;
+		break;
+	default:
+		irq_set_handler_locked(d, handle_bad_irq);
+		return -EINVAL;
+	}
+
+	irq_set_handler_locked(d, handler);
+
+	raw_spin_lock_irqsave(&sfp->lock, flags);
+	irq_type |= readl_relaxed(base + GPIOIS) & ~mask;
+	writel_relaxed(irq_type, base + GPIOIS);
+	edge_both |= readl_relaxed(base + GPIOIBE) & ~mask;
+	writel_relaxed(edge_both, base + GPIOIBE);
+	polarity |= readl_relaxed(base + GPIOIEV) & ~mask;
+	writel_relaxed(polarity, base + GPIOIEV);
+	raw_spin_unlock_irqrestore(&sfp->lock, flags);
+	return 0;
+}
+
+static struct irq_chip starfive_irq_chip = {
+	.irq_ack = starfive_irq_ack,
+	.irq_mask = starfive_irq_mask,
+	.irq_mask_ack = starfive_irq_mask_ack,
+	.irq_unmask = starfive_irq_unmask,
+	.irq_set_type = starfive_irq_set_type,
+	.flags = IRQCHIP_SET_TYPE_MASKED,
+};
+
+static void starfive_gpio_irq_handler(struct irq_desc *desc)
+{
+	struct starfive_pinctrl *sfp = starfive_from_irq_desc(desc);
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+	unsigned long mis;
+	unsigned int pin;
+
+	chained_irq_enter(chip, desc);
+
+	mis = readl_relaxed(sfp->base + GPIOMIS + 0);
+	for_each_set_bit(pin, &mis, 32)
+		generic_handle_domain_irq(sfp->gc.irq.domain, pin);
+
+	mis = readl_relaxed(sfp->base + GPIOMIS + 4);
+	for_each_set_bit(pin, &mis, 32)
+		generic_handle_domain_irq(sfp->gc.irq.domain, pin + 32);
+
+	chained_irq_exit(chip, desc);
+}
+
+static int starfive_gpio_init_hw(struct gpio_chip *gc)
+{
+	struct starfive_pinctrl *sfp = starfive_from_gc(gc);
+
+	/* mask all GPIO interrupts */
+	writel(0, sfp->base + GPIOIE + 0);
+	writel(0, sfp->base + GPIOIE + 4);
+	/* clear edge interrupt flags */
+	writel(~0U, sfp->base + GPIOIC + 0);
+	writel(~0U, sfp->base + GPIOIC + 4);
+	/* enable GPIO interrupts */
+	writel(1, sfp->base + GPIOEN);
+	return 0;
+}
+
+static void starfive_disable_clock(void *data)
+{
+	clk_disable_unprepare(data);
+}
+
+static int starfive_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct starfive_pinctrl *sfp;
+	struct clk *clk;
+	struct reset_control *rst;
+	u32 value;
+	int ret;
+
+	sfp = devm_kzalloc(dev, sizeof(*sfp), GFP_KERNEL);
+	if (!sfp)
+		return -ENOMEM;
+
+	sfp->base = devm_platform_ioremap_resource_byname(pdev, "gpio");
+	if (IS_ERR(sfp->base))
+		return PTR_ERR(sfp->base);
+
+	sfp->padctl = devm_platform_ioremap_resource_byname(pdev, "padctl");
+	if (IS_ERR(sfp->padctl))
+		return PTR_ERR(sfp->padctl);
+
+	clk = devm_clk_get(dev, NULL);
+	if (IS_ERR(clk)) {
+		ret = PTR_ERR(clk);
+		return dev_err_probe(dev, ret, "could not get clock: %d\n", ret);
+	}
+
+	rst = devm_reset_control_get_exclusive(dev, NULL);
+	if (IS_ERR(rst)) {
+		ret = PTR_ERR(rst);
+		return dev_err_probe(dev, ret, "could not get reset: %d\n", ret);
+	}
+
+	ret = clk_prepare_enable(clk);
+	if (ret)
+		return dev_err_probe(dev, ret, "could not enable clock: %d\n", ret);
+
+	ret = devm_add_action_or_reset(dev, starfive_disable_clock, clk);
+	if (ret)
+		return ret;
+
+	ret = reset_control_deassert(rst);
+	if (ret)
+		return dev_err_probe(dev, ret, "could not deassert reset: %d\n", ret);
+
+	platform_set_drvdata(pdev, sfp);
+	sfp->gc.parent = dev;
+	raw_spin_lock_init(&sfp->lock);
+
+	ret = devm_pinctrl_register_and_init(dev, &starfive_desc, sfp, &sfp->pctl);
+	if (ret)
+		return dev_err_probe(dev, ret, "could not register pinctrl driver: %d\n", ret);
+
+	if (!device_property_read_u32(dev, "starfive,signal-group", &value)) {
+		if (value > 6) {
+			dev_err(dev, "invalid signal group %u\n", value);
+			return -EINVAL;
+		}
+		writel(value, sfp->padctl + IO_PADSHARE_SEL);
+	}
+
+	value = readl(sfp->padctl + IO_PADSHARE_SEL);
+	switch (value) {
+	case 0:
+		sfp->gpios.pin_base = PAD_INVALID_GPIO;
+		goto done;
+	case 1:
+		sfp->gpios.pin_base = PAD_GPIO(0);
+		break;
+	case 2:
+		sfp->gpios.pin_base = PAD_FUNC_SHARE(72);
+		break;
+	case 3:
+		sfp->gpios.pin_base = PAD_FUNC_SHARE(70);
+		break;
+	case 4: case 5: case 6:
+		sfp->gpios.pin_base = PAD_FUNC_SHARE(0);
+		break;
+	default:
+		dev_err(dev, "invalid signal group %u\n", value);
+		return -EINVAL;
+	}
+
+	sfp->gc.label = dev_name(dev);
+	sfp->gc.owner = THIS_MODULE;
+	sfp->gc.request = starfive_gpio_request;
+	sfp->gc.free = starfive_gpio_free;
+	sfp->gc.get_direction = starfive_gpio_get_direction;
+	sfp->gc.direction_input = starfive_gpio_direction_input;
+	sfp->gc.direction_output = starfive_gpio_direction_output;
+	sfp->gc.get = starfive_gpio_get;
+	sfp->gc.set = starfive_gpio_set;
+	sfp->gc.set_config = starfive_gpio_set_config;
+	sfp->gc.add_pin_ranges = starfive_gpio_add_pin_ranges;
+	sfp->gc.base = -1;
+	sfp->gc.ngpio = NR_GPIOS;
+
+	starfive_irq_chip.parent_device = dev;
+	starfive_irq_chip.name = sfp->gc.label;
+
+	sfp->gc.irq.chip = &starfive_irq_chip;
+	sfp->gc.irq.parent_handler = starfive_gpio_irq_handler;
+	sfp->gc.irq.num_parents = 1;
+	sfp->gc.irq.parents = devm_kcalloc(dev, sfp->gc.irq.num_parents,
+					   sizeof(*sfp->gc.irq.parents), GFP_KERNEL);
+	if (!sfp->gc.irq.parents)
+		return -ENOMEM;
+	sfp->gc.irq.default_type = IRQ_TYPE_NONE;
+	sfp->gc.irq.handler = handle_bad_irq;
+	sfp->gc.irq.init_hw = starfive_gpio_init_hw;
+
+	ret = platform_get_irq(pdev, 0);
+	if (ret < 0)
+		return ret;
+	sfp->gc.irq.parents[0] = ret;
+
+	ret = devm_gpiochip_add_data(dev, &sfp->gc, sfp);
+	if (ret) {
+		dev_err(dev, "could not register gpiochip: %d\n", ret);
+		return ret;
+	}
+
+done:
+	return pinctrl_enable(sfp->pctl);
+}
+
+static const struct of_device_id starfive_of_match[] = {
+	{ .compatible = "starfive,jh7100-pinctrl" },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, starfive_of_match);
+
+static struct platform_driver starfive_pinctrl_driver = {
+	.probe = starfive_probe,
+	.driver = {
+		.name = DRIVER_NAME,
+		.of_match_table = starfive_of_match,
+	},
+};
+module_platform_driver(starfive_pinctrl_driver);
+
+MODULE_DESCRIPTION("Pinctrl driver for StarFive SoCs");
+MODULE_AUTHOR("Emil Renner Berthing <kernel@esmil.dk>");
+MODULE_LICENSE("GPL v2");
-- 
2.33.1


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 143+ messages in thread

* [PATCH v2 13/16] dt-bindings: serial: snps-dw-apb-uart: Add JH7100 uarts
  2021-10-21 17:42 ` Emil Renner Berthing
@ 2021-10-21 17:42   ` Emil Renner Berthing
  -1 siblings, 0 replies; 143+ messages in thread
From: Emil Renner Berthing @ 2021-10-21 17:42 UTC (permalink / raw)
  To: linux-riscv, devicetree, linux-clk, linux-gpio, linux-serial
  Cc: Emil Renner Berthing, Palmer Dabbelt, Paul Walmsley, Rob Herring,
	Michael Turquette, Stephen Boyd, Thomas Gleixner, Marc Zyngier,
	Philipp Zabel, Linus Walleij, Greg Kroah-Hartman, Daniel Lezcano,
	Andy Shevchenko, Jiri Slaby, Maximilian Luz, Sagar Kadam,
	Drew Fustini, Geert Uytterhoeven, Michael Zhu, Fu Wei,
	Anup Patel, Atish Patra, Matteo Croce, linux-kernel

Add compatibles for the StarFive JH7100 uarts.

Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
Reviewed-by: Geert Uytterhoeven <geert@linux-m68k.org>
---
 .../devicetree/bindings/serial/snps-dw-apb-uart.yaml         | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml b/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml
index b49fda5e608f..12137fe80acf 100644
--- a/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml
+++ b/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml
@@ -40,6 +40,11 @@ properties:
               - brcm,bcm11351-dw-apb-uart
               - brcm,bcm21664-dw-apb-uart
           - const: snps,dw-apb-uart
+      - items:
+          - enum:
+              - starfive,jh7100-hsuart
+              - starfive,jh7100-uart
+          - const: snps,dw-apb-uart
       - const: snps,dw-apb-uart
 
   reg:
-- 
2.33.1


^ permalink raw reply related	[flat|nested] 143+ messages in thread

* [PATCH v2 13/16] dt-bindings: serial: snps-dw-apb-uart: Add JH7100 uarts
@ 2021-10-21 17:42   ` Emil Renner Berthing
  0 siblings, 0 replies; 143+ messages in thread
From: Emil Renner Berthing @ 2021-10-21 17:42 UTC (permalink / raw)
  To: linux-riscv, devicetree, linux-clk, linux-gpio, linux-serial
  Cc: Emil Renner Berthing, Palmer Dabbelt, Paul Walmsley, Rob Herring,
	Michael Turquette, Stephen Boyd, Thomas Gleixner, Marc Zyngier,
	Philipp Zabel, Linus Walleij, Greg Kroah-Hartman, Daniel Lezcano,
	Andy Shevchenko, Jiri Slaby, Maximilian Luz, Sagar Kadam,
	Drew Fustini, Geert Uytterhoeven, Michael Zhu, Fu Wei,
	Anup Patel, Atish Patra, Matteo Croce, linux-kernel

Add compatibles for the StarFive JH7100 uarts.

Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
Reviewed-by: Geert Uytterhoeven <geert@linux-m68k.org>
---
 .../devicetree/bindings/serial/snps-dw-apb-uart.yaml         | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml b/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml
index b49fda5e608f..12137fe80acf 100644
--- a/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml
+++ b/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml
@@ -40,6 +40,11 @@ properties:
               - brcm,bcm11351-dw-apb-uart
               - brcm,bcm21664-dw-apb-uart
           - const: snps,dw-apb-uart
+      - items:
+          - enum:
+              - starfive,jh7100-hsuart
+              - starfive,jh7100-uart
+          - const: snps,dw-apb-uart
       - const: snps,dw-apb-uart
 
   reg:
-- 
2.33.1


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 143+ messages in thread

* [PATCH v2 14/16] serial: 8250_dw: Add skip_clk_set_rate quirk
  2021-10-21 17:42 ` Emil Renner Berthing
@ 2021-10-21 17:42   ` Emil Renner Berthing
  -1 siblings, 0 replies; 143+ messages in thread
From: Emil Renner Berthing @ 2021-10-21 17:42 UTC (permalink / raw)
  To: linux-riscv, devicetree, linux-clk, linux-gpio, linux-serial
  Cc: Emil Renner Berthing, Palmer Dabbelt, Paul Walmsley, Rob Herring,
	Michael Turquette, Stephen Boyd, Thomas Gleixner, Marc Zyngier,
	Philipp Zabel, Linus Walleij, Greg Kroah-Hartman, Daniel Lezcano,
	Andy Shevchenko, Jiri Slaby, Maximilian Luz, Sagar Kadam,
	Drew Fustini, Geert Uytterhoeven, Michael Zhu, Fu Wei,
	Anup Patel, Atish Patra, Matteo Croce, linux-kernel

On the StarFive JH7100 SoC the UART core clocks can't be set to exactly
16 * 115200Hz and many other common bitrates. Trying this will only
result in a higher input clock, but low enough that the UART's internal
divisor can't come close enough to the baud rate target. So rather than
try to set the input clock it's better to rely solely on the UART's
internal divisor.

Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
---
 drivers/tty/serial/8250/8250_dw.c | 19 ++++++++++++++++---
 1 file changed, 16 insertions(+), 3 deletions(-)

diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c
index 5a2ff843ec5d..729b59b14ff1 100644
--- a/drivers/tty/serial/8250/8250_dw.c
+++ b/drivers/tty/serial/8250/8250_dw.c
@@ -50,6 +50,7 @@ struct dw8250_data {
 	struct reset_control	*rst;
 
 	unsigned int		skip_autocfg:1;
+	unsigned int		skip_clk_set_rate:1;
 	unsigned int		uart_16550_compatible:1;
 };
 
@@ -326,14 +327,18 @@ dw8250_do_pm(struct uart_port *port, unsigned int state, unsigned int old)
 		pm_runtime_put_sync_suspend(port->dev);
 }
 
-static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios,
-			       struct ktermios *old)
+static void dw8250_do_clk_set_rate(struct uart_port *p, struct ktermios *termios)
 {
-	unsigned long newrate = tty_termios_baud_rate(termios) * 16;
 	struct dw8250_data *d = to_dw8250_data(p->private_data);
+	unsigned long newrate;
 	long rate;
 	int ret;
 
+	if (d->skip_clk_set_rate)
+		return;
+
+	newrate = tty_termios_baud_rate(termios) * 16;
+
 	clk_disable_unprepare(d->clk);
 	rate = clk_round_rate(d->clk, newrate);
 	if (rate > 0) {
@@ -349,7 +354,12 @@ static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios,
 			swap(p->uartclk, rate);
 	}
 	clk_prepare_enable(d->clk);
+}
 
+static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios,
+			       struct ktermios *old)
+{
+	dw8250_do_clk_set_rate(p, termios);
 	dw8250_do_set_termios(p, termios, old);
 }
 
@@ -417,6 +427,8 @@ static void dw8250_quirks(struct uart_port *p, struct dw8250_data *data)
 
 		if (of_device_is_compatible(np, "marvell,armada-38x-uart"))
 			p->serial_out = dw8250_serial_out38x;
+		if (of_device_is_compatible(np, "starfive,jh7100-uart"))
+			data->skip_clk_set_rate = true;
 
 	} else if (acpi_dev_present("APMC0D08", NULL, -1)) {
 		p->iotype = UPIO_MEM32;
@@ -699,6 +711,7 @@ static const struct of_device_id dw8250_of_match[] = {
 	{ .compatible = "cavium,octeon-3860-uart" },
 	{ .compatible = "marvell,armada-38x-uart" },
 	{ .compatible = "renesas,rzn1-uart" },
+	{ .compatible = "starfive,jh7100-uart" },
 	{ /* Sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, dw8250_of_match);
-- 
2.33.1


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 143+ messages in thread

* [PATCH v2 14/16] serial: 8250_dw: Add skip_clk_set_rate quirk
@ 2021-10-21 17:42   ` Emil Renner Berthing
  0 siblings, 0 replies; 143+ messages in thread
From: Emil Renner Berthing @ 2021-10-21 17:42 UTC (permalink / raw)
  To: linux-riscv, devicetree, linux-clk, linux-gpio, linux-serial
  Cc: Emil Renner Berthing, Palmer Dabbelt, Paul Walmsley, Rob Herring,
	Michael Turquette, Stephen Boyd, Thomas Gleixner, Marc Zyngier,
	Philipp Zabel, Linus Walleij, Greg Kroah-Hartman, Daniel Lezcano,
	Andy Shevchenko, Jiri Slaby, Maximilian Luz, Sagar Kadam,
	Drew Fustini, Geert Uytterhoeven, Michael Zhu, Fu Wei,
	Anup Patel, Atish Patra, Matteo Croce, linux-kernel

On the StarFive JH7100 SoC the UART core clocks can't be set to exactly
16 * 115200Hz and many other common bitrates. Trying this will only
result in a higher input clock, but low enough that the UART's internal
divisor can't come close enough to the baud rate target. So rather than
try to set the input clock it's better to rely solely on the UART's
internal divisor.

Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
---
 drivers/tty/serial/8250/8250_dw.c | 19 ++++++++++++++++---
 1 file changed, 16 insertions(+), 3 deletions(-)

diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c
index 5a2ff843ec5d..729b59b14ff1 100644
--- a/drivers/tty/serial/8250/8250_dw.c
+++ b/drivers/tty/serial/8250/8250_dw.c
@@ -50,6 +50,7 @@ struct dw8250_data {
 	struct reset_control	*rst;
 
 	unsigned int		skip_autocfg:1;
+	unsigned int		skip_clk_set_rate:1;
 	unsigned int		uart_16550_compatible:1;
 };
 
@@ -326,14 +327,18 @@ dw8250_do_pm(struct uart_port *port, unsigned int state, unsigned int old)
 		pm_runtime_put_sync_suspend(port->dev);
 }
 
-static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios,
-			       struct ktermios *old)
+static void dw8250_do_clk_set_rate(struct uart_port *p, struct ktermios *termios)
 {
-	unsigned long newrate = tty_termios_baud_rate(termios) * 16;
 	struct dw8250_data *d = to_dw8250_data(p->private_data);
+	unsigned long newrate;
 	long rate;
 	int ret;
 
+	if (d->skip_clk_set_rate)
+		return;
+
+	newrate = tty_termios_baud_rate(termios) * 16;
+
 	clk_disable_unprepare(d->clk);
 	rate = clk_round_rate(d->clk, newrate);
 	if (rate > 0) {
@@ -349,7 +354,12 @@ static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios,
 			swap(p->uartclk, rate);
 	}
 	clk_prepare_enable(d->clk);
+}
 
+static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios,
+			       struct ktermios *old)
+{
+	dw8250_do_clk_set_rate(p, termios);
 	dw8250_do_set_termios(p, termios, old);
 }
 
@@ -417,6 +427,8 @@ static void dw8250_quirks(struct uart_port *p, struct dw8250_data *data)
 
 		if (of_device_is_compatible(np, "marvell,armada-38x-uart"))
 			p->serial_out = dw8250_serial_out38x;
+		if (of_device_is_compatible(np, "starfive,jh7100-uart"))
+			data->skip_clk_set_rate = true;
 
 	} else if (acpi_dev_present("APMC0D08", NULL, -1)) {
 		p->iotype = UPIO_MEM32;
@@ -699,6 +711,7 @@ static const struct of_device_id dw8250_of_match[] = {
 	{ .compatible = "cavium,octeon-3860-uart" },
 	{ .compatible = "marvell,armada-38x-uart" },
 	{ .compatible = "renesas,rzn1-uart" },
+	{ .compatible = "starfive,jh7100-uart" },
 	{ /* Sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, dw8250_of_match);
-- 
2.33.1


^ permalink raw reply related	[flat|nested] 143+ messages in thread

* [PATCH v2 15/16] RISC-V: Add initial StarFive JH7100 device tree
  2021-10-21 17:42 ` Emil Renner Berthing
@ 2021-10-21 17:42   ` Emil Renner Berthing
  -1 siblings, 0 replies; 143+ messages in thread
From: Emil Renner Berthing @ 2021-10-21 17:42 UTC (permalink / raw)
  To: linux-riscv, devicetree, linux-clk, linux-gpio, linux-serial
  Cc: Emil Renner Berthing, Palmer Dabbelt, Paul Walmsley, Rob Herring,
	Michael Turquette, Stephen Boyd, Thomas Gleixner, Marc Zyngier,
	Philipp Zabel, Linus Walleij, Greg Kroah-Hartman, Daniel Lezcano,
	Andy Shevchenko, Jiri Slaby, Maximilian Luz, Sagar Kadam,
	Drew Fustini, Geert Uytterhoeven, Michael Zhu, Fu Wei,
	Anup Patel, Atish Patra, Matteo Croce, linux-kernel

Add initial device tree for the StarFive JH7100 SoC.

The CPU and cache data is based on the device tree in the vendor u-boot
port.

Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
---
 arch/riscv/boot/dts/starfive/jh7100.dtsi | 228 +++++++++++++++++++++++
 1 file changed, 228 insertions(+)
 create mode 100644 arch/riscv/boot/dts/starfive/jh7100.dtsi

diff --git a/arch/riscv/boot/dts/starfive/jh7100.dtsi b/arch/riscv/boot/dts/starfive/jh7100.dtsi
new file mode 100644
index 000000000000..90ee1e7b1c24
--- /dev/null
+++ b/arch/riscv/boot/dts/starfive/jh7100.dtsi
@@ -0,0 +1,228 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/* Copyright (c) 2021 StarFive Technology Co., Ltd. */
+/* Copyright (c) 2021 Emil Renner Berthing <kernel@esmil.dk> */
+
+/dts-v1/;
+#include <dt-bindings/clock/starfive-jh7100.h>
+#include <dt-bindings/reset/starfive-jh7100.h>
+
+/ {
+	compatible = "starfive,jh7100";
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu@0 {
+			compatible = "sifive,u74-mc", "riscv";
+			reg = <0>;
+			d-cache-block-size = <64>;
+			d-cache-sets = <64>;
+			d-cache-size = <32768>;
+			d-tlb-sets = <1>;
+			d-tlb-size = <32>;
+			device_type = "cpu";
+			i-cache-block-size = <64>;
+			i-cache-sets = <64>;
+			i-cache-size = <32768>;
+			i-tlb-sets = <1>;
+			i-tlb-size = <32>;
+			mmu-type = "riscv,sv39";
+			riscv,isa = "rv64imafdc";
+			tlb-split;
+
+			cpu0_intc: interrupt-controller {
+				compatible = "riscv,cpu-intc";
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
+		};
+
+		cpu@1 {
+			compatible = "sifive,u74-mc", "riscv";
+			reg = <1>;
+			d-cache-block-size = <64>;
+			d-cache-sets = <64>;
+			d-cache-size = <32768>;
+			d-tlb-sets = <1>;
+			d-tlb-size = <32>;
+			device_type = "cpu";
+			i-cache-block-size = <64>;
+			i-cache-sets = <64>;
+			i-cache-size = <32768>;
+			i-tlb-sets = <1>;
+			i-tlb-size = <32>;
+			mmu-type = "riscv,sv39";
+			riscv,isa = "rv64imafdc";
+			tlb-split;
+
+			cpu1_intc: interrupt-controller {
+				compatible = "riscv,cpu-intc";
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
+		};
+	};
+
+	osc_sys: osc_sys {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		/* This value must be overridden by the board */
+		clock-frequency = <0>;
+	};
+
+	osc_aud: osc_aud {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		/* This value must be overridden by the board */
+		clock-frequency = <0>;
+	};
+
+	gmac_rmii_ref: gmac_rmii_ref {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		/* Should be overridden by the board when needed */
+		clock-frequency = <0>;
+	};
+
+	gmac_gr_mii_rxclk: gmac_gr_mii_rxclk {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		/* Should be overridden by the board when needed */
+		clock-frequency = <0>;
+	};
+
+	soc {
+		compatible = "simple-bus";
+		interrupt-parent = <&plic>;
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		clint: clint@2000000 {
+			compatible = "starfive,jh7100-clint", "sifive,clint0";
+			reg = <0x0 0x2000000 0x0 0x10000>;
+			interrupts-extended = <&cpu0_intc 3 &cpu0_intc 7
+					       &cpu1_intc 3 &cpu1_intc 7>;
+		};
+
+		plic: interrupt-controller@c000000 {
+			compatible = "starfive,jh7100-plic", "sifive,plic-1.0.0";
+			reg = <0x0 0xc000000 0x0 0x4000000>;
+			interrupts-extended = <&cpu0_intc 11 &cpu0_intc 9
+					       &cpu1_intc 11 &cpu1_intc 9>;
+			interrupt-controller;
+			#address-cells = <0>;
+			#interrupt-cells = <1>;
+			riscv,ndev = <127>;
+		};
+
+		clkgen: clock-controller@11800000 {
+			compatible = "starfive,jh7100-clkgen";
+			reg = <0x0 0x11800000 0x0 0x10000>;
+			clocks = <&osc_sys>, <&osc_aud>, <&gmac_rmii_ref>, <&gmac_gr_mii_rxclk>;
+			clock-names = "osc_sys", "osc_aud", "gmac_rmii_ref", "gmac_gr_mii_rxclk";
+			#clock-cells = <1>;
+		};
+
+		rstgen: reset-controller@11840000 {
+			compatible = "starfive,jh7100-reset";
+			reg = <0x0 0x11840000 0x0 0x10000>;
+			#reset-cells = <1>;
+		};
+
+		i2c0: i2c@118b0000 {
+			compatible = "snps,designware-i2c";
+			reg = <0x0 0x118b0000 0x0 0x10000>;
+			clocks = <&clkgen JH7100_CLK_I2C0_CORE>,
+				 <&clkgen JH7100_CLK_I2C0_APB>;
+			clock-names = "ref", "pclk";
+			resets = <&rstgen JH7100_RSTN_I2C0_APB>;
+			interrupts = <96>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
+		i2c1: i2c@118c0000 {
+			compatible = "snps,designware-i2c";
+			reg = <0x0 0x118c0000 0x0 0x10000>;
+			clocks = <&clkgen JH7100_CLK_I2C1_CORE>,
+				 <&clkgen JH7100_CLK_I2C1_APB>;
+			clock-names = "ref", "pclk";
+			resets = <&rstgen JH7100_RSTN_I2C1_APB>;
+			interrupts = <97>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
+		gpio: pinctrl@11910000 {
+			compatible = "starfive,jh7100-pinctrl";
+			reg = <0x0 0x11910000 0x0 0x10000>,
+			      <0x0 0x11858000 0x0 0x1000>;
+			reg-names = "gpio", "padctl";
+			clocks = <&clkgen JH7100_CLK_GPIO_APB>;
+			resets = <&rstgen JH7100_RSTN_GPIO_APB>;
+			interrupts = <32>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		uart2: serial@12430000 {
+			compatible = "starfive,jh7100-uart", "snps,dw-apb-uart";
+			reg = <0x0 0x12430000 0x0 0x10000>;
+			clocks = <&clkgen JH7100_CLK_UART2_CORE>,
+				 <&clkgen JH7100_CLK_UART2_APB>;
+			clock-names = "baudclk", "apb_pclk";
+			resets = <&rstgen JH7100_RSTN_UART2_APB>;
+			interrupts = <72>;
+			reg-io-width = <4>;
+			reg-shift = <2>;
+			status = "disabled";
+		};
+
+		uart3: serial@12440000 {
+			compatible = "starfive,jh7100-uart", "snps,dw-apb-uart";
+			reg = <0x0 0x12440000 0x0 0x10000>;
+			clocks = <&clkgen JH7100_CLK_UART3_CORE>,
+				 <&clkgen JH7100_CLK_UART3_APB>;
+			clock-names = "baudclk", "apb_pclk";
+			resets = <&rstgen JH7100_RSTN_UART3_APB>;
+			interrupts = <73>;
+			reg-io-width = <4>;
+			reg-shift = <2>;
+			status = "disabled";
+		};
+
+		i2c2: i2c@12450000 {
+			compatible = "snps,designware-i2c";
+			reg = <0x0 0x12450000 0x0 0x10000>;
+			clocks = <&clkgen JH7100_CLK_I2C2_CORE>,
+				 <&clkgen JH7100_CLK_I2C2_APB>;
+			clock-names = "ref", "pclk";
+			resets = <&rstgen JH7100_RSTN_I2C2_APB>;
+			interrupts = <74>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
+		i2c3: i2c@12460000 {
+			compatible = "snps,designware-i2c";
+			reg = <0x0 0x12460000 0x0 0x10000>;
+			clocks = <&clkgen JH7100_CLK_I2C3_CORE>,
+				 <&clkgen JH7100_CLK_I2C3_APB>;
+			clock-names = "ref", "pclk";
+			resets = <&rstgen JH7100_RSTN_I2C3_APB>;
+			interrupts = <75>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+	};
+};
-- 
2.33.1


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 143+ messages in thread

* [PATCH v2 15/16] RISC-V: Add initial StarFive JH7100 device tree
@ 2021-10-21 17:42   ` Emil Renner Berthing
  0 siblings, 0 replies; 143+ messages in thread
From: Emil Renner Berthing @ 2021-10-21 17:42 UTC (permalink / raw)
  To: linux-riscv, devicetree, linux-clk, linux-gpio, linux-serial
  Cc: Emil Renner Berthing, Palmer Dabbelt, Paul Walmsley, Rob Herring,
	Michael Turquette, Stephen Boyd, Thomas Gleixner, Marc Zyngier,
	Philipp Zabel, Linus Walleij, Greg Kroah-Hartman, Daniel Lezcano,
	Andy Shevchenko, Jiri Slaby, Maximilian Luz, Sagar Kadam,
	Drew Fustini, Geert Uytterhoeven, Michael Zhu, Fu Wei,
	Anup Patel, Atish Patra, Matteo Croce, linux-kernel

Add initial device tree for the StarFive JH7100 SoC.

The CPU and cache data is based on the device tree in the vendor u-boot
port.

Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
---
 arch/riscv/boot/dts/starfive/jh7100.dtsi | 228 +++++++++++++++++++++++
 1 file changed, 228 insertions(+)
 create mode 100644 arch/riscv/boot/dts/starfive/jh7100.dtsi

diff --git a/arch/riscv/boot/dts/starfive/jh7100.dtsi b/arch/riscv/boot/dts/starfive/jh7100.dtsi
new file mode 100644
index 000000000000..90ee1e7b1c24
--- /dev/null
+++ b/arch/riscv/boot/dts/starfive/jh7100.dtsi
@@ -0,0 +1,228 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/* Copyright (c) 2021 StarFive Technology Co., Ltd. */
+/* Copyright (c) 2021 Emil Renner Berthing <kernel@esmil.dk> */
+
+/dts-v1/;
+#include <dt-bindings/clock/starfive-jh7100.h>
+#include <dt-bindings/reset/starfive-jh7100.h>
+
+/ {
+	compatible = "starfive,jh7100";
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu@0 {
+			compatible = "sifive,u74-mc", "riscv";
+			reg = <0>;
+			d-cache-block-size = <64>;
+			d-cache-sets = <64>;
+			d-cache-size = <32768>;
+			d-tlb-sets = <1>;
+			d-tlb-size = <32>;
+			device_type = "cpu";
+			i-cache-block-size = <64>;
+			i-cache-sets = <64>;
+			i-cache-size = <32768>;
+			i-tlb-sets = <1>;
+			i-tlb-size = <32>;
+			mmu-type = "riscv,sv39";
+			riscv,isa = "rv64imafdc";
+			tlb-split;
+
+			cpu0_intc: interrupt-controller {
+				compatible = "riscv,cpu-intc";
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
+		};
+
+		cpu@1 {
+			compatible = "sifive,u74-mc", "riscv";
+			reg = <1>;
+			d-cache-block-size = <64>;
+			d-cache-sets = <64>;
+			d-cache-size = <32768>;
+			d-tlb-sets = <1>;
+			d-tlb-size = <32>;
+			device_type = "cpu";
+			i-cache-block-size = <64>;
+			i-cache-sets = <64>;
+			i-cache-size = <32768>;
+			i-tlb-sets = <1>;
+			i-tlb-size = <32>;
+			mmu-type = "riscv,sv39";
+			riscv,isa = "rv64imafdc";
+			tlb-split;
+
+			cpu1_intc: interrupt-controller {
+				compatible = "riscv,cpu-intc";
+				interrupt-controller;
+				#interrupt-cells = <1>;
+			};
+		};
+	};
+
+	osc_sys: osc_sys {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		/* This value must be overridden by the board */
+		clock-frequency = <0>;
+	};
+
+	osc_aud: osc_aud {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		/* This value must be overridden by the board */
+		clock-frequency = <0>;
+	};
+
+	gmac_rmii_ref: gmac_rmii_ref {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		/* Should be overridden by the board when needed */
+		clock-frequency = <0>;
+	};
+
+	gmac_gr_mii_rxclk: gmac_gr_mii_rxclk {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		/* Should be overridden by the board when needed */
+		clock-frequency = <0>;
+	};
+
+	soc {
+		compatible = "simple-bus";
+		interrupt-parent = <&plic>;
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		clint: clint@2000000 {
+			compatible = "starfive,jh7100-clint", "sifive,clint0";
+			reg = <0x0 0x2000000 0x0 0x10000>;
+			interrupts-extended = <&cpu0_intc 3 &cpu0_intc 7
+					       &cpu1_intc 3 &cpu1_intc 7>;
+		};
+
+		plic: interrupt-controller@c000000 {
+			compatible = "starfive,jh7100-plic", "sifive,plic-1.0.0";
+			reg = <0x0 0xc000000 0x0 0x4000000>;
+			interrupts-extended = <&cpu0_intc 11 &cpu0_intc 9
+					       &cpu1_intc 11 &cpu1_intc 9>;
+			interrupt-controller;
+			#address-cells = <0>;
+			#interrupt-cells = <1>;
+			riscv,ndev = <127>;
+		};
+
+		clkgen: clock-controller@11800000 {
+			compatible = "starfive,jh7100-clkgen";
+			reg = <0x0 0x11800000 0x0 0x10000>;
+			clocks = <&osc_sys>, <&osc_aud>, <&gmac_rmii_ref>, <&gmac_gr_mii_rxclk>;
+			clock-names = "osc_sys", "osc_aud", "gmac_rmii_ref", "gmac_gr_mii_rxclk";
+			#clock-cells = <1>;
+		};
+
+		rstgen: reset-controller@11840000 {
+			compatible = "starfive,jh7100-reset";
+			reg = <0x0 0x11840000 0x0 0x10000>;
+			#reset-cells = <1>;
+		};
+
+		i2c0: i2c@118b0000 {
+			compatible = "snps,designware-i2c";
+			reg = <0x0 0x118b0000 0x0 0x10000>;
+			clocks = <&clkgen JH7100_CLK_I2C0_CORE>,
+				 <&clkgen JH7100_CLK_I2C0_APB>;
+			clock-names = "ref", "pclk";
+			resets = <&rstgen JH7100_RSTN_I2C0_APB>;
+			interrupts = <96>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
+		i2c1: i2c@118c0000 {
+			compatible = "snps,designware-i2c";
+			reg = <0x0 0x118c0000 0x0 0x10000>;
+			clocks = <&clkgen JH7100_CLK_I2C1_CORE>,
+				 <&clkgen JH7100_CLK_I2C1_APB>;
+			clock-names = "ref", "pclk";
+			resets = <&rstgen JH7100_RSTN_I2C1_APB>;
+			interrupts = <97>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
+		gpio: pinctrl@11910000 {
+			compatible = "starfive,jh7100-pinctrl";
+			reg = <0x0 0x11910000 0x0 0x10000>,
+			      <0x0 0x11858000 0x0 0x1000>;
+			reg-names = "gpio", "padctl";
+			clocks = <&clkgen JH7100_CLK_GPIO_APB>;
+			resets = <&rstgen JH7100_RSTN_GPIO_APB>;
+			interrupts = <32>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		uart2: serial@12430000 {
+			compatible = "starfive,jh7100-uart", "snps,dw-apb-uart";
+			reg = <0x0 0x12430000 0x0 0x10000>;
+			clocks = <&clkgen JH7100_CLK_UART2_CORE>,
+				 <&clkgen JH7100_CLK_UART2_APB>;
+			clock-names = "baudclk", "apb_pclk";
+			resets = <&rstgen JH7100_RSTN_UART2_APB>;
+			interrupts = <72>;
+			reg-io-width = <4>;
+			reg-shift = <2>;
+			status = "disabled";
+		};
+
+		uart3: serial@12440000 {
+			compatible = "starfive,jh7100-uart", "snps,dw-apb-uart";
+			reg = <0x0 0x12440000 0x0 0x10000>;
+			clocks = <&clkgen JH7100_CLK_UART3_CORE>,
+				 <&clkgen JH7100_CLK_UART3_APB>;
+			clock-names = "baudclk", "apb_pclk";
+			resets = <&rstgen JH7100_RSTN_UART3_APB>;
+			interrupts = <73>;
+			reg-io-width = <4>;
+			reg-shift = <2>;
+			status = "disabled";
+		};
+
+		i2c2: i2c@12450000 {
+			compatible = "snps,designware-i2c";
+			reg = <0x0 0x12450000 0x0 0x10000>;
+			clocks = <&clkgen JH7100_CLK_I2C2_CORE>,
+				 <&clkgen JH7100_CLK_I2C2_APB>;
+			clock-names = "ref", "pclk";
+			resets = <&rstgen JH7100_RSTN_I2C2_APB>;
+			interrupts = <74>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
+		i2c3: i2c@12460000 {
+			compatible = "snps,designware-i2c";
+			reg = <0x0 0x12460000 0x0 0x10000>;
+			clocks = <&clkgen JH7100_CLK_I2C3_CORE>,
+				 <&clkgen JH7100_CLK_I2C3_APB>;
+			clock-names = "ref", "pclk";
+			resets = <&rstgen JH7100_RSTN_I2C3_APB>;
+			interrupts = <75>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+	};
+};
-- 
2.33.1


^ permalink raw reply related	[flat|nested] 143+ messages in thread

* [PATCH v2 16/16] RISC-V: Add BeagleV Starlight Beta device tree
  2021-10-21 17:42 ` Emil Renner Berthing
@ 2021-10-21 17:42   ` Emil Renner Berthing
  -1 siblings, 0 replies; 143+ messages in thread
From: Emil Renner Berthing @ 2021-10-21 17:42 UTC (permalink / raw)
  To: linux-riscv, devicetree, linux-clk, linux-gpio, linux-serial
  Cc: Emil Renner Berthing, Palmer Dabbelt, Paul Walmsley, Rob Herring,
	Michael Turquette, Stephen Boyd, Thomas Gleixner, Marc Zyngier,
	Philipp Zabel, Linus Walleij, Greg Kroah-Hartman, Daniel Lezcano,
	Andy Shevchenko, Jiri Slaby, Maximilian Luz, Sagar Kadam,
	Drew Fustini, Geert Uytterhoeven, Michael Zhu, Fu Wei,
	Anup Patel, Atish Patra, Matteo Croce, linux-kernel

Add initial device tree for the BeagleV Starlight Beta board. About 300
of these boards were sent out as part of a now cancelled BeagleBoard.org
project.

I2C timing data is based on the device tree in the vendor u-boot port.
Heartbeat LED added by Geert.

Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
Co-developed-by: Geert Uytterhoeven <geert@linux-m68k.org>
Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
---
 arch/riscv/boot/dts/Makefile                  |   1 +
 arch/riscv/boot/dts/starfive/Makefile         |   2 +
 .../dts/starfive/jh7100-beaglev-starlight.dts | 162 ++++++++++++++++++
 3 files changed, 165 insertions(+)
 create mode 100644 arch/riscv/boot/dts/starfive/Makefile
 create mode 100644 arch/riscv/boot/dts/starfive/jh7100-beaglev-starlight.dts

diff --git a/arch/riscv/boot/dts/Makefile b/arch/riscv/boot/dts/Makefile
index fe996b88319e..ff174996cdfd 100644
--- a/arch/riscv/boot/dts/Makefile
+++ b/arch/riscv/boot/dts/Makefile
@@ -1,5 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0
 subdir-y += sifive
+subdir-y += starfive
 subdir-$(CONFIG_SOC_CANAAN_K210_DTB_BUILTIN) += canaan
 subdir-y += microchip
 
diff --git a/arch/riscv/boot/dts/starfive/Makefile b/arch/riscv/boot/dts/starfive/Makefile
new file mode 100644
index 000000000000..0ea1bc15ab30
--- /dev/null
+++ b/arch/riscv/boot/dts/starfive/Makefile
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0
+dtb-$(CONFIG_SOC_STARFIVE) += jh7100-beaglev-starlight.dtb
diff --git a/arch/riscv/boot/dts/starfive/jh7100-beaglev-starlight.dts b/arch/riscv/boot/dts/starfive/jh7100-beaglev-starlight.dts
new file mode 100644
index 000000000000..d30d42d299c6
--- /dev/null
+++ b/arch/riscv/boot/dts/starfive/jh7100-beaglev-starlight.dts
@@ -0,0 +1,162 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/* Copyright (C) 2021 StarFive Technology Co., Ltd. */
+/* Copyright (C) 2021 Emil Renner Berthing <kernel@esmil.dk> */
+
+/dts-v1/;
+#include "jh7100.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/leds/common.h>
+#include <dt-bindings/pinctrl/pinctrl-starfive.h>
+
+/ {
+	model = "BeagleV Starlight Beta";
+	compatible = "beagle,beaglev-starlight-jh7100-r0", "starfive,jh7100";
+
+	aliases {
+		serial0 = &uart3;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	cpus {
+		timebase-frequency = <6250000>;
+	};
+
+	memory@80000000 {
+		device_type = "memory";
+		reg = <0x0 0x80000000 0x2 0x0>;
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		led-ack {
+			gpios = <&gpio 43 GPIO_ACTIVE_HIGH>;
+			color = <LED_COLOR_ID_GREEN>;
+			function = LED_FUNCTION_HEARTBEAT;
+			linux,default-trigger = "heartbeat";
+			label = "ack";
+		};
+	};
+};
+
+&gpio {
+	i2c0_pins: i2c0-0 {
+		i2c-pins {
+			pinmux = <GPIOMUX(62, GPO_LOW,
+				  GPO_I2C0_PAD_SCK_OEN,
+				  GPI_I2C0_PAD_SCK_IN)>,
+				 <GPIOMUX(61, GPO_LOW,
+				  GPO_I2C0_PAD_SDA_OEN,
+				  GPI_I2C0_PAD_SDA_IN)>;
+			bias-disable; /* external pull-up */
+			input-enable;
+			input-schmitt-enable;
+		};
+	};
+
+	i2c1_pins: i2c1-0 {
+		i2c-pins {
+			pinmux = <GPIOMUX(47, GPO_LOW,
+				  GPO_I2C1_PAD_SCK_OEN,
+				  GPI_I2C1_PAD_SCK_IN)>,
+				 <GPIOMUX(48, GPO_LOW,
+				  GPO_I2C1_PAD_SDA_OEN,
+				  GPI_I2C1_PAD_SDA_IN)>;
+			bias-pull-up;
+			input-enable;
+			input-schmitt-enable;
+		};
+	};
+
+	i2c2_pins: i2c2-0 {
+		i2c-pins {
+			pinmux = <GPIOMUX(60, GPO_LOW,
+				  GPO_I2C2_PAD_SCK_OEN,
+				  GPI_I2C2_PAD_SCK_IN)>,
+				 <GPIOMUX(59, GPO_LOW,
+				  GPO_I2C2_PAD_SDA_OEN,
+				  GPI_I2C2_PAD_SDA_IN)>;
+			bias-disable; /* external pull-up */
+			input-enable;
+			input-schmitt-enable;
+		};
+	};
+
+	uart3_pins: uart3-0 {
+		rx-pin {
+			pinmux = <GPIOMUX(13, GPO_LOW, GPO_DISABLE,
+				  GPI_UART3_PAD_SIN)>;
+			bias-pull-up;
+			drive-strength = <14>;
+			input-enable;
+			input-schmitt-enable;
+			slew-rate = <0>;
+		};
+		tx-pin {
+			pinmux = <GPIOMUX(14, GPO_UART3_PAD_SOUT,
+				  GPO_ENABLE, GPI_NONE)>;
+			bias-disable;
+			drive-strength = <35>;
+			input-disable;
+			input-schmitt-disable;
+			slew-rate = <0>;
+		};
+	};
+};
+
+&i2c0 {
+	clock-frequency = <100000>;
+	i2c-sda-hold-time-ns = <300>;
+	i2c-sda-falling-time-ns = <500>;
+	i2c-scl-falling-time-ns = <500>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c0_pins>;
+	status = "okay";
+
+	pmic@5e {
+		compatible = "ti,tps65086";
+		reg = <0x5e>;
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		regulators {
+		};
+	};
+};
+
+&i2c1 {
+	clock-frequency = <400000>;
+	i2c-sda-hold-time-ns = <300>;
+	i2c-sda-falling-time-ns = <100>;
+	i2c-scl-falling-time-ns = <100>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c1_pins>;
+	status = "okay";
+};
+
+&i2c2 {
+	clock-frequency = <100000>;
+	i2c-sda-hold-time-ns = <300>;
+	i2c-sda-falling-time-ns = <500>;
+	i2c-scl-falling-time-ns = <500>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c2_pins>;
+	status = "okay";
+};
+
+&osc_sys {
+	clock-frequency = <25000000>;
+};
+
+&osc_aud {
+	clock-frequency = <27000000>;
+};
+
+&uart3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart3_pins>;
+	status = "okay";
+};
-- 
2.33.1


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 143+ messages in thread

* [PATCH v2 16/16] RISC-V: Add BeagleV Starlight Beta device tree
@ 2021-10-21 17:42   ` Emil Renner Berthing
  0 siblings, 0 replies; 143+ messages in thread
From: Emil Renner Berthing @ 2021-10-21 17:42 UTC (permalink / raw)
  To: linux-riscv, devicetree, linux-clk, linux-gpio, linux-serial
  Cc: Emil Renner Berthing, Palmer Dabbelt, Paul Walmsley, Rob Herring,
	Michael Turquette, Stephen Boyd, Thomas Gleixner, Marc Zyngier,
	Philipp Zabel, Linus Walleij, Greg Kroah-Hartman, Daniel Lezcano,
	Andy Shevchenko, Jiri Slaby, Maximilian Luz, Sagar Kadam,
	Drew Fustini, Geert Uytterhoeven, Michael Zhu, Fu Wei,
	Anup Patel, Atish Patra, Matteo Croce, linux-kernel

Add initial device tree for the BeagleV Starlight Beta board. About 300
of these boards were sent out as part of a now cancelled BeagleBoard.org
project.

I2C timing data is based on the device tree in the vendor u-boot port.
Heartbeat LED added by Geert.

Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
Co-developed-by: Geert Uytterhoeven <geert@linux-m68k.org>
Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
---
 arch/riscv/boot/dts/Makefile                  |   1 +
 arch/riscv/boot/dts/starfive/Makefile         |   2 +
 .../dts/starfive/jh7100-beaglev-starlight.dts | 162 ++++++++++++++++++
 3 files changed, 165 insertions(+)
 create mode 100644 arch/riscv/boot/dts/starfive/Makefile
 create mode 100644 arch/riscv/boot/dts/starfive/jh7100-beaglev-starlight.dts

diff --git a/arch/riscv/boot/dts/Makefile b/arch/riscv/boot/dts/Makefile
index fe996b88319e..ff174996cdfd 100644
--- a/arch/riscv/boot/dts/Makefile
+++ b/arch/riscv/boot/dts/Makefile
@@ -1,5 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0
 subdir-y += sifive
+subdir-y += starfive
 subdir-$(CONFIG_SOC_CANAAN_K210_DTB_BUILTIN) += canaan
 subdir-y += microchip
 
diff --git a/arch/riscv/boot/dts/starfive/Makefile b/arch/riscv/boot/dts/starfive/Makefile
new file mode 100644
index 000000000000..0ea1bc15ab30
--- /dev/null
+++ b/arch/riscv/boot/dts/starfive/Makefile
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0
+dtb-$(CONFIG_SOC_STARFIVE) += jh7100-beaglev-starlight.dtb
diff --git a/arch/riscv/boot/dts/starfive/jh7100-beaglev-starlight.dts b/arch/riscv/boot/dts/starfive/jh7100-beaglev-starlight.dts
new file mode 100644
index 000000000000..d30d42d299c6
--- /dev/null
+++ b/arch/riscv/boot/dts/starfive/jh7100-beaglev-starlight.dts
@@ -0,0 +1,162 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/* Copyright (C) 2021 StarFive Technology Co., Ltd. */
+/* Copyright (C) 2021 Emil Renner Berthing <kernel@esmil.dk> */
+
+/dts-v1/;
+#include "jh7100.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/leds/common.h>
+#include <dt-bindings/pinctrl/pinctrl-starfive.h>
+
+/ {
+	model = "BeagleV Starlight Beta";
+	compatible = "beagle,beaglev-starlight-jh7100-r0", "starfive,jh7100";
+
+	aliases {
+		serial0 = &uart3;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	cpus {
+		timebase-frequency = <6250000>;
+	};
+
+	memory@80000000 {
+		device_type = "memory";
+		reg = <0x0 0x80000000 0x2 0x0>;
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		led-ack {
+			gpios = <&gpio 43 GPIO_ACTIVE_HIGH>;
+			color = <LED_COLOR_ID_GREEN>;
+			function = LED_FUNCTION_HEARTBEAT;
+			linux,default-trigger = "heartbeat";
+			label = "ack";
+		};
+	};
+};
+
+&gpio {
+	i2c0_pins: i2c0-0 {
+		i2c-pins {
+			pinmux = <GPIOMUX(62, GPO_LOW,
+				  GPO_I2C0_PAD_SCK_OEN,
+				  GPI_I2C0_PAD_SCK_IN)>,
+				 <GPIOMUX(61, GPO_LOW,
+				  GPO_I2C0_PAD_SDA_OEN,
+				  GPI_I2C0_PAD_SDA_IN)>;
+			bias-disable; /* external pull-up */
+			input-enable;
+			input-schmitt-enable;
+		};
+	};
+
+	i2c1_pins: i2c1-0 {
+		i2c-pins {
+			pinmux = <GPIOMUX(47, GPO_LOW,
+				  GPO_I2C1_PAD_SCK_OEN,
+				  GPI_I2C1_PAD_SCK_IN)>,
+				 <GPIOMUX(48, GPO_LOW,
+				  GPO_I2C1_PAD_SDA_OEN,
+				  GPI_I2C1_PAD_SDA_IN)>;
+			bias-pull-up;
+			input-enable;
+			input-schmitt-enable;
+		};
+	};
+
+	i2c2_pins: i2c2-0 {
+		i2c-pins {
+			pinmux = <GPIOMUX(60, GPO_LOW,
+				  GPO_I2C2_PAD_SCK_OEN,
+				  GPI_I2C2_PAD_SCK_IN)>,
+				 <GPIOMUX(59, GPO_LOW,
+				  GPO_I2C2_PAD_SDA_OEN,
+				  GPI_I2C2_PAD_SDA_IN)>;
+			bias-disable; /* external pull-up */
+			input-enable;
+			input-schmitt-enable;
+		};
+	};
+
+	uart3_pins: uart3-0 {
+		rx-pin {
+			pinmux = <GPIOMUX(13, GPO_LOW, GPO_DISABLE,
+				  GPI_UART3_PAD_SIN)>;
+			bias-pull-up;
+			drive-strength = <14>;
+			input-enable;
+			input-schmitt-enable;
+			slew-rate = <0>;
+		};
+		tx-pin {
+			pinmux = <GPIOMUX(14, GPO_UART3_PAD_SOUT,
+				  GPO_ENABLE, GPI_NONE)>;
+			bias-disable;
+			drive-strength = <35>;
+			input-disable;
+			input-schmitt-disable;
+			slew-rate = <0>;
+		};
+	};
+};
+
+&i2c0 {
+	clock-frequency = <100000>;
+	i2c-sda-hold-time-ns = <300>;
+	i2c-sda-falling-time-ns = <500>;
+	i2c-scl-falling-time-ns = <500>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c0_pins>;
+	status = "okay";
+
+	pmic@5e {
+		compatible = "ti,tps65086";
+		reg = <0x5e>;
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		regulators {
+		};
+	};
+};
+
+&i2c1 {
+	clock-frequency = <400000>;
+	i2c-sda-hold-time-ns = <300>;
+	i2c-sda-falling-time-ns = <100>;
+	i2c-scl-falling-time-ns = <100>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c1_pins>;
+	status = "okay";
+};
+
+&i2c2 {
+	clock-frequency = <100000>;
+	i2c-sda-hold-time-ns = <300>;
+	i2c-sda-falling-time-ns = <500>;
+	i2c-scl-falling-time-ns = <500>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c2_pins>;
+	status = "okay";
+};
+
+&osc_sys {
+	clock-frequency = <25000000>;
+};
+
+&osc_aud {
+	clock-frequency = <27000000>;
+};
+
+&uart3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart3_pins>;
+	status = "okay";
+};
-- 
2.33.1


^ permalink raw reply related	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 12/16] pinctrl: starfive: Add pinctrl driver for StarFive SoCs
  2021-10-21 17:42   ` Emil Renner Berthing
@ 2021-10-21 19:01     ` Drew Fustini
  -1 siblings, 0 replies; 143+ messages in thread
From: Drew Fustini @ 2021-10-21 19:01 UTC (permalink / raw)
  To: Emil Renner Berthing
  Cc: linux-riscv, devicetree, linux-clk, linux-gpio, linux-serial,
	Palmer Dabbelt, Paul Walmsley, Rob Herring, Michael Turquette,
	Stephen Boyd, Thomas Gleixner, Marc Zyngier, Philipp Zabel,
	Linus Walleij, Greg Kroah-Hartman, Daniel Lezcano,
	Andy Shevchenko, Jiri Slaby, Maximilian Luz, Sagar Kadam,
	Drew Fustini, Geert Uytterhoeven, Michael Zhu, Fu Wei,
	Anup Patel, Atish Patra, Matteo Croce, linux-kernel, Huan Feng

On Thu, Oct 21, 2021 at 07:42:19PM +0200, Emil Renner Berthing wrote:
> Add a combined pinctrl and GPIO driver for the StarFive JH7100 SoC.
> 
> For each "GPIO" there are two registers for configuring the output and
> output enable signals which may come from other peripherals. Among these
> are two special signals that are constant 0 and constant 1 respectively.
> Controlling the GPIOs from software is done by choosing one of these
> signals. In other words the same registers are used for both pinmuxing
> and controlling the GPIOs, which makes it easier to combine the pinctrl
> and GPIO driver in one.
> 
> I wrote the pinconf and pinmux parts, but the GPIO part of the code is
> based on the GPIO driver in the vendor tree written by Huan Feng with
> cleanups and fixes by Drew and me.
> 
> Datasheet: https://github.com/starfive-tech/JH7100_Docs/blob/main/JH7100%20Data%20Sheet%20V01.01.04-EN%20(4-21-2021).pdf
> Co-developed-by: Huan Feng <huan.feng@starfivetech.com>
> Signed-off-by: Huan Feng <huan.feng@starfivetech.com>
> Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
> Co-developed-by: Drew Fustini <drew@beagleboard.org>
> Signed-off-by: Drew Fustini <drew@beagleboard.org>
> ---
>  MAINTAINERS                        |    8 +
>  drivers/pinctrl/Kconfig            |   16 +
>  drivers/pinctrl/Makefile           |    1 +
>  drivers/pinctrl/pinctrl-starfive.c | 1387 ++++++++++++++++++++++++++++
>  4 files changed, 1412 insertions(+)
>  create mode 100644 drivers/pinctrl/pinctrl-starfive.c
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index b3f3a29fc91f..1f122f93a5a5 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -17855,6 +17855,14 @@ F:	Documentation/devicetree/bindings/clock/starfive,jh7100-clkgen.yaml
>  F:	drivers/clk/starfive/clk-starfive-jh7100.c
>  F:	include/dt-bindings/clock/starfive-jh7100.h
>  
> +STARFIVE JH7100 PINCTRL DRIVER
> +M:	Emil Renner Berthing <kernel@esmil.dk>
> +L:	linux-gpio@vger.kernel.org
> +S:	Maintained
> +F:	Documentation/devicetree/bindings/pinctrl/starfive,jh7100-pinctrl.yaml
> +F:	drivers/pinctrl/pinctrl-starfive.c
> +F:	include/dt-bindings/pinctrl/pinctrl-starfive.h
> +
>  STARFIVE JH7100 RESET CONTROLLER DRIVER
>  M:	Emil Renner Berthing <kernel@esmil.dk>
>  S:	Maintained
> diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
> index 31921108e456..98caa94acf9e 100644
> --- a/drivers/pinctrl/Kconfig
> +++ b/drivers/pinctrl/Kconfig
> @@ -265,6 +265,22 @@ config PINCTRL_ST
>  	select PINCONF
>  	select GPIOLIB_IRQCHIP
>  
> +config PINCTRL_STARFIVE
> +	tristate "Pinctrl and GPIO driver for the StarFive JH7100 SoC"
> +	depends on SOC_STARFIVE || COMPILE_TEST
> +	default SOC_STARFIVE
> +	select GENERIC_PINCTRL_GROUPS
> +	select GENERIC_PINMUX_FUNCTIONS
> +	select GENERIC_PINCONF
> +	select GPIOLIB
> +	select GPIOLIB_IRQCHIP
> +	select OF_GPIO
> +	help
> +	  Say yes here to support pin control on the StarFive JH7100 SoC.
> +	  This also provides an interface to the GPIO pins not used by other
> +	  peripherals supporting inputs, outputs, configuring pull-up/pull-down
> +	  and interrupts on input changes.
> +
>  config PINCTRL_STMFX
>  	tristate "STMicroelectronics STMFX GPIO expander pinctrl driver"
>  	depends on I2C
> diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
> index 200073bcc2c1..9c258047f11c 100644
> --- a/drivers/pinctrl/Makefile
> +++ b/drivers/pinctrl/Makefile
> @@ -38,6 +38,7 @@ obj-$(CONFIG_PINCTRL_LANTIQ)	+= pinctrl-lantiq.o
>  obj-$(CONFIG_PINCTRL_LPC18XX)	+= pinctrl-lpc18xx.o
>  obj-$(CONFIG_PINCTRL_TB10X)	+= pinctrl-tb10x.o
>  obj-$(CONFIG_PINCTRL_ST) 	+= pinctrl-st.o
> +obj-$(CONFIG_PINCTRL_STARFIVE)	+= pinctrl-starfive.o
>  obj-$(CONFIG_PINCTRL_STMFX) 	+= pinctrl-stmfx.o
>  obj-$(CONFIG_PINCTRL_ZYNQ)	+= pinctrl-zynq.o
>  obj-$(CONFIG_PINCTRL_ZYNQMP)	+= pinctrl-zynqmp.o
> diff --git a/drivers/pinctrl/pinctrl-starfive.c b/drivers/pinctrl/pinctrl-starfive.c
> new file mode 100644
> index 000000000000..ca99fad883e6
> --- /dev/null
> +++ b/drivers/pinctrl/pinctrl-starfive.c
> @@ -0,0 +1,1387 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Pinctrl / GPIO driver for StarFive JH7100 SoC
> + *
> + * Copyright (C) 2020 Shanghai StarFive Technology Co., Ltd.
> + * Copyright (C) 2021 Emil Renner Berthing <kernel@esmil.dk>
> + */
> +
> +#include <linux/bits.h>
> +#include <linux/clk.h>
> +#include <linux/gpio/driver.h>
> +#include <linux/io.h>
> +#include <linux/mod_devicetable.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/platform_device.h>
> +#include <linux/reset.h>
> +#include <linux/spinlock.h>
> +
> +#include <linux/pinctrl/pinctrl.h>
> +#include <linux/pinctrl/pinmux.h>
> +
> +#include <dt-bindings/pinctrl/pinctrl-starfive.h>
> +
> +#include "core.h"
> +#include "pinctrl-utils.h"
> +#include "pinmux.h"
> +#include "pinconf.h"
> +
> +#define DRIVER_NAME "pinctrl-starfive"
> +
> +/*
> + * Refer to Section 12. GPIO Registers in the JH7100 data sheet:
> + * https://github.com/starfive-tech/JH7100_Docs
> + */
> +#define NR_GPIOS	64
> +
> +/*
> + * Global enable for GPIO interrupts. If bit 0 is set to 1 the GPIO interrupts
> + * are enabled. If set to 0 the GPIO interrupts are disabled.
> + */
> +#define GPIOEN		0x000
> +
> +/*
> + * The following 32-bit registers come in pairs, but only the offset of the
> + * first register is defined. The first controls (interrupts for) GPIO 0-31 and
> + * the second GPIO 32-63.
> + */
> +
> +/*
> + * Interrupt Type. If set to 1 the interrupt is edge-triggered. If set to 0 the
> + * interrupt is level-triggered.
> + */
> +#define GPIOIS		0x010
> +
> +/*
> + * Edge-Trigger Interrupt Type.  If set to 1 the interrupt gets triggered on
> + * both positive and negative edges. If set to 0 the interrupt is triggered by a
> + * single edge.
> + */
> +#define GPIOIBE		0x018
> +
> +/*
> + * Interrupt Trigger Polarity. If set to 1 the interrupt is triggered on a
> + * rising edge (edge-triggered) or high level (level-triggered). If set to 0 the
> + * interrupt is triggered on a falling edge (edge-triggered) or low level
> + * (level-triggered).
> + */
> +#define GPIOIEV		0x020
> +
> +/*
> + * Interrupt Mask. If set to 1 the interrupt is disabled (masked). If set to 0
> + * the interrupt is enabled (unmasked).
> + */
> +#define GPIOIE		0x028

It bothered me that the datasheet used the term GPIOIE for the interrupt
mask register. I had used a more verbose #define name because I worried
someone reading GPIOIE in functions might mistake it for an interrupt
enable register. This happened to me when I was originally working with
the gpio driver.

However I suppose the best solution would have been to get the datasheet
updated as I can see how it is best to have #define names in the driver
match the datasheet.

> +
> +/*
> + * Clear Edge-Triggered Interrupts. Write a 1 to clear the edge-triggered
> + * interrupt.
> + */
> +#define GPIOIC		0x030
> +
> +/*
> + * Edge-Triggered Interrupt Status. A 1 means the configured edge was detected.
> + */
> +#define GPIORIS		0x038
> +
> +/*
> + * Interrupt Status after Masking. A 1 means the configured edge or level was
> + * detected and not masked.
> + */
> +#define GPIOMIS		0x040
> +
> +/*
> + * Data Value. Dynamically reflects the value of the GPIO pin. If 1 the pin is
> + * a digital 1 and if 0 the pin is a digital 0.
> + */
> +#define GPIODIN		0x048
> +
> +/*
> + * From the data sheet section 12.2, there are 64 32-bit output data registers
> + * and 64 output enable registers. Output data and output enable registers for
> + * a given GPIO are contiguous. Eg. GPO0_DOUT_CFG is 0x50 and GPO0_DOEN_CFG is
> + * 0x54 while GPO1_DOUT_CFG is 0x58 and GPO1_DOEN_CFG is 0x5c.  The stride
> + * between GPIO registers is effectively 8, thus: GPOn_DOUT_CFG is 0x50 + 8n
> + * and GPOn_DOEN_CFG is 0x54 + 8n.
> + */
> +#define GPON_DOUT_CFG	0x050
> +#define GPON_DOEN_CFG	0x054
> +
> +/*
> + * From Section 12.3, there are 75 input signal configuration registers which
> + * are 4 bytes wide starting with GPI_CPU_JTAG_TCK_CFG at 0x250 and ending with
> + * GPI_USB_OVER_CURRENT_CFG 0x378
> + */
> +#define GPI_CFG_OFFSET	0x250
> +
> +/*
> + * Pad Control Bits. There are 16 pad control bits for each pin located in 103
> + * 32-bit registers controlling PAD_GPIO[0] to PAD_GPIO[63] followed by
> + * PAD_FUNC_SHARE[0] to PAD_FUNC_SHARE[141]. Odd numbered pins use the upper 16
> + * bit of each register.
> + */
> +#define PAD_SLEW_RATE_MASK		GENMASK(11, 9)
> +#define PAD_SLEW_RATE_POS		9
> +#define PAD_BIAS_STRONG_PULL_UP		BIT(8)
> +#define PAD_INPUT_ENABLE		BIT(7)
> +#define PAD_INPUT_SCHMITT_ENABLE	BIT(6)
> +#define PAD_BIAS_DISABLE		BIT(5)
> +#define PAD_BIAS_PULL_DOWN		BIT(4)
> +#define PAD_BIAS_MASK			(PAD_BIAS_STRONG_PULL_UP | \
> +					 PAD_BIAS_DISABLE | \
> +					 PAD_BIAS_PULL_DOWN)
> +#define PAD_DRIVE_STRENGTH_MASK		GENMASK(3, 0)
> +#define PAD_DRIVE_STRENGTH_POS		0
> +
> +/*
> + * From Section 11, the IO_PADSHARE_SEL register can be programmed to select
> + * one of seven pre-defined multiplexed signal groups on PAD_FUNC_SHARE and
> + * PAD_GPIO pads. This is a global setting.
> + */
> +#define IO_PADSHARE_SEL			0x1a0
> +
> +/*
> + * This just needs to be some number such that when
> + * sfp->gpio.pin_base = PAD_INVALID_GPIO then
> + * starfive_pin_to_gpio(sfp, validpin) is never a valid GPIO number.
> + * That is it should underflow and return something >= NR_GPIOS.
> + */
> +#define PAD_INVALID_GPIO		0x10000
> +
> +/*
> + * The packed pinmux values from the device tree look like this:
> + *
> + *  | 31 - 24 | 23 - 16 | 15 - 8 |     7    |     6    |  5 - 0  |
> + *  |  dout   |  doen   |  din   | dout rev | doen rev | gpio nr |
> + *
> + * ..but the GPOn_DOUT_CFG and GPOn_DOEN_CFG registers look like this:
> + *
> + *  |      31       | 30 - 8 |   7 - 0   |
> + *  | dout/doen rev | unused | dout/doen |
> + */
> +static unsigned int starfive_pinmux_to_gpio(u32 v)
> +{
> +	return v & (NR_GPIOS - 1);
> +}
> +
> +static u32 starfive_pinmux_to_dout(u32 v)
> +{
> +	return ((v & BIT(7)) << (31 - 7)) | ((v >> 24) & GENMASK(7, 0));
> +}
> +
> +static u32 starfive_pinmux_to_doen(u32 v)
> +{
> +	return ((v & BIT(6)) << (31 - 6)) | ((v >> 16) & GENMASK(7, 0));
> +}
> +
> +static u32 starfive_pinmux_to_din(u32 v)
> +{
> +	return (v >> 8) & GENMASK(7, 0);
> +}
> +
> +/*
> + * The maximum GPIO output current depends on the chosen drive strength:
> + *
> + *  DS:   0     1     2     3     4     5     6     7
> + *  mA:  14.2  21.2  28.2  35.2  42.2  49.1  56.0  62.8
> + *
> + * After rounding that is 7*DS + 14 mA
> + */
> +static u32 starfive_drive_strength_to_max_mA(u16 ds)
> +{
> +	return 7 * ds + 14;
> +}
> +
> +static u16 starfive_drive_strength_from_max_mA(u32 i)
> +{
> +	return (clamp(i, 14U, 63U) - 14) / 7;
> +}
> +
> +struct starfive_pinctrl {
> +	struct gpio_chip gc;
> +	struct pinctrl_gpio_range gpios;
> +	raw_spinlock_t lock;
> +	void __iomem *base;
> +	void __iomem *padctl;
> +	struct pinctrl_dev *pctl;
> +};
> +
> +static struct device *starfive_dev(const struct starfive_pinctrl *sfp)
> +{
> +	return sfp->gc.parent;
> +}
> +
> +static unsigned int starfive_pin_to_gpio(const struct starfive_pinctrl *sfp,
> +					 unsigned int pin)
> +{
> +	return pin - sfp->gpios.pin_base;
> +}
> +
> +static unsigned int starfive_gpio_to_pin(const struct starfive_pinctrl *sfp,
> +					 unsigned int gpio)
> +{
> +	return sfp->gpios.pin_base + gpio;
> +}
> +
> +static struct starfive_pinctrl *starfive_from_gc(struct gpio_chip *gc)
> +{
> +	return container_of(gc, struct starfive_pinctrl, gc);
> +}
> +
> +static struct starfive_pinctrl *starfive_from_irq_data(struct irq_data *d)
> +{
> +	return starfive_from_gc(irq_data_get_irq_chip_data(d));
> +}
> +
> +static struct starfive_pinctrl *starfive_from_irq_desc(struct irq_desc *desc)
> +{
> +	return starfive_from_gc(irq_desc_get_handler_data(desc));
> +}
> +
> +static const struct pinctrl_pin_desc starfive_pins[] = {
> +	PINCTRL_PIN(PAD_GPIO(0), "GPIO[0]"),
> +	PINCTRL_PIN(PAD_GPIO(1), "GPIO[1]"),
> +	PINCTRL_PIN(PAD_GPIO(2), "GPIO[2]"),
> +	PINCTRL_PIN(PAD_GPIO(3), "GPIO[3]"),
> +	PINCTRL_PIN(PAD_GPIO(4), "GPIO[4]"),
> +	PINCTRL_PIN(PAD_GPIO(5), "GPIO[5]"),
> +	PINCTRL_PIN(PAD_GPIO(6), "GPIO[6]"),
> +	PINCTRL_PIN(PAD_GPIO(7), "GPIO[7]"),
> +	PINCTRL_PIN(PAD_GPIO(8), "GPIO[8]"),
> +	PINCTRL_PIN(PAD_GPIO(9), "GPIO[9]"),
> +	PINCTRL_PIN(PAD_GPIO(10), "GPIO[10]"),
> +	PINCTRL_PIN(PAD_GPIO(11), "GPIO[11]"),
> +	PINCTRL_PIN(PAD_GPIO(12), "GPIO[12]"),
> +	PINCTRL_PIN(PAD_GPIO(13), "GPIO[13]"),
> +	PINCTRL_PIN(PAD_GPIO(14), "GPIO[14]"),
> +	PINCTRL_PIN(PAD_GPIO(15), "GPIO[15]"),
> +	PINCTRL_PIN(PAD_GPIO(16), "GPIO[16]"),
> +	PINCTRL_PIN(PAD_GPIO(17), "GPIO[17]"),
> +	PINCTRL_PIN(PAD_GPIO(18), "GPIO[18]"),
> +	PINCTRL_PIN(PAD_GPIO(19), "GPIO[19]"),
> +	PINCTRL_PIN(PAD_GPIO(20), "GPIO[20]"),
> +	PINCTRL_PIN(PAD_GPIO(21), "GPIO[21]"),
> +	PINCTRL_PIN(PAD_GPIO(22), "GPIO[22]"),
> +	PINCTRL_PIN(PAD_GPIO(23), "GPIO[23]"),
> +	PINCTRL_PIN(PAD_GPIO(24), "GPIO[24]"),
> +	PINCTRL_PIN(PAD_GPIO(25), "GPIO[25]"),
> +	PINCTRL_PIN(PAD_GPIO(26), "GPIO[26]"),
> +	PINCTRL_PIN(PAD_GPIO(27), "GPIO[27]"),
> +	PINCTRL_PIN(PAD_GPIO(28), "GPIO[28]"),
> +	PINCTRL_PIN(PAD_GPIO(29), "GPIO[29]"),
> +	PINCTRL_PIN(PAD_GPIO(30), "GPIO[30]"),
> +	PINCTRL_PIN(PAD_GPIO(31), "GPIO[31]"),
> +	PINCTRL_PIN(PAD_GPIO(32), "GPIO[32]"),
> +	PINCTRL_PIN(PAD_GPIO(33), "GPIO[33]"),
> +	PINCTRL_PIN(PAD_GPIO(34), "GPIO[34]"),
> +	PINCTRL_PIN(PAD_GPIO(35), "GPIO[35]"),
> +	PINCTRL_PIN(PAD_GPIO(36), "GPIO[36]"),
> +	PINCTRL_PIN(PAD_GPIO(37), "GPIO[37]"),
> +	PINCTRL_PIN(PAD_GPIO(38), "GPIO[38]"),
> +	PINCTRL_PIN(PAD_GPIO(39), "GPIO[39]"),
> +	PINCTRL_PIN(PAD_GPIO(40), "GPIO[40]"),
> +	PINCTRL_PIN(PAD_GPIO(41), "GPIO[41]"),
> +	PINCTRL_PIN(PAD_GPIO(42), "GPIO[42]"),
> +	PINCTRL_PIN(PAD_GPIO(43), "GPIO[43]"),
> +	PINCTRL_PIN(PAD_GPIO(44), "GPIO[44]"),
> +	PINCTRL_PIN(PAD_GPIO(45), "GPIO[45]"),
> +	PINCTRL_PIN(PAD_GPIO(46), "GPIO[46]"),
> +	PINCTRL_PIN(PAD_GPIO(47), "GPIO[47]"),
> +	PINCTRL_PIN(PAD_GPIO(48), "GPIO[48]"),
> +	PINCTRL_PIN(PAD_GPIO(49), "GPIO[49]"),
> +	PINCTRL_PIN(PAD_GPIO(50), "GPIO[50]"),
> +	PINCTRL_PIN(PAD_GPIO(51), "GPIO[51]"),
> +	PINCTRL_PIN(PAD_GPIO(52), "GPIO[52]"),
> +	PINCTRL_PIN(PAD_GPIO(53), "GPIO[53]"),
> +	PINCTRL_PIN(PAD_GPIO(54), "GPIO[54]"),
> +	PINCTRL_PIN(PAD_GPIO(55), "GPIO[55]"),
> +	PINCTRL_PIN(PAD_GPIO(56), "GPIO[56]"),
> +	PINCTRL_PIN(PAD_GPIO(57), "GPIO[57]"),
> +	PINCTRL_PIN(PAD_GPIO(58), "GPIO[58]"),
> +	PINCTRL_PIN(PAD_GPIO(59), "GPIO[59]"),
> +	PINCTRL_PIN(PAD_GPIO(60), "GPIO[60]"),
> +	PINCTRL_PIN(PAD_GPIO(61), "GPIO[61]"),
> +	PINCTRL_PIN(PAD_GPIO(62), "GPIO[62]"),
> +	PINCTRL_PIN(PAD_GPIO(63), "GPIO[63]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(0), "FUNC_SHARE[0]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(1), "FUNC_SHARE[1]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(2), "FUNC_SHARE[2]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(3), "FUNC_SHARE[3]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(4), "FUNC_SHARE[4]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(5), "FUNC_SHARE[5]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(6), "FUNC_SHARE[6]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(7), "FUNC_SHARE[7]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(8), "FUNC_SHARE[8]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(9), "FUNC_SHARE[9]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(10), "FUNC_SHARE[10]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(11), "FUNC_SHARE[11]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(12), "FUNC_SHARE[12]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(13), "FUNC_SHARE[13]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(14), "FUNC_SHARE[14]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(15), "FUNC_SHARE[15]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(16), "FUNC_SHARE[16]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(17), "FUNC_SHARE[17]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(18), "FUNC_SHARE[18]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(19), "FUNC_SHARE[19]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(20), "FUNC_SHARE[20]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(21), "FUNC_SHARE[21]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(22), "FUNC_SHARE[22]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(23), "FUNC_SHARE[23]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(24), "FUNC_SHARE[24]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(25), "FUNC_SHARE[25]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(26), "FUNC_SHARE[26]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(27), "FUNC_SHARE[27]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(28), "FUNC_SHARE[28]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(29), "FUNC_SHARE[29]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(30), "FUNC_SHARE[30]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(31), "FUNC_SHARE[31]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(32), "FUNC_SHARE[32]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(33), "FUNC_SHARE[33]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(34), "FUNC_SHARE[34]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(35), "FUNC_SHARE[35]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(36), "FUNC_SHARE[36]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(37), "FUNC_SHARE[37]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(38), "FUNC_SHARE[38]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(39), "FUNC_SHARE[39]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(40), "FUNC_SHARE[40]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(41), "FUNC_SHARE[41]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(42), "FUNC_SHARE[42]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(43), "FUNC_SHARE[43]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(44), "FUNC_SHARE[44]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(45), "FUNC_SHARE[45]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(46), "FUNC_SHARE[46]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(47), "FUNC_SHARE[47]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(48), "FUNC_SHARE[48]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(49), "FUNC_SHARE[49]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(50), "FUNC_SHARE[50]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(51), "FUNC_SHARE[51]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(52), "FUNC_SHARE[52]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(53), "FUNC_SHARE[53]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(54), "FUNC_SHARE[54]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(55), "FUNC_SHARE[55]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(56), "FUNC_SHARE[56]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(57), "FUNC_SHARE[57]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(58), "FUNC_SHARE[58]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(59), "FUNC_SHARE[59]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(60), "FUNC_SHARE[60]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(61), "FUNC_SHARE[61]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(62), "FUNC_SHARE[62]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(63), "FUNC_SHARE[63]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(64), "FUNC_SHARE[64]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(65), "FUNC_SHARE[65]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(66), "FUNC_SHARE[66]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(67), "FUNC_SHARE[67]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(68), "FUNC_SHARE[68]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(69), "FUNC_SHARE[69]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(70), "FUNC_SHARE[70]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(71), "FUNC_SHARE[71]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(72), "FUNC_SHARE[72]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(73), "FUNC_SHARE[73]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(74), "FUNC_SHARE[74]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(75), "FUNC_SHARE[75]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(76), "FUNC_SHARE[76]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(77), "FUNC_SHARE[77]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(78), "FUNC_SHARE[78]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(79), "FUNC_SHARE[79]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(80), "FUNC_SHARE[80]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(81), "FUNC_SHARE[81]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(82), "FUNC_SHARE[82]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(83), "FUNC_SHARE[83]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(84), "FUNC_SHARE[84]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(85), "FUNC_SHARE[85]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(86), "FUNC_SHARE[86]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(87), "FUNC_SHARE[87]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(88), "FUNC_SHARE[88]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(89), "FUNC_SHARE[89]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(90), "FUNC_SHARE[90]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(91), "FUNC_SHARE[91]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(92), "FUNC_SHARE[92]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(93), "FUNC_SHARE[93]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(94), "FUNC_SHARE[94]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(95), "FUNC_SHARE[95]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(96), "FUNC_SHARE[96]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(97), "FUNC_SHARE[97]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(98), "FUNC_SHARE[98]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(99), "FUNC_SHARE[99]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(100), "FUNC_SHARE[100]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(101), "FUNC_SHARE[101]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(102), "FUNC_SHARE[102]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(103), "FUNC_SHARE[103]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(104), "FUNC_SHARE[104]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(105), "FUNC_SHARE[105]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(106), "FUNC_SHARE[106]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(107), "FUNC_SHARE[107]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(108), "FUNC_SHARE[108]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(109), "FUNC_SHARE[109]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(110), "FUNC_SHARE[110]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(111), "FUNC_SHARE[111]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(112), "FUNC_SHARE[112]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(113), "FUNC_SHARE[113]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(114), "FUNC_SHARE[114]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(115), "FUNC_SHARE[115]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(116), "FUNC_SHARE[116]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(117), "FUNC_SHARE[117]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(118), "FUNC_SHARE[118]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(119), "FUNC_SHARE[119]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(120), "FUNC_SHARE[120]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(121), "FUNC_SHARE[121]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(122), "FUNC_SHARE[122]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(123), "FUNC_SHARE[123]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(124), "FUNC_SHARE[124]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(125), "FUNC_SHARE[125]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(126), "FUNC_SHARE[126]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(127), "FUNC_SHARE[127]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(128), "FUNC_SHARE[128]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(129), "FUNC_SHARE[129]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(130), "FUNC_SHARE[130]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(131), "FUNC_SHARE[131]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(132), "FUNC_SHARE[132]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(133), "FUNC_SHARE[133]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(134), "FUNC_SHARE[134]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(135), "FUNC_SHARE[135]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(136), "FUNC_SHARE[136]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(137), "FUNC_SHARE[137]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(138), "FUNC_SHARE[138]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(139), "FUNC_SHARE[139]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(140), "FUNC_SHARE[140]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(141), "FUNC_SHARE[141]"),
> +};
> +
> +#ifdef CONFIG_DEBUG_FS
> +static void starfive_pin_dbg_show(struct pinctrl_dev *pctldev,
> +				  struct seq_file *s,
> +				  unsigned int pin)
> +{
> +	struct starfive_pinctrl *sfp = pinctrl_dev_get_drvdata(pctldev);
> +	unsigned int gpio = starfive_pin_to_gpio(sfp, pin);
> +	void __iomem *reg;
> +	u32 dout, doen;
> +
> +	if (gpio >= NR_GPIOS)
> +		return;
> +
> +	reg = sfp->base + GPON_DOUT_CFG + 8 * gpio;
> +	dout = readl_relaxed(reg + 0x000);
> +	doen = readl_relaxed(reg + 0x004);
> +
> +	seq_printf(s, "dout=%u%s doen=%u%s",
> +		   dout & (u32)GENMASK(7, 0), (dout & BIT(31)) ? "r" : "",
> +		   doen & (u32)GENMASK(7, 0), (doen & BIT(31)) ? "r" : "");
> +}
> +#else
> +#define starfive_pin_dbg_show NULL
> +#endif
> +
> +static int starfive_dt_node_to_map(struct pinctrl_dev *pctldev,
> +				   struct device_node *np,
> +				   struct pinctrl_map **maps,
> +				   unsigned int *num_maps)
> +{
> +	struct starfive_pinctrl *sfp = pinctrl_dev_get_drvdata(pctldev);
> +	struct device *dev = starfive_dev(sfp);
> +	const char **pgnames;
> +	struct pinctrl_map *map;
> +	struct device_node *child;
> +	const char *grpname;
> +	int *pins;
> +	u32 *pinmux;
> +	int nmaps;
> +	int ngroups;
> +	int ret;
> +
> +	nmaps = 0;
> +	ngroups = 0;
> +	for_each_child_of_node(np, child) {
> +		int npinmux = of_property_count_u32_elems(child, "pinmux");
> +		int npins   = of_property_count_u32_elems(child, "pins");
> +
> +		if (npinmux > 0 && npins > 0) {
> +			dev_err(dev, "invalid pinctrl group %pOFn.%pOFn: %s\n",
> +				np, child, "both pinmux and pins set");
> +			of_node_put(child);
> +			return -EINVAL;
> +		}
> +
> +		if (npinmux > 0) {
> +			nmaps += 2;
> +		} else if (npins > 0) {
> +			nmaps += 1;
> +		} else {
> +			dev_err(dev, "invalid pinctrl group %pOFn.%pOFn: %s\n",
> +				np, child, "neither pinmux nor pins set");
> +			of_node_put(child);
> +			return -EINVAL;
> +		}
> +		ngroups += 1;
> +	}
> +
> +	ret = -ENOMEM;
> +	pgnames = devm_kcalloc(dev, ngroups, sizeof(*pgnames), GFP_KERNEL);
> +	if (!pgnames)
> +		return ret;
> +
> +	map = kcalloc(nmaps, sizeof(*map), GFP_KERNEL);
> +	if (!map)
> +		goto free_pgnames;
> +
> +	nmaps = 0;
> +	ngroups = 0;
> +	for_each_child_of_node(np, child) {
> +		int npins;
> +		int i;
> +
> +		ret = -ENOMEM;
> +		grpname = devm_kasprintf(dev, GFP_KERNEL, "%s.%s", np->name, child->name);
> +		if (!grpname)
> +			goto put_child;
> +
> +		pgnames[ngroups++] = grpname;
> +
> +		if ((npins = of_property_count_u32_elems(child, "pinmux")) > 0) {
> +			pins = devm_kcalloc(dev, npins, sizeof(*pins), GFP_KERNEL);
> +			if (!pins)
> +				goto free_grpname;
> +
> +			pinmux = devm_kcalloc(dev, npins, sizeof(*pinmux), GFP_KERNEL);
> +			if (!pinmux)
> +				goto free_pins;
> +
> +			for (i = 0; i < npins; i++) {
> +				u32 v;
> +
> +				ret = of_property_read_u32_index(child, "pinmux", i, &v);
> +				if (ret)
> +					goto free_pinmux;
> +				pins[i] = starfive_gpio_to_pin(sfp, starfive_pinmux_to_gpio(v));
> +				pinmux[i] = v;
> +			}
> +
> +			map[nmaps].type = PIN_MAP_TYPE_MUX_GROUP;
> +			map[nmaps].data.mux.function = np->name;
> +			map[nmaps].data.mux.group = grpname;
> +			nmaps += 1;
> +		} else if ((npins = of_property_count_u32_elems(child, "pins")) > 0) {
> +			pins = devm_kcalloc(dev, npins, sizeof(*pins), GFP_KERNEL);
> +			if (!pins)
> +				goto free_grpname;
> +
> +			pinmux = NULL;
> +
> +			for (i = 0; i < npins; i++) {
> +				u32 v;
> +
> +				ret = of_property_read_u32_index(child, "pins", i, &v);
> +				if (ret)
> +					goto free_pins;
> +				pins[i] = v;
> +			}
> +		} else {
> +			ret = -EINVAL;
> +			goto free_grpname;
> +		}
> +
> +		ret = pinctrl_generic_add_group(pctldev, grpname, pins, npins, pinmux);
> +		if (ret < 0) {
> +			dev_err(dev, "error adding group %pOFn.%pOFn: %d\n",
> +				np, child, ret);
> +			goto free_pinmux;
> +		}
> +
> +		ret = pinconf_generic_parse_dt_config(child, pctldev,
> +						      &map[nmaps].data.configs.configs,
> +						      &map[nmaps].data.configs.num_configs);
> +		if (ret) {
> +			dev_err(dev, "invalid pinctrl group %pOFn.%pOFn: %s\n",
> +				np, child, "error parsing pin config");
> +			goto put_child;
> +		}
> +
> +		/* don't create a map if there are no pinconf settings */
> +		if (map[nmaps].data.configs.num_configs == 0)
> +			continue;
> +
> +		map[nmaps].type = PIN_MAP_TYPE_CONFIGS_GROUP;
> +		map[nmaps].data.configs.group_or_pin = grpname;
> +		nmaps += 1;
> +	}
> +
> +	ret = pinmux_generic_add_function(pctldev, np->name, pgnames, ngroups, NULL);
> +	if (ret < 0) {
> +		dev_err(dev, "error adding function %pOFn: %d\n", np, ret);
> +		goto free_map;
> +	}
> +
> +	*maps = map;
> +	*num_maps = nmaps;
> +	return 0;
> +
> +free_pinmux:
> +	devm_kfree(dev, pinmux);
> +free_pins:
> +	devm_kfree(dev, pins);
> +free_grpname:
> +	devm_kfree(dev, grpname);
> +put_child:
> +	of_node_put(child);
> +free_map:
> +	pinctrl_utils_free_map(pctldev, map, nmaps);
> +free_pgnames:
> +	devm_kfree(dev, pgnames);
> +	return ret;
> +}
> +
> +static const struct pinctrl_ops starfive_pinctrl_ops = {
> +	.get_groups_count = pinctrl_generic_get_group_count,
> +	.get_group_name = pinctrl_generic_get_group_name,
> +	.get_group_pins = pinctrl_generic_get_group_pins,
> +	.pin_dbg_show = starfive_pin_dbg_show,
> +	.dt_node_to_map = starfive_dt_node_to_map,
> +	.dt_free_map = pinctrl_utils_free_map,
> +};
> +
> +static int starfive_set_mux(struct pinctrl_dev *pctldev,
> +			    unsigned int fsel, unsigned int gsel)
> +{
> +	struct starfive_pinctrl *sfp = pinctrl_dev_get_drvdata(pctldev);
> +	struct device *dev = starfive_dev(sfp);
> +	const struct group_desc *group;
> +	const u32 *pinmux;
> +	unsigned int i;
> +
> +	group = pinctrl_generic_get_group(pctldev, gsel);
> +	if (!group)
> +		return -EINVAL;
> +
> +	pinmux = group->data;
> +	for (i = 0; i < group->num_pins; i++) {
> +		u32 v = pinmux[i];
> +		unsigned int gpio = starfive_pinmux_to_gpio(v);
> +		u32 dout = starfive_pinmux_to_dout(v);
> +		u32 doen = starfive_pinmux_to_doen(v);
> +		u32 din = starfive_pinmux_to_din(v);
> +		void __iomem *reg_dout;
> +		void __iomem *reg_doen;
> +		void __iomem *reg_din;
> +		unsigned long flags;
> +
> +		dev_dbg(dev, "GPIO%u: dout=0x%x doen=0x%x din=0x%x\n",
> +			gpio, dout, doen, din);
> +
> +		reg_dout = sfp->base + GPON_DOUT_CFG + 8 * gpio;
> +		reg_doen = sfp->base + GPON_DOEN_CFG + 8 * gpio;
> +		if (din != GPI_NONE)
> +			reg_din = sfp->base + GPI_CFG_OFFSET + 4 * din;
> +		else
> +			reg_din = NULL;
> +
> +		raw_spin_lock_irqsave(&sfp->lock, flags);
> +		writel_relaxed(dout, reg_dout);
> +		writel_relaxed(doen, reg_doen);
> +		if (reg_din)
> +			writel_relaxed(gpio + 2, reg_din);
> +		raw_spin_unlock_irqrestore(&sfp->lock, flags);
> +	}
> +
> +	return 0;
> +}
> +
> +static const struct pinmux_ops starfive_pinmux_ops = {
> +	.get_functions_count = pinmux_generic_get_function_count,
> +	.get_function_name = pinmux_generic_get_function_name,
> +	.get_function_groups = pinmux_generic_get_function_groups,
> +	.set_mux = starfive_set_mux,
> +	.strict = true,
> +};
> +
> +static u16 starfive_padctl_get(struct starfive_pinctrl *sfp,
> +			       unsigned int pin)
> +{
> +	void __iomem *reg = sfp->padctl + 4 * (pin / 2);
> +	int shift = 16 * (pin % 2);
> +
> +	return readl_relaxed(reg) >> shift;
> +}
> +
> +static void starfive_padctl_rmw(struct starfive_pinctrl *sfp,
> +				unsigned int pin,
> +				u16 _mask, u16 _value)
> +{
> +	void __iomem *reg = sfp->padctl + 4 * (pin / 2);
> +	int shift = 16 * (pin % 2);
> +	u32 mask = (u32)_mask << shift;
> +	u32 value = (u32)_value << shift;
> +	unsigned long flags;
> +
> +	dev_dbg(starfive_dev(sfp),
> +		"padctl_rmw(%u, 0x%03x, 0x%03x)\n", pin, _mask, _value);
> +
> +	raw_spin_lock_irqsave(&sfp->lock, flags);
> +	value |= readl_relaxed(reg) & ~mask;
> +	writel_relaxed(value, reg);
> +	raw_spin_unlock_irqrestore(&sfp->lock, flags);
> +}
> +
> +#define PIN_CONFIG_STARFIVE_STRONG_PULL_UP	(PIN_CONFIG_END + 1)
> +
> +static const struct pinconf_generic_params starfive_pinconf_custom_params[] = {
> +	{ "starfive,strong-pull-up", PIN_CONFIG_STARFIVE_STRONG_PULL_UP, 1 },
> +};
> +
> +#ifdef CONFIG_DEBUG_FS
> +static const struct pin_config_item starfive_pinconf_custom_conf_items[] = {
> +	PCONFDUMP(PIN_CONFIG_STARFIVE_STRONG_PULL_UP, "input bias strong pull-up", NULL, false),
> +};
> +
> +static_assert(ARRAY_SIZE(starfive_pinconf_custom_conf_items) ==
> +	      ARRAY_SIZE(starfive_pinconf_custom_params));
> +#else
> +#define starfive_pinconf_custom_conf_items NULL
> +#endif
> +
> +static int starfive_pinconf_get(struct pinctrl_dev *pctldev,
> +				unsigned int pin, unsigned long *config)
> +{
> +	struct starfive_pinctrl *sfp = pinctrl_dev_get_drvdata(pctldev);
> +	u16 value = starfive_padctl_get(sfp, pin);
> +	int param = pinconf_to_config_param(*config);
> +	u32 arg;
> +	bool enabled;
> +
> +	switch (param) {
> +	case PIN_CONFIG_BIAS_DISABLE:
> +		enabled = value & PAD_BIAS_DISABLE;
> +		arg = 0;
> +		break;
> +	case PIN_CONFIG_BIAS_PULL_DOWN:
> +		enabled = value & PAD_BIAS_PULL_DOWN;
> +		arg = 1;
> +		break;
> +	case PIN_CONFIG_BIAS_PULL_UP:
> +		enabled = !(value & PAD_BIAS_MASK);
> +		arg = 1;
> +		break;
> +	case PIN_CONFIG_DRIVE_STRENGTH:
> +		enabled = value & PAD_DRIVE_STRENGTH_MASK;
> +		arg = starfive_drive_strength_to_max_mA(value & PAD_DRIVE_STRENGTH_MASK);
> +		break;
> +	case PIN_CONFIG_INPUT_ENABLE:
> +		enabled = value & PAD_INPUT_ENABLE;
> +		arg = enabled;
> +		break;
> +	case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
> +		enabled = value & PAD_INPUT_SCHMITT_ENABLE;
> +		arg = enabled;
> +		break;
> +	case PIN_CONFIG_SLEW_RATE:
> +		enabled = value & PAD_SLEW_RATE_MASK;
> +		arg = (value & PAD_SLEW_RATE_MASK) >> PAD_SLEW_RATE_POS;
> +		break;
> +	case PIN_CONFIG_STARFIVE_STRONG_PULL_UP:
> +		enabled = value & PAD_BIAS_STRONG_PULL_UP;
> +		arg = enabled;
> +		break;
> +	default:
> +		return -ENOTSUPP;
> +	}
> +
> +	*config = pinconf_to_config_packed(param, arg);
> +	return enabled ? 0 : -EINVAL;
> +}
> +
> +static int starfive_pinconf_group_get(struct pinctrl_dev *pctldev,
> +				      unsigned int gsel, unsigned long *config)
> +{
> +	const struct group_desc *group;
> +
> +	group = pinctrl_generic_get_group(pctldev, gsel);
> +	if (!group)
> +		return -EINVAL;
> +
> +	return starfive_pinconf_get(pctldev, group->pins[0], config);
> +}
> +
> +static int starfive_pinconf_group_set(struct pinctrl_dev *pctldev,
> +				      unsigned int gsel,
> +				      unsigned long *configs,
> +				      unsigned int num_configs)
> +{
> +	struct starfive_pinctrl *sfp = pinctrl_dev_get_drvdata(pctldev);
> +	const struct group_desc *group;
> +	u16 mask, value;
> +	int i;
> +
> +	group = pinctrl_generic_get_group(pctldev, gsel);
> +	if (!group)
> +		return -EINVAL;
> +
> +	mask = 0;
> +	value = 0;
> +	for (i = 0; i < num_configs; i++) {
> +		int param = pinconf_to_config_param(configs[i]);
> +		u32 arg = pinconf_to_config_argument(configs[i]);
> +
> +		switch (param) {
> +		case PIN_CONFIG_BIAS_DISABLE:
> +			mask |= PAD_BIAS_MASK;
> +			value = (value & ~PAD_BIAS_MASK) | PAD_BIAS_DISABLE;
> +			break;
> +		case PIN_CONFIG_BIAS_PULL_DOWN:
> +			if (arg == 0)
> +				return -ENOTSUPP;
> +			mask |= PAD_BIAS_MASK;
> +			value = (value & ~PAD_BIAS_MASK) | PAD_BIAS_PULL_DOWN;
> +			break;
> +		case PIN_CONFIG_BIAS_PULL_UP:
> +			if (arg == 0)
> +				return -ENOTSUPP;
> +			mask |= PAD_BIAS_MASK;
> +			value = value & ~PAD_BIAS_MASK;
> +			break;
> +		case PIN_CONFIG_DRIVE_STRENGTH:
> +			mask |= PAD_DRIVE_STRENGTH_MASK;
> +			value = (value & ~PAD_DRIVE_STRENGTH_MASK) |
> +				starfive_drive_strength_from_max_mA(arg);
> +			break;
> +		case PIN_CONFIG_INPUT_ENABLE:
> +			mask |= PAD_INPUT_ENABLE;
> +			if (arg)
> +				value |= PAD_INPUT_ENABLE;
> +			else
> +				value &= ~PAD_INPUT_ENABLE;
> +			break;
> +		case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
> +			mask |= PAD_INPUT_SCHMITT_ENABLE;
> +			if (arg)
> +				value |= PAD_INPUT_SCHMITT_ENABLE;
> +			else
> +				value &= ~PAD_INPUT_SCHMITT_ENABLE;
> +			break;
> +		case PIN_CONFIG_SLEW_RATE:
> +			mask |= PAD_SLEW_RATE_MASK;
> +			value = (value & ~PAD_SLEW_RATE_MASK) |
> +				((arg << PAD_SLEW_RATE_POS) & PAD_SLEW_RATE_MASK);
> +			break;
> +		case PIN_CONFIG_STARFIVE_STRONG_PULL_UP:
> +			if (arg) {
> +				mask |= PAD_BIAS_MASK;
> +				value = (value & ~PAD_BIAS_MASK) |
> +					PAD_BIAS_STRONG_PULL_UP;
> +			} else {
> +				mask |= PAD_BIAS_STRONG_PULL_UP;
> +				value = value & ~PAD_BIAS_STRONG_PULL_UP;
> +			}
> +			break;
> +		default:
> +			return -ENOTSUPP;
> +		}
> +	}
> +
> +	for (i = 0; i < group->num_pins; i++)
> +		starfive_padctl_rmw(sfp, group->pins[i], mask, value);
> +
> +	return 0;
> +}
> +
> +#ifdef CONFIG_DEBUG_FS
> +static void starfive_pinconf_dbg_show(struct pinctrl_dev *pctldev,
> +				      struct seq_file *s, unsigned int pin)
> +{
> +	struct starfive_pinctrl *sfp = pinctrl_dev_get_drvdata(pctldev);
> +	u16 value = starfive_padctl_get(sfp, pin);
> +
> +	seq_printf(s, " (0x%03x)", value);
> +}
> +#else
> +#define starfive_pinconf_dbg_show NULL
> +#endif
> +
> +static const struct pinconf_ops starfive_pinconf_ops = {
> +	.pin_config_get = starfive_pinconf_get,
> +	.pin_config_group_get = starfive_pinconf_group_get,
> +	.pin_config_group_set = starfive_pinconf_group_set,
> +	.pin_config_dbg_show = starfive_pinconf_dbg_show,
> +	.is_generic = true,
> +};
> +
> +static struct pinctrl_desc starfive_desc = {
> +	.name = DRIVER_NAME,
> +	.pins = starfive_pins,
> +	.npins = ARRAY_SIZE(starfive_pins),
> +	.pctlops = &starfive_pinctrl_ops,
> +	.pmxops = &starfive_pinmux_ops,
> +	.confops = &starfive_pinconf_ops,
> +	.owner = THIS_MODULE,
> +	.num_custom_params = ARRAY_SIZE(starfive_pinconf_custom_params),
> +	.custom_params = starfive_pinconf_custom_params,
> +	.custom_conf_items = starfive_pinconf_custom_conf_items,
> +};
> +
> +static int starfive_gpio_request(struct gpio_chip *gc, unsigned int gpio)
> +{
> +	return pinctrl_gpio_request(gc->base + gpio);
> +}
> +
> +static void starfive_gpio_free(struct gpio_chip *gc, unsigned int gpio)
> +{
> +	pinctrl_gpio_free(gc->base + gpio);
> +}
> +
> +static int starfive_gpio_get_direction(struct gpio_chip *gc, unsigned int gpio)
> +{
> +	struct starfive_pinctrl *sfp = starfive_from_gc(gc);
> +
> +	if (gpio >= NR_GPIOS)
> +		return -EINVAL;
> +
> +	/* return GPIO_LINE_DIRECTION_OUT (0) only if doen == GPO_ENABLE (0) */
> +	return readl_relaxed(sfp->base + GPON_DOEN_CFG + 8 * gpio) != GPO_ENABLE;
> +}
> +
> +static int starfive_gpio_direction_input(struct gpio_chip *gc,
> +					 unsigned int gpio)
> +{
> +	struct starfive_pinctrl *sfp = starfive_from_gc(gc);
> +	void __iomem *doen;
> +	unsigned long flags;
> +
> +	if (gpio >= NR_GPIOS)
> +		return -EINVAL;
> +
> +	/* enable input and schmitt trigger */
> +	starfive_padctl_rmw(sfp, starfive_gpio_to_pin(sfp, gpio),
> +			    PAD_INPUT_ENABLE | PAD_INPUT_SCHMITT_ENABLE,
> +			    PAD_INPUT_ENABLE | PAD_INPUT_SCHMITT_ENABLE);
> +
> +	doen = sfp->base + GPON_DOEN_CFG + 8 * gpio;
> +	raw_spin_lock_irqsave(&sfp->lock, flags);
> +	writel_relaxed(GPO_DISABLE, doen);
> +	raw_spin_unlock_irqrestore(&sfp->lock, flags);
> +	return 0;
> +}
> +
> +static int starfive_gpio_direction_output(struct gpio_chip *gc,
> +					  unsigned int gpio, int value)
> +{
> +	struct starfive_pinctrl *sfp = starfive_from_gc(gc);
> +	void __iomem *dout;
> +	void __iomem *doen;
> +	unsigned long flags;
> +
> +	if (gpio >= NR_GPIOS)
> +		return -EINVAL;
> +
> +	dout = sfp->base + GPON_DOUT_CFG + 8 * gpio;
> +	doen = sfp->base + GPON_DOEN_CFG + 8 * gpio;
> +	raw_spin_lock_irqsave(&sfp->lock, flags);
> +	writel_relaxed(value, dout);
> +	writel_relaxed(GPO_ENABLE, doen);
> +	raw_spin_unlock_irqrestore(&sfp->lock, flags);
> +
> +	/* disable input, schmitt trigger and bias */
> +	starfive_padctl_rmw(sfp, starfive_gpio_to_pin(sfp, gpio),
> +			    PAD_BIAS_MASK | PAD_INPUT_ENABLE | PAD_INPUT_SCHMITT_ENABLE,
> +			    PAD_BIAS_DISABLE);
> +
> +	return 0;
> +}
> +
> +static int starfive_gpio_get(struct gpio_chip *gc, unsigned int gpio)
> +{
> +	struct starfive_pinctrl *sfp = starfive_from_gc(gc);
> +	void __iomem *din;
> +
> +	if (gpio >= NR_GPIOS)
> +		return -EINVAL;
> +
> +	din = sfp->base + GPIODIN + 4 * (gpio / 32);
> +	return !!(readl_relaxed(din) & BIT(gpio % 32));
> +}
> +
> +static void starfive_gpio_set(struct gpio_chip *gc, unsigned int gpio,
> +			      int value)
> +{
> +	struct starfive_pinctrl *sfp = starfive_from_gc(gc);
> +	void __iomem *dout;
> +	unsigned long flags;
> +
> +	if (gpio >= NR_GPIOS)
> +		return;
> +
> +	dout = sfp->base + GPON_DOUT_CFG + 8 * gpio;
> +	raw_spin_lock_irqsave(&sfp->lock, flags);
> +	writel_relaxed(value, dout);
> +	raw_spin_unlock_irqrestore(&sfp->lock, flags);
> +}
> +
> +static int starfive_gpio_set_config(struct gpio_chip *gc, unsigned int gpio,
> +				    unsigned long config)
> +{
> +	struct starfive_pinctrl *sfp = starfive_from_gc(gc);
> +	u32 arg = pinconf_to_config_argument(config);
> +	u16 mask;
> +	u16 value;
> +
> +	switch (pinconf_to_config_param(config)) {
> +	case PIN_CONFIG_BIAS_DISABLE:
> +		mask  = PAD_BIAS_MASK;
> +		value = PAD_BIAS_DISABLE;
> +		break;
> +	case PIN_CONFIG_BIAS_PULL_DOWN:
> +		if (arg == 0)
> +			return -ENOTSUPP;
> +		mask  = PAD_BIAS_MASK;
> +		value = PAD_BIAS_PULL_DOWN;
> +		break;
> +	case PIN_CONFIG_BIAS_PULL_UP:
> +		if (arg == 0)
> +			return -ENOTSUPP;
> +		mask  = PAD_BIAS_MASK;
> +		value = 0;
> +		break;
> +	case PIN_CONFIG_DRIVE_PUSH_PULL:
> +		return 0;
> +	case PIN_CONFIG_INPUT_ENABLE:
> +		mask  = PAD_INPUT_ENABLE;
> +		value = arg ? PAD_INPUT_ENABLE : 0;
> +		break;
> +	case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
> +		mask  = PAD_INPUT_SCHMITT_ENABLE;
> +		value = arg ? PAD_INPUT_SCHMITT_ENABLE : 0;
> +		break;
> +	default:
> +		return -ENOTSUPP;
> +	};
> +
> +	starfive_padctl_rmw(sfp, starfive_gpio_to_pin(sfp, gpio), mask, value);
> +	return 0;
> +}
> +
> +static int starfive_gpio_add_pin_ranges(struct gpio_chip *gc)
> +{
> +	struct starfive_pinctrl *sfp = starfive_from_gc(gc);
> +
> +	sfp->gpios.name = sfp->gc.label;
> +	sfp->gpios.base = sfp->gc.base;
> +	/*
> +	 * sfp->gpios.pin_base depends on the chosen signal group
> +	 * and is set in starfive_probe()
> +	 */
> +	sfp->gpios.npins = NR_GPIOS;
> +	sfp->gpios.gc = &sfp->gc;
> +	pinctrl_add_gpio_range(sfp->pctl, &sfp->gpios);
> +	return 0;
> +}
> +
> +static void starfive_irq_ack(struct irq_data *d)
> +{
> +	struct starfive_pinctrl *sfp = starfive_from_irq_data(d);
> +	irq_hw_number_t gpio = irqd_to_hwirq(d);
> +	void __iomem *ic = sfp->base + GPIOIC + 4 * (gpio / 32);
> +	u32 mask = BIT(gpio % 32);
> +	unsigned long flags;
> +
> +	raw_spin_lock_irqsave(&sfp->lock, flags);
> +	writel_relaxed(mask, ic);
> +	raw_spin_unlock_irqrestore(&sfp->lock, flags);
> +}
> +
> +static void starfive_irq_mask(struct irq_data *d)
> +{
> +	struct starfive_pinctrl *sfp = starfive_from_irq_data(d);
> +	irq_hw_number_t gpio = irqd_to_hwirq(d);
> +	void __iomem *ie = sfp->base + GPIOIE + 4 * (gpio / 32);
> +	u32 mask = BIT(gpio % 32);
> +	unsigned long flags;
> +	u32 value;
> +
> +	raw_spin_lock_irqsave(&sfp->lock, flags);
> +	value = readl_relaxed(ie) & ~mask;
> +	writel_relaxed(value, ie);
> +	raw_spin_unlock_irqrestore(&sfp->lock, flags);
> +}
> +
> +static void starfive_irq_mask_ack(struct irq_data *d)
> +{
> +	struct starfive_pinctrl *sfp = starfive_from_irq_data(d);
> +	irq_hw_number_t gpio = irqd_to_hwirq(d);
> +	void __iomem *ie = sfp->base + GPIOIE + 4 * (gpio / 32);
> +	void __iomem *ic = sfp->base + GPIOIC + 4 * (gpio / 32);
> +	u32 mask = BIT(gpio % 32);
> +	unsigned long flags;
> +	u32 value;
> +
> +	raw_spin_lock_irqsave(&sfp->lock, flags);
> +	value = readl_relaxed(ie) & ~mask;
> +	writel_relaxed(value, ie);
> +	writel_relaxed(mask, ic);
> +	raw_spin_unlock_irqrestore(&sfp->lock, flags);
> +}
> +
> +static void starfive_irq_unmask(struct irq_data *d)
> +{
> +	struct starfive_pinctrl *sfp = starfive_from_irq_data(d);
> +	irq_hw_number_t gpio = irqd_to_hwirq(d);
> +	void __iomem *ie = sfp->base + GPIOIE + 4 * (gpio / 32);
> +	u32 mask = BIT(gpio % 32);
> +	unsigned long flags;
> +	u32 value;
> +
> +	raw_spin_lock_irqsave(&sfp->lock, flags);
> +	value = readl_relaxed(ie) | mask;
> +	writel_relaxed(value, ie);
> +	raw_spin_unlock_irqrestore(&sfp->lock, flags);
> +}
> +
> +static int starfive_irq_set_type(struct irq_data *d, unsigned int trigger)
> +{
> +	struct starfive_pinctrl *sfp = starfive_from_irq_data(d);
> +	irq_hw_number_t gpio = irqd_to_hwirq(d);
> +	void __iomem *base = sfp->base + 4 * (gpio / 32);
> +	u32 mask = BIT(gpio % 32);
> +	u32 irq_type, edge_both, polarity;
> +	irq_flow_handler_t handler;
> +	unsigned long flags;
> +
> +	switch (trigger) {
> +	case IRQ_TYPE_EDGE_RISING:
> +		irq_type  = mask; /* 1: edge triggered */
> +		edge_both = 0;    /* 0: single edge */
> +		polarity  = mask; /* 1: rising edge */
> +		handler   = handle_edge_irq;
> +		break;
> +	case IRQ_TYPE_EDGE_FALLING:
> +		irq_type  = mask; /* 1: edge triggered */
> +		edge_both = 0;    /* 0: single edge */
> +		polarity  = 0;    /* 0: falling edge */
> +		handler   = handle_edge_irq;
> +		break;
> +	case IRQ_TYPE_EDGE_BOTH:
> +		irq_type  = mask; /* 1: edge triggered */
> +		edge_both = mask; /* 1: both edges */
> +		polarity  = 0;    /* 0: ignored */
> +		handler   = handle_edge_irq;
> +		break;
> +	case IRQ_TYPE_LEVEL_HIGH:
> +		irq_type  = 0;    /* 0: level triggered */
> +		edge_both = 0;    /* 0: ignored */
> +		polarity  = mask; /* 1: high level */
> +		handler   = handle_level_irq;
> +		break;
> +	case IRQ_TYPE_LEVEL_LOW:
> +		irq_type  = 0;    /* 0: level triggered */
> +		edge_both = 0;    /* 0: ignored */
> +		polarity  = 0;    /* 0: low level */
> +		handler   = handle_level_irq;
> +		break;
> +	default:
> +		irq_set_handler_locked(d, handle_bad_irq);
> +		return -EINVAL;
> +	}
> +
> +	irq_set_handler_locked(d, handler);
> +
> +	raw_spin_lock_irqsave(&sfp->lock, flags);
> +	irq_type |= readl_relaxed(base + GPIOIS) & ~mask;
> +	writel_relaxed(irq_type, base + GPIOIS);
> +	edge_both |= readl_relaxed(base + GPIOIBE) & ~mask;
> +	writel_relaxed(edge_both, base + GPIOIBE);
> +	polarity |= readl_relaxed(base + GPIOIEV) & ~mask;
> +	writel_relaxed(polarity, base + GPIOIEV);
> +	raw_spin_unlock_irqrestore(&sfp->lock, flags);
> +	return 0;
> +}
> +
> +static struct irq_chip starfive_irq_chip = {
> +	.irq_ack = starfive_irq_ack,
> +	.irq_mask = starfive_irq_mask,
> +	.irq_mask_ack = starfive_irq_mask_ack,
> +	.irq_unmask = starfive_irq_unmask,
> +	.irq_set_type = starfive_irq_set_type,
> +	.flags = IRQCHIP_SET_TYPE_MASKED,
> +};
> +
> +static void starfive_gpio_irq_handler(struct irq_desc *desc)
> +{
> +	struct starfive_pinctrl *sfp = starfive_from_irq_desc(desc);
> +	struct irq_chip *chip = irq_desc_get_chip(desc);
> +	unsigned long mis;
> +	unsigned int pin;
> +
> +	chained_irq_enter(chip, desc);
> +
> +	mis = readl_relaxed(sfp->base + GPIOMIS + 0);
> +	for_each_set_bit(pin, &mis, 32)
> +		generic_handle_domain_irq(sfp->gc.irq.domain, pin);
> +
> +	mis = readl_relaxed(sfp->base + GPIOMIS + 4);
> +	for_each_set_bit(pin, &mis, 32)
> +		generic_handle_domain_irq(sfp->gc.irq.domain, pin + 32);
> +
> +	chained_irq_exit(chip, desc);
> +}
> +
> +static int starfive_gpio_init_hw(struct gpio_chip *gc)
> +{
> +	struct starfive_pinctrl *sfp = starfive_from_gc(gc);
> +
> +	/* mask all GPIO interrupts */
> +	writel(0, sfp->base + GPIOIE + 0);
> +	writel(0, sfp->base + GPIOIE + 4);

Woudln't 0 in GPIOIE mean mask is disabled for all interrupts?

In other words, wouldn't this enable all the interrupts?

Thanks,
Drew

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 12/16] pinctrl: starfive: Add pinctrl driver for StarFive SoCs
@ 2021-10-21 19:01     ` Drew Fustini
  0 siblings, 0 replies; 143+ messages in thread
From: Drew Fustini @ 2021-10-21 19:01 UTC (permalink / raw)
  To: Emil Renner Berthing
  Cc: linux-riscv, devicetree, linux-clk, linux-gpio, linux-serial,
	Palmer Dabbelt, Paul Walmsley, Rob Herring, Michael Turquette,
	Stephen Boyd, Thomas Gleixner, Marc Zyngier, Philipp Zabel,
	Linus Walleij, Greg Kroah-Hartman, Daniel Lezcano,
	Andy Shevchenko, Jiri Slaby, Maximilian Luz, Sagar Kadam,
	Drew Fustini, Geert Uytterhoeven, Michael Zhu, Fu Wei,
	Anup Patel, Atish Patra, Matteo Croce, linux-kernel, Huan Feng

On Thu, Oct 21, 2021 at 07:42:19PM +0200, Emil Renner Berthing wrote:
> Add a combined pinctrl and GPIO driver for the StarFive JH7100 SoC.
> 
> For each "GPIO" there are two registers for configuring the output and
> output enable signals which may come from other peripherals. Among these
> are two special signals that are constant 0 and constant 1 respectively.
> Controlling the GPIOs from software is done by choosing one of these
> signals. In other words the same registers are used for both pinmuxing
> and controlling the GPIOs, which makes it easier to combine the pinctrl
> and GPIO driver in one.
> 
> I wrote the pinconf and pinmux parts, but the GPIO part of the code is
> based on the GPIO driver in the vendor tree written by Huan Feng with
> cleanups and fixes by Drew and me.
> 
> Datasheet: https://github.com/starfive-tech/JH7100_Docs/blob/main/JH7100%20Data%20Sheet%20V01.01.04-EN%20(4-21-2021).pdf
> Co-developed-by: Huan Feng <huan.feng@starfivetech.com>
> Signed-off-by: Huan Feng <huan.feng@starfivetech.com>
> Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
> Co-developed-by: Drew Fustini <drew@beagleboard.org>
> Signed-off-by: Drew Fustini <drew@beagleboard.org>
> ---
>  MAINTAINERS                        |    8 +
>  drivers/pinctrl/Kconfig            |   16 +
>  drivers/pinctrl/Makefile           |    1 +
>  drivers/pinctrl/pinctrl-starfive.c | 1387 ++++++++++++++++++++++++++++
>  4 files changed, 1412 insertions(+)
>  create mode 100644 drivers/pinctrl/pinctrl-starfive.c
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index b3f3a29fc91f..1f122f93a5a5 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -17855,6 +17855,14 @@ F:	Documentation/devicetree/bindings/clock/starfive,jh7100-clkgen.yaml
>  F:	drivers/clk/starfive/clk-starfive-jh7100.c
>  F:	include/dt-bindings/clock/starfive-jh7100.h
>  
> +STARFIVE JH7100 PINCTRL DRIVER
> +M:	Emil Renner Berthing <kernel@esmil.dk>
> +L:	linux-gpio@vger.kernel.org
> +S:	Maintained
> +F:	Documentation/devicetree/bindings/pinctrl/starfive,jh7100-pinctrl.yaml
> +F:	drivers/pinctrl/pinctrl-starfive.c
> +F:	include/dt-bindings/pinctrl/pinctrl-starfive.h
> +
>  STARFIVE JH7100 RESET CONTROLLER DRIVER
>  M:	Emil Renner Berthing <kernel@esmil.dk>
>  S:	Maintained
> diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
> index 31921108e456..98caa94acf9e 100644
> --- a/drivers/pinctrl/Kconfig
> +++ b/drivers/pinctrl/Kconfig
> @@ -265,6 +265,22 @@ config PINCTRL_ST
>  	select PINCONF
>  	select GPIOLIB_IRQCHIP
>  
> +config PINCTRL_STARFIVE
> +	tristate "Pinctrl and GPIO driver for the StarFive JH7100 SoC"
> +	depends on SOC_STARFIVE || COMPILE_TEST
> +	default SOC_STARFIVE
> +	select GENERIC_PINCTRL_GROUPS
> +	select GENERIC_PINMUX_FUNCTIONS
> +	select GENERIC_PINCONF
> +	select GPIOLIB
> +	select GPIOLIB_IRQCHIP
> +	select OF_GPIO
> +	help
> +	  Say yes here to support pin control on the StarFive JH7100 SoC.
> +	  This also provides an interface to the GPIO pins not used by other
> +	  peripherals supporting inputs, outputs, configuring pull-up/pull-down
> +	  and interrupts on input changes.
> +
>  config PINCTRL_STMFX
>  	tristate "STMicroelectronics STMFX GPIO expander pinctrl driver"
>  	depends on I2C
> diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
> index 200073bcc2c1..9c258047f11c 100644
> --- a/drivers/pinctrl/Makefile
> +++ b/drivers/pinctrl/Makefile
> @@ -38,6 +38,7 @@ obj-$(CONFIG_PINCTRL_LANTIQ)	+= pinctrl-lantiq.o
>  obj-$(CONFIG_PINCTRL_LPC18XX)	+= pinctrl-lpc18xx.o
>  obj-$(CONFIG_PINCTRL_TB10X)	+= pinctrl-tb10x.o
>  obj-$(CONFIG_PINCTRL_ST) 	+= pinctrl-st.o
> +obj-$(CONFIG_PINCTRL_STARFIVE)	+= pinctrl-starfive.o
>  obj-$(CONFIG_PINCTRL_STMFX) 	+= pinctrl-stmfx.o
>  obj-$(CONFIG_PINCTRL_ZYNQ)	+= pinctrl-zynq.o
>  obj-$(CONFIG_PINCTRL_ZYNQMP)	+= pinctrl-zynqmp.o
> diff --git a/drivers/pinctrl/pinctrl-starfive.c b/drivers/pinctrl/pinctrl-starfive.c
> new file mode 100644
> index 000000000000..ca99fad883e6
> --- /dev/null
> +++ b/drivers/pinctrl/pinctrl-starfive.c
> @@ -0,0 +1,1387 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Pinctrl / GPIO driver for StarFive JH7100 SoC
> + *
> + * Copyright (C) 2020 Shanghai StarFive Technology Co., Ltd.
> + * Copyright (C) 2021 Emil Renner Berthing <kernel@esmil.dk>
> + */
> +
> +#include <linux/bits.h>
> +#include <linux/clk.h>
> +#include <linux/gpio/driver.h>
> +#include <linux/io.h>
> +#include <linux/mod_devicetable.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/platform_device.h>
> +#include <linux/reset.h>
> +#include <linux/spinlock.h>
> +
> +#include <linux/pinctrl/pinctrl.h>
> +#include <linux/pinctrl/pinmux.h>
> +
> +#include <dt-bindings/pinctrl/pinctrl-starfive.h>
> +
> +#include "core.h"
> +#include "pinctrl-utils.h"
> +#include "pinmux.h"
> +#include "pinconf.h"
> +
> +#define DRIVER_NAME "pinctrl-starfive"
> +
> +/*
> + * Refer to Section 12. GPIO Registers in the JH7100 data sheet:
> + * https://github.com/starfive-tech/JH7100_Docs
> + */
> +#define NR_GPIOS	64
> +
> +/*
> + * Global enable for GPIO interrupts. If bit 0 is set to 1 the GPIO interrupts
> + * are enabled. If set to 0 the GPIO interrupts are disabled.
> + */
> +#define GPIOEN		0x000
> +
> +/*
> + * The following 32-bit registers come in pairs, but only the offset of the
> + * first register is defined. The first controls (interrupts for) GPIO 0-31 and
> + * the second GPIO 32-63.
> + */
> +
> +/*
> + * Interrupt Type. If set to 1 the interrupt is edge-triggered. If set to 0 the
> + * interrupt is level-triggered.
> + */
> +#define GPIOIS		0x010
> +
> +/*
> + * Edge-Trigger Interrupt Type.  If set to 1 the interrupt gets triggered on
> + * both positive and negative edges. If set to 0 the interrupt is triggered by a
> + * single edge.
> + */
> +#define GPIOIBE		0x018
> +
> +/*
> + * Interrupt Trigger Polarity. If set to 1 the interrupt is triggered on a
> + * rising edge (edge-triggered) or high level (level-triggered). If set to 0 the
> + * interrupt is triggered on a falling edge (edge-triggered) or low level
> + * (level-triggered).
> + */
> +#define GPIOIEV		0x020
> +
> +/*
> + * Interrupt Mask. If set to 1 the interrupt is disabled (masked). If set to 0
> + * the interrupt is enabled (unmasked).
> + */
> +#define GPIOIE		0x028

It bothered me that the datasheet used the term GPIOIE for the interrupt
mask register. I had used a more verbose #define name because I worried
someone reading GPIOIE in functions might mistake it for an interrupt
enable register. This happened to me when I was originally working with
the gpio driver.

However I suppose the best solution would have been to get the datasheet
updated as I can see how it is best to have #define names in the driver
match the datasheet.

> +
> +/*
> + * Clear Edge-Triggered Interrupts. Write a 1 to clear the edge-triggered
> + * interrupt.
> + */
> +#define GPIOIC		0x030
> +
> +/*
> + * Edge-Triggered Interrupt Status. A 1 means the configured edge was detected.
> + */
> +#define GPIORIS		0x038
> +
> +/*
> + * Interrupt Status after Masking. A 1 means the configured edge or level was
> + * detected and not masked.
> + */
> +#define GPIOMIS		0x040
> +
> +/*
> + * Data Value. Dynamically reflects the value of the GPIO pin. If 1 the pin is
> + * a digital 1 and if 0 the pin is a digital 0.
> + */
> +#define GPIODIN		0x048
> +
> +/*
> + * From the data sheet section 12.2, there are 64 32-bit output data registers
> + * and 64 output enable registers. Output data and output enable registers for
> + * a given GPIO are contiguous. Eg. GPO0_DOUT_CFG is 0x50 and GPO0_DOEN_CFG is
> + * 0x54 while GPO1_DOUT_CFG is 0x58 and GPO1_DOEN_CFG is 0x5c.  The stride
> + * between GPIO registers is effectively 8, thus: GPOn_DOUT_CFG is 0x50 + 8n
> + * and GPOn_DOEN_CFG is 0x54 + 8n.
> + */
> +#define GPON_DOUT_CFG	0x050
> +#define GPON_DOEN_CFG	0x054
> +
> +/*
> + * From Section 12.3, there are 75 input signal configuration registers which
> + * are 4 bytes wide starting with GPI_CPU_JTAG_TCK_CFG at 0x250 and ending with
> + * GPI_USB_OVER_CURRENT_CFG 0x378
> + */
> +#define GPI_CFG_OFFSET	0x250
> +
> +/*
> + * Pad Control Bits. There are 16 pad control bits for each pin located in 103
> + * 32-bit registers controlling PAD_GPIO[0] to PAD_GPIO[63] followed by
> + * PAD_FUNC_SHARE[0] to PAD_FUNC_SHARE[141]. Odd numbered pins use the upper 16
> + * bit of each register.
> + */
> +#define PAD_SLEW_RATE_MASK		GENMASK(11, 9)
> +#define PAD_SLEW_RATE_POS		9
> +#define PAD_BIAS_STRONG_PULL_UP		BIT(8)
> +#define PAD_INPUT_ENABLE		BIT(7)
> +#define PAD_INPUT_SCHMITT_ENABLE	BIT(6)
> +#define PAD_BIAS_DISABLE		BIT(5)
> +#define PAD_BIAS_PULL_DOWN		BIT(4)
> +#define PAD_BIAS_MASK			(PAD_BIAS_STRONG_PULL_UP | \
> +					 PAD_BIAS_DISABLE | \
> +					 PAD_BIAS_PULL_DOWN)
> +#define PAD_DRIVE_STRENGTH_MASK		GENMASK(3, 0)
> +#define PAD_DRIVE_STRENGTH_POS		0
> +
> +/*
> + * From Section 11, the IO_PADSHARE_SEL register can be programmed to select
> + * one of seven pre-defined multiplexed signal groups on PAD_FUNC_SHARE and
> + * PAD_GPIO pads. This is a global setting.
> + */
> +#define IO_PADSHARE_SEL			0x1a0
> +
> +/*
> + * This just needs to be some number such that when
> + * sfp->gpio.pin_base = PAD_INVALID_GPIO then
> + * starfive_pin_to_gpio(sfp, validpin) is never a valid GPIO number.
> + * That is it should underflow and return something >= NR_GPIOS.
> + */
> +#define PAD_INVALID_GPIO		0x10000
> +
> +/*
> + * The packed pinmux values from the device tree look like this:
> + *
> + *  | 31 - 24 | 23 - 16 | 15 - 8 |     7    |     6    |  5 - 0  |
> + *  |  dout   |  doen   |  din   | dout rev | doen rev | gpio nr |
> + *
> + * ..but the GPOn_DOUT_CFG and GPOn_DOEN_CFG registers look like this:
> + *
> + *  |      31       | 30 - 8 |   7 - 0   |
> + *  | dout/doen rev | unused | dout/doen |
> + */
> +static unsigned int starfive_pinmux_to_gpio(u32 v)
> +{
> +	return v & (NR_GPIOS - 1);
> +}
> +
> +static u32 starfive_pinmux_to_dout(u32 v)
> +{
> +	return ((v & BIT(7)) << (31 - 7)) | ((v >> 24) & GENMASK(7, 0));
> +}
> +
> +static u32 starfive_pinmux_to_doen(u32 v)
> +{
> +	return ((v & BIT(6)) << (31 - 6)) | ((v >> 16) & GENMASK(7, 0));
> +}
> +
> +static u32 starfive_pinmux_to_din(u32 v)
> +{
> +	return (v >> 8) & GENMASK(7, 0);
> +}
> +
> +/*
> + * The maximum GPIO output current depends on the chosen drive strength:
> + *
> + *  DS:   0     1     2     3     4     5     6     7
> + *  mA:  14.2  21.2  28.2  35.2  42.2  49.1  56.0  62.8
> + *
> + * After rounding that is 7*DS + 14 mA
> + */
> +static u32 starfive_drive_strength_to_max_mA(u16 ds)
> +{
> +	return 7 * ds + 14;
> +}
> +
> +static u16 starfive_drive_strength_from_max_mA(u32 i)
> +{
> +	return (clamp(i, 14U, 63U) - 14) / 7;
> +}
> +
> +struct starfive_pinctrl {
> +	struct gpio_chip gc;
> +	struct pinctrl_gpio_range gpios;
> +	raw_spinlock_t lock;
> +	void __iomem *base;
> +	void __iomem *padctl;
> +	struct pinctrl_dev *pctl;
> +};
> +
> +static struct device *starfive_dev(const struct starfive_pinctrl *sfp)
> +{
> +	return sfp->gc.parent;
> +}
> +
> +static unsigned int starfive_pin_to_gpio(const struct starfive_pinctrl *sfp,
> +					 unsigned int pin)
> +{
> +	return pin - sfp->gpios.pin_base;
> +}
> +
> +static unsigned int starfive_gpio_to_pin(const struct starfive_pinctrl *sfp,
> +					 unsigned int gpio)
> +{
> +	return sfp->gpios.pin_base + gpio;
> +}
> +
> +static struct starfive_pinctrl *starfive_from_gc(struct gpio_chip *gc)
> +{
> +	return container_of(gc, struct starfive_pinctrl, gc);
> +}
> +
> +static struct starfive_pinctrl *starfive_from_irq_data(struct irq_data *d)
> +{
> +	return starfive_from_gc(irq_data_get_irq_chip_data(d));
> +}
> +
> +static struct starfive_pinctrl *starfive_from_irq_desc(struct irq_desc *desc)
> +{
> +	return starfive_from_gc(irq_desc_get_handler_data(desc));
> +}
> +
> +static const struct pinctrl_pin_desc starfive_pins[] = {
> +	PINCTRL_PIN(PAD_GPIO(0), "GPIO[0]"),
> +	PINCTRL_PIN(PAD_GPIO(1), "GPIO[1]"),
> +	PINCTRL_PIN(PAD_GPIO(2), "GPIO[2]"),
> +	PINCTRL_PIN(PAD_GPIO(3), "GPIO[3]"),
> +	PINCTRL_PIN(PAD_GPIO(4), "GPIO[4]"),
> +	PINCTRL_PIN(PAD_GPIO(5), "GPIO[5]"),
> +	PINCTRL_PIN(PAD_GPIO(6), "GPIO[6]"),
> +	PINCTRL_PIN(PAD_GPIO(7), "GPIO[7]"),
> +	PINCTRL_PIN(PAD_GPIO(8), "GPIO[8]"),
> +	PINCTRL_PIN(PAD_GPIO(9), "GPIO[9]"),
> +	PINCTRL_PIN(PAD_GPIO(10), "GPIO[10]"),
> +	PINCTRL_PIN(PAD_GPIO(11), "GPIO[11]"),
> +	PINCTRL_PIN(PAD_GPIO(12), "GPIO[12]"),
> +	PINCTRL_PIN(PAD_GPIO(13), "GPIO[13]"),
> +	PINCTRL_PIN(PAD_GPIO(14), "GPIO[14]"),
> +	PINCTRL_PIN(PAD_GPIO(15), "GPIO[15]"),
> +	PINCTRL_PIN(PAD_GPIO(16), "GPIO[16]"),
> +	PINCTRL_PIN(PAD_GPIO(17), "GPIO[17]"),
> +	PINCTRL_PIN(PAD_GPIO(18), "GPIO[18]"),
> +	PINCTRL_PIN(PAD_GPIO(19), "GPIO[19]"),
> +	PINCTRL_PIN(PAD_GPIO(20), "GPIO[20]"),
> +	PINCTRL_PIN(PAD_GPIO(21), "GPIO[21]"),
> +	PINCTRL_PIN(PAD_GPIO(22), "GPIO[22]"),
> +	PINCTRL_PIN(PAD_GPIO(23), "GPIO[23]"),
> +	PINCTRL_PIN(PAD_GPIO(24), "GPIO[24]"),
> +	PINCTRL_PIN(PAD_GPIO(25), "GPIO[25]"),
> +	PINCTRL_PIN(PAD_GPIO(26), "GPIO[26]"),
> +	PINCTRL_PIN(PAD_GPIO(27), "GPIO[27]"),
> +	PINCTRL_PIN(PAD_GPIO(28), "GPIO[28]"),
> +	PINCTRL_PIN(PAD_GPIO(29), "GPIO[29]"),
> +	PINCTRL_PIN(PAD_GPIO(30), "GPIO[30]"),
> +	PINCTRL_PIN(PAD_GPIO(31), "GPIO[31]"),
> +	PINCTRL_PIN(PAD_GPIO(32), "GPIO[32]"),
> +	PINCTRL_PIN(PAD_GPIO(33), "GPIO[33]"),
> +	PINCTRL_PIN(PAD_GPIO(34), "GPIO[34]"),
> +	PINCTRL_PIN(PAD_GPIO(35), "GPIO[35]"),
> +	PINCTRL_PIN(PAD_GPIO(36), "GPIO[36]"),
> +	PINCTRL_PIN(PAD_GPIO(37), "GPIO[37]"),
> +	PINCTRL_PIN(PAD_GPIO(38), "GPIO[38]"),
> +	PINCTRL_PIN(PAD_GPIO(39), "GPIO[39]"),
> +	PINCTRL_PIN(PAD_GPIO(40), "GPIO[40]"),
> +	PINCTRL_PIN(PAD_GPIO(41), "GPIO[41]"),
> +	PINCTRL_PIN(PAD_GPIO(42), "GPIO[42]"),
> +	PINCTRL_PIN(PAD_GPIO(43), "GPIO[43]"),
> +	PINCTRL_PIN(PAD_GPIO(44), "GPIO[44]"),
> +	PINCTRL_PIN(PAD_GPIO(45), "GPIO[45]"),
> +	PINCTRL_PIN(PAD_GPIO(46), "GPIO[46]"),
> +	PINCTRL_PIN(PAD_GPIO(47), "GPIO[47]"),
> +	PINCTRL_PIN(PAD_GPIO(48), "GPIO[48]"),
> +	PINCTRL_PIN(PAD_GPIO(49), "GPIO[49]"),
> +	PINCTRL_PIN(PAD_GPIO(50), "GPIO[50]"),
> +	PINCTRL_PIN(PAD_GPIO(51), "GPIO[51]"),
> +	PINCTRL_PIN(PAD_GPIO(52), "GPIO[52]"),
> +	PINCTRL_PIN(PAD_GPIO(53), "GPIO[53]"),
> +	PINCTRL_PIN(PAD_GPIO(54), "GPIO[54]"),
> +	PINCTRL_PIN(PAD_GPIO(55), "GPIO[55]"),
> +	PINCTRL_PIN(PAD_GPIO(56), "GPIO[56]"),
> +	PINCTRL_PIN(PAD_GPIO(57), "GPIO[57]"),
> +	PINCTRL_PIN(PAD_GPIO(58), "GPIO[58]"),
> +	PINCTRL_PIN(PAD_GPIO(59), "GPIO[59]"),
> +	PINCTRL_PIN(PAD_GPIO(60), "GPIO[60]"),
> +	PINCTRL_PIN(PAD_GPIO(61), "GPIO[61]"),
> +	PINCTRL_PIN(PAD_GPIO(62), "GPIO[62]"),
> +	PINCTRL_PIN(PAD_GPIO(63), "GPIO[63]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(0), "FUNC_SHARE[0]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(1), "FUNC_SHARE[1]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(2), "FUNC_SHARE[2]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(3), "FUNC_SHARE[3]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(4), "FUNC_SHARE[4]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(5), "FUNC_SHARE[5]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(6), "FUNC_SHARE[6]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(7), "FUNC_SHARE[7]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(8), "FUNC_SHARE[8]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(9), "FUNC_SHARE[9]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(10), "FUNC_SHARE[10]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(11), "FUNC_SHARE[11]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(12), "FUNC_SHARE[12]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(13), "FUNC_SHARE[13]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(14), "FUNC_SHARE[14]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(15), "FUNC_SHARE[15]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(16), "FUNC_SHARE[16]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(17), "FUNC_SHARE[17]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(18), "FUNC_SHARE[18]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(19), "FUNC_SHARE[19]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(20), "FUNC_SHARE[20]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(21), "FUNC_SHARE[21]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(22), "FUNC_SHARE[22]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(23), "FUNC_SHARE[23]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(24), "FUNC_SHARE[24]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(25), "FUNC_SHARE[25]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(26), "FUNC_SHARE[26]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(27), "FUNC_SHARE[27]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(28), "FUNC_SHARE[28]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(29), "FUNC_SHARE[29]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(30), "FUNC_SHARE[30]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(31), "FUNC_SHARE[31]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(32), "FUNC_SHARE[32]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(33), "FUNC_SHARE[33]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(34), "FUNC_SHARE[34]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(35), "FUNC_SHARE[35]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(36), "FUNC_SHARE[36]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(37), "FUNC_SHARE[37]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(38), "FUNC_SHARE[38]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(39), "FUNC_SHARE[39]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(40), "FUNC_SHARE[40]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(41), "FUNC_SHARE[41]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(42), "FUNC_SHARE[42]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(43), "FUNC_SHARE[43]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(44), "FUNC_SHARE[44]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(45), "FUNC_SHARE[45]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(46), "FUNC_SHARE[46]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(47), "FUNC_SHARE[47]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(48), "FUNC_SHARE[48]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(49), "FUNC_SHARE[49]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(50), "FUNC_SHARE[50]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(51), "FUNC_SHARE[51]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(52), "FUNC_SHARE[52]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(53), "FUNC_SHARE[53]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(54), "FUNC_SHARE[54]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(55), "FUNC_SHARE[55]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(56), "FUNC_SHARE[56]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(57), "FUNC_SHARE[57]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(58), "FUNC_SHARE[58]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(59), "FUNC_SHARE[59]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(60), "FUNC_SHARE[60]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(61), "FUNC_SHARE[61]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(62), "FUNC_SHARE[62]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(63), "FUNC_SHARE[63]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(64), "FUNC_SHARE[64]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(65), "FUNC_SHARE[65]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(66), "FUNC_SHARE[66]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(67), "FUNC_SHARE[67]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(68), "FUNC_SHARE[68]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(69), "FUNC_SHARE[69]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(70), "FUNC_SHARE[70]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(71), "FUNC_SHARE[71]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(72), "FUNC_SHARE[72]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(73), "FUNC_SHARE[73]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(74), "FUNC_SHARE[74]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(75), "FUNC_SHARE[75]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(76), "FUNC_SHARE[76]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(77), "FUNC_SHARE[77]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(78), "FUNC_SHARE[78]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(79), "FUNC_SHARE[79]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(80), "FUNC_SHARE[80]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(81), "FUNC_SHARE[81]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(82), "FUNC_SHARE[82]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(83), "FUNC_SHARE[83]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(84), "FUNC_SHARE[84]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(85), "FUNC_SHARE[85]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(86), "FUNC_SHARE[86]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(87), "FUNC_SHARE[87]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(88), "FUNC_SHARE[88]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(89), "FUNC_SHARE[89]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(90), "FUNC_SHARE[90]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(91), "FUNC_SHARE[91]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(92), "FUNC_SHARE[92]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(93), "FUNC_SHARE[93]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(94), "FUNC_SHARE[94]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(95), "FUNC_SHARE[95]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(96), "FUNC_SHARE[96]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(97), "FUNC_SHARE[97]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(98), "FUNC_SHARE[98]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(99), "FUNC_SHARE[99]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(100), "FUNC_SHARE[100]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(101), "FUNC_SHARE[101]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(102), "FUNC_SHARE[102]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(103), "FUNC_SHARE[103]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(104), "FUNC_SHARE[104]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(105), "FUNC_SHARE[105]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(106), "FUNC_SHARE[106]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(107), "FUNC_SHARE[107]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(108), "FUNC_SHARE[108]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(109), "FUNC_SHARE[109]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(110), "FUNC_SHARE[110]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(111), "FUNC_SHARE[111]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(112), "FUNC_SHARE[112]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(113), "FUNC_SHARE[113]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(114), "FUNC_SHARE[114]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(115), "FUNC_SHARE[115]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(116), "FUNC_SHARE[116]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(117), "FUNC_SHARE[117]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(118), "FUNC_SHARE[118]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(119), "FUNC_SHARE[119]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(120), "FUNC_SHARE[120]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(121), "FUNC_SHARE[121]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(122), "FUNC_SHARE[122]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(123), "FUNC_SHARE[123]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(124), "FUNC_SHARE[124]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(125), "FUNC_SHARE[125]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(126), "FUNC_SHARE[126]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(127), "FUNC_SHARE[127]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(128), "FUNC_SHARE[128]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(129), "FUNC_SHARE[129]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(130), "FUNC_SHARE[130]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(131), "FUNC_SHARE[131]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(132), "FUNC_SHARE[132]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(133), "FUNC_SHARE[133]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(134), "FUNC_SHARE[134]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(135), "FUNC_SHARE[135]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(136), "FUNC_SHARE[136]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(137), "FUNC_SHARE[137]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(138), "FUNC_SHARE[138]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(139), "FUNC_SHARE[139]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(140), "FUNC_SHARE[140]"),
> +	PINCTRL_PIN(PAD_FUNC_SHARE(141), "FUNC_SHARE[141]"),
> +};
> +
> +#ifdef CONFIG_DEBUG_FS
> +static void starfive_pin_dbg_show(struct pinctrl_dev *pctldev,
> +				  struct seq_file *s,
> +				  unsigned int pin)
> +{
> +	struct starfive_pinctrl *sfp = pinctrl_dev_get_drvdata(pctldev);
> +	unsigned int gpio = starfive_pin_to_gpio(sfp, pin);
> +	void __iomem *reg;
> +	u32 dout, doen;
> +
> +	if (gpio >= NR_GPIOS)
> +		return;
> +
> +	reg = sfp->base + GPON_DOUT_CFG + 8 * gpio;
> +	dout = readl_relaxed(reg + 0x000);
> +	doen = readl_relaxed(reg + 0x004);
> +
> +	seq_printf(s, "dout=%u%s doen=%u%s",
> +		   dout & (u32)GENMASK(7, 0), (dout & BIT(31)) ? "r" : "",
> +		   doen & (u32)GENMASK(7, 0), (doen & BIT(31)) ? "r" : "");
> +}
> +#else
> +#define starfive_pin_dbg_show NULL
> +#endif
> +
> +static int starfive_dt_node_to_map(struct pinctrl_dev *pctldev,
> +				   struct device_node *np,
> +				   struct pinctrl_map **maps,
> +				   unsigned int *num_maps)
> +{
> +	struct starfive_pinctrl *sfp = pinctrl_dev_get_drvdata(pctldev);
> +	struct device *dev = starfive_dev(sfp);
> +	const char **pgnames;
> +	struct pinctrl_map *map;
> +	struct device_node *child;
> +	const char *grpname;
> +	int *pins;
> +	u32 *pinmux;
> +	int nmaps;
> +	int ngroups;
> +	int ret;
> +
> +	nmaps = 0;
> +	ngroups = 0;
> +	for_each_child_of_node(np, child) {
> +		int npinmux = of_property_count_u32_elems(child, "pinmux");
> +		int npins   = of_property_count_u32_elems(child, "pins");
> +
> +		if (npinmux > 0 && npins > 0) {
> +			dev_err(dev, "invalid pinctrl group %pOFn.%pOFn: %s\n",
> +				np, child, "both pinmux and pins set");
> +			of_node_put(child);
> +			return -EINVAL;
> +		}
> +
> +		if (npinmux > 0) {
> +			nmaps += 2;
> +		} else if (npins > 0) {
> +			nmaps += 1;
> +		} else {
> +			dev_err(dev, "invalid pinctrl group %pOFn.%pOFn: %s\n",
> +				np, child, "neither pinmux nor pins set");
> +			of_node_put(child);
> +			return -EINVAL;
> +		}
> +		ngroups += 1;
> +	}
> +
> +	ret = -ENOMEM;
> +	pgnames = devm_kcalloc(dev, ngroups, sizeof(*pgnames), GFP_KERNEL);
> +	if (!pgnames)
> +		return ret;
> +
> +	map = kcalloc(nmaps, sizeof(*map), GFP_KERNEL);
> +	if (!map)
> +		goto free_pgnames;
> +
> +	nmaps = 0;
> +	ngroups = 0;
> +	for_each_child_of_node(np, child) {
> +		int npins;
> +		int i;
> +
> +		ret = -ENOMEM;
> +		grpname = devm_kasprintf(dev, GFP_KERNEL, "%s.%s", np->name, child->name);
> +		if (!grpname)
> +			goto put_child;
> +
> +		pgnames[ngroups++] = grpname;
> +
> +		if ((npins = of_property_count_u32_elems(child, "pinmux")) > 0) {
> +			pins = devm_kcalloc(dev, npins, sizeof(*pins), GFP_KERNEL);
> +			if (!pins)
> +				goto free_grpname;
> +
> +			pinmux = devm_kcalloc(dev, npins, sizeof(*pinmux), GFP_KERNEL);
> +			if (!pinmux)
> +				goto free_pins;
> +
> +			for (i = 0; i < npins; i++) {
> +				u32 v;
> +
> +				ret = of_property_read_u32_index(child, "pinmux", i, &v);
> +				if (ret)
> +					goto free_pinmux;
> +				pins[i] = starfive_gpio_to_pin(sfp, starfive_pinmux_to_gpio(v));
> +				pinmux[i] = v;
> +			}
> +
> +			map[nmaps].type = PIN_MAP_TYPE_MUX_GROUP;
> +			map[nmaps].data.mux.function = np->name;
> +			map[nmaps].data.mux.group = grpname;
> +			nmaps += 1;
> +		} else if ((npins = of_property_count_u32_elems(child, "pins")) > 0) {
> +			pins = devm_kcalloc(dev, npins, sizeof(*pins), GFP_KERNEL);
> +			if (!pins)
> +				goto free_grpname;
> +
> +			pinmux = NULL;
> +
> +			for (i = 0; i < npins; i++) {
> +				u32 v;
> +
> +				ret = of_property_read_u32_index(child, "pins", i, &v);
> +				if (ret)
> +					goto free_pins;
> +				pins[i] = v;
> +			}
> +		} else {
> +			ret = -EINVAL;
> +			goto free_grpname;
> +		}
> +
> +		ret = pinctrl_generic_add_group(pctldev, grpname, pins, npins, pinmux);
> +		if (ret < 0) {
> +			dev_err(dev, "error adding group %pOFn.%pOFn: %d\n",
> +				np, child, ret);
> +			goto free_pinmux;
> +		}
> +
> +		ret = pinconf_generic_parse_dt_config(child, pctldev,
> +						      &map[nmaps].data.configs.configs,
> +						      &map[nmaps].data.configs.num_configs);
> +		if (ret) {
> +			dev_err(dev, "invalid pinctrl group %pOFn.%pOFn: %s\n",
> +				np, child, "error parsing pin config");
> +			goto put_child;
> +		}
> +
> +		/* don't create a map if there are no pinconf settings */
> +		if (map[nmaps].data.configs.num_configs == 0)
> +			continue;
> +
> +		map[nmaps].type = PIN_MAP_TYPE_CONFIGS_GROUP;
> +		map[nmaps].data.configs.group_or_pin = grpname;
> +		nmaps += 1;
> +	}
> +
> +	ret = pinmux_generic_add_function(pctldev, np->name, pgnames, ngroups, NULL);
> +	if (ret < 0) {
> +		dev_err(dev, "error adding function %pOFn: %d\n", np, ret);
> +		goto free_map;
> +	}
> +
> +	*maps = map;
> +	*num_maps = nmaps;
> +	return 0;
> +
> +free_pinmux:
> +	devm_kfree(dev, pinmux);
> +free_pins:
> +	devm_kfree(dev, pins);
> +free_grpname:
> +	devm_kfree(dev, grpname);
> +put_child:
> +	of_node_put(child);
> +free_map:
> +	pinctrl_utils_free_map(pctldev, map, nmaps);
> +free_pgnames:
> +	devm_kfree(dev, pgnames);
> +	return ret;
> +}
> +
> +static const struct pinctrl_ops starfive_pinctrl_ops = {
> +	.get_groups_count = pinctrl_generic_get_group_count,
> +	.get_group_name = pinctrl_generic_get_group_name,
> +	.get_group_pins = pinctrl_generic_get_group_pins,
> +	.pin_dbg_show = starfive_pin_dbg_show,
> +	.dt_node_to_map = starfive_dt_node_to_map,
> +	.dt_free_map = pinctrl_utils_free_map,
> +};
> +
> +static int starfive_set_mux(struct pinctrl_dev *pctldev,
> +			    unsigned int fsel, unsigned int gsel)
> +{
> +	struct starfive_pinctrl *sfp = pinctrl_dev_get_drvdata(pctldev);
> +	struct device *dev = starfive_dev(sfp);
> +	const struct group_desc *group;
> +	const u32 *pinmux;
> +	unsigned int i;
> +
> +	group = pinctrl_generic_get_group(pctldev, gsel);
> +	if (!group)
> +		return -EINVAL;
> +
> +	pinmux = group->data;
> +	for (i = 0; i < group->num_pins; i++) {
> +		u32 v = pinmux[i];
> +		unsigned int gpio = starfive_pinmux_to_gpio(v);
> +		u32 dout = starfive_pinmux_to_dout(v);
> +		u32 doen = starfive_pinmux_to_doen(v);
> +		u32 din = starfive_pinmux_to_din(v);
> +		void __iomem *reg_dout;
> +		void __iomem *reg_doen;
> +		void __iomem *reg_din;
> +		unsigned long flags;
> +
> +		dev_dbg(dev, "GPIO%u: dout=0x%x doen=0x%x din=0x%x\n",
> +			gpio, dout, doen, din);
> +
> +		reg_dout = sfp->base + GPON_DOUT_CFG + 8 * gpio;
> +		reg_doen = sfp->base + GPON_DOEN_CFG + 8 * gpio;
> +		if (din != GPI_NONE)
> +			reg_din = sfp->base + GPI_CFG_OFFSET + 4 * din;
> +		else
> +			reg_din = NULL;
> +
> +		raw_spin_lock_irqsave(&sfp->lock, flags);
> +		writel_relaxed(dout, reg_dout);
> +		writel_relaxed(doen, reg_doen);
> +		if (reg_din)
> +			writel_relaxed(gpio + 2, reg_din);
> +		raw_spin_unlock_irqrestore(&sfp->lock, flags);
> +	}
> +
> +	return 0;
> +}
> +
> +static const struct pinmux_ops starfive_pinmux_ops = {
> +	.get_functions_count = pinmux_generic_get_function_count,
> +	.get_function_name = pinmux_generic_get_function_name,
> +	.get_function_groups = pinmux_generic_get_function_groups,
> +	.set_mux = starfive_set_mux,
> +	.strict = true,
> +};
> +
> +static u16 starfive_padctl_get(struct starfive_pinctrl *sfp,
> +			       unsigned int pin)
> +{
> +	void __iomem *reg = sfp->padctl + 4 * (pin / 2);
> +	int shift = 16 * (pin % 2);
> +
> +	return readl_relaxed(reg) >> shift;
> +}
> +
> +static void starfive_padctl_rmw(struct starfive_pinctrl *sfp,
> +				unsigned int pin,
> +				u16 _mask, u16 _value)
> +{
> +	void __iomem *reg = sfp->padctl + 4 * (pin / 2);
> +	int shift = 16 * (pin % 2);
> +	u32 mask = (u32)_mask << shift;
> +	u32 value = (u32)_value << shift;
> +	unsigned long flags;
> +
> +	dev_dbg(starfive_dev(sfp),
> +		"padctl_rmw(%u, 0x%03x, 0x%03x)\n", pin, _mask, _value);
> +
> +	raw_spin_lock_irqsave(&sfp->lock, flags);
> +	value |= readl_relaxed(reg) & ~mask;
> +	writel_relaxed(value, reg);
> +	raw_spin_unlock_irqrestore(&sfp->lock, flags);
> +}
> +
> +#define PIN_CONFIG_STARFIVE_STRONG_PULL_UP	(PIN_CONFIG_END + 1)
> +
> +static const struct pinconf_generic_params starfive_pinconf_custom_params[] = {
> +	{ "starfive,strong-pull-up", PIN_CONFIG_STARFIVE_STRONG_PULL_UP, 1 },
> +};
> +
> +#ifdef CONFIG_DEBUG_FS
> +static const struct pin_config_item starfive_pinconf_custom_conf_items[] = {
> +	PCONFDUMP(PIN_CONFIG_STARFIVE_STRONG_PULL_UP, "input bias strong pull-up", NULL, false),
> +};
> +
> +static_assert(ARRAY_SIZE(starfive_pinconf_custom_conf_items) ==
> +	      ARRAY_SIZE(starfive_pinconf_custom_params));
> +#else
> +#define starfive_pinconf_custom_conf_items NULL
> +#endif
> +
> +static int starfive_pinconf_get(struct pinctrl_dev *pctldev,
> +				unsigned int pin, unsigned long *config)
> +{
> +	struct starfive_pinctrl *sfp = pinctrl_dev_get_drvdata(pctldev);
> +	u16 value = starfive_padctl_get(sfp, pin);
> +	int param = pinconf_to_config_param(*config);
> +	u32 arg;
> +	bool enabled;
> +
> +	switch (param) {
> +	case PIN_CONFIG_BIAS_DISABLE:
> +		enabled = value & PAD_BIAS_DISABLE;
> +		arg = 0;
> +		break;
> +	case PIN_CONFIG_BIAS_PULL_DOWN:
> +		enabled = value & PAD_BIAS_PULL_DOWN;
> +		arg = 1;
> +		break;
> +	case PIN_CONFIG_BIAS_PULL_UP:
> +		enabled = !(value & PAD_BIAS_MASK);
> +		arg = 1;
> +		break;
> +	case PIN_CONFIG_DRIVE_STRENGTH:
> +		enabled = value & PAD_DRIVE_STRENGTH_MASK;
> +		arg = starfive_drive_strength_to_max_mA(value & PAD_DRIVE_STRENGTH_MASK);
> +		break;
> +	case PIN_CONFIG_INPUT_ENABLE:
> +		enabled = value & PAD_INPUT_ENABLE;
> +		arg = enabled;
> +		break;
> +	case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
> +		enabled = value & PAD_INPUT_SCHMITT_ENABLE;
> +		arg = enabled;
> +		break;
> +	case PIN_CONFIG_SLEW_RATE:
> +		enabled = value & PAD_SLEW_RATE_MASK;
> +		arg = (value & PAD_SLEW_RATE_MASK) >> PAD_SLEW_RATE_POS;
> +		break;
> +	case PIN_CONFIG_STARFIVE_STRONG_PULL_UP:
> +		enabled = value & PAD_BIAS_STRONG_PULL_UP;
> +		arg = enabled;
> +		break;
> +	default:
> +		return -ENOTSUPP;
> +	}
> +
> +	*config = pinconf_to_config_packed(param, arg);
> +	return enabled ? 0 : -EINVAL;
> +}
> +
> +static int starfive_pinconf_group_get(struct pinctrl_dev *pctldev,
> +				      unsigned int gsel, unsigned long *config)
> +{
> +	const struct group_desc *group;
> +
> +	group = pinctrl_generic_get_group(pctldev, gsel);
> +	if (!group)
> +		return -EINVAL;
> +
> +	return starfive_pinconf_get(pctldev, group->pins[0], config);
> +}
> +
> +static int starfive_pinconf_group_set(struct pinctrl_dev *pctldev,
> +				      unsigned int gsel,
> +				      unsigned long *configs,
> +				      unsigned int num_configs)
> +{
> +	struct starfive_pinctrl *sfp = pinctrl_dev_get_drvdata(pctldev);
> +	const struct group_desc *group;
> +	u16 mask, value;
> +	int i;
> +
> +	group = pinctrl_generic_get_group(pctldev, gsel);
> +	if (!group)
> +		return -EINVAL;
> +
> +	mask = 0;
> +	value = 0;
> +	for (i = 0; i < num_configs; i++) {
> +		int param = pinconf_to_config_param(configs[i]);
> +		u32 arg = pinconf_to_config_argument(configs[i]);
> +
> +		switch (param) {
> +		case PIN_CONFIG_BIAS_DISABLE:
> +			mask |= PAD_BIAS_MASK;
> +			value = (value & ~PAD_BIAS_MASK) | PAD_BIAS_DISABLE;
> +			break;
> +		case PIN_CONFIG_BIAS_PULL_DOWN:
> +			if (arg == 0)
> +				return -ENOTSUPP;
> +			mask |= PAD_BIAS_MASK;
> +			value = (value & ~PAD_BIAS_MASK) | PAD_BIAS_PULL_DOWN;
> +			break;
> +		case PIN_CONFIG_BIAS_PULL_UP:
> +			if (arg == 0)
> +				return -ENOTSUPP;
> +			mask |= PAD_BIAS_MASK;
> +			value = value & ~PAD_BIAS_MASK;
> +			break;
> +		case PIN_CONFIG_DRIVE_STRENGTH:
> +			mask |= PAD_DRIVE_STRENGTH_MASK;
> +			value = (value & ~PAD_DRIVE_STRENGTH_MASK) |
> +				starfive_drive_strength_from_max_mA(arg);
> +			break;
> +		case PIN_CONFIG_INPUT_ENABLE:
> +			mask |= PAD_INPUT_ENABLE;
> +			if (arg)
> +				value |= PAD_INPUT_ENABLE;
> +			else
> +				value &= ~PAD_INPUT_ENABLE;
> +			break;
> +		case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
> +			mask |= PAD_INPUT_SCHMITT_ENABLE;
> +			if (arg)
> +				value |= PAD_INPUT_SCHMITT_ENABLE;
> +			else
> +				value &= ~PAD_INPUT_SCHMITT_ENABLE;
> +			break;
> +		case PIN_CONFIG_SLEW_RATE:
> +			mask |= PAD_SLEW_RATE_MASK;
> +			value = (value & ~PAD_SLEW_RATE_MASK) |
> +				((arg << PAD_SLEW_RATE_POS) & PAD_SLEW_RATE_MASK);
> +			break;
> +		case PIN_CONFIG_STARFIVE_STRONG_PULL_UP:
> +			if (arg) {
> +				mask |= PAD_BIAS_MASK;
> +				value = (value & ~PAD_BIAS_MASK) |
> +					PAD_BIAS_STRONG_PULL_UP;
> +			} else {
> +				mask |= PAD_BIAS_STRONG_PULL_UP;
> +				value = value & ~PAD_BIAS_STRONG_PULL_UP;
> +			}
> +			break;
> +		default:
> +			return -ENOTSUPP;
> +		}
> +	}
> +
> +	for (i = 0; i < group->num_pins; i++)
> +		starfive_padctl_rmw(sfp, group->pins[i], mask, value);
> +
> +	return 0;
> +}
> +
> +#ifdef CONFIG_DEBUG_FS
> +static void starfive_pinconf_dbg_show(struct pinctrl_dev *pctldev,
> +				      struct seq_file *s, unsigned int pin)
> +{
> +	struct starfive_pinctrl *sfp = pinctrl_dev_get_drvdata(pctldev);
> +	u16 value = starfive_padctl_get(sfp, pin);
> +
> +	seq_printf(s, " (0x%03x)", value);
> +}
> +#else
> +#define starfive_pinconf_dbg_show NULL
> +#endif
> +
> +static const struct pinconf_ops starfive_pinconf_ops = {
> +	.pin_config_get = starfive_pinconf_get,
> +	.pin_config_group_get = starfive_pinconf_group_get,
> +	.pin_config_group_set = starfive_pinconf_group_set,
> +	.pin_config_dbg_show = starfive_pinconf_dbg_show,
> +	.is_generic = true,
> +};
> +
> +static struct pinctrl_desc starfive_desc = {
> +	.name = DRIVER_NAME,
> +	.pins = starfive_pins,
> +	.npins = ARRAY_SIZE(starfive_pins),
> +	.pctlops = &starfive_pinctrl_ops,
> +	.pmxops = &starfive_pinmux_ops,
> +	.confops = &starfive_pinconf_ops,
> +	.owner = THIS_MODULE,
> +	.num_custom_params = ARRAY_SIZE(starfive_pinconf_custom_params),
> +	.custom_params = starfive_pinconf_custom_params,
> +	.custom_conf_items = starfive_pinconf_custom_conf_items,
> +};
> +
> +static int starfive_gpio_request(struct gpio_chip *gc, unsigned int gpio)
> +{
> +	return pinctrl_gpio_request(gc->base + gpio);
> +}
> +
> +static void starfive_gpio_free(struct gpio_chip *gc, unsigned int gpio)
> +{
> +	pinctrl_gpio_free(gc->base + gpio);
> +}
> +
> +static int starfive_gpio_get_direction(struct gpio_chip *gc, unsigned int gpio)
> +{
> +	struct starfive_pinctrl *sfp = starfive_from_gc(gc);
> +
> +	if (gpio >= NR_GPIOS)
> +		return -EINVAL;
> +
> +	/* return GPIO_LINE_DIRECTION_OUT (0) only if doen == GPO_ENABLE (0) */
> +	return readl_relaxed(sfp->base + GPON_DOEN_CFG + 8 * gpio) != GPO_ENABLE;
> +}
> +
> +static int starfive_gpio_direction_input(struct gpio_chip *gc,
> +					 unsigned int gpio)
> +{
> +	struct starfive_pinctrl *sfp = starfive_from_gc(gc);
> +	void __iomem *doen;
> +	unsigned long flags;
> +
> +	if (gpio >= NR_GPIOS)
> +		return -EINVAL;
> +
> +	/* enable input and schmitt trigger */
> +	starfive_padctl_rmw(sfp, starfive_gpio_to_pin(sfp, gpio),
> +			    PAD_INPUT_ENABLE | PAD_INPUT_SCHMITT_ENABLE,
> +			    PAD_INPUT_ENABLE | PAD_INPUT_SCHMITT_ENABLE);
> +
> +	doen = sfp->base + GPON_DOEN_CFG + 8 * gpio;
> +	raw_spin_lock_irqsave(&sfp->lock, flags);
> +	writel_relaxed(GPO_DISABLE, doen);
> +	raw_spin_unlock_irqrestore(&sfp->lock, flags);
> +	return 0;
> +}
> +
> +static int starfive_gpio_direction_output(struct gpio_chip *gc,
> +					  unsigned int gpio, int value)
> +{
> +	struct starfive_pinctrl *sfp = starfive_from_gc(gc);
> +	void __iomem *dout;
> +	void __iomem *doen;
> +	unsigned long flags;
> +
> +	if (gpio >= NR_GPIOS)
> +		return -EINVAL;
> +
> +	dout = sfp->base + GPON_DOUT_CFG + 8 * gpio;
> +	doen = sfp->base + GPON_DOEN_CFG + 8 * gpio;
> +	raw_spin_lock_irqsave(&sfp->lock, flags);
> +	writel_relaxed(value, dout);
> +	writel_relaxed(GPO_ENABLE, doen);
> +	raw_spin_unlock_irqrestore(&sfp->lock, flags);
> +
> +	/* disable input, schmitt trigger and bias */
> +	starfive_padctl_rmw(sfp, starfive_gpio_to_pin(sfp, gpio),
> +			    PAD_BIAS_MASK | PAD_INPUT_ENABLE | PAD_INPUT_SCHMITT_ENABLE,
> +			    PAD_BIAS_DISABLE);
> +
> +	return 0;
> +}
> +
> +static int starfive_gpio_get(struct gpio_chip *gc, unsigned int gpio)
> +{
> +	struct starfive_pinctrl *sfp = starfive_from_gc(gc);
> +	void __iomem *din;
> +
> +	if (gpio >= NR_GPIOS)
> +		return -EINVAL;
> +
> +	din = sfp->base + GPIODIN + 4 * (gpio / 32);
> +	return !!(readl_relaxed(din) & BIT(gpio % 32));
> +}
> +
> +static void starfive_gpio_set(struct gpio_chip *gc, unsigned int gpio,
> +			      int value)
> +{
> +	struct starfive_pinctrl *sfp = starfive_from_gc(gc);
> +	void __iomem *dout;
> +	unsigned long flags;
> +
> +	if (gpio >= NR_GPIOS)
> +		return;
> +
> +	dout = sfp->base + GPON_DOUT_CFG + 8 * gpio;
> +	raw_spin_lock_irqsave(&sfp->lock, flags);
> +	writel_relaxed(value, dout);
> +	raw_spin_unlock_irqrestore(&sfp->lock, flags);
> +}
> +
> +static int starfive_gpio_set_config(struct gpio_chip *gc, unsigned int gpio,
> +				    unsigned long config)
> +{
> +	struct starfive_pinctrl *sfp = starfive_from_gc(gc);
> +	u32 arg = pinconf_to_config_argument(config);
> +	u16 mask;
> +	u16 value;
> +
> +	switch (pinconf_to_config_param(config)) {
> +	case PIN_CONFIG_BIAS_DISABLE:
> +		mask  = PAD_BIAS_MASK;
> +		value = PAD_BIAS_DISABLE;
> +		break;
> +	case PIN_CONFIG_BIAS_PULL_DOWN:
> +		if (arg == 0)
> +			return -ENOTSUPP;
> +		mask  = PAD_BIAS_MASK;
> +		value = PAD_BIAS_PULL_DOWN;
> +		break;
> +	case PIN_CONFIG_BIAS_PULL_UP:
> +		if (arg == 0)
> +			return -ENOTSUPP;
> +		mask  = PAD_BIAS_MASK;
> +		value = 0;
> +		break;
> +	case PIN_CONFIG_DRIVE_PUSH_PULL:
> +		return 0;
> +	case PIN_CONFIG_INPUT_ENABLE:
> +		mask  = PAD_INPUT_ENABLE;
> +		value = arg ? PAD_INPUT_ENABLE : 0;
> +		break;
> +	case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
> +		mask  = PAD_INPUT_SCHMITT_ENABLE;
> +		value = arg ? PAD_INPUT_SCHMITT_ENABLE : 0;
> +		break;
> +	default:
> +		return -ENOTSUPP;
> +	};
> +
> +	starfive_padctl_rmw(sfp, starfive_gpio_to_pin(sfp, gpio), mask, value);
> +	return 0;
> +}
> +
> +static int starfive_gpio_add_pin_ranges(struct gpio_chip *gc)
> +{
> +	struct starfive_pinctrl *sfp = starfive_from_gc(gc);
> +
> +	sfp->gpios.name = sfp->gc.label;
> +	sfp->gpios.base = sfp->gc.base;
> +	/*
> +	 * sfp->gpios.pin_base depends on the chosen signal group
> +	 * and is set in starfive_probe()
> +	 */
> +	sfp->gpios.npins = NR_GPIOS;
> +	sfp->gpios.gc = &sfp->gc;
> +	pinctrl_add_gpio_range(sfp->pctl, &sfp->gpios);
> +	return 0;
> +}
> +
> +static void starfive_irq_ack(struct irq_data *d)
> +{
> +	struct starfive_pinctrl *sfp = starfive_from_irq_data(d);
> +	irq_hw_number_t gpio = irqd_to_hwirq(d);
> +	void __iomem *ic = sfp->base + GPIOIC + 4 * (gpio / 32);
> +	u32 mask = BIT(gpio % 32);
> +	unsigned long flags;
> +
> +	raw_spin_lock_irqsave(&sfp->lock, flags);
> +	writel_relaxed(mask, ic);
> +	raw_spin_unlock_irqrestore(&sfp->lock, flags);
> +}
> +
> +static void starfive_irq_mask(struct irq_data *d)
> +{
> +	struct starfive_pinctrl *sfp = starfive_from_irq_data(d);
> +	irq_hw_number_t gpio = irqd_to_hwirq(d);
> +	void __iomem *ie = sfp->base + GPIOIE + 4 * (gpio / 32);
> +	u32 mask = BIT(gpio % 32);
> +	unsigned long flags;
> +	u32 value;
> +
> +	raw_spin_lock_irqsave(&sfp->lock, flags);
> +	value = readl_relaxed(ie) & ~mask;
> +	writel_relaxed(value, ie);
> +	raw_spin_unlock_irqrestore(&sfp->lock, flags);
> +}
> +
> +static void starfive_irq_mask_ack(struct irq_data *d)
> +{
> +	struct starfive_pinctrl *sfp = starfive_from_irq_data(d);
> +	irq_hw_number_t gpio = irqd_to_hwirq(d);
> +	void __iomem *ie = sfp->base + GPIOIE + 4 * (gpio / 32);
> +	void __iomem *ic = sfp->base + GPIOIC + 4 * (gpio / 32);
> +	u32 mask = BIT(gpio % 32);
> +	unsigned long flags;
> +	u32 value;
> +
> +	raw_spin_lock_irqsave(&sfp->lock, flags);
> +	value = readl_relaxed(ie) & ~mask;
> +	writel_relaxed(value, ie);
> +	writel_relaxed(mask, ic);
> +	raw_spin_unlock_irqrestore(&sfp->lock, flags);
> +}
> +
> +static void starfive_irq_unmask(struct irq_data *d)
> +{
> +	struct starfive_pinctrl *sfp = starfive_from_irq_data(d);
> +	irq_hw_number_t gpio = irqd_to_hwirq(d);
> +	void __iomem *ie = sfp->base + GPIOIE + 4 * (gpio / 32);
> +	u32 mask = BIT(gpio % 32);
> +	unsigned long flags;
> +	u32 value;
> +
> +	raw_spin_lock_irqsave(&sfp->lock, flags);
> +	value = readl_relaxed(ie) | mask;
> +	writel_relaxed(value, ie);
> +	raw_spin_unlock_irqrestore(&sfp->lock, flags);
> +}
> +
> +static int starfive_irq_set_type(struct irq_data *d, unsigned int trigger)
> +{
> +	struct starfive_pinctrl *sfp = starfive_from_irq_data(d);
> +	irq_hw_number_t gpio = irqd_to_hwirq(d);
> +	void __iomem *base = sfp->base + 4 * (gpio / 32);
> +	u32 mask = BIT(gpio % 32);
> +	u32 irq_type, edge_both, polarity;
> +	irq_flow_handler_t handler;
> +	unsigned long flags;
> +
> +	switch (trigger) {
> +	case IRQ_TYPE_EDGE_RISING:
> +		irq_type  = mask; /* 1: edge triggered */
> +		edge_both = 0;    /* 0: single edge */
> +		polarity  = mask; /* 1: rising edge */
> +		handler   = handle_edge_irq;
> +		break;
> +	case IRQ_TYPE_EDGE_FALLING:
> +		irq_type  = mask; /* 1: edge triggered */
> +		edge_both = 0;    /* 0: single edge */
> +		polarity  = 0;    /* 0: falling edge */
> +		handler   = handle_edge_irq;
> +		break;
> +	case IRQ_TYPE_EDGE_BOTH:
> +		irq_type  = mask; /* 1: edge triggered */
> +		edge_both = mask; /* 1: both edges */
> +		polarity  = 0;    /* 0: ignored */
> +		handler   = handle_edge_irq;
> +		break;
> +	case IRQ_TYPE_LEVEL_HIGH:
> +		irq_type  = 0;    /* 0: level triggered */
> +		edge_both = 0;    /* 0: ignored */
> +		polarity  = mask; /* 1: high level */
> +		handler   = handle_level_irq;
> +		break;
> +	case IRQ_TYPE_LEVEL_LOW:
> +		irq_type  = 0;    /* 0: level triggered */
> +		edge_both = 0;    /* 0: ignored */
> +		polarity  = 0;    /* 0: low level */
> +		handler   = handle_level_irq;
> +		break;
> +	default:
> +		irq_set_handler_locked(d, handle_bad_irq);
> +		return -EINVAL;
> +	}
> +
> +	irq_set_handler_locked(d, handler);
> +
> +	raw_spin_lock_irqsave(&sfp->lock, flags);
> +	irq_type |= readl_relaxed(base + GPIOIS) & ~mask;
> +	writel_relaxed(irq_type, base + GPIOIS);
> +	edge_both |= readl_relaxed(base + GPIOIBE) & ~mask;
> +	writel_relaxed(edge_both, base + GPIOIBE);
> +	polarity |= readl_relaxed(base + GPIOIEV) & ~mask;
> +	writel_relaxed(polarity, base + GPIOIEV);
> +	raw_spin_unlock_irqrestore(&sfp->lock, flags);
> +	return 0;
> +}
> +
> +static struct irq_chip starfive_irq_chip = {
> +	.irq_ack = starfive_irq_ack,
> +	.irq_mask = starfive_irq_mask,
> +	.irq_mask_ack = starfive_irq_mask_ack,
> +	.irq_unmask = starfive_irq_unmask,
> +	.irq_set_type = starfive_irq_set_type,
> +	.flags = IRQCHIP_SET_TYPE_MASKED,
> +};
> +
> +static void starfive_gpio_irq_handler(struct irq_desc *desc)
> +{
> +	struct starfive_pinctrl *sfp = starfive_from_irq_desc(desc);
> +	struct irq_chip *chip = irq_desc_get_chip(desc);
> +	unsigned long mis;
> +	unsigned int pin;
> +
> +	chained_irq_enter(chip, desc);
> +
> +	mis = readl_relaxed(sfp->base + GPIOMIS + 0);
> +	for_each_set_bit(pin, &mis, 32)
> +		generic_handle_domain_irq(sfp->gc.irq.domain, pin);
> +
> +	mis = readl_relaxed(sfp->base + GPIOMIS + 4);
> +	for_each_set_bit(pin, &mis, 32)
> +		generic_handle_domain_irq(sfp->gc.irq.domain, pin + 32);
> +
> +	chained_irq_exit(chip, desc);
> +}
> +
> +static int starfive_gpio_init_hw(struct gpio_chip *gc)
> +{
> +	struct starfive_pinctrl *sfp = starfive_from_gc(gc);
> +
> +	/* mask all GPIO interrupts */
> +	writel(0, sfp->base + GPIOIE + 0);
> +	writel(0, sfp->base + GPIOIE + 4);

Woudln't 0 in GPIOIE mean mask is disabled for all interrupts?

In other words, wouldn't this enable all the interrupts?

Thanks,
Drew

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 12/16] pinctrl: starfive: Add pinctrl driver for StarFive SoCs
  2021-10-21 19:01     ` Drew Fustini
@ 2021-10-21 19:50       ` Emil Renner Berthing
  -1 siblings, 0 replies; 143+ messages in thread
From: Emil Renner Berthing @ 2021-10-21 19:50 UTC (permalink / raw)
  To: Drew Fustini
  Cc: linux-riscv,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	linux-clk, open list:GPIO SUBSYSTEM, open list:SERIAL DRIVERS,
	Palmer Dabbelt, Paul Walmsley, Rob Herring, Michael Turquette,
	Stephen Boyd, Thomas Gleixner, Marc Zyngier, Philipp Zabel,
	Linus Walleij, Greg Kroah-Hartman, Daniel Lezcano,
	Andy Shevchenko, Jiri Slaby, Maximilian Luz, Sagar Kadam,
	Drew Fustini, Geert Uytterhoeven, Michael Zhu, Fu Wei,
	Anup Patel, Atish Patra, Matteo Croce, Linux Kernel Mailing List,
	Huan Feng

On Thu, 21 Oct 2021 at 21:01, Drew Fustini <dfustini@baylibre.com> wrote:
> On Thu, Oct 21, 2021 at 07:42:19PM +0200, Emil Renner Berthing wrote:
> > +/*
> > + * Interrupt Trigger Polarity. If set to 1 the interrupt is triggered on a
> > + * rising edge (edge-triggered) or high level (level-triggered). If set to 0 the
> > + * interrupt is triggered on a falling edge (edge-triggered) or low level
> > + * (level-triggered).
> > + */
> > +#define GPIOIEV              0x020
> > +
> > +/*
> > + * Interrupt Mask. If set to 1 the interrupt is disabled (masked). If set to 0
> > + * the interrupt is enabled (unmasked).
> > + */
> > +#define GPIOIE               0x028
>
> It bothered me that the datasheet used the term GPIOIE for the interrupt
> mask register. I had used a more verbose #define name because I worried
> someone reading GPIOIE in functions might mistake it for an interrupt
> enable register. This happened to me when I was originally working with
> the gpio driver.
>
> However I suppose the best solution would have been to get the datasheet
> updated as I can see how it is best to have #define names in the driver
> match the datasheet.
>
> > +static void starfive_irq_mask(struct irq_data *d)
> > +{
> > +     struct starfive_pinctrl *sfp = starfive_from_irq_data(d);
> > +     irq_hw_number_t gpio = irqd_to_hwirq(d);
> > +     void __iomem *ie = sfp->base + GPIOIE + 4 * (gpio / 32);
> > +     u32 mask = BIT(gpio % 32);
> > +     unsigned long flags;
> > +     u32 value;
> > +
> > +     raw_spin_lock_irqsave(&sfp->lock, flags);
> > +     value = readl_relaxed(ie) & ~mask;
> > +     writel_relaxed(value, ie);
> > +     raw_spin_unlock_irqrestore(&sfp->lock, flags);
> > +}
> > +
> > +static void starfive_irq_mask_ack(struct irq_data *d)
> > +{
> > +     struct starfive_pinctrl *sfp = starfive_from_irq_data(d);
> > +     irq_hw_number_t gpio = irqd_to_hwirq(d);
> > +     void __iomem *ie = sfp->base + GPIOIE + 4 * (gpio / 32);
> > +     void __iomem *ic = sfp->base + GPIOIC + 4 * (gpio / 32);
> > +     u32 mask = BIT(gpio % 32);
> > +     unsigned long flags;
> > +     u32 value;
> > +
> > +     raw_spin_lock_irqsave(&sfp->lock, flags);
> > +     value = readl_relaxed(ie) & ~mask;
> > +     writel_relaxed(value, ie);
> > +     writel_relaxed(mask, ic);
> > +     raw_spin_unlock_irqrestore(&sfp->lock, flags);
> > +}
> > +
> > +static void starfive_irq_unmask(struct irq_data *d)
> > +{
> > +     struct starfive_pinctrl *sfp = starfive_from_irq_data(d);
> > +     irq_hw_number_t gpio = irqd_to_hwirq(d);
> > +     void __iomem *ie = sfp->base + GPIOIE + 4 * (gpio / 32);
> > +     u32 mask = BIT(gpio % 32);
> > +     unsigned long flags;
> > +     u32 value;
> > +
> > +     raw_spin_lock_irqsave(&sfp->lock, flags);
> > +     value = readl_relaxed(ie) | mask;
> > +     writel_relaxed(value, ie);
> > +     raw_spin_unlock_irqrestore(&sfp->lock, flags);
> > +}
> > +

...

> > +static int starfive_gpio_init_hw(struct gpio_chip *gc)
> > +{
> > +     struct starfive_pinctrl *sfp = starfive_from_gc(gc);
> > +
> > +     /* mask all GPIO interrupts */
> > +     writel(0, sfp->base + GPIOIE + 0);
> > +     writel(0, sfp->base + GPIOIE + 4);
>
> Woudln't 0 in GPIOIE mean mask is disabled for all interrupts?
>
> In other words, wouldn't this enable all the interrupts?

Heh, you're right. The code does the exact opposite of what the
documentation says it should be doing. However I just tried and with
the code as it is now GPIO interrupts work fine, but with the logic
flipped the kernel fails to boot. I'm guessing because an interrupt
storm. So it seems to me the documentation might be wrong and GPIOIE
is actually a good name.

Michael Zhu: Can you confirm if a 1 or 0 enables the interrupt in the
GPIOIE registers?

/Emil

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 12/16] pinctrl: starfive: Add pinctrl driver for StarFive SoCs
@ 2021-10-21 19:50       ` Emil Renner Berthing
  0 siblings, 0 replies; 143+ messages in thread
From: Emil Renner Berthing @ 2021-10-21 19:50 UTC (permalink / raw)
  To: Drew Fustini
  Cc: linux-riscv,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	linux-clk, open list:GPIO SUBSYSTEM, open list:SERIAL DRIVERS,
	Palmer Dabbelt, Paul Walmsley, Rob Herring, Michael Turquette,
	Stephen Boyd, Thomas Gleixner, Marc Zyngier, Philipp Zabel,
	Linus Walleij, Greg Kroah-Hartman, Daniel Lezcano,
	Andy Shevchenko, Jiri Slaby, Maximilian Luz, Sagar Kadam,
	Drew Fustini, Geert Uytterhoeven, Michael Zhu, Fu Wei,
	Anup Patel, Atish Patra, Matteo Croce, Linux Kernel Mailing List,
	Huan Feng

On Thu, 21 Oct 2021 at 21:01, Drew Fustini <dfustini@baylibre.com> wrote:
> On Thu, Oct 21, 2021 at 07:42:19PM +0200, Emil Renner Berthing wrote:
> > +/*
> > + * Interrupt Trigger Polarity. If set to 1 the interrupt is triggered on a
> > + * rising edge (edge-triggered) or high level (level-triggered). If set to 0 the
> > + * interrupt is triggered on a falling edge (edge-triggered) or low level
> > + * (level-triggered).
> > + */
> > +#define GPIOIEV              0x020
> > +
> > +/*
> > + * Interrupt Mask. If set to 1 the interrupt is disabled (masked). If set to 0
> > + * the interrupt is enabled (unmasked).
> > + */
> > +#define GPIOIE               0x028
>
> It bothered me that the datasheet used the term GPIOIE for the interrupt
> mask register. I had used a more verbose #define name because I worried
> someone reading GPIOIE in functions might mistake it for an interrupt
> enable register. This happened to me when I was originally working with
> the gpio driver.
>
> However I suppose the best solution would have been to get the datasheet
> updated as I can see how it is best to have #define names in the driver
> match the datasheet.
>
> > +static void starfive_irq_mask(struct irq_data *d)
> > +{
> > +     struct starfive_pinctrl *sfp = starfive_from_irq_data(d);
> > +     irq_hw_number_t gpio = irqd_to_hwirq(d);
> > +     void __iomem *ie = sfp->base + GPIOIE + 4 * (gpio / 32);
> > +     u32 mask = BIT(gpio % 32);
> > +     unsigned long flags;
> > +     u32 value;
> > +
> > +     raw_spin_lock_irqsave(&sfp->lock, flags);
> > +     value = readl_relaxed(ie) & ~mask;
> > +     writel_relaxed(value, ie);
> > +     raw_spin_unlock_irqrestore(&sfp->lock, flags);
> > +}
> > +
> > +static void starfive_irq_mask_ack(struct irq_data *d)
> > +{
> > +     struct starfive_pinctrl *sfp = starfive_from_irq_data(d);
> > +     irq_hw_number_t gpio = irqd_to_hwirq(d);
> > +     void __iomem *ie = sfp->base + GPIOIE + 4 * (gpio / 32);
> > +     void __iomem *ic = sfp->base + GPIOIC + 4 * (gpio / 32);
> > +     u32 mask = BIT(gpio % 32);
> > +     unsigned long flags;
> > +     u32 value;
> > +
> > +     raw_spin_lock_irqsave(&sfp->lock, flags);
> > +     value = readl_relaxed(ie) & ~mask;
> > +     writel_relaxed(value, ie);
> > +     writel_relaxed(mask, ic);
> > +     raw_spin_unlock_irqrestore(&sfp->lock, flags);
> > +}
> > +
> > +static void starfive_irq_unmask(struct irq_data *d)
> > +{
> > +     struct starfive_pinctrl *sfp = starfive_from_irq_data(d);
> > +     irq_hw_number_t gpio = irqd_to_hwirq(d);
> > +     void __iomem *ie = sfp->base + GPIOIE + 4 * (gpio / 32);
> > +     u32 mask = BIT(gpio % 32);
> > +     unsigned long flags;
> > +     u32 value;
> > +
> > +     raw_spin_lock_irqsave(&sfp->lock, flags);
> > +     value = readl_relaxed(ie) | mask;
> > +     writel_relaxed(value, ie);
> > +     raw_spin_unlock_irqrestore(&sfp->lock, flags);
> > +}
> > +

...

> > +static int starfive_gpio_init_hw(struct gpio_chip *gc)
> > +{
> > +     struct starfive_pinctrl *sfp = starfive_from_gc(gc);
> > +
> > +     /* mask all GPIO interrupts */
> > +     writel(0, sfp->base + GPIOIE + 0);
> > +     writel(0, sfp->base + GPIOIE + 4);
>
> Woudln't 0 in GPIOIE mean mask is disabled for all interrupts?
>
> In other words, wouldn't this enable all the interrupts?

Heh, you're right. The code does the exact opposite of what the
documentation says it should be doing. However I just tried and with
the code as it is now GPIO interrupts work fine, but with the logic
flipped the kernel fails to boot. I'm guessing because an interrupt
storm. So it seems to me the documentation might be wrong and GPIOIE
is actually a good name.

Michael Zhu: Can you confirm if a 1 or 0 enables the interrupt in the
GPIOIE registers?

/Emil

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 12/16] pinctrl: starfive: Add pinctrl driver for StarFive SoCs
  2021-10-21 19:50       ` Emil Renner Berthing
@ 2021-10-22  2:06         ` Drew Fustini
  -1 siblings, 0 replies; 143+ messages in thread
From: Drew Fustini @ 2021-10-22  2:06 UTC (permalink / raw)
  To: Emil Renner Berthing
  Cc: linux-riscv,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	linux-clk, open list:GPIO SUBSYSTEM, open list:SERIAL DRIVERS,
	Palmer Dabbelt, Paul Walmsley, Rob Herring, Michael Turquette,
	Stephen Boyd, Thomas Gleixner, Marc Zyngier, Philipp Zabel,
	Linus Walleij, Greg Kroah-Hartman, Daniel Lezcano,
	Andy Shevchenko, Jiri Slaby, Maximilian Luz, Sagar Kadam,
	Drew Fustini, Geert Uytterhoeven, Michael Zhu, Fu Wei,
	Anup Patel, Atish Patra, Matteo Croce, Linux Kernel Mailing List,
	Huan Feng

On Thu, Oct 21, 2021 at 09:50:42PM +0200, Emil Renner Berthing wrote:
> On Thu, 21 Oct 2021 at 21:01, Drew Fustini <dfustini@baylibre.com> wrote:
> > On Thu, Oct 21, 2021 at 07:42:19PM +0200, Emil Renner Berthing wrote:
> > > +/*
> > > + * Interrupt Trigger Polarity. If set to 1 the interrupt is triggered on a
> > > + * rising edge (edge-triggered) or high level (level-triggered). If set to 0 the
> > > + * interrupt is triggered on a falling edge (edge-triggered) or low level
> > > + * (level-triggered).
> > > + */
> > > +#define GPIOIEV              0x020
> > > +
> > > +/*
> > > + * Interrupt Mask. If set to 1 the interrupt is disabled (masked). If set to 0
> > > + * the interrupt is enabled (unmasked).
> > > + */
> > > +#define GPIOIE               0x028
> >
> > It bothered me that the datasheet used the term GPIOIE for the interrupt
> > mask register. I had used a more verbose #define name because I worried
> > someone reading GPIOIE in functions might mistake it for an interrupt
> > enable register. This happened to me when I was originally working with
> > the gpio driver.
> >
> > However I suppose the best solution would have been to get the datasheet
> > updated as I can see how it is best to have #define names in the driver
> > match the datasheet.
> >
> > > +static void starfive_irq_mask(struct irq_data *d)
> > > +{
> > > +     struct starfive_pinctrl *sfp = starfive_from_irq_data(d);
> > > +     irq_hw_number_t gpio = irqd_to_hwirq(d);
> > > +     void __iomem *ie = sfp->base + GPIOIE + 4 * (gpio / 32);
> > > +     u32 mask = BIT(gpio % 32);
> > > +     unsigned long flags;
> > > +     u32 value;
> > > +
> > > +     raw_spin_lock_irqsave(&sfp->lock, flags);
> > > +     value = readl_relaxed(ie) & ~mask;
> > > +     writel_relaxed(value, ie);
> > > +     raw_spin_unlock_irqrestore(&sfp->lock, flags);
> > > +}
> > > +
> > > +static void starfive_irq_mask_ack(struct irq_data *d)
> > > +{
> > > +     struct starfive_pinctrl *sfp = starfive_from_irq_data(d);
> > > +     irq_hw_number_t gpio = irqd_to_hwirq(d);
> > > +     void __iomem *ie = sfp->base + GPIOIE + 4 * (gpio / 32);
> > > +     void __iomem *ic = sfp->base + GPIOIC + 4 * (gpio / 32);
> > > +     u32 mask = BIT(gpio % 32);
> > > +     unsigned long flags;
> > > +     u32 value;
> > > +
> > > +     raw_spin_lock_irqsave(&sfp->lock, flags);
> > > +     value = readl_relaxed(ie) & ~mask;
> > > +     writel_relaxed(value, ie);
> > > +     writel_relaxed(mask, ic);
> > > +     raw_spin_unlock_irqrestore(&sfp->lock, flags);
> > > +}
> > > +
> > > +static void starfive_irq_unmask(struct irq_data *d)
> > > +{
> > > +     struct starfive_pinctrl *sfp = starfive_from_irq_data(d);
> > > +     irq_hw_number_t gpio = irqd_to_hwirq(d);
> > > +     void __iomem *ie = sfp->base + GPIOIE + 4 * (gpio / 32);
> > > +     u32 mask = BIT(gpio % 32);
> > > +     unsigned long flags;
> > > +     u32 value;
> > > +
> > > +     raw_spin_lock_irqsave(&sfp->lock, flags);
> > > +     value = readl_relaxed(ie) | mask;
> > > +     writel_relaxed(value, ie);
> > > +     raw_spin_unlock_irqrestore(&sfp->lock, flags);
> > > +}
> > > +
> 
> ...
> 
> > > +static int starfive_gpio_init_hw(struct gpio_chip *gc)
> > > +{
> > > +     struct starfive_pinctrl *sfp = starfive_from_gc(gc);
> > > +
> > > +     /* mask all GPIO interrupts */
> > > +     writel(0, sfp->base + GPIOIE + 0);
> > > +     writel(0, sfp->base + GPIOIE + 4);
> >
> > Woudln't 0 in GPIOIE mean mask is disabled for all interrupts?
> >
> > In other words, wouldn't this enable all the interrupts?
> 
> Heh, you're right. The code does the exact opposite of what the
> documentation says it should be doing. However I just tried and with
> the code as it is now GPIO interrupts work fine, but with the logic
> flipped the kernel fails to boot. I'm guessing because an interrupt
> storm. So it seems to me the documentation might be wrong and GPIOIE
> is actually a good name.

Ah, it seems I once knew this back in July [1] but never got the
documentation changed:

NOTE: Table 12-9 in the JH7100 datasheet is incorrect regarding fields
GPIOIE_0 and GPIOIE_1. An interrupt is enabled (unmasked) when the bit
is   set to 1 and it is disabled (masked) when set to 0. The datasheet
incorrectly states the opposite. I think this is due to the datasheet
author thinking of it as mask field which it is not, it is an enable
field. I will raise an issue on the documentation repo.


> 
> Michael Zhu: Can you confirm if a 1 or 0 enables the interrupt in the
> GPIOIE registers?
> 
> /Emil

[1] https://github.com/esmil/linux/pull/34/commits/e247a259e40312d0202cdbdd686dbba09afc7813

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 12/16] pinctrl: starfive: Add pinctrl driver for StarFive SoCs
@ 2021-10-22  2:06         ` Drew Fustini
  0 siblings, 0 replies; 143+ messages in thread
From: Drew Fustini @ 2021-10-22  2:06 UTC (permalink / raw)
  To: Emil Renner Berthing
  Cc: linux-riscv,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	linux-clk, open list:GPIO SUBSYSTEM, open list:SERIAL DRIVERS,
	Palmer Dabbelt, Paul Walmsley, Rob Herring, Michael Turquette,
	Stephen Boyd, Thomas Gleixner, Marc Zyngier, Philipp Zabel,
	Linus Walleij, Greg Kroah-Hartman, Daniel Lezcano,
	Andy Shevchenko, Jiri Slaby, Maximilian Luz, Sagar Kadam,
	Drew Fustini, Geert Uytterhoeven, Michael Zhu, Fu Wei,
	Anup Patel, Atish Patra, Matteo Croce, Linux Kernel Mailing List,
	Huan Feng

On Thu, Oct 21, 2021 at 09:50:42PM +0200, Emil Renner Berthing wrote:
> On Thu, 21 Oct 2021 at 21:01, Drew Fustini <dfustini@baylibre.com> wrote:
> > On Thu, Oct 21, 2021 at 07:42:19PM +0200, Emil Renner Berthing wrote:
> > > +/*
> > > + * Interrupt Trigger Polarity. If set to 1 the interrupt is triggered on a
> > > + * rising edge (edge-triggered) or high level (level-triggered). If set to 0 the
> > > + * interrupt is triggered on a falling edge (edge-triggered) or low level
> > > + * (level-triggered).
> > > + */
> > > +#define GPIOIEV              0x020
> > > +
> > > +/*
> > > + * Interrupt Mask. If set to 1 the interrupt is disabled (masked). If set to 0
> > > + * the interrupt is enabled (unmasked).
> > > + */
> > > +#define GPIOIE               0x028
> >
> > It bothered me that the datasheet used the term GPIOIE for the interrupt
> > mask register. I had used a more verbose #define name because I worried
> > someone reading GPIOIE in functions might mistake it for an interrupt
> > enable register. This happened to me when I was originally working with
> > the gpio driver.
> >
> > However I suppose the best solution would have been to get the datasheet
> > updated as I can see how it is best to have #define names in the driver
> > match the datasheet.
> >
> > > +static void starfive_irq_mask(struct irq_data *d)
> > > +{
> > > +     struct starfive_pinctrl *sfp = starfive_from_irq_data(d);
> > > +     irq_hw_number_t gpio = irqd_to_hwirq(d);
> > > +     void __iomem *ie = sfp->base + GPIOIE + 4 * (gpio / 32);
> > > +     u32 mask = BIT(gpio % 32);
> > > +     unsigned long flags;
> > > +     u32 value;
> > > +
> > > +     raw_spin_lock_irqsave(&sfp->lock, flags);
> > > +     value = readl_relaxed(ie) & ~mask;
> > > +     writel_relaxed(value, ie);
> > > +     raw_spin_unlock_irqrestore(&sfp->lock, flags);
> > > +}
> > > +
> > > +static void starfive_irq_mask_ack(struct irq_data *d)
> > > +{
> > > +     struct starfive_pinctrl *sfp = starfive_from_irq_data(d);
> > > +     irq_hw_number_t gpio = irqd_to_hwirq(d);
> > > +     void __iomem *ie = sfp->base + GPIOIE + 4 * (gpio / 32);
> > > +     void __iomem *ic = sfp->base + GPIOIC + 4 * (gpio / 32);
> > > +     u32 mask = BIT(gpio % 32);
> > > +     unsigned long flags;
> > > +     u32 value;
> > > +
> > > +     raw_spin_lock_irqsave(&sfp->lock, flags);
> > > +     value = readl_relaxed(ie) & ~mask;
> > > +     writel_relaxed(value, ie);
> > > +     writel_relaxed(mask, ic);
> > > +     raw_spin_unlock_irqrestore(&sfp->lock, flags);
> > > +}
> > > +
> > > +static void starfive_irq_unmask(struct irq_data *d)
> > > +{
> > > +     struct starfive_pinctrl *sfp = starfive_from_irq_data(d);
> > > +     irq_hw_number_t gpio = irqd_to_hwirq(d);
> > > +     void __iomem *ie = sfp->base + GPIOIE + 4 * (gpio / 32);
> > > +     u32 mask = BIT(gpio % 32);
> > > +     unsigned long flags;
> > > +     u32 value;
> > > +
> > > +     raw_spin_lock_irqsave(&sfp->lock, flags);
> > > +     value = readl_relaxed(ie) | mask;
> > > +     writel_relaxed(value, ie);
> > > +     raw_spin_unlock_irqrestore(&sfp->lock, flags);
> > > +}
> > > +
> 
> ...
> 
> > > +static int starfive_gpio_init_hw(struct gpio_chip *gc)
> > > +{
> > > +     struct starfive_pinctrl *sfp = starfive_from_gc(gc);
> > > +
> > > +     /* mask all GPIO interrupts */
> > > +     writel(0, sfp->base + GPIOIE + 0);
> > > +     writel(0, sfp->base + GPIOIE + 4);
> >
> > Woudln't 0 in GPIOIE mean mask is disabled for all interrupts?
> >
> > In other words, wouldn't this enable all the interrupts?
> 
> Heh, you're right. The code does the exact opposite of what the
> documentation says it should be doing. However I just tried and with
> the code as it is now GPIO interrupts work fine, but with the logic
> flipped the kernel fails to boot. I'm guessing because an interrupt
> storm. So it seems to me the documentation might be wrong and GPIOIE
> is actually a good name.

Ah, it seems I once knew this back in July [1] but never got the
documentation changed:

NOTE: Table 12-9 in the JH7100 datasheet is incorrect regarding fields
GPIOIE_0 and GPIOIE_1. An interrupt is enabled (unmasked) when the bit
is   set to 1 and it is disabled (masked) when set to 0. The datasheet
incorrectly states the opposite. I think this is due to the datasheet
author thinking of it as mask field which it is not, it is an enable
field. I will raise an issue on the documentation repo.


> 
> Michael Zhu: Can you confirm if a 1 or 0 enables the interrupt in the
> GPIOIE registers?
> 
> /Emil

[1] https://github.com/esmil/linux/pull/34/commits/e247a259e40312d0202cdbdd686dbba09afc7813

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 01/16] RISC-V: Add StarFive SoC Kconfig option
  2021-10-21 17:42   ` Emil Renner Berthing
@ 2021-10-22  8:50     ` Andy Shevchenko
  -1 siblings, 0 replies; 143+ messages in thread
From: Andy Shevchenko @ 2021-10-22  8:50 UTC (permalink / raw)
  To: Emil Renner Berthing
  Cc: linux-riscv, devicetree, linux-clk, open list:GPIO SUBSYSTEM,
	open list:SERIAL DRIVERS, Palmer Dabbelt, Paul Walmsley,
	Rob Herring, Michael Turquette, Stephen Boyd, Thomas Gleixner,
	Marc Zyngier, Philipp Zabel, Linus Walleij, Greg Kroah-Hartman,
	Daniel Lezcano, Andy Shevchenko, Jiri Slaby, Maximilian Luz,
	Sagar Kadam, Drew Fustini, Geert Uytterhoeven, Michael Zhu,
	Fu Wei, Anup Patel, Atish Patra, Matteo Croce,
	Linux Kernel Mailing List

On Thu, Oct 21, 2021 at 8:42 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
>
> Add StarFive Kconfig option to select SoC specific and common drivers
> required for these SoCs.

...

> +config SOC_STARFIVE
> +       bool "StarFive SoCs"
> +       select PINCTRL
> +       select RESET_CONTROLLER

> +       select SIFIVE_PLIC

If this is well understood and platform related the above two are too
generic. Why have you selected them?

> +       help
> +         This enables support for StarFive SoC platform hardware.

Not too much to read here. What is the point of this help?
I would elaborate what kind of platform it may support, what kind of
drivers it selects due to necessity of the accomplishing the boot
process, etc.

-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 01/16] RISC-V: Add StarFive SoC Kconfig option
@ 2021-10-22  8:50     ` Andy Shevchenko
  0 siblings, 0 replies; 143+ messages in thread
From: Andy Shevchenko @ 2021-10-22  8:50 UTC (permalink / raw)
  To: Emil Renner Berthing
  Cc: linux-riscv, devicetree, linux-clk, open list:GPIO SUBSYSTEM,
	open list:SERIAL DRIVERS, Palmer Dabbelt, Paul Walmsley,
	Rob Herring, Michael Turquette, Stephen Boyd, Thomas Gleixner,
	Marc Zyngier, Philipp Zabel, Linus Walleij, Greg Kroah-Hartman,
	Daniel Lezcano, Andy Shevchenko, Jiri Slaby, Maximilian Luz,
	Sagar Kadam, Drew Fustini, Geert Uytterhoeven, Michael Zhu,
	Fu Wei, Anup Patel, Atish Patra, Matteo Croce,
	Linux Kernel Mailing List

On Thu, Oct 21, 2021 at 8:42 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
>
> Add StarFive Kconfig option to select SoC specific and common drivers
> required for these SoCs.

...

> +config SOC_STARFIVE
> +       bool "StarFive SoCs"
> +       select PINCTRL
> +       select RESET_CONTROLLER

> +       select SIFIVE_PLIC

If this is well understood and platform related the above two are too
generic. Why have you selected them?

> +       help
> +         This enables support for StarFive SoC platform hardware.

Not too much to read here. What is the point of this help?
I would elaborate what kind of platform it may support, what kind of
drivers it selects due to necessity of the accomplishing the boot
process, etc.

-- 
With Best Regards,
Andy Shevchenko

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 01/16] RISC-V: Add StarFive SoC Kconfig option
  2021-10-22  8:50     ` Andy Shevchenko
@ 2021-10-22  9:40       ` Emil Renner Berthing
  -1 siblings, 0 replies; 143+ messages in thread
From: Emil Renner Berthing @ 2021-10-22  9:40 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: linux-riscv, devicetree, linux-clk, open list:GPIO SUBSYSTEM,
	open list:SERIAL DRIVERS, Palmer Dabbelt, Paul Walmsley,
	Rob Herring, Michael Turquette, Stephen Boyd, Thomas Gleixner,
	Marc Zyngier, Philipp Zabel, Linus Walleij, Greg Kroah-Hartman,
	Daniel Lezcano, Andy Shevchenko, Jiri Slaby, Maximilian Luz,
	Sagar Kadam, Drew Fustini, Geert Uytterhoeven, Michael Zhu,
	Fu Wei, Anup Patel, Atish Patra, Matteo Croce,
	Linux Kernel Mailing List

On Fri, 22 Oct 2021 at 10:51, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> On Thu, Oct 21, 2021 at 8:42 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> >
> > Add StarFive Kconfig option to select SoC specific and common drivers
> > required for these SoCs.
>
> ...
>
> > +config SOC_STARFIVE
> > +       bool "StarFive SoCs"
> > +       select PINCTRL
> > +       select RESET_CONTROLLER
>
> > +       select SIFIVE_PLIC
>
> If this is well understood and platform related the above two are too
> generic. Why have you selected them?

From your last comments the criterion seemed to be to only add it here
if it would otherwise fail to boot. Well it does fail to boot without
the reset and pinctrl drivers. The clock driver too, but RISCV already
selects COMMON_CLK. Once PINCTRL and RESET_CONTROLLER is selected the
specific drivers defaults to SOC_STARFIVE.

Alternatively we'd select the drivers too, but I can't promise that
future StarFive chips will need the same JH7100 clock and reset
drivers. Doing it this way means that selecting SOC_STARFIVE by
default gives you a kernel that will boot on all StarFive SoCs, but
you can still customise it further to your particular chip. It seems
like SOC_SIFIVE is doing the same.

> > +       help
> > +         This enables support for StarFive SoC platform hardware.
>
> Not too much to read here. What is the point of this help?
> I would elaborate what kind of platform it may support, what kind of
> drivers it selects due to necessity of the accomplishing the boot
> process, etc.

This is exactly as the other descriptions in this file. I don't know
why SOC_STARFIVE should be special.

/Emil

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 01/16] RISC-V: Add StarFive SoC Kconfig option
@ 2021-10-22  9:40       ` Emil Renner Berthing
  0 siblings, 0 replies; 143+ messages in thread
From: Emil Renner Berthing @ 2021-10-22  9:40 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: linux-riscv, devicetree, linux-clk, open list:GPIO SUBSYSTEM,
	open list:SERIAL DRIVERS, Palmer Dabbelt, Paul Walmsley,
	Rob Herring, Michael Turquette, Stephen Boyd, Thomas Gleixner,
	Marc Zyngier, Philipp Zabel, Linus Walleij, Greg Kroah-Hartman,
	Daniel Lezcano, Andy Shevchenko, Jiri Slaby, Maximilian Luz,
	Sagar Kadam, Drew Fustini, Geert Uytterhoeven, Michael Zhu,
	Fu Wei, Anup Patel, Atish Patra, Matteo Croce,
	Linux Kernel Mailing List

On Fri, 22 Oct 2021 at 10:51, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> On Thu, Oct 21, 2021 at 8:42 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> >
> > Add StarFive Kconfig option to select SoC specific and common drivers
> > required for these SoCs.
>
> ...
>
> > +config SOC_STARFIVE
> > +       bool "StarFive SoCs"
> > +       select PINCTRL
> > +       select RESET_CONTROLLER
>
> > +       select SIFIVE_PLIC
>
> If this is well understood and platform related the above two are too
> generic. Why have you selected them?

From your last comments the criterion seemed to be to only add it here
if it would otherwise fail to boot. Well it does fail to boot without
the reset and pinctrl drivers. The clock driver too, but RISCV already
selects COMMON_CLK. Once PINCTRL and RESET_CONTROLLER is selected the
specific drivers defaults to SOC_STARFIVE.

Alternatively we'd select the drivers too, but I can't promise that
future StarFive chips will need the same JH7100 clock and reset
drivers. Doing it this way means that selecting SOC_STARFIVE by
default gives you a kernel that will boot on all StarFive SoCs, but
you can still customise it further to your particular chip. It seems
like SOC_SIFIVE is doing the same.

> > +       help
> > +         This enables support for StarFive SoC platform hardware.
>
> Not too much to read here. What is the point of this help?
> I would elaborate what kind of platform it may support, what kind of
> drivers it selects due to necessity of the accomplishing the boot
> process, etc.

This is exactly as the other descriptions in this file. I don't know
why SOC_STARFIVE should be special.

/Emil

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 06/16] clk: starfive: Add JH7100 clock generator driver
  2021-10-21 17:42   ` Emil Renner Berthing
@ 2021-10-22 12:33     ` Andy Shevchenko
  -1 siblings, 0 replies; 143+ messages in thread
From: Andy Shevchenko @ 2021-10-22 12:33 UTC (permalink / raw)
  To: Emil Renner Berthing
  Cc: linux-riscv, devicetree, linux-clk, open list:GPIO SUBSYSTEM,
	open list:SERIAL DRIVERS, Geert Uytterhoeven, Palmer Dabbelt,
	Paul Walmsley, Rob Herring, Michael Turquette, Stephen Boyd,
	Thomas Gleixner, Marc Zyngier, Philipp Zabel, Linus Walleij,
	Greg Kroah-Hartman, Daniel Lezcano, Andy Shevchenko, Jiri Slaby,
	Maximilian Luz, Sagar Kadam, Drew Fustini, Michael Zhu, Fu Wei,
	Anup Patel, Atish Patra, Matteo Croce, Linux Kernel Mailing List

On Thu, Oct 21, 2021 at 8:43 PM Emil Renner Berthing <kernel@esmil.dk> wrote:

...

> +static struct clk_hw *clk_starfive_jh7100_get(struct of_phandle_args *clkspec, void *data)
> +{
> +       struct clk_starfive_jh7100_priv *priv = data;
> +       unsigned int idx = clkspec->args[0];
> +
> +       if (idx >= JH7100_CLK_END) {
> +               dev_err(priv->dev, "invalid clock index %u\n", idx);
> +               return ERR_PTR(-EINVAL);

After this
https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core.git/commit/?h=driver-core-next&id=7065f92255bb2468dbb9aa0537ff186ef64d5a02
It's okay to use

> +       }

       if (idx >= JH7100_CLK_END)
               return dev_err_probe(priv->dev, -EINVAL, "invalid clock
index %u\n", idx);

Ditto for other similar cases.

> +       if (idx >= JH7100_CLK_PLL0_OUT)
> +               return priv->pll[idx - JH7100_CLK_PLL0_OUT];
> +
> +       return &priv->reg[idx].hw;
> +}

...

> +       while (idx)
> +               clk_hw_unregister(&priv->reg[--idx].hw);

I still consider that usual pattern, i.e.

       while (idx--)
               clk_hw_unregister(&priv->reg[idx].hw);

but since you are pushing hard for your variant I'll leave it to the
maintainers and author.

-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 06/16] clk: starfive: Add JH7100 clock generator driver
@ 2021-10-22 12:33     ` Andy Shevchenko
  0 siblings, 0 replies; 143+ messages in thread
From: Andy Shevchenko @ 2021-10-22 12:33 UTC (permalink / raw)
  To: Emil Renner Berthing
  Cc: linux-riscv, devicetree, linux-clk, open list:GPIO SUBSYSTEM,
	open list:SERIAL DRIVERS, Geert Uytterhoeven, Palmer Dabbelt,
	Paul Walmsley, Rob Herring, Michael Turquette, Stephen Boyd,
	Thomas Gleixner, Marc Zyngier, Philipp Zabel, Linus Walleij,
	Greg Kroah-Hartman, Daniel Lezcano, Andy Shevchenko, Jiri Slaby,
	Maximilian Luz, Sagar Kadam, Drew Fustini, Michael Zhu, Fu Wei,
	Anup Patel, Atish Patra, Matteo Croce, Linux Kernel Mailing List

On Thu, Oct 21, 2021 at 8:43 PM Emil Renner Berthing <kernel@esmil.dk> wrote:

...

> +static struct clk_hw *clk_starfive_jh7100_get(struct of_phandle_args *clkspec, void *data)
> +{
> +       struct clk_starfive_jh7100_priv *priv = data;
> +       unsigned int idx = clkspec->args[0];
> +
> +       if (idx >= JH7100_CLK_END) {
> +               dev_err(priv->dev, "invalid clock index %u\n", idx);
> +               return ERR_PTR(-EINVAL);

After this
https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core.git/commit/?h=driver-core-next&id=7065f92255bb2468dbb9aa0537ff186ef64d5a02
It's okay to use

> +       }

       if (idx >= JH7100_CLK_END)
               return dev_err_probe(priv->dev, -EINVAL, "invalid clock
index %u\n", idx);

Ditto for other similar cases.

> +       if (idx >= JH7100_CLK_PLL0_OUT)
> +               return priv->pll[idx - JH7100_CLK_PLL0_OUT];
> +
> +       return &priv->reg[idx].hw;
> +}

...

> +       while (idx)
> +               clk_hw_unregister(&priv->reg[--idx].hw);

I still consider that usual pattern, i.e.

       while (idx--)
               clk_hw_unregister(&priv->reg[idx].hw);

but since you are pushing hard for your variant I'll leave it to the
maintainers and author.

-- 
With Best Regards,
Andy Shevchenko

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 01/16] RISC-V: Add StarFive SoC Kconfig option
  2021-10-22  9:40       ` Emil Renner Berthing
@ 2021-10-22 12:40         ` Andy Shevchenko
  -1 siblings, 0 replies; 143+ messages in thread
From: Andy Shevchenko @ 2021-10-22 12:40 UTC (permalink / raw)
  To: Emil Renner Berthing
  Cc: linux-riscv, devicetree, linux-clk, open list:GPIO SUBSYSTEM,
	open list:SERIAL DRIVERS, Palmer Dabbelt, Paul Walmsley,
	Rob Herring, Michael Turquette, Stephen Boyd, Thomas Gleixner,
	Marc Zyngier, Philipp Zabel, Linus Walleij, Greg Kroah-Hartman,
	Daniel Lezcano, Andy Shevchenko, Jiri Slaby, Maximilian Luz,
	Sagar Kadam, Drew Fustini, Geert Uytterhoeven, Michael Zhu,
	Fu Wei, Anup Patel, Atish Patra, Matteo Croce,
	Linux Kernel Mailing List

On Fri, Oct 22, 2021 at 12:40 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> On Fri, 22 Oct 2021 at 10:51, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > On Thu, Oct 21, 2021 at 8:42 PM Emil Renner Berthing <kernel@esmil.dk> wrote:

...

> > > +config SOC_STARFIVE
> > > +       bool "StarFive SoCs"
> > > +       select PINCTRL
> > > +       select RESET_CONTROLLER
> >
> > > +       select SIFIVE_PLIC
> >
> > If this is well understood and platform related the above two are too
> > generic. Why have you selected them?
>
> From your last comments the criterion seemed to be to only add it here
> if it would otherwise fail to boot. Well it does fail to boot without
> the reset and pinctrl drivers. The clock driver too, but RISCV already
> selects COMMON_CLK. Once PINCTRL and RESET_CONTROLLER is selected the
> specific drivers defaults to SOC_STARFIVE.
>
> Alternatively we'd select the drivers too, but I can't promise that
> future StarFive chips will need the same JH7100 clock and reset
> drivers. Doing it this way means that selecting SOC_STARFIVE by
> default gives you a kernel that will boot on all StarFive SoCs, but
> you can still customise it further to your particular chip. It seems
> like SOC_SIFIVE is doing the same.

Okay, please add this justification to the commit message in the next version.

...

> > > +       help
> > > +         This enables support for StarFive SoC platform hardware.
> >
> > Not too much to read here. What is the point of this help?
> > I would elaborate what kind of platform it may support, what kind of
> > drivers it selects due to necessity of the accomplishing the boot
> > process, etc.
>
> This is exactly as the other descriptions in this file. I don't know
> why SOC_STARFIVE should be special.

OK.

-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 01/16] RISC-V: Add StarFive SoC Kconfig option
@ 2021-10-22 12:40         ` Andy Shevchenko
  0 siblings, 0 replies; 143+ messages in thread
From: Andy Shevchenko @ 2021-10-22 12:40 UTC (permalink / raw)
  To: Emil Renner Berthing
  Cc: linux-riscv, devicetree, linux-clk, open list:GPIO SUBSYSTEM,
	open list:SERIAL DRIVERS, Palmer Dabbelt, Paul Walmsley,
	Rob Herring, Michael Turquette, Stephen Boyd, Thomas Gleixner,
	Marc Zyngier, Philipp Zabel, Linus Walleij, Greg Kroah-Hartman,
	Daniel Lezcano, Andy Shevchenko, Jiri Slaby, Maximilian Luz,
	Sagar Kadam, Drew Fustini, Geert Uytterhoeven, Michael Zhu,
	Fu Wei, Anup Patel, Atish Patra, Matteo Croce,
	Linux Kernel Mailing List

On Fri, Oct 22, 2021 at 12:40 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> On Fri, 22 Oct 2021 at 10:51, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > On Thu, Oct 21, 2021 at 8:42 PM Emil Renner Berthing <kernel@esmil.dk> wrote:

...

> > > +config SOC_STARFIVE
> > > +       bool "StarFive SoCs"
> > > +       select PINCTRL
> > > +       select RESET_CONTROLLER
> >
> > > +       select SIFIVE_PLIC
> >
> > If this is well understood and platform related the above two are too
> > generic. Why have you selected them?
>
> From your last comments the criterion seemed to be to only add it here
> if it would otherwise fail to boot. Well it does fail to boot without
> the reset and pinctrl drivers. The clock driver too, but RISCV already
> selects COMMON_CLK. Once PINCTRL and RESET_CONTROLLER is selected the
> specific drivers defaults to SOC_STARFIVE.
>
> Alternatively we'd select the drivers too, but I can't promise that
> future StarFive chips will need the same JH7100 clock and reset
> drivers. Doing it this way means that selecting SOC_STARFIVE by
> default gives you a kernel that will boot on all StarFive SoCs, but
> you can still customise it further to your particular chip. It seems
> like SOC_SIFIVE is doing the same.

Okay, please add this justification to the commit message in the next version.

...

> > > +       help
> > > +         This enables support for StarFive SoC platform hardware.
> >
> > Not too much to read here. What is the point of this help?
> > I would elaborate what kind of platform it may support, what kind of
> > drivers it selects due to necessity of the accomplishing the boot
> > process, etc.
>
> This is exactly as the other descriptions in this file. I don't know
> why SOC_STARFIVE should be special.

OK.

-- 
With Best Regards,
Andy Shevchenko

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 06/16] clk: starfive: Add JH7100 clock generator driver
  2021-10-22 12:33     ` Andy Shevchenko
@ 2021-10-22 12:44       ` Geert Uytterhoeven
  -1 siblings, 0 replies; 143+ messages in thread
From: Geert Uytterhoeven @ 2021-10-22 12:44 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Emil Renner Berthing, linux-riscv, devicetree, linux-clk,
	open list:GPIO SUBSYSTEM, open list:SERIAL DRIVERS,
	Palmer Dabbelt, Paul Walmsley, Rob Herring, Michael Turquette,
	Stephen Boyd, Thomas Gleixner, Marc Zyngier, Philipp Zabel,
	Linus Walleij, Greg Kroah-Hartman, Daniel Lezcano,
	Andy Shevchenko, Jiri Slaby, Maximilian Luz, Sagar Kadam,
	Drew Fustini, Michael Zhu, Fu Wei, Anup Patel, Atish Patra,
	Matteo Croce, Linux Kernel Mailing List

On Fri, Oct 22, 2021 at 2:34 PM Andy Shevchenko
<andy.shevchenko@gmail.com> wrote:
> On Thu, Oct 21, 2021 at 8:43 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> > +       while (idx)
> > +               clk_hw_unregister(&priv->reg[--idx].hw);
>
> I still consider that usual pattern, i.e.
>
>        while (idx--)
>                clk_hw_unregister(&priv->reg[idx].hw);
>
> but since you are pushing hard for your variant I'll leave it to the
> maintainers and author.

I agree with Andy.

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 06/16] clk: starfive: Add JH7100 clock generator driver
@ 2021-10-22 12:44       ` Geert Uytterhoeven
  0 siblings, 0 replies; 143+ messages in thread
From: Geert Uytterhoeven @ 2021-10-22 12:44 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Emil Renner Berthing, linux-riscv, devicetree, linux-clk,
	open list:GPIO SUBSYSTEM, open list:SERIAL DRIVERS,
	Palmer Dabbelt, Paul Walmsley, Rob Herring, Michael Turquette,
	Stephen Boyd, Thomas Gleixner, Marc Zyngier, Philipp Zabel,
	Linus Walleij, Greg Kroah-Hartman, Daniel Lezcano,
	Andy Shevchenko, Jiri Slaby, Maximilian Luz, Sagar Kadam,
	Drew Fustini, Michael Zhu, Fu Wei, Anup Patel, Atish Patra,
	Matteo Croce, Linux Kernel Mailing List

On Fri, Oct 22, 2021 at 2:34 PM Andy Shevchenko
<andy.shevchenko@gmail.com> wrote:
> On Thu, Oct 21, 2021 at 8:43 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> > +       while (idx)
> > +               clk_hw_unregister(&priv->reg[--idx].hw);
>
> I still consider that usual pattern, i.e.
>
>        while (idx--)
>                clk_hw_unregister(&priv->reg[idx].hw);
>
> but since you are pushing hard for your variant I'll leave it to the
> maintainers and author.

I agree with Andy.

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 09/16] reset: starfive-jh7100: Add StarFive JH7100 reset driver
  2021-10-21 17:42   ` Emil Renner Berthing
@ 2021-10-22 12:55     ` Andy Shevchenko
  -1 siblings, 0 replies; 143+ messages in thread
From: Andy Shevchenko @ 2021-10-22 12:55 UTC (permalink / raw)
  To: Emil Renner Berthing
  Cc: linux-riscv, devicetree, linux-clk, open list:GPIO SUBSYSTEM,
	open list:SERIAL DRIVERS, Palmer Dabbelt, Paul Walmsley,
	Rob Herring, Michael Turquette, Stephen Boyd, Thomas Gleixner,
	Marc Zyngier, Philipp Zabel, Linus Walleij, Greg Kroah-Hartman,
	Daniel Lezcano, Andy Shevchenko, Jiri Slaby, Maximilian Luz,
	Sagar Kadam, Drew Fustini, Geert Uytterhoeven, Michael Zhu,
	Fu Wei, Anup Patel, Atish Patra, Matteo Croce,
	Linux Kernel Mailing List

On Thu, Oct 21, 2021 at 8:43 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
>
> Add a driver for the StarFive JH7100 reset controller.

...

> +config RESET_STARFIVE_JH7100
> +       bool "StarFive JH7100 Reset Driver"
> +       depends on SOC_STARFIVE || COMPILE_TEST

> +       depends on OF

No evidence of this dependency. Why to limit test coverage?

> +       default SOC_STARFIVE

...

> +/*
> + * Reset driver for the StarFive JH7100 SoC
> + *
> + * Copyright (C) 2021 Emil Renner Berthing <kernel@esmil.dk>

> + *

Redundant empty line.

> + */

...

> +#include <linux/of_device.h>

No evidence of any usage of this header. Perhaps you meant mod_devicetable.h?

...

> +static const u32 jh7100_reset_asserted[4] = {

> +       BIT(JH7100_RST_U74 % 32) |
> +       BIT(JH7100_RST_VP6_DRESET % 32) |
> +       BIT(JH7100_RST_VP6_BRESET % 32),

It's hard to notice that this is only one entry. See also below.

> +       BIT(JH7100_RST_HIFI4_DRESET % 32) |
> +       BIT(JH7100_RST_HIFI4_BRESET % 32),
> +
> +       BIT(JH7100_RST_E24 % 32)

+ Comma.

> +};

Why all these ugly % 32 against constants?

...

> +       if (!assert)
> +               done ^= mask;

Can you convert this to simple

  if (assert)
    ret = readl_...
  else
    ret = readl_...

below?

> +       spin_lock_irqsave(&data->lock, flags);
> +
> +       value = readl(reg_assert);
> +       if (assert)
> +               value |= mask;
> +       else
> +               value &= ~mask;
> +       writel(value, reg_assert);

> +       /* if the associated clock is gated, deasserting might otherwise hang forever */
> +       ret = readl_poll_timeout(reg_status, value, (value & mask) == done, 0, 1000);

You run delays under spin lock. You need to use _atomic variant.

> +       spin_unlock_irqrestore(&data->lock, flags);

...

> +       u32 value = (readl(reg_status) ^ jh7100_reset_asserted[offset]) & mask;

> +       dev_dbg(rcdev->dev, "status(%lu) = %d\n", id, !value);
> +       return !value;

Dup of ! operator. Can it be value = !(...); above?

-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 09/16] reset: starfive-jh7100: Add StarFive JH7100 reset driver
@ 2021-10-22 12:55     ` Andy Shevchenko
  0 siblings, 0 replies; 143+ messages in thread
From: Andy Shevchenko @ 2021-10-22 12:55 UTC (permalink / raw)
  To: Emil Renner Berthing
  Cc: linux-riscv, devicetree, linux-clk, open list:GPIO SUBSYSTEM,
	open list:SERIAL DRIVERS, Palmer Dabbelt, Paul Walmsley,
	Rob Herring, Michael Turquette, Stephen Boyd, Thomas Gleixner,
	Marc Zyngier, Philipp Zabel, Linus Walleij, Greg Kroah-Hartman,
	Daniel Lezcano, Andy Shevchenko, Jiri Slaby, Maximilian Luz,
	Sagar Kadam, Drew Fustini, Geert Uytterhoeven, Michael Zhu,
	Fu Wei, Anup Patel, Atish Patra, Matteo Croce,
	Linux Kernel Mailing List

On Thu, Oct 21, 2021 at 8:43 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
>
> Add a driver for the StarFive JH7100 reset controller.

...

> +config RESET_STARFIVE_JH7100
> +       bool "StarFive JH7100 Reset Driver"
> +       depends on SOC_STARFIVE || COMPILE_TEST

> +       depends on OF

No evidence of this dependency. Why to limit test coverage?

> +       default SOC_STARFIVE

...

> +/*
> + * Reset driver for the StarFive JH7100 SoC
> + *
> + * Copyright (C) 2021 Emil Renner Berthing <kernel@esmil.dk>

> + *

Redundant empty line.

> + */

...

> +#include <linux/of_device.h>

No evidence of any usage of this header. Perhaps you meant mod_devicetable.h?

...

> +static const u32 jh7100_reset_asserted[4] = {

> +       BIT(JH7100_RST_U74 % 32) |
> +       BIT(JH7100_RST_VP6_DRESET % 32) |
> +       BIT(JH7100_RST_VP6_BRESET % 32),

It's hard to notice that this is only one entry. See also below.

> +       BIT(JH7100_RST_HIFI4_DRESET % 32) |
> +       BIT(JH7100_RST_HIFI4_BRESET % 32),
> +
> +       BIT(JH7100_RST_E24 % 32)

+ Comma.

> +};

Why all these ugly % 32 against constants?

...

> +       if (!assert)
> +               done ^= mask;

Can you convert this to simple

  if (assert)
    ret = readl_...
  else
    ret = readl_...

below?

> +       spin_lock_irqsave(&data->lock, flags);
> +
> +       value = readl(reg_assert);
> +       if (assert)
> +               value |= mask;
> +       else
> +               value &= ~mask;
> +       writel(value, reg_assert);

> +       /* if the associated clock is gated, deasserting might otherwise hang forever */
> +       ret = readl_poll_timeout(reg_status, value, (value & mask) == done, 0, 1000);

You run delays under spin lock. You need to use _atomic variant.

> +       spin_unlock_irqrestore(&data->lock, flags);

...

> +       u32 value = (readl(reg_status) ^ jh7100_reset_asserted[offset]) & mask;

> +       dev_dbg(rcdev->dev, "status(%lu) = %d\n", id, !value);
> +       return !value;

Dup of ! operator. Can it be value = !(...); above?

-- 
With Best Regards,
Andy Shevchenko

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 09/16] reset: starfive-jh7100: Add StarFive JH7100 reset driver
  2021-10-21 17:42   ` Emil Renner Berthing
@ 2021-10-22 13:06     ` Andreas Schwab
  -1 siblings, 0 replies; 143+ messages in thread
From: Andreas Schwab @ 2021-10-22 13:06 UTC (permalink / raw)
  To: Emil Renner Berthing
  Cc: linux-riscv, devicetree, linux-clk, linux-gpio, linux-serial,
	Palmer Dabbelt, Paul Walmsley, Rob Herring, Michael Turquette,
	Stephen Boyd, Thomas Gleixner, Marc Zyngier, Philipp Zabel,
	Linus Walleij, Greg Kroah-Hartman, Daniel Lezcano,
	Andy Shevchenko, Jiri Slaby, Maximilian Luz, Sagar Kadam,
	Drew Fustini, Geert Uytterhoeven, Michael Zhu, Fu Wei,
	Anup Patel, Atish Patra, Matteo Croce, linux-kernel

On Okt 21 2021, Emil Renner Berthing wrote:

> +config RESET_STARFIVE_JH7100
> +	bool "StarFive JH7100 Reset Driver"
> +	depends on SOC_STARFIVE || COMPILE_TEST

Why does it need to depend on SOC_STARFIVE?

Andreas.

-- 
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 7578 EB47 D4E5 4D69 2510  2552 DF73 E780 A9DA AEC1
"And now for something completely different."

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 09/16] reset: starfive-jh7100: Add StarFive JH7100 reset driver
@ 2021-10-22 13:06     ` Andreas Schwab
  0 siblings, 0 replies; 143+ messages in thread
From: Andreas Schwab @ 2021-10-22 13:06 UTC (permalink / raw)
  To: Emil Renner Berthing
  Cc: linux-riscv, devicetree, linux-clk, linux-gpio, linux-serial,
	Palmer Dabbelt, Paul Walmsley, Rob Herring, Michael Turquette,
	Stephen Boyd, Thomas Gleixner, Marc Zyngier, Philipp Zabel,
	Linus Walleij, Greg Kroah-Hartman, Daniel Lezcano,
	Andy Shevchenko, Jiri Slaby, Maximilian Luz, Sagar Kadam,
	Drew Fustini, Geert Uytterhoeven, Michael Zhu, Fu Wei,
	Anup Patel, Atish Patra, Matteo Croce, linux-kernel

On Okt 21 2021, Emil Renner Berthing wrote:

> +config RESET_STARFIVE_JH7100
> +	bool "StarFive JH7100 Reset Driver"
> +	depends on SOC_STARFIVE || COMPILE_TEST

Why does it need to depend on SOC_STARFIVE?

Andreas.

-- 
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 7578 EB47 D4E5 4D69 2510  2552 DF73 E780 A9DA AEC1
"And now for something completely different."

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 06/16] clk: starfive: Add JH7100 clock generator driver
  2021-10-22 12:33     ` Andy Shevchenko
@ 2021-10-22 13:13       ` Emil Renner Berthing
  -1 siblings, 0 replies; 143+ messages in thread
From: Emil Renner Berthing @ 2021-10-22 13:13 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: linux-riscv, devicetree, linux-clk, open list:GPIO SUBSYSTEM,
	open list:SERIAL DRIVERS, Geert Uytterhoeven, Palmer Dabbelt,
	Paul Walmsley, Rob Herring, Michael Turquette, Stephen Boyd,
	Thomas Gleixner, Marc Zyngier, Philipp Zabel, Linus Walleij,
	Greg Kroah-Hartman, Daniel Lezcano, Andy Shevchenko, Jiri Slaby,
	Maximilian Luz, Sagar Kadam, Drew Fustini, Michael Zhu, Fu Wei,
	Anup Patel, Atish Patra, Matteo Croce, Linux Kernel Mailing List

On Fri, 22 Oct 2021 at 14:34, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> On Thu, Oct 21, 2021 at 8:43 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
>
> ...
>
> > +static struct clk_hw *clk_starfive_jh7100_get(struct of_phandle_args *clkspec, void *data)
> > +{
> > +       struct clk_starfive_jh7100_priv *priv = data;
> > +       unsigned int idx = clkspec->args[0];
> > +
> > +       if (idx >= JH7100_CLK_END) {
> > +               dev_err(priv->dev, "invalid clock index %u\n", idx);
> > +               return ERR_PTR(-EINVAL);
>
> After this
> https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core.git/commit/?h=driver-core-next&id=7065f92255bb2468dbb9aa0537ff186ef64d5a02
> It's okay to use
>
> > +       }
>
>        if (idx >= JH7100_CLK_END)
>                return dev_err_probe(priv->dev, -EINVAL, "invalid clock
> index %u\n", idx);
>
> Ditto for other similar cases.

Hmm.. this function doesn't return int, but struct clk_hw *, hence the ERR_PTR.
Also I don't see any other similar cases in this driver.

> > +       if (idx >= JH7100_CLK_PLL0_OUT)
> > +               return priv->pll[idx - JH7100_CLK_PLL0_OUT];
> > +
> > +       return &priv->reg[idx].hw;
> > +}
>
> ...
>
> > +       while (idx)
> > +               clk_hw_unregister(&priv->reg[--idx].hw);
>
> I still consider that usual pattern, i.e.
>
>        while (idx--)
>                clk_hw_unregister(&priv->reg[idx].hw);
>
> but since you are pushing hard for your variant I'll leave it to the
> maintainers and author.
>
> --
> With Best Regards,
> Andy Shevchenko

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 06/16] clk: starfive: Add JH7100 clock generator driver
@ 2021-10-22 13:13       ` Emil Renner Berthing
  0 siblings, 0 replies; 143+ messages in thread
From: Emil Renner Berthing @ 2021-10-22 13:13 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: linux-riscv, devicetree, linux-clk, open list:GPIO SUBSYSTEM,
	open list:SERIAL DRIVERS, Geert Uytterhoeven, Palmer Dabbelt,
	Paul Walmsley, Rob Herring, Michael Turquette, Stephen Boyd,
	Thomas Gleixner, Marc Zyngier, Philipp Zabel, Linus Walleij,
	Greg Kroah-Hartman, Daniel Lezcano, Andy Shevchenko, Jiri Slaby,
	Maximilian Luz, Sagar Kadam, Drew Fustini, Michael Zhu, Fu Wei,
	Anup Patel, Atish Patra, Matteo Croce, Linux Kernel Mailing List

On Fri, 22 Oct 2021 at 14:34, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> On Thu, Oct 21, 2021 at 8:43 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
>
> ...
>
> > +static struct clk_hw *clk_starfive_jh7100_get(struct of_phandle_args *clkspec, void *data)
> > +{
> > +       struct clk_starfive_jh7100_priv *priv = data;
> > +       unsigned int idx = clkspec->args[0];
> > +
> > +       if (idx >= JH7100_CLK_END) {
> > +               dev_err(priv->dev, "invalid clock index %u\n", idx);
> > +               return ERR_PTR(-EINVAL);
>
> After this
> https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core.git/commit/?h=driver-core-next&id=7065f92255bb2468dbb9aa0537ff186ef64d5a02
> It's okay to use
>
> > +       }
>
>        if (idx >= JH7100_CLK_END)
>                return dev_err_probe(priv->dev, -EINVAL, "invalid clock
> index %u\n", idx);
>
> Ditto for other similar cases.

Hmm.. this function doesn't return int, but struct clk_hw *, hence the ERR_PTR.
Also I don't see any other similar cases in this driver.

> > +       if (idx >= JH7100_CLK_PLL0_OUT)
> > +               return priv->pll[idx - JH7100_CLK_PLL0_OUT];
> > +
> > +       return &priv->reg[idx].hw;
> > +}
>
> ...
>
> > +       while (idx)
> > +               clk_hw_unregister(&priv->reg[--idx].hw);
>
> I still consider that usual pattern, i.e.
>
>        while (idx--)
>                clk_hw_unregister(&priv->reg[idx].hw);
>
> but since you are pushing hard for your variant I'll leave it to the
> maintainers and author.
>
> --
> With Best Regards,
> Andy Shevchenko

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 12/16] pinctrl: starfive: Add pinctrl driver for StarFive SoCs
  2021-10-21 17:42   ` Emil Renner Berthing
@ 2021-10-22 13:31     ` Andy Shevchenko
  -1 siblings, 0 replies; 143+ messages in thread
From: Andy Shevchenko @ 2021-10-22 13:31 UTC (permalink / raw)
  To: Emil Renner Berthing
  Cc: linux-riscv, devicetree, linux-clk, open list:GPIO SUBSYSTEM,
	open list:SERIAL DRIVERS, Palmer Dabbelt, Paul Walmsley,
	Rob Herring, Michael Turquette, Stephen Boyd, Thomas Gleixner,
	Marc Zyngier, Philipp Zabel, Linus Walleij, Greg Kroah-Hartman,
	Daniel Lezcano, Andy Shevchenko, Jiri Slaby, Maximilian Luz,
	Sagar Kadam, Drew Fustini, Geert Uytterhoeven, Michael Zhu,
	Fu Wei, Anup Patel, Atish Patra, Matteo Croce,
	Linux Kernel Mailing List, Huan Feng

On Thu, Oct 21, 2021 at 8:44 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
>
> Add a combined pinctrl and GPIO driver for the StarFive JH7100 SoC.
>
> For each "GPIO" there are two registers for configuring the output and
> output enable signals which may come from other peripherals. Among these
> are two special signals that are constant 0 and constant 1 respectively.
> Controlling the GPIOs from software is done by choosing one of these
> signals. In other words the same registers are used for both pinmuxing

pin muxing

> and controlling the GPIOs, which makes it easier to combine the pinctrl
> and GPIO driver in one.
>
> I wrote the pinconf and pinmux parts, but the GPIO part of the code is
> based on the GPIO driver in the vendor tree written by Huan Feng with
> cleanups and fixes by Drew and me.

...

> +#define PAD_BIAS_MASK                  (PAD_BIAS_STRONG_PULL_UP | \
> +                                        PAD_BIAS_DISABLE | \
> +                                        PAD_BIAS_PULL_DOWN)

It's slightly better looking if the value is begins on the next line

#define PAD_BIAS_MASK    \
        (PAD_BIAS_STRONG_PULL_UP | \
         PAD_BIAS_DISABLE | \
         PAD_BIAS_PULL_DOWN)

...

> +       seq_printf(s, "dout=%u%s doen=%u%s",
> +                  dout & (u32)GENMASK(7, 0), (dout & BIT(31)) ? "r" : "",
> +                  doen & (u32)GENMASK(7, 0), (doen & BIT(31)) ? "r" : "");

Why castings?

...

> +       for_each_child_of_node(np, child) {
> +               int npinmux = of_property_count_u32_elems(child, "pinmux");
> +               int npins   = of_property_count_u32_elems(child, "pins");
> +
> +               if (npinmux > 0 && npins > 0) {

> +                       dev_err(dev, "invalid pinctrl group %pOFn.%pOFn: %s\n",
> +                               np, child, "both pinmux and pins set");

Why %s for string literal?! It's quite unusual. Ditto for other similar cases.

> +                       of_node_put(child);
> +                       return -EINVAL;
> +               }

...

> +               } else {
> +                       dev_err(dev, "invalid pinctrl group %pOFn.%pOFn: %s\n",
> +                               np, child, "neither pinmux nor pins set");
> +                       of_node_put(child);
> +                       return -EINVAL;
> +               }

This can be checjed above with other sanity check(s), right?

> +               ngroups += 1;
> +       }

...

> +       ret = -ENOMEM;

It should be below...

> +       pgnames = devm_kcalloc(dev, ngroups, sizeof(*pgnames), GFP_KERNEL);
> +       if (!pgnames)
> +               return ret;

...like here, where it makes more sense.

> +       map = kcalloc(nmaps, sizeof(*map), GFP_KERNEL);
> +       if (!map)
> +               goto free_pgnames;

...

> +       for_each_child_of_node(np, child) {
> +               int npins;
> +               int i;
> +
> +               ret = -ENOMEM;
> +               grpname = devm_kasprintf(dev, GFP_KERNEL, "%s.%s", np->name, child->name);
> +               if (!grpname)
> +                       goto put_child;
> +
> +               pgnames[ngroups++] = grpname;
> +
> +               if ((npins = of_property_count_u32_elems(child, "pinmux")) > 0) {
> +                       pins = devm_kcalloc(dev, npins, sizeof(*pins), GFP_KERNEL);
> +                       if (!pins)
> +                               goto free_grpname;
> +
> +                       pinmux = devm_kcalloc(dev, npins, sizeof(*pinmux), GFP_KERNEL);
> +                       if (!pinmux)
> +                               goto free_pins;
> +
> +                       for (i = 0; i < npins; i++) {
> +                               u32 v;
> +
> +                               ret = of_property_read_u32_index(child, "pinmux", i, &v);
> +                               if (ret)
> +                                       goto free_pinmux;
> +                               pins[i] = starfive_gpio_to_pin(sfp, starfive_pinmux_to_gpio(v));
> +                               pinmux[i] = v;
> +                       }

Why you can't use of_property_read_u32_array() APIs?

> +                       map[nmaps].type = PIN_MAP_TYPE_MUX_GROUP;
> +                       map[nmaps].data.mux.function = np->name;
> +                       map[nmaps].data.mux.group = grpname;
> +                       nmaps += 1;
> +               } else if ((npins = of_property_count_u32_elems(child, "pins")) > 0) {
> +                       pins = devm_kcalloc(dev, npins, sizeof(*pins), GFP_KERNEL);
> +                       if (!pins)
> +                               goto free_grpname;
> +
> +                       pinmux = NULL;
> +
> +                       for (i = 0; i < npins; i++) {
> +                               u32 v;
> +
> +                               ret = of_property_read_u32_index(child, "pins", i, &v);
> +                               if (ret)
> +                                       goto free_pins;
> +                               pins[i] = v;
> +                       }

NIH _array() APIs.

> +               } else {
> +                       ret = -EINVAL;
> +                       goto free_grpname;
> +               }
> +
> +               ret = pinctrl_generic_add_group(pctldev, grpname, pins, npins, pinmux);
> +               if (ret < 0) {
> +                       dev_err(dev, "error adding group %pOFn.%pOFn: %d\n",
> +                               np, child, ret);
> +                       goto free_pinmux;
> +               }
> +
> +               ret = pinconf_generic_parse_dt_config(child, pctldev,
> +                                                     &map[nmaps].data.configs.configs,
> +                                                     &map[nmaps].data.configs.num_configs);
> +               if (ret) {
> +                       dev_err(dev, "invalid pinctrl group %pOFn.%pOFn: %s\n",
> +                               np, child, "error parsing pin config");
> +                       goto put_child;
> +               }
> +
> +               /* don't create a map if there are no pinconf settings */
> +               if (map[nmaps].data.configs.num_configs == 0)
> +                       continue;
> +
> +               map[nmaps].type = PIN_MAP_TYPE_CONFIGS_GROUP;
> +               map[nmaps].data.configs.group_or_pin = grpname;
> +               nmaps += 1;
> +       }

...

> +free_pinmux:
> +       devm_kfree(dev, pinmux);
> +free_pins:
> +       devm_kfree(dev, pins);
> +free_grpname:
> +       devm_kfree(dev, grpname);

> +free_pgnames:
> +       devm_kfree(dev, pgnames);

Just no, please get rid of them either way as I explained in previous reviews.

...

> +               raw_spin_lock_irqsave(&sfp->lock, flags);
> +               writel_relaxed(dout, reg_dout);
> +               writel_relaxed(doen, reg_doen);
> +               if (reg_din)
> +                       writel_relaxed(gpio + 2, reg_din);

Why 0 can't be written?

> +               raw_spin_unlock_irqrestore(&sfp->lock, flags);

...

> +       dev_dbg(starfive_dev(sfp),
> +               "padctl_rmw(%u, 0x%03x, 0x%03x)\n", pin, _mask, _value);

One line?

...

> +       mask = 0;
> +       value = 0;
> +       for (i = 0; i < num_configs; i++) {
> +               int param = pinconf_to_config_param(configs[i]);
> +               u32 arg = pinconf_to_config_argument(configs[i]);
>
+
> +               switch (param) {
> +               case PIN_CONFIG_BIAS_DISABLE:
> +                       mask |= PAD_BIAS_MASK;
> +                       value = (value & ~PAD_BIAS_MASK) | PAD_BIAS_DISABLE;

Okay, I have got why you are masking on each iteration, but here is
the question, shouldn't you apply the cnages belonged to each of the
group of options as it's requested by the user? Here you basically
ignore all previous changes to bias.

I would expect that you have something like

for () {
  switch (type) {
  case BIAS*:
    return apply_bias();
  ...other types...
  default:
    return err;
  }
}

> +                       break;
> +               case PIN_CONFIG_BIAS_PULL_DOWN:
> +                       if (arg == 0)
> +                               return -ENOTSUPP;
> +                       mask |= PAD_BIAS_MASK;
> +                       value = (value & ~PAD_BIAS_MASK) | PAD_BIAS_PULL_DOWN;
> +                       break;
> +               case PIN_CONFIG_BIAS_PULL_UP:
> +                       if (arg == 0)
> +                               return -ENOTSUPP;
> +                       mask |= PAD_BIAS_MASK;
> +                       value = value & ~PAD_BIAS_MASK;
> +                       break;
> +               case PIN_CONFIG_DRIVE_STRENGTH:
> +                       mask |= PAD_DRIVE_STRENGTH_MASK;
> +                       value = (value & ~PAD_DRIVE_STRENGTH_MASK) |
> +                               starfive_drive_strength_from_max_mA(arg);
> +                       break;
> +               case PIN_CONFIG_INPUT_ENABLE:
> +                       mask |= PAD_INPUT_ENABLE;
> +                       if (arg)
> +                               value |= PAD_INPUT_ENABLE;
> +                       else
> +                               value &= ~PAD_INPUT_ENABLE;
> +                       break;
> +               case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
> +                       mask |= PAD_INPUT_SCHMITT_ENABLE;
> +                       if (arg)
> +                               value |= PAD_INPUT_SCHMITT_ENABLE;
> +                       else
> +                               value &= ~PAD_INPUT_SCHMITT_ENABLE;
> +                       break;
> +               case PIN_CONFIG_SLEW_RATE:
> +                       mask |= PAD_SLEW_RATE_MASK;
> +                       value = (value & ~PAD_SLEW_RATE_MASK) |
> +                               ((arg << PAD_SLEW_RATE_POS) & PAD_SLEW_RATE_MASK);
> +                       break;
> +               case PIN_CONFIG_STARFIVE_STRONG_PULL_UP:
> +                       if (arg) {
> +                               mask |= PAD_BIAS_MASK;
> +                               value = (value & ~PAD_BIAS_MASK) |
> +                                       PAD_BIAS_STRONG_PULL_UP;
> +                       } else {
> +                               mask |= PAD_BIAS_STRONG_PULL_UP;
> +                               value = value & ~PAD_BIAS_STRONG_PULL_UP;
> +                       }
> +                       break;
> +               default:
> +                       return -ENOTSUPP;
> +               }
> +       }

...

> +static int starfive_gpio_request(struct gpio_chip *gc, unsigned int gpio)
> +{
> +       return pinctrl_gpio_request(gc->base + gpio);
> +}
> +
> +static void starfive_gpio_free(struct gpio_chip *gc, unsigned int gpio)
> +{
> +       pinctrl_gpio_free(gc->base + gpio);
> +}

Point of having these function is...?

...

> +       if (gpio >= NR_GPIOS)
> +               return -EINVAL;

Dead code?

...

> +       if (gpio >= NR_GPIOS)
> +               return -EINVAL;

Dead code?

...

> +       /* enable input and schmitt trigger */

Use capitalization consistently.

...

> +       if (gpio >= NR_GPIOS)
> +               return -EINVAL;

Dead code?

...

> +       if (gpio >= NR_GPIOS)
> +               return -EINVAL;

Dead code?

...

> +       if (gpio >= NR_GPIOS)
> +               return;

Dead code?

...

> +       struct starfive_pinctrl *sfp = starfive_from_gc(gc);

The starfive_from_gc() is useless. Inline it whenever you use it.

...

> +       case IRQ_TYPE_EDGE_RISING:
> +               irq_type  = mask; /* 1: edge triggered */
> +               edge_both = 0;    /* 0: single edge */
> +               polarity  = mask; /* 1: rising edge */
> +               handler   = handle_edge_irq;
> +               break;
> +       case IRQ_TYPE_EDGE_FALLING:
> +               irq_type  = mask; /* 1: edge triggered */
> +               edge_both = 0;    /* 0: single edge */
> +               polarity  = 0;    /* 0: falling edge */
> +               handler   = handle_edge_irq
> +               break;
> +       case IRQ_TYPE_EDGE_BOTH:
> +               irq_type  = mask; /* 1: edge triggered */
> +               edge_both = mask; /* 1: both edges */
> +               polarity  = 0;    /* 0: ignored */
> +               handler   = handle_edge_irq;

Dup. You may do it once without any temporary variable.
I haven't got why you haven't addressed this.

> +               break;
> +       case IRQ_TYPE_LEVEL_HIGH:
> +               irq_type  = 0;    /* 0: level triggered */
> +               edge_both = 0;    /* 0: ignored */
> +               polarity  = mask; /* 1: high level */
> +               handler   = handle_level_irq;
> +               break;
> +       case IRQ_TYPE_LEVEL_LOW:
> +               irq_type  = 0;    /* 0: level triggered */
> +               edge_both = 0;    /* 0: ignored */
> +               polarity  = 0;    /* 0: low level */
> +               handler   = handle_level_irq;

Ditto.

> +               break;

...

> +       clk = devm_clk_get(dev, NULL);
> +       if (IS_ERR(clk)) {

> +               ret = PTR_ERR(clk);

Inline into below.

> +               return dev_err_probe(dev, ret, "could not get clock: %d\n", ret);
> +       }

Ditto for all other similar cases.

...

> +       ret = clk_prepare_enable(clk);
> +       if (ret)
> +               return dev_err_probe(dev, ret, "could not enable clock: %d\n", ret);

Double ret?!Ditto for all other similar cases.

...

> +       if (!device_property_read_u32(dev, "starfive,signal-group", &value)) {

Since you are using of_property_* elsewhere, makes sense to use same
here, or otherwise, use device_*() APIs there.

...

> +done:

Perhaps you may factor out the function and get rid of this label.

-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 12/16] pinctrl: starfive: Add pinctrl driver for StarFive SoCs
@ 2021-10-22 13:31     ` Andy Shevchenko
  0 siblings, 0 replies; 143+ messages in thread
From: Andy Shevchenko @ 2021-10-22 13:31 UTC (permalink / raw)
  To: Emil Renner Berthing
  Cc: linux-riscv, devicetree, linux-clk, open list:GPIO SUBSYSTEM,
	open list:SERIAL DRIVERS, Palmer Dabbelt, Paul Walmsley,
	Rob Herring, Michael Turquette, Stephen Boyd, Thomas Gleixner,
	Marc Zyngier, Philipp Zabel, Linus Walleij, Greg Kroah-Hartman,
	Daniel Lezcano, Andy Shevchenko, Jiri Slaby, Maximilian Luz,
	Sagar Kadam, Drew Fustini, Geert Uytterhoeven, Michael Zhu,
	Fu Wei, Anup Patel, Atish Patra, Matteo Croce,
	Linux Kernel Mailing List, Huan Feng

On Thu, Oct 21, 2021 at 8:44 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
>
> Add a combined pinctrl and GPIO driver for the StarFive JH7100 SoC.
>
> For each "GPIO" there are two registers for configuring the output and
> output enable signals which may come from other peripherals. Among these
> are two special signals that are constant 0 and constant 1 respectively.
> Controlling the GPIOs from software is done by choosing one of these
> signals. In other words the same registers are used for both pinmuxing

pin muxing

> and controlling the GPIOs, which makes it easier to combine the pinctrl
> and GPIO driver in one.
>
> I wrote the pinconf and pinmux parts, but the GPIO part of the code is
> based on the GPIO driver in the vendor tree written by Huan Feng with
> cleanups and fixes by Drew and me.

...

> +#define PAD_BIAS_MASK                  (PAD_BIAS_STRONG_PULL_UP | \
> +                                        PAD_BIAS_DISABLE | \
> +                                        PAD_BIAS_PULL_DOWN)

It's slightly better looking if the value is begins on the next line

#define PAD_BIAS_MASK    \
        (PAD_BIAS_STRONG_PULL_UP | \
         PAD_BIAS_DISABLE | \
         PAD_BIAS_PULL_DOWN)

...

> +       seq_printf(s, "dout=%u%s doen=%u%s",
> +                  dout & (u32)GENMASK(7, 0), (dout & BIT(31)) ? "r" : "",
> +                  doen & (u32)GENMASK(7, 0), (doen & BIT(31)) ? "r" : "");

Why castings?

...

> +       for_each_child_of_node(np, child) {
> +               int npinmux = of_property_count_u32_elems(child, "pinmux");
> +               int npins   = of_property_count_u32_elems(child, "pins");
> +
> +               if (npinmux > 0 && npins > 0) {

> +                       dev_err(dev, "invalid pinctrl group %pOFn.%pOFn: %s\n",
> +                               np, child, "both pinmux and pins set");

Why %s for string literal?! It's quite unusual. Ditto for other similar cases.

> +                       of_node_put(child);
> +                       return -EINVAL;
> +               }

...

> +               } else {
> +                       dev_err(dev, "invalid pinctrl group %pOFn.%pOFn: %s\n",
> +                               np, child, "neither pinmux nor pins set");
> +                       of_node_put(child);
> +                       return -EINVAL;
> +               }

This can be checjed above with other sanity check(s), right?

> +               ngroups += 1;
> +       }

...

> +       ret = -ENOMEM;

It should be below...

> +       pgnames = devm_kcalloc(dev, ngroups, sizeof(*pgnames), GFP_KERNEL);
> +       if (!pgnames)
> +               return ret;

...like here, where it makes more sense.

> +       map = kcalloc(nmaps, sizeof(*map), GFP_KERNEL);
> +       if (!map)
> +               goto free_pgnames;

...

> +       for_each_child_of_node(np, child) {
> +               int npins;
> +               int i;
> +
> +               ret = -ENOMEM;
> +               grpname = devm_kasprintf(dev, GFP_KERNEL, "%s.%s", np->name, child->name);
> +               if (!grpname)
> +                       goto put_child;
> +
> +               pgnames[ngroups++] = grpname;
> +
> +               if ((npins = of_property_count_u32_elems(child, "pinmux")) > 0) {
> +                       pins = devm_kcalloc(dev, npins, sizeof(*pins), GFP_KERNEL);
> +                       if (!pins)
> +                               goto free_grpname;
> +
> +                       pinmux = devm_kcalloc(dev, npins, sizeof(*pinmux), GFP_KERNEL);
> +                       if (!pinmux)
> +                               goto free_pins;
> +
> +                       for (i = 0; i < npins; i++) {
> +                               u32 v;
> +
> +                               ret = of_property_read_u32_index(child, "pinmux", i, &v);
> +                               if (ret)
> +                                       goto free_pinmux;
> +                               pins[i] = starfive_gpio_to_pin(sfp, starfive_pinmux_to_gpio(v));
> +                               pinmux[i] = v;
> +                       }

Why you can't use of_property_read_u32_array() APIs?

> +                       map[nmaps].type = PIN_MAP_TYPE_MUX_GROUP;
> +                       map[nmaps].data.mux.function = np->name;
> +                       map[nmaps].data.mux.group = grpname;
> +                       nmaps += 1;
> +               } else if ((npins = of_property_count_u32_elems(child, "pins")) > 0) {
> +                       pins = devm_kcalloc(dev, npins, sizeof(*pins), GFP_KERNEL);
> +                       if (!pins)
> +                               goto free_grpname;
> +
> +                       pinmux = NULL;
> +
> +                       for (i = 0; i < npins; i++) {
> +                               u32 v;
> +
> +                               ret = of_property_read_u32_index(child, "pins", i, &v);
> +                               if (ret)
> +                                       goto free_pins;
> +                               pins[i] = v;
> +                       }

NIH _array() APIs.

> +               } else {
> +                       ret = -EINVAL;
> +                       goto free_grpname;
> +               }
> +
> +               ret = pinctrl_generic_add_group(pctldev, grpname, pins, npins, pinmux);
> +               if (ret < 0) {
> +                       dev_err(dev, "error adding group %pOFn.%pOFn: %d\n",
> +                               np, child, ret);
> +                       goto free_pinmux;
> +               }
> +
> +               ret = pinconf_generic_parse_dt_config(child, pctldev,
> +                                                     &map[nmaps].data.configs.configs,
> +                                                     &map[nmaps].data.configs.num_configs);
> +               if (ret) {
> +                       dev_err(dev, "invalid pinctrl group %pOFn.%pOFn: %s\n",
> +                               np, child, "error parsing pin config");
> +                       goto put_child;
> +               }
> +
> +               /* don't create a map if there are no pinconf settings */
> +               if (map[nmaps].data.configs.num_configs == 0)
> +                       continue;
> +
> +               map[nmaps].type = PIN_MAP_TYPE_CONFIGS_GROUP;
> +               map[nmaps].data.configs.group_or_pin = grpname;
> +               nmaps += 1;
> +       }

...

> +free_pinmux:
> +       devm_kfree(dev, pinmux);
> +free_pins:
> +       devm_kfree(dev, pins);
> +free_grpname:
> +       devm_kfree(dev, grpname);

> +free_pgnames:
> +       devm_kfree(dev, pgnames);

Just no, please get rid of them either way as I explained in previous reviews.

...

> +               raw_spin_lock_irqsave(&sfp->lock, flags);
> +               writel_relaxed(dout, reg_dout);
> +               writel_relaxed(doen, reg_doen);
> +               if (reg_din)
> +                       writel_relaxed(gpio + 2, reg_din);

Why 0 can't be written?

> +               raw_spin_unlock_irqrestore(&sfp->lock, flags);

...

> +       dev_dbg(starfive_dev(sfp),
> +               "padctl_rmw(%u, 0x%03x, 0x%03x)\n", pin, _mask, _value);

One line?

...

> +       mask = 0;
> +       value = 0;
> +       for (i = 0; i < num_configs; i++) {
> +               int param = pinconf_to_config_param(configs[i]);
> +               u32 arg = pinconf_to_config_argument(configs[i]);
>
+
> +               switch (param) {
> +               case PIN_CONFIG_BIAS_DISABLE:
> +                       mask |= PAD_BIAS_MASK;
> +                       value = (value & ~PAD_BIAS_MASK) | PAD_BIAS_DISABLE;

Okay, I have got why you are masking on each iteration, but here is
the question, shouldn't you apply the cnages belonged to each of the
group of options as it's requested by the user? Here you basically
ignore all previous changes to bias.

I would expect that you have something like

for () {
  switch (type) {
  case BIAS*:
    return apply_bias();
  ...other types...
  default:
    return err;
  }
}

> +                       break;
> +               case PIN_CONFIG_BIAS_PULL_DOWN:
> +                       if (arg == 0)
> +                               return -ENOTSUPP;
> +                       mask |= PAD_BIAS_MASK;
> +                       value = (value & ~PAD_BIAS_MASK) | PAD_BIAS_PULL_DOWN;
> +                       break;
> +               case PIN_CONFIG_BIAS_PULL_UP:
> +                       if (arg == 0)
> +                               return -ENOTSUPP;
> +                       mask |= PAD_BIAS_MASK;
> +                       value = value & ~PAD_BIAS_MASK;
> +                       break;
> +               case PIN_CONFIG_DRIVE_STRENGTH:
> +                       mask |= PAD_DRIVE_STRENGTH_MASK;
> +                       value = (value & ~PAD_DRIVE_STRENGTH_MASK) |
> +                               starfive_drive_strength_from_max_mA(arg);
> +                       break;
> +               case PIN_CONFIG_INPUT_ENABLE:
> +                       mask |= PAD_INPUT_ENABLE;
> +                       if (arg)
> +                               value |= PAD_INPUT_ENABLE;
> +                       else
> +                               value &= ~PAD_INPUT_ENABLE;
> +                       break;
> +               case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
> +                       mask |= PAD_INPUT_SCHMITT_ENABLE;
> +                       if (arg)
> +                               value |= PAD_INPUT_SCHMITT_ENABLE;
> +                       else
> +                               value &= ~PAD_INPUT_SCHMITT_ENABLE;
> +                       break;
> +               case PIN_CONFIG_SLEW_RATE:
> +                       mask |= PAD_SLEW_RATE_MASK;
> +                       value = (value & ~PAD_SLEW_RATE_MASK) |
> +                               ((arg << PAD_SLEW_RATE_POS) & PAD_SLEW_RATE_MASK);
> +                       break;
> +               case PIN_CONFIG_STARFIVE_STRONG_PULL_UP:
> +                       if (arg) {
> +                               mask |= PAD_BIAS_MASK;
> +                               value = (value & ~PAD_BIAS_MASK) |
> +                                       PAD_BIAS_STRONG_PULL_UP;
> +                       } else {
> +                               mask |= PAD_BIAS_STRONG_PULL_UP;
> +                               value = value & ~PAD_BIAS_STRONG_PULL_UP;
> +                       }
> +                       break;
> +               default:
> +                       return -ENOTSUPP;
> +               }
> +       }

...

> +static int starfive_gpio_request(struct gpio_chip *gc, unsigned int gpio)
> +{
> +       return pinctrl_gpio_request(gc->base + gpio);
> +}
> +
> +static void starfive_gpio_free(struct gpio_chip *gc, unsigned int gpio)
> +{
> +       pinctrl_gpio_free(gc->base + gpio);
> +}

Point of having these function is...?

...

> +       if (gpio >= NR_GPIOS)
> +               return -EINVAL;

Dead code?

...

> +       if (gpio >= NR_GPIOS)
> +               return -EINVAL;

Dead code?

...

> +       /* enable input and schmitt trigger */

Use capitalization consistently.

...

> +       if (gpio >= NR_GPIOS)
> +               return -EINVAL;

Dead code?

...

> +       if (gpio >= NR_GPIOS)
> +               return -EINVAL;

Dead code?

...

> +       if (gpio >= NR_GPIOS)
> +               return;

Dead code?

...

> +       struct starfive_pinctrl *sfp = starfive_from_gc(gc);

The starfive_from_gc() is useless. Inline it whenever you use it.

...

> +       case IRQ_TYPE_EDGE_RISING:
> +               irq_type  = mask; /* 1: edge triggered */
> +               edge_both = 0;    /* 0: single edge */
> +               polarity  = mask; /* 1: rising edge */
> +               handler   = handle_edge_irq;
> +               break;
> +       case IRQ_TYPE_EDGE_FALLING:
> +               irq_type  = mask; /* 1: edge triggered */
> +               edge_both = 0;    /* 0: single edge */
> +               polarity  = 0;    /* 0: falling edge */
> +               handler   = handle_edge_irq
> +               break;
> +       case IRQ_TYPE_EDGE_BOTH:
> +               irq_type  = mask; /* 1: edge triggered */
> +               edge_both = mask; /* 1: both edges */
> +               polarity  = 0;    /* 0: ignored */
> +               handler   = handle_edge_irq;

Dup. You may do it once without any temporary variable.
I haven't got why you haven't addressed this.

> +               break;
> +       case IRQ_TYPE_LEVEL_HIGH:
> +               irq_type  = 0;    /* 0: level triggered */
> +               edge_both = 0;    /* 0: ignored */
> +               polarity  = mask; /* 1: high level */
> +               handler   = handle_level_irq;
> +               break;
> +       case IRQ_TYPE_LEVEL_LOW:
> +               irq_type  = 0;    /* 0: level triggered */
> +               edge_both = 0;    /* 0: ignored */
> +               polarity  = 0;    /* 0: low level */
> +               handler   = handle_level_irq;

Ditto.

> +               break;

...

> +       clk = devm_clk_get(dev, NULL);
> +       if (IS_ERR(clk)) {

> +               ret = PTR_ERR(clk);

Inline into below.

> +               return dev_err_probe(dev, ret, "could not get clock: %d\n", ret);
> +       }

Ditto for all other similar cases.

...

> +       ret = clk_prepare_enable(clk);
> +       if (ret)
> +               return dev_err_probe(dev, ret, "could not enable clock: %d\n", ret);

Double ret?!Ditto for all other similar cases.

...

> +       if (!device_property_read_u32(dev, "starfive,signal-group", &value)) {

Since you are using of_property_* elsewhere, makes sense to use same
here, or otherwise, use device_*() APIs there.

...

> +done:

Perhaps you may factor out the function and get rid of this label.

-- 
With Best Regards,
Andy Shevchenko

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 09/16] reset: starfive-jh7100: Add StarFive JH7100 reset driver
  2021-10-22 12:55     ` Andy Shevchenko
@ 2021-10-22 13:34       ` Emil Renner Berthing
  -1 siblings, 0 replies; 143+ messages in thread
From: Emil Renner Berthing @ 2021-10-22 13:34 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: linux-riscv, devicetree, linux-clk, open list:GPIO SUBSYSTEM,
	open list:SERIAL DRIVERS, Palmer Dabbelt, Paul Walmsley,
	Rob Herring, Michael Turquette, Stephen Boyd, Thomas Gleixner,
	Marc Zyngier, Philipp Zabel, Linus Walleij, Greg Kroah-Hartman,
	Daniel Lezcano, Andy Shevchenko, Jiri Slaby, Maximilian Luz,
	Sagar Kadam, Drew Fustini, Geert Uytterhoeven, Michael Zhu,
	Fu Wei, Anup Patel, Atish Patra, Matteo Croce,
	Linux Kernel Mailing List

On Fri, 22 Oct 2021 at 14:56, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> On Thu, Oct 21, 2021 at 8:43 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> > +static const u32 jh7100_reset_asserted[4] = {
>
> > +       BIT(JH7100_RST_U74 % 32) |
> > +       BIT(JH7100_RST_VP6_DRESET % 32) |
> > +       BIT(JH7100_RST_VP6_BRESET % 32),
>
> It's hard to notice that this is only one entry. See also below.

Yeah, so what would be a better way to style it?

> > +       BIT(JH7100_RST_HIFI4_DRESET % 32) |
> > +       BIT(JH7100_RST_HIFI4_BRESET % 32),
> > +
> > +       BIT(JH7100_RST_E24 % 32)
>
> + Comma.
>
> > +};
>
> Why all these ugly % 32 against constants?

Because the JH7100_RST_ values goes higher than 31. There is a
BIT_MASK macro, but that does % BITS_PER_LONG and this is a 64bit
machine.

> ...
>
> > +       if (!assert)
> > +               done ^= mask;
>
> Can you convert this to simple
>
>   if (assert)
>     ret = readl_...
>   else
>     ret = readl_...
>
> below?

I don't see how that would work. We're using the done value in in the
readl_poll_timeout. Maybe you can be a bit more explicit.

The reason is that for most reset lines a 0 in the status register
means it's asserted and a 1 means it's deasserted. For the few reset
lines above this is reversed though.

/Emil

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 09/16] reset: starfive-jh7100: Add StarFive JH7100 reset driver
@ 2021-10-22 13:34       ` Emil Renner Berthing
  0 siblings, 0 replies; 143+ messages in thread
From: Emil Renner Berthing @ 2021-10-22 13:34 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: linux-riscv, devicetree, linux-clk, open list:GPIO SUBSYSTEM,
	open list:SERIAL DRIVERS, Palmer Dabbelt, Paul Walmsley,
	Rob Herring, Michael Turquette, Stephen Boyd, Thomas Gleixner,
	Marc Zyngier, Philipp Zabel, Linus Walleij, Greg Kroah-Hartman,
	Daniel Lezcano, Andy Shevchenko, Jiri Slaby, Maximilian Luz,
	Sagar Kadam, Drew Fustini, Geert Uytterhoeven, Michael Zhu,
	Fu Wei, Anup Patel, Atish Patra, Matteo Croce,
	Linux Kernel Mailing List

On Fri, 22 Oct 2021 at 14:56, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> On Thu, Oct 21, 2021 at 8:43 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> > +static const u32 jh7100_reset_asserted[4] = {
>
> > +       BIT(JH7100_RST_U74 % 32) |
> > +       BIT(JH7100_RST_VP6_DRESET % 32) |
> > +       BIT(JH7100_RST_VP6_BRESET % 32),
>
> It's hard to notice that this is only one entry. See also below.

Yeah, so what would be a better way to style it?

> > +       BIT(JH7100_RST_HIFI4_DRESET % 32) |
> > +       BIT(JH7100_RST_HIFI4_BRESET % 32),
> > +
> > +       BIT(JH7100_RST_E24 % 32)
>
> + Comma.
>
> > +};
>
> Why all these ugly % 32 against constants?

Because the JH7100_RST_ values goes higher than 31. There is a
BIT_MASK macro, but that does % BITS_PER_LONG and this is a 64bit
machine.

> ...
>
> > +       if (!assert)
> > +               done ^= mask;
>
> Can you convert this to simple
>
>   if (assert)
>     ret = readl_...
>   else
>     ret = readl_...
>
> below?

I don't see how that would work. We're using the done value in in the
readl_poll_timeout. Maybe you can be a bit more explicit.

The reason is that for most reset lines a 0 in the status register
means it's asserted and a 1 means it's deasserted. For the few reset
lines above this is reversed though.

/Emil

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 06/16] clk: starfive: Add JH7100 clock generator driver
  2021-10-22 13:13       ` Emil Renner Berthing
@ 2021-10-22 13:35         ` Andy Shevchenko
  -1 siblings, 0 replies; 143+ messages in thread
From: Andy Shevchenko @ 2021-10-22 13:35 UTC (permalink / raw)
  To: Emil Renner Berthing
  Cc: linux-riscv, devicetree, linux-clk, open list:GPIO SUBSYSTEM,
	open list:SERIAL DRIVERS, Geert Uytterhoeven, Palmer Dabbelt,
	Paul Walmsley, Rob Herring, Michael Turquette, Stephen Boyd,
	Thomas Gleixner, Marc Zyngier, Philipp Zabel, Linus Walleij,
	Greg Kroah-Hartman, Daniel Lezcano, Andy Shevchenko, Jiri Slaby,
	Maximilian Luz, Sagar Kadam, Drew Fustini, Michael Zhu, Fu Wei,
	Anup Patel, Atish Patra, Matteo Croce, Linux Kernel Mailing List

On Fri, Oct 22, 2021 at 4:13 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> On Fri, 22 Oct 2021 at 14:34, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:

...

> Hmm.. this function doesn't return int, but struct clk_hw *, hence the ERR_PTR.

Ah, indeed, sorry. Got your point.

Of course one may try 'return ERR_PTR(dev_err_probe())', but this looks ugly.

-- 
With Best Regards,
Andy Shevchenko

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 06/16] clk: starfive: Add JH7100 clock generator driver
@ 2021-10-22 13:35         ` Andy Shevchenko
  0 siblings, 0 replies; 143+ messages in thread
From: Andy Shevchenko @ 2021-10-22 13:35 UTC (permalink / raw)
  To: Emil Renner Berthing
  Cc: linux-riscv, devicetree, linux-clk, open list:GPIO SUBSYSTEM,
	open list:SERIAL DRIVERS, Geert Uytterhoeven, Palmer Dabbelt,
	Paul Walmsley, Rob Herring, Michael Turquette, Stephen Boyd,
	Thomas Gleixner, Marc Zyngier, Philipp Zabel, Linus Walleij,
	Greg Kroah-Hartman, Daniel Lezcano, Andy Shevchenko, Jiri Slaby,
	Maximilian Luz, Sagar Kadam, Drew Fustini, Michael Zhu, Fu Wei,
	Anup Patel, Atish Patra, Matteo Croce, Linux Kernel Mailing List

On Fri, Oct 22, 2021 at 4:13 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> On Fri, 22 Oct 2021 at 14:34, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:

...

> Hmm.. this function doesn't return int, but struct clk_hw *, hence the ERR_PTR.

Ah, indeed, sorry. Got your point.

Of course one may try 'return ERR_PTR(dev_err_probe())', but this looks ugly.

-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 09/16] reset: starfive-jh7100: Add StarFive JH7100 reset driver
  2021-10-22 13:34       ` Emil Renner Berthing
@ 2021-10-22 13:38         ` Andy Shevchenko
  -1 siblings, 0 replies; 143+ messages in thread
From: Andy Shevchenko @ 2021-10-22 13:38 UTC (permalink / raw)
  To: Emil Renner Berthing
  Cc: linux-riscv, devicetree, linux-clk, open list:GPIO SUBSYSTEM,
	open list:SERIAL DRIVERS, Palmer Dabbelt, Paul Walmsley,
	Rob Herring, Michael Turquette, Stephen Boyd, Thomas Gleixner,
	Marc Zyngier, Philipp Zabel, Linus Walleij, Greg Kroah-Hartman,
	Daniel Lezcano, Andy Shevchenko, Jiri Slaby, Maximilian Luz,
	Sagar Kadam, Drew Fustini, Geert Uytterhoeven, Michael Zhu,
	Fu Wei, Anup Patel, Atish Patra, Matteo Croce,
	Linux Kernel Mailing List

On Fri, Oct 22, 2021 at 4:35 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> On Fri, 22 Oct 2021 at 14:56, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > On Thu, Oct 21, 2021 at 8:43 PM Emil Renner Berthing <kernel@esmil.dk> wrote:

...

> > Why all these ugly % 32 against constants?
>
> Because the JH7100_RST_ values goes higher than 31. There is a
> BIT_MASK macro, but that does % BITS_PER_LONG and this is a 64bit
> machine.

And? It's exactly what you have to use!

...

> > Can you convert this to simple
> >
> >   if (assert)
> >     ret = readl_...
> >   else
> >     ret = readl_...
> >
> > below?
>
> I don't see how that would work. We're using the done value in in the
> readl_poll_timeout. Maybe you can be a bit more explicit.

Supply done either == mask or == ^mask. Try it.

-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 09/16] reset: starfive-jh7100: Add StarFive JH7100 reset driver
@ 2021-10-22 13:38         ` Andy Shevchenko
  0 siblings, 0 replies; 143+ messages in thread
From: Andy Shevchenko @ 2021-10-22 13:38 UTC (permalink / raw)
  To: Emil Renner Berthing
  Cc: linux-riscv, devicetree, linux-clk, open list:GPIO SUBSYSTEM,
	open list:SERIAL DRIVERS, Palmer Dabbelt, Paul Walmsley,
	Rob Herring, Michael Turquette, Stephen Boyd, Thomas Gleixner,
	Marc Zyngier, Philipp Zabel, Linus Walleij, Greg Kroah-Hartman,
	Daniel Lezcano, Andy Shevchenko, Jiri Slaby, Maximilian Luz,
	Sagar Kadam, Drew Fustini, Geert Uytterhoeven, Michael Zhu,
	Fu Wei, Anup Patel, Atish Patra, Matteo Croce,
	Linux Kernel Mailing List

On Fri, Oct 22, 2021 at 4:35 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> On Fri, 22 Oct 2021 at 14:56, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > On Thu, Oct 21, 2021 at 8:43 PM Emil Renner Berthing <kernel@esmil.dk> wrote:

...

> > Why all these ugly % 32 against constants?
>
> Because the JH7100_RST_ values goes higher than 31. There is a
> BIT_MASK macro, but that does % BITS_PER_LONG and this is a 64bit
> machine.

And? It's exactly what you have to use!

...

> > Can you convert this to simple
> >
> >   if (assert)
> >     ret = readl_...
> >   else
> >     ret = readl_...
> >
> > below?
>
> I don't see how that would work. We're using the done value in in the
> readl_poll_timeout. Maybe you can be a bit more explicit.

Supply done either == mask or == ^mask. Try it.

-- 
With Best Regards,
Andy Shevchenko

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 09/16] reset: starfive-jh7100: Add StarFive JH7100 reset driver
  2021-10-22 13:06     ` Andreas Schwab
@ 2021-10-22 13:41       ` Emil Renner Berthing
  -1 siblings, 0 replies; 143+ messages in thread
From: Emil Renner Berthing @ 2021-10-22 13:41 UTC (permalink / raw)
  To: Andreas Schwab
  Cc: linux-riscv,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	linux-clk, open list:GPIO SUBSYSTEM, open list:SERIAL DRIVERS,
	Palmer Dabbelt, Paul Walmsley, Rob Herring, Michael Turquette,
	Stephen Boyd, Thomas Gleixner, Marc Zyngier, Philipp Zabel,
	Linus Walleij, Greg Kroah-Hartman, Daniel Lezcano,
	Andy Shevchenko, Jiri Slaby, Maximilian Luz, Sagar Kadam,
	Drew Fustini, Geert Uytterhoeven, Michael Zhu, Fu Wei,
	Anup Patel, Atish Patra, Matteo Croce, Linux Kernel Mailing List

On Fri, 22 Oct 2021 at 15:06, Andreas Schwab <schwab@linux-m68k.org> wrote:
> On Okt 21 2021, Emil Renner Berthing wrote:
>
> > +config RESET_STARFIVE_JH7100
> > +     bool "StarFive JH7100 Reset Driver"
> > +     depends on SOC_STARFIVE || COMPILE_TEST
>
> Why does it need to depend on SOC_STARFIVE?

It strictly doesn't but most other drivers in the same Kconfig file
also depends on ARCH_something or SOC_something. In particular
RESET_K210 depends on SOC_CANAAN. I think this is to prevent
overwhelming the user with useless choices if they didn't enable the
relevant SoC, and for others there are the COMPILE_TEST option.

/Emil

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 09/16] reset: starfive-jh7100: Add StarFive JH7100 reset driver
@ 2021-10-22 13:41       ` Emil Renner Berthing
  0 siblings, 0 replies; 143+ messages in thread
From: Emil Renner Berthing @ 2021-10-22 13:41 UTC (permalink / raw)
  To: Andreas Schwab
  Cc: linux-riscv,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	linux-clk, open list:GPIO SUBSYSTEM, open list:SERIAL DRIVERS,
	Palmer Dabbelt, Paul Walmsley, Rob Herring, Michael Turquette,
	Stephen Boyd, Thomas Gleixner, Marc Zyngier, Philipp Zabel,
	Linus Walleij, Greg Kroah-Hartman, Daniel Lezcano,
	Andy Shevchenko, Jiri Slaby, Maximilian Luz, Sagar Kadam,
	Drew Fustini, Geert Uytterhoeven, Michael Zhu, Fu Wei,
	Anup Patel, Atish Patra, Matteo Croce, Linux Kernel Mailing List

On Fri, 22 Oct 2021 at 15:06, Andreas Schwab <schwab@linux-m68k.org> wrote:
> On Okt 21 2021, Emil Renner Berthing wrote:
>
> > +config RESET_STARFIVE_JH7100
> > +     bool "StarFive JH7100 Reset Driver"
> > +     depends on SOC_STARFIVE || COMPILE_TEST
>
> Why does it need to depend on SOC_STARFIVE?

It strictly doesn't but most other drivers in the same Kconfig file
also depends on ARCH_something or SOC_something. In particular
RESET_K210 depends on SOC_CANAAN. I think this is to prevent
overwhelming the user with useless choices if they didn't enable the
relevant SoC, and for others there are the COMPILE_TEST option.

/Emil

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 09/16] reset: starfive-jh7100: Add StarFive JH7100 reset driver
  2021-10-22 13:38         ` Andy Shevchenko
@ 2021-10-22 13:50           ` Emil Renner Berthing
  -1 siblings, 0 replies; 143+ messages in thread
From: Emil Renner Berthing @ 2021-10-22 13:50 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: linux-riscv, devicetree, linux-clk, open list:GPIO SUBSYSTEM,
	open list:SERIAL DRIVERS, Palmer Dabbelt, Paul Walmsley,
	Rob Herring, Michael Turquette, Stephen Boyd, Thomas Gleixner,
	Marc Zyngier, Philipp Zabel, Linus Walleij, Greg Kroah-Hartman,
	Daniel Lezcano, Andy Shevchenko, Jiri Slaby, Maximilian Luz,
	Sagar Kadam, Drew Fustini, Geert Uytterhoeven, Michael Zhu,
	Fu Wei, Anup Patel, Atish Patra, Matteo Croce,
	Linux Kernel Mailing List

On Fri, 22 Oct 2021 at 15:39, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> On Fri, Oct 22, 2021 at 4:35 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> > On Fri, 22 Oct 2021 at 14:56, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > > On Thu, Oct 21, 2021 at 8:43 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
>
> ...
>
> > > Why all these ugly % 32 against constants?
> >
> > Because the JH7100_RST_ values goes higher than 31. There is a
> > BIT_MASK macro, but that does % BITS_PER_LONG and this is a 64bit
> > machine.
>
> And? It's exactly what you have to use!


> > > Can you convert this to simple
> > >
> > >   if (assert)
> > >     ret = readl_...
> > >   else
> > >     ret = readl_...
> > >
> > > below?
> >
> > I don't see how that would work. We're using the done value in in the
> > readl_poll_timeout. Maybe you can be a bit more explicit.
>
> Supply done either == mask or == ^mask. Try it.

So you want this?
if (assert)
  ret = readl_poll_timeout_atomic(reg_status, value, (value & mask) ==
done, 0, 1000);
else
  ret = readl_poll_timeout_atomic(reg_status, value, (value & mask) ==
^done, 0, 1000);

The compiler might be clever enough, but I'd worry the long body of
the readl_poll_timeout_atomic macro is inline twice. Rather than just
flipping the bit in `done`.

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 09/16] reset: starfive-jh7100: Add StarFive JH7100 reset driver
@ 2021-10-22 13:50           ` Emil Renner Berthing
  0 siblings, 0 replies; 143+ messages in thread
From: Emil Renner Berthing @ 2021-10-22 13:50 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: linux-riscv, devicetree, linux-clk, open list:GPIO SUBSYSTEM,
	open list:SERIAL DRIVERS, Palmer Dabbelt, Paul Walmsley,
	Rob Herring, Michael Turquette, Stephen Boyd, Thomas Gleixner,
	Marc Zyngier, Philipp Zabel, Linus Walleij, Greg Kroah-Hartman,
	Daniel Lezcano, Andy Shevchenko, Jiri Slaby, Maximilian Luz,
	Sagar Kadam, Drew Fustini, Geert Uytterhoeven, Michael Zhu,
	Fu Wei, Anup Patel, Atish Patra, Matteo Croce,
	Linux Kernel Mailing List

On Fri, 22 Oct 2021 at 15:39, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> On Fri, Oct 22, 2021 at 4:35 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> > On Fri, 22 Oct 2021 at 14:56, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > > On Thu, Oct 21, 2021 at 8:43 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
>
> ...
>
> > > Why all these ugly % 32 against constants?
> >
> > Because the JH7100_RST_ values goes higher than 31. There is a
> > BIT_MASK macro, but that does % BITS_PER_LONG and this is a 64bit
> > machine.
>
> And? It's exactly what you have to use!


> > > Can you convert this to simple
> > >
> > >   if (assert)
> > >     ret = readl_...
> > >   else
> > >     ret = readl_...
> > >
> > > below?
> >
> > I don't see how that would work. We're using the done value in in the
> > readl_poll_timeout. Maybe you can be a bit more explicit.
>
> Supply done either == mask or == ^mask. Try it.

So you want this?
if (assert)
  ret = readl_poll_timeout_atomic(reg_status, value, (value & mask) ==
done, 0, 1000);
else
  ret = readl_poll_timeout_atomic(reg_status, value, (value & mask) ==
^done, 0, 1000);

The compiler might be clever enough, but I'd worry the long body of
the readl_poll_timeout_atomic macro is inline twice. Rather than just
flipping the bit in `done`.

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 09/16] reset: starfive-jh7100: Add StarFive JH7100 reset driver
  2021-10-22 13:50           ` Emil Renner Berthing
@ 2021-10-22 13:56             ` Andy Shevchenko
  -1 siblings, 0 replies; 143+ messages in thread
From: Andy Shevchenko @ 2021-10-22 13:56 UTC (permalink / raw)
  To: Emil Renner Berthing
  Cc: linux-riscv, devicetree, linux-clk, open list:GPIO SUBSYSTEM,
	open list:SERIAL DRIVERS, Palmer Dabbelt, Paul Walmsley,
	Rob Herring, Michael Turquette, Stephen Boyd, Thomas Gleixner,
	Marc Zyngier, Philipp Zabel, Linus Walleij, Greg Kroah-Hartman,
	Daniel Lezcano, Andy Shevchenko, Jiri Slaby, Maximilian Luz,
	Sagar Kadam, Drew Fustini, Geert Uytterhoeven, Michael Zhu,
	Fu Wei, Anup Patel, Atish Patra, Matteo Croce,
	Linux Kernel Mailing List

On Fri, Oct 22, 2021 at 4:50 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> On Fri, 22 Oct 2021 at 15:39, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > On Fri, Oct 22, 2021 at 4:35 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> > > On Fri, 22 Oct 2021 at 14:56, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > > > On Thu, Oct 21, 2021 at 8:43 PM Emil Renner Berthing <kernel@esmil.dk> wrote:

...

> > > > Can you convert this to simple
> > > >
> > > >   if (assert)
> > > >     ret = readl_...
> > > >   else
> > > >     ret = readl_...
> > > >
> > > > below?
> > >
> > > I don't see how that would work. We're using the done value in in the
> > > readl_poll_timeout. Maybe you can be a bit more explicit.
> >
> > Supply done either == mask or == ^mask. Try it.
>
> So you want this?
> if (assert)
>   ret = readl_poll_timeout_atomic(reg_status, value, (value & mask) ==
> done, 0, 1000);
> else
>   ret = readl_poll_timeout_atomic(reg_status, value, (value & mask) ==
> ^done, 0, 1000);
>
> The compiler might be clever enough, but I'd worry the long body of
> the readl_poll_timeout_atomic macro is inline twice. Rather than just
> flipping the bit in `done`.

You have a point, although it would be nice to have confirmation of either.

-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 09/16] reset: starfive-jh7100: Add StarFive JH7100 reset driver
@ 2021-10-22 13:56             ` Andy Shevchenko
  0 siblings, 0 replies; 143+ messages in thread
From: Andy Shevchenko @ 2021-10-22 13:56 UTC (permalink / raw)
  To: Emil Renner Berthing
  Cc: linux-riscv, devicetree, linux-clk, open list:GPIO SUBSYSTEM,
	open list:SERIAL DRIVERS, Palmer Dabbelt, Paul Walmsley,
	Rob Herring, Michael Turquette, Stephen Boyd, Thomas Gleixner,
	Marc Zyngier, Philipp Zabel, Linus Walleij, Greg Kroah-Hartman,
	Daniel Lezcano, Andy Shevchenko, Jiri Slaby, Maximilian Luz,
	Sagar Kadam, Drew Fustini, Geert Uytterhoeven, Michael Zhu,
	Fu Wei, Anup Patel, Atish Patra, Matteo Croce,
	Linux Kernel Mailing List

On Fri, Oct 22, 2021 at 4:50 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> On Fri, 22 Oct 2021 at 15:39, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > On Fri, Oct 22, 2021 at 4:35 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> > > On Fri, 22 Oct 2021 at 14:56, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > > > On Thu, Oct 21, 2021 at 8:43 PM Emil Renner Berthing <kernel@esmil.dk> wrote:

...

> > > > Can you convert this to simple
> > > >
> > > >   if (assert)
> > > >     ret = readl_...
> > > >   else
> > > >     ret = readl_...
> > > >
> > > > below?
> > >
> > > I don't see how that would work. We're using the done value in in the
> > > readl_poll_timeout. Maybe you can be a bit more explicit.
> >
> > Supply done either == mask or == ^mask. Try it.
>
> So you want this?
> if (assert)
>   ret = readl_poll_timeout_atomic(reg_status, value, (value & mask) ==
> done, 0, 1000);
> else
>   ret = readl_poll_timeout_atomic(reg_status, value, (value & mask) ==
> ^done, 0, 1000);
>
> The compiler might be clever enough, but I'd worry the long body of
> the readl_poll_timeout_atomic macro is inline twice. Rather than just
> flipping the bit in `done`.

You have a point, although it would be nice to have confirmation of either.

-- 
With Best Regards,
Andy Shevchenko

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 09/16] reset: starfive-jh7100: Add StarFive JH7100 reset driver
  2021-10-22 13:38         ` Andy Shevchenko
@ 2021-10-22 14:25           ` Emil Renner Berthing
  -1 siblings, 0 replies; 143+ messages in thread
From: Emil Renner Berthing @ 2021-10-22 14:25 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: linux-riscv, devicetree, linux-clk, open list:GPIO SUBSYSTEM,
	open list:SERIAL DRIVERS, Palmer Dabbelt, Paul Walmsley,
	Rob Herring, Michael Turquette, Stephen Boyd, Thomas Gleixner,
	Marc Zyngier, Philipp Zabel, Linus Walleij, Greg Kroah-Hartman,
	Daniel Lezcano, Andy Shevchenko, Jiri Slaby, Maximilian Luz,
	Sagar Kadam, Drew Fustini, Geert Uytterhoeven, Michael Zhu,
	Fu Wei, Anup Patel, Atish Patra, Matteo Croce,
	Linux Kernel Mailing List

On Fri, 22 Oct 2021 at 15:39, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> On Fri, Oct 22, 2021 at 4:35 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> > On Fri, 22 Oct 2021 at 14:56, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > > On Thu, Oct 21, 2021 at 8:43 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
>
> ...
>
> > > Why all these ugly % 32 against constants?
> >
> > Because the JH7100_RST_ values goes higher than 31. There is a
> > BIT_MASK macro, but that does % BITS_PER_LONG and this is a 64bit
> > machine.
>
> And? It's exactly what you have to use!

So you want me to use an unsigned long array or DECLARE_BITMAP and
juggle two different index and bit offsets?
Also is there a macro for handling that we'd then need 4 commas on
32bit COMPILE_TEST and 2 commas on 64bit?
If you have some other way in mind you'll have to be a lot more explicit again.

The point of the jh7100_reset_asserted array is that it exactly
mirrors the values of the status registers when the lines are
asserted. Maybe writing it like this would be more explicit:

static const u32 jh7100_reset_asserted[4] = {
        /* STATUS0 register */
        BIT(JH7100_RST_U74 % 32) |
        BIT(JH7100_RST_VP6_DRESET % 32) |
        BIT(JH7100_RST_VP6_BRESET % 32),
        /* STATUS1 register */
        BIT(JH7100_RST_HIFI4_DRESET % 32) |
        BIT(JH7100_RST_HIFI4_BRESET % 32),
        /* STATUS2 register */
        BIT(JH7100_RST_E24 % 32),
        /* STATUS3 register */
        0,
};

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 09/16] reset: starfive-jh7100: Add StarFive JH7100 reset driver
@ 2021-10-22 14:25           ` Emil Renner Berthing
  0 siblings, 0 replies; 143+ messages in thread
From: Emil Renner Berthing @ 2021-10-22 14:25 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: linux-riscv, devicetree, linux-clk, open list:GPIO SUBSYSTEM,
	open list:SERIAL DRIVERS, Palmer Dabbelt, Paul Walmsley,
	Rob Herring, Michael Turquette, Stephen Boyd, Thomas Gleixner,
	Marc Zyngier, Philipp Zabel, Linus Walleij, Greg Kroah-Hartman,
	Daniel Lezcano, Andy Shevchenko, Jiri Slaby, Maximilian Luz,
	Sagar Kadam, Drew Fustini, Geert Uytterhoeven, Michael Zhu,
	Fu Wei, Anup Patel, Atish Patra, Matteo Croce,
	Linux Kernel Mailing List

On Fri, 22 Oct 2021 at 15:39, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> On Fri, Oct 22, 2021 at 4:35 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> > On Fri, 22 Oct 2021 at 14:56, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > > On Thu, Oct 21, 2021 at 8:43 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
>
> ...
>
> > > Why all these ugly % 32 against constants?
> >
> > Because the JH7100_RST_ values goes higher than 31. There is a
> > BIT_MASK macro, but that does % BITS_PER_LONG and this is a 64bit
> > machine.
>
> And? It's exactly what you have to use!

So you want me to use an unsigned long array or DECLARE_BITMAP and
juggle two different index and bit offsets?
Also is there a macro for handling that we'd then need 4 commas on
32bit COMPILE_TEST and 2 commas on 64bit?
If you have some other way in mind you'll have to be a lot more explicit again.

The point of the jh7100_reset_asserted array is that it exactly
mirrors the values of the status registers when the lines are
asserted. Maybe writing it like this would be more explicit:

static const u32 jh7100_reset_asserted[4] = {
        /* STATUS0 register */
        BIT(JH7100_RST_U74 % 32) |
        BIT(JH7100_RST_VP6_DRESET % 32) |
        BIT(JH7100_RST_VP6_BRESET % 32),
        /* STATUS1 register */
        BIT(JH7100_RST_HIFI4_DRESET % 32) |
        BIT(JH7100_RST_HIFI4_BRESET % 32),
        /* STATUS2 register */
        BIT(JH7100_RST_E24 % 32),
        /* STATUS3 register */
        0,
};

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 09/16] reset: starfive-jh7100: Add StarFive JH7100 reset driver
  2021-10-22 14:25           ` Emil Renner Berthing
@ 2021-10-22 14:49             ` Andy Shevchenko
  -1 siblings, 0 replies; 143+ messages in thread
From: Andy Shevchenko @ 2021-10-22 14:49 UTC (permalink / raw)
  To: Emil Renner Berthing
  Cc: linux-riscv, devicetree, linux-clk, open list:GPIO SUBSYSTEM,
	open list:SERIAL DRIVERS, Palmer Dabbelt, Paul Walmsley,
	Rob Herring, Michael Turquette, Stephen Boyd, Thomas Gleixner,
	Marc Zyngier, Philipp Zabel, Linus Walleij, Greg Kroah-Hartman,
	Daniel Lezcano, Andy Shevchenko, Jiri Slaby, Maximilian Luz,
	Sagar Kadam, Drew Fustini, Geert Uytterhoeven, Michael Zhu,
	Fu Wei, Anup Patel, Atish Patra, Matteo Croce,
	Linux Kernel Mailing List

On Fri, Oct 22, 2021 at 5:25 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> On Fri, 22 Oct 2021 at 15:39, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > On Fri, Oct 22, 2021 at 4:35 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> > > On Fri, 22 Oct 2021 at 14:56, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > > > On Thu, Oct 21, 2021 at 8:43 PM Emil Renner Berthing <kernel@esmil.dk> wrote:

...

> > > > Why all these ugly % 32 against constants?
> > >
> > > Because the JH7100_RST_ values goes higher than 31. There is a
> > > BIT_MASK macro, but that does % BITS_PER_LONG and this is a 64bit
> > > machine.
> >
> > And? It's exactly what you have to use!
>
> So you want me to use an unsigned long array or DECLARE_BITMAP and
> juggle two different index and bit offsets?

What are the offsets of those status registers?
AFAICS they are sequential 4 32-bit registers.

So bitmap is exactly what is suitable here, you are right!
See gpio-xilinx and gpio-pca953x on how to use bitmaps in the GPIO drivers.

> Also is there a macro for handling that we'd then need 4 commas on
> 32bit COMPILE_TEST and 2 commas on 64bit?
> If you have some other way in mind you'll have to be a lot more explicit again.
>
> The point of the jh7100_reset_asserted array is that it exactly
> mirrors the values of the status registers when the lines are
> asserted. Maybe writing it like this would be more explicit:
>
> static const u32 jh7100_reset_asserted[4] = {
>         /* STATUS0 register */
>         BIT(JH7100_RST_U74 % 32) |
>         BIT(JH7100_RST_VP6_DRESET % 32) |
>         BIT(JH7100_RST_VP6_BRESET % 32),
>         /* STATUS1 register */
>         BIT(JH7100_RST_HIFI4_DRESET % 32) |
>         BIT(JH7100_RST_HIFI4_BRESET % 32),
>         /* STATUS2 register */
>         BIT(JH7100_RST_E24 % 32),
>         /* STATUS3 register */
>         0,
> };

--
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 09/16] reset: starfive-jh7100: Add StarFive JH7100 reset driver
@ 2021-10-22 14:49             ` Andy Shevchenko
  0 siblings, 0 replies; 143+ messages in thread
From: Andy Shevchenko @ 2021-10-22 14:49 UTC (permalink / raw)
  To: Emil Renner Berthing
  Cc: linux-riscv, devicetree, linux-clk, open list:GPIO SUBSYSTEM,
	open list:SERIAL DRIVERS, Palmer Dabbelt, Paul Walmsley,
	Rob Herring, Michael Turquette, Stephen Boyd, Thomas Gleixner,
	Marc Zyngier, Philipp Zabel, Linus Walleij, Greg Kroah-Hartman,
	Daniel Lezcano, Andy Shevchenko, Jiri Slaby, Maximilian Luz,
	Sagar Kadam, Drew Fustini, Geert Uytterhoeven, Michael Zhu,
	Fu Wei, Anup Patel, Atish Patra, Matteo Croce,
	Linux Kernel Mailing List

On Fri, Oct 22, 2021 at 5:25 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> On Fri, 22 Oct 2021 at 15:39, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > On Fri, Oct 22, 2021 at 4:35 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> > > On Fri, 22 Oct 2021 at 14:56, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > > > On Thu, Oct 21, 2021 at 8:43 PM Emil Renner Berthing <kernel@esmil.dk> wrote:

...

> > > > Why all these ugly % 32 against constants?
> > >
> > > Because the JH7100_RST_ values goes higher than 31. There is a
> > > BIT_MASK macro, but that does % BITS_PER_LONG and this is a 64bit
> > > machine.
> >
> > And? It's exactly what you have to use!
>
> So you want me to use an unsigned long array or DECLARE_BITMAP and
> juggle two different index and bit offsets?

What are the offsets of those status registers?
AFAICS they are sequential 4 32-bit registers.

So bitmap is exactly what is suitable here, you are right!
See gpio-xilinx and gpio-pca953x on how to use bitmaps in the GPIO drivers.

> Also is there a macro for handling that we'd then need 4 commas on
> 32bit COMPILE_TEST and 2 commas on 64bit?
> If you have some other way in mind you'll have to be a lot more explicit again.
>
> The point of the jh7100_reset_asserted array is that it exactly
> mirrors the values of the status registers when the lines are
> asserted. Maybe writing it like this would be more explicit:
>
> static const u32 jh7100_reset_asserted[4] = {
>         /* STATUS0 register */
>         BIT(JH7100_RST_U74 % 32) |
>         BIT(JH7100_RST_VP6_DRESET % 32) |
>         BIT(JH7100_RST_VP6_BRESET % 32),
>         /* STATUS1 register */
>         BIT(JH7100_RST_HIFI4_DRESET % 32) |
>         BIT(JH7100_RST_HIFI4_BRESET % 32),
>         /* STATUS2 register */
>         BIT(JH7100_RST_E24 % 32),
>         /* STATUS3 register */
>         0,
> };

--
With Best Regards,
Andy Shevchenko

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 09/16] reset: starfive-jh7100: Add StarFive JH7100 reset driver
  2021-10-22 14:49             ` Andy Shevchenko
@ 2021-10-22 14:50               ` Andy Shevchenko
  -1 siblings, 0 replies; 143+ messages in thread
From: Andy Shevchenko @ 2021-10-22 14:50 UTC (permalink / raw)
  To: Emil Renner Berthing
  Cc: linux-riscv, devicetree, linux-clk, open list:GPIO SUBSYSTEM,
	open list:SERIAL DRIVERS, Palmer Dabbelt, Paul Walmsley,
	Rob Herring, Michael Turquette, Stephen Boyd, Thomas Gleixner,
	Marc Zyngier, Philipp Zabel, Linus Walleij, Greg Kroah-Hartman,
	Daniel Lezcano, Andy Shevchenko, Jiri Slaby, Maximilian Luz,
	Sagar Kadam, Drew Fustini, Geert Uytterhoeven, Michael Zhu,
	Fu Wei, Anup Patel, Atish Patra, Matteo Croce,
	Linux Kernel Mailing List

On Fri, Oct 22, 2021 at 5:49 PM Andy Shevchenko
<andy.shevchenko@gmail.com> wrote:
> On Fri, Oct 22, 2021 at 5:25 PM Emil Renner Berthing <kernel@esmil.dk> wrote:

...

> See gpio-xilinx and gpio-pca953x on how to use bitmaps in the GPIO drivers.

It might be confusing, what I meant is take that as an example on how
the bitmaps are used in the GPIO drivers.

-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 09/16] reset: starfive-jh7100: Add StarFive JH7100 reset driver
@ 2021-10-22 14:50               ` Andy Shevchenko
  0 siblings, 0 replies; 143+ messages in thread
From: Andy Shevchenko @ 2021-10-22 14:50 UTC (permalink / raw)
  To: Emil Renner Berthing
  Cc: linux-riscv, devicetree, linux-clk, open list:GPIO SUBSYSTEM,
	open list:SERIAL DRIVERS, Palmer Dabbelt, Paul Walmsley,
	Rob Herring, Michael Turquette, Stephen Boyd, Thomas Gleixner,
	Marc Zyngier, Philipp Zabel, Linus Walleij, Greg Kroah-Hartman,
	Daniel Lezcano, Andy Shevchenko, Jiri Slaby, Maximilian Luz,
	Sagar Kadam, Drew Fustini, Geert Uytterhoeven, Michael Zhu,
	Fu Wei, Anup Patel, Atish Patra, Matteo Croce,
	Linux Kernel Mailing List

On Fri, Oct 22, 2021 at 5:49 PM Andy Shevchenko
<andy.shevchenko@gmail.com> wrote:
> On Fri, Oct 22, 2021 at 5:25 PM Emil Renner Berthing <kernel@esmil.dk> wrote:

...

> See gpio-xilinx and gpio-pca953x on how to use bitmaps in the GPIO drivers.

It might be confusing, what I meant is take that as an example on how
the bitmaps are used in the GPIO drivers.

-- 
With Best Regards,
Andy Shevchenko

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 09/16] reset: starfive-jh7100: Add StarFive JH7100 reset driver
  2021-10-22 14:49             ` Andy Shevchenko
@ 2021-10-22 14:56               ` Emil Renner Berthing
  -1 siblings, 0 replies; 143+ messages in thread
From: Emil Renner Berthing @ 2021-10-22 14:56 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: linux-riscv, devicetree, linux-clk, open list:GPIO SUBSYSTEM,
	open list:SERIAL DRIVERS, Palmer Dabbelt, Paul Walmsley,
	Rob Herring, Michael Turquette, Stephen Boyd, Thomas Gleixner,
	Marc Zyngier, Philipp Zabel, Linus Walleij, Greg Kroah-Hartman,
	Daniel Lezcano, Andy Shevchenko, Jiri Slaby, Maximilian Luz,
	Sagar Kadam, Drew Fustini, Geert Uytterhoeven, Michael Zhu,
	Fu Wei, Anup Patel, Atish Patra, Matteo Croce,
	Linux Kernel Mailing List

On Fri, 22 Oct 2021 at 16:50, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> On Fri, Oct 22, 2021 at 5:25 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> > On Fri, 22 Oct 2021 at 15:39, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > > On Fri, Oct 22, 2021 at 4:35 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> > > > On Fri, 22 Oct 2021 at 14:56, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > > > > On Thu, Oct 21, 2021 at 8:43 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
>
> ...
>
> > > > > Why all these ugly % 32 against constants?
> > > >
> > > > Because the JH7100_RST_ values goes higher than 31. There is a
> > > > BIT_MASK macro, but that does % BITS_PER_LONG and this is a 64bit
> > > > machine.
> > >
> > > And? It's exactly what you have to use!
> >
> > So you want me to use an unsigned long array or DECLARE_BITMAP and
> > juggle two different index and bit offsets?
>
> What are the offsets of those status registers?
> AFAICS they are sequential 4 32-bit registers.

That's right, but we're on a 64bit machine, so DECLARE_BITMAP will
give us an unsigned long array that doesn't match that.

> So bitmap is exactly what is suitable here, you are right!
> See gpio-xilinx and gpio-pca953x on how to use bitmaps in the GPIO drivers.

None of them has a pre-initialized const DECLARE_BITMAP, so they don't
have to deal with the 4 vs. 2 commas problem.

> > Also is there a macro for handling that we'd then need 4 commas on
> > 32bit COMPILE_TEST and 2 commas on 64bit?
> > If you have some other way in mind you'll have to be a lot more explicit again.
> >
> > The point of the jh7100_reset_asserted array is that it exactly
> > mirrors the values of the status registers when the lines are
> > asserted. Maybe writing it like this would be more explicit:
> >
> > static const u32 jh7100_reset_asserted[4] = {
> >         /* STATUS0 register */
> >         BIT(JH7100_RST_U74 % 32) |
> >         BIT(JH7100_RST_VP6_DRESET % 32) |
> >         BIT(JH7100_RST_VP6_BRESET % 32),
> >         /* STATUS1 register */
> >         BIT(JH7100_RST_HIFI4_DRESET % 32) |
> >         BIT(JH7100_RST_HIFI4_BRESET % 32),
> >         /* STATUS2 register */
> >         BIT(JH7100_RST_E24 % 32),
> >         /* STATUS3 register */
> >         0,
> > };
>
> --
> With Best Regards,
> Andy Shevchenko

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 09/16] reset: starfive-jh7100: Add StarFive JH7100 reset driver
@ 2021-10-22 14:56               ` Emil Renner Berthing
  0 siblings, 0 replies; 143+ messages in thread
From: Emil Renner Berthing @ 2021-10-22 14:56 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: linux-riscv, devicetree, linux-clk, open list:GPIO SUBSYSTEM,
	open list:SERIAL DRIVERS, Palmer Dabbelt, Paul Walmsley,
	Rob Herring, Michael Turquette, Stephen Boyd, Thomas Gleixner,
	Marc Zyngier, Philipp Zabel, Linus Walleij, Greg Kroah-Hartman,
	Daniel Lezcano, Andy Shevchenko, Jiri Slaby, Maximilian Luz,
	Sagar Kadam, Drew Fustini, Geert Uytterhoeven, Michael Zhu,
	Fu Wei, Anup Patel, Atish Patra, Matteo Croce,
	Linux Kernel Mailing List

On Fri, 22 Oct 2021 at 16:50, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> On Fri, Oct 22, 2021 at 5:25 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> > On Fri, 22 Oct 2021 at 15:39, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > > On Fri, Oct 22, 2021 at 4:35 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> > > > On Fri, 22 Oct 2021 at 14:56, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > > > > On Thu, Oct 21, 2021 at 8:43 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
>
> ...
>
> > > > > Why all these ugly % 32 against constants?
> > > >
> > > > Because the JH7100_RST_ values goes higher than 31. There is a
> > > > BIT_MASK macro, but that does % BITS_PER_LONG and this is a 64bit
> > > > machine.
> > >
> > > And? It's exactly what you have to use!
> >
> > So you want me to use an unsigned long array or DECLARE_BITMAP and
> > juggle two different index and bit offsets?
>
> What are the offsets of those status registers?
> AFAICS they are sequential 4 32-bit registers.

That's right, but we're on a 64bit machine, so DECLARE_BITMAP will
give us an unsigned long array that doesn't match that.

> So bitmap is exactly what is suitable here, you are right!
> See gpio-xilinx and gpio-pca953x on how to use bitmaps in the GPIO drivers.

None of them has a pre-initialized const DECLARE_BITMAP, so they don't
have to deal with the 4 vs. 2 commas problem.

> > Also is there a macro for handling that we'd then need 4 commas on
> > 32bit COMPILE_TEST and 2 commas on 64bit?
> > If you have some other way in mind you'll have to be a lot more explicit again.
> >
> > The point of the jh7100_reset_asserted array is that it exactly
> > mirrors the values of the status registers when the lines are
> > asserted. Maybe writing it like this would be more explicit:
> >
> > static const u32 jh7100_reset_asserted[4] = {
> >         /* STATUS0 register */
> >         BIT(JH7100_RST_U74 % 32) |
> >         BIT(JH7100_RST_VP6_DRESET % 32) |
> >         BIT(JH7100_RST_VP6_BRESET % 32),
> >         /* STATUS1 register */
> >         BIT(JH7100_RST_HIFI4_DRESET % 32) |
> >         BIT(JH7100_RST_HIFI4_BRESET % 32),
> >         /* STATUS2 register */
> >         BIT(JH7100_RST_E24 % 32),
> >         /* STATUS3 register */
> >         0,
> > };
>
> --
> With Best Regards,
> Andy Shevchenko

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 09/16] reset: starfive-jh7100: Add StarFive JH7100 reset driver
  2021-10-22 14:56               ` Emil Renner Berthing
@ 2021-10-22 15:24                 ` Andy Shevchenko
  -1 siblings, 0 replies; 143+ messages in thread
From: Andy Shevchenko @ 2021-10-22 15:24 UTC (permalink / raw)
  To: Emil Renner Berthing
  Cc: linux-riscv, devicetree, linux-clk, open list:GPIO SUBSYSTEM,
	open list:SERIAL DRIVERS, Palmer Dabbelt, Paul Walmsley,
	Rob Herring, Michael Turquette, Stephen Boyd, Thomas Gleixner,
	Marc Zyngier, Philipp Zabel, Linus Walleij, Greg Kroah-Hartman,
	Daniel Lezcano, Andy Shevchenko, Jiri Slaby, Maximilian Luz,
	Sagar Kadam, Drew Fustini, Geert Uytterhoeven, Michael Zhu,
	Fu Wei, Anup Patel, Atish Patra, Matteo Croce,
	Linux Kernel Mailing List

On Fri, Oct 22, 2021 at 5:56 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> On Fri, 22 Oct 2021 at 16:50, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > On Fri, Oct 22, 2021 at 5:25 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> > > On Fri, 22 Oct 2021 at 15:39, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > > > On Fri, Oct 22, 2021 at 4:35 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> > > > > On Fri, 22 Oct 2021 at 14:56, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > > > > > On Thu, Oct 21, 2021 at 8:43 PM Emil Renner Berthing <kernel@esmil.dk> wrote:

...

> > > > > > Why all these ugly % 32 against constants?
> > > > >
> > > > > Because the JH7100_RST_ values goes higher than 31. There is a
> > > > > BIT_MASK macro, but that does % BITS_PER_LONG and this is a 64bit
> > > > > machine.
> > > >
> > > > And? It's exactly what you have to use!
> > >
> > > So you want me to use an unsigned long array or DECLARE_BITMAP and
> > > juggle two different index and bit offsets?
> >
> > What are the offsets of those status registers?
> > AFAICS they are sequential 4 32-bit registers.
>
> That's right, but we're on a 64bit machine, so DECLARE_BITMAP will
> give us an unsigned long array that doesn't match that.

I didn't get it, sorry.
You will have a bitmap array which you will split to 32-bit values.
What you will probably need is to move  xgpio_get_value32() and void
xgpio_set_value32() to the one of bitmap related headers (look for
bitmap_get_value8() and friends).

> > So bitmap is exactly what is suitable here, you are right!
> > See gpio-xilinx and gpio-pca953x on how to use bitmaps in the GPIO drivers.
>
> None of them has a pre-initialized const DECLARE_BITMAP, so they don't
> have to deal with the 4 vs. 2 commas problem.

I believe it's well possible to refactor this to look much better with
bitmaps (as it represents the hardware very well).

> > > Also is there a macro for handling that we'd then need 4 commas on
> > > 32bit COMPILE_TEST and 2 commas on 64bit?
> > > If you have some other way in mind you'll have to be a lot more explicit again.
> > >
> > > The point of the jh7100_reset_asserted array is that it exactly
> > > mirrors the values of the status registers when the lines are
> > > asserted. Maybe writing it like this would be more explicit:
> > >
> > > static const u32 jh7100_reset_asserted[4] = {
> > >         /* STATUS0 register */
> > >         BIT(JH7100_RST_U74 % 32) |
> > >         BIT(JH7100_RST_VP6_DRESET % 32) |
> > >         BIT(JH7100_RST_VP6_BRESET % 32),
> > >         /* STATUS1 register */
> > >         BIT(JH7100_RST_HIFI4_DRESET % 32) |
> > >         BIT(JH7100_RST_HIFI4_BRESET % 32),
> > >         /* STATUS2 register */
> > >         BIT(JH7100_RST_E24 % 32),
> > >         /* STATUS3 register */
> > >         0,
> > > };

-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 09/16] reset: starfive-jh7100: Add StarFive JH7100 reset driver
@ 2021-10-22 15:24                 ` Andy Shevchenko
  0 siblings, 0 replies; 143+ messages in thread
From: Andy Shevchenko @ 2021-10-22 15:24 UTC (permalink / raw)
  To: Emil Renner Berthing
  Cc: linux-riscv, devicetree, linux-clk, open list:GPIO SUBSYSTEM,
	open list:SERIAL DRIVERS, Palmer Dabbelt, Paul Walmsley,
	Rob Herring, Michael Turquette, Stephen Boyd, Thomas Gleixner,
	Marc Zyngier, Philipp Zabel, Linus Walleij, Greg Kroah-Hartman,
	Daniel Lezcano, Andy Shevchenko, Jiri Slaby, Maximilian Luz,
	Sagar Kadam, Drew Fustini, Geert Uytterhoeven, Michael Zhu,
	Fu Wei, Anup Patel, Atish Patra, Matteo Croce,
	Linux Kernel Mailing List

On Fri, Oct 22, 2021 at 5:56 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> On Fri, 22 Oct 2021 at 16:50, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > On Fri, Oct 22, 2021 at 5:25 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> > > On Fri, 22 Oct 2021 at 15:39, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > > > On Fri, Oct 22, 2021 at 4:35 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> > > > > On Fri, 22 Oct 2021 at 14:56, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > > > > > On Thu, Oct 21, 2021 at 8:43 PM Emil Renner Berthing <kernel@esmil.dk> wrote:

...

> > > > > > Why all these ugly % 32 against constants?
> > > > >
> > > > > Because the JH7100_RST_ values goes higher than 31. There is a
> > > > > BIT_MASK macro, but that does % BITS_PER_LONG and this is a 64bit
> > > > > machine.
> > > >
> > > > And? It's exactly what you have to use!
> > >
> > > So you want me to use an unsigned long array or DECLARE_BITMAP and
> > > juggle two different index and bit offsets?
> >
> > What are the offsets of those status registers?
> > AFAICS they are sequential 4 32-bit registers.
>
> That's right, but we're on a 64bit machine, so DECLARE_BITMAP will
> give us an unsigned long array that doesn't match that.

I didn't get it, sorry.
You will have a bitmap array which you will split to 32-bit values.
What you will probably need is to move  xgpio_get_value32() and void
xgpio_set_value32() to the one of bitmap related headers (look for
bitmap_get_value8() and friends).

> > So bitmap is exactly what is suitable here, you are right!
> > See gpio-xilinx and gpio-pca953x on how to use bitmaps in the GPIO drivers.
>
> None of them has a pre-initialized const DECLARE_BITMAP, so they don't
> have to deal with the 4 vs. 2 commas problem.

I believe it's well possible to refactor this to look much better with
bitmaps (as it represents the hardware very well).

> > > Also is there a macro for handling that we'd then need 4 commas on
> > > 32bit COMPILE_TEST and 2 commas on 64bit?
> > > If you have some other way in mind you'll have to be a lot more explicit again.
> > >
> > > The point of the jh7100_reset_asserted array is that it exactly
> > > mirrors the values of the status registers when the lines are
> > > asserted. Maybe writing it like this would be more explicit:
> > >
> > > static const u32 jh7100_reset_asserted[4] = {
> > >         /* STATUS0 register */
> > >         BIT(JH7100_RST_U74 % 32) |
> > >         BIT(JH7100_RST_VP6_DRESET % 32) |
> > >         BIT(JH7100_RST_VP6_BRESET % 32),
> > >         /* STATUS1 register */
> > >         BIT(JH7100_RST_HIFI4_DRESET % 32) |
> > >         BIT(JH7100_RST_HIFI4_BRESET % 32),
> > >         /* STATUS2 register */
> > >         BIT(JH7100_RST_E24 % 32),
> > >         /* STATUS3 register */
> > >         0,
> > > };

-- 
With Best Regards,
Andy Shevchenko

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 09/16] reset: starfive-jh7100: Add StarFive JH7100 reset driver
  2021-10-22 15:24                 ` Andy Shevchenko
@ 2021-10-22 15:36                   ` Emil Renner Berthing
  -1 siblings, 0 replies; 143+ messages in thread
From: Emil Renner Berthing @ 2021-10-22 15:36 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: linux-riscv, devicetree, linux-clk, open list:GPIO SUBSYSTEM,
	open list:SERIAL DRIVERS, Palmer Dabbelt, Paul Walmsley,
	Rob Herring, Michael Turquette, Stephen Boyd, Thomas Gleixner,
	Marc Zyngier, Philipp Zabel, Linus Walleij, Greg Kroah-Hartman,
	Daniel Lezcano, Andy Shevchenko, Jiri Slaby, Maximilian Luz,
	Sagar Kadam, Drew Fustini, Geert Uytterhoeven, Michael Zhu,
	Fu Wei, Anup Patel, Atish Patra, Matteo Croce,
	Linux Kernel Mailing List

On Fri, 22 Oct 2021 at 17:25, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> On Fri, Oct 22, 2021 at 5:56 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> > On Fri, 22 Oct 2021 at 16:50, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > > On Fri, Oct 22, 2021 at 5:25 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> > > > On Fri, 22 Oct 2021 at 15:39, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > > > > On Fri, Oct 22, 2021 at 4:35 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> > > > > > On Fri, 22 Oct 2021 at 14:56, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > > > > > > On Thu, Oct 21, 2021 at 8:43 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
>
> ...
>
> > > > > > > Why all these ugly % 32 against constants?
> > > > > >
> > > > > > Because the JH7100_RST_ values goes higher than 31. There is a
> > > > > > BIT_MASK macro, but that does % BITS_PER_LONG and this is a 64bit
> > > > > > machine.
> > > > >
> > > > > And? It's exactly what you have to use!
> > > >
> > > > So you want me to use an unsigned long array or DECLARE_BITMAP and
> > > > juggle two different index and bit offsets?
> > >
> > > What are the offsets of those status registers?
> > > AFAICS they are sequential 4 32-bit registers.
> >
> > That's right, but we're on a 64bit machine, so DECLARE_BITMAP will
> > give us an unsigned long array that doesn't match that.
>
> I didn't get it, sorry.
> You will have a bitmap array which you will split to 32-bit values.
> What you will probably need is to move  xgpio_get_value32() and void
> xgpio_set_value32() to the one of bitmap related headers (look for
> bitmap_get_value8() and friends).
>
> > > So bitmap is exactly what is suitable here, you are right!
> > > See gpio-xilinx and gpio-pca953x on how to use bitmaps in the GPIO drivers.
> >
> > None of them has a pre-initialized const DECLARE_BITMAP, so they don't
> > have to deal with the 4 vs. 2 commas problem.
>
> I believe it's well possible to refactor this to look much better with
> bitmaps (as it represents the hardware very well).

Right, but how exactly? This works on on 64bit, but not with 32bit COMPILE_TEST:

static const DECLARE_BITMAP(jh7100_reset_asserted, JH7100_RSTN_END) = {
        /* STATUS0 register */
        BIT_MASK(JH7100_RST_U74) |
        BIT_MASK(JH7100_RST_VP6_DRESET) |
        BIT_MASK(JH7100_RST_VP6_BRESET) |
        /* STATUS1 register */
        BIT_MASK(JH7100_RST_HIFI4_DRESET) |
        BIT_MASK(JH7100_RST_HIFI4_BRESET),
        /* STATUS2 register */
        BIT_MASK(JH7100_RST_E24) |
        /* STATUS3 register */
        0,
};


> > > > Also is there a macro for handling that we'd then need 4 commas on
> > > > 32bit COMPILE_TEST and 2 commas on 64bit?
> > > > If you have some other way in mind you'll have to be a lot more explicit again.
> > > >
> > > > The point of the jh7100_reset_asserted array is that it exactly
> > > > mirrors the values of the status registers when the lines are
> > > > asserted. Maybe writing it like this would be more explicit:
> > > >
> > > > static const u32 jh7100_reset_asserted[4] = {
> > > >         /* STATUS0 register */
> > > >         BIT(JH7100_RST_U74 % 32) |
> > > >         BIT(JH7100_RST_VP6_DRESET % 32) |
> > > >         BIT(JH7100_RST_VP6_BRESET % 32),
> > > >         /* STATUS1 register */
> > > >         BIT(JH7100_RST_HIFI4_DRESET % 32) |
> > > >         BIT(JH7100_RST_HIFI4_BRESET % 32),
> > > >         /* STATUS2 register */
> > > >         BIT(JH7100_RST_E24 % 32),
> > > >         /* STATUS3 register */
> > > >         0,
> > > > };
>
> --
> With Best Regards,
> Andy Shevchenko

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 09/16] reset: starfive-jh7100: Add StarFive JH7100 reset driver
@ 2021-10-22 15:36                   ` Emil Renner Berthing
  0 siblings, 0 replies; 143+ messages in thread
From: Emil Renner Berthing @ 2021-10-22 15:36 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: linux-riscv, devicetree, linux-clk, open list:GPIO SUBSYSTEM,
	open list:SERIAL DRIVERS, Palmer Dabbelt, Paul Walmsley,
	Rob Herring, Michael Turquette, Stephen Boyd, Thomas Gleixner,
	Marc Zyngier, Philipp Zabel, Linus Walleij, Greg Kroah-Hartman,
	Daniel Lezcano, Andy Shevchenko, Jiri Slaby, Maximilian Luz,
	Sagar Kadam, Drew Fustini, Geert Uytterhoeven, Michael Zhu,
	Fu Wei, Anup Patel, Atish Patra, Matteo Croce,
	Linux Kernel Mailing List

On Fri, 22 Oct 2021 at 17:25, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> On Fri, Oct 22, 2021 at 5:56 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> > On Fri, 22 Oct 2021 at 16:50, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > > On Fri, Oct 22, 2021 at 5:25 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> > > > On Fri, 22 Oct 2021 at 15:39, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > > > > On Fri, Oct 22, 2021 at 4:35 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> > > > > > On Fri, 22 Oct 2021 at 14:56, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > > > > > > On Thu, Oct 21, 2021 at 8:43 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
>
> ...
>
> > > > > > > Why all these ugly % 32 against constants?
> > > > > >
> > > > > > Because the JH7100_RST_ values goes higher than 31. There is a
> > > > > > BIT_MASK macro, but that does % BITS_PER_LONG and this is a 64bit
> > > > > > machine.
> > > > >
> > > > > And? It's exactly what you have to use!
> > > >
> > > > So you want me to use an unsigned long array or DECLARE_BITMAP and
> > > > juggle two different index and bit offsets?
> > >
> > > What are the offsets of those status registers?
> > > AFAICS they are sequential 4 32-bit registers.
> >
> > That's right, but we're on a 64bit machine, so DECLARE_BITMAP will
> > give us an unsigned long array that doesn't match that.
>
> I didn't get it, sorry.
> You will have a bitmap array which you will split to 32-bit values.
> What you will probably need is to move  xgpio_get_value32() and void
> xgpio_set_value32() to the one of bitmap related headers (look for
> bitmap_get_value8() and friends).
>
> > > So bitmap is exactly what is suitable here, you are right!
> > > See gpio-xilinx and gpio-pca953x on how to use bitmaps in the GPIO drivers.
> >
> > None of them has a pre-initialized const DECLARE_BITMAP, so they don't
> > have to deal with the 4 vs. 2 commas problem.
>
> I believe it's well possible to refactor this to look much better with
> bitmaps (as it represents the hardware very well).

Right, but how exactly? This works on on 64bit, but not with 32bit COMPILE_TEST:

static const DECLARE_BITMAP(jh7100_reset_asserted, JH7100_RSTN_END) = {
        /* STATUS0 register */
        BIT_MASK(JH7100_RST_U74) |
        BIT_MASK(JH7100_RST_VP6_DRESET) |
        BIT_MASK(JH7100_RST_VP6_BRESET) |
        /* STATUS1 register */
        BIT_MASK(JH7100_RST_HIFI4_DRESET) |
        BIT_MASK(JH7100_RST_HIFI4_BRESET),
        /* STATUS2 register */
        BIT_MASK(JH7100_RST_E24) |
        /* STATUS3 register */
        0,
};


> > > > Also is there a macro for handling that we'd then need 4 commas on
> > > > 32bit COMPILE_TEST and 2 commas on 64bit?
> > > > If you have some other way in mind you'll have to be a lot more explicit again.
> > > >
> > > > The point of the jh7100_reset_asserted array is that it exactly
> > > > mirrors the values of the status registers when the lines are
> > > > asserted. Maybe writing it like this would be more explicit:
> > > >
> > > > static const u32 jh7100_reset_asserted[4] = {
> > > >         /* STATUS0 register */
> > > >         BIT(JH7100_RST_U74 % 32) |
> > > >         BIT(JH7100_RST_VP6_DRESET % 32) |
> > > >         BIT(JH7100_RST_VP6_BRESET % 32),
> > > >         /* STATUS1 register */
> > > >         BIT(JH7100_RST_HIFI4_DRESET % 32) |
> > > >         BIT(JH7100_RST_HIFI4_BRESET % 32),
> > > >         /* STATUS2 register */
> > > >         BIT(JH7100_RST_E24 % 32),
> > > >         /* STATUS3 register */
> > > >         0,
> > > > };
>
> --
> With Best Regards,
> Andy Shevchenko

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 09/16] reset: starfive-jh7100: Add StarFive JH7100 reset driver
  2021-10-22 15:36                   ` Emil Renner Berthing
@ 2021-10-22 15:54                     ` Andy Shevchenko
  -1 siblings, 0 replies; 143+ messages in thread
From: Andy Shevchenko @ 2021-10-22 15:54 UTC (permalink / raw)
  To: Emil Renner Berthing
  Cc: linux-riscv, devicetree, linux-clk, open list:GPIO SUBSYSTEM,
	open list:SERIAL DRIVERS, Palmer Dabbelt, Paul Walmsley,
	Rob Herring, Michael Turquette, Stephen Boyd, Thomas Gleixner,
	Marc Zyngier, Philipp Zabel, Linus Walleij, Greg Kroah-Hartman,
	Daniel Lezcano, Jiri Slaby, Maximilian Luz, Sagar Kadam,
	Drew Fustini, Geert Uytterhoeven, Michael Zhu, Fu Wei,
	Anup Patel, Atish Patra, Matteo Croce, Linux Kernel Mailing List

On Fri, Oct 22, 2021 at 05:36:21PM +0200, Emil Renner Berthing wrote:
> On Fri, 22 Oct 2021 at 17:25, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > On Fri, Oct 22, 2021 at 5:56 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> > > On Fri, 22 Oct 2021 at 16:50, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > > > On Fri, Oct 22, 2021 at 5:25 PM Emil Renner Berthing <kernel@esmil.dk> wrote:

...

> > > > AFAICS they are sequential 4 32-bit registers.
> > >
> > > That's right, but we're on a 64bit machine, so DECLARE_BITMAP will
> > > give us an unsigned long array that doesn't match that.
> >
> > I didn't get it, sorry.
> > You will have a bitmap array which you will split to 32-bit values.
> > What you will probably need is to move  xgpio_get_value32() and void
> > xgpio_set_value32() to the one of bitmap related headers (look for
> > bitmap_get_value8() and friends).
> >
> > > > So bitmap is exactly what is suitable here, you are right!
> > > > See gpio-xilinx and gpio-pca953x on how to use bitmaps in the GPIO drivers.
> > >
> > > None of them has a pre-initialized const DECLARE_BITMAP, so they don't
> > > have to deal with the 4 vs. 2 commas problem.
> >
> > I believe it's well possible to refactor this to look much better with
> > bitmaps (as it represents the hardware very well).
> 
> Right, but how exactly? This works on on 64bit, but not with 32bit COMPILE_TEST:
> 
> static const DECLARE_BITMAP(jh7100_reset_asserted, JH7100_RSTN_END) = {
>         /* STATUS0 register */
>         BIT_MASK(JH7100_RST_U74) |
>         BIT_MASK(JH7100_RST_VP6_DRESET) |
>         BIT_MASK(JH7100_RST_VP6_BRESET) |
>         /* STATUS1 register */
>         BIT_MASK(JH7100_RST_HIFI4_DRESET) |
>         BIT_MASK(JH7100_RST_HIFI4_BRESET),
>         /* STATUS2 register */
>         BIT_MASK(JH7100_RST_E24) |
>         /* STATUS3 register */
>         0,
> };

BITMAP_FROM_U64() ?

> > > > > Also is there a macro for handling that we'd then need 4 commas on
> > > > > 32bit COMPILE_TEST and 2 commas on 64bit?
> > > > > If you have some other way in mind you'll have to be a lot more explicit again.
> > > > >
> > > > > The point of the jh7100_reset_asserted array is that it exactly
> > > > > mirrors the values of the status registers when the lines are
> > > > > asserted.

-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 09/16] reset: starfive-jh7100: Add StarFive JH7100 reset driver
@ 2021-10-22 15:54                     ` Andy Shevchenko
  0 siblings, 0 replies; 143+ messages in thread
From: Andy Shevchenko @ 2021-10-22 15:54 UTC (permalink / raw)
  To: Emil Renner Berthing
  Cc: linux-riscv, devicetree, linux-clk, open list:GPIO SUBSYSTEM,
	open list:SERIAL DRIVERS, Palmer Dabbelt, Paul Walmsley,
	Rob Herring, Michael Turquette, Stephen Boyd, Thomas Gleixner,
	Marc Zyngier, Philipp Zabel, Linus Walleij, Greg Kroah-Hartman,
	Daniel Lezcano, Jiri Slaby, Maximilian Luz, Sagar Kadam,
	Drew Fustini, Geert Uytterhoeven, Michael Zhu, Fu Wei,
	Anup Patel, Atish Patra, Matteo Croce, Linux Kernel Mailing List

On Fri, Oct 22, 2021 at 05:36:21PM +0200, Emil Renner Berthing wrote:
> On Fri, 22 Oct 2021 at 17:25, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > On Fri, Oct 22, 2021 at 5:56 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> > > On Fri, 22 Oct 2021 at 16:50, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > > > On Fri, Oct 22, 2021 at 5:25 PM Emil Renner Berthing <kernel@esmil.dk> wrote:

...

> > > > AFAICS they are sequential 4 32-bit registers.
> > >
> > > That's right, but we're on a 64bit machine, so DECLARE_BITMAP will
> > > give us an unsigned long array that doesn't match that.
> >
> > I didn't get it, sorry.
> > You will have a bitmap array which you will split to 32-bit values.
> > What you will probably need is to move  xgpio_get_value32() and void
> > xgpio_set_value32() to the one of bitmap related headers (look for
> > bitmap_get_value8() and friends).
> >
> > > > So bitmap is exactly what is suitable here, you are right!
> > > > See gpio-xilinx and gpio-pca953x on how to use bitmaps in the GPIO drivers.
> > >
> > > None of them has a pre-initialized const DECLARE_BITMAP, so they don't
> > > have to deal with the 4 vs. 2 commas problem.
> >
> > I believe it's well possible to refactor this to look much better with
> > bitmaps (as it represents the hardware very well).
> 
> Right, but how exactly? This works on on 64bit, but not with 32bit COMPILE_TEST:
> 
> static const DECLARE_BITMAP(jh7100_reset_asserted, JH7100_RSTN_END) = {
>         /* STATUS0 register */
>         BIT_MASK(JH7100_RST_U74) |
>         BIT_MASK(JH7100_RST_VP6_DRESET) |
>         BIT_MASK(JH7100_RST_VP6_BRESET) |
>         /* STATUS1 register */
>         BIT_MASK(JH7100_RST_HIFI4_DRESET) |
>         BIT_MASK(JH7100_RST_HIFI4_BRESET),
>         /* STATUS2 register */
>         BIT_MASK(JH7100_RST_E24) |
>         /* STATUS3 register */
>         0,
> };

BITMAP_FROM_U64() ?

> > > > > Also is there a macro for handling that we'd then need 4 commas on
> > > > > 32bit COMPILE_TEST and 2 commas on 64bit?
> > > > > If you have some other way in mind you'll have to be a lot more explicit again.
> > > > >
> > > > > The point of the jh7100_reset_asserted array is that it exactly
> > > > > mirrors the values of the status registers when the lines are
> > > > > asserted.

-- 
With Best Regards,
Andy Shevchenko



_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 09/16] reset: starfive-jh7100: Add StarFive JH7100 reset driver
  2021-10-22 15:54                     ` Andy Shevchenko
@ 2021-10-22 15:59                       ` Emil Renner Berthing
  -1 siblings, 0 replies; 143+ messages in thread
From: Emil Renner Berthing @ 2021-10-22 15:59 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: linux-riscv, devicetree, linux-clk, open list:GPIO SUBSYSTEM,
	open list:SERIAL DRIVERS, Palmer Dabbelt, Paul Walmsley,
	Rob Herring, Michael Turquette, Stephen Boyd, Thomas Gleixner,
	Marc Zyngier, Philipp Zabel, Linus Walleij, Greg Kroah-Hartman,
	Daniel Lezcano, Jiri Slaby, Maximilian Luz, Sagar Kadam,
	Drew Fustini, Geert Uytterhoeven, Michael Zhu, Fu Wei,
	Anup Patel, Atish Patra, Matteo Croce, Linux Kernel Mailing List

On Fri, 22 Oct 2021 at 17:55, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> On Fri, Oct 22, 2021 at 05:36:21PM +0200, Emil Renner Berthing wrote:
> > On Fri, 22 Oct 2021 at 17:25, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > > On Fri, Oct 22, 2021 at 5:56 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> > > > On Fri, 22 Oct 2021 at 16:50, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > > > > On Fri, Oct 22, 2021 at 5:25 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
>
> ...
>
> > > > > AFAICS they are sequential 4 32-bit registers.
> > > >
> > > > That's right, but we're on a 64bit machine, so DECLARE_BITMAP will
> > > > give us an unsigned long array that doesn't match that.
> > >
> > > I didn't get it, sorry.
> > > You will have a bitmap array which you will split to 32-bit values.
> > > What you will probably need is to move  xgpio_get_value32() and void
> > > xgpio_set_value32() to the one of bitmap related headers (look for
> > > bitmap_get_value8() and friends).
> > >
> > > > > So bitmap is exactly what is suitable here, you are right!
> > > > > See gpio-xilinx and gpio-pca953x on how to use bitmaps in the GPIO drivers.
> > > >
> > > > None of them has a pre-initialized const DECLARE_BITMAP, so they don't
> > > > have to deal with the 4 vs. 2 commas problem.
> > >
> > > I believe it's well possible to refactor this to look much better with
> > > bitmaps (as it represents the hardware very well).
> >
> > Right, but how exactly? This works on on 64bit, but not with 32bit COMPILE_TEST:
> >
> > static const DECLARE_BITMAP(jh7100_reset_asserted, JH7100_RSTN_END) = {
> >         /* STATUS0 register */
> >         BIT_MASK(JH7100_RST_U74) |
> >         BIT_MASK(JH7100_RST_VP6_DRESET) |
> >         BIT_MASK(JH7100_RST_VP6_BRESET) |
> >         /* STATUS1 register */
> >         BIT_MASK(JH7100_RST_HIFI4_DRESET) |
> >         BIT_MASK(JH7100_RST_HIFI4_BRESET),
> >         /* STATUS2 register */
> >         BIT_MASK(JH7100_RST_E24) |
> >         /* STATUS3 register */
> >         0,
> > };
>
> BITMAP_FROM_U64() ?

So you think this is better?

static const DECLARE_BITMAP(jh7100_reset_asserted, JH7100_RSTN_END) = {
        BITMAP_FROM_U64(
                /* STATUS0 register */
                BIT_MASK(JH7100_RST_U74) |
                BIT_MASK(JH7100_RST_VP6_DRESET) |
                BIT_MASK(JH7100_RST_VP6_BRESET) |
                /* STATUS1 register */
                BIT_MASK(JH7100_RST_HIFI4_DRESET) |
                BIT_MASK(JH7100_RST_HIFI4_BRESET)
        ),
        BITMAP_FROM_U64(
                /* STATUS2 register */
                BIT_MASK(JH7100_RST_E24) |
                /* STATUS3 register */
                0
        ),
};

> > > > > > Also is there a macro for handling that we'd then need 4 commas on
> > > > > > 32bit COMPILE_TEST and 2 commas on 64bit?
> > > > > > If you have some other way in mind you'll have to be a lot more explicit again.
> > > > > >
> > > > > > The point of the jh7100_reset_asserted array is that it exactly
> > > > > > mirrors the values of the status registers when the lines are
> > > > > > asserted.
>
> --
> With Best Regards,
> Andy Shevchenko
>
>
>
> _______________________________________________
> linux-riscv mailing list
> linux-riscv@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 09/16] reset: starfive-jh7100: Add StarFive JH7100 reset driver
@ 2021-10-22 15:59                       ` Emil Renner Berthing
  0 siblings, 0 replies; 143+ messages in thread
From: Emil Renner Berthing @ 2021-10-22 15:59 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: linux-riscv, devicetree, linux-clk, open list:GPIO SUBSYSTEM,
	open list:SERIAL DRIVERS, Palmer Dabbelt, Paul Walmsley,
	Rob Herring, Michael Turquette, Stephen Boyd, Thomas Gleixner,
	Marc Zyngier, Philipp Zabel, Linus Walleij, Greg Kroah-Hartman,
	Daniel Lezcano, Jiri Slaby, Maximilian Luz, Sagar Kadam,
	Drew Fustini, Geert Uytterhoeven, Michael Zhu, Fu Wei,
	Anup Patel, Atish Patra, Matteo Croce, Linux Kernel Mailing List

On Fri, 22 Oct 2021 at 17:55, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> On Fri, Oct 22, 2021 at 05:36:21PM +0200, Emil Renner Berthing wrote:
> > On Fri, 22 Oct 2021 at 17:25, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > > On Fri, Oct 22, 2021 at 5:56 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> > > > On Fri, 22 Oct 2021 at 16:50, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > > > > On Fri, Oct 22, 2021 at 5:25 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
>
> ...
>
> > > > > AFAICS they are sequential 4 32-bit registers.
> > > >
> > > > That's right, but we're on a 64bit machine, so DECLARE_BITMAP will
> > > > give us an unsigned long array that doesn't match that.
> > >
> > > I didn't get it, sorry.
> > > You will have a bitmap array which you will split to 32-bit values.
> > > What you will probably need is to move  xgpio_get_value32() and void
> > > xgpio_set_value32() to the one of bitmap related headers (look for
> > > bitmap_get_value8() and friends).
> > >
> > > > > So bitmap is exactly what is suitable here, you are right!
> > > > > See gpio-xilinx and gpio-pca953x on how to use bitmaps in the GPIO drivers.
> > > >
> > > > None of them has a pre-initialized const DECLARE_BITMAP, so they don't
> > > > have to deal with the 4 vs. 2 commas problem.
> > >
> > > I believe it's well possible to refactor this to look much better with
> > > bitmaps (as it represents the hardware very well).
> >
> > Right, but how exactly? This works on on 64bit, but not with 32bit COMPILE_TEST:
> >
> > static const DECLARE_BITMAP(jh7100_reset_asserted, JH7100_RSTN_END) = {
> >         /* STATUS0 register */
> >         BIT_MASK(JH7100_RST_U74) |
> >         BIT_MASK(JH7100_RST_VP6_DRESET) |
> >         BIT_MASK(JH7100_RST_VP6_BRESET) |
> >         /* STATUS1 register */
> >         BIT_MASK(JH7100_RST_HIFI4_DRESET) |
> >         BIT_MASK(JH7100_RST_HIFI4_BRESET),
> >         /* STATUS2 register */
> >         BIT_MASK(JH7100_RST_E24) |
> >         /* STATUS3 register */
> >         0,
> > };
>
> BITMAP_FROM_U64() ?

So you think this is better?

static const DECLARE_BITMAP(jh7100_reset_asserted, JH7100_RSTN_END) = {
        BITMAP_FROM_U64(
                /* STATUS0 register */
                BIT_MASK(JH7100_RST_U74) |
                BIT_MASK(JH7100_RST_VP6_DRESET) |
                BIT_MASK(JH7100_RST_VP6_BRESET) |
                /* STATUS1 register */
                BIT_MASK(JH7100_RST_HIFI4_DRESET) |
                BIT_MASK(JH7100_RST_HIFI4_BRESET)
        ),
        BITMAP_FROM_U64(
                /* STATUS2 register */
                BIT_MASK(JH7100_RST_E24) |
                /* STATUS3 register */
                0
        ),
};

> > > > > > Also is there a macro for handling that we'd then need 4 commas on
> > > > > > 32bit COMPILE_TEST and 2 commas on 64bit?
> > > > > > If you have some other way in mind you'll have to be a lot more explicit again.
> > > > > >
> > > > > > The point of the jh7100_reset_asserted array is that it exactly
> > > > > > mirrors the values of the status registers when the lines are
> > > > > > asserted.
>
> --
> With Best Regards,
> Andy Shevchenko
>
>
>
> _______________________________________________
> linux-riscv mailing list
> linux-riscv@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-riscv

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 12/16] pinctrl: starfive: Add pinctrl driver for StarFive SoCs
  2021-10-22 13:31     ` Andy Shevchenko
@ 2021-10-23 18:45       ` Emil Renner Berthing
  -1 siblings, 0 replies; 143+ messages in thread
From: Emil Renner Berthing @ 2021-10-23 18:45 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: linux-riscv, devicetree, linux-clk, open list:GPIO SUBSYSTEM,
	open list:SERIAL DRIVERS, Palmer Dabbelt, Paul Walmsley,
	Rob Herring, Michael Turquette, Stephen Boyd, Thomas Gleixner,
	Marc Zyngier, Philipp Zabel, Linus Walleij, Greg Kroah-Hartman,
	Daniel Lezcano, Andy Shevchenko, Jiri Slaby, Maximilian Luz,
	Sagar Kadam, Drew Fustini, Geert Uytterhoeven, Michael Zhu,
	Fu Wei, Anup Patel, Atish Patra, Matteo Croce,
	Linux Kernel Mailing List, Huan Feng

On Fri, 22 Oct 2021 at 15:32, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> On Thu, Oct 21, 2021 at 8:44 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> > +       for_each_child_of_node(np, child) {
> > +               int npins;
> > +               int i;
> > +
> > +               ret = -ENOMEM;
> > +               grpname = devm_kasprintf(dev, GFP_KERNEL, "%s.%s", np->name, child->name);
> > +               if (!grpname)
> > +                       goto put_child;
> > +
> > +               pgnames[ngroups++] = grpname;
> > +
> > +               if ((npins = of_property_count_u32_elems(child, "pinmux")) > 0) {
> > +                       pins = devm_kcalloc(dev, npins, sizeof(*pins), GFP_KERNEL);
> > +                       if (!pins)
> > +                               goto free_grpname;
> > +
> > +                       pinmux = devm_kcalloc(dev, npins, sizeof(*pinmux), GFP_KERNEL);
> > +                       if (!pinmux)
> > +                               goto free_pins;
> > +
> > +                       for (i = 0; i < npins; i++) {
> > +                               u32 v;
> > +
> > +                               ret = of_property_read_u32_index(child, "pinmux", i, &v);
> > +                               if (ret)
> > +                                       goto free_pinmux;
> > +                               pins[i] = starfive_gpio_to_pin(sfp, starfive_pinmux_to_gpio(v));
> > +                               pinmux[i] = v;
> > +                       }
>
> Why you can't use of_property_read_u32_array() APIs?

I can here, but..

> > +                       map[nmaps].type = PIN_MAP_TYPE_MUX_GROUP;
> > +                       map[nmaps].data.mux.function = np->name;
> > +                       map[nmaps].data.mux.group = grpname;
> > +                       nmaps += 1;
> > +               } else if ((npins = of_property_count_u32_elems(child, "pins")) > 0) {
> > +                       pins = devm_kcalloc(dev, npins, sizeof(*pins), GFP_KERNEL);
> > +                       if (!pins)
> > +                               goto free_grpname;
> > +
> > +                       pinmux = NULL;
> > +
> > +                       for (i = 0; i < npins; i++) {
> > +                               u32 v;
> > +
> > +                               ret = of_property_read_u32_index(child, "pins", i, &v);
> > +                               if (ret)
> > +                                       goto free_pins;
> > +                               pins[i] = v;
> > +                       }
>
> NIH _array() APIs.

.. here the pins array is an int array and not u32 array. I can cast
it and and hope Linux will never run on a machine where sizeof(int) !=
4 if you think that's better?

> > +               } else {
> > +                       ret = -EINVAL;
> > +                       goto free_grpname;
> > +               }
> > +
> > +               ret = pinctrl_generic_add_group(pctldev, grpname, pins, npins, pinmux);
> > +               if (ret < 0) {
> > +                       dev_err(dev, "error adding group %pOFn.%pOFn: %d\n",
> > +                               np, child, ret);
> > +                       goto free_pinmux;
> > +               }
> > +
> > +               ret = pinconf_generic_parse_dt_config(child, pctldev,
> > +                                                     &map[nmaps].data.configs.configs,
> > +                                                     &map[nmaps].data.configs.num_configs);
> > +               if (ret) {
> > +                       dev_err(dev, "invalid pinctrl group %pOFn.%pOFn: %s\n",
> > +                               np, child, "error parsing pin config");
> > +                       goto put_child;
> > +               }
> > +
> > +               /* don't create a map if there are no pinconf settings */
> > +               if (map[nmaps].data.configs.num_configs == 0)
> > +                       continue;
> > +
> > +               map[nmaps].type = PIN_MAP_TYPE_CONFIGS_GROUP;
> > +               map[nmaps].data.configs.group_or_pin = grpname;
> > +               nmaps += 1;
> > +       }
>
> ...
>
> > +free_pinmux:
> > +       devm_kfree(dev, pinmux);
> > +free_pins:
> > +       devm_kfree(dev, pins);
> > +free_grpname:
> > +       devm_kfree(dev, grpname);
>
> > +free_pgnames:
> > +       devm_kfree(dev, pgnames);
>
> Just no, please get rid of them either way as I explained in previous reviews.

So I asked you if you thought it was better to leave these unused
allocations when parsing the device tree node fails but you never
answered that. I didn't want put words in your mouth so I could only
assume you didn't. I'd really like a straight answer to that so I have
something to refer to when people ask why this driver doesn't do the
same as fx. the pinctrl-single. So just to be clear: do you think it's
better to leave this unused garbage allocated if parsing the device
tree node fails?

> > +               raw_spin_lock_irqsave(&sfp->lock, flags);
> > +               writel_relaxed(dout, reg_dout);
> > +               writel_relaxed(doen, reg_doen);
> > +               if (reg_din)
> > +                       writel_relaxed(gpio + 2, reg_din);
>
> Why 0 can't be written?

Because signal 0 is a special "always 0" signal and signal 1 is a
special "always 1" signal, and after that signal n is the input value
of GPIO n - 2. We don't want to overwrite the PoR defaults.

> > +       mask = 0;
> > +       value = 0;
> > +       for (i = 0; i < num_configs; i++) {
> > +               int param = pinconf_to_config_param(configs[i]);
> > +               u32 arg = pinconf_to_config_argument(configs[i]);
> >
> +
> > +               switch (param) {
> > +               case PIN_CONFIG_BIAS_DISABLE:
> > +                       mask |= PAD_BIAS_MASK;
> > +                       value = (value & ~PAD_BIAS_MASK) | PAD_BIAS_DISABLE;
>
> Okay, I have got why you are masking on each iteration, but here is
> the question, shouldn't you apply the cnages belonged to each of the
> group of options as it's requested by the user? Here you basically
> ignore all previous changes to bias.
>
> I would expect that you have something like
>
> for () {
>   switch (type) {
>   case BIAS*:
>     return apply_bias();
>   ...other types...
>   default:
>     return err;
>   }
> }

I such cases where you get conflicting PIN_CONFIG_BIAS_* settings I
don't see why it's better to do the rmw on the padctl register for the
first bias setting only to then change the bits again a few
microseconds later when the loop encounters the second bias setting.
After the loop is done the end result would still be just the last
bias setting.

> > +                       break;
> > +               case PIN_CONFIG_BIAS_PULL_DOWN:
> > +                       if (arg == 0)
> > +                               return -ENOTSUPP;
> > +                       mask |= PAD_BIAS_MASK;
> > +                       value = (value & ~PAD_BIAS_MASK) | PAD_BIAS_PULL_DOWN;
> > +                       break;
> > +               case PIN_CONFIG_BIAS_PULL_UP:
> > +                       if (arg == 0)
> > +                               return -ENOTSUPP;
> > +                       mask |= PAD_BIAS_MASK;
> > +                       value = value & ~PAD_BIAS_MASK;
> > +                       break;
> > +               case PIN_CONFIG_DRIVE_STRENGTH:
> > +                       mask |= PAD_DRIVE_STRENGTH_MASK;
> > +                       value = (value & ~PAD_DRIVE_STRENGTH_MASK) |
> > +                               starfive_drive_strength_from_max_mA(arg);
> > +                       break;
> > +               case PIN_CONFIG_INPUT_ENABLE:
> > +                       mask |= PAD_INPUT_ENABLE;
> > +                       if (arg)
> > +                               value |= PAD_INPUT_ENABLE;
> > +                       else
> > +                               value &= ~PAD_INPUT_ENABLE;
> > +                       break;
> > +               case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
> > +                       mask |= PAD_INPUT_SCHMITT_ENABLE;
> > +                       if (arg)
> > +                               value |= PAD_INPUT_SCHMITT_ENABLE;
> > +                       else
> > +                               value &= ~PAD_INPUT_SCHMITT_ENABLE;
> > +                       break;
> > +               case PIN_CONFIG_SLEW_RATE:
> > +                       mask |= PAD_SLEW_RATE_MASK;
> > +                       value = (value & ~PAD_SLEW_RATE_MASK) |
> > +                               ((arg << PAD_SLEW_RATE_POS) & PAD_SLEW_RATE_MASK);
> > +                       break;
> > +               case PIN_CONFIG_STARFIVE_STRONG_PULL_UP:
> > +                       if (arg) {
> > +                               mask |= PAD_BIAS_MASK;
> > +                               value = (value & ~PAD_BIAS_MASK) |
> > +                                       PAD_BIAS_STRONG_PULL_UP;
> > +                       } else {
> > +                               mask |= PAD_BIAS_STRONG_PULL_UP;
> > +                               value = value & ~PAD_BIAS_STRONG_PULL_UP;
> > +                       }
> > +                       break;
> > +               default:
> > +                       return -ENOTSUPP;
> > +               }
> > +       }
>
> ...
>
> > +static int starfive_gpio_request(struct gpio_chip *gc, unsigned int gpio)
> > +{
> > +       return pinctrl_gpio_request(gc->base + gpio);
> > +}
> > +
> > +static void starfive_gpio_free(struct gpio_chip *gc, unsigned int gpio)
> > +{
> > +       pinctrl_gpio_free(gc->base + gpio);
> > +}
>
> Point of having these function is...?

These calls tells the pinctrl system that a certain pin is now used
for GPIO. Conversely it'll also prevent fx. userspace from doing GPIO
on a pin that's already used by I2C, a UART or some other peripheral.

> > +       /* enable input and schmitt trigger */
>
> Use capitalization consistently.

I am?

> > +       case IRQ_TYPE_EDGE_RISING:
> > +               irq_type  = mask; /* 1: edge triggered */
> > +               edge_both = 0;    /* 0: single edge */
> > +               polarity  = mask; /* 1: rising edge */
> > +               handler   = handle_edge_irq;
> > +               break;
> > +       case IRQ_TYPE_EDGE_FALLING:
> > +               irq_type  = mask; /* 1: edge triggered */
> > +               edge_both = 0;    /* 0: single edge */
> > +               polarity  = 0;    /* 0: falling edge */
> > +               handler   = handle_edge_irq
> > +               break;
> > +       case IRQ_TYPE_EDGE_BOTH:
> > +               irq_type  = mask; /* 1: edge triggered */
> > +               edge_both = mask; /* 1: both edges */
> > +               polarity  = 0;    /* 0: ignored */
> > +               handler   = handle_edge_irq;
>
> Dup. You may do it once without any temporary variable.
> I haven't got why you haven't addressed this.

So you want two switches on the trigger variable, one for irq_type,
edge_both and polarity, and one for the handler? If this is not what
you have in mind please be a lot more explicit. Trying to guess what
you mean gets really old.

> > +               break;
> > +       case IRQ_TYPE_LEVEL_HIGH:
> > +               irq_type  = 0;    /* 0: level triggered */
> > +               edge_both = 0;    /* 0: ignored */
> > +               polarity  = mask; /* 1: high level */
> > +               handler   = handle_level_irq;
> > +               break;
> > +       case IRQ_TYPE_LEVEL_LOW:
> > +               irq_type  = 0;    /* 0: level triggered */
> > +               edge_both = 0;    /* 0: ignored */
> > +               polarity  = 0;    /* 0: low level */
> > +               handler   = handle_level_irq;
>
> Ditto.
>
> > +               break;
>
> ...
>
> > +       clk = devm_clk_get(dev, NULL);
> > +       if (IS_ERR(clk)) {
>
> > +               ret = PTR_ERR(clk);
>
> Inline into below.
>
> > +               return dev_err_probe(dev, ret, "could not get clock: %d\n", ret);
> > +       }
>
> Ditto for all other similar cases.

So you would rather want this?
  return dev_err_probe(dev, PTR_ERR(clk), "could not get clock: %d\n",
PTR_ERR(clk));
or just not tell why getting the clock failed?

> > +       if (!device_property_read_u32(dev, "starfive,signal-group", &value)) {
>
> Since you are using of_property_* elsewhere, makes sense to use same
> here, or otherwise, use device_*() APIs there.

Wait, so now you want of_property_read_u32(dev->of_node, ...) here
again, is that right?

/Emil

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 12/16] pinctrl: starfive: Add pinctrl driver for StarFive SoCs
@ 2021-10-23 18:45       ` Emil Renner Berthing
  0 siblings, 0 replies; 143+ messages in thread
From: Emil Renner Berthing @ 2021-10-23 18:45 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: linux-riscv, devicetree, linux-clk, open list:GPIO SUBSYSTEM,
	open list:SERIAL DRIVERS, Palmer Dabbelt, Paul Walmsley,
	Rob Herring, Michael Turquette, Stephen Boyd, Thomas Gleixner,
	Marc Zyngier, Philipp Zabel, Linus Walleij, Greg Kroah-Hartman,
	Daniel Lezcano, Andy Shevchenko, Jiri Slaby, Maximilian Luz,
	Sagar Kadam, Drew Fustini, Geert Uytterhoeven, Michael Zhu,
	Fu Wei, Anup Patel, Atish Patra, Matteo Croce,
	Linux Kernel Mailing List, Huan Feng

On Fri, 22 Oct 2021 at 15:32, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> On Thu, Oct 21, 2021 at 8:44 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> > +       for_each_child_of_node(np, child) {
> > +               int npins;
> > +               int i;
> > +
> > +               ret = -ENOMEM;
> > +               grpname = devm_kasprintf(dev, GFP_KERNEL, "%s.%s", np->name, child->name);
> > +               if (!grpname)
> > +                       goto put_child;
> > +
> > +               pgnames[ngroups++] = grpname;
> > +
> > +               if ((npins = of_property_count_u32_elems(child, "pinmux")) > 0) {
> > +                       pins = devm_kcalloc(dev, npins, sizeof(*pins), GFP_KERNEL);
> > +                       if (!pins)
> > +                               goto free_grpname;
> > +
> > +                       pinmux = devm_kcalloc(dev, npins, sizeof(*pinmux), GFP_KERNEL);
> > +                       if (!pinmux)
> > +                               goto free_pins;
> > +
> > +                       for (i = 0; i < npins; i++) {
> > +                               u32 v;
> > +
> > +                               ret = of_property_read_u32_index(child, "pinmux", i, &v);
> > +                               if (ret)
> > +                                       goto free_pinmux;
> > +                               pins[i] = starfive_gpio_to_pin(sfp, starfive_pinmux_to_gpio(v));
> > +                               pinmux[i] = v;
> > +                       }
>
> Why you can't use of_property_read_u32_array() APIs?

I can here, but..

> > +                       map[nmaps].type = PIN_MAP_TYPE_MUX_GROUP;
> > +                       map[nmaps].data.mux.function = np->name;
> > +                       map[nmaps].data.mux.group = grpname;
> > +                       nmaps += 1;
> > +               } else if ((npins = of_property_count_u32_elems(child, "pins")) > 0) {
> > +                       pins = devm_kcalloc(dev, npins, sizeof(*pins), GFP_KERNEL);
> > +                       if (!pins)
> > +                               goto free_grpname;
> > +
> > +                       pinmux = NULL;
> > +
> > +                       for (i = 0; i < npins; i++) {
> > +                               u32 v;
> > +
> > +                               ret = of_property_read_u32_index(child, "pins", i, &v);
> > +                               if (ret)
> > +                                       goto free_pins;
> > +                               pins[i] = v;
> > +                       }
>
> NIH _array() APIs.

.. here the pins array is an int array and not u32 array. I can cast
it and and hope Linux will never run on a machine where sizeof(int) !=
4 if you think that's better?

> > +               } else {
> > +                       ret = -EINVAL;
> > +                       goto free_grpname;
> > +               }
> > +
> > +               ret = pinctrl_generic_add_group(pctldev, grpname, pins, npins, pinmux);
> > +               if (ret < 0) {
> > +                       dev_err(dev, "error adding group %pOFn.%pOFn: %d\n",
> > +                               np, child, ret);
> > +                       goto free_pinmux;
> > +               }
> > +
> > +               ret = pinconf_generic_parse_dt_config(child, pctldev,
> > +                                                     &map[nmaps].data.configs.configs,
> > +                                                     &map[nmaps].data.configs.num_configs);
> > +               if (ret) {
> > +                       dev_err(dev, "invalid pinctrl group %pOFn.%pOFn: %s\n",
> > +                               np, child, "error parsing pin config");
> > +                       goto put_child;
> > +               }
> > +
> > +               /* don't create a map if there are no pinconf settings */
> > +               if (map[nmaps].data.configs.num_configs == 0)
> > +                       continue;
> > +
> > +               map[nmaps].type = PIN_MAP_TYPE_CONFIGS_GROUP;
> > +               map[nmaps].data.configs.group_or_pin = grpname;
> > +               nmaps += 1;
> > +       }
>
> ...
>
> > +free_pinmux:
> > +       devm_kfree(dev, pinmux);
> > +free_pins:
> > +       devm_kfree(dev, pins);
> > +free_grpname:
> > +       devm_kfree(dev, grpname);
>
> > +free_pgnames:
> > +       devm_kfree(dev, pgnames);
>
> Just no, please get rid of them either way as I explained in previous reviews.

So I asked you if you thought it was better to leave these unused
allocations when parsing the device tree node fails but you never
answered that. I didn't want put words in your mouth so I could only
assume you didn't. I'd really like a straight answer to that so I have
something to refer to when people ask why this driver doesn't do the
same as fx. the pinctrl-single. So just to be clear: do you think it's
better to leave this unused garbage allocated if parsing the device
tree node fails?

> > +               raw_spin_lock_irqsave(&sfp->lock, flags);
> > +               writel_relaxed(dout, reg_dout);
> > +               writel_relaxed(doen, reg_doen);
> > +               if (reg_din)
> > +                       writel_relaxed(gpio + 2, reg_din);
>
> Why 0 can't be written?

Because signal 0 is a special "always 0" signal and signal 1 is a
special "always 1" signal, and after that signal n is the input value
of GPIO n - 2. We don't want to overwrite the PoR defaults.

> > +       mask = 0;
> > +       value = 0;
> > +       for (i = 0; i < num_configs; i++) {
> > +               int param = pinconf_to_config_param(configs[i]);
> > +               u32 arg = pinconf_to_config_argument(configs[i]);
> >
> +
> > +               switch (param) {
> > +               case PIN_CONFIG_BIAS_DISABLE:
> > +                       mask |= PAD_BIAS_MASK;
> > +                       value = (value & ~PAD_BIAS_MASK) | PAD_BIAS_DISABLE;
>
> Okay, I have got why you are masking on each iteration, but here is
> the question, shouldn't you apply the cnages belonged to each of the
> group of options as it's requested by the user? Here you basically
> ignore all previous changes to bias.
>
> I would expect that you have something like
>
> for () {
>   switch (type) {
>   case BIAS*:
>     return apply_bias();
>   ...other types...
>   default:
>     return err;
>   }
> }

I such cases where you get conflicting PIN_CONFIG_BIAS_* settings I
don't see why it's better to do the rmw on the padctl register for the
first bias setting only to then change the bits again a few
microseconds later when the loop encounters the second bias setting.
After the loop is done the end result would still be just the last
bias setting.

> > +                       break;
> > +               case PIN_CONFIG_BIAS_PULL_DOWN:
> > +                       if (arg == 0)
> > +                               return -ENOTSUPP;
> > +                       mask |= PAD_BIAS_MASK;
> > +                       value = (value & ~PAD_BIAS_MASK) | PAD_BIAS_PULL_DOWN;
> > +                       break;
> > +               case PIN_CONFIG_BIAS_PULL_UP:
> > +                       if (arg == 0)
> > +                               return -ENOTSUPP;
> > +                       mask |= PAD_BIAS_MASK;
> > +                       value = value & ~PAD_BIAS_MASK;
> > +                       break;
> > +               case PIN_CONFIG_DRIVE_STRENGTH:
> > +                       mask |= PAD_DRIVE_STRENGTH_MASK;
> > +                       value = (value & ~PAD_DRIVE_STRENGTH_MASK) |
> > +                               starfive_drive_strength_from_max_mA(arg);
> > +                       break;
> > +               case PIN_CONFIG_INPUT_ENABLE:
> > +                       mask |= PAD_INPUT_ENABLE;
> > +                       if (arg)
> > +                               value |= PAD_INPUT_ENABLE;
> > +                       else
> > +                               value &= ~PAD_INPUT_ENABLE;
> > +                       break;
> > +               case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
> > +                       mask |= PAD_INPUT_SCHMITT_ENABLE;
> > +                       if (arg)
> > +                               value |= PAD_INPUT_SCHMITT_ENABLE;
> > +                       else
> > +                               value &= ~PAD_INPUT_SCHMITT_ENABLE;
> > +                       break;
> > +               case PIN_CONFIG_SLEW_RATE:
> > +                       mask |= PAD_SLEW_RATE_MASK;
> > +                       value = (value & ~PAD_SLEW_RATE_MASK) |
> > +                               ((arg << PAD_SLEW_RATE_POS) & PAD_SLEW_RATE_MASK);
> > +                       break;
> > +               case PIN_CONFIG_STARFIVE_STRONG_PULL_UP:
> > +                       if (arg) {
> > +                               mask |= PAD_BIAS_MASK;
> > +                               value = (value & ~PAD_BIAS_MASK) |
> > +                                       PAD_BIAS_STRONG_PULL_UP;
> > +                       } else {
> > +                               mask |= PAD_BIAS_STRONG_PULL_UP;
> > +                               value = value & ~PAD_BIAS_STRONG_PULL_UP;
> > +                       }
> > +                       break;
> > +               default:
> > +                       return -ENOTSUPP;
> > +               }
> > +       }
>
> ...
>
> > +static int starfive_gpio_request(struct gpio_chip *gc, unsigned int gpio)
> > +{
> > +       return pinctrl_gpio_request(gc->base + gpio);
> > +}
> > +
> > +static void starfive_gpio_free(struct gpio_chip *gc, unsigned int gpio)
> > +{
> > +       pinctrl_gpio_free(gc->base + gpio);
> > +}
>
> Point of having these function is...?

These calls tells the pinctrl system that a certain pin is now used
for GPIO. Conversely it'll also prevent fx. userspace from doing GPIO
on a pin that's already used by I2C, a UART or some other peripheral.

> > +       /* enable input and schmitt trigger */
>
> Use capitalization consistently.

I am?

> > +       case IRQ_TYPE_EDGE_RISING:
> > +               irq_type  = mask; /* 1: edge triggered */
> > +               edge_both = 0;    /* 0: single edge */
> > +               polarity  = mask; /* 1: rising edge */
> > +               handler   = handle_edge_irq;
> > +               break;
> > +       case IRQ_TYPE_EDGE_FALLING:
> > +               irq_type  = mask; /* 1: edge triggered */
> > +               edge_both = 0;    /* 0: single edge */
> > +               polarity  = 0;    /* 0: falling edge */
> > +               handler   = handle_edge_irq
> > +               break;
> > +       case IRQ_TYPE_EDGE_BOTH:
> > +               irq_type  = mask; /* 1: edge triggered */
> > +               edge_both = mask; /* 1: both edges */
> > +               polarity  = 0;    /* 0: ignored */
> > +               handler   = handle_edge_irq;
>
> Dup. You may do it once without any temporary variable.
> I haven't got why you haven't addressed this.

So you want two switches on the trigger variable, one for irq_type,
edge_both and polarity, and one for the handler? If this is not what
you have in mind please be a lot more explicit. Trying to guess what
you mean gets really old.

> > +               break;
> > +       case IRQ_TYPE_LEVEL_HIGH:
> > +               irq_type  = 0;    /* 0: level triggered */
> > +               edge_both = 0;    /* 0: ignored */
> > +               polarity  = mask; /* 1: high level */
> > +               handler   = handle_level_irq;
> > +               break;
> > +       case IRQ_TYPE_LEVEL_LOW:
> > +               irq_type  = 0;    /* 0: level triggered */
> > +               edge_both = 0;    /* 0: ignored */
> > +               polarity  = 0;    /* 0: low level */
> > +               handler   = handle_level_irq;
>
> Ditto.
>
> > +               break;
>
> ...
>
> > +       clk = devm_clk_get(dev, NULL);
> > +       if (IS_ERR(clk)) {
>
> > +               ret = PTR_ERR(clk);
>
> Inline into below.
>
> > +               return dev_err_probe(dev, ret, "could not get clock: %d\n", ret);
> > +       }
>
> Ditto for all other similar cases.

So you would rather want this?
  return dev_err_probe(dev, PTR_ERR(clk), "could not get clock: %d\n",
PTR_ERR(clk));
or just not tell why getting the clock failed?

> > +       if (!device_property_read_u32(dev, "starfive,signal-group", &value)) {
>
> Since you are using of_property_* elsewhere, makes sense to use same
> here, or otherwise, use device_*() APIs there.

Wait, so now you want of_property_read_u32(dev->of_node, ...) here
again, is that right?

/Emil

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 12/16] pinctrl: starfive: Add pinctrl driver for StarFive SoCs
  2021-10-23 18:45       ` Emil Renner Berthing
@ 2021-10-23 20:28         ` Andy Shevchenko
  -1 siblings, 0 replies; 143+ messages in thread
From: Andy Shevchenko @ 2021-10-23 20:28 UTC (permalink / raw)
  To: Emil Renner Berthing
  Cc: linux-riscv, devicetree, linux-clk, open list:GPIO SUBSYSTEM,
	open list:SERIAL DRIVERS, Palmer Dabbelt, Paul Walmsley,
	Rob Herring, Michael Turquette, Stephen Boyd, Thomas Gleixner,
	Marc Zyngier, Philipp Zabel, Linus Walleij, Greg Kroah-Hartman,
	Daniel Lezcano, Andy Shevchenko, Jiri Slaby, Maximilian Luz,
	Sagar Kadam, Drew Fustini, Geert Uytterhoeven, Michael Zhu,
	Fu Wei, Anup Patel, Atish Patra, Matteo Croce,
	Linux Kernel Mailing List, Huan Feng

On Sat, Oct 23, 2021 at 9:46 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> On Fri, 22 Oct 2021 at 15:32, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > On Thu, Oct 21, 2021 at 8:44 PM Emil Renner Berthing <kernel@esmil.dk> wrote:

...

> > > +               } else if ((npins = of_property_count_u32_elems(child, "pins")) > 0) {
> > > +                       pins = devm_kcalloc(dev, npins, sizeof(*pins), GFP_KERNEL);
> > > +                       if (!pins)
> > > +                               goto free_grpname;
> > > +
> > > +                       pinmux = NULL;
> > > +
> > > +                       for (i = 0; i < npins; i++) {
> > > +                               u32 v;
> > > +
> > > +                               ret = of_property_read_u32_index(child, "pins", i, &v);
> > > +                               if (ret)
> > > +                                       goto free_pins;
> > > +                               pins[i] = v;
> > > +                       }
> >
> > NIH _array() APIs.
>
> .. here the pins array is an int array and not u32 array. I can cast
> it and and hope Linux will never run on a machine where sizeof(int) !=
> 4 if you think that's better?

Can you make it u32?

...

> > > +free_pinmux:
> > > +       devm_kfree(dev, pinmux);
> > > +free_pins:
> > > +       devm_kfree(dev, pins);
> > > +free_grpname:
> > > +       devm_kfree(dev, grpname);
> >
> > > +free_pgnames:
> > > +       devm_kfree(dev, pgnames);
> >
> > Just no, please get rid of them either way as I explained in previous reviews.
>
> So I asked you if you thought it was better to leave these unused
> allocations when parsing the device tree node fails but you never
> answered that. I didn't want put words in your mouth so I could only
> assume you didn't. I'd really like a straight answer to that so I have
> something to refer to when people ask why this driver doesn't do the
> same as fx. the pinctrl-single. So just to be clear: do you think it's
> better to leave this unused garbage allocated if parsing the device
> tree node fails?

If it's only one time use, I don't think it's good to have it hanging
around, BUT at the same time devm_*() is not suitable for such
allocations.

...

> > > +               if (reg_din)
> > > +                       writel_relaxed(gpio + 2, reg_din);
> >
> > Why 0 can't be written?
>
> Because signal 0 is a special "always 0" signal and signal 1 is a
> special "always 1" signal, and after that signal n is the input value
> of GPIO n - 2. We don't want to overwrite the PoR defaults.

Okay, this, perhaps, needs a comment (if I have not missed the existing one).

And what about checking for reg_din? Do you have some blocks output-only?

...

> > > +               case PIN_CONFIG_BIAS_DISABLE:
> > > +                       mask |= PAD_BIAS_MASK;
> > > +                       value = (value & ~PAD_BIAS_MASK) | PAD_BIAS_DISABLE;
> >
> > Okay, I have got why you are masking on each iteration, but here is
> > the question, shouldn't you apply the cnages belonged to each of the
> > group of options as it's requested by the user? Here you basically
> > ignore all previous changes to bias.
> >
> > I would expect that you have something like
> >
> > for () {
> >   switch (type) {
> >   case BIAS*:
> >     return apply_bias();
> >   ...other types...
> >   default:
> >     return err;
> >   }
> > }
>
> I such cases where you get conflicting PIN_CONFIG_BIAS_* settings I
> don't see why it's better to do the rmw on the padctl register for the
> first bias setting only to then change the bits again a few
> microseconds later when the loop encounters the second bias setting.
> After the loop is done the end result would still be just the last
> bias setting.

It could be bias X followed by something else followed by bias Y. You
will write something else with bias Y. I admit I don't know this
hardware and you and maintainers are supposed to decide what's better,
but my guts are telling me that current algo is buggy.

> > > +                       break;

...

> > > +static int starfive_gpio_request(struct gpio_chip *gc, unsigned int gpio)
> > > +{
> > > +       return pinctrl_gpio_request(gc->base + gpio);
> > > +}
> > > +
> > > +static void starfive_gpio_free(struct gpio_chip *gc, unsigned int gpio)
> > > +{
> > > +       pinctrl_gpio_free(gc->base + gpio);
> > > +}
> >
> > Point of having these function is...?
>
> These calls tells the pinctrl system that a certain pin is now used
> for GPIO. Conversely it'll also prevent fx. userspace from doing GPIO
> on a pin that's already used by I2C, a UART or some other peripheral.

Isn't pin control doing it by default?

...

> > > +       /* enable input and schmitt trigger */
> >
> > Use capitalization consistently.
>
> I am?

In the comment is one style, in other comments it's another.

...

> > > +       case IRQ_TYPE_EDGE_RISING:

> > > +               handler   = handle_edge_irq;
> > > +               break;
> > > +       case IRQ_TYPE_EDGE_FALLING:

> > > +               handler   = handle_edge_irq
> > > +               break;
> > > +       case IRQ_TYPE_EDGE_BOTH:

> > > +               handler   = handle_edge_irq;
> >
> > Dup. You may do it once without any temporary variable.
> > I haven't got why you haven't addressed this.
>
> So you want two switches on the trigger variable, one for irq_type,
> edge_both and polarity, and one for the handler? If this is not what
> you have in mind please be a lot more explicit. Trying to guess what
> you mean gets really old.

switch (type) {
case bla bla bla:
  ...everything except handler...
}

if (type & EDGE)
 irq_lock(edge_handler)
else if (type & LEVEL)
 irq_lock(level_handler)

>
> > > +               break;
> > > +       case IRQ_TYPE_LEVEL_HIGH:

> > > +               handler   = handle_level_irq;
> > > +               break;
> > > +       case IRQ_TYPE_LEVEL_LOW:

> > > +               handler   = handle_level_irq;
> >
> > Ditto.
> >
> > > +               break;

...

> > > +       clk = devm_clk_get(dev, NULL);
> > > +       if (IS_ERR(clk)) {
> >
> > > +               ret = PTR_ERR(clk);
> >
> > Inline into below.
> >
> > > +               return dev_err_probe(dev, ret, "could not get clock: %d\n", ret);
> > > +       }
> >
> > Ditto for all other similar cases.
>
> So you would rather want this?
>   return dev_err_probe(dev, PTR_ERR(clk), "could not get clock: %d\n",
> PTR_ERR(clk));
> or just not tell why getting the clock failed?

Of course not, no dup of the printing error code is needed. I guess I
mentioned it in another patch.

return dev_err_probe(dev, PTR_ERR($error), "$msg\n");

...

> > > +       if (!device_property_read_u32(dev, "starfive,signal-group", &value)) {
> >
> > Since you are using of_property_* elsewhere, makes sense to use same
> > here, or otherwise, use device_*() APIs there.
>
> Wait, so now you want of_property_read_u32(dev->of_node, ...) here
> again, is that right?

Before I missed that there are other of_property_read*() calls, now
since you used them elsewhere it makes sense to be consistent over the
code.

-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 12/16] pinctrl: starfive: Add pinctrl driver for StarFive SoCs
@ 2021-10-23 20:28         ` Andy Shevchenko
  0 siblings, 0 replies; 143+ messages in thread
From: Andy Shevchenko @ 2021-10-23 20:28 UTC (permalink / raw)
  To: Emil Renner Berthing
  Cc: linux-riscv, devicetree, linux-clk, open list:GPIO SUBSYSTEM,
	open list:SERIAL DRIVERS, Palmer Dabbelt, Paul Walmsley,
	Rob Herring, Michael Turquette, Stephen Boyd, Thomas Gleixner,
	Marc Zyngier, Philipp Zabel, Linus Walleij, Greg Kroah-Hartman,
	Daniel Lezcano, Andy Shevchenko, Jiri Slaby, Maximilian Luz,
	Sagar Kadam, Drew Fustini, Geert Uytterhoeven, Michael Zhu,
	Fu Wei, Anup Patel, Atish Patra, Matteo Croce,
	Linux Kernel Mailing List, Huan Feng

On Sat, Oct 23, 2021 at 9:46 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> On Fri, 22 Oct 2021 at 15:32, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > On Thu, Oct 21, 2021 at 8:44 PM Emil Renner Berthing <kernel@esmil.dk> wrote:

...

> > > +               } else if ((npins = of_property_count_u32_elems(child, "pins")) > 0) {
> > > +                       pins = devm_kcalloc(dev, npins, sizeof(*pins), GFP_KERNEL);
> > > +                       if (!pins)
> > > +                               goto free_grpname;
> > > +
> > > +                       pinmux = NULL;
> > > +
> > > +                       for (i = 0; i < npins; i++) {
> > > +                               u32 v;
> > > +
> > > +                               ret = of_property_read_u32_index(child, "pins", i, &v);
> > > +                               if (ret)
> > > +                                       goto free_pins;
> > > +                               pins[i] = v;
> > > +                       }
> >
> > NIH _array() APIs.
>
> .. here the pins array is an int array and not u32 array. I can cast
> it and and hope Linux will never run on a machine where sizeof(int) !=
> 4 if you think that's better?

Can you make it u32?

...

> > > +free_pinmux:
> > > +       devm_kfree(dev, pinmux);
> > > +free_pins:
> > > +       devm_kfree(dev, pins);
> > > +free_grpname:
> > > +       devm_kfree(dev, grpname);
> >
> > > +free_pgnames:
> > > +       devm_kfree(dev, pgnames);
> >
> > Just no, please get rid of them either way as I explained in previous reviews.
>
> So I asked you if you thought it was better to leave these unused
> allocations when parsing the device tree node fails but you never
> answered that. I didn't want put words in your mouth so I could only
> assume you didn't. I'd really like a straight answer to that so I have
> something to refer to when people ask why this driver doesn't do the
> same as fx. the pinctrl-single. So just to be clear: do you think it's
> better to leave this unused garbage allocated if parsing the device
> tree node fails?

If it's only one time use, I don't think it's good to have it hanging
around, BUT at the same time devm_*() is not suitable for such
allocations.

...

> > > +               if (reg_din)
> > > +                       writel_relaxed(gpio + 2, reg_din);
> >
> > Why 0 can't be written?
>
> Because signal 0 is a special "always 0" signal and signal 1 is a
> special "always 1" signal, and after that signal n is the input value
> of GPIO n - 2. We don't want to overwrite the PoR defaults.

Okay, this, perhaps, needs a comment (if I have not missed the existing one).

And what about checking for reg_din? Do you have some blocks output-only?

...

> > > +               case PIN_CONFIG_BIAS_DISABLE:
> > > +                       mask |= PAD_BIAS_MASK;
> > > +                       value = (value & ~PAD_BIAS_MASK) | PAD_BIAS_DISABLE;
> >
> > Okay, I have got why you are masking on each iteration, but here is
> > the question, shouldn't you apply the cnages belonged to each of the
> > group of options as it's requested by the user? Here you basically
> > ignore all previous changes to bias.
> >
> > I would expect that you have something like
> >
> > for () {
> >   switch (type) {
> >   case BIAS*:
> >     return apply_bias();
> >   ...other types...
> >   default:
> >     return err;
> >   }
> > }
>
> I such cases where you get conflicting PIN_CONFIG_BIAS_* settings I
> don't see why it's better to do the rmw on the padctl register for the
> first bias setting only to then change the bits again a few
> microseconds later when the loop encounters the second bias setting.
> After the loop is done the end result would still be just the last
> bias setting.

It could be bias X followed by something else followed by bias Y. You
will write something else with bias Y. I admit I don't know this
hardware and you and maintainers are supposed to decide what's better,
but my guts are telling me that current algo is buggy.

> > > +                       break;

...

> > > +static int starfive_gpio_request(struct gpio_chip *gc, unsigned int gpio)
> > > +{
> > > +       return pinctrl_gpio_request(gc->base + gpio);
> > > +}
> > > +
> > > +static void starfive_gpio_free(struct gpio_chip *gc, unsigned int gpio)
> > > +{
> > > +       pinctrl_gpio_free(gc->base + gpio);
> > > +}
> >
> > Point of having these function is...?
>
> These calls tells the pinctrl system that a certain pin is now used
> for GPIO. Conversely it'll also prevent fx. userspace from doing GPIO
> on a pin that's already used by I2C, a UART or some other peripheral.

Isn't pin control doing it by default?

...

> > > +       /* enable input and schmitt trigger */
> >
> > Use capitalization consistently.
>
> I am?

In the comment is one style, in other comments it's another.

...

> > > +       case IRQ_TYPE_EDGE_RISING:

> > > +               handler   = handle_edge_irq;
> > > +               break;
> > > +       case IRQ_TYPE_EDGE_FALLING:

> > > +               handler   = handle_edge_irq
> > > +               break;
> > > +       case IRQ_TYPE_EDGE_BOTH:

> > > +               handler   = handle_edge_irq;
> >
> > Dup. You may do it once without any temporary variable.
> > I haven't got why you haven't addressed this.
>
> So you want two switches on the trigger variable, one for irq_type,
> edge_both and polarity, and one for the handler? If this is not what
> you have in mind please be a lot more explicit. Trying to guess what
> you mean gets really old.

switch (type) {
case bla bla bla:
  ...everything except handler...
}

if (type & EDGE)
 irq_lock(edge_handler)
else if (type & LEVEL)
 irq_lock(level_handler)

>
> > > +               break;
> > > +       case IRQ_TYPE_LEVEL_HIGH:

> > > +               handler   = handle_level_irq;
> > > +               break;
> > > +       case IRQ_TYPE_LEVEL_LOW:

> > > +               handler   = handle_level_irq;
> >
> > Ditto.
> >
> > > +               break;

...

> > > +       clk = devm_clk_get(dev, NULL);
> > > +       if (IS_ERR(clk)) {
> >
> > > +               ret = PTR_ERR(clk);
> >
> > Inline into below.
> >
> > > +               return dev_err_probe(dev, ret, "could not get clock: %d\n", ret);
> > > +       }
> >
> > Ditto for all other similar cases.
>
> So you would rather want this?
>   return dev_err_probe(dev, PTR_ERR(clk), "could not get clock: %d\n",
> PTR_ERR(clk));
> or just not tell why getting the clock failed?

Of course not, no dup of the printing error code is needed. I guess I
mentioned it in another patch.

return dev_err_probe(dev, PTR_ERR($error), "$msg\n");

...

> > > +       if (!device_property_read_u32(dev, "starfive,signal-group", &value)) {
> >
> > Since you are using of_property_* elsewhere, makes sense to use same
> > here, or otherwise, use device_*() APIs there.
>
> Wait, so now you want of_property_read_u32(dev->of_node, ...) here
> again, is that right?

Before I missed that there are other of_property_read*() calls, now
since you used them elsewhere it makes sense to be consistent over the
code.

-- 
With Best Regards,
Andy Shevchenko

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 12/16] pinctrl: starfive: Add pinctrl driver for StarFive SoCs
  2021-10-23 20:28         ` Andy Shevchenko
@ 2021-10-23 21:02           ` Emil Renner Berthing
  -1 siblings, 0 replies; 143+ messages in thread
From: Emil Renner Berthing @ 2021-10-23 21:02 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: linux-riscv, devicetree, linux-clk, open list:GPIO SUBSYSTEM,
	open list:SERIAL DRIVERS, Palmer Dabbelt, Paul Walmsley,
	Rob Herring, Michael Turquette, Stephen Boyd, Thomas Gleixner,
	Marc Zyngier, Philipp Zabel, Linus Walleij, Greg Kroah-Hartman,
	Daniel Lezcano, Andy Shevchenko, Jiri Slaby, Maximilian Luz,
	Sagar Kadam, Drew Fustini, Geert Uytterhoeven, Michael Zhu,
	Fu Wei, Anup Patel, Atish Patra, Matteo Croce,
	Linux Kernel Mailing List, Huan Feng

On Sat, 23 Oct 2021 at 22:29, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> On Sat, Oct 23, 2021 at 9:46 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> > On Fri, 22 Oct 2021 at 15:32, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > > On Thu, Oct 21, 2021 at 8:44 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> > > > +               } else if ((npins = of_property_count_u32_elems(child, "pins")) > 0) {
> > > > +                       pins = devm_kcalloc(dev, npins, sizeof(*pins), GFP_KERNEL);
> > > > +                       if (!pins)
> > > > +                               goto free_grpname;
> > > > +
> > > > +                       pinmux = NULL;
> > > > +
> > > > +                       for (i = 0; i < npins; i++) {
> > > > +                               u32 v;
> > > > +
> > > > +                               ret = of_property_read_u32_index(child, "pins", i, &v);
> > > > +                               if (ret)
> > > > +                                       goto free_pins;
> > > > +                               pins[i] = v;
> > > > +                       }
> > >
> > > NIH _array() APIs.
> >
> > .. here the pins array is an int array and not u32 array. I can cast
> > it and and hope Linux will never run on a machine where sizeof(int) !=
> > 4 if you think that's better?
>
> Can you make it u32?

No, the pinctrl API takes an int array.

> > > > +free_pinmux:
> > > > +       devm_kfree(dev, pinmux);
> > > > +free_pins:
> > > > +       devm_kfree(dev, pins);
> > > > +free_grpname:
> > > > +       devm_kfree(dev, grpname);
> > >
> > > > +free_pgnames:
> > > > +       devm_kfree(dev, pgnames);
> > >
> > > Just no, please get rid of them either way as I explained in previous reviews.
> >
> > So I asked you if you thought it was better to leave these unused
> > allocations when parsing the device tree node fails but you never
> > answered that. I didn't want put words in your mouth so I could only
> > assume you didn't. I'd really like a straight answer to that so I have
> > something to refer to when people ask why this driver doesn't do the
> > same as fx. the pinctrl-single. So just to be clear: do you think it's
> > better to leave this unused garbage allocated if parsing the device
> > tree node fails?
>
> If it's only one time use, I don't think it's good to have it hanging
> around, BUT at the same time devm_*() is not suitable for such
> allocations.

So is that a yes or a no to my question? It's not clear to me.

> > > > +               if (reg_din)
> > > > +                       writel_relaxed(gpio + 2, reg_din);
> > >
> > > Why 0 can't be written?
> >
> > Because signal 0 is a special "always 0" signal and signal 1 is a
> > special "always 1" signal, and after that signal n is the input value
> > of GPIO n - 2. We don't want to overwrite the PoR defaults.
>
> Okay, this, perhaps, needs a comment (if I have not missed the existing one).
>
> And what about checking for reg_din? Do you have some blocks output-only?

I don't know know what you mean by the first question, but yes fx. the
uart tx pins would be an example of pins that have their output signal
set to the uart peripheral, the output enable set to the special
"always enabled" signal, and no input signal is set to any of the tx
pins.

> > > > +               case PIN_CONFIG_BIAS_DISABLE:
> > > > +                       mask |= PAD_BIAS_MASK;
> > > > +                       value = (value & ~PAD_BIAS_MASK) | PAD_BIAS_DISABLE;
> > >
> > > Okay, I have got why you are masking on each iteration, but here is
> > > the question, shouldn't you apply the cnages belonged to each of the
> > > group of options as it's requested by the user? Here you basically
> > > ignore all previous changes to bias.
> > >
> > > I would expect that you have something like
> > >
> > > for () {
> > >   switch (type) {
> > >   case BIAS*:
> > >     return apply_bias();
> > >   ...other types...
> > >   default:
> > >     return err;
> > >   }
> > > }
> >
> > I such cases where you get conflicting PIN_CONFIG_BIAS_* settings I
> > don't see why it's better to do the rmw on the padctl register for the
> > first bias setting only to then change the bits again a few
> > microseconds later when the loop encounters the second bias setting.
> > After the loop is done the end result would still be just the last
> > bias setting.
>
> It could be bias X followed by something else followed by bias Y. You
> will write something else with bias Y. I admit I don't know this
> hardware and you and maintainers are supposed to decide what's better,
> but my guts are telling me that current algo is buggy.

So there is only one padctl register pr. pin. I don't see why first
setting the bias bits to X, then setting some other bits, and then
setting the bias bits to Y would be different from just setting all
the bits in one go. Except for during that little microsecond window
during the loop that I actually think it's better to avoid.

> > > > +                       break;
>
> ...
>
> > > > +static int starfive_gpio_request(struct gpio_chip *gc, unsigned int gpio)
> > > > +{
> > > > +       return pinctrl_gpio_request(gc->base + gpio);
> > > > +}
> > > > +
> > > > +static void starfive_gpio_free(struct gpio_chip *gc, unsigned int gpio)
> > > > +{
> > > > +       pinctrl_gpio_free(gc->base + gpio);
> > > > +}
> > >
> > > Point of having these function is...?
> >
> > These calls tells the pinctrl system that a certain pin is now used
> > for GPIO. Conversely it'll also prevent fx. userspace from doing GPIO
> > on a pin that's already used by I2C, a UART or some other peripheral.
>
> Isn't pin control doing it by default?

I actually tested that before posting and the answer seems to be no.

> ...
>
> > > > +       /* enable input and schmitt trigger */
> > >
> > > Use capitalization consistently.
> >
> > I am?
>
> In the comment is one style, in other comments it's another.

There are documentation comments in the beginning of the file and then
there are code comments in the code. I think it's a lot easier to read
like that, but if you insist I can lowercase the documentation.

> > > > +       case IRQ_TYPE_EDGE_RISING:
>
> > > > +               handler   = handle_edge_irq;
> > > > +               break;
> > > > +       case IRQ_TYPE_EDGE_FALLING:
>
> > > > +               handler   = handle_edge_irq
> > > > +               break;
> > > > +       case IRQ_TYPE_EDGE_BOTH:
>
> > > > +               handler   = handle_edge_irq;
> > >
> > > Dup. You may do it once without any temporary variable.
> > > I haven't got why you haven't addressed this.
> >
> > So you want two switches on the trigger variable, one for irq_type,
> > edge_both and polarity, and one for the handler? If this is not what
> > you have in mind please be a lot more explicit. Trying to guess what
> > you mean gets really old.
>
> switch (type) {
> case bla bla bla:
>   ...everything except handler...
> }
>
> if (type & EDGE)
>  irq_lock(edge_handler)
> else if (type & LEVEL)
>  irq_lock(level_handler)

If you look at include/dt-bindings/interrupt-controller/irq.h I don't
think such a mask exists. I guess we could do

if (trigger & IRQ_TYPE_EDGE_BOTH)
  edge_handler
else if (trigger == IRQ_TYPE_LEVEL_HIGH || trigger == IRQ_TYPE_LEVEL_LOW)
 level_handler
else
  return -EINVAL

..but at that point I think it's probably easer to read a 2nd switch
case or just leave the code as it is. What do you think?

> >
> > > > +               break;
> > > > +       case IRQ_TYPE_LEVEL_HIGH:
>
> > > > +               handler   = handle_level_irq;
> > > > +               break;
> > > > +       case IRQ_TYPE_LEVEL_LOW:
>
> > > > +               handler   = handle_level_irq;
> > >
> > > Ditto.
> > >
> > > > +               break;
>
> ...
>
> > > > +       clk = devm_clk_get(dev, NULL);
> > > > +       if (IS_ERR(clk)) {
> > >
> > > > +               ret = PTR_ERR(clk);
> > >
> > > Inline into below.
> > >
> > > > +               return dev_err_probe(dev, ret, "could not get clock: %d\n", ret);
> > > > +       }
> > >
> > > Ditto for all other similar cases.
> >
> > So you would rather want this?
> >   return dev_err_probe(dev, PTR_ERR(clk), "could not get clock: %d\n",
> > PTR_ERR(clk));
> > or just not tell why getting the clock failed?
>
> Of course not, no dup of the printing error code is needed. I guess I
> mentioned it in another patch.
>
> return dev_err_probe(dev, PTR_ERR($error), "$msg\n");
>
> ...
>
> > > > +       if (!device_property_read_u32(dev, "starfive,signal-group", &value)) {
> > >
> > > Since you are using of_property_* elsewhere, makes sense to use same
> > > here, or otherwise, use device_*() APIs there.
> >
> > Wait, so now you want of_property_read_u32(dev->of_node, ...) here
> > again, is that right?
>
> Before I missed that there are other of_property_read*() calls, now
> since you used them elsewhere it makes sense to be consistent over the
> code.

Gotcha.
> --
> With Best Regards,
> Andy Shevchenko

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 12/16] pinctrl: starfive: Add pinctrl driver for StarFive SoCs
@ 2021-10-23 21:02           ` Emil Renner Berthing
  0 siblings, 0 replies; 143+ messages in thread
From: Emil Renner Berthing @ 2021-10-23 21:02 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: linux-riscv, devicetree, linux-clk, open list:GPIO SUBSYSTEM,
	open list:SERIAL DRIVERS, Palmer Dabbelt, Paul Walmsley,
	Rob Herring, Michael Turquette, Stephen Boyd, Thomas Gleixner,
	Marc Zyngier, Philipp Zabel, Linus Walleij, Greg Kroah-Hartman,
	Daniel Lezcano, Andy Shevchenko, Jiri Slaby, Maximilian Luz,
	Sagar Kadam, Drew Fustini, Geert Uytterhoeven, Michael Zhu,
	Fu Wei, Anup Patel, Atish Patra, Matteo Croce,
	Linux Kernel Mailing List, Huan Feng

On Sat, 23 Oct 2021 at 22:29, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> On Sat, Oct 23, 2021 at 9:46 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> > On Fri, 22 Oct 2021 at 15:32, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > > On Thu, Oct 21, 2021 at 8:44 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> > > > +               } else if ((npins = of_property_count_u32_elems(child, "pins")) > 0) {
> > > > +                       pins = devm_kcalloc(dev, npins, sizeof(*pins), GFP_KERNEL);
> > > > +                       if (!pins)
> > > > +                               goto free_grpname;
> > > > +
> > > > +                       pinmux = NULL;
> > > > +
> > > > +                       for (i = 0; i < npins; i++) {
> > > > +                               u32 v;
> > > > +
> > > > +                               ret = of_property_read_u32_index(child, "pins", i, &v);
> > > > +                               if (ret)
> > > > +                                       goto free_pins;
> > > > +                               pins[i] = v;
> > > > +                       }
> > >
> > > NIH _array() APIs.
> >
> > .. here the pins array is an int array and not u32 array. I can cast
> > it and and hope Linux will never run on a machine where sizeof(int) !=
> > 4 if you think that's better?
>
> Can you make it u32?

No, the pinctrl API takes an int array.

> > > > +free_pinmux:
> > > > +       devm_kfree(dev, pinmux);
> > > > +free_pins:
> > > > +       devm_kfree(dev, pins);
> > > > +free_grpname:
> > > > +       devm_kfree(dev, grpname);
> > >
> > > > +free_pgnames:
> > > > +       devm_kfree(dev, pgnames);
> > >
> > > Just no, please get rid of them either way as I explained in previous reviews.
> >
> > So I asked you if you thought it was better to leave these unused
> > allocations when parsing the device tree node fails but you never
> > answered that. I didn't want put words in your mouth so I could only
> > assume you didn't. I'd really like a straight answer to that so I have
> > something to refer to when people ask why this driver doesn't do the
> > same as fx. the pinctrl-single. So just to be clear: do you think it's
> > better to leave this unused garbage allocated if parsing the device
> > tree node fails?
>
> If it's only one time use, I don't think it's good to have it hanging
> around, BUT at the same time devm_*() is not suitable for such
> allocations.

So is that a yes or a no to my question? It's not clear to me.

> > > > +               if (reg_din)
> > > > +                       writel_relaxed(gpio + 2, reg_din);
> > >
> > > Why 0 can't be written?
> >
> > Because signal 0 is a special "always 0" signal and signal 1 is a
> > special "always 1" signal, and after that signal n is the input value
> > of GPIO n - 2. We don't want to overwrite the PoR defaults.
>
> Okay, this, perhaps, needs a comment (if I have not missed the existing one).
>
> And what about checking for reg_din? Do you have some blocks output-only?

I don't know know what you mean by the first question, but yes fx. the
uart tx pins would be an example of pins that have their output signal
set to the uart peripheral, the output enable set to the special
"always enabled" signal, and no input signal is set to any of the tx
pins.

> > > > +               case PIN_CONFIG_BIAS_DISABLE:
> > > > +                       mask |= PAD_BIAS_MASK;
> > > > +                       value = (value & ~PAD_BIAS_MASK) | PAD_BIAS_DISABLE;
> > >
> > > Okay, I have got why you are masking on each iteration, but here is
> > > the question, shouldn't you apply the cnages belonged to each of the
> > > group of options as it's requested by the user? Here you basically
> > > ignore all previous changes to bias.
> > >
> > > I would expect that you have something like
> > >
> > > for () {
> > >   switch (type) {
> > >   case BIAS*:
> > >     return apply_bias();
> > >   ...other types...
> > >   default:
> > >     return err;
> > >   }
> > > }
> >
> > I such cases where you get conflicting PIN_CONFIG_BIAS_* settings I
> > don't see why it's better to do the rmw on the padctl register for the
> > first bias setting only to then change the bits again a few
> > microseconds later when the loop encounters the second bias setting.
> > After the loop is done the end result would still be just the last
> > bias setting.
>
> It could be bias X followed by something else followed by bias Y. You
> will write something else with bias Y. I admit I don't know this
> hardware and you and maintainers are supposed to decide what's better,
> but my guts are telling me that current algo is buggy.

So there is only one padctl register pr. pin. I don't see why first
setting the bias bits to X, then setting some other bits, and then
setting the bias bits to Y would be different from just setting all
the bits in one go. Except for during that little microsecond window
during the loop that I actually think it's better to avoid.

> > > > +                       break;
>
> ...
>
> > > > +static int starfive_gpio_request(struct gpio_chip *gc, unsigned int gpio)
> > > > +{
> > > > +       return pinctrl_gpio_request(gc->base + gpio);
> > > > +}
> > > > +
> > > > +static void starfive_gpio_free(struct gpio_chip *gc, unsigned int gpio)
> > > > +{
> > > > +       pinctrl_gpio_free(gc->base + gpio);
> > > > +}
> > >
> > > Point of having these function is...?
> >
> > These calls tells the pinctrl system that a certain pin is now used
> > for GPIO. Conversely it'll also prevent fx. userspace from doing GPIO
> > on a pin that's already used by I2C, a UART or some other peripheral.
>
> Isn't pin control doing it by default?

I actually tested that before posting and the answer seems to be no.

> ...
>
> > > > +       /* enable input and schmitt trigger */
> > >
> > > Use capitalization consistently.
> >
> > I am?
>
> In the comment is one style, in other comments it's another.

There are documentation comments in the beginning of the file and then
there are code comments in the code. I think it's a lot easier to read
like that, but if you insist I can lowercase the documentation.

> > > > +       case IRQ_TYPE_EDGE_RISING:
>
> > > > +               handler   = handle_edge_irq;
> > > > +               break;
> > > > +       case IRQ_TYPE_EDGE_FALLING:
>
> > > > +               handler   = handle_edge_irq
> > > > +               break;
> > > > +       case IRQ_TYPE_EDGE_BOTH:
>
> > > > +               handler   = handle_edge_irq;
> > >
> > > Dup. You may do it once without any temporary variable.
> > > I haven't got why you haven't addressed this.
> >
> > So you want two switches on the trigger variable, one for irq_type,
> > edge_both and polarity, and one for the handler? If this is not what
> > you have in mind please be a lot more explicit. Trying to guess what
> > you mean gets really old.
>
> switch (type) {
> case bla bla bla:
>   ...everything except handler...
> }
>
> if (type & EDGE)
>  irq_lock(edge_handler)
> else if (type & LEVEL)
>  irq_lock(level_handler)

If you look at include/dt-bindings/interrupt-controller/irq.h I don't
think such a mask exists. I guess we could do

if (trigger & IRQ_TYPE_EDGE_BOTH)
  edge_handler
else if (trigger == IRQ_TYPE_LEVEL_HIGH || trigger == IRQ_TYPE_LEVEL_LOW)
 level_handler
else
  return -EINVAL

..but at that point I think it's probably easer to read a 2nd switch
case or just leave the code as it is. What do you think?

> >
> > > > +               break;
> > > > +       case IRQ_TYPE_LEVEL_HIGH:
>
> > > > +               handler   = handle_level_irq;
> > > > +               break;
> > > > +       case IRQ_TYPE_LEVEL_LOW:
>
> > > > +               handler   = handle_level_irq;
> > >
> > > Ditto.
> > >
> > > > +               break;
>
> ...
>
> > > > +       clk = devm_clk_get(dev, NULL);
> > > > +       if (IS_ERR(clk)) {
> > >
> > > > +               ret = PTR_ERR(clk);
> > >
> > > Inline into below.
> > >
> > > > +               return dev_err_probe(dev, ret, "could not get clock: %d\n", ret);
> > > > +       }
> > >
> > > Ditto for all other similar cases.
> >
> > So you would rather want this?
> >   return dev_err_probe(dev, PTR_ERR(clk), "could not get clock: %d\n",
> > PTR_ERR(clk));
> > or just not tell why getting the clock failed?
>
> Of course not, no dup of the printing error code is needed. I guess I
> mentioned it in another patch.
>
> return dev_err_probe(dev, PTR_ERR($error), "$msg\n");
>
> ...
>
> > > > +       if (!device_property_read_u32(dev, "starfive,signal-group", &value)) {
> > >
> > > Since you are using of_property_* elsewhere, makes sense to use same
> > > here, or otherwise, use device_*() APIs there.
> >
> > Wait, so now you want of_property_read_u32(dev->of_node, ...) here
> > again, is that right?
>
> Before I missed that there are other of_property_read*() calls, now
> since you used them elsewhere it makes sense to be consistent over the
> code.

Gotcha.
> --
> With Best Regards,
> Andy Shevchenko

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 12/16] pinctrl: starfive: Add pinctrl driver for StarFive SoCs
  2021-10-23 21:02           ` Emil Renner Berthing
@ 2021-10-24  9:29             ` Emil Renner Berthing
  -1 siblings, 0 replies; 143+ messages in thread
From: Emil Renner Berthing @ 2021-10-24  9:29 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: linux-riscv, devicetree, linux-clk, open list:GPIO SUBSYSTEM,
	open list:SERIAL DRIVERS, Palmer Dabbelt, Paul Walmsley,
	Rob Herring, Michael Turquette, Stephen Boyd, Thomas Gleixner,
	Marc Zyngier, Philipp Zabel, Linus Walleij, Greg Kroah-Hartman,
	Daniel Lezcano, Andy Shevchenko, Jiri Slaby, Maximilian Luz,
	Sagar Kadam, Drew Fustini, Geert Uytterhoeven, Michael Zhu,
	Fu Wei, Anup Patel, Atish Patra, Matteo Croce,
	Linux Kernel Mailing List, Huan Feng

On Sat, 23 Oct 2021 at 23:02, Emil Renner Berthing <kernel@esmil.dk> wrote:
> On Sat, 23 Oct 2021 at 22:29, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > On Sat, Oct 23, 2021 at 9:46 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> > > On Fri, 22 Oct 2021 at 15:32, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > > > On Thu, Oct 21, 2021 at 8:44 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> > > So I asked you if you thought it was better to leave these unused
> > > allocations when parsing the device tree node fails but you never
> > > answered that. I didn't want put words in your mouth so I could only
> > > assume you didn't. I'd really like a straight answer to that so I have
> > > something to refer to when people ask why this driver doesn't do the
> > > same as fx. the pinctrl-single. So just to be clear: do you think it's
> > > better to leave this unused garbage allocated if parsing the device
> > > tree node fails?
> >
> > If it's only one time use, I don't think it's good to have it hanging
> > around, BUT at the same time devm_*() is not suitable for such
> > allocations.
>
> So is that a yes or a no to my question? It's not clear to me.

I see now that you've probably misunderstood what the code does. It's
not one time use. The function parses the device tree and dynamically
registers groups and functions with the pinctrl framework. Each group
needs a string name, an int array of pins and optionally the pinmux
data. Once the group is registered those pieces of data needs to live
with the group until the drive is unloaded. But if the device tree
parsing fails before the group is registered then those allocations
would never be referenced and just hang around as garbage until the
driver is unloaded. In such cases fx. pinctrl-single uses devm_free to
free them again.

> > > > > +               if (reg_din)
> > > > > +                       writel_relaxed(gpio + 2, reg_din);
> > > >
> > > > Why 0 can't be written?
> > >
> > > Because signal 0 is a special "always 0" signal and signal 1 is a
> > > special "always 1" signal, and after that signal n is the input value
> > > of GPIO n - 2. We don't want to overwrite the PoR defaults.
> >
> > Okay, this, perhaps, needs a comment (if I have not missed the existing one).
> >
> > And what about checking for reg_din? Do you have some blocks output-only?
>
> I don't know know what you mean by the first question, but yes fx. the
> uart tx pins would be an example of pins that have their output signal
> set to the uart peripheral, the output enable set to the special
> "always enabled" signal, and no input signal is set to any of the tx
> pins.
>
> > > > > +               case PIN_CONFIG_BIAS_DISABLE:
> > > > > +                       mask |= PAD_BIAS_MASK;
> > > > > +                       value = (value & ~PAD_BIAS_MASK) | PAD_BIAS_DISABLE;
> > > >
> > > > Okay, I have got why you are masking on each iteration, but here is
> > > > the question, shouldn't you apply the cnages belonged to each of the
> > > > group of options as it's requested by the user? Here you basically
> > > > ignore all previous changes to bias.
> > > >
> > > > I would expect that you have something like
> > > >
> > > > for () {
> > > >   switch (type) {
> > > >   case BIAS*:
> > > >     return apply_bias();
> > > >   ...other types...
> > > >   default:
> > > >     return err;
> > > >   }
> > > > }
> > >
> > > I such cases where you get conflicting PIN_CONFIG_BIAS_* settings I
> > > don't see why it's better to do the rmw on the padctl register for the
> > > first bias setting only to then change the bits again a few
> > > microseconds later when the loop encounters the second bias setting.
> > > After the loop is done the end result would still be just the last
> > > bias setting.
> >
> > It could be bias X followed by something else followed by bias Y. You
> > will write something else with bias Y. I admit I don't know this
> > hardware and you and maintainers are supposed to decide what's better,
> > but my guts are telling me that current algo is buggy.
>
> So there is only one padctl register pr. pin. I don't see why first
> setting the bias bits to X, then setting some other bits, and then
> setting the bias bits to Y would be different from just setting all
> the bits in one go. Except for during that little microsecond window
> during the loop that I actually think it's better to avoid.

Maybe an example is in order. Suppose we get strong pull-up, drive
strength 3 and pull-down config flags (the strong pull-up and pull
down flags conflict) and the padctl value is 0x0c0 (pull-up, input and
schmitt trigger enabled). With your solution of just altering the
padctl bits immediately we'd call starfive_padctl_rmw 3 times in rapid
succession like this:

starfive_padctl_rmw(pin, 0x130, 0x100);
starfive_padctl_rmw(pin, 0x007, 0x003);
starfive_padctl_rmw(pin, 0x130, 0x010);

..and the end result would be 0x0d3, although the strong pull-up would
be enabled for the microseconds between the 1st and 3nd call.
As the code is now it'd just directly do

starfive_padctl_rmw(pin, 0x137, 0x013)

..which again results in 0x0d3, only without the microsecond blink of
the strong pull-up.

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 12/16] pinctrl: starfive: Add pinctrl driver for StarFive SoCs
@ 2021-10-24  9:29             ` Emil Renner Berthing
  0 siblings, 0 replies; 143+ messages in thread
From: Emil Renner Berthing @ 2021-10-24  9:29 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: linux-riscv, devicetree, linux-clk, open list:GPIO SUBSYSTEM,
	open list:SERIAL DRIVERS, Palmer Dabbelt, Paul Walmsley,
	Rob Herring, Michael Turquette, Stephen Boyd, Thomas Gleixner,
	Marc Zyngier, Philipp Zabel, Linus Walleij, Greg Kroah-Hartman,
	Daniel Lezcano, Andy Shevchenko, Jiri Slaby, Maximilian Luz,
	Sagar Kadam, Drew Fustini, Geert Uytterhoeven, Michael Zhu,
	Fu Wei, Anup Patel, Atish Patra, Matteo Croce,
	Linux Kernel Mailing List, Huan Feng

On Sat, 23 Oct 2021 at 23:02, Emil Renner Berthing <kernel@esmil.dk> wrote:
> On Sat, 23 Oct 2021 at 22:29, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > On Sat, Oct 23, 2021 at 9:46 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> > > On Fri, 22 Oct 2021 at 15:32, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > > > On Thu, Oct 21, 2021 at 8:44 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> > > So I asked you if you thought it was better to leave these unused
> > > allocations when parsing the device tree node fails but you never
> > > answered that. I didn't want put words in your mouth so I could only
> > > assume you didn't. I'd really like a straight answer to that so I have
> > > something to refer to when people ask why this driver doesn't do the
> > > same as fx. the pinctrl-single. So just to be clear: do you think it's
> > > better to leave this unused garbage allocated if parsing the device
> > > tree node fails?
> >
> > If it's only one time use, I don't think it's good to have it hanging
> > around, BUT at the same time devm_*() is not suitable for such
> > allocations.
>
> So is that a yes or a no to my question? It's not clear to me.

I see now that you've probably misunderstood what the code does. It's
not one time use. The function parses the device tree and dynamically
registers groups and functions with the pinctrl framework. Each group
needs a string name, an int array of pins and optionally the pinmux
data. Once the group is registered those pieces of data needs to live
with the group until the drive is unloaded. But if the device tree
parsing fails before the group is registered then those allocations
would never be referenced and just hang around as garbage until the
driver is unloaded. In such cases fx. pinctrl-single uses devm_free to
free them again.

> > > > > +               if (reg_din)
> > > > > +                       writel_relaxed(gpio + 2, reg_din);
> > > >
> > > > Why 0 can't be written?
> > >
> > > Because signal 0 is a special "always 0" signal and signal 1 is a
> > > special "always 1" signal, and after that signal n is the input value
> > > of GPIO n - 2. We don't want to overwrite the PoR defaults.
> >
> > Okay, this, perhaps, needs a comment (if I have not missed the existing one).
> >
> > And what about checking for reg_din? Do you have some blocks output-only?
>
> I don't know know what you mean by the first question, but yes fx. the
> uart tx pins would be an example of pins that have their output signal
> set to the uart peripheral, the output enable set to the special
> "always enabled" signal, and no input signal is set to any of the tx
> pins.
>
> > > > > +               case PIN_CONFIG_BIAS_DISABLE:
> > > > > +                       mask |= PAD_BIAS_MASK;
> > > > > +                       value = (value & ~PAD_BIAS_MASK) | PAD_BIAS_DISABLE;
> > > >
> > > > Okay, I have got why you are masking on each iteration, but here is
> > > > the question, shouldn't you apply the cnages belonged to each of the
> > > > group of options as it's requested by the user? Here you basically
> > > > ignore all previous changes to bias.
> > > >
> > > > I would expect that you have something like
> > > >
> > > > for () {
> > > >   switch (type) {
> > > >   case BIAS*:
> > > >     return apply_bias();
> > > >   ...other types...
> > > >   default:
> > > >     return err;
> > > >   }
> > > > }
> > >
> > > I such cases where you get conflicting PIN_CONFIG_BIAS_* settings I
> > > don't see why it's better to do the rmw on the padctl register for the
> > > first bias setting only to then change the bits again a few
> > > microseconds later when the loop encounters the second bias setting.
> > > After the loop is done the end result would still be just the last
> > > bias setting.
> >
> > It could be bias X followed by something else followed by bias Y. You
> > will write something else with bias Y. I admit I don't know this
> > hardware and you and maintainers are supposed to decide what's better,
> > but my guts are telling me that current algo is buggy.
>
> So there is only one padctl register pr. pin. I don't see why first
> setting the bias bits to X, then setting some other bits, and then
> setting the bias bits to Y would be different from just setting all
> the bits in one go. Except for during that little microsecond window
> during the loop that I actually think it's better to avoid.

Maybe an example is in order. Suppose we get strong pull-up, drive
strength 3 and pull-down config flags (the strong pull-up and pull
down flags conflict) and the padctl value is 0x0c0 (pull-up, input and
schmitt trigger enabled). With your solution of just altering the
padctl bits immediately we'd call starfive_padctl_rmw 3 times in rapid
succession like this:

starfive_padctl_rmw(pin, 0x130, 0x100);
starfive_padctl_rmw(pin, 0x007, 0x003);
starfive_padctl_rmw(pin, 0x130, 0x010);

..and the end result would be 0x0d3, although the strong pull-up would
be enabled for the microseconds between the 1st and 3nd call.
As the code is now it'd just directly do

starfive_padctl_rmw(pin, 0x137, 0x013)

..which again results in 0x0d3, only without the microsecond blink of
the strong pull-up.

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 11/16] dt-bindings: pinctrl: Add StarFive JH7100 bindings
  2021-10-21 17:42   ` Emil Renner Berthing
@ 2021-10-24 23:11     ` Linus Walleij
  -1 siblings, 0 replies; 143+ messages in thread
From: Linus Walleij @ 2021-10-24 23:11 UTC (permalink / raw)
  To: Emil Renner Berthing
  Cc: linux-riscv,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	linux-clk, open list:GPIO SUBSYSTEM, open list:SERIAL DRIVERS,
	Palmer Dabbelt, Paul Walmsley, Rob Herring, Michael Turquette,
	Stephen Boyd, Thomas Gleixner, Marc Zyngier, Philipp Zabel,
	Greg Kroah-Hartman, Daniel Lezcano, Andy Shevchenko, Jiri Slaby,
	Maximilian Luz, Sagar Kadam, Drew Fustini, Geert Uytterhoeven,
	Michael Zhu, Fu Wei, Anup Patel, Atish Patra, Matteo Croce,
	linux-kernel

On Thu, Oct 21, 2021 at 7:42 PM Emil Renner Berthing <kernel@esmil.dk> wrote:

> Add bindings for the StarFive JH7100 GPIO/pin controller.
>
> Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>

That is a very terse commit message for an entirely new
SoC, please put a little blurb about this silicon there.
Like mention that it is RISC-V at least.

Overall quite interesting!

> +$id: http://devicetree.org/schemas/pinctrl/starfive,jh7100-pinctrl.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: StarFive JH7100 Pin Controller Device Tree Bindings
> +
> +maintainers:
> +  - Emil Renner Berthing <kernel@esmil.dk>
> +  - Drew Fustini <drew@beagleboard.org>

Add description: talking about that this is a RISC-V SoC
and other implicit things that are really good to know.

> +  starfive,signal-group:
> +    description: |
> +      The SoC has a global setting selecting one of 7 different pinmux
> +      configurations of the pads named GPIO[0:63] and FUNC_SHARE[0:141]. After
> +      this global setting is chosen only the 64 "GPIO" pins can be further
> +      muxed by configuring them to be controlled by certain peripherals rather
> +      than software.
> +      Note that in configuration 0 none of GPIOs are routed to pads, and only
> +      in configuration 1 are the GPIOs routed to the pads named GPIO[0:63].
> +      If this property is not set it defaults to the configuration already
> +      chosen by the earlier boot stages.
> +    $ref: /schemas/types.yaml#/definitions/uint32
> +    enum: [0, 1, 2, 3, 4, 5, 6]

This still is hard for me to understand. Does it mean that 0..6 define
how the direct-to-peripheral-pins are set up?

Then it would make sense to describe what happens for 0, 1, 2 ...6
i.e. what the different set-ups are.

Actually this is what we call group-based pin multiplexing in Linux,
this property seems to avoid using that concept.
See for example:
Documentation/devicetree/bindings/pinctrl/cortina,gemini-pinctrl.txt

> +    patternProperties:
> +      '-pins*$':
> +        type: object
> +        description: |
> +          A pinctrl node should contain at least one subnode representing the
> +          pinctrl groups available on the machine. Each subnode will list the
> +          pins it needs, and how they should be configured, with regard to
> +          muxer configuration, bias, input enable/disable, input schmitt
> +          trigger enable/disable, slew-rate and drive strength.
> +        $ref: "/schemas/pinctrl/pincfg-node.yaml"

Nice that you use pincfg-node.yaml

> +        properties:
> +          pins:
> +            description: |
> +              The list of pin identifiers that properties in the node apply to.
> +              This should be set using either the PAD_GPIO or PAD_FUNC_SHARE
> +              macro. Either this or "pinmux" has to be specified.
> +
> +          pinmux:
> +            description: |
> +              The list of GPIO identifiers and their mux settings that
> +              properties in the node apply to. This should be set using the
> +              GPIOMUX macro. Either this or "pins" has to be specified.

What about referencing
Documentation/devicetree/bindings/pinctrl/pinmux-node.yaml
for this?

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 11/16] dt-bindings: pinctrl: Add StarFive JH7100 bindings
@ 2021-10-24 23:11     ` Linus Walleij
  0 siblings, 0 replies; 143+ messages in thread
From: Linus Walleij @ 2021-10-24 23:11 UTC (permalink / raw)
  To: Emil Renner Berthing
  Cc: linux-riscv,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	linux-clk, open list:GPIO SUBSYSTEM, open list:SERIAL DRIVERS,
	Palmer Dabbelt, Paul Walmsley, Rob Herring, Michael Turquette,
	Stephen Boyd, Thomas Gleixner, Marc Zyngier, Philipp Zabel,
	Greg Kroah-Hartman, Daniel Lezcano, Andy Shevchenko, Jiri Slaby,
	Maximilian Luz, Sagar Kadam, Drew Fustini, Geert Uytterhoeven,
	Michael Zhu, Fu Wei, Anup Patel, Atish Patra, Matteo Croce,
	linux-kernel

On Thu, Oct 21, 2021 at 7:42 PM Emil Renner Berthing <kernel@esmil.dk> wrote:

> Add bindings for the StarFive JH7100 GPIO/pin controller.
>
> Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>

That is a very terse commit message for an entirely new
SoC, please put a little blurb about this silicon there.
Like mention that it is RISC-V at least.

Overall quite interesting!

> +$id: http://devicetree.org/schemas/pinctrl/starfive,jh7100-pinctrl.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: StarFive JH7100 Pin Controller Device Tree Bindings
> +
> +maintainers:
> +  - Emil Renner Berthing <kernel@esmil.dk>
> +  - Drew Fustini <drew@beagleboard.org>

Add description: talking about that this is a RISC-V SoC
and other implicit things that are really good to know.

> +  starfive,signal-group:
> +    description: |
> +      The SoC has a global setting selecting one of 7 different pinmux
> +      configurations of the pads named GPIO[0:63] and FUNC_SHARE[0:141]. After
> +      this global setting is chosen only the 64 "GPIO" pins can be further
> +      muxed by configuring them to be controlled by certain peripherals rather
> +      than software.
> +      Note that in configuration 0 none of GPIOs are routed to pads, and only
> +      in configuration 1 are the GPIOs routed to the pads named GPIO[0:63].
> +      If this property is not set it defaults to the configuration already
> +      chosen by the earlier boot stages.
> +    $ref: /schemas/types.yaml#/definitions/uint32
> +    enum: [0, 1, 2, 3, 4, 5, 6]

This still is hard for me to understand. Does it mean that 0..6 define
how the direct-to-peripheral-pins are set up?

Then it would make sense to describe what happens for 0, 1, 2 ...6
i.e. what the different set-ups are.

Actually this is what we call group-based pin multiplexing in Linux,
this property seems to avoid using that concept.
See for example:
Documentation/devicetree/bindings/pinctrl/cortina,gemini-pinctrl.txt

> +    patternProperties:
> +      '-pins*$':
> +        type: object
> +        description: |
> +          A pinctrl node should contain at least one subnode representing the
> +          pinctrl groups available on the machine. Each subnode will list the
> +          pins it needs, and how they should be configured, with regard to
> +          muxer configuration, bias, input enable/disable, input schmitt
> +          trigger enable/disable, slew-rate and drive strength.
> +        $ref: "/schemas/pinctrl/pincfg-node.yaml"

Nice that you use pincfg-node.yaml

> +        properties:
> +          pins:
> +            description: |
> +              The list of pin identifiers that properties in the node apply to.
> +              This should be set using either the PAD_GPIO or PAD_FUNC_SHARE
> +              macro. Either this or "pinmux" has to be specified.
> +
> +          pinmux:
> +            description: |
> +              The list of GPIO identifiers and their mux settings that
> +              properties in the node apply to. This should be set using the
> +              GPIOMUX macro. Either this or "pins" has to be specified.

What about referencing
Documentation/devicetree/bindings/pinctrl/pinmux-node.yaml
for this?

Yours,
Linus Walleij

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 11/16] dt-bindings: pinctrl: Add StarFive JH7100 bindings
  2021-10-24 23:11     ` Linus Walleij
@ 2021-10-25  0:35       ` Emil Renner Berthing
  -1 siblings, 0 replies; 143+ messages in thread
From: Emil Renner Berthing @ 2021-10-25  0:35 UTC (permalink / raw)
  To: Linus Walleij
  Cc: linux-riscv,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	linux-clk, open list:GPIO SUBSYSTEM, open list:SERIAL DRIVERS,
	Palmer Dabbelt, Paul Walmsley, Rob Herring, Michael Turquette,
	Stephen Boyd, Thomas Gleixner, Marc Zyngier, Philipp Zabel,
	Greg Kroah-Hartman, Daniel Lezcano, Andy Shevchenko, Jiri Slaby,
	Maximilian Luz, Sagar Kadam, Drew Fustini, Geert Uytterhoeven,
	Michael Zhu, Fu Wei, Anup Patel, Atish Patra, Matteo Croce,
	linux-kernel

On Mon, 25 Oct 2021 at 01:11, Linus Walleij <linus.walleij@linaro.org> wrote:
> On Thu, Oct 21, 2021 at 7:42 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
>
> > Add bindings for the StarFive JH7100 GPIO/pin controller.
> >
> > Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
>
> That is a very terse commit message for an entirely new
> SoC, please put a little blurb about this silicon there.
> Like mention that it is RISC-V at least.

Will do!

> Overall quite interesting!
>
> > +$id: http://devicetree.org/schemas/pinctrl/starfive,jh7100-pinctrl.yaml#
> > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > +
> > +title: StarFive JH7100 Pin Controller Device Tree Bindings
> > +
> > +maintainers:
> > +  - Emil Renner Berthing <kernel@esmil.dk>
> > +  - Drew Fustini <drew@beagleboard.org>
>
> Add description: talking about that this is a RISC-V SoC
> and other implicit things that are really good to know.

Gotcha.

> > +  starfive,signal-group:
> > +    description: |
> > +      The SoC has a global setting selecting one of 7 different pinmux
> > +      configurations of the pads named GPIO[0:63] and FUNC_SHARE[0:141]. After
> > +      this global setting is chosen only the 64 "GPIO" pins can be further
> > +      muxed by configuring them to be controlled by certain peripherals rather
> > +      than software.
> > +      Note that in configuration 0 none of GPIOs are routed to pads, and only
> > +      in configuration 1 are the GPIOs routed to the pads named GPIO[0:63].
> > +      If this property is not set it defaults to the configuration already
> > +      chosen by the earlier boot stages.
> > +    $ref: /schemas/types.yaml#/definitions/uint32
> > +    enum: [0, 1, 2, 3, 4, 5, 6]
>
> This still is hard for me to understand. Does it mean that 0..6 define
> how the direct-to-peripheral-pins are set up?

Yeah, so the SoC has many pins, but only the pins named GPIO[0:63] and
FUNC_SHARE[0:141] can be muxed. To do that you first select one of 7
different "signal groups". This is a global setting. There is just a
single register on the whole SoC where you write either 0, 1, .., or
6. As an example signal group 6 maps LCD output to FUNC_SHARE[40:97],
ethernet phy connection to FUNC_SHARE[115:141], MIPI to GPIO[0:60] and
confusingly it maps "GPIO0", "GPIO1", ..., "GPIO63" to pins
FUNC_SHARE[0:63]. So the pin names doesn't necessarily match the
function. In fact only signal group 1 maps GPIO0-63 to pins
GPIO[0:63]. See table 11-1 starting on page 62 of this PDF:
https://github.com/starfive-tech/JH7100_Docs/blob/main/JH7100%20Data%20Sheet%20V01.01.04-EN%20(4-21-2021).pdf

GPIO0-63 can of course be used as GPIOs, but they can also have their
output value and output enable controlled by certain (slow)
peripherals like UARTs, I2C, SPI, PWM etc. These can be chosen freely.
So once you've chosen signal group 6, you can have any of GPIO0-GPIO63
(that is any of pins FUNC_SHARE[0:63]) be controlled by the UART0 TX
signal fx.

So for each of GPIO0 to GPIO63 there is a register to select the
output value signal and a register to select its output enable signal.
You can see the list of signals to choose from in the header
introduced in the previous patch.

Input from GPIO0-63 to peripherals works the other way around. Here
there is a register for each input signal, where you can select which
(if any) of GPIO0-63 is routed to the peripheral.

> Then it would make sense to describe what happens for 0, 1, 2 ...6
> i.e. what the different set-ups are.

Yeah, so how much of table 11-1 does it make sense to write out.
Certainly I can list how GPIO0-63 are mapped to pins for each of the 7
signal groups, but should I also list LCD, ethernet, interconnect,
mipi etc. for each of the 7 signal groups?

> Actually this is what we call group-based pin multiplexing in Linux,
> this property seems to avoid using that concept.
> See for example:
> Documentation/devicetree/bindings/pinctrl/cortina,gemini-pinctrl.txt

I don't think this is the same, but hope you can tell me after reading
the description above.

> > +    patternProperties:
> > +      '-pins*$':
> > +        type: object
> > +        description: |
> > +          A pinctrl node should contain at least one subnode representing the
> > +          pinctrl groups available on the machine. Each subnode will list the
> > +          pins it needs, and how they should be configured, with regard to
> > +          muxer configuration, bias, input enable/disable, input schmitt
> > +          trigger enable/disable, slew-rate and drive strength.
> > +        $ref: "/schemas/pinctrl/pincfg-node.yaml"
>
> Nice that you use pincfg-node.yaml
>
> > +        properties:
> > +          pins:
> > +            description: |
> > +              The list of pin identifiers that properties in the node apply to.
> > +              This should be set using either the PAD_GPIO or PAD_FUNC_SHARE
> > +              macro. Either this or "pinmux" has to be specified.
> > +
> > +          pinmux:
> > +            description: |
> > +              The list of GPIO identifiers and their mux settings that
> > +              properties in the node apply to. This should be set using the
> > +              GPIOMUX macro. Either this or "pins" has to be specified.
>
> What about referencing
> Documentation/devicetree/bindings/pinctrl/pinmux-node.yaml
> for this?

Sure. You just mean adding $ref: like above right?

Thanks!
/Emil

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 11/16] dt-bindings: pinctrl: Add StarFive JH7100 bindings
@ 2021-10-25  0:35       ` Emil Renner Berthing
  0 siblings, 0 replies; 143+ messages in thread
From: Emil Renner Berthing @ 2021-10-25  0:35 UTC (permalink / raw)
  To: Linus Walleij
  Cc: linux-riscv,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	linux-clk, open list:GPIO SUBSYSTEM, open list:SERIAL DRIVERS,
	Palmer Dabbelt, Paul Walmsley, Rob Herring, Michael Turquette,
	Stephen Boyd, Thomas Gleixner, Marc Zyngier, Philipp Zabel,
	Greg Kroah-Hartman, Daniel Lezcano, Andy Shevchenko, Jiri Slaby,
	Maximilian Luz, Sagar Kadam, Drew Fustini, Geert Uytterhoeven,
	Michael Zhu, Fu Wei, Anup Patel, Atish Patra, Matteo Croce,
	linux-kernel

On Mon, 25 Oct 2021 at 01:11, Linus Walleij <linus.walleij@linaro.org> wrote:
> On Thu, Oct 21, 2021 at 7:42 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
>
> > Add bindings for the StarFive JH7100 GPIO/pin controller.
> >
> > Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
>
> That is a very terse commit message for an entirely new
> SoC, please put a little blurb about this silicon there.
> Like mention that it is RISC-V at least.

Will do!

> Overall quite interesting!
>
> > +$id: http://devicetree.org/schemas/pinctrl/starfive,jh7100-pinctrl.yaml#
> > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > +
> > +title: StarFive JH7100 Pin Controller Device Tree Bindings
> > +
> > +maintainers:
> > +  - Emil Renner Berthing <kernel@esmil.dk>
> > +  - Drew Fustini <drew@beagleboard.org>
>
> Add description: talking about that this is a RISC-V SoC
> and other implicit things that are really good to know.

Gotcha.

> > +  starfive,signal-group:
> > +    description: |
> > +      The SoC has a global setting selecting one of 7 different pinmux
> > +      configurations of the pads named GPIO[0:63] and FUNC_SHARE[0:141]. After
> > +      this global setting is chosen only the 64 "GPIO" pins can be further
> > +      muxed by configuring them to be controlled by certain peripherals rather
> > +      than software.
> > +      Note that in configuration 0 none of GPIOs are routed to pads, and only
> > +      in configuration 1 are the GPIOs routed to the pads named GPIO[0:63].
> > +      If this property is not set it defaults to the configuration already
> > +      chosen by the earlier boot stages.
> > +    $ref: /schemas/types.yaml#/definitions/uint32
> > +    enum: [0, 1, 2, 3, 4, 5, 6]
>
> This still is hard for me to understand. Does it mean that 0..6 define
> how the direct-to-peripheral-pins are set up?

Yeah, so the SoC has many pins, but only the pins named GPIO[0:63] and
FUNC_SHARE[0:141] can be muxed. To do that you first select one of 7
different "signal groups". This is a global setting. There is just a
single register on the whole SoC where you write either 0, 1, .., or
6. As an example signal group 6 maps LCD output to FUNC_SHARE[40:97],
ethernet phy connection to FUNC_SHARE[115:141], MIPI to GPIO[0:60] and
confusingly it maps "GPIO0", "GPIO1", ..., "GPIO63" to pins
FUNC_SHARE[0:63]. So the pin names doesn't necessarily match the
function. In fact only signal group 1 maps GPIO0-63 to pins
GPIO[0:63]. See table 11-1 starting on page 62 of this PDF:
https://github.com/starfive-tech/JH7100_Docs/blob/main/JH7100%20Data%20Sheet%20V01.01.04-EN%20(4-21-2021).pdf

GPIO0-63 can of course be used as GPIOs, but they can also have their
output value and output enable controlled by certain (slow)
peripherals like UARTs, I2C, SPI, PWM etc. These can be chosen freely.
So once you've chosen signal group 6, you can have any of GPIO0-GPIO63
(that is any of pins FUNC_SHARE[0:63]) be controlled by the UART0 TX
signal fx.

So for each of GPIO0 to GPIO63 there is a register to select the
output value signal and a register to select its output enable signal.
You can see the list of signals to choose from in the header
introduced in the previous patch.

Input from GPIO0-63 to peripherals works the other way around. Here
there is a register for each input signal, where you can select which
(if any) of GPIO0-63 is routed to the peripheral.

> Then it would make sense to describe what happens for 0, 1, 2 ...6
> i.e. what the different set-ups are.

Yeah, so how much of table 11-1 does it make sense to write out.
Certainly I can list how GPIO0-63 are mapped to pins for each of the 7
signal groups, but should I also list LCD, ethernet, interconnect,
mipi etc. for each of the 7 signal groups?

> Actually this is what we call group-based pin multiplexing in Linux,
> this property seems to avoid using that concept.
> See for example:
> Documentation/devicetree/bindings/pinctrl/cortina,gemini-pinctrl.txt

I don't think this is the same, but hope you can tell me after reading
the description above.

> > +    patternProperties:
> > +      '-pins*$':
> > +        type: object
> > +        description: |
> > +          A pinctrl node should contain at least one subnode representing the
> > +          pinctrl groups available on the machine. Each subnode will list the
> > +          pins it needs, and how they should be configured, with regard to
> > +          muxer configuration, bias, input enable/disable, input schmitt
> > +          trigger enable/disable, slew-rate and drive strength.
> > +        $ref: "/schemas/pinctrl/pincfg-node.yaml"
>
> Nice that you use pincfg-node.yaml
>
> > +        properties:
> > +          pins:
> > +            description: |
> > +              The list of pin identifiers that properties in the node apply to.
> > +              This should be set using either the PAD_GPIO or PAD_FUNC_SHARE
> > +              macro. Either this or "pinmux" has to be specified.
> > +
> > +          pinmux:
> > +            description: |
> > +              The list of GPIO identifiers and their mux settings that
> > +              properties in the node apply to. This should be set using the
> > +              GPIOMUX macro. Either this or "pins" has to be specified.
>
> What about referencing
> Documentation/devicetree/bindings/pinctrl/pinmux-node.yaml
> for this?

Sure. You just mean adding $ref: like above right?

Thanks!
/Emil

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 12/16] pinctrl: starfive: Add pinctrl driver for StarFive SoCs
  2021-10-24  9:29             ` Emil Renner Berthing
@ 2021-10-25 10:15               ` Andy Shevchenko
  -1 siblings, 0 replies; 143+ messages in thread
From: Andy Shevchenko @ 2021-10-25 10:15 UTC (permalink / raw)
  To: Emil Renner Berthing
  Cc: linux-riscv, devicetree, linux-clk, open list:GPIO SUBSYSTEM,
	open list:SERIAL DRIVERS, Palmer Dabbelt, Paul Walmsley,
	Rob Herring, Michael Turquette, Stephen Boyd, Thomas Gleixner,
	Marc Zyngier, Philipp Zabel, Linus Walleij, Greg Kroah-Hartman,
	Daniel Lezcano, Andy Shevchenko, Jiri Slaby, Maximilian Luz,
	Sagar Kadam, Drew Fustini, Geert Uytterhoeven, Michael Zhu,
	Fu Wei, Anup Patel, Atish Patra, Matteo Croce,
	Linux Kernel Mailing List, Huan Feng

On Sun, Oct 24, 2021 at 12:29 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> On Sat, 23 Oct 2021 at 23:02, Emil Renner Berthing <kernel@esmil.dk> wrote:
> > On Sat, 23 Oct 2021 at 22:29, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > > On Sat, Oct 23, 2021 at 9:46 PM Emil Renner Berthing <kernel@esmil.dk> wrote:

...

> > So is that a yes or a no to my question? It's not clear to me.
>
> I see now that you've probably misunderstood what the code does. It's
> not one time use. The function parses the device tree and dynamically
> registers groups and functions with the pinctrl framework. Each group
> needs a string name, an int array of pins and optionally the pinmux
> data. Once the group is registered those pieces of data needs to live
> with the group until the drive is unloaded. But if the device tree
> parsing fails before the group is registered then those allocations
> would never be referenced and just hang around as garbage until the
> driver is unloaded. In such cases fx. pinctrl-single uses devm_free to
> free them again.

Thank you for elaboration. Please, drop devm_*(). In this case it's
inappropriate to use it. pinctrl-single should be amended accordingly,
but it's out of scope here.

...

> > > > I such cases where you get conflicting PIN_CONFIG_BIAS_* settings I
> > > > don't see why it's better to do the rmw on the padctl register for the
> > > > first bias setting only to then change the bits again a few
> > > > microseconds later when the loop encounters the second bias setting.
> > > > After the loop is done the end result would still be just the last
> > > > bias setting.
> > >
> > > It could be bias X followed by something else followed by bias Y. You
> > > will write something else with bias Y. I admit I don't know this
> > > hardware and you and maintainers are supposed to decide what's better,
> > > but my guts are telling me that current algo is buggy.
> >
> > So there is only one padctl register pr. pin. I don't see why first
> > setting the bias bits to X, then setting some other bits, and then
> > setting the bias bits to Y would be different from just setting all
> > the bits in one go. Except for during that little microsecond window
> > during the loop that I actually think it's better to avoid.
>
> Maybe an example is in order. Suppose we get strong pull-up, drive
> strength 3 and pull-down config flags (the strong pull-up and pull
> down flags conflict) and the padctl value is 0x0c0 (pull-up, input and
> schmitt trigger enabled). With your solution of just altering the
> padctl bits immediately we'd call starfive_padctl_rmw 3 times in rapid
> succession like this:
>
> starfive_padctl_rmw(pin, 0x130, 0x100);
> starfive_padctl_rmw(pin, 0x007, 0x003);
> starfive_padctl_rmw(pin, 0x130, 0x010);
>
> ..and the end result would be 0x0d3, although the strong pull-up would
> be enabled for the microseconds between the 1st and 3nd call.
> As the code is now it'd just directly do
>
> starfive_padctl_rmw(pin, 0x137, 0x013)
>
> ..which again results in 0x0d3, only without the microsecond blink of
> the strong pull-up.

You missed the point. Hardware on the other end may behave well
differently in these two cases.

-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 12/16] pinctrl: starfive: Add pinctrl driver for StarFive SoCs
@ 2021-10-25 10:15               ` Andy Shevchenko
  0 siblings, 0 replies; 143+ messages in thread
From: Andy Shevchenko @ 2021-10-25 10:15 UTC (permalink / raw)
  To: Emil Renner Berthing
  Cc: linux-riscv, devicetree, linux-clk, open list:GPIO SUBSYSTEM,
	open list:SERIAL DRIVERS, Palmer Dabbelt, Paul Walmsley,
	Rob Herring, Michael Turquette, Stephen Boyd, Thomas Gleixner,
	Marc Zyngier, Philipp Zabel, Linus Walleij, Greg Kroah-Hartman,
	Daniel Lezcano, Andy Shevchenko, Jiri Slaby, Maximilian Luz,
	Sagar Kadam, Drew Fustini, Geert Uytterhoeven, Michael Zhu,
	Fu Wei, Anup Patel, Atish Patra, Matteo Croce,
	Linux Kernel Mailing List, Huan Feng

On Sun, Oct 24, 2021 at 12:29 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> On Sat, 23 Oct 2021 at 23:02, Emil Renner Berthing <kernel@esmil.dk> wrote:
> > On Sat, 23 Oct 2021 at 22:29, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > > On Sat, Oct 23, 2021 at 9:46 PM Emil Renner Berthing <kernel@esmil.dk> wrote:

...

> > So is that a yes or a no to my question? It's not clear to me.
>
> I see now that you've probably misunderstood what the code does. It's
> not one time use. The function parses the device tree and dynamically
> registers groups and functions with the pinctrl framework. Each group
> needs a string name, an int array of pins and optionally the pinmux
> data. Once the group is registered those pieces of data needs to live
> with the group until the drive is unloaded. But if the device tree
> parsing fails before the group is registered then those allocations
> would never be referenced and just hang around as garbage until the
> driver is unloaded. In such cases fx. pinctrl-single uses devm_free to
> free them again.

Thank you for elaboration. Please, drop devm_*(). In this case it's
inappropriate to use it. pinctrl-single should be amended accordingly,
but it's out of scope here.

...

> > > > I such cases where you get conflicting PIN_CONFIG_BIAS_* settings I
> > > > don't see why it's better to do the rmw on the padctl register for the
> > > > first bias setting only to then change the bits again a few
> > > > microseconds later when the loop encounters the second bias setting.
> > > > After the loop is done the end result would still be just the last
> > > > bias setting.
> > >
> > > It could be bias X followed by something else followed by bias Y. You
> > > will write something else with bias Y. I admit I don't know this
> > > hardware and you and maintainers are supposed to decide what's better,
> > > but my guts are telling me that current algo is buggy.
> >
> > So there is only one padctl register pr. pin. I don't see why first
> > setting the bias bits to X, then setting some other bits, and then
> > setting the bias bits to Y would be different from just setting all
> > the bits in one go. Except for during that little microsecond window
> > during the loop that I actually think it's better to avoid.
>
> Maybe an example is in order. Suppose we get strong pull-up, drive
> strength 3 and pull-down config flags (the strong pull-up and pull
> down flags conflict) and the padctl value is 0x0c0 (pull-up, input and
> schmitt trigger enabled). With your solution of just altering the
> padctl bits immediately we'd call starfive_padctl_rmw 3 times in rapid
> succession like this:
>
> starfive_padctl_rmw(pin, 0x130, 0x100);
> starfive_padctl_rmw(pin, 0x007, 0x003);
> starfive_padctl_rmw(pin, 0x130, 0x010);
>
> ..and the end result would be 0x0d3, although the strong pull-up would
> be enabled for the microseconds between the 1st and 3nd call.
> As the code is now it'd just directly do
>
> starfive_padctl_rmw(pin, 0x137, 0x013)
>
> ..which again results in 0x0d3, only without the microsecond blink of
> the strong pull-up.

You missed the point. Hardware on the other end may behave well
differently in these two cases.

-- 
With Best Regards,
Andy Shevchenko

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 12/16] pinctrl: starfive: Add pinctrl driver for StarFive SoCs
  2021-10-25 10:15               ` Andy Shevchenko
@ 2021-10-25 10:24                 ` Emil Renner Berthing
  -1 siblings, 0 replies; 143+ messages in thread
From: Emil Renner Berthing @ 2021-10-25 10:24 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: linux-riscv, devicetree, linux-clk, open list:GPIO SUBSYSTEM,
	open list:SERIAL DRIVERS, Palmer Dabbelt, Paul Walmsley,
	Rob Herring, Michael Turquette, Stephen Boyd, Thomas Gleixner,
	Marc Zyngier, Philipp Zabel, Linus Walleij, Greg Kroah-Hartman,
	Daniel Lezcano, Andy Shevchenko, Jiri Slaby, Maximilian Luz,
	Sagar Kadam, Drew Fustini, Geert Uytterhoeven, Michael Zhu,
	Fu Wei, Anup Patel, Atish Patra, Matteo Croce,
	Linux Kernel Mailing List, Huan Feng

On Mon, 25 Oct 2021 at 12:16, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> On Sun, Oct 24, 2021 at 12:29 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> > On Sat, 23 Oct 2021 at 23:02, Emil Renner Berthing <kernel@esmil.dk> wrote:
> > > On Sat, 23 Oct 2021 at 22:29, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > > > On Sat, Oct 23, 2021 at 9:46 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
>
> ...
>
> > > So is that a yes or a no to my question? It's not clear to me.
> >
> > I see now that you've probably misunderstood what the code does. It's
> > not one time use. The function parses the device tree and dynamically
> > registers groups and functions with the pinctrl framework. Each group
> > needs a string name, an int array of pins and optionally the pinmux
> > data. Once the group is registered those pieces of data needs to live
> > with the group until the drive is unloaded. But if the device tree
> > parsing fails before the group is registered then those allocations
> > would never be referenced and just hang around as garbage until the
> > driver is unloaded. In such cases fx. pinctrl-single uses devm_free to
> > free them again.
>
> Thank you for elaboration. Please, drop devm_*(). In this case it's
> inappropriate to use it. pinctrl-single should be amended accordingly,
> but it's out of scope here.
>
> ...
>
> > > > > I such cases where you get conflicting PIN_CONFIG_BIAS_* settings I
> > > > > don't see why it's better to do the rmw on the padctl register for the
> > > > > first bias setting only to then change the bits again a few
> > > > > microseconds later when the loop encounters the second bias setting.
> > > > > After the loop is done the end result would still be just the last
> > > > > bias setting.
> > > >
> > > > It could be bias X followed by something else followed by bias Y. You
> > > > will write something else with bias Y. I admit I don't know this
> > > > hardware and you and maintainers are supposed to decide what's better,
> > > > but my guts are telling me that current algo is buggy.
> > >
> > > So there is only one padctl register pr. pin. I don't see why first
> > > setting the bias bits to X, then setting some other bits, and then
> > > setting the bias bits to Y would be different from just setting all
> > > the bits in one go. Except for during that little microsecond window
> > > during the loop that I actually think it's better to avoid.
> >
> > Maybe an example is in order. Suppose we get strong pull-up, drive
> > strength 3 and pull-down config flags (the strong pull-up and pull
> > down flags conflict) and the padctl value is 0x0c0 (pull-up, input and
> > schmitt trigger enabled). With your solution of just altering the
> > padctl bits immediately we'd call starfive_padctl_rmw 3 times in rapid
> > succession like this:
> >
> > starfive_padctl_rmw(pin, 0x130, 0x100);
> > starfive_padctl_rmw(pin, 0x007, 0x003);
> > starfive_padctl_rmw(pin, 0x130, 0x010);
> >
> > ..and the end result would be 0x0d3, although the strong pull-up would
> > be enabled for the microseconds between the 1st and 3nd call.
> > As the code is now it'd just directly do
> >
> > starfive_padctl_rmw(pin, 0x137, 0x013)
> >
> > ..which again results in 0x0d3, only without the microsecond blink of
> > the strong pull-up.
>
> You missed the point. Hardware on the other end may behave well
> differently in these two cases.

Right, but that can never be an intended behaviour. Which of the
conflicting bias settings comes first and is blipped before the 2nd
remains entirely depends on how the pinctrl framework parses the
devicetree. I'd much rather have it cleanly go to just one of the
states, which might be the wrong one, but the conflicting bias
settings are wrong to begin with.

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 12/16] pinctrl: starfive: Add pinctrl driver for StarFive SoCs
@ 2021-10-25 10:24                 ` Emil Renner Berthing
  0 siblings, 0 replies; 143+ messages in thread
From: Emil Renner Berthing @ 2021-10-25 10:24 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: linux-riscv, devicetree, linux-clk, open list:GPIO SUBSYSTEM,
	open list:SERIAL DRIVERS, Palmer Dabbelt, Paul Walmsley,
	Rob Herring, Michael Turquette, Stephen Boyd, Thomas Gleixner,
	Marc Zyngier, Philipp Zabel, Linus Walleij, Greg Kroah-Hartman,
	Daniel Lezcano, Andy Shevchenko, Jiri Slaby, Maximilian Luz,
	Sagar Kadam, Drew Fustini, Geert Uytterhoeven, Michael Zhu,
	Fu Wei, Anup Patel, Atish Patra, Matteo Croce,
	Linux Kernel Mailing List, Huan Feng

On Mon, 25 Oct 2021 at 12:16, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> On Sun, Oct 24, 2021 at 12:29 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> > On Sat, 23 Oct 2021 at 23:02, Emil Renner Berthing <kernel@esmil.dk> wrote:
> > > On Sat, 23 Oct 2021 at 22:29, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > > > On Sat, Oct 23, 2021 at 9:46 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
>
> ...
>
> > > So is that a yes or a no to my question? It's not clear to me.
> >
> > I see now that you've probably misunderstood what the code does. It's
> > not one time use. The function parses the device tree and dynamically
> > registers groups and functions with the pinctrl framework. Each group
> > needs a string name, an int array of pins and optionally the pinmux
> > data. Once the group is registered those pieces of data needs to live
> > with the group until the drive is unloaded. But if the device tree
> > parsing fails before the group is registered then those allocations
> > would never be referenced and just hang around as garbage until the
> > driver is unloaded. In such cases fx. pinctrl-single uses devm_free to
> > free them again.
>
> Thank you for elaboration. Please, drop devm_*(). In this case it's
> inappropriate to use it. pinctrl-single should be amended accordingly,
> but it's out of scope here.
>
> ...
>
> > > > > I such cases where you get conflicting PIN_CONFIG_BIAS_* settings I
> > > > > don't see why it's better to do the rmw on the padctl register for the
> > > > > first bias setting only to then change the bits again a few
> > > > > microseconds later when the loop encounters the second bias setting.
> > > > > After the loop is done the end result would still be just the last
> > > > > bias setting.
> > > >
> > > > It could be bias X followed by something else followed by bias Y. You
> > > > will write something else with bias Y. I admit I don't know this
> > > > hardware and you and maintainers are supposed to decide what's better,
> > > > but my guts are telling me that current algo is buggy.
> > >
> > > So there is only one padctl register pr. pin. I don't see why first
> > > setting the bias bits to X, then setting some other bits, and then
> > > setting the bias bits to Y would be different from just setting all
> > > the bits in one go. Except for during that little microsecond window
> > > during the loop that I actually think it's better to avoid.
> >
> > Maybe an example is in order. Suppose we get strong pull-up, drive
> > strength 3 and pull-down config flags (the strong pull-up and pull
> > down flags conflict) and the padctl value is 0x0c0 (pull-up, input and
> > schmitt trigger enabled). With your solution of just altering the
> > padctl bits immediately we'd call starfive_padctl_rmw 3 times in rapid
> > succession like this:
> >
> > starfive_padctl_rmw(pin, 0x130, 0x100);
> > starfive_padctl_rmw(pin, 0x007, 0x003);
> > starfive_padctl_rmw(pin, 0x130, 0x010);
> >
> > ..and the end result would be 0x0d3, although the strong pull-up would
> > be enabled for the microseconds between the 1st and 3nd call.
> > As the code is now it'd just directly do
> >
> > starfive_padctl_rmw(pin, 0x137, 0x013)
> >
> > ..which again results in 0x0d3, only without the microsecond blink of
> > the strong pull-up.
>
> You missed the point. Hardware on the other end may behave well
> differently in these two cases.

Right, but that can never be an intended behaviour. Which of the
conflicting bias settings comes first and is blipped before the 2nd
remains entirely depends on how the pinctrl framework parses the
devicetree. I'd much rather have it cleanly go to just one of the
states, which might be the wrong one, but the conflicting bias
settings are wrong to begin with.

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 12/16] pinctrl: starfive: Add pinctrl driver for StarFive SoCs
  2021-10-25 10:24                 ` Emil Renner Berthing
@ 2021-10-25 10:51                   ` Andy Shevchenko
  -1 siblings, 0 replies; 143+ messages in thread
From: Andy Shevchenko @ 2021-10-25 10:51 UTC (permalink / raw)
  To: Emil Renner Berthing
  Cc: linux-riscv, devicetree, linux-clk, open list:GPIO SUBSYSTEM,
	open list:SERIAL DRIVERS, Palmer Dabbelt, Paul Walmsley,
	Rob Herring, Michael Turquette, Stephen Boyd, Thomas Gleixner,
	Marc Zyngier, Philipp Zabel, Linus Walleij, Greg Kroah-Hartman,
	Daniel Lezcano, Andy Shevchenko, Jiri Slaby, Maximilian Luz,
	Sagar Kadam, Drew Fustini, Geert Uytterhoeven, Michael Zhu,
	Fu Wei, Anup Patel, Atish Patra, Matteo Croce,
	Linux Kernel Mailing List, Huan Feng

On Mon, Oct 25, 2021 at 1:24 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> On Mon, 25 Oct 2021 at 12:16, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > On Sun, Oct 24, 2021 at 12:29 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> > > On Sat, 23 Oct 2021 at 23:02, Emil Renner Berthing <kernel@esmil.dk> wrote:
> > > > On Sat, 23 Oct 2021 at 22:29, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > > > > On Sat, Oct 23, 2021 at 9:46 PM Emil Renner Berthing <kernel@esmil.dk> wrote:

...

> > > > > > I such cases where you get conflicting PIN_CONFIG_BIAS_* settings I
> > > > > > don't see why it's better to do the rmw on the padctl register for the
> > > > > > first bias setting only to then change the bits again a few
> > > > > > microseconds later when the loop encounters the second bias setting.
> > > > > > After the loop is done the end result would still be just the last
> > > > > > bias setting.
> > > > >
> > > > > It could be bias X followed by something else followed by bias Y. You
> > > > > will write something else with bias Y. I admit I don't know this
> > > > > hardware and you and maintainers are supposed to decide what's better,
> > > > > but my guts are telling me that current algo is buggy.
> > > >
> > > > So there is only one padctl register pr. pin. I don't see why first
> > > > setting the bias bits to X, then setting some other bits, and then
> > > > setting the bias bits to Y would be different from just setting all
> > > > the bits in one go. Except for during that little microsecond window
> > > > during the loop that I actually think it's better to avoid.
> > >
> > > Maybe an example is in order. Suppose we get strong pull-up, drive
> > > strength 3 and pull-down config flags (the strong pull-up and pull
> > > down flags conflict) and the padctl value is 0x0c0 (pull-up, input and
> > > schmitt trigger enabled). With your solution of just altering the
> > > padctl bits immediately we'd call starfive_padctl_rmw 3 times in rapid
> > > succession like this:
> > >
> > > starfive_padctl_rmw(pin, 0x130, 0x100);
> > > starfive_padctl_rmw(pin, 0x007, 0x003);
> > > starfive_padctl_rmw(pin, 0x130, 0x010);
> > >
> > > ..and the end result would be 0x0d3, although the strong pull-up would
> > > be enabled for the microseconds between the 1st and 3nd call.
> > > As the code is now it'd just directly do
> > >
> > > starfive_padctl_rmw(pin, 0x137, 0x013)
> > >
> > > ..which again results in 0x0d3, only without the microsecond blink of
> > > the strong pull-up.
> >
> > You missed the point. Hardware on the other end may behave well
> > differently in these two cases.
>
> Right, but that can never be an intended behaviour. Which of the
> conflicting bias settings comes first and is blipped before the 2nd
> remains entirely depends on how the pinctrl framework parses the
> devicetree. I'd much rather have it cleanly go to just one of the
> states, which might be the wrong one, but the conflicting bias
> settings are wrong to begin with.

That's why I said that is up to you and maintainers and people who
know hardware better than me.

-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 12/16] pinctrl: starfive: Add pinctrl driver for StarFive SoCs
@ 2021-10-25 10:51                   ` Andy Shevchenko
  0 siblings, 0 replies; 143+ messages in thread
From: Andy Shevchenko @ 2021-10-25 10:51 UTC (permalink / raw)
  To: Emil Renner Berthing
  Cc: linux-riscv, devicetree, linux-clk, open list:GPIO SUBSYSTEM,
	open list:SERIAL DRIVERS, Palmer Dabbelt, Paul Walmsley,
	Rob Herring, Michael Turquette, Stephen Boyd, Thomas Gleixner,
	Marc Zyngier, Philipp Zabel, Linus Walleij, Greg Kroah-Hartman,
	Daniel Lezcano, Andy Shevchenko, Jiri Slaby, Maximilian Luz,
	Sagar Kadam, Drew Fustini, Geert Uytterhoeven, Michael Zhu,
	Fu Wei, Anup Patel, Atish Patra, Matteo Croce,
	Linux Kernel Mailing List, Huan Feng

On Mon, Oct 25, 2021 at 1:24 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> On Mon, 25 Oct 2021 at 12:16, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > On Sun, Oct 24, 2021 at 12:29 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> > > On Sat, 23 Oct 2021 at 23:02, Emil Renner Berthing <kernel@esmil.dk> wrote:
> > > > On Sat, 23 Oct 2021 at 22:29, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > > > > On Sat, Oct 23, 2021 at 9:46 PM Emil Renner Berthing <kernel@esmil.dk> wrote:

...

> > > > > > I such cases where you get conflicting PIN_CONFIG_BIAS_* settings I
> > > > > > don't see why it's better to do the rmw on the padctl register for the
> > > > > > first bias setting only to then change the bits again a few
> > > > > > microseconds later when the loop encounters the second bias setting.
> > > > > > After the loop is done the end result would still be just the last
> > > > > > bias setting.
> > > > >
> > > > > It could be bias X followed by something else followed by bias Y. You
> > > > > will write something else with bias Y. I admit I don't know this
> > > > > hardware and you and maintainers are supposed to decide what's better,
> > > > > but my guts are telling me that current algo is buggy.
> > > >
> > > > So there is only one padctl register pr. pin. I don't see why first
> > > > setting the bias bits to X, then setting some other bits, and then
> > > > setting the bias bits to Y would be different from just setting all
> > > > the bits in one go. Except for during that little microsecond window
> > > > during the loop that I actually think it's better to avoid.
> > >
> > > Maybe an example is in order. Suppose we get strong pull-up, drive
> > > strength 3 and pull-down config flags (the strong pull-up and pull
> > > down flags conflict) and the padctl value is 0x0c0 (pull-up, input and
> > > schmitt trigger enabled). With your solution of just altering the
> > > padctl bits immediately we'd call starfive_padctl_rmw 3 times in rapid
> > > succession like this:
> > >
> > > starfive_padctl_rmw(pin, 0x130, 0x100);
> > > starfive_padctl_rmw(pin, 0x007, 0x003);
> > > starfive_padctl_rmw(pin, 0x130, 0x010);
> > >
> > > ..and the end result would be 0x0d3, although the strong pull-up would
> > > be enabled for the microseconds between the 1st and 3nd call.
> > > As the code is now it'd just directly do
> > >
> > > starfive_padctl_rmw(pin, 0x137, 0x013)
> > >
> > > ..which again results in 0x0d3, only without the microsecond blink of
> > > the strong pull-up.
> >
> > You missed the point. Hardware on the other end may behave well
> > differently in these two cases.
>
> Right, but that can never be an intended behaviour. Which of the
> conflicting bias settings comes first and is blipped before the 2nd
> remains entirely depends on how the pinctrl framework parses the
> devicetree. I'd much rather have it cleanly go to just one of the
> states, which might be the wrong one, but the conflicting bias
> settings are wrong to begin with.

That's why I said that is up to you and maintainers and people who
know hardware better than me.

-- 
With Best Regards,
Andy Shevchenko

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 06/16] clk: starfive: Add JH7100 clock generator driver
  2021-10-21 17:42   ` Emil Renner Berthing
@ 2021-10-26 20:19     ` Stephen Boyd
  -1 siblings, 0 replies; 143+ messages in thread
From: Stephen Boyd @ 2021-10-26 20:19 UTC (permalink / raw)
  To: Emil Renner Berthing, devicetree, linux-clk, linux-gpio,
	linux-riscv, linux-serial
  Cc: Geert Uytterhoeven, Palmer Dabbelt, Paul Walmsley, Rob Herring,
	Michael Turquette, Thomas Gleixner, Marc Zyngier, Philipp Zabel,
	Linus Walleij, Greg Kroah-Hartman, Daniel Lezcano,
	Andy Shevchenko, Jiri Slaby, Maximilian Luz, Sagar Kadam,
	Drew Fustini, Michael Zhu, Fu Wei, Anup Patel, Atish Patra,
	Matteo Croce, linux-kernel, Emil Renner Berthing

Quoting Emil Renner Berthing (2021-10-21 10:42:13)
> diff --git a/drivers/clk/starfive/clk-starfive-jh7100.c b/drivers/clk/starfive/clk-starfive-jh7100.c
> new file mode 100644
> index 000000000000..f109576f18c5
> --- /dev/null
> +++ b/drivers/clk/starfive/clk-starfive-jh7100.c
> @@ -0,0 +1,776 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * StarFive JH7100 Clock Generator Driver
> + *
> + * Copyright 2021 Ahmad Fatoum, Pengutronix
> + * Copyright (C) 2021 Glider bv
> + * Copyright (C) 2021 Emil Renner Berthing <kernel@esmil.dk>
> + */
> +
> +#include <linux/bits.h>
> +#include <linux/clk.h>

Is this include used?

> +#include <linux/clk-provider.h>
> +#include <linux/debugfs.h>
> +#include <linux/device.h>
> +#include <linux/init.h>
> +#include <linux/io.h>
> +#include <linux/kernel.h>
> +#include <linux/mod_devicetable.h>
> +#include <linux/module.h>
> +#include <linux/overflow.h>

Is this include used?

> +#include <linux/platform_device.h>
> +
> +#include <dt-bindings/clock/starfive-jh7100.h>
> +
> +#define JH7100_CLK_ENABLE_SHIFT        31
> +#define JH7100_CLK_INVERT_SHIFT        30
> +#define JH7100_CLK_MUX_SHIFT   24
> +
> +#define JH7100_CLK_ENABLE      BIT(31)
> +#define JH7100_CLK_INVERT      BIT(30)
> +#define JH7100_CLK_MUX_MASK    GENMASK(27, 24)
> +#define JH7100_CLK_DIV_MASK    GENMASK(23, 0)
> +
> +static const char *const cpundbus_root_sels[] __initconst = {
> +       [0] = "osc_sys",
> +       [1] = "pll0_out",
> +       [2] = "pll1_out",
> +       [3] = "pll2_out",
> +};
> +
> +static const char *const dla_root_sels[] __initconst = {
> +       [0] = "osc_sys",
> +       [1] = "pll1_out",
> +       [2] = "pll2_out",
> +};
> +
> +static const char *const dsp_root_sels[] __initconst = {
> +       [0] = "osc_sys",
> +       [1] = "pll0_out",
> +       [2] = "pll1_out",
> +       [3] = "pll2_out",
> +};
> +
> +static const char *const gmacusb_root_sels[] __initconst = {
> +       [0] = "osc_sys",
> +       [1] = "pll0_out",
> +       [2] = "pll2_out",
> +};
> +
> +static const char *const perh0_root_sels[] __initconst = {
> +       [0] = "osc_sys",
> +       [1] = "pll0_out",
> +};
> +
> +static const char *const perh1_root_sels[] __initconst = {
> +       [0] = "osc_sys",
> +       [1] = "pll2_out",
> +};
> +
> +static const char *const vin_root_sels[] __initconst = {
> +       [0] = "osc_sys",
> +       [1] = "pll1_out",
> +       [2] = "pll2_out",
> +};
> +
> +static const char *const vout_root_sels[] __initconst = {
> +       [0] = "osc_aud",
> +       [1] = "pll0_out",
> +       [2] = "pll2_out",
> +};
> +
> +static const char *const cdechifi4_root_sels[] __initconst = {
> +       [0] = "osc_sys",
> +       [1] = "pll1_out",
> +       [2] = "pll2_out",
> +};
> +
> +static const char *const cdec_root_sels[] __initconst = {
> +       [0] = "osc_sys",
> +       [1] = "pll0_out",
> +       [2] = "pll1_out",
> +};
> +
> +static const char *const voutbus_root_sels[] __initconst = {
> +       [0] = "osc_aud",
> +       [1] = "pll0_out",
> +       [2] = "pll2_out",
> +};
> +
> +static const char *const pll2_refclk_sels[] __initconst = {
> +       [0] = "osc_sys",
> +       [1] = "osc_aud",
> +};
> +
> +static const char *const ddrc0_sels[] __initconst = {
> +       [0] = "ddrosc_div2",
> +       [1] = "ddrpll_div2",
> +       [2] = "ddrpll_div4",
> +       [3] = "ddrpll_div8",
> +};
> +
> +static const char *const ddrc1_sels[] __initconst = {
> +       [0] = "ddrosc_div2",
> +       [1] = "ddrpll_div2",
> +       [2] = "ddrpll_div4",
> +       [3] = "ddrpll_div8",
> +};
> +
> +static const char *const nne_bus_sels[] __initconst = {
> +       [0] = "cpu_axi",
> +       [1] = "nnebus_src1",
> +};
> +
> +static const char *const usbphy_25m_sels[] __initconst = {
> +       [0] = "osc_sys",
> +       [1] = "usbphy_plldiv25m",
> +};
> +
> +static const char *const gmac_tx_sels[] __initconst = {
> +       [0] = "gmac_gtxclk",
> +       [1] = "gmac_mii_txclk",
> +       [2] = "gmac_rmii_txclk",
> +};
> +
> +static const char *const gmac_rx_pre_sels[] __initconst = {
> +       [0] = "gmac_gr_mii_rxclk",
> +       [1] = "gmac_rmii_rxclk",
> +};
> +
> +struct jh7100_clk {
> +       struct clk_hw hw;
> +       unsigned int idx;
> +       u32 max;

Why u32?

> +};
> +
> +struct clk_starfive_jh7100_priv {
> +       /* protect registers against overlapping read-modify-write */
> +       spinlock_t rmw_lock;

Does overlapping mean concurrent? Do different clks share the same
registers?

> +       struct device *dev;
> +       void __iomem *base;
> +       struct clk_hw *pll[3];
> +       struct jh7100_clk reg[JH7100_CLK_PLL0_OUT];
> +};
> +
> +static struct jh7100_clk *jh7100_clk_from(struct clk_hw *hw)
> +{
> +       return container_of(hw, struct jh7100_clk, hw);
> +}
> +
> +static struct clk_starfive_jh7100_priv *jh7100_priv_from(struct jh7100_clk *clk)
> +{
> +       return container_of(clk, struct clk_starfive_jh7100_priv, reg[clk->idx]);
> +}
> +
> +static u32 jh7100_clk_reg_get(struct jh7100_clk *clk)
> +{
> +       struct clk_starfive_jh7100_priv *priv = jh7100_priv_from(clk);
> +       void __iomem *reg = priv->base + 4 * clk->idx;
> +
> +       return readl_relaxed(reg);
> +}
> +
> +static void jh7100_clk_reg_rmw(struct jh7100_clk *clk, u32 mask, u32 value)
> +{
> +       struct clk_starfive_jh7100_priv *priv = jh7100_priv_from(clk);
> +       void __iomem *reg = priv->base + 4 * clk->idx;
> +       unsigned long flags;
> +
> +       spin_lock_irqsave(&priv->rmw_lock, flags);
> +       value |= readl_relaxed(reg) & ~mask;
> +       writel_relaxed(value, reg);
> +       spin_unlock_irqrestore(&priv->rmw_lock, flags);
> +}
> +
> +static int jh7100_clk_enable(struct clk_hw *hw)
> +{
> +       struct jh7100_clk *clk = jh7100_clk_from(hw);
> +
> +       dev_dbg(jh7100_priv_from(clk)->dev, "enable(%s)\n", clk_hw_get_name(&clk->hw));
> +
> +       jh7100_clk_reg_rmw(clk, JH7100_CLK_ENABLE, JH7100_CLK_ENABLE);
> +       return 0;
> +}
> +
> +static void jh7100_clk_disable(struct clk_hw *hw)
> +{
> +       struct jh7100_clk *clk = jh7100_clk_from(hw);
> +
> +       dev_dbg(jh7100_priv_from(clk)->dev, "disable(%s)\n", clk_hw_get_name(&clk->hw));
> +
> +       jh7100_clk_reg_rmw(clk, JH7100_CLK_ENABLE, 0);
> +}
> +
> +static int jh7100_clk_is_enabled(struct clk_hw *hw)
> +{
> +       struct jh7100_clk *clk = jh7100_clk_from(hw);
> +
> +       return !!(jh7100_clk_reg_get(clk) & JH7100_CLK_ENABLE);
> +}
> +
> +static int jh7100_clk_is_parent_enabled(struct clk_hw *hw)
> +{
> +       return clk_hw_is_enabled(clk_hw_get_parent(hw));

Why do we need this function? The parent being enabled implies this clk
is enabled if this clk can't gate itself but then knowing this clk is
enabled is useful for what?

> +}
> +
> +static unsigned long jh7100_clk_recalc_rate(struct clk_hw *hw,
> +                                           unsigned long parent_rate)
> +{
> +       struct jh7100_clk *clk = jh7100_clk_from(hw);
> +       u32 value = jh7100_clk_reg_get(clk) & JH7100_CLK_DIV_MASK;
> +       unsigned long rate;
> +
> +       if (value)
> +               rate = parent_rate / value;
> +       else
> +               rate = 0;
> +
> +       dev_dbg(jh7100_priv_from(clk)->dev, "recalc_rate(%s, %lu) = %lu (div %u)\n",
> +               clk_hw_get_name(&clk->hw), parent_rate, rate, value);
> +
> +       return rate;
> +}
> +
> +static unsigned long jh7100_clk_bestdiv(struct jh7100_clk *clk,
> +                                       unsigned long rate, unsigned long parent)
> +{
> +       unsigned long max = clk->max & JH7100_CLK_DIV_MASK;
> +       unsigned long div = DIV_ROUND_UP(parent, rate);
> +
> +       return min(div, max);
> +}
> +
> +static int jh7100_clk_determine_rate(struct clk_hw *hw,
> +                                    struct clk_rate_request *req)
> +{
> +       struct jh7100_clk *clk = jh7100_clk_from(hw);
> +       unsigned long parent = req->best_parent_rate;
> +       unsigned long rate = clamp(req->rate, req->min_rate, req->max_rate);
> +       unsigned long div = jh7100_clk_bestdiv(clk, rate, parent);
> +       unsigned long result = parent / div;
> +
> +       /*
> +        * We want the result clamped by min_rate and max_rate if possible:
> +        * Case 1: div hits the max divider value, which means it's less than
> +        * parent / rate, so the result is greater than rate and min_rate in
> +        * particular. We can't do anything about result > max_rate because the
> +        * divider doesn't go any further.
> +        * Case 2: div = DIV_ROUND_UP(parent, rate) which means the result is
> +        * always lower or equal to rate and max_rate.  However the result may
> +        * turn out lower than min_rate, but then the next higher rate is fine:
> +        *   div - 1 = ceil(parent / rate) - 1 < parent / rate
> +        * and thus
> +        *   min_rate <= rate < parent / (div - 1)
> +        */
> +       if (result < req->min_rate && div > 1) {
> +               div -= 1;
> +               result = parent / div;
> +       }
> +
> +       dev_dbg(jh7100_priv_from(clk)->dev,
> +               "determine_rate(%s, {%lu<=%lu<=%lu from %lu}) = %lu (div %lu)\n",
> +               clk_hw_get_name(&clk->hw), req->min_rate, req->rate, req->max_rate,
> +               parent, result, div);
> +
> +       req->rate = result;
> +       return 0;
> +}
> +
> +static int jh7100_clk_set_rate(struct clk_hw *hw,
> +                              unsigned long rate,
> +                              unsigned long parent_rate)
> +{
> +       struct jh7100_clk *clk = jh7100_clk_from(hw);
> +       unsigned long div = jh7100_clk_bestdiv(clk, rate, parent_rate);
> +
> +       dev_dbg(jh7100_priv_from(clk)->dev,
> +               "set_rate(%s, %lu, %lu) = %lu (div %lu)\n",
> +               clk_hw_get_name(&clk->hw), rate, parent_rate,
> +               parent_rate / div, div);
> +
> +       jh7100_clk_reg_rmw(clk, JH7100_CLK_DIV_MASK, div);
> +       return 0;
> +}
> +
> +static u8 jh7100_clk_get_parent(struct clk_hw *hw)
> +{
> +       struct jh7100_clk *clk = jh7100_clk_from(hw);
> +       u32 value = jh7100_clk_reg_get(clk);
> +
> +       return (value & JH7100_CLK_MUX_MASK) >> JH7100_CLK_MUX_SHIFT;
> +}
> +
> +static int jh7100_clk_set_parent(struct clk_hw *hw, u8 index)
> +{
> +       struct jh7100_clk *clk = jh7100_clk_from(hw);
> +       u32 value = (u32)index << JH7100_CLK_MUX_SHIFT;
> +
> +       dev_dbg(jh7100_priv_from(clk)->dev, "set_parent(%s, %u)\n",
> +               clk_hw_get_name(&clk->hw), index);

Please remove these dev_dbg() messages. We have tracepoints for general
clk operations and the driver shouldn't duplicate that.

> +
> +       jh7100_clk_reg_rmw(clk, JH7100_CLK_MUX_MASK, value);
> +       return 0;
> +}
> +
> +static int jh7100_clk_mux_determine_rate(struct clk_hw *hw,
> +                                        struct clk_rate_request *req)
> +{
> +       struct jh7100_clk *clk = jh7100_clk_from(hw);
> +       int ret = clk_mux_determine_rate_flags(&clk->hw, req, 0);
> +
> +       dev_dbg(jh7100_priv_from(clk)->dev, "determine_rate(%s) = %d\n",
> +               clk_hw_get_name(&clk->hw), ret);
> +
> +       return ret;
> +}
> +
> +static int jh7100_clk_get_phase(struct clk_hw *hw)
> +{
> +       struct jh7100_clk *clk = jh7100_clk_from(hw);
> +       u32 value = jh7100_clk_reg_get(clk);
> +
> +       return (value & JH7100_CLK_INVERT) ? 180 : 0;
> +}
> +
> +static int jh7100_clk_set_phase(struct clk_hw *hw, int degrees)
> +{
> +       struct jh7100_clk *clk = jh7100_clk_from(hw);
> +       u32 value;
> +
> +       dev_dbg(jh7100_priv_from(clk)->dev, "set_phase(%s, %d)\n",
> +               clk_hw_get_name(&clk->hw), degrees);
> +
> +       if (degrees == 0)
> +               value = 0;
> +       else if (degrees == 180)
> +               value = JH7100_CLK_INVERT;
> +       else
> +               return -EINVAL;
> +
> +       jh7100_clk_reg_rmw(clk, JH7100_CLK_INVERT, value);
> +       return 0;
> +}
> +
> +#ifdef CONFIG_DEBUG_FS
> +static void jh7100_clk_debug_init(struct clk_hw *hw, struct dentry *dentry)
> +{
> +       static const struct debugfs_reg32 jh7100_clk_reg = {
> +               .name = "CTRL",
> +               .offset = 0,
> +       };
> +       struct jh7100_clk *clk = jh7100_clk_from(hw);
> +       struct clk_starfive_jh7100_priv *priv = jh7100_priv_from(clk);
> +       struct debugfs_regset32 *regset;
> +
> +       regset = devm_kzalloc(priv->dev, sizeof(*regset), GFP_KERNEL);
> +       if (!regset)
> +               return;
> +
> +       regset->regs = &jh7100_clk_reg;
> +       regset->nregs = 1;
> +       regset->base = priv->base + 4 * clk->idx;
> +
> +       debugfs_create_regset32("registers", 0400, dentry, regset);
> +}
> +#else
> +#define jh7100_clk_debug_init NULL
> +#endif
> +
> +static const struct clk_ops jh7100_clk_gate_ops = {
> +       .enable = jh7100_clk_enable,
> +       .disable = jh7100_clk_disable,
> +       .is_enabled = jh7100_clk_is_enabled,
> +       .debug_init = jh7100_clk_debug_init,
> +};
> +
> +static const struct clk_ops jh7100_clk_div_ops = {
> +       .is_enabled = jh7100_clk_is_parent_enabled,
> +       .recalc_rate = jh7100_clk_recalc_rate,
> +       .determine_rate = jh7100_clk_determine_rate,
> +       .set_rate = jh7100_clk_set_rate,
> +       .debug_init = jh7100_clk_debug_init,
> +};
> +
> +static const struct clk_ops jh7100_clk_gdiv_ops = {
> +       .enable = jh7100_clk_enable,
> +       .disable = jh7100_clk_disable,
> +       .is_enabled = jh7100_clk_is_enabled,
> +       .recalc_rate = jh7100_clk_recalc_rate,
> +       .determine_rate = jh7100_clk_determine_rate,
> +       .set_rate = jh7100_clk_set_rate,
> +       .debug_init = jh7100_clk_debug_init,
> +};
> +
> +static const struct clk_ops jh7100_clk_mux_ops = {
> +       .is_enabled = jh7100_clk_is_parent_enabled,
> +       .get_parent = jh7100_clk_get_parent,
> +       .set_parent = jh7100_clk_set_parent,
> +       .determine_rate = jh7100_clk_mux_determine_rate,
> +       .debug_init = jh7100_clk_debug_init,
> +};
> +
> +static const struct clk_ops jh7100_clk_gmux_ops = {
> +       .enable = jh7100_clk_enable,
> +       .disable = jh7100_clk_disable,
> +       .is_enabled = jh7100_clk_is_enabled,
> +       .get_parent = jh7100_clk_get_parent,
> +       .set_parent = jh7100_clk_set_parent,
> +       .determine_rate = jh7100_clk_mux_determine_rate,
> +       .debug_init = jh7100_clk_debug_init,
> +};
> +
> +static const struct clk_ops jh7100_clk_inv_ops = {
> +       .is_enabled = jh7100_clk_is_parent_enabled,
> +       .get_phase = jh7100_clk_get_phase,
> +       .set_phase = jh7100_clk_set_phase,
> +       .debug_init = jh7100_clk_debug_init,
> +};
> +
> +#define JH7100_GATE(_idx, _name, _parent, _flags) [_idx] = { \

Typical macro style is to tab out the \ to a single column

> +       .name = _name, \
> +       .ops = &jh7100_clk_gate_ops, \
> +       .parent = _parent, \
> +       .flags = CLK_SET_RATE_PARENT | (_flags), \
> +       .max = JH7100_CLK_ENABLE, \
> +}
> +
> +#define JH7100__DIV(_idx, _name, _parent, _max) [_idx] = { \
> +       .name = _name, \
> +       .ops = &jh7100_clk_div_ops, \
> +       .parent = _parent, \
> +       .flags = 0, \
> +       .max = _max, \
> +}
> +
> +#define JH7100_GDIV(_idx, _name, _parent, _max, _flags) [_idx] = { \
> +       .name = _name, \
> +       .ops = &jh7100_clk_gdiv_ops, \
> +       .parent = _parent, \
> +       .flags = (_flags), \
> +       .max = JH7100_CLK_ENABLE | (_max), \
> +}
> +
> +#define JH7100__MUX(_idx, _name, _parents) [_idx] = { \
> +       .name = _name, \
> +       .ops = &jh7100_clk_mux_ops, \
> +       .parents = _parents, \
> +       .flags = 0, \
> +       .max = (ARRAY_SIZE(_parents) - 1) << JH7100_CLK_MUX_SHIFT, \
> +}
> +
> +#define JH7100_GMUX(_idx, _name, _parents, _flags) [_idx] = { \
> +       .name = _name, \
> +       .ops = &jh7100_clk_gmux_ops, \
> +       .parents = _parents, \
> +       .flags = (_flags), \
> +       .max = JH7100_CLK_ENABLE | \
> +               ((ARRAY_SIZE(_parents) - 1) << JH7100_CLK_MUX_SHIFT), \
> +}
> +
> +#define JH7100__INV(_idx, _name, _parent) [_idx] = { \
> +       .name = _name, \
> +       .ops = &jh7100_clk_inv_ops, \
> +       .parent = _parent, \
> +       .flags = CLK_SET_RATE_PARENT, \
> +       .max = JH7100_CLK_INVERT, \
> +}
> +
> +static const struct {
> +       const char *name;
> +       const struct clk_ops *ops;
> +       union {
> +               const char *parent;
> +               const char *const *parents;
> +       };
> +       unsigned long flags;
> +       u32 max;
> +} jh7100_clk_data[] __initconst = {
> +       JH7100__MUX(JH7100_CLK_CPUNDBUS_ROOT, "cpundbus_root", cpundbus_root_sels),
> +       JH7100__MUX(JH7100_CLK_DLA_ROOT, "dla_root", dla_root_sels),
> +       JH7100__MUX(JH7100_CLK_DSP_ROOT, "dsp_root", dsp_root_sels),
> +       JH7100__MUX(JH7100_CLK_GMACUSB_ROOT, "gmacusb_root", gmacusb_root_sels),
> +       JH7100__MUX(JH7100_CLK_PERH0_ROOT, "perh0_root", perh0_root_sels),
> +       JH7100__MUX(JH7100_CLK_PERH1_ROOT, "perh1_root", perh1_root_sels),
> +       JH7100__MUX(JH7100_CLK_VIN_ROOT, "vin_root", vin_root_sels),
> +       JH7100__MUX(JH7100_CLK_VOUT_ROOT, "vout_root", vout_root_sels),
> +       JH7100_GDIV(JH7100_CLK_AUDIO_ROOT, "audio_root", "pll0_out", 8, 0),
> +       JH7100__MUX(JH7100_CLK_CDECHIFI4_ROOT, "cdechifi4_root", cdechifi4_root_sels),
> +       JH7100__MUX(JH7100_CLK_CDEC_ROOT, "cdec_root", cdec_root_sels),
> +       JH7100__MUX(JH7100_CLK_VOUTBUS_ROOT, "voutbus_root", voutbus_root_sels),
> +       JH7100__DIV(JH7100_CLK_CPUNBUS_ROOT_DIV, "cpunbus_root_div", "cpundbus_root", 2),
> +       JH7100__DIV(JH7100_CLK_DSP_ROOT_DIV, "dsp_root_div", "dsp_root", 4),
> +       JH7100__DIV(JH7100_CLK_PERH0_SRC, "perh0_src", "perh0_root", 4),
> +       JH7100__DIV(JH7100_CLK_PERH1_SRC, "perh1_src", "perh1_root", 4),
> +       JH7100_GDIV(JH7100_CLK_PLL0_TESTOUT, "pll0_testout", "perh0_src", 31, 0),
> +       JH7100_GDIV(JH7100_CLK_PLL1_TESTOUT, "pll1_testout", "dla_root", 31, 0),
> +       JH7100_GDIV(JH7100_CLK_PLL2_TESTOUT, "pll2_testout", "perh1_src", 31, 0),
> +       JH7100__MUX(JH7100_CLK_PLL2_REF, "pll2_refclk", pll2_refclk_sels),
> +       JH7100__DIV(JH7100_CLK_CPU_CORE, "cpu_core", "cpunbus_root_div", 8),
> +       JH7100__DIV(JH7100_CLK_CPU_AXI, "cpu_axi", "cpu_core", 8),
> +       JH7100__DIV(JH7100_CLK_AHB_BUS, "ahb_bus", "cpunbus_root_div", 8),
> +       JH7100__DIV(JH7100_CLK_APB1_BUS, "apb1_bus", "ahb_bus", 8),
> +       JH7100__DIV(JH7100_CLK_APB2_BUS, "apb2_bus", "ahb_bus", 8),
> +       JH7100_GATE(JH7100_CLK_DOM3AHB_BUS, "dom3ahb_bus", "ahb_bus", CLK_IGNORE_UNUSED),
> +       JH7100_GATE(JH7100_CLK_DOM7AHB_BUS, "dom7ahb_bus", "ahb_bus", CLK_IGNORE_UNUSED),
> +       JH7100_GATE(JH7100_CLK_U74_CORE0, "u74_core0", "cpu_core", CLK_IGNORE_UNUSED),
> +       JH7100_GDIV(JH7100_CLK_U74_CORE1, "u74_core1", "cpu_core", 8, CLK_IGNORE_UNUSED),
> +       JH7100_GATE(JH7100_CLK_U74_AXI, "u74_axi", "cpu_axi", CLK_IGNORE_UNUSED),
> +       JH7100_GATE(JH7100_CLK_U74RTC_TOGGLE, "u74rtc_toggle", "osc_sys", CLK_IGNORE_UNUSED),
> +       JH7100_GATE(JH7100_CLK_SGDMA2P_AXI, "sgdma2p_axi", "cpu_axi", 0),
> +       JH7100_GATE(JH7100_CLK_DMA2PNOC_AXI, "dma2pnoc_axi", "cpu_axi", 0),
> +       JH7100_GATE(JH7100_CLK_SGDMA2P_AHB, "sgdma2p_ahb", "ahb_bus", 0),
> +       JH7100__DIV(JH7100_CLK_DLA_BUS, "dla_bus", "dla_root", 4),
> +       JH7100_GATE(JH7100_CLK_DLA_AXI, "dla_axi", "dla_bus", 0),
> +       JH7100_GATE(JH7100_CLK_DLANOC_AXI, "dlanoc_axi", "dla_bus", 0),
> +       JH7100_GATE(JH7100_CLK_DLA_APB, "dla_apb", "apb1_bus", 0),
> +       JH7100_GDIV(JH7100_CLK_VP6_CORE, "vp6_core", "dsp_root_div", 4, 0),
> +       JH7100__DIV(JH7100_CLK_VP6BUS_SRC, "vp6bus_src", "dsp_root", 4),
> +       JH7100_GDIV(JH7100_CLK_VP6_AXI, "vp6_axi", "vp6bus_src", 4, 0),
> +       JH7100__DIV(JH7100_CLK_VCDECBUS_SRC, "vcdecbus_src", "cdechifi4_root", 4),
> +       JH7100__DIV(JH7100_CLK_VDEC_BUS, "vdec_bus", "vcdecbus_src", 8),
> +       JH7100_GATE(JH7100_CLK_VDEC_AXI, "vdec_axi", "vdec_bus", 0),
> +       JH7100_GATE(JH7100_CLK_VDECBRG_MAIN, "vdecbrg_mainclk", "vdec_bus", 0),
> +       JH7100_GDIV(JH7100_CLK_VDEC_BCLK, "vdec_bclk", "vcdecbus_src", 8, 0),
> +       JH7100_GDIV(JH7100_CLK_VDEC_CCLK, "vdec_cclk", "cdec_root", 8, 0),
> +       JH7100_GATE(JH7100_CLK_VDEC_APB, "vdec_apb", "apb1_bus", 0),
> +       JH7100_GDIV(JH7100_CLK_JPEG_AXI, "jpeg_axi", "cpunbus_root_div", 8, 0),
> +       JH7100_GDIV(JH7100_CLK_JPEG_CCLK, "jpeg_cclk", "cpunbus_root_div", 8, 0),
> +       JH7100_GATE(JH7100_CLK_JPEG_APB, "jpeg_apb", "apb1_bus", 0),
> +       JH7100_GDIV(JH7100_CLK_GC300_2X, "gc300_2x", "cdechifi4_root", 8, 0),
> +       JH7100_GATE(JH7100_CLK_GC300_AHB, "gc300_ahb", "ahb_bus", 0),
> +       JH7100__DIV(JH7100_CLK_JPCGC300_AXIBUS, "jpcgc300_axibus", "vcdecbus_src", 8),
> +       JH7100_GATE(JH7100_CLK_GC300_AXI, "gc300_axi", "jpcgc300_axibus", 0),
> +       JH7100_GATE(JH7100_CLK_JPCGC300_MAIN, "jpcgc300_mainclk", "jpcgc300_axibus", 0),
> +       JH7100__DIV(JH7100_CLK_VENC_BUS, "venc_bus", "vcdecbus_src", 8),
> +       JH7100_GATE(JH7100_CLK_VENC_AXI, "venc_axi", "venc_bus", 0),
> +       JH7100_GATE(JH7100_CLK_VENCBRG_MAIN, "vencbrg_mainclk", "venc_bus", 0),
> +       JH7100_GDIV(JH7100_CLK_VENC_BCLK, "venc_bclk", "vcdecbus_src", 8, 0),
> +       JH7100_GDIV(JH7100_CLK_VENC_CCLK, "venc_cclk", "cdec_root", 8, 0),
> +       JH7100_GATE(JH7100_CLK_VENC_APB, "venc_apb", "apb1_bus", 0),
> +       JH7100_GDIV(JH7100_CLK_DDRPLL_DIV2, "ddrpll_div2", "pll1_out", 2, CLK_IGNORE_UNUSED),
> +       JH7100_GDIV(JH7100_CLK_DDRPLL_DIV4, "ddrpll_div4", "ddrpll_div2", 2, CLK_IGNORE_UNUSED),
> +       JH7100_GDIV(JH7100_CLK_DDRPLL_DIV8, "ddrpll_div8", "ddrpll_div4", 2, CLK_IGNORE_UNUSED),
> +       JH7100_GDIV(JH7100_CLK_DDROSC_DIV2, "ddrosc_div2", "osc_sys", 2, CLK_IGNORE_UNUSED),
> +       JH7100_GMUX(JH7100_CLK_DDRC0, "ddrc0", ddrc0_sels, CLK_IGNORE_UNUSED),
> +       JH7100_GMUX(JH7100_CLK_DDRC1, "ddrc1", ddrc1_sels, CLK_IGNORE_UNUSED),

Is it really unused? Or it is CLK_IS_CRITICAL?

> +       JH7100_GATE(JH7100_CLK_DDRPHY_APB, "ddrphy_apb", "apb1_bus", CLK_IGNORE_UNUSED),
> +       JH7100__DIV(JH7100_CLK_NOC_ROB, "noc_rob", "cpunbus_root_div", 8),
> +       JH7100__DIV(JH7100_CLK_NOC_COG, "noc_cog", "dla_root", 8),
> +       JH7100_GATE(JH7100_CLK_NNE_AHB, "nne_ahb", "ahb_bus", 0),
> +       JH7100__DIV(JH7100_CLK_NNEBUS_SRC1, "nnebus_src1", "dsp_root", 4),
> +       JH7100__MUX(JH7100_CLK_NNE_BUS, "nne_bus", nne_bus_sels),
> +       JH7100_GATE(JH7100_CLK_NNE_AXI, "nne_axi", "nne_bus", 0),
> +       JH7100_GATE(JH7100_CLK_NNENOC_AXI, "nnenoc_axi", "nne_bus", 0),
> +       JH7100_GATE(JH7100_CLK_DLASLV_AXI, "dlaslv_axi", "nne_bus", 0),
> +       JH7100_GATE(JH7100_CLK_DSPX2C_AXI, "dspx2c_axi", "nne_bus", CLK_IGNORE_UNUSED),
> +       JH7100__DIV(JH7100_CLK_HIFI4_SRC, "hifi4_src", "cdechifi4_root", 4),
> +       JH7100__DIV(JH7100_CLK_HIFI4_COREFREE, "hifi4_corefree", "hifi4_src", 8),
> +       JH7100_GATE(JH7100_CLK_HIFI4_CORE, "hifi4_core", "hifi4_corefree", 0),
> +       JH7100__DIV(JH7100_CLK_HIFI4_BUS, "hifi4_bus", "hifi4_corefree", 8),
> +       JH7100_GATE(JH7100_CLK_HIFI4_AXI, "hifi4_axi", "hifi4_bus", 0),
> +       JH7100_GATE(JH7100_CLK_HIFI4NOC_AXI, "hifi4noc_axi", "hifi4_bus", 0),
> +       JH7100__DIV(JH7100_CLK_SGDMA1P_BUS, "sgdma1p_bus", "cpunbus_root_div", 8),
> +       JH7100_GATE(JH7100_CLK_SGDMA1P_AXI, "sgdma1p_axi", "sgdma1p_bus", 0),
> +       JH7100_GATE(JH7100_CLK_DMA1P_AXI, "dma1p_axi", "sgdma1p_bus", 0),
> +       JH7100_GDIV(JH7100_CLK_X2C_AXI, "x2c_axi", "cpunbus_root_div", 8, CLK_IGNORE_UNUSED),
> +       JH7100__DIV(JH7100_CLK_USB_BUS, "usb_bus", "cpunbus_root_div", 8),
> +       JH7100_GATE(JH7100_CLK_USB_AXI, "usb_axi", "usb_bus", 0),
> +       JH7100_GATE(JH7100_CLK_USBNOC_AXI, "usbnoc_axi", "usb_bus", 0),
> +       JH7100__DIV(JH7100_CLK_USBPHY_ROOTDIV, "usbphy_rootdiv", "gmacusb_root", 4),
> +       JH7100_GDIV(JH7100_CLK_USBPHY_125M, "usbphy_125m", "usbphy_rootdiv", 8, 0),
> +       JH7100_GDIV(JH7100_CLK_USBPHY_PLLDIV25M, "usbphy_plldiv25m", "usbphy_rootdiv", 32, 0),
> +       JH7100__MUX(JH7100_CLK_USBPHY_25M, "usbphy_25m", usbphy_25m_sels),
> +       JH7100__DIV(JH7100_CLK_AUDIO_DIV, "audio_div", "audio_root", 131072),
> +       JH7100_GATE(JH7100_CLK_AUDIO_SRC, "audio_src", "audio_div", 0),
> +       JH7100_GATE(JH7100_CLK_AUDIO_12288, "audio_12288", "osc_aud", 0),
> +       JH7100_GDIV(JH7100_CLK_VIN_SRC, "vin_src", "vin_root", 4, 0),
> +       JH7100__DIV(JH7100_CLK_ISP0_BUS, "isp0_bus", "vin_src", 8),
> +       JH7100_GATE(JH7100_CLK_ISP0_AXI, "isp0_axi", "isp0_bus", 0),
> +       JH7100_GATE(JH7100_CLK_ISP0NOC_AXI, "isp0noc_axi", "isp0_bus", 0),
> +       JH7100_GATE(JH7100_CLK_ISPSLV_AXI, "ispslv_axi", "isp0_bus", 0),
> +       JH7100__DIV(JH7100_CLK_ISP1_BUS, "isp1_bus", "vin_src", 8),
> +       JH7100_GATE(JH7100_CLK_ISP1_AXI, "isp1_axi", "isp1_bus", 0),
> +       JH7100_GATE(JH7100_CLK_ISP1NOC_AXI, "isp1noc_axi", "isp1_bus", 0),
> +       JH7100__DIV(JH7100_CLK_VIN_BUS, "vin_bus", "vin_src", 8),
> +       JH7100_GATE(JH7100_CLK_VIN_AXI, "vin_axi", "vin_bus", 0),
> +       JH7100_GATE(JH7100_CLK_VINNOC_AXI, "vinnoc_axi", "vin_bus", 0),
> +       JH7100_GDIV(JH7100_CLK_VOUT_SRC, "vout_src", "vout_root", 4, 0),
> +       JH7100__DIV(JH7100_CLK_DISPBUS_SRC, "dispbus_src", "voutbus_root", 4),
> +       JH7100__DIV(JH7100_CLK_DISP_BUS, "disp_bus", "dispbus_src", 4),
> +       JH7100_GATE(JH7100_CLK_DISP_AXI, "disp_axi", "disp_bus", 0),
> +       JH7100_GATE(JH7100_CLK_DISPNOC_AXI, "dispnoc_axi", "disp_bus", 0),
> +       JH7100_GATE(JH7100_CLK_SDIO0_AHB, "sdio0_ahb", "ahb_bus", 0),
> +       JH7100_GDIV(JH7100_CLK_SDIO0_CCLKINT, "sdio0_cclkint", "perh0_src", 24, 0),
> +       JH7100__INV(JH7100_CLK_SDIO0_CCLKINT_INV, "sdio0_cclkint_inv", "sdio0_cclkint"),
> +       JH7100_GATE(JH7100_CLK_SDIO1_AHB, "sdio1_ahb", "ahb_bus", 0),
> +       JH7100_GDIV(JH7100_CLK_SDIO1_CCLKINT, "sdio1_cclkint", "perh1_src", 24, 0),
> +       JH7100__INV(JH7100_CLK_SDIO1_CCLKINT_INV, "sdio1_cclkint_inv", "sdio1_cclkint"),
> +       JH7100_GATE(JH7100_CLK_GMAC_AHB, "gmac_ahb", "ahb_bus", 0),
> +       JH7100__DIV(JH7100_CLK_GMAC_ROOT_DIV, "gmac_root_div", "gmacusb_root", 8),
> +       JH7100_GDIV(JH7100_CLK_GMAC_PTP_REF, "gmac_ptp_refclk", "gmac_root_div", 31, 0),
> +       JH7100_GDIV(JH7100_CLK_GMAC_GTX, "gmac_gtxclk", "gmac_root_div", 255, 0),
> +       JH7100_GDIV(JH7100_CLK_GMAC_RMII_TX, "gmac_rmii_txclk", "gmac_rmii_ref", 8, 0),
> +       JH7100_GDIV(JH7100_CLK_GMAC_RMII_RX, "gmac_rmii_rxclk", "gmac_rmii_ref", 8, 0),
> +       JH7100__MUX(JH7100_CLK_GMAC_TX, "gmac_tx", gmac_tx_sels),
> +       JH7100__INV(JH7100_CLK_GMAC_TX_INV, "gmac_tx_inv", "gmac_tx"),
> +       JH7100__MUX(JH7100_CLK_GMAC_RX_PRE, "gmac_rx_pre", gmac_rx_pre_sels),
> +       JH7100__INV(JH7100_CLK_GMAC_RX_INV, "gmac_rx_inv", "gmac_rx_pre"),
> +       JH7100_GATE(JH7100_CLK_GMAC_RMII, "gmac_rmii", "gmac_rmii_ref", 0),
> +       JH7100_GDIV(JH7100_CLK_GMAC_TOPHYREF, "gmac_tophyref", "gmac_root_div", 127, 0),
> +       JH7100_GATE(JH7100_CLK_SPI2AHB_AHB, "spi2ahb_ahb", "ahb_bus", 0),
> +       JH7100_GDIV(JH7100_CLK_SPI2AHB_CORE, "spi2ahb_core", "perh0_src", 31, 0),
> +       JH7100_GATE(JH7100_CLK_EZMASTER_AHB, "ezmaster_ahb", "ahb_bus", 0),
> +       JH7100_GATE(JH7100_CLK_E24_AHB, "e24_ahb", "ahb_bus", 0),
> +       JH7100_GATE(JH7100_CLK_E24RTC_TOGGLE, "e24rtc_toggle", "osc_sys", 0),
> +       JH7100_GATE(JH7100_CLK_QSPI_AHB, "qspi_ahb", "ahb_bus", 0),
> +       JH7100_GATE(JH7100_CLK_QSPI_APB, "qspi_apb", "apb1_bus", 0),
> +       JH7100_GDIV(JH7100_CLK_QSPI_REF, "qspi_refclk", "perh0_src", 31, 0),
> +       JH7100_GATE(JH7100_CLK_SEC_AHB, "sec_ahb", "ahb_bus", 0),
> +       JH7100_GATE(JH7100_CLK_AES, "aes_clk", "sec_ahb", 0),
> +       JH7100_GATE(JH7100_CLK_SHA, "sha_clk", "sec_ahb", 0),
> +       JH7100_GATE(JH7100_CLK_PKA, "pka_clk", "sec_ahb", 0),
> +       JH7100_GATE(JH7100_CLK_TRNG_APB, "trng_apb", "apb1_bus", 0),
> +       JH7100_GATE(JH7100_CLK_OTP_APB, "otp_apb", "apb1_bus", 0),
> +       JH7100_GATE(JH7100_CLK_UART0_APB, "uart0_apb", "apb1_bus", 0),
> +       JH7100_GDIV(JH7100_CLK_UART0_CORE, "uart0_core", "perh1_src", 63, 0),
> +       JH7100_GATE(JH7100_CLK_UART1_APB, "uart1_apb", "apb1_bus", 0),
> +       JH7100_GDIV(JH7100_CLK_UART1_CORE, "uart1_core", "perh1_src", 63, 0),
> +       JH7100_GATE(JH7100_CLK_SPI0_APB, "spi0_apb", "apb1_bus", 0),
> +       JH7100_GDIV(JH7100_CLK_SPI0_CORE, "spi0_core", "perh1_src", 63, 0),
> +       JH7100_GATE(JH7100_CLK_SPI1_APB, "spi1_apb", "apb1_bus", 0),
> +       JH7100_GDIV(JH7100_CLK_SPI1_CORE, "spi1_core", "perh1_src", 63, 0),
> +       JH7100_GATE(JH7100_CLK_I2C0_APB, "i2c0_apb", "apb1_bus", 0),
> +       JH7100_GDIV(JH7100_CLK_I2C0_CORE, "i2c0_core", "perh1_src", 63, 0),
> +       JH7100_GATE(JH7100_CLK_I2C1_APB, "i2c1_apb", "apb1_bus", 0),
> +       JH7100_GDIV(JH7100_CLK_I2C1_CORE, "i2c1_core", "perh1_src", 63, 0),
> +       JH7100_GATE(JH7100_CLK_GPIO_APB, "gpio_apb", "apb1_bus", 0),
> +       JH7100_GATE(JH7100_CLK_UART2_APB, "uart2_apb", "apb2_bus", 0),
> +       JH7100_GDIV(JH7100_CLK_UART2_CORE, "uart2_core", "perh0_src", 63, 0),
> +       JH7100_GATE(JH7100_CLK_UART3_APB, "uart3_apb", "apb2_bus", 0),
> +       JH7100_GDIV(JH7100_CLK_UART3_CORE, "uart3_core", "perh0_src", 63, 0),
> +       JH7100_GATE(JH7100_CLK_SPI2_APB, "spi2_apb", "apb2_bus", 0),
> +       JH7100_GDIV(JH7100_CLK_SPI2_CORE, "spi2_core", "perh0_src", 63, 0),
> +       JH7100_GATE(JH7100_CLK_SPI3_APB, "spi3_apb", "apb2_bus", 0),
> +       JH7100_GDIV(JH7100_CLK_SPI3_CORE, "spi3_core", "perh0_src", 63, 0),
> +       JH7100_GATE(JH7100_CLK_I2C2_APB, "i2c2_apb", "apb2_bus", 0),
> +       JH7100_GDIV(JH7100_CLK_I2C2_CORE, "i2c2_core", "perh0_src", 63, 0),
> +       JH7100_GATE(JH7100_CLK_I2C3_APB, "i2c3_apb", "apb2_bus", 0),
> +       JH7100_GDIV(JH7100_CLK_I2C3_CORE, "i2c3_core", "perh0_src", 63, 0),
> +       JH7100_GATE(JH7100_CLK_WDTIMER_APB, "wdtimer_apb", "apb2_bus", 0),
> +       JH7100_GDIV(JH7100_CLK_WDT_CORE, "wdt_coreclk", "perh0_src", 63, 0),
> +       JH7100_GDIV(JH7100_CLK_TIMER0_CORE, "timer0_coreclk", "perh0_src", 63, 0),
> +       JH7100_GDIV(JH7100_CLK_TIMER1_CORE, "timer1_coreclk", "perh0_src", 63, 0),
> +       JH7100_GDIV(JH7100_CLK_TIMER2_CORE, "timer2_coreclk", "perh0_src", 63, 0),
> +       JH7100_GDIV(JH7100_CLK_TIMER3_CORE, "timer3_coreclk", "perh0_src", 63, 0),
> +       JH7100_GDIV(JH7100_CLK_TIMER4_CORE, "timer4_coreclk", "perh0_src", 63, 0),
> +       JH7100_GDIV(JH7100_CLK_TIMER5_CORE, "timer5_coreclk", "perh0_src", 63, 0),
> +       JH7100_GDIV(JH7100_CLK_TIMER6_CORE, "timer6_coreclk", "perh0_src", 63, 0),
> +       JH7100_GATE(JH7100_CLK_VP6INTC_APB, "vp6intc_apb", "apb2_bus", 0),
> +       JH7100_GATE(JH7100_CLK_PWM_APB, "pwm_apb", "apb2_bus", 0),
> +       JH7100_GATE(JH7100_CLK_MSI_APB, "msi_apb", "apb2_bus", 0),
> +       JH7100_GATE(JH7100_CLK_TEMP_APB, "temp_apb", "apb2_bus", 0),
> +       JH7100_GDIV(JH7100_CLK_TEMP_SENSE, "temp_sense", "osc_sys", 31, 0),
> +       JH7100_GATE(JH7100_CLK_SYSERR_APB, "syserr_apb", "apb2_bus", 0),
> +};
> +
> +static struct clk_hw *clk_starfive_jh7100_get(struct of_phandle_args *clkspec, void *data)
> +{
> +       struct clk_starfive_jh7100_priv *priv = data;
> +       unsigned int idx = clkspec->args[0];
> +
> +       if (idx >= JH7100_CLK_END) {
> +               dev_err(priv->dev, "invalid clock index %u\n", idx);

We should pull this sort of error message up into the core instead of
have it in every driver. It also doesn't look very meaningful to print
the name of the device that's providing the clks vs. the name of the
device that's requesting the clk that can't be found.

> +               return ERR_PTR(-EINVAL);
> +       }
> +
> +       if (idx >= JH7100_CLK_PLL0_OUT)
> +               return priv->pll[idx - JH7100_CLK_PLL0_OUT];
> +
> +       return &priv->reg[idx].hw;
> +}
> +
> +static int __init clk_starfive_jh7100_probe(struct platform_device *pdev)

Drop __init as this can be called after kernel init is over.

> +{
> +       struct clk_starfive_jh7100_priv *priv;
> +       unsigned int idx;
> +       int ret;
> +
> +       priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
> +       if (!priv)
> +               return -ENOMEM;
> +
> +       spin_lock_init(&priv->rmw_lock);
> +       priv->dev = &pdev->dev;
> +       priv->base = devm_platform_ioremap_resource(pdev, 0);
> +       if (IS_ERR(priv->base))
> +               return PTR_ERR(priv->base);
> +
> +       priv->pll[0] = devm_clk_hw_register_fixed_factor(priv->dev, "pll0_out",
> +                                                        "osc_sys", 0, 40, 1);
> +       if (IS_ERR(priv->pll[0]))
> +               return PTR_ERR(priv->pll[0]);
> +
> +       priv->pll[1] = devm_clk_hw_register_fixed_factor(priv->dev, "pll1_out",
> +                                                        "osc_sys", 0, 64, 1);
> +       if (IS_ERR(priv->pll[1]))
> +               return PTR_ERR(priv->pll[1]);
> +
> +       priv->pll[2] = devm_clk_hw_register_fixed_factor(priv->dev, "pll2_out",
> +                                                        "pll2_refclk", 0, 55, 1);
> +       if (IS_ERR(priv->pll[2]))
> +               return PTR_ERR(priv->pll[2]);
> +
> +       for (idx = 0; idx < JH7100_CLK_PLL0_OUT; idx++) {
> +               u32 max_parent = (jh7100_clk_data[idx].max & JH7100_CLK_MUX_MASK) >>
> +                                JH7100_CLK_MUX_SHIFT;
> +               struct clk_init_data init = {
> +                       .name = jh7100_clk_data[idx].name,
> +                       .ops = jh7100_clk_data[idx].ops,
> +                       .num_parents = max_parent + 1,
> +                       .flags = jh7100_clk_data[idx].flags,
> +               };
> +               struct jh7100_clk *clk = &priv->reg[idx];
> +
> +               if (init.num_parents > 1)
> +                       init.parent_names = jh7100_clk_data[idx].parents;
> +               else
> +                       init.parent_names = &jh7100_clk_data[idx].parent;

Can you use clk_parent_data instead of parent_names? To make the object
size even smaller you can use the DT index instead of the .fw_name
field. 

> +
> +               clk->hw.init = &init;
> +               clk->idx = idx;
> +               clk->max = jh7100_clk_data[idx].max;
> +
> +               ret = clk_hw_register(priv->dev, &clk->hw);

Why not use devm_clk_hw_register()?

> +               if (ret)
> +                       goto err;
> +       }
> +
> +       ret = devm_of_clk_add_hw_provider(priv->dev, clk_starfive_jh7100_get, priv);
> +       if (ret)
> +               goto err;
> +
> +       return 0;
> +err:
> +       while (idx)
> +               clk_hw_unregister(&priv->reg[--idx].hw);
> +       return ret;
> +}
> +
> +static const struct of_device_id clk_starfive_jh7100_match[] = {
> +       { .compatible = "starfive,jh7100-clkgen" },
> +       { /* sentinel */ }
> +};

Please add MODULE_DEVICE_TABLE()

> +
> +static struct platform_driver clk_starfive_jh7100_driver = {
> +       .probe = clk_starfive_jh7100_probe,
> +       .driver = {

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 06/16] clk: starfive: Add JH7100 clock generator driver
@ 2021-10-26 20:19     ` Stephen Boyd
  0 siblings, 0 replies; 143+ messages in thread
From: Stephen Boyd @ 2021-10-26 20:19 UTC (permalink / raw)
  To: Emil Renner Berthing, devicetree, linux-clk, linux-gpio,
	linux-riscv, linux-serial
  Cc: Geert Uytterhoeven, Palmer Dabbelt, Paul Walmsley, Rob Herring,
	Michael Turquette, Thomas Gleixner, Marc Zyngier, Philipp Zabel,
	Linus Walleij, Greg Kroah-Hartman, Daniel Lezcano,
	Andy Shevchenko, Jiri Slaby, Maximilian Luz, Sagar Kadam,
	Drew Fustini, Michael Zhu, Fu Wei, Anup Patel, Atish Patra,
	Matteo Croce, linux-kernel, Emil Renner Berthing

Quoting Emil Renner Berthing (2021-10-21 10:42:13)
> diff --git a/drivers/clk/starfive/clk-starfive-jh7100.c b/drivers/clk/starfive/clk-starfive-jh7100.c
> new file mode 100644
> index 000000000000..f109576f18c5
> --- /dev/null
> +++ b/drivers/clk/starfive/clk-starfive-jh7100.c
> @@ -0,0 +1,776 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * StarFive JH7100 Clock Generator Driver
> + *
> + * Copyright 2021 Ahmad Fatoum, Pengutronix
> + * Copyright (C) 2021 Glider bv
> + * Copyright (C) 2021 Emil Renner Berthing <kernel@esmil.dk>
> + */
> +
> +#include <linux/bits.h>
> +#include <linux/clk.h>

Is this include used?

> +#include <linux/clk-provider.h>
> +#include <linux/debugfs.h>
> +#include <linux/device.h>
> +#include <linux/init.h>
> +#include <linux/io.h>
> +#include <linux/kernel.h>
> +#include <linux/mod_devicetable.h>
> +#include <linux/module.h>
> +#include <linux/overflow.h>

Is this include used?

> +#include <linux/platform_device.h>
> +
> +#include <dt-bindings/clock/starfive-jh7100.h>
> +
> +#define JH7100_CLK_ENABLE_SHIFT        31
> +#define JH7100_CLK_INVERT_SHIFT        30
> +#define JH7100_CLK_MUX_SHIFT   24
> +
> +#define JH7100_CLK_ENABLE      BIT(31)
> +#define JH7100_CLK_INVERT      BIT(30)
> +#define JH7100_CLK_MUX_MASK    GENMASK(27, 24)
> +#define JH7100_CLK_DIV_MASK    GENMASK(23, 0)
> +
> +static const char *const cpundbus_root_sels[] __initconst = {
> +       [0] = "osc_sys",
> +       [1] = "pll0_out",
> +       [2] = "pll1_out",
> +       [3] = "pll2_out",
> +};
> +
> +static const char *const dla_root_sels[] __initconst = {
> +       [0] = "osc_sys",
> +       [1] = "pll1_out",
> +       [2] = "pll2_out",
> +};
> +
> +static const char *const dsp_root_sels[] __initconst = {
> +       [0] = "osc_sys",
> +       [1] = "pll0_out",
> +       [2] = "pll1_out",
> +       [3] = "pll2_out",
> +};
> +
> +static const char *const gmacusb_root_sels[] __initconst = {
> +       [0] = "osc_sys",
> +       [1] = "pll0_out",
> +       [2] = "pll2_out",
> +};
> +
> +static const char *const perh0_root_sels[] __initconst = {
> +       [0] = "osc_sys",
> +       [1] = "pll0_out",
> +};
> +
> +static const char *const perh1_root_sels[] __initconst = {
> +       [0] = "osc_sys",
> +       [1] = "pll2_out",
> +};
> +
> +static const char *const vin_root_sels[] __initconst = {
> +       [0] = "osc_sys",
> +       [1] = "pll1_out",
> +       [2] = "pll2_out",
> +};
> +
> +static const char *const vout_root_sels[] __initconst = {
> +       [0] = "osc_aud",
> +       [1] = "pll0_out",
> +       [2] = "pll2_out",
> +};
> +
> +static const char *const cdechifi4_root_sels[] __initconst = {
> +       [0] = "osc_sys",
> +       [1] = "pll1_out",
> +       [2] = "pll2_out",
> +};
> +
> +static const char *const cdec_root_sels[] __initconst = {
> +       [0] = "osc_sys",
> +       [1] = "pll0_out",
> +       [2] = "pll1_out",
> +};
> +
> +static const char *const voutbus_root_sels[] __initconst = {
> +       [0] = "osc_aud",
> +       [1] = "pll0_out",
> +       [2] = "pll2_out",
> +};
> +
> +static const char *const pll2_refclk_sels[] __initconst = {
> +       [0] = "osc_sys",
> +       [1] = "osc_aud",
> +};
> +
> +static const char *const ddrc0_sels[] __initconst = {
> +       [0] = "ddrosc_div2",
> +       [1] = "ddrpll_div2",
> +       [2] = "ddrpll_div4",
> +       [3] = "ddrpll_div8",
> +};
> +
> +static const char *const ddrc1_sels[] __initconst = {
> +       [0] = "ddrosc_div2",
> +       [1] = "ddrpll_div2",
> +       [2] = "ddrpll_div4",
> +       [3] = "ddrpll_div8",
> +};
> +
> +static const char *const nne_bus_sels[] __initconst = {
> +       [0] = "cpu_axi",
> +       [1] = "nnebus_src1",
> +};
> +
> +static const char *const usbphy_25m_sels[] __initconst = {
> +       [0] = "osc_sys",
> +       [1] = "usbphy_plldiv25m",
> +};
> +
> +static const char *const gmac_tx_sels[] __initconst = {
> +       [0] = "gmac_gtxclk",
> +       [1] = "gmac_mii_txclk",
> +       [2] = "gmac_rmii_txclk",
> +};
> +
> +static const char *const gmac_rx_pre_sels[] __initconst = {
> +       [0] = "gmac_gr_mii_rxclk",
> +       [1] = "gmac_rmii_rxclk",
> +};
> +
> +struct jh7100_clk {
> +       struct clk_hw hw;
> +       unsigned int idx;
> +       u32 max;

Why u32?

> +};
> +
> +struct clk_starfive_jh7100_priv {
> +       /* protect registers against overlapping read-modify-write */
> +       spinlock_t rmw_lock;

Does overlapping mean concurrent? Do different clks share the same
registers?

> +       struct device *dev;
> +       void __iomem *base;
> +       struct clk_hw *pll[3];
> +       struct jh7100_clk reg[JH7100_CLK_PLL0_OUT];
> +};
> +
> +static struct jh7100_clk *jh7100_clk_from(struct clk_hw *hw)
> +{
> +       return container_of(hw, struct jh7100_clk, hw);
> +}
> +
> +static struct clk_starfive_jh7100_priv *jh7100_priv_from(struct jh7100_clk *clk)
> +{
> +       return container_of(clk, struct clk_starfive_jh7100_priv, reg[clk->idx]);
> +}
> +
> +static u32 jh7100_clk_reg_get(struct jh7100_clk *clk)
> +{
> +       struct clk_starfive_jh7100_priv *priv = jh7100_priv_from(clk);
> +       void __iomem *reg = priv->base + 4 * clk->idx;
> +
> +       return readl_relaxed(reg);
> +}
> +
> +static void jh7100_clk_reg_rmw(struct jh7100_clk *clk, u32 mask, u32 value)
> +{
> +       struct clk_starfive_jh7100_priv *priv = jh7100_priv_from(clk);
> +       void __iomem *reg = priv->base + 4 * clk->idx;
> +       unsigned long flags;
> +
> +       spin_lock_irqsave(&priv->rmw_lock, flags);
> +       value |= readl_relaxed(reg) & ~mask;
> +       writel_relaxed(value, reg);
> +       spin_unlock_irqrestore(&priv->rmw_lock, flags);
> +}
> +
> +static int jh7100_clk_enable(struct clk_hw *hw)
> +{
> +       struct jh7100_clk *clk = jh7100_clk_from(hw);
> +
> +       dev_dbg(jh7100_priv_from(clk)->dev, "enable(%s)\n", clk_hw_get_name(&clk->hw));
> +
> +       jh7100_clk_reg_rmw(clk, JH7100_CLK_ENABLE, JH7100_CLK_ENABLE);
> +       return 0;
> +}
> +
> +static void jh7100_clk_disable(struct clk_hw *hw)
> +{
> +       struct jh7100_clk *clk = jh7100_clk_from(hw);
> +
> +       dev_dbg(jh7100_priv_from(clk)->dev, "disable(%s)\n", clk_hw_get_name(&clk->hw));
> +
> +       jh7100_clk_reg_rmw(clk, JH7100_CLK_ENABLE, 0);
> +}
> +
> +static int jh7100_clk_is_enabled(struct clk_hw *hw)
> +{
> +       struct jh7100_clk *clk = jh7100_clk_from(hw);
> +
> +       return !!(jh7100_clk_reg_get(clk) & JH7100_CLK_ENABLE);
> +}
> +
> +static int jh7100_clk_is_parent_enabled(struct clk_hw *hw)
> +{
> +       return clk_hw_is_enabled(clk_hw_get_parent(hw));

Why do we need this function? The parent being enabled implies this clk
is enabled if this clk can't gate itself but then knowing this clk is
enabled is useful for what?

> +}
> +
> +static unsigned long jh7100_clk_recalc_rate(struct clk_hw *hw,
> +                                           unsigned long parent_rate)
> +{
> +       struct jh7100_clk *clk = jh7100_clk_from(hw);
> +       u32 value = jh7100_clk_reg_get(clk) & JH7100_CLK_DIV_MASK;
> +       unsigned long rate;
> +
> +       if (value)
> +               rate = parent_rate / value;
> +       else
> +               rate = 0;
> +
> +       dev_dbg(jh7100_priv_from(clk)->dev, "recalc_rate(%s, %lu) = %lu (div %u)\n",
> +               clk_hw_get_name(&clk->hw), parent_rate, rate, value);
> +
> +       return rate;
> +}
> +
> +static unsigned long jh7100_clk_bestdiv(struct jh7100_clk *clk,
> +                                       unsigned long rate, unsigned long parent)
> +{
> +       unsigned long max = clk->max & JH7100_CLK_DIV_MASK;
> +       unsigned long div = DIV_ROUND_UP(parent, rate);
> +
> +       return min(div, max);
> +}
> +
> +static int jh7100_clk_determine_rate(struct clk_hw *hw,
> +                                    struct clk_rate_request *req)
> +{
> +       struct jh7100_clk *clk = jh7100_clk_from(hw);
> +       unsigned long parent = req->best_parent_rate;
> +       unsigned long rate = clamp(req->rate, req->min_rate, req->max_rate);
> +       unsigned long div = jh7100_clk_bestdiv(clk, rate, parent);
> +       unsigned long result = parent / div;
> +
> +       /*
> +        * We want the result clamped by min_rate and max_rate if possible:
> +        * Case 1: div hits the max divider value, which means it's less than
> +        * parent / rate, so the result is greater than rate and min_rate in
> +        * particular. We can't do anything about result > max_rate because the
> +        * divider doesn't go any further.
> +        * Case 2: div = DIV_ROUND_UP(parent, rate) which means the result is
> +        * always lower or equal to rate and max_rate.  However the result may
> +        * turn out lower than min_rate, but then the next higher rate is fine:
> +        *   div - 1 = ceil(parent / rate) - 1 < parent / rate
> +        * and thus
> +        *   min_rate <= rate < parent / (div - 1)
> +        */
> +       if (result < req->min_rate && div > 1) {
> +               div -= 1;
> +               result = parent / div;
> +       }
> +
> +       dev_dbg(jh7100_priv_from(clk)->dev,
> +               "determine_rate(%s, {%lu<=%lu<=%lu from %lu}) = %lu (div %lu)\n",
> +               clk_hw_get_name(&clk->hw), req->min_rate, req->rate, req->max_rate,
> +               parent, result, div);
> +
> +       req->rate = result;
> +       return 0;
> +}
> +
> +static int jh7100_clk_set_rate(struct clk_hw *hw,
> +                              unsigned long rate,
> +                              unsigned long parent_rate)
> +{
> +       struct jh7100_clk *clk = jh7100_clk_from(hw);
> +       unsigned long div = jh7100_clk_bestdiv(clk, rate, parent_rate);
> +
> +       dev_dbg(jh7100_priv_from(clk)->dev,
> +               "set_rate(%s, %lu, %lu) = %lu (div %lu)\n",
> +               clk_hw_get_name(&clk->hw), rate, parent_rate,
> +               parent_rate / div, div);
> +
> +       jh7100_clk_reg_rmw(clk, JH7100_CLK_DIV_MASK, div);
> +       return 0;
> +}
> +
> +static u8 jh7100_clk_get_parent(struct clk_hw *hw)
> +{
> +       struct jh7100_clk *clk = jh7100_clk_from(hw);
> +       u32 value = jh7100_clk_reg_get(clk);
> +
> +       return (value & JH7100_CLK_MUX_MASK) >> JH7100_CLK_MUX_SHIFT;
> +}
> +
> +static int jh7100_clk_set_parent(struct clk_hw *hw, u8 index)
> +{
> +       struct jh7100_clk *clk = jh7100_clk_from(hw);
> +       u32 value = (u32)index << JH7100_CLK_MUX_SHIFT;
> +
> +       dev_dbg(jh7100_priv_from(clk)->dev, "set_parent(%s, %u)\n",
> +               clk_hw_get_name(&clk->hw), index);

Please remove these dev_dbg() messages. We have tracepoints for general
clk operations and the driver shouldn't duplicate that.

> +
> +       jh7100_clk_reg_rmw(clk, JH7100_CLK_MUX_MASK, value);
> +       return 0;
> +}
> +
> +static int jh7100_clk_mux_determine_rate(struct clk_hw *hw,
> +                                        struct clk_rate_request *req)
> +{
> +       struct jh7100_clk *clk = jh7100_clk_from(hw);
> +       int ret = clk_mux_determine_rate_flags(&clk->hw, req, 0);
> +
> +       dev_dbg(jh7100_priv_from(clk)->dev, "determine_rate(%s) = %d\n",
> +               clk_hw_get_name(&clk->hw), ret);
> +
> +       return ret;
> +}
> +
> +static int jh7100_clk_get_phase(struct clk_hw *hw)
> +{
> +       struct jh7100_clk *clk = jh7100_clk_from(hw);
> +       u32 value = jh7100_clk_reg_get(clk);
> +
> +       return (value & JH7100_CLK_INVERT) ? 180 : 0;
> +}
> +
> +static int jh7100_clk_set_phase(struct clk_hw *hw, int degrees)
> +{
> +       struct jh7100_clk *clk = jh7100_clk_from(hw);
> +       u32 value;
> +
> +       dev_dbg(jh7100_priv_from(clk)->dev, "set_phase(%s, %d)\n",
> +               clk_hw_get_name(&clk->hw), degrees);
> +
> +       if (degrees == 0)
> +               value = 0;
> +       else if (degrees == 180)
> +               value = JH7100_CLK_INVERT;
> +       else
> +               return -EINVAL;
> +
> +       jh7100_clk_reg_rmw(clk, JH7100_CLK_INVERT, value);
> +       return 0;
> +}
> +
> +#ifdef CONFIG_DEBUG_FS
> +static void jh7100_clk_debug_init(struct clk_hw *hw, struct dentry *dentry)
> +{
> +       static const struct debugfs_reg32 jh7100_clk_reg = {
> +               .name = "CTRL",
> +               .offset = 0,
> +       };
> +       struct jh7100_clk *clk = jh7100_clk_from(hw);
> +       struct clk_starfive_jh7100_priv *priv = jh7100_priv_from(clk);
> +       struct debugfs_regset32 *regset;
> +
> +       regset = devm_kzalloc(priv->dev, sizeof(*regset), GFP_KERNEL);
> +       if (!regset)
> +               return;
> +
> +       regset->regs = &jh7100_clk_reg;
> +       regset->nregs = 1;
> +       regset->base = priv->base + 4 * clk->idx;
> +
> +       debugfs_create_regset32("registers", 0400, dentry, regset);
> +}
> +#else
> +#define jh7100_clk_debug_init NULL
> +#endif
> +
> +static const struct clk_ops jh7100_clk_gate_ops = {
> +       .enable = jh7100_clk_enable,
> +       .disable = jh7100_clk_disable,
> +       .is_enabled = jh7100_clk_is_enabled,
> +       .debug_init = jh7100_clk_debug_init,
> +};
> +
> +static const struct clk_ops jh7100_clk_div_ops = {
> +       .is_enabled = jh7100_clk_is_parent_enabled,
> +       .recalc_rate = jh7100_clk_recalc_rate,
> +       .determine_rate = jh7100_clk_determine_rate,
> +       .set_rate = jh7100_clk_set_rate,
> +       .debug_init = jh7100_clk_debug_init,
> +};
> +
> +static const struct clk_ops jh7100_clk_gdiv_ops = {
> +       .enable = jh7100_clk_enable,
> +       .disable = jh7100_clk_disable,
> +       .is_enabled = jh7100_clk_is_enabled,
> +       .recalc_rate = jh7100_clk_recalc_rate,
> +       .determine_rate = jh7100_clk_determine_rate,
> +       .set_rate = jh7100_clk_set_rate,
> +       .debug_init = jh7100_clk_debug_init,
> +};
> +
> +static const struct clk_ops jh7100_clk_mux_ops = {
> +       .is_enabled = jh7100_clk_is_parent_enabled,
> +       .get_parent = jh7100_clk_get_parent,
> +       .set_parent = jh7100_clk_set_parent,
> +       .determine_rate = jh7100_clk_mux_determine_rate,
> +       .debug_init = jh7100_clk_debug_init,
> +};
> +
> +static const struct clk_ops jh7100_clk_gmux_ops = {
> +       .enable = jh7100_clk_enable,
> +       .disable = jh7100_clk_disable,
> +       .is_enabled = jh7100_clk_is_enabled,
> +       .get_parent = jh7100_clk_get_parent,
> +       .set_parent = jh7100_clk_set_parent,
> +       .determine_rate = jh7100_clk_mux_determine_rate,
> +       .debug_init = jh7100_clk_debug_init,
> +};
> +
> +static const struct clk_ops jh7100_clk_inv_ops = {
> +       .is_enabled = jh7100_clk_is_parent_enabled,
> +       .get_phase = jh7100_clk_get_phase,
> +       .set_phase = jh7100_clk_set_phase,
> +       .debug_init = jh7100_clk_debug_init,
> +};
> +
> +#define JH7100_GATE(_idx, _name, _parent, _flags) [_idx] = { \

Typical macro style is to tab out the \ to a single column

> +       .name = _name, \
> +       .ops = &jh7100_clk_gate_ops, \
> +       .parent = _parent, \
> +       .flags = CLK_SET_RATE_PARENT | (_flags), \
> +       .max = JH7100_CLK_ENABLE, \
> +}
> +
> +#define JH7100__DIV(_idx, _name, _parent, _max) [_idx] = { \
> +       .name = _name, \
> +       .ops = &jh7100_clk_div_ops, \
> +       .parent = _parent, \
> +       .flags = 0, \
> +       .max = _max, \
> +}
> +
> +#define JH7100_GDIV(_idx, _name, _parent, _max, _flags) [_idx] = { \
> +       .name = _name, \
> +       .ops = &jh7100_clk_gdiv_ops, \
> +       .parent = _parent, \
> +       .flags = (_flags), \
> +       .max = JH7100_CLK_ENABLE | (_max), \
> +}
> +
> +#define JH7100__MUX(_idx, _name, _parents) [_idx] = { \
> +       .name = _name, \
> +       .ops = &jh7100_clk_mux_ops, \
> +       .parents = _parents, \
> +       .flags = 0, \
> +       .max = (ARRAY_SIZE(_parents) - 1) << JH7100_CLK_MUX_SHIFT, \
> +}
> +
> +#define JH7100_GMUX(_idx, _name, _parents, _flags) [_idx] = { \
> +       .name = _name, \
> +       .ops = &jh7100_clk_gmux_ops, \
> +       .parents = _parents, \
> +       .flags = (_flags), \
> +       .max = JH7100_CLK_ENABLE | \
> +               ((ARRAY_SIZE(_parents) - 1) << JH7100_CLK_MUX_SHIFT), \
> +}
> +
> +#define JH7100__INV(_idx, _name, _parent) [_idx] = { \
> +       .name = _name, \
> +       .ops = &jh7100_clk_inv_ops, \
> +       .parent = _parent, \
> +       .flags = CLK_SET_RATE_PARENT, \
> +       .max = JH7100_CLK_INVERT, \
> +}
> +
> +static const struct {
> +       const char *name;
> +       const struct clk_ops *ops;
> +       union {
> +               const char *parent;
> +               const char *const *parents;
> +       };
> +       unsigned long flags;
> +       u32 max;
> +} jh7100_clk_data[] __initconst = {
> +       JH7100__MUX(JH7100_CLK_CPUNDBUS_ROOT, "cpundbus_root", cpundbus_root_sels),
> +       JH7100__MUX(JH7100_CLK_DLA_ROOT, "dla_root", dla_root_sels),
> +       JH7100__MUX(JH7100_CLK_DSP_ROOT, "dsp_root", dsp_root_sels),
> +       JH7100__MUX(JH7100_CLK_GMACUSB_ROOT, "gmacusb_root", gmacusb_root_sels),
> +       JH7100__MUX(JH7100_CLK_PERH0_ROOT, "perh0_root", perh0_root_sels),
> +       JH7100__MUX(JH7100_CLK_PERH1_ROOT, "perh1_root", perh1_root_sels),
> +       JH7100__MUX(JH7100_CLK_VIN_ROOT, "vin_root", vin_root_sels),
> +       JH7100__MUX(JH7100_CLK_VOUT_ROOT, "vout_root", vout_root_sels),
> +       JH7100_GDIV(JH7100_CLK_AUDIO_ROOT, "audio_root", "pll0_out", 8, 0),
> +       JH7100__MUX(JH7100_CLK_CDECHIFI4_ROOT, "cdechifi4_root", cdechifi4_root_sels),
> +       JH7100__MUX(JH7100_CLK_CDEC_ROOT, "cdec_root", cdec_root_sels),
> +       JH7100__MUX(JH7100_CLK_VOUTBUS_ROOT, "voutbus_root", voutbus_root_sels),
> +       JH7100__DIV(JH7100_CLK_CPUNBUS_ROOT_DIV, "cpunbus_root_div", "cpundbus_root", 2),
> +       JH7100__DIV(JH7100_CLK_DSP_ROOT_DIV, "dsp_root_div", "dsp_root", 4),
> +       JH7100__DIV(JH7100_CLK_PERH0_SRC, "perh0_src", "perh0_root", 4),
> +       JH7100__DIV(JH7100_CLK_PERH1_SRC, "perh1_src", "perh1_root", 4),
> +       JH7100_GDIV(JH7100_CLK_PLL0_TESTOUT, "pll0_testout", "perh0_src", 31, 0),
> +       JH7100_GDIV(JH7100_CLK_PLL1_TESTOUT, "pll1_testout", "dla_root", 31, 0),
> +       JH7100_GDIV(JH7100_CLK_PLL2_TESTOUT, "pll2_testout", "perh1_src", 31, 0),
> +       JH7100__MUX(JH7100_CLK_PLL2_REF, "pll2_refclk", pll2_refclk_sels),
> +       JH7100__DIV(JH7100_CLK_CPU_CORE, "cpu_core", "cpunbus_root_div", 8),
> +       JH7100__DIV(JH7100_CLK_CPU_AXI, "cpu_axi", "cpu_core", 8),
> +       JH7100__DIV(JH7100_CLK_AHB_BUS, "ahb_bus", "cpunbus_root_div", 8),
> +       JH7100__DIV(JH7100_CLK_APB1_BUS, "apb1_bus", "ahb_bus", 8),
> +       JH7100__DIV(JH7100_CLK_APB2_BUS, "apb2_bus", "ahb_bus", 8),
> +       JH7100_GATE(JH7100_CLK_DOM3AHB_BUS, "dom3ahb_bus", "ahb_bus", CLK_IGNORE_UNUSED),
> +       JH7100_GATE(JH7100_CLK_DOM7AHB_BUS, "dom7ahb_bus", "ahb_bus", CLK_IGNORE_UNUSED),
> +       JH7100_GATE(JH7100_CLK_U74_CORE0, "u74_core0", "cpu_core", CLK_IGNORE_UNUSED),
> +       JH7100_GDIV(JH7100_CLK_U74_CORE1, "u74_core1", "cpu_core", 8, CLK_IGNORE_UNUSED),
> +       JH7100_GATE(JH7100_CLK_U74_AXI, "u74_axi", "cpu_axi", CLK_IGNORE_UNUSED),
> +       JH7100_GATE(JH7100_CLK_U74RTC_TOGGLE, "u74rtc_toggle", "osc_sys", CLK_IGNORE_UNUSED),
> +       JH7100_GATE(JH7100_CLK_SGDMA2P_AXI, "sgdma2p_axi", "cpu_axi", 0),
> +       JH7100_GATE(JH7100_CLK_DMA2PNOC_AXI, "dma2pnoc_axi", "cpu_axi", 0),
> +       JH7100_GATE(JH7100_CLK_SGDMA2P_AHB, "sgdma2p_ahb", "ahb_bus", 0),
> +       JH7100__DIV(JH7100_CLK_DLA_BUS, "dla_bus", "dla_root", 4),
> +       JH7100_GATE(JH7100_CLK_DLA_AXI, "dla_axi", "dla_bus", 0),
> +       JH7100_GATE(JH7100_CLK_DLANOC_AXI, "dlanoc_axi", "dla_bus", 0),
> +       JH7100_GATE(JH7100_CLK_DLA_APB, "dla_apb", "apb1_bus", 0),
> +       JH7100_GDIV(JH7100_CLK_VP6_CORE, "vp6_core", "dsp_root_div", 4, 0),
> +       JH7100__DIV(JH7100_CLK_VP6BUS_SRC, "vp6bus_src", "dsp_root", 4),
> +       JH7100_GDIV(JH7100_CLK_VP6_AXI, "vp6_axi", "vp6bus_src", 4, 0),
> +       JH7100__DIV(JH7100_CLK_VCDECBUS_SRC, "vcdecbus_src", "cdechifi4_root", 4),
> +       JH7100__DIV(JH7100_CLK_VDEC_BUS, "vdec_bus", "vcdecbus_src", 8),
> +       JH7100_GATE(JH7100_CLK_VDEC_AXI, "vdec_axi", "vdec_bus", 0),
> +       JH7100_GATE(JH7100_CLK_VDECBRG_MAIN, "vdecbrg_mainclk", "vdec_bus", 0),
> +       JH7100_GDIV(JH7100_CLK_VDEC_BCLK, "vdec_bclk", "vcdecbus_src", 8, 0),
> +       JH7100_GDIV(JH7100_CLK_VDEC_CCLK, "vdec_cclk", "cdec_root", 8, 0),
> +       JH7100_GATE(JH7100_CLK_VDEC_APB, "vdec_apb", "apb1_bus", 0),
> +       JH7100_GDIV(JH7100_CLK_JPEG_AXI, "jpeg_axi", "cpunbus_root_div", 8, 0),
> +       JH7100_GDIV(JH7100_CLK_JPEG_CCLK, "jpeg_cclk", "cpunbus_root_div", 8, 0),
> +       JH7100_GATE(JH7100_CLK_JPEG_APB, "jpeg_apb", "apb1_bus", 0),
> +       JH7100_GDIV(JH7100_CLK_GC300_2X, "gc300_2x", "cdechifi4_root", 8, 0),
> +       JH7100_GATE(JH7100_CLK_GC300_AHB, "gc300_ahb", "ahb_bus", 0),
> +       JH7100__DIV(JH7100_CLK_JPCGC300_AXIBUS, "jpcgc300_axibus", "vcdecbus_src", 8),
> +       JH7100_GATE(JH7100_CLK_GC300_AXI, "gc300_axi", "jpcgc300_axibus", 0),
> +       JH7100_GATE(JH7100_CLK_JPCGC300_MAIN, "jpcgc300_mainclk", "jpcgc300_axibus", 0),
> +       JH7100__DIV(JH7100_CLK_VENC_BUS, "venc_bus", "vcdecbus_src", 8),
> +       JH7100_GATE(JH7100_CLK_VENC_AXI, "venc_axi", "venc_bus", 0),
> +       JH7100_GATE(JH7100_CLK_VENCBRG_MAIN, "vencbrg_mainclk", "venc_bus", 0),
> +       JH7100_GDIV(JH7100_CLK_VENC_BCLK, "venc_bclk", "vcdecbus_src", 8, 0),
> +       JH7100_GDIV(JH7100_CLK_VENC_CCLK, "venc_cclk", "cdec_root", 8, 0),
> +       JH7100_GATE(JH7100_CLK_VENC_APB, "venc_apb", "apb1_bus", 0),
> +       JH7100_GDIV(JH7100_CLK_DDRPLL_DIV2, "ddrpll_div2", "pll1_out", 2, CLK_IGNORE_UNUSED),
> +       JH7100_GDIV(JH7100_CLK_DDRPLL_DIV4, "ddrpll_div4", "ddrpll_div2", 2, CLK_IGNORE_UNUSED),
> +       JH7100_GDIV(JH7100_CLK_DDRPLL_DIV8, "ddrpll_div8", "ddrpll_div4", 2, CLK_IGNORE_UNUSED),
> +       JH7100_GDIV(JH7100_CLK_DDROSC_DIV2, "ddrosc_div2", "osc_sys", 2, CLK_IGNORE_UNUSED),
> +       JH7100_GMUX(JH7100_CLK_DDRC0, "ddrc0", ddrc0_sels, CLK_IGNORE_UNUSED),
> +       JH7100_GMUX(JH7100_CLK_DDRC1, "ddrc1", ddrc1_sels, CLK_IGNORE_UNUSED),

Is it really unused? Or it is CLK_IS_CRITICAL?

> +       JH7100_GATE(JH7100_CLK_DDRPHY_APB, "ddrphy_apb", "apb1_bus", CLK_IGNORE_UNUSED),
> +       JH7100__DIV(JH7100_CLK_NOC_ROB, "noc_rob", "cpunbus_root_div", 8),
> +       JH7100__DIV(JH7100_CLK_NOC_COG, "noc_cog", "dla_root", 8),
> +       JH7100_GATE(JH7100_CLK_NNE_AHB, "nne_ahb", "ahb_bus", 0),
> +       JH7100__DIV(JH7100_CLK_NNEBUS_SRC1, "nnebus_src1", "dsp_root", 4),
> +       JH7100__MUX(JH7100_CLK_NNE_BUS, "nne_bus", nne_bus_sels),
> +       JH7100_GATE(JH7100_CLK_NNE_AXI, "nne_axi", "nne_bus", 0),
> +       JH7100_GATE(JH7100_CLK_NNENOC_AXI, "nnenoc_axi", "nne_bus", 0),
> +       JH7100_GATE(JH7100_CLK_DLASLV_AXI, "dlaslv_axi", "nne_bus", 0),
> +       JH7100_GATE(JH7100_CLK_DSPX2C_AXI, "dspx2c_axi", "nne_bus", CLK_IGNORE_UNUSED),
> +       JH7100__DIV(JH7100_CLK_HIFI4_SRC, "hifi4_src", "cdechifi4_root", 4),
> +       JH7100__DIV(JH7100_CLK_HIFI4_COREFREE, "hifi4_corefree", "hifi4_src", 8),
> +       JH7100_GATE(JH7100_CLK_HIFI4_CORE, "hifi4_core", "hifi4_corefree", 0),
> +       JH7100__DIV(JH7100_CLK_HIFI4_BUS, "hifi4_bus", "hifi4_corefree", 8),
> +       JH7100_GATE(JH7100_CLK_HIFI4_AXI, "hifi4_axi", "hifi4_bus", 0),
> +       JH7100_GATE(JH7100_CLK_HIFI4NOC_AXI, "hifi4noc_axi", "hifi4_bus", 0),
> +       JH7100__DIV(JH7100_CLK_SGDMA1P_BUS, "sgdma1p_bus", "cpunbus_root_div", 8),
> +       JH7100_GATE(JH7100_CLK_SGDMA1P_AXI, "sgdma1p_axi", "sgdma1p_bus", 0),
> +       JH7100_GATE(JH7100_CLK_DMA1P_AXI, "dma1p_axi", "sgdma1p_bus", 0),
> +       JH7100_GDIV(JH7100_CLK_X2C_AXI, "x2c_axi", "cpunbus_root_div", 8, CLK_IGNORE_UNUSED),
> +       JH7100__DIV(JH7100_CLK_USB_BUS, "usb_bus", "cpunbus_root_div", 8),
> +       JH7100_GATE(JH7100_CLK_USB_AXI, "usb_axi", "usb_bus", 0),
> +       JH7100_GATE(JH7100_CLK_USBNOC_AXI, "usbnoc_axi", "usb_bus", 0),
> +       JH7100__DIV(JH7100_CLK_USBPHY_ROOTDIV, "usbphy_rootdiv", "gmacusb_root", 4),
> +       JH7100_GDIV(JH7100_CLK_USBPHY_125M, "usbphy_125m", "usbphy_rootdiv", 8, 0),
> +       JH7100_GDIV(JH7100_CLK_USBPHY_PLLDIV25M, "usbphy_plldiv25m", "usbphy_rootdiv", 32, 0),
> +       JH7100__MUX(JH7100_CLK_USBPHY_25M, "usbphy_25m", usbphy_25m_sels),
> +       JH7100__DIV(JH7100_CLK_AUDIO_DIV, "audio_div", "audio_root", 131072),
> +       JH7100_GATE(JH7100_CLK_AUDIO_SRC, "audio_src", "audio_div", 0),
> +       JH7100_GATE(JH7100_CLK_AUDIO_12288, "audio_12288", "osc_aud", 0),
> +       JH7100_GDIV(JH7100_CLK_VIN_SRC, "vin_src", "vin_root", 4, 0),
> +       JH7100__DIV(JH7100_CLK_ISP0_BUS, "isp0_bus", "vin_src", 8),
> +       JH7100_GATE(JH7100_CLK_ISP0_AXI, "isp0_axi", "isp0_bus", 0),
> +       JH7100_GATE(JH7100_CLK_ISP0NOC_AXI, "isp0noc_axi", "isp0_bus", 0),
> +       JH7100_GATE(JH7100_CLK_ISPSLV_AXI, "ispslv_axi", "isp0_bus", 0),
> +       JH7100__DIV(JH7100_CLK_ISP1_BUS, "isp1_bus", "vin_src", 8),
> +       JH7100_GATE(JH7100_CLK_ISP1_AXI, "isp1_axi", "isp1_bus", 0),
> +       JH7100_GATE(JH7100_CLK_ISP1NOC_AXI, "isp1noc_axi", "isp1_bus", 0),
> +       JH7100__DIV(JH7100_CLK_VIN_BUS, "vin_bus", "vin_src", 8),
> +       JH7100_GATE(JH7100_CLK_VIN_AXI, "vin_axi", "vin_bus", 0),
> +       JH7100_GATE(JH7100_CLK_VINNOC_AXI, "vinnoc_axi", "vin_bus", 0),
> +       JH7100_GDIV(JH7100_CLK_VOUT_SRC, "vout_src", "vout_root", 4, 0),
> +       JH7100__DIV(JH7100_CLK_DISPBUS_SRC, "dispbus_src", "voutbus_root", 4),
> +       JH7100__DIV(JH7100_CLK_DISP_BUS, "disp_bus", "dispbus_src", 4),
> +       JH7100_GATE(JH7100_CLK_DISP_AXI, "disp_axi", "disp_bus", 0),
> +       JH7100_GATE(JH7100_CLK_DISPNOC_AXI, "dispnoc_axi", "disp_bus", 0),
> +       JH7100_GATE(JH7100_CLK_SDIO0_AHB, "sdio0_ahb", "ahb_bus", 0),
> +       JH7100_GDIV(JH7100_CLK_SDIO0_CCLKINT, "sdio0_cclkint", "perh0_src", 24, 0),
> +       JH7100__INV(JH7100_CLK_SDIO0_CCLKINT_INV, "sdio0_cclkint_inv", "sdio0_cclkint"),
> +       JH7100_GATE(JH7100_CLK_SDIO1_AHB, "sdio1_ahb", "ahb_bus", 0),
> +       JH7100_GDIV(JH7100_CLK_SDIO1_CCLKINT, "sdio1_cclkint", "perh1_src", 24, 0),
> +       JH7100__INV(JH7100_CLK_SDIO1_CCLKINT_INV, "sdio1_cclkint_inv", "sdio1_cclkint"),
> +       JH7100_GATE(JH7100_CLK_GMAC_AHB, "gmac_ahb", "ahb_bus", 0),
> +       JH7100__DIV(JH7100_CLK_GMAC_ROOT_DIV, "gmac_root_div", "gmacusb_root", 8),
> +       JH7100_GDIV(JH7100_CLK_GMAC_PTP_REF, "gmac_ptp_refclk", "gmac_root_div", 31, 0),
> +       JH7100_GDIV(JH7100_CLK_GMAC_GTX, "gmac_gtxclk", "gmac_root_div", 255, 0),
> +       JH7100_GDIV(JH7100_CLK_GMAC_RMII_TX, "gmac_rmii_txclk", "gmac_rmii_ref", 8, 0),
> +       JH7100_GDIV(JH7100_CLK_GMAC_RMII_RX, "gmac_rmii_rxclk", "gmac_rmii_ref", 8, 0),
> +       JH7100__MUX(JH7100_CLK_GMAC_TX, "gmac_tx", gmac_tx_sels),
> +       JH7100__INV(JH7100_CLK_GMAC_TX_INV, "gmac_tx_inv", "gmac_tx"),
> +       JH7100__MUX(JH7100_CLK_GMAC_RX_PRE, "gmac_rx_pre", gmac_rx_pre_sels),
> +       JH7100__INV(JH7100_CLK_GMAC_RX_INV, "gmac_rx_inv", "gmac_rx_pre"),
> +       JH7100_GATE(JH7100_CLK_GMAC_RMII, "gmac_rmii", "gmac_rmii_ref", 0),
> +       JH7100_GDIV(JH7100_CLK_GMAC_TOPHYREF, "gmac_tophyref", "gmac_root_div", 127, 0),
> +       JH7100_GATE(JH7100_CLK_SPI2AHB_AHB, "spi2ahb_ahb", "ahb_bus", 0),
> +       JH7100_GDIV(JH7100_CLK_SPI2AHB_CORE, "spi2ahb_core", "perh0_src", 31, 0),
> +       JH7100_GATE(JH7100_CLK_EZMASTER_AHB, "ezmaster_ahb", "ahb_bus", 0),
> +       JH7100_GATE(JH7100_CLK_E24_AHB, "e24_ahb", "ahb_bus", 0),
> +       JH7100_GATE(JH7100_CLK_E24RTC_TOGGLE, "e24rtc_toggle", "osc_sys", 0),
> +       JH7100_GATE(JH7100_CLK_QSPI_AHB, "qspi_ahb", "ahb_bus", 0),
> +       JH7100_GATE(JH7100_CLK_QSPI_APB, "qspi_apb", "apb1_bus", 0),
> +       JH7100_GDIV(JH7100_CLK_QSPI_REF, "qspi_refclk", "perh0_src", 31, 0),
> +       JH7100_GATE(JH7100_CLK_SEC_AHB, "sec_ahb", "ahb_bus", 0),
> +       JH7100_GATE(JH7100_CLK_AES, "aes_clk", "sec_ahb", 0),
> +       JH7100_GATE(JH7100_CLK_SHA, "sha_clk", "sec_ahb", 0),
> +       JH7100_GATE(JH7100_CLK_PKA, "pka_clk", "sec_ahb", 0),
> +       JH7100_GATE(JH7100_CLK_TRNG_APB, "trng_apb", "apb1_bus", 0),
> +       JH7100_GATE(JH7100_CLK_OTP_APB, "otp_apb", "apb1_bus", 0),
> +       JH7100_GATE(JH7100_CLK_UART0_APB, "uart0_apb", "apb1_bus", 0),
> +       JH7100_GDIV(JH7100_CLK_UART0_CORE, "uart0_core", "perh1_src", 63, 0),
> +       JH7100_GATE(JH7100_CLK_UART1_APB, "uart1_apb", "apb1_bus", 0),
> +       JH7100_GDIV(JH7100_CLK_UART1_CORE, "uart1_core", "perh1_src", 63, 0),
> +       JH7100_GATE(JH7100_CLK_SPI0_APB, "spi0_apb", "apb1_bus", 0),
> +       JH7100_GDIV(JH7100_CLK_SPI0_CORE, "spi0_core", "perh1_src", 63, 0),
> +       JH7100_GATE(JH7100_CLK_SPI1_APB, "spi1_apb", "apb1_bus", 0),
> +       JH7100_GDIV(JH7100_CLK_SPI1_CORE, "spi1_core", "perh1_src", 63, 0),
> +       JH7100_GATE(JH7100_CLK_I2C0_APB, "i2c0_apb", "apb1_bus", 0),
> +       JH7100_GDIV(JH7100_CLK_I2C0_CORE, "i2c0_core", "perh1_src", 63, 0),
> +       JH7100_GATE(JH7100_CLK_I2C1_APB, "i2c1_apb", "apb1_bus", 0),
> +       JH7100_GDIV(JH7100_CLK_I2C1_CORE, "i2c1_core", "perh1_src", 63, 0),
> +       JH7100_GATE(JH7100_CLK_GPIO_APB, "gpio_apb", "apb1_bus", 0),
> +       JH7100_GATE(JH7100_CLK_UART2_APB, "uart2_apb", "apb2_bus", 0),
> +       JH7100_GDIV(JH7100_CLK_UART2_CORE, "uart2_core", "perh0_src", 63, 0),
> +       JH7100_GATE(JH7100_CLK_UART3_APB, "uart3_apb", "apb2_bus", 0),
> +       JH7100_GDIV(JH7100_CLK_UART3_CORE, "uart3_core", "perh0_src", 63, 0),
> +       JH7100_GATE(JH7100_CLK_SPI2_APB, "spi2_apb", "apb2_bus", 0),
> +       JH7100_GDIV(JH7100_CLK_SPI2_CORE, "spi2_core", "perh0_src", 63, 0),
> +       JH7100_GATE(JH7100_CLK_SPI3_APB, "spi3_apb", "apb2_bus", 0),
> +       JH7100_GDIV(JH7100_CLK_SPI3_CORE, "spi3_core", "perh0_src", 63, 0),
> +       JH7100_GATE(JH7100_CLK_I2C2_APB, "i2c2_apb", "apb2_bus", 0),
> +       JH7100_GDIV(JH7100_CLK_I2C2_CORE, "i2c2_core", "perh0_src", 63, 0),
> +       JH7100_GATE(JH7100_CLK_I2C3_APB, "i2c3_apb", "apb2_bus", 0),
> +       JH7100_GDIV(JH7100_CLK_I2C3_CORE, "i2c3_core", "perh0_src", 63, 0),
> +       JH7100_GATE(JH7100_CLK_WDTIMER_APB, "wdtimer_apb", "apb2_bus", 0),
> +       JH7100_GDIV(JH7100_CLK_WDT_CORE, "wdt_coreclk", "perh0_src", 63, 0),
> +       JH7100_GDIV(JH7100_CLK_TIMER0_CORE, "timer0_coreclk", "perh0_src", 63, 0),
> +       JH7100_GDIV(JH7100_CLK_TIMER1_CORE, "timer1_coreclk", "perh0_src", 63, 0),
> +       JH7100_GDIV(JH7100_CLK_TIMER2_CORE, "timer2_coreclk", "perh0_src", 63, 0),
> +       JH7100_GDIV(JH7100_CLK_TIMER3_CORE, "timer3_coreclk", "perh0_src", 63, 0),
> +       JH7100_GDIV(JH7100_CLK_TIMER4_CORE, "timer4_coreclk", "perh0_src", 63, 0),
> +       JH7100_GDIV(JH7100_CLK_TIMER5_CORE, "timer5_coreclk", "perh0_src", 63, 0),
> +       JH7100_GDIV(JH7100_CLK_TIMER6_CORE, "timer6_coreclk", "perh0_src", 63, 0),
> +       JH7100_GATE(JH7100_CLK_VP6INTC_APB, "vp6intc_apb", "apb2_bus", 0),
> +       JH7100_GATE(JH7100_CLK_PWM_APB, "pwm_apb", "apb2_bus", 0),
> +       JH7100_GATE(JH7100_CLK_MSI_APB, "msi_apb", "apb2_bus", 0),
> +       JH7100_GATE(JH7100_CLK_TEMP_APB, "temp_apb", "apb2_bus", 0),
> +       JH7100_GDIV(JH7100_CLK_TEMP_SENSE, "temp_sense", "osc_sys", 31, 0),
> +       JH7100_GATE(JH7100_CLK_SYSERR_APB, "syserr_apb", "apb2_bus", 0),
> +};
> +
> +static struct clk_hw *clk_starfive_jh7100_get(struct of_phandle_args *clkspec, void *data)
> +{
> +       struct clk_starfive_jh7100_priv *priv = data;
> +       unsigned int idx = clkspec->args[0];
> +
> +       if (idx >= JH7100_CLK_END) {
> +               dev_err(priv->dev, "invalid clock index %u\n", idx);

We should pull this sort of error message up into the core instead of
have it in every driver. It also doesn't look very meaningful to print
the name of the device that's providing the clks vs. the name of the
device that's requesting the clk that can't be found.

> +               return ERR_PTR(-EINVAL);
> +       }
> +
> +       if (idx >= JH7100_CLK_PLL0_OUT)
> +               return priv->pll[idx - JH7100_CLK_PLL0_OUT];
> +
> +       return &priv->reg[idx].hw;
> +}
> +
> +static int __init clk_starfive_jh7100_probe(struct platform_device *pdev)

Drop __init as this can be called after kernel init is over.

> +{
> +       struct clk_starfive_jh7100_priv *priv;
> +       unsigned int idx;
> +       int ret;
> +
> +       priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
> +       if (!priv)
> +               return -ENOMEM;
> +
> +       spin_lock_init(&priv->rmw_lock);
> +       priv->dev = &pdev->dev;
> +       priv->base = devm_platform_ioremap_resource(pdev, 0);
> +       if (IS_ERR(priv->base))
> +               return PTR_ERR(priv->base);
> +
> +       priv->pll[0] = devm_clk_hw_register_fixed_factor(priv->dev, "pll0_out",
> +                                                        "osc_sys", 0, 40, 1);
> +       if (IS_ERR(priv->pll[0]))
> +               return PTR_ERR(priv->pll[0]);
> +
> +       priv->pll[1] = devm_clk_hw_register_fixed_factor(priv->dev, "pll1_out",
> +                                                        "osc_sys", 0, 64, 1);
> +       if (IS_ERR(priv->pll[1]))
> +               return PTR_ERR(priv->pll[1]);
> +
> +       priv->pll[2] = devm_clk_hw_register_fixed_factor(priv->dev, "pll2_out",
> +                                                        "pll2_refclk", 0, 55, 1);
> +       if (IS_ERR(priv->pll[2]))
> +               return PTR_ERR(priv->pll[2]);
> +
> +       for (idx = 0; idx < JH7100_CLK_PLL0_OUT; idx++) {
> +               u32 max_parent = (jh7100_clk_data[idx].max & JH7100_CLK_MUX_MASK) >>
> +                                JH7100_CLK_MUX_SHIFT;
> +               struct clk_init_data init = {
> +                       .name = jh7100_clk_data[idx].name,
> +                       .ops = jh7100_clk_data[idx].ops,
> +                       .num_parents = max_parent + 1,
> +                       .flags = jh7100_clk_data[idx].flags,
> +               };
> +               struct jh7100_clk *clk = &priv->reg[idx];
> +
> +               if (init.num_parents > 1)
> +                       init.parent_names = jh7100_clk_data[idx].parents;
> +               else
> +                       init.parent_names = &jh7100_clk_data[idx].parent;

Can you use clk_parent_data instead of parent_names? To make the object
size even smaller you can use the DT index instead of the .fw_name
field. 

> +
> +               clk->hw.init = &init;
> +               clk->idx = idx;
> +               clk->max = jh7100_clk_data[idx].max;
> +
> +               ret = clk_hw_register(priv->dev, &clk->hw);

Why not use devm_clk_hw_register()?

> +               if (ret)
> +                       goto err;
> +       }
> +
> +       ret = devm_of_clk_add_hw_provider(priv->dev, clk_starfive_jh7100_get, priv);
> +       if (ret)
> +               goto err;
> +
> +       return 0;
> +err:
> +       while (idx)
> +               clk_hw_unregister(&priv->reg[--idx].hw);
> +       return ret;
> +}
> +
> +static const struct of_device_id clk_starfive_jh7100_match[] = {
> +       { .compatible = "starfive,jh7100-clkgen" },
> +       { /* sentinel */ }
> +};

Please add MODULE_DEVICE_TABLE()

> +
> +static struct platform_driver clk_starfive_jh7100_driver = {
> +       .probe = clk_starfive_jh7100_probe,
> +       .driver = {

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 06/16] clk: starfive: Add JH7100 clock generator driver
  2021-10-26 20:19     ` Stephen Boyd
@ 2021-10-26 22:35       ` Emil Renner Berthing
  -1 siblings, 0 replies; 143+ messages in thread
From: Emil Renner Berthing @ 2021-10-26 22:35 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	linux-clk, open list:GPIO SUBSYSTEM, linux-riscv,
	open list:SERIAL DRIVERS, Geert Uytterhoeven, Palmer Dabbelt,
	Paul Walmsley, Rob Herring, Michael Turquette, Thomas Gleixner,
	Marc Zyngier, Philipp Zabel, Linus Walleij, Greg Kroah-Hartman,
	Daniel Lezcano, Andy Shevchenko, Jiri Slaby, Maximilian Luz,
	Sagar Kadam, Drew Fustini, Michael Zhu, Fu Wei, Anup Patel,
	Atish Patra, Matteo Croce, Linux Kernel Mailing List

On Tue, 26 Oct 2021 at 22:20, Stephen Boyd <sboyd@kernel.org> wrote:
> Quoting Emil Renner Berthing (2021-10-21 10:42:13)
> > +struct jh7100_clk {
> > +       struct clk_hw hw;
> > +       unsigned int idx;
> > +       u32 max;
>
> Why u32?

The idea here was to mirror the configuration register when all valid
fields are set to their maximum value, so that the clk_ops methods
could check which features of this clock was enabled. But you're right
none of the methods actually need that and only the dividers use this
to know the maximum divider value, so it might as well be an unsigned
int max_div.

> > +};
> > +
> > +struct clk_starfive_jh7100_priv {
> > +       /* protect registers against overlapping read-modify-write */
> > +       spinlock_t rmw_lock;
>
> Does overlapping mean concurrent?

Yes, sorry.

> Do different clks share the same registers?

No, each clock has their own register, but they use that register both
to gate the clock and other configuration. The Locking chapter of
Documentation/driver-api/clk.rst talks about the prepare lock and the
enable lock and then says:
"However, access to resources that are shared between operations of
the two groups needs to be protected by the drivers. An example of
such a resource would be a register that controls both the clock rate
and the clock enable/disable state."

> > +       struct device *dev;
> > +       void __iomem *base;
> > +       struct clk_hw *pll[3];
> > +       struct jh7100_clk reg[JH7100_CLK_PLL0_OUT];
> > +};
> > +
> > +static int jh7100_clk_is_enabled(struct clk_hw *hw)
> > +{
> > +       struct jh7100_clk *clk = jh7100_clk_from(hw);
> > +
> > +       return !!(jh7100_clk_reg_get(clk) & JH7100_CLK_ENABLE);
> > +}
> > +
> > +static int jh7100_clk_is_parent_enabled(struct clk_hw *hw)
> > +{
> > +       return clk_hw_is_enabled(clk_hw_get_parent(hw));
>
> Why do we need this function? The parent being enabled implies this clk
> is enabled if this clk can't gate itself but then knowing this clk is
> enabled is useful for what?

Probably only useful to me getting an overview of which clocks were
actually enabled by grepping clk_summary. I'll delete it.

...

> > +static int jh7100_clk_set_parent(struct clk_hw *hw, u8 index)
> > +{
> > +       struct jh7100_clk *clk = jh7100_clk_from(hw);
> > +       u32 value = (u32)index << JH7100_CLK_MUX_SHIFT;
> > +
> > +       dev_dbg(jh7100_priv_from(clk)->dev, "set_parent(%s, %u)\n",
> > +               clk_hw_get_name(&clk->hw), index);
>
> Please remove these dev_dbg() messages. We have tracepoints for general
> clk operations and the driver shouldn't duplicate that.

Gotcha.

> > +
> > +static const struct clk_ops jh7100_clk_inv_ops = {
> > +       .is_enabled = jh7100_clk_is_parent_enabled,
> > +       .get_phase = jh7100_clk_get_phase,
> > +       .set_phase = jh7100_clk_set_phase,
> > +       .debug_init = jh7100_clk_debug_init,
> > +};
> > +
> > +#define JH7100_GATE(_idx, _name, _parent, _flags) [_idx] = { \
>
> Typical macro style is to tab out the \ to a single column

Ah, thanks. Will fix.

> > +       .name = _name, \
> > +       .ops = &jh7100_clk_gate_ops, \
> > +       .parent = _parent, \
> > +       .flags = CLK_SET_RATE_PARENT | (_flags), \
> > +       .max = JH7100_CLK_ENABLE, \
> > +}
> > +
> > +#define JH7100__DIV(_idx, _name, _parent, _max) [_idx] = { \
> > +       .name = _name, \
> > +       .ops = &jh7100_clk_div_ops, \
> > +       .parent = _parent, \
> > +       .flags = 0, \
> > +       .max = _max, \
> > +}
> > +
> > +#define JH7100_GDIV(_idx, _name, _parent, _max, _flags) [_idx] = { \
> > +       .name = _name, \
> > +       .ops = &jh7100_clk_gdiv_ops, \
> > +       .parent = _parent, \
> > +       .flags = (_flags), \
> > +       .max = JH7100_CLK_ENABLE | (_max), \
> > +}
> > +
> > +#define JH7100__MUX(_idx, _name, _parents) [_idx] = { \
> > +       .name = _name, \
> > +       .ops = &jh7100_clk_mux_ops, \
> > +       .parents = _parents, \
> > +       .flags = 0, \
> > +       .max = (ARRAY_SIZE(_parents) - 1) << JH7100_CLK_MUX_SHIFT, \
> > +}
> > +
> > +#define JH7100_GMUX(_idx, _name, _parents, _flags) [_idx] = { \
> > +       .name = _name, \
> > +       .ops = &jh7100_clk_gmux_ops, \
> > +       .parents = _parents, \
> > +       .flags = (_flags), \
> > +       .max = JH7100_CLK_ENABLE | \
> > +               ((ARRAY_SIZE(_parents) - 1) << JH7100_CLK_MUX_SHIFT), \
> > +}
> > +
> > +#define JH7100__INV(_idx, _name, _parent) [_idx] = { \
> > +       .name = _name, \
> > +       .ops = &jh7100_clk_inv_ops, \
> > +       .parent = _parent, \
> > +       .flags = CLK_SET_RATE_PARENT, \
> > +       .max = JH7100_CLK_INVERT, \
> > +}
> > +
> > +static const struct {
> > +       const char *name;
> > +       const struct clk_ops *ops;
> > +       union {
> > +               const char *parent;
> > +               const char *const *parents;
> > +       };
> > +       unsigned long flags;
> > +       u32 max;
> > +} jh7100_clk_data[] __initconst = {
> > +       JH7100__MUX(JH7100_CLK_CPUNDBUS_ROOT, "cpundbus_root", cpundbus_root_sels),
> > +       JH7100__MUX(JH7100_CLK_DLA_ROOT, "dla_root", dla_root_sels),
> > +       JH7100__MUX(JH7100_CLK_DSP_ROOT, "dsp_root", dsp_root_sels),
> > +       JH7100__MUX(JH7100_CLK_GMACUSB_ROOT, "gmacusb_root", gmacusb_root_sels),
> > +       JH7100__MUX(JH7100_CLK_PERH0_ROOT, "perh0_root", perh0_root_sels),
> > +       JH7100__MUX(JH7100_CLK_PERH1_ROOT, "perh1_root", perh1_root_sels),
> > +       JH7100__MUX(JH7100_CLK_VIN_ROOT, "vin_root", vin_root_sels),
> > +       JH7100__MUX(JH7100_CLK_VOUT_ROOT, "vout_root", vout_root_sels),
> > +       JH7100_GDIV(JH7100_CLK_AUDIO_ROOT, "audio_root", "pll0_out", 8, 0),
> > +       JH7100__MUX(JH7100_CLK_CDECHIFI4_ROOT, "cdechifi4_root", cdechifi4_root_sels),
> > +       JH7100__MUX(JH7100_CLK_CDEC_ROOT, "cdec_root", cdec_root_sels),
> > +       JH7100__MUX(JH7100_CLK_VOUTBUS_ROOT, "voutbus_root", voutbus_root_sels),
> > +       JH7100__DIV(JH7100_CLK_CPUNBUS_ROOT_DIV, "cpunbus_root_div", "cpundbus_root", 2),
> > +       JH7100__DIV(JH7100_CLK_DSP_ROOT_DIV, "dsp_root_div", "dsp_root", 4),
> > +       JH7100__DIV(JH7100_CLK_PERH0_SRC, "perh0_src", "perh0_root", 4),
> > +       JH7100__DIV(JH7100_CLK_PERH1_SRC, "perh1_src", "perh1_root", 4),
> > +       JH7100_GDIV(JH7100_CLK_PLL0_TESTOUT, "pll0_testout", "perh0_src", 31, 0),
> > +       JH7100_GDIV(JH7100_CLK_PLL1_TESTOUT, "pll1_testout", "dla_root", 31, 0),
> > +       JH7100_GDIV(JH7100_CLK_PLL2_TESTOUT, "pll2_testout", "perh1_src", 31, 0),
> > +       JH7100__MUX(JH7100_CLK_PLL2_REF, "pll2_refclk", pll2_refclk_sels),
> > +       JH7100__DIV(JH7100_CLK_CPU_CORE, "cpu_core", "cpunbus_root_div", 8),
> > +       JH7100__DIV(JH7100_CLK_CPU_AXI, "cpu_axi", "cpu_core", 8),
> > +       JH7100__DIV(JH7100_CLK_AHB_BUS, "ahb_bus", "cpunbus_root_div", 8),
> > +       JH7100__DIV(JH7100_CLK_APB1_BUS, "apb1_bus", "ahb_bus", 8),
> > +       JH7100__DIV(JH7100_CLK_APB2_BUS, "apb2_bus", "ahb_bus", 8),
> > +       JH7100_GATE(JH7100_CLK_DOM3AHB_BUS, "dom3ahb_bus", "ahb_bus", CLK_IGNORE_UNUSED),
> > +       JH7100_GATE(JH7100_CLK_DOM7AHB_BUS, "dom7ahb_bus", "ahb_bus", CLK_IGNORE_UNUSED),
> > +       JH7100_GATE(JH7100_CLK_U74_CORE0, "u74_core0", "cpu_core", CLK_IGNORE_UNUSED),
> > +       JH7100_GDIV(JH7100_CLK_U74_CORE1, "u74_core1", "cpu_core", 8, CLK_IGNORE_UNUSED),
> > +       JH7100_GATE(JH7100_CLK_U74_AXI, "u74_axi", "cpu_axi", CLK_IGNORE_UNUSED),
> > +       JH7100_GATE(JH7100_CLK_U74RTC_TOGGLE, "u74rtc_toggle", "osc_sys", CLK_IGNORE_UNUSED),
> > +       JH7100_GATE(JH7100_CLK_SGDMA2P_AXI, "sgdma2p_axi", "cpu_axi", 0),
> > +       JH7100_GATE(JH7100_CLK_DMA2PNOC_AXI, "dma2pnoc_axi", "cpu_axi", 0),
> > +       JH7100_GATE(JH7100_CLK_SGDMA2P_AHB, "sgdma2p_ahb", "ahb_bus", 0),
> > +       JH7100__DIV(JH7100_CLK_DLA_BUS, "dla_bus", "dla_root", 4),
> > +       JH7100_GATE(JH7100_CLK_DLA_AXI, "dla_axi", "dla_bus", 0),
> > +       JH7100_GATE(JH7100_CLK_DLANOC_AXI, "dlanoc_axi", "dla_bus", 0),
> > +       JH7100_GATE(JH7100_CLK_DLA_APB, "dla_apb", "apb1_bus", 0),
> > +       JH7100_GDIV(JH7100_CLK_VP6_CORE, "vp6_core", "dsp_root_div", 4, 0),
> > +       JH7100__DIV(JH7100_CLK_VP6BUS_SRC, "vp6bus_src", "dsp_root", 4),
> > +       JH7100_GDIV(JH7100_CLK_VP6_AXI, "vp6_axi", "vp6bus_src", 4, 0),
> > +       JH7100__DIV(JH7100_CLK_VCDECBUS_SRC, "vcdecbus_src", "cdechifi4_root", 4),
> > +       JH7100__DIV(JH7100_CLK_VDEC_BUS, "vdec_bus", "vcdecbus_src", 8),
> > +       JH7100_GATE(JH7100_CLK_VDEC_AXI, "vdec_axi", "vdec_bus", 0),
> > +       JH7100_GATE(JH7100_CLK_VDECBRG_MAIN, "vdecbrg_mainclk", "vdec_bus", 0),
> > +       JH7100_GDIV(JH7100_CLK_VDEC_BCLK, "vdec_bclk", "vcdecbus_src", 8, 0),
> > +       JH7100_GDIV(JH7100_CLK_VDEC_CCLK, "vdec_cclk", "cdec_root", 8, 0),
> > +       JH7100_GATE(JH7100_CLK_VDEC_APB, "vdec_apb", "apb1_bus", 0),
> > +       JH7100_GDIV(JH7100_CLK_JPEG_AXI, "jpeg_axi", "cpunbus_root_div", 8, 0),
> > +       JH7100_GDIV(JH7100_CLK_JPEG_CCLK, "jpeg_cclk", "cpunbus_root_div", 8, 0),
> > +       JH7100_GATE(JH7100_CLK_JPEG_APB, "jpeg_apb", "apb1_bus", 0),
> > +       JH7100_GDIV(JH7100_CLK_GC300_2X, "gc300_2x", "cdechifi4_root", 8, 0),
> > +       JH7100_GATE(JH7100_CLK_GC300_AHB, "gc300_ahb", "ahb_bus", 0),
> > +       JH7100__DIV(JH7100_CLK_JPCGC300_AXIBUS, "jpcgc300_axibus", "vcdecbus_src", 8),
> > +       JH7100_GATE(JH7100_CLK_GC300_AXI, "gc300_axi", "jpcgc300_axibus", 0),
> > +       JH7100_GATE(JH7100_CLK_JPCGC300_MAIN, "jpcgc300_mainclk", "jpcgc300_axibus", 0),
> > +       JH7100__DIV(JH7100_CLK_VENC_BUS, "venc_bus", "vcdecbus_src", 8),
> > +       JH7100_GATE(JH7100_CLK_VENC_AXI, "venc_axi", "venc_bus", 0),
> > +       JH7100_GATE(JH7100_CLK_VENCBRG_MAIN, "vencbrg_mainclk", "venc_bus", 0),
> > +       JH7100_GDIV(JH7100_CLK_VENC_BCLK, "venc_bclk", "vcdecbus_src", 8, 0),
> > +       JH7100_GDIV(JH7100_CLK_VENC_CCLK, "venc_cclk", "cdec_root", 8, 0),
> > +       JH7100_GATE(JH7100_CLK_VENC_APB, "venc_apb", "apb1_bus", 0),
> > +       JH7100_GDIV(JH7100_CLK_DDRPLL_DIV2, "ddrpll_div2", "pll1_out", 2, CLK_IGNORE_UNUSED),
> > +       JH7100_GDIV(JH7100_CLK_DDRPLL_DIV4, "ddrpll_div4", "ddrpll_div2", 2, CLK_IGNORE_UNUSED),
> > +       JH7100_GDIV(JH7100_CLK_DDRPLL_DIV8, "ddrpll_div8", "ddrpll_div4", 2, CLK_IGNORE_UNUSED),
> > +       JH7100_GDIV(JH7100_CLK_DDROSC_DIV2, "ddrosc_div2", "osc_sys", 2, CLK_IGNORE_UNUSED),
> > +       JH7100_GMUX(JH7100_CLK_DDRC0, "ddrc0", ddrc0_sels, CLK_IGNORE_UNUSED),
> > +       JH7100_GMUX(JH7100_CLK_DDRC1, "ddrc1", ddrc1_sels, CLK_IGNORE_UNUSED),
>
> Is it really unused? Or it is CLK_IS_CRITICAL?

Ah no. CLK_IS_CRITICAL is exactly what they are, thanks.

> > +       JH7100_GATE(JH7100_CLK_DDRPHY_APB, "ddrphy_apb", "apb1_bus", CLK_IGNORE_UNUSED),
> > +       JH7100__DIV(JH7100_CLK_NOC_ROB, "noc_rob", "cpunbus_root_div", 8),
> > +       JH7100__DIV(JH7100_CLK_NOC_COG, "noc_cog", "dla_root", 8),
> > +       JH7100_GATE(JH7100_CLK_NNE_AHB, "nne_ahb", "ahb_bus", 0),
> > +       JH7100__DIV(JH7100_CLK_NNEBUS_SRC1, "nnebus_src1", "dsp_root", 4),
> > +       JH7100__MUX(JH7100_CLK_NNE_BUS, "nne_bus", nne_bus_sels),
> > +       JH7100_GATE(JH7100_CLK_NNE_AXI, "nne_axi", "nne_bus", 0),
> > +       JH7100_GATE(JH7100_CLK_NNENOC_AXI, "nnenoc_axi", "nne_bus", 0),
> > +       JH7100_GATE(JH7100_CLK_DLASLV_AXI, "dlaslv_axi", "nne_bus", 0),
> > +       JH7100_GATE(JH7100_CLK_DSPX2C_AXI, "dspx2c_axi", "nne_bus", CLK_IGNORE_UNUSED),
> > +       JH7100__DIV(JH7100_CLK_HIFI4_SRC, "hifi4_src", "cdechifi4_root", 4),
> > +       JH7100__DIV(JH7100_CLK_HIFI4_COREFREE, "hifi4_corefree", "hifi4_src", 8),
> > +       JH7100_GATE(JH7100_CLK_HIFI4_CORE, "hifi4_core", "hifi4_corefree", 0),
> > +       JH7100__DIV(JH7100_CLK_HIFI4_BUS, "hifi4_bus", "hifi4_corefree", 8),
> > +       JH7100_GATE(JH7100_CLK_HIFI4_AXI, "hifi4_axi", "hifi4_bus", 0),
> > +       JH7100_GATE(JH7100_CLK_HIFI4NOC_AXI, "hifi4noc_axi", "hifi4_bus", 0),
> > +       JH7100__DIV(JH7100_CLK_SGDMA1P_BUS, "sgdma1p_bus", "cpunbus_root_div", 8),
> > +       JH7100_GATE(JH7100_CLK_SGDMA1P_AXI, "sgdma1p_axi", "sgdma1p_bus", 0),
> > +       JH7100_GATE(JH7100_CLK_DMA1P_AXI, "dma1p_axi", "sgdma1p_bus", 0),
> > +       JH7100_GDIV(JH7100_CLK_X2C_AXI, "x2c_axi", "cpunbus_root_div", 8, CLK_IGNORE_UNUSED),
> > +       JH7100__DIV(JH7100_CLK_USB_BUS, "usb_bus", "cpunbus_root_div", 8),
> > +       JH7100_GATE(JH7100_CLK_USB_AXI, "usb_axi", "usb_bus", 0),
> > +       JH7100_GATE(JH7100_CLK_USBNOC_AXI, "usbnoc_axi", "usb_bus", 0),
> > +       JH7100__DIV(JH7100_CLK_USBPHY_ROOTDIV, "usbphy_rootdiv", "gmacusb_root", 4),
> > +       JH7100_GDIV(JH7100_CLK_USBPHY_125M, "usbphy_125m", "usbphy_rootdiv", 8, 0),
> > +       JH7100_GDIV(JH7100_CLK_USBPHY_PLLDIV25M, "usbphy_plldiv25m", "usbphy_rootdiv", 32, 0),
> > +       JH7100__MUX(JH7100_CLK_USBPHY_25M, "usbphy_25m", usbphy_25m_sels),
> > +       JH7100__DIV(JH7100_CLK_AUDIO_DIV, "audio_div", "audio_root", 131072),
> > +       JH7100_GATE(JH7100_CLK_AUDIO_SRC, "audio_src", "audio_div", 0),
> > +       JH7100_GATE(JH7100_CLK_AUDIO_12288, "audio_12288", "osc_aud", 0),
> > +       JH7100_GDIV(JH7100_CLK_VIN_SRC, "vin_src", "vin_root", 4, 0),
> > +       JH7100__DIV(JH7100_CLK_ISP0_BUS, "isp0_bus", "vin_src", 8),
> > +       JH7100_GATE(JH7100_CLK_ISP0_AXI, "isp0_axi", "isp0_bus", 0),
> > +       JH7100_GATE(JH7100_CLK_ISP0NOC_AXI, "isp0noc_axi", "isp0_bus", 0),
> > +       JH7100_GATE(JH7100_CLK_ISPSLV_AXI, "ispslv_axi", "isp0_bus", 0),
> > +       JH7100__DIV(JH7100_CLK_ISP1_BUS, "isp1_bus", "vin_src", 8),
> > +       JH7100_GATE(JH7100_CLK_ISP1_AXI, "isp1_axi", "isp1_bus", 0),
> > +       JH7100_GATE(JH7100_CLK_ISP1NOC_AXI, "isp1noc_axi", "isp1_bus", 0),
> > +       JH7100__DIV(JH7100_CLK_VIN_BUS, "vin_bus", "vin_src", 8),
> > +       JH7100_GATE(JH7100_CLK_VIN_AXI, "vin_axi", "vin_bus", 0),
> > +       JH7100_GATE(JH7100_CLK_VINNOC_AXI, "vinnoc_axi", "vin_bus", 0),
> > +       JH7100_GDIV(JH7100_CLK_VOUT_SRC, "vout_src", "vout_root", 4, 0),
> > +       JH7100__DIV(JH7100_CLK_DISPBUS_SRC, "dispbus_src", "voutbus_root", 4),
> > +       JH7100__DIV(JH7100_CLK_DISP_BUS, "disp_bus", "dispbus_src", 4),
> > +       JH7100_GATE(JH7100_CLK_DISP_AXI, "disp_axi", "disp_bus", 0),
> > +       JH7100_GATE(JH7100_CLK_DISPNOC_AXI, "dispnoc_axi", "disp_bus", 0),
> > +       JH7100_GATE(JH7100_CLK_SDIO0_AHB, "sdio0_ahb", "ahb_bus", 0),
> > +       JH7100_GDIV(JH7100_CLK_SDIO0_CCLKINT, "sdio0_cclkint", "perh0_src", 24, 0),
> > +       JH7100__INV(JH7100_CLK_SDIO0_CCLKINT_INV, "sdio0_cclkint_inv", "sdio0_cclkint"),
> > +       JH7100_GATE(JH7100_CLK_SDIO1_AHB, "sdio1_ahb", "ahb_bus", 0),
> > +       JH7100_GDIV(JH7100_CLK_SDIO1_CCLKINT, "sdio1_cclkint", "perh1_src", 24, 0),
> > +       JH7100__INV(JH7100_CLK_SDIO1_CCLKINT_INV, "sdio1_cclkint_inv", "sdio1_cclkint"),
> > +       JH7100_GATE(JH7100_CLK_GMAC_AHB, "gmac_ahb", "ahb_bus", 0),
> > +       JH7100__DIV(JH7100_CLK_GMAC_ROOT_DIV, "gmac_root_div", "gmacusb_root", 8),
> > +       JH7100_GDIV(JH7100_CLK_GMAC_PTP_REF, "gmac_ptp_refclk", "gmac_root_div", 31, 0),
> > +       JH7100_GDIV(JH7100_CLK_GMAC_GTX, "gmac_gtxclk", "gmac_root_div", 255, 0),
> > +       JH7100_GDIV(JH7100_CLK_GMAC_RMII_TX, "gmac_rmii_txclk", "gmac_rmii_ref", 8, 0),
> > +       JH7100_GDIV(JH7100_CLK_GMAC_RMII_RX, "gmac_rmii_rxclk", "gmac_rmii_ref", 8, 0),
> > +       JH7100__MUX(JH7100_CLK_GMAC_TX, "gmac_tx", gmac_tx_sels),
> > +       JH7100__INV(JH7100_CLK_GMAC_TX_INV, "gmac_tx_inv", "gmac_tx"),
> > +       JH7100__MUX(JH7100_CLK_GMAC_RX_PRE, "gmac_rx_pre", gmac_rx_pre_sels),
> > +       JH7100__INV(JH7100_CLK_GMAC_RX_INV, "gmac_rx_inv", "gmac_rx_pre"),
> > +       JH7100_GATE(JH7100_CLK_GMAC_RMII, "gmac_rmii", "gmac_rmii_ref", 0),
> > +       JH7100_GDIV(JH7100_CLK_GMAC_TOPHYREF, "gmac_tophyref", "gmac_root_div", 127, 0),
> > +       JH7100_GATE(JH7100_CLK_SPI2AHB_AHB, "spi2ahb_ahb", "ahb_bus", 0),
> > +       JH7100_GDIV(JH7100_CLK_SPI2AHB_CORE, "spi2ahb_core", "perh0_src", 31, 0),
> > +       JH7100_GATE(JH7100_CLK_EZMASTER_AHB, "ezmaster_ahb", "ahb_bus", 0),
> > +       JH7100_GATE(JH7100_CLK_E24_AHB, "e24_ahb", "ahb_bus", 0),
> > +       JH7100_GATE(JH7100_CLK_E24RTC_TOGGLE, "e24rtc_toggle", "osc_sys", 0),
> > +       JH7100_GATE(JH7100_CLK_QSPI_AHB, "qspi_ahb", "ahb_bus", 0),
> > +       JH7100_GATE(JH7100_CLK_QSPI_APB, "qspi_apb", "apb1_bus", 0),
> > +       JH7100_GDIV(JH7100_CLK_QSPI_REF, "qspi_refclk", "perh0_src", 31, 0),
> > +       JH7100_GATE(JH7100_CLK_SEC_AHB, "sec_ahb", "ahb_bus", 0),
> > +       JH7100_GATE(JH7100_CLK_AES, "aes_clk", "sec_ahb", 0),
> > +       JH7100_GATE(JH7100_CLK_SHA, "sha_clk", "sec_ahb", 0),
> > +       JH7100_GATE(JH7100_CLK_PKA, "pka_clk", "sec_ahb", 0),
> > +       JH7100_GATE(JH7100_CLK_TRNG_APB, "trng_apb", "apb1_bus", 0),
> > +       JH7100_GATE(JH7100_CLK_OTP_APB, "otp_apb", "apb1_bus", 0),
> > +       JH7100_GATE(JH7100_CLK_UART0_APB, "uart0_apb", "apb1_bus", 0),
> > +       JH7100_GDIV(JH7100_CLK_UART0_CORE, "uart0_core", "perh1_src", 63, 0),
> > +       JH7100_GATE(JH7100_CLK_UART1_APB, "uart1_apb", "apb1_bus", 0),
> > +       JH7100_GDIV(JH7100_CLK_UART1_CORE, "uart1_core", "perh1_src", 63, 0),
> > +       JH7100_GATE(JH7100_CLK_SPI0_APB, "spi0_apb", "apb1_bus", 0),
> > +       JH7100_GDIV(JH7100_CLK_SPI0_CORE, "spi0_core", "perh1_src", 63, 0),
> > +       JH7100_GATE(JH7100_CLK_SPI1_APB, "spi1_apb", "apb1_bus", 0),
> > +       JH7100_GDIV(JH7100_CLK_SPI1_CORE, "spi1_core", "perh1_src", 63, 0),
> > +       JH7100_GATE(JH7100_CLK_I2C0_APB, "i2c0_apb", "apb1_bus", 0),
> > +       JH7100_GDIV(JH7100_CLK_I2C0_CORE, "i2c0_core", "perh1_src", 63, 0),
> > +       JH7100_GATE(JH7100_CLK_I2C1_APB, "i2c1_apb", "apb1_bus", 0),
> > +       JH7100_GDIV(JH7100_CLK_I2C1_CORE, "i2c1_core", "perh1_src", 63, 0),
> > +       JH7100_GATE(JH7100_CLK_GPIO_APB, "gpio_apb", "apb1_bus", 0),
> > +       JH7100_GATE(JH7100_CLK_UART2_APB, "uart2_apb", "apb2_bus", 0),
> > +       JH7100_GDIV(JH7100_CLK_UART2_CORE, "uart2_core", "perh0_src", 63, 0),
> > +       JH7100_GATE(JH7100_CLK_UART3_APB, "uart3_apb", "apb2_bus", 0),
> > +       JH7100_GDIV(JH7100_CLK_UART3_CORE, "uart3_core", "perh0_src", 63, 0),
> > +       JH7100_GATE(JH7100_CLK_SPI2_APB, "spi2_apb", "apb2_bus", 0),
> > +       JH7100_GDIV(JH7100_CLK_SPI2_CORE, "spi2_core", "perh0_src", 63, 0),
> > +       JH7100_GATE(JH7100_CLK_SPI3_APB, "spi3_apb", "apb2_bus", 0),
> > +       JH7100_GDIV(JH7100_CLK_SPI3_CORE, "spi3_core", "perh0_src", 63, 0),
> > +       JH7100_GATE(JH7100_CLK_I2C2_APB, "i2c2_apb", "apb2_bus", 0),
> > +       JH7100_GDIV(JH7100_CLK_I2C2_CORE, "i2c2_core", "perh0_src", 63, 0),
> > +       JH7100_GATE(JH7100_CLK_I2C3_APB, "i2c3_apb", "apb2_bus", 0),
> > +       JH7100_GDIV(JH7100_CLK_I2C3_CORE, "i2c3_core", "perh0_src", 63, 0),
> > +       JH7100_GATE(JH7100_CLK_WDTIMER_APB, "wdtimer_apb", "apb2_bus", 0),
> > +       JH7100_GDIV(JH7100_CLK_WDT_CORE, "wdt_coreclk", "perh0_src", 63, 0),
> > +       JH7100_GDIV(JH7100_CLK_TIMER0_CORE, "timer0_coreclk", "perh0_src", 63, 0),
> > +       JH7100_GDIV(JH7100_CLK_TIMER1_CORE, "timer1_coreclk", "perh0_src", 63, 0),
> > +       JH7100_GDIV(JH7100_CLK_TIMER2_CORE, "timer2_coreclk", "perh0_src", 63, 0),
> > +       JH7100_GDIV(JH7100_CLK_TIMER3_CORE, "timer3_coreclk", "perh0_src", 63, 0),
> > +       JH7100_GDIV(JH7100_CLK_TIMER4_CORE, "timer4_coreclk", "perh0_src", 63, 0),
> > +       JH7100_GDIV(JH7100_CLK_TIMER5_CORE, "timer5_coreclk", "perh0_src", 63, 0),
> > +       JH7100_GDIV(JH7100_CLK_TIMER6_CORE, "timer6_coreclk", "perh0_src", 63, 0),
> > +       JH7100_GATE(JH7100_CLK_VP6INTC_APB, "vp6intc_apb", "apb2_bus", 0),
> > +       JH7100_GATE(JH7100_CLK_PWM_APB, "pwm_apb", "apb2_bus", 0),
> > +       JH7100_GATE(JH7100_CLK_MSI_APB, "msi_apb", "apb2_bus", 0),
> > +       JH7100_GATE(JH7100_CLK_TEMP_APB, "temp_apb", "apb2_bus", 0),
> > +       JH7100_GDIV(JH7100_CLK_TEMP_SENSE, "temp_sense", "osc_sys", 31, 0),
> > +       JH7100_GATE(JH7100_CLK_SYSERR_APB, "syserr_apb", "apb2_bus", 0),
> > +};
> > +
> > +static struct clk_hw *clk_starfive_jh7100_get(struct of_phandle_args *clkspec, void *data)
> > +{
> > +       struct clk_starfive_jh7100_priv *priv = data;
> > +       unsigned int idx = clkspec->args[0];
> > +
> > +       if (idx >= JH7100_CLK_END) {
> > +               dev_err(priv->dev, "invalid clock index %u\n", idx);
>
> We should pull this sort of error message up into the core instead of
> have it in every driver. It also doesn't look very meaningful to print
> the name of the device that's providing the clks vs. the name of the
> device that's requesting the clk that can't be found.

Makes sense. I'll just remove the message then.

> > +               return ERR_PTR(-EINVAL);
> > +       }
> > +
> > +       if (idx >= JH7100_CLK_PLL0_OUT)
> > +               return priv->pll[idx - JH7100_CLK_PLL0_OUT];
> > +
> > +       return &priv->reg[idx].hw;
> > +}
> > +
> > +static int __init clk_starfive_jh7100_probe(struct platform_device *pdev)
>
> Drop __init as this can be called after kernel init is over.

Oh interesting, I'd like to know when that can happen. The comment for
the builtin_platform_driver macro says it's just a wrapper for
device_initcall.

Won't we then need to remove all the __initconst tags too since the
probe function walks through jh7100_clk_data which eventually
references all __initconst data?

> > +{
> > +       struct clk_starfive_jh7100_priv *priv;
> > +       unsigned int idx;
> > +       int ret;
> > +
> > +       priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
> > +       if (!priv)
> > +               return -ENOMEM;
> > +
> > +       spin_lock_init(&priv->rmw_lock);
> > +       priv->dev = &pdev->dev;
> > +       priv->base = devm_platform_ioremap_resource(pdev, 0);
> > +       if (IS_ERR(priv->base))
> > +               return PTR_ERR(priv->base);
> > +
> > +       priv->pll[0] = devm_clk_hw_register_fixed_factor(priv->dev, "pll0_out",
> > +                                                        "osc_sys", 0, 40, 1);
> > +       if (IS_ERR(priv->pll[0]))
> > +               return PTR_ERR(priv->pll[0]);
> > +
> > +       priv->pll[1] = devm_clk_hw_register_fixed_factor(priv->dev, "pll1_out",
> > +                                                        "osc_sys", 0, 64, 1);
> > +       if (IS_ERR(priv->pll[1]))
> > +               return PTR_ERR(priv->pll[1]);
> > +
> > +       priv->pll[2] = devm_clk_hw_register_fixed_factor(priv->dev, "pll2_out",
> > +                                                        "pll2_refclk", 0, 55, 1);
> > +       if (IS_ERR(priv->pll[2]))
> > +               return PTR_ERR(priv->pll[2]);
> > +
> > +       for (idx = 0; idx < JH7100_CLK_PLL0_OUT; idx++) {
> > +               u32 max_parent = (jh7100_clk_data[idx].max & JH7100_CLK_MUX_MASK) >>
> > +                                JH7100_CLK_MUX_SHIFT;
> > +               struct clk_init_data init = {
> > +                       .name = jh7100_clk_data[idx].name,
> > +                       .ops = jh7100_clk_data[idx].ops,
> > +                       .num_parents = max_parent + 1,
> > +                       .flags = jh7100_clk_data[idx].flags,
> > +               };
> > +               struct jh7100_clk *clk = &priv->reg[idx];
> > +
> > +               if (init.num_parents > 1)
> > +                       init.parent_names = jh7100_clk_data[idx].parents;
> > +               else
> > +                       init.parent_names = &jh7100_clk_data[idx].parent;
>
> Can you use clk_parent_data instead of parent_names? To make the object
> size even smaller you can use the DT index instead of the .fw_name
> field.

Ah cool. I'll look into that.

> > +
> > +               clk->hw.init = &init;
> > +               clk->idx = idx;
> > +               clk->max = jh7100_clk_data[idx].max;
> > +
> > +               ret = clk_hw_register(priv->dev, &clk->hw);
>
> Why not use devm_clk_hw_register()?

I probably could. Just for my understanding that's just to avoid the
loop on error below, because as a builtin driver the device won't
otherwise go away, right?

> > +               if (ret)
> > +                       goto err;
> > +       }
> > +
> > +       ret = devm_of_clk_add_hw_provider(priv->dev, clk_starfive_jh7100_get, priv);
> > +       if (ret)
> > +               goto err;
> > +
> > +       return 0;
> > +err:
> > +       while (idx)
> > +               clk_hw_unregister(&priv->reg[--idx].hw);
> > +       return ret;
> > +}
> > +
> > +static const struct of_device_id clk_starfive_jh7100_match[] = {
> > +       { .compatible = "starfive,jh7100-clkgen" },
> > +       { /* sentinel */ }
> > +};
>
> Please add MODULE_DEVICE_TABLE()

Will do!

Thank you.
/Emil

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 06/16] clk: starfive: Add JH7100 clock generator driver
@ 2021-10-26 22:35       ` Emil Renner Berthing
  0 siblings, 0 replies; 143+ messages in thread
From: Emil Renner Berthing @ 2021-10-26 22:35 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	linux-clk, open list:GPIO SUBSYSTEM, linux-riscv,
	open list:SERIAL DRIVERS, Geert Uytterhoeven, Palmer Dabbelt,
	Paul Walmsley, Rob Herring, Michael Turquette, Thomas Gleixner,
	Marc Zyngier, Philipp Zabel, Linus Walleij, Greg Kroah-Hartman,
	Daniel Lezcano, Andy Shevchenko, Jiri Slaby, Maximilian Luz,
	Sagar Kadam, Drew Fustini, Michael Zhu, Fu Wei, Anup Patel,
	Atish Patra, Matteo Croce, Linux Kernel Mailing List

On Tue, 26 Oct 2021 at 22:20, Stephen Boyd <sboyd@kernel.org> wrote:
> Quoting Emil Renner Berthing (2021-10-21 10:42:13)
> > +struct jh7100_clk {
> > +       struct clk_hw hw;
> > +       unsigned int idx;
> > +       u32 max;
>
> Why u32?

The idea here was to mirror the configuration register when all valid
fields are set to their maximum value, so that the clk_ops methods
could check which features of this clock was enabled. But you're right
none of the methods actually need that and only the dividers use this
to know the maximum divider value, so it might as well be an unsigned
int max_div.

> > +};
> > +
> > +struct clk_starfive_jh7100_priv {
> > +       /* protect registers against overlapping read-modify-write */
> > +       spinlock_t rmw_lock;
>
> Does overlapping mean concurrent?

Yes, sorry.

> Do different clks share the same registers?

No, each clock has their own register, but they use that register both
to gate the clock and other configuration. The Locking chapter of
Documentation/driver-api/clk.rst talks about the prepare lock and the
enable lock and then says:
"However, access to resources that are shared between operations of
the two groups needs to be protected by the drivers. An example of
such a resource would be a register that controls both the clock rate
and the clock enable/disable state."

> > +       struct device *dev;
> > +       void __iomem *base;
> > +       struct clk_hw *pll[3];
> > +       struct jh7100_clk reg[JH7100_CLK_PLL0_OUT];
> > +};
> > +
> > +static int jh7100_clk_is_enabled(struct clk_hw *hw)
> > +{
> > +       struct jh7100_clk *clk = jh7100_clk_from(hw);
> > +
> > +       return !!(jh7100_clk_reg_get(clk) & JH7100_CLK_ENABLE);
> > +}
> > +
> > +static int jh7100_clk_is_parent_enabled(struct clk_hw *hw)
> > +{
> > +       return clk_hw_is_enabled(clk_hw_get_parent(hw));
>
> Why do we need this function? The parent being enabled implies this clk
> is enabled if this clk can't gate itself but then knowing this clk is
> enabled is useful for what?

Probably only useful to me getting an overview of which clocks were
actually enabled by grepping clk_summary. I'll delete it.

...

> > +static int jh7100_clk_set_parent(struct clk_hw *hw, u8 index)
> > +{
> > +       struct jh7100_clk *clk = jh7100_clk_from(hw);
> > +       u32 value = (u32)index << JH7100_CLK_MUX_SHIFT;
> > +
> > +       dev_dbg(jh7100_priv_from(clk)->dev, "set_parent(%s, %u)\n",
> > +               clk_hw_get_name(&clk->hw), index);
>
> Please remove these dev_dbg() messages. We have tracepoints for general
> clk operations and the driver shouldn't duplicate that.

Gotcha.

> > +
> > +static const struct clk_ops jh7100_clk_inv_ops = {
> > +       .is_enabled = jh7100_clk_is_parent_enabled,
> > +       .get_phase = jh7100_clk_get_phase,
> > +       .set_phase = jh7100_clk_set_phase,
> > +       .debug_init = jh7100_clk_debug_init,
> > +};
> > +
> > +#define JH7100_GATE(_idx, _name, _parent, _flags) [_idx] = { \
>
> Typical macro style is to tab out the \ to a single column

Ah, thanks. Will fix.

> > +       .name = _name, \
> > +       .ops = &jh7100_clk_gate_ops, \
> > +       .parent = _parent, \
> > +       .flags = CLK_SET_RATE_PARENT | (_flags), \
> > +       .max = JH7100_CLK_ENABLE, \
> > +}
> > +
> > +#define JH7100__DIV(_idx, _name, _parent, _max) [_idx] = { \
> > +       .name = _name, \
> > +       .ops = &jh7100_clk_div_ops, \
> > +       .parent = _parent, \
> > +       .flags = 0, \
> > +       .max = _max, \
> > +}
> > +
> > +#define JH7100_GDIV(_idx, _name, _parent, _max, _flags) [_idx] = { \
> > +       .name = _name, \
> > +       .ops = &jh7100_clk_gdiv_ops, \
> > +       .parent = _parent, \
> > +       .flags = (_flags), \
> > +       .max = JH7100_CLK_ENABLE | (_max), \
> > +}
> > +
> > +#define JH7100__MUX(_idx, _name, _parents) [_idx] = { \
> > +       .name = _name, \
> > +       .ops = &jh7100_clk_mux_ops, \
> > +       .parents = _parents, \
> > +       .flags = 0, \
> > +       .max = (ARRAY_SIZE(_parents) - 1) << JH7100_CLK_MUX_SHIFT, \
> > +}
> > +
> > +#define JH7100_GMUX(_idx, _name, _parents, _flags) [_idx] = { \
> > +       .name = _name, \
> > +       .ops = &jh7100_clk_gmux_ops, \
> > +       .parents = _parents, \
> > +       .flags = (_flags), \
> > +       .max = JH7100_CLK_ENABLE | \
> > +               ((ARRAY_SIZE(_parents) - 1) << JH7100_CLK_MUX_SHIFT), \
> > +}
> > +
> > +#define JH7100__INV(_idx, _name, _parent) [_idx] = { \
> > +       .name = _name, \
> > +       .ops = &jh7100_clk_inv_ops, \
> > +       .parent = _parent, \
> > +       .flags = CLK_SET_RATE_PARENT, \
> > +       .max = JH7100_CLK_INVERT, \
> > +}
> > +
> > +static const struct {
> > +       const char *name;
> > +       const struct clk_ops *ops;
> > +       union {
> > +               const char *parent;
> > +               const char *const *parents;
> > +       };
> > +       unsigned long flags;
> > +       u32 max;
> > +} jh7100_clk_data[] __initconst = {
> > +       JH7100__MUX(JH7100_CLK_CPUNDBUS_ROOT, "cpundbus_root", cpundbus_root_sels),
> > +       JH7100__MUX(JH7100_CLK_DLA_ROOT, "dla_root", dla_root_sels),
> > +       JH7100__MUX(JH7100_CLK_DSP_ROOT, "dsp_root", dsp_root_sels),
> > +       JH7100__MUX(JH7100_CLK_GMACUSB_ROOT, "gmacusb_root", gmacusb_root_sels),
> > +       JH7100__MUX(JH7100_CLK_PERH0_ROOT, "perh0_root", perh0_root_sels),
> > +       JH7100__MUX(JH7100_CLK_PERH1_ROOT, "perh1_root", perh1_root_sels),
> > +       JH7100__MUX(JH7100_CLK_VIN_ROOT, "vin_root", vin_root_sels),
> > +       JH7100__MUX(JH7100_CLK_VOUT_ROOT, "vout_root", vout_root_sels),
> > +       JH7100_GDIV(JH7100_CLK_AUDIO_ROOT, "audio_root", "pll0_out", 8, 0),
> > +       JH7100__MUX(JH7100_CLK_CDECHIFI4_ROOT, "cdechifi4_root", cdechifi4_root_sels),
> > +       JH7100__MUX(JH7100_CLK_CDEC_ROOT, "cdec_root", cdec_root_sels),
> > +       JH7100__MUX(JH7100_CLK_VOUTBUS_ROOT, "voutbus_root", voutbus_root_sels),
> > +       JH7100__DIV(JH7100_CLK_CPUNBUS_ROOT_DIV, "cpunbus_root_div", "cpundbus_root", 2),
> > +       JH7100__DIV(JH7100_CLK_DSP_ROOT_DIV, "dsp_root_div", "dsp_root", 4),
> > +       JH7100__DIV(JH7100_CLK_PERH0_SRC, "perh0_src", "perh0_root", 4),
> > +       JH7100__DIV(JH7100_CLK_PERH1_SRC, "perh1_src", "perh1_root", 4),
> > +       JH7100_GDIV(JH7100_CLK_PLL0_TESTOUT, "pll0_testout", "perh0_src", 31, 0),
> > +       JH7100_GDIV(JH7100_CLK_PLL1_TESTOUT, "pll1_testout", "dla_root", 31, 0),
> > +       JH7100_GDIV(JH7100_CLK_PLL2_TESTOUT, "pll2_testout", "perh1_src", 31, 0),
> > +       JH7100__MUX(JH7100_CLK_PLL2_REF, "pll2_refclk", pll2_refclk_sels),
> > +       JH7100__DIV(JH7100_CLK_CPU_CORE, "cpu_core", "cpunbus_root_div", 8),
> > +       JH7100__DIV(JH7100_CLK_CPU_AXI, "cpu_axi", "cpu_core", 8),
> > +       JH7100__DIV(JH7100_CLK_AHB_BUS, "ahb_bus", "cpunbus_root_div", 8),
> > +       JH7100__DIV(JH7100_CLK_APB1_BUS, "apb1_bus", "ahb_bus", 8),
> > +       JH7100__DIV(JH7100_CLK_APB2_BUS, "apb2_bus", "ahb_bus", 8),
> > +       JH7100_GATE(JH7100_CLK_DOM3AHB_BUS, "dom3ahb_bus", "ahb_bus", CLK_IGNORE_UNUSED),
> > +       JH7100_GATE(JH7100_CLK_DOM7AHB_BUS, "dom7ahb_bus", "ahb_bus", CLK_IGNORE_UNUSED),
> > +       JH7100_GATE(JH7100_CLK_U74_CORE0, "u74_core0", "cpu_core", CLK_IGNORE_UNUSED),
> > +       JH7100_GDIV(JH7100_CLK_U74_CORE1, "u74_core1", "cpu_core", 8, CLK_IGNORE_UNUSED),
> > +       JH7100_GATE(JH7100_CLK_U74_AXI, "u74_axi", "cpu_axi", CLK_IGNORE_UNUSED),
> > +       JH7100_GATE(JH7100_CLK_U74RTC_TOGGLE, "u74rtc_toggle", "osc_sys", CLK_IGNORE_UNUSED),
> > +       JH7100_GATE(JH7100_CLK_SGDMA2P_AXI, "sgdma2p_axi", "cpu_axi", 0),
> > +       JH7100_GATE(JH7100_CLK_DMA2PNOC_AXI, "dma2pnoc_axi", "cpu_axi", 0),
> > +       JH7100_GATE(JH7100_CLK_SGDMA2P_AHB, "sgdma2p_ahb", "ahb_bus", 0),
> > +       JH7100__DIV(JH7100_CLK_DLA_BUS, "dla_bus", "dla_root", 4),
> > +       JH7100_GATE(JH7100_CLK_DLA_AXI, "dla_axi", "dla_bus", 0),
> > +       JH7100_GATE(JH7100_CLK_DLANOC_AXI, "dlanoc_axi", "dla_bus", 0),
> > +       JH7100_GATE(JH7100_CLK_DLA_APB, "dla_apb", "apb1_bus", 0),
> > +       JH7100_GDIV(JH7100_CLK_VP6_CORE, "vp6_core", "dsp_root_div", 4, 0),
> > +       JH7100__DIV(JH7100_CLK_VP6BUS_SRC, "vp6bus_src", "dsp_root", 4),
> > +       JH7100_GDIV(JH7100_CLK_VP6_AXI, "vp6_axi", "vp6bus_src", 4, 0),
> > +       JH7100__DIV(JH7100_CLK_VCDECBUS_SRC, "vcdecbus_src", "cdechifi4_root", 4),
> > +       JH7100__DIV(JH7100_CLK_VDEC_BUS, "vdec_bus", "vcdecbus_src", 8),
> > +       JH7100_GATE(JH7100_CLK_VDEC_AXI, "vdec_axi", "vdec_bus", 0),
> > +       JH7100_GATE(JH7100_CLK_VDECBRG_MAIN, "vdecbrg_mainclk", "vdec_bus", 0),
> > +       JH7100_GDIV(JH7100_CLK_VDEC_BCLK, "vdec_bclk", "vcdecbus_src", 8, 0),
> > +       JH7100_GDIV(JH7100_CLK_VDEC_CCLK, "vdec_cclk", "cdec_root", 8, 0),
> > +       JH7100_GATE(JH7100_CLK_VDEC_APB, "vdec_apb", "apb1_bus", 0),
> > +       JH7100_GDIV(JH7100_CLK_JPEG_AXI, "jpeg_axi", "cpunbus_root_div", 8, 0),
> > +       JH7100_GDIV(JH7100_CLK_JPEG_CCLK, "jpeg_cclk", "cpunbus_root_div", 8, 0),
> > +       JH7100_GATE(JH7100_CLK_JPEG_APB, "jpeg_apb", "apb1_bus", 0),
> > +       JH7100_GDIV(JH7100_CLK_GC300_2X, "gc300_2x", "cdechifi4_root", 8, 0),
> > +       JH7100_GATE(JH7100_CLK_GC300_AHB, "gc300_ahb", "ahb_bus", 0),
> > +       JH7100__DIV(JH7100_CLK_JPCGC300_AXIBUS, "jpcgc300_axibus", "vcdecbus_src", 8),
> > +       JH7100_GATE(JH7100_CLK_GC300_AXI, "gc300_axi", "jpcgc300_axibus", 0),
> > +       JH7100_GATE(JH7100_CLK_JPCGC300_MAIN, "jpcgc300_mainclk", "jpcgc300_axibus", 0),
> > +       JH7100__DIV(JH7100_CLK_VENC_BUS, "venc_bus", "vcdecbus_src", 8),
> > +       JH7100_GATE(JH7100_CLK_VENC_AXI, "venc_axi", "venc_bus", 0),
> > +       JH7100_GATE(JH7100_CLK_VENCBRG_MAIN, "vencbrg_mainclk", "venc_bus", 0),
> > +       JH7100_GDIV(JH7100_CLK_VENC_BCLK, "venc_bclk", "vcdecbus_src", 8, 0),
> > +       JH7100_GDIV(JH7100_CLK_VENC_CCLK, "venc_cclk", "cdec_root", 8, 0),
> > +       JH7100_GATE(JH7100_CLK_VENC_APB, "venc_apb", "apb1_bus", 0),
> > +       JH7100_GDIV(JH7100_CLK_DDRPLL_DIV2, "ddrpll_div2", "pll1_out", 2, CLK_IGNORE_UNUSED),
> > +       JH7100_GDIV(JH7100_CLK_DDRPLL_DIV4, "ddrpll_div4", "ddrpll_div2", 2, CLK_IGNORE_UNUSED),
> > +       JH7100_GDIV(JH7100_CLK_DDRPLL_DIV8, "ddrpll_div8", "ddrpll_div4", 2, CLK_IGNORE_UNUSED),
> > +       JH7100_GDIV(JH7100_CLK_DDROSC_DIV2, "ddrosc_div2", "osc_sys", 2, CLK_IGNORE_UNUSED),
> > +       JH7100_GMUX(JH7100_CLK_DDRC0, "ddrc0", ddrc0_sels, CLK_IGNORE_UNUSED),
> > +       JH7100_GMUX(JH7100_CLK_DDRC1, "ddrc1", ddrc1_sels, CLK_IGNORE_UNUSED),
>
> Is it really unused? Or it is CLK_IS_CRITICAL?

Ah no. CLK_IS_CRITICAL is exactly what they are, thanks.

> > +       JH7100_GATE(JH7100_CLK_DDRPHY_APB, "ddrphy_apb", "apb1_bus", CLK_IGNORE_UNUSED),
> > +       JH7100__DIV(JH7100_CLK_NOC_ROB, "noc_rob", "cpunbus_root_div", 8),
> > +       JH7100__DIV(JH7100_CLK_NOC_COG, "noc_cog", "dla_root", 8),
> > +       JH7100_GATE(JH7100_CLK_NNE_AHB, "nne_ahb", "ahb_bus", 0),
> > +       JH7100__DIV(JH7100_CLK_NNEBUS_SRC1, "nnebus_src1", "dsp_root", 4),
> > +       JH7100__MUX(JH7100_CLK_NNE_BUS, "nne_bus", nne_bus_sels),
> > +       JH7100_GATE(JH7100_CLK_NNE_AXI, "nne_axi", "nne_bus", 0),
> > +       JH7100_GATE(JH7100_CLK_NNENOC_AXI, "nnenoc_axi", "nne_bus", 0),
> > +       JH7100_GATE(JH7100_CLK_DLASLV_AXI, "dlaslv_axi", "nne_bus", 0),
> > +       JH7100_GATE(JH7100_CLK_DSPX2C_AXI, "dspx2c_axi", "nne_bus", CLK_IGNORE_UNUSED),
> > +       JH7100__DIV(JH7100_CLK_HIFI4_SRC, "hifi4_src", "cdechifi4_root", 4),
> > +       JH7100__DIV(JH7100_CLK_HIFI4_COREFREE, "hifi4_corefree", "hifi4_src", 8),
> > +       JH7100_GATE(JH7100_CLK_HIFI4_CORE, "hifi4_core", "hifi4_corefree", 0),
> > +       JH7100__DIV(JH7100_CLK_HIFI4_BUS, "hifi4_bus", "hifi4_corefree", 8),
> > +       JH7100_GATE(JH7100_CLK_HIFI4_AXI, "hifi4_axi", "hifi4_bus", 0),
> > +       JH7100_GATE(JH7100_CLK_HIFI4NOC_AXI, "hifi4noc_axi", "hifi4_bus", 0),
> > +       JH7100__DIV(JH7100_CLK_SGDMA1P_BUS, "sgdma1p_bus", "cpunbus_root_div", 8),
> > +       JH7100_GATE(JH7100_CLK_SGDMA1P_AXI, "sgdma1p_axi", "sgdma1p_bus", 0),
> > +       JH7100_GATE(JH7100_CLK_DMA1P_AXI, "dma1p_axi", "sgdma1p_bus", 0),
> > +       JH7100_GDIV(JH7100_CLK_X2C_AXI, "x2c_axi", "cpunbus_root_div", 8, CLK_IGNORE_UNUSED),
> > +       JH7100__DIV(JH7100_CLK_USB_BUS, "usb_bus", "cpunbus_root_div", 8),
> > +       JH7100_GATE(JH7100_CLK_USB_AXI, "usb_axi", "usb_bus", 0),
> > +       JH7100_GATE(JH7100_CLK_USBNOC_AXI, "usbnoc_axi", "usb_bus", 0),
> > +       JH7100__DIV(JH7100_CLK_USBPHY_ROOTDIV, "usbphy_rootdiv", "gmacusb_root", 4),
> > +       JH7100_GDIV(JH7100_CLK_USBPHY_125M, "usbphy_125m", "usbphy_rootdiv", 8, 0),
> > +       JH7100_GDIV(JH7100_CLK_USBPHY_PLLDIV25M, "usbphy_plldiv25m", "usbphy_rootdiv", 32, 0),
> > +       JH7100__MUX(JH7100_CLK_USBPHY_25M, "usbphy_25m", usbphy_25m_sels),
> > +       JH7100__DIV(JH7100_CLK_AUDIO_DIV, "audio_div", "audio_root", 131072),
> > +       JH7100_GATE(JH7100_CLK_AUDIO_SRC, "audio_src", "audio_div", 0),
> > +       JH7100_GATE(JH7100_CLK_AUDIO_12288, "audio_12288", "osc_aud", 0),
> > +       JH7100_GDIV(JH7100_CLK_VIN_SRC, "vin_src", "vin_root", 4, 0),
> > +       JH7100__DIV(JH7100_CLK_ISP0_BUS, "isp0_bus", "vin_src", 8),
> > +       JH7100_GATE(JH7100_CLK_ISP0_AXI, "isp0_axi", "isp0_bus", 0),
> > +       JH7100_GATE(JH7100_CLK_ISP0NOC_AXI, "isp0noc_axi", "isp0_bus", 0),
> > +       JH7100_GATE(JH7100_CLK_ISPSLV_AXI, "ispslv_axi", "isp0_bus", 0),
> > +       JH7100__DIV(JH7100_CLK_ISP1_BUS, "isp1_bus", "vin_src", 8),
> > +       JH7100_GATE(JH7100_CLK_ISP1_AXI, "isp1_axi", "isp1_bus", 0),
> > +       JH7100_GATE(JH7100_CLK_ISP1NOC_AXI, "isp1noc_axi", "isp1_bus", 0),
> > +       JH7100__DIV(JH7100_CLK_VIN_BUS, "vin_bus", "vin_src", 8),
> > +       JH7100_GATE(JH7100_CLK_VIN_AXI, "vin_axi", "vin_bus", 0),
> > +       JH7100_GATE(JH7100_CLK_VINNOC_AXI, "vinnoc_axi", "vin_bus", 0),
> > +       JH7100_GDIV(JH7100_CLK_VOUT_SRC, "vout_src", "vout_root", 4, 0),
> > +       JH7100__DIV(JH7100_CLK_DISPBUS_SRC, "dispbus_src", "voutbus_root", 4),
> > +       JH7100__DIV(JH7100_CLK_DISP_BUS, "disp_bus", "dispbus_src", 4),
> > +       JH7100_GATE(JH7100_CLK_DISP_AXI, "disp_axi", "disp_bus", 0),
> > +       JH7100_GATE(JH7100_CLK_DISPNOC_AXI, "dispnoc_axi", "disp_bus", 0),
> > +       JH7100_GATE(JH7100_CLK_SDIO0_AHB, "sdio0_ahb", "ahb_bus", 0),
> > +       JH7100_GDIV(JH7100_CLK_SDIO0_CCLKINT, "sdio0_cclkint", "perh0_src", 24, 0),
> > +       JH7100__INV(JH7100_CLK_SDIO0_CCLKINT_INV, "sdio0_cclkint_inv", "sdio0_cclkint"),
> > +       JH7100_GATE(JH7100_CLK_SDIO1_AHB, "sdio1_ahb", "ahb_bus", 0),
> > +       JH7100_GDIV(JH7100_CLK_SDIO1_CCLKINT, "sdio1_cclkint", "perh1_src", 24, 0),
> > +       JH7100__INV(JH7100_CLK_SDIO1_CCLKINT_INV, "sdio1_cclkint_inv", "sdio1_cclkint"),
> > +       JH7100_GATE(JH7100_CLK_GMAC_AHB, "gmac_ahb", "ahb_bus", 0),
> > +       JH7100__DIV(JH7100_CLK_GMAC_ROOT_DIV, "gmac_root_div", "gmacusb_root", 8),
> > +       JH7100_GDIV(JH7100_CLK_GMAC_PTP_REF, "gmac_ptp_refclk", "gmac_root_div", 31, 0),
> > +       JH7100_GDIV(JH7100_CLK_GMAC_GTX, "gmac_gtxclk", "gmac_root_div", 255, 0),
> > +       JH7100_GDIV(JH7100_CLK_GMAC_RMII_TX, "gmac_rmii_txclk", "gmac_rmii_ref", 8, 0),
> > +       JH7100_GDIV(JH7100_CLK_GMAC_RMII_RX, "gmac_rmii_rxclk", "gmac_rmii_ref", 8, 0),
> > +       JH7100__MUX(JH7100_CLK_GMAC_TX, "gmac_tx", gmac_tx_sels),
> > +       JH7100__INV(JH7100_CLK_GMAC_TX_INV, "gmac_tx_inv", "gmac_tx"),
> > +       JH7100__MUX(JH7100_CLK_GMAC_RX_PRE, "gmac_rx_pre", gmac_rx_pre_sels),
> > +       JH7100__INV(JH7100_CLK_GMAC_RX_INV, "gmac_rx_inv", "gmac_rx_pre"),
> > +       JH7100_GATE(JH7100_CLK_GMAC_RMII, "gmac_rmii", "gmac_rmii_ref", 0),
> > +       JH7100_GDIV(JH7100_CLK_GMAC_TOPHYREF, "gmac_tophyref", "gmac_root_div", 127, 0),
> > +       JH7100_GATE(JH7100_CLK_SPI2AHB_AHB, "spi2ahb_ahb", "ahb_bus", 0),
> > +       JH7100_GDIV(JH7100_CLK_SPI2AHB_CORE, "spi2ahb_core", "perh0_src", 31, 0),
> > +       JH7100_GATE(JH7100_CLK_EZMASTER_AHB, "ezmaster_ahb", "ahb_bus", 0),
> > +       JH7100_GATE(JH7100_CLK_E24_AHB, "e24_ahb", "ahb_bus", 0),
> > +       JH7100_GATE(JH7100_CLK_E24RTC_TOGGLE, "e24rtc_toggle", "osc_sys", 0),
> > +       JH7100_GATE(JH7100_CLK_QSPI_AHB, "qspi_ahb", "ahb_bus", 0),
> > +       JH7100_GATE(JH7100_CLK_QSPI_APB, "qspi_apb", "apb1_bus", 0),
> > +       JH7100_GDIV(JH7100_CLK_QSPI_REF, "qspi_refclk", "perh0_src", 31, 0),
> > +       JH7100_GATE(JH7100_CLK_SEC_AHB, "sec_ahb", "ahb_bus", 0),
> > +       JH7100_GATE(JH7100_CLK_AES, "aes_clk", "sec_ahb", 0),
> > +       JH7100_GATE(JH7100_CLK_SHA, "sha_clk", "sec_ahb", 0),
> > +       JH7100_GATE(JH7100_CLK_PKA, "pka_clk", "sec_ahb", 0),
> > +       JH7100_GATE(JH7100_CLK_TRNG_APB, "trng_apb", "apb1_bus", 0),
> > +       JH7100_GATE(JH7100_CLK_OTP_APB, "otp_apb", "apb1_bus", 0),
> > +       JH7100_GATE(JH7100_CLK_UART0_APB, "uart0_apb", "apb1_bus", 0),
> > +       JH7100_GDIV(JH7100_CLK_UART0_CORE, "uart0_core", "perh1_src", 63, 0),
> > +       JH7100_GATE(JH7100_CLK_UART1_APB, "uart1_apb", "apb1_bus", 0),
> > +       JH7100_GDIV(JH7100_CLK_UART1_CORE, "uart1_core", "perh1_src", 63, 0),
> > +       JH7100_GATE(JH7100_CLK_SPI0_APB, "spi0_apb", "apb1_bus", 0),
> > +       JH7100_GDIV(JH7100_CLK_SPI0_CORE, "spi0_core", "perh1_src", 63, 0),
> > +       JH7100_GATE(JH7100_CLK_SPI1_APB, "spi1_apb", "apb1_bus", 0),
> > +       JH7100_GDIV(JH7100_CLK_SPI1_CORE, "spi1_core", "perh1_src", 63, 0),
> > +       JH7100_GATE(JH7100_CLK_I2C0_APB, "i2c0_apb", "apb1_bus", 0),
> > +       JH7100_GDIV(JH7100_CLK_I2C0_CORE, "i2c0_core", "perh1_src", 63, 0),
> > +       JH7100_GATE(JH7100_CLK_I2C1_APB, "i2c1_apb", "apb1_bus", 0),
> > +       JH7100_GDIV(JH7100_CLK_I2C1_CORE, "i2c1_core", "perh1_src", 63, 0),
> > +       JH7100_GATE(JH7100_CLK_GPIO_APB, "gpio_apb", "apb1_bus", 0),
> > +       JH7100_GATE(JH7100_CLK_UART2_APB, "uart2_apb", "apb2_bus", 0),
> > +       JH7100_GDIV(JH7100_CLK_UART2_CORE, "uart2_core", "perh0_src", 63, 0),
> > +       JH7100_GATE(JH7100_CLK_UART3_APB, "uart3_apb", "apb2_bus", 0),
> > +       JH7100_GDIV(JH7100_CLK_UART3_CORE, "uart3_core", "perh0_src", 63, 0),
> > +       JH7100_GATE(JH7100_CLK_SPI2_APB, "spi2_apb", "apb2_bus", 0),
> > +       JH7100_GDIV(JH7100_CLK_SPI2_CORE, "spi2_core", "perh0_src", 63, 0),
> > +       JH7100_GATE(JH7100_CLK_SPI3_APB, "spi3_apb", "apb2_bus", 0),
> > +       JH7100_GDIV(JH7100_CLK_SPI3_CORE, "spi3_core", "perh0_src", 63, 0),
> > +       JH7100_GATE(JH7100_CLK_I2C2_APB, "i2c2_apb", "apb2_bus", 0),
> > +       JH7100_GDIV(JH7100_CLK_I2C2_CORE, "i2c2_core", "perh0_src", 63, 0),
> > +       JH7100_GATE(JH7100_CLK_I2C3_APB, "i2c3_apb", "apb2_bus", 0),
> > +       JH7100_GDIV(JH7100_CLK_I2C3_CORE, "i2c3_core", "perh0_src", 63, 0),
> > +       JH7100_GATE(JH7100_CLK_WDTIMER_APB, "wdtimer_apb", "apb2_bus", 0),
> > +       JH7100_GDIV(JH7100_CLK_WDT_CORE, "wdt_coreclk", "perh0_src", 63, 0),
> > +       JH7100_GDIV(JH7100_CLK_TIMER0_CORE, "timer0_coreclk", "perh0_src", 63, 0),
> > +       JH7100_GDIV(JH7100_CLK_TIMER1_CORE, "timer1_coreclk", "perh0_src", 63, 0),
> > +       JH7100_GDIV(JH7100_CLK_TIMER2_CORE, "timer2_coreclk", "perh0_src", 63, 0),
> > +       JH7100_GDIV(JH7100_CLK_TIMER3_CORE, "timer3_coreclk", "perh0_src", 63, 0),
> > +       JH7100_GDIV(JH7100_CLK_TIMER4_CORE, "timer4_coreclk", "perh0_src", 63, 0),
> > +       JH7100_GDIV(JH7100_CLK_TIMER5_CORE, "timer5_coreclk", "perh0_src", 63, 0),
> > +       JH7100_GDIV(JH7100_CLK_TIMER6_CORE, "timer6_coreclk", "perh0_src", 63, 0),
> > +       JH7100_GATE(JH7100_CLK_VP6INTC_APB, "vp6intc_apb", "apb2_bus", 0),
> > +       JH7100_GATE(JH7100_CLK_PWM_APB, "pwm_apb", "apb2_bus", 0),
> > +       JH7100_GATE(JH7100_CLK_MSI_APB, "msi_apb", "apb2_bus", 0),
> > +       JH7100_GATE(JH7100_CLK_TEMP_APB, "temp_apb", "apb2_bus", 0),
> > +       JH7100_GDIV(JH7100_CLK_TEMP_SENSE, "temp_sense", "osc_sys", 31, 0),
> > +       JH7100_GATE(JH7100_CLK_SYSERR_APB, "syserr_apb", "apb2_bus", 0),
> > +};
> > +
> > +static struct clk_hw *clk_starfive_jh7100_get(struct of_phandle_args *clkspec, void *data)
> > +{
> > +       struct clk_starfive_jh7100_priv *priv = data;
> > +       unsigned int idx = clkspec->args[0];
> > +
> > +       if (idx >= JH7100_CLK_END) {
> > +               dev_err(priv->dev, "invalid clock index %u\n", idx);
>
> We should pull this sort of error message up into the core instead of
> have it in every driver. It also doesn't look very meaningful to print
> the name of the device that's providing the clks vs. the name of the
> device that's requesting the clk that can't be found.

Makes sense. I'll just remove the message then.

> > +               return ERR_PTR(-EINVAL);
> > +       }
> > +
> > +       if (idx >= JH7100_CLK_PLL0_OUT)
> > +               return priv->pll[idx - JH7100_CLK_PLL0_OUT];
> > +
> > +       return &priv->reg[idx].hw;
> > +}
> > +
> > +static int __init clk_starfive_jh7100_probe(struct platform_device *pdev)
>
> Drop __init as this can be called after kernel init is over.

Oh interesting, I'd like to know when that can happen. The comment for
the builtin_platform_driver macro says it's just a wrapper for
device_initcall.

Won't we then need to remove all the __initconst tags too since the
probe function walks through jh7100_clk_data which eventually
references all __initconst data?

> > +{
> > +       struct clk_starfive_jh7100_priv *priv;
> > +       unsigned int idx;
> > +       int ret;
> > +
> > +       priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
> > +       if (!priv)
> > +               return -ENOMEM;
> > +
> > +       spin_lock_init(&priv->rmw_lock);
> > +       priv->dev = &pdev->dev;
> > +       priv->base = devm_platform_ioremap_resource(pdev, 0);
> > +       if (IS_ERR(priv->base))
> > +               return PTR_ERR(priv->base);
> > +
> > +       priv->pll[0] = devm_clk_hw_register_fixed_factor(priv->dev, "pll0_out",
> > +                                                        "osc_sys", 0, 40, 1);
> > +       if (IS_ERR(priv->pll[0]))
> > +               return PTR_ERR(priv->pll[0]);
> > +
> > +       priv->pll[1] = devm_clk_hw_register_fixed_factor(priv->dev, "pll1_out",
> > +                                                        "osc_sys", 0, 64, 1);
> > +       if (IS_ERR(priv->pll[1]))
> > +               return PTR_ERR(priv->pll[1]);
> > +
> > +       priv->pll[2] = devm_clk_hw_register_fixed_factor(priv->dev, "pll2_out",
> > +                                                        "pll2_refclk", 0, 55, 1);
> > +       if (IS_ERR(priv->pll[2]))
> > +               return PTR_ERR(priv->pll[2]);
> > +
> > +       for (idx = 0; idx < JH7100_CLK_PLL0_OUT; idx++) {
> > +               u32 max_parent = (jh7100_clk_data[idx].max & JH7100_CLK_MUX_MASK) >>
> > +                                JH7100_CLK_MUX_SHIFT;
> > +               struct clk_init_data init = {
> > +                       .name = jh7100_clk_data[idx].name,
> > +                       .ops = jh7100_clk_data[idx].ops,
> > +                       .num_parents = max_parent + 1,
> > +                       .flags = jh7100_clk_data[idx].flags,
> > +               };
> > +               struct jh7100_clk *clk = &priv->reg[idx];
> > +
> > +               if (init.num_parents > 1)
> > +                       init.parent_names = jh7100_clk_data[idx].parents;
> > +               else
> > +                       init.parent_names = &jh7100_clk_data[idx].parent;
>
> Can you use clk_parent_data instead of parent_names? To make the object
> size even smaller you can use the DT index instead of the .fw_name
> field.

Ah cool. I'll look into that.

> > +
> > +               clk->hw.init = &init;
> > +               clk->idx = idx;
> > +               clk->max = jh7100_clk_data[idx].max;
> > +
> > +               ret = clk_hw_register(priv->dev, &clk->hw);
>
> Why not use devm_clk_hw_register()?

I probably could. Just for my understanding that's just to avoid the
loop on error below, because as a builtin driver the device won't
otherwise go away, right?

> > +               if (ret)
> > +                       goto err;
> > +       }
> > +
> > +       ret = devm_of_clk_add_hw_provider(priv->dev, clk_starfive_jh7100_get, priv);
> > +       if (ret)
> > +               goto err;
> > +
> > +       return 0;
> > +err:
> > +       while (idx)
> > +               clk_hw_unregister(&priv->reg[--idx].hw);
> > +       return ret;
> > +}
> > +
> > +static const struct of_device_id clk_starfive_jh7100_match[] = {
> > +       { .compatible = "starfive,jh7100-clkgen" },
> > +       { /* sentinel */ }
> > +};
>
> Please add MODULE_DEVICE_TABLE()

Will do!

Thank you.
/Emil

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 06/16] clk: starfive: Add JH7100 clock generator driver
  2021-10-26 22:35       ` Emil Renner Berthing
@ 2021-10-27  0:54         ` Stephen Boyd
  -1 siblings, 0 replies; 143+ messages in thread
From: Stephen Boyd @ 2021-10-27  0:54 UTC (permalink / raw)
  To: Emil Renner Berthing
  Cc: devicetree, linux-clk, linux-gpio, linux-riscv, linux-serial,
	Geert Uytterhoeven, Palmer Dabbelt, Paul Walmsley, Rob Herring,
	Michael Turquette, Thomas Gleixner, Marc Zyngier, Philipp Zabel,
	Linus Walleij, Greg Kroah-Hartman, Daniel Lezcano,
	Andy Shevchenko, Jiri Slaby, Maximilian Luz, Sagar Kadam,
	Drew Fustini, Michael Zhu, Fu Wei, Anup Patel, Atish Patra,
	Matteo Croce, Linux Kernel Mailing List

Quoting Emil Renner Berthing (2021-10-26 15:35:36)
> On Tue, 26 Oct 2021 at 22:20, Stephen Boyd <sboyd@kernel.org> wrote:
> > Quoting Emil Renner Berthing (2021-10-21 10:42:13)
> > > +};
> > > +
> > > +struct clk_starfive_jh7100_priv {
> > > +       /* protect registers against overlapping read-modify-write */
> > > +       spinlock_t rmw_lock;
> >
> > Does overlapping mean concurrent?
> 
> Yes, sorry.
> 
> > Do different clks share the same registers?
> 
> No, each clock has their own register, but they use that register both
> to gate the clock and other configuration. The Locking chapter of
> Documentation/driver-api/clk.rst talks about the prepare lock and the
> enable lock and then says:
> "However, access to resources that are shared between operations of
> the two groups needs to be protected by the drivers. An example of
> such a resource would be a register that controls both the clock rate
> and the clock enable/disable state."

Alright got it. Maybe say "protect clk enable and set rate from
happening at the same time".

> 
> > > +               return ERR_PTR(-EINVAL);
> > > +       }
> > > +
> > > +       if (idx >= JH7100_CLK_PLL0_OUT)
> > > +               return priv->pll[idx - JH7100_CLK_PLL0_OUT];
> > > +
> > > +       return &priv->reg[idx].hw;
> > > +}
> > > +
> > > +static int __init clk_starfive_jh7100_probe(struct platform_device *pdev)
> >
> > Drop __init as this can be called after kernel init is over.
> 
> Oh interesting, I'd like to know when that can happen. The comment for
> the builtin_platform_driver macro says it's just a wrapper for

I thought this was using module_platform_driver() macro?

> device_initcall.
> 
> Won't we then need to remove all the __initconst tags too since the
> probe function walks through jh7100_clk_data which eventually
> references all __initconst data?

Yes. If it's builtin_platform_driver() it can't be a module/tristate
Kconfig, in which case all the init markings can stay.

> 
> > > +
> > > +               clk->hw.init = &init;
> > > +               clk->idx = idx;
> > > +               clk->max = jh7100_clk_data[idx].max;
> > > +
> > > +               ret = clk_hw_register(priv->dev, &clk->hw);
> >
> > Why not use devm_clk_hw_register()?
> 
> I probably could. Just for my understanding that's just to avoid the
> loop on error below, because as a builtin driver the device won't
> otherwise go away, right?

Yes

> 
> > > +               if (ret)
> > > +                       goto err;
> > > +       }
> > > +
> > > +       ret = devm_of_clk_add_hw_provider(priv->dev, clk_starfive_jh7100_get, priv);
> > > +       if (ret)
> > > +               goto err;
> > > +
> > > +       return 0;
> > > +err:
> > > +       while (idx)
> > > +               clk_hw_unregister(&priv->reg[--idx].hw);
> > > +       return ret;
> > > +}
> > > +
> > > +static const struct of_device_id clk_starfive_jh7100_match[] = {
> > > +       { .compatible = "starfive,jh7100-clkgen" },
> > > +       { /* sentinel */ }
> > > +};
> >
> > Please add MODULE_DEVICE_TABLE()
> 
> Will do!

If it's never going to be a module then don't add any module_* things.

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 06/16] clk: starfive: Add JH7100 clock generator driver
@ 2021-10-27  0:54         ` Stephen Boyd
  0 siblings, 0 replies; 143+ messages in thread
From: Stephen Boyd @ 2021-10-27  0:54 UTC (permalink / raw)
  To: Emil Renner Berthing
  Cc: devicetree, linux-clk, linux-gpio, linux-riscv, linux-serial,
	Geert Uytterhoeven, Palmer Dabbelt, Paul Walmsley, Rob Herring,
	Michael Turquette, Thomas Gleixner, Marc Zyngier, Philipp Zabel,
	Linus Walleij, Greg Kroah-Hartman, Daniel Lezcano,
	Andy Shevchenko, Jiri Slaby, Maximilian Luz, Sagar Kadam,
	Drew Fustini, Michael Zhu, Fu Wei, Anup Patel, Atish Patra,
	Matteo Croce, Linux Kernel Mailing List

Quoting Emil Renner Berthing (2021-10-26 15:35:36)
> On Tue, 26 Oct 2021 at 22:20, Stephen Boyd <sboyd@kernel.org> wrote:
> > Quoting Emil Renner Berthing (2021-10-21 10:42:13)
> > > +};
> > > +
> > > +struct clk_starfive_jh7100_priv {
> > > +       /* protect registers against overlapping read-modify-write */
> > > +       spinlock_t rmw_lock;
> >
> > Does overlapping mean concurrent?
> 
> Yes, sorry.
> 
> > Do different clks share the same registers?
> 
> No, each clock has their own register, but they use that register both
> to gate the clock and other configuration. The Locking chapter of
> Documentation/driver-api/clk.rst talks about the prepare lock and the
> enable lock and then says:
> "However, access to resources that are shared between operations of
> the two groups needs to be protected by the drivers. An example of
> such a resource would be a register that controls both the clock rate
> and the clock enable/disable state."

Alright got it. Maybe say "protect clk enable and set rate from
happening at the same time".

> 
> > > +               return ERR_PTR(-EINVAL);
> > > +       }
> > > +
> > > +       if (idx >= JH7100_CLK_PLL0_OUT)
> > > +               return priv->pll[idx - JH7100_CLK_PLL0_OUT];
> > > +
> > > +       return &priv->reg[idx].hw;
> > > +}
> > > +
> > > +static int __init clk_starfive_jh7100_probe(struct platform_device *pdev)
> >
> > Drop __init as this can be called after kernel init is over.
> 
> Oh interesting, I'd like to know when that can happen. The comment for
> the builtin_platform_driver macro says it's just a wrapper for

I thought this was using module_platform_driver() macro?

> device_initcall.
> 
> Won't we then need to remove all the __initconst tags too since the
> probe function walks through jh7100_clk_data which eventually
> references all __initconst data?

Yes. If it's builtin_platform_driver() it can't be a module/tristate
Kconfig, in which case all the init markings can stay.

> 
> > > +
> > > +               clk->hw.init = &init;
> > > +               clk->idx = idx;
> > > +               clk->max = jh7100_clk_data[idx].max;
> > > +
> > > +               ret = clk_hw_register(priv->dev, &clk->hw);
> >
> > Why not use devm_clk_hw_register()?
> 
> I probably could. Just for my understanding that's just to avoid the
> loop on error below, because as a builtin driver the device won't
> otherwise go away, right?

Yes

> 
> > > +               if (ret)
> > > +                       goto err;
> > > +       }
> > > +
> > > +       ret = devm_of_clk_add_hw_provider(priv->dev, clk_starfive_jh7100_get, priv);
> > > +       if (ret)
> > > +               goto err;
> > > +
> > > +       return 0;
> > > +err:
> > > +       while (idx)
> > > +               clk_hw_unregister(&priv->reg[--idx].hw);
> > > +       return ret;
> > > +}
> > > +
> > > +static const struct of_device_id clk_starfive_jh7100_match[] = {
> > > +       { .compatible = "starfive,jh7100-clkgen" },
> > > +       { /* sentinel */ }
> > > +};
> >
> > Please add MODULE_DEVICE_TABLE()
> 
> Will do!

If it's never going to be a module then don't add any module_* things.

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 06/16] clk: starfive: Add JH7100 clock generator driver
  2021-10-27  0:54         ` Stephen Boyd
@ 2021-10-27  9:30           ` Andy Shevchenko
  -1 siblings, 0 replies; 143+ messages in thread
From: Andy Shevchenko @ 2021-10-27  9:30 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Emil Renner Berthing, devicetree, linux-clk, linux-gpio,
	linux-riscv, linux-serial, Geert Uytterhoeven, Palmer Dabbelt,
	Paul Walmsley, Rob Herring, Michael Turquette, Thomas Gleixner,
	Marc Zyngier, Philipp Zabel, Linus Walleij, Greg Kroah-Hartman,
	Daniel Lezcano, Jiri Slaby, Maximilian Luz, Sagar Kadam,
	Drew Fustini, Michael Zhu, Fu Wei, Anup Patel, Atish Patra,
	Matteo Croce, Linux Kernel Mailing List

On Tue, Oct 26, 2021 at 05:54:03PM -0700, Stephen Boyd wrote:
> Quoting Emil Renner Berthing (2021-10-26 15:35:36)
> > On Tue, 26 Oct 2021 at 22:20, Stephen Boyd <sboyd@kernel.org> wrote:
> > > Quoting Emil Renner Berthing (2021-10-21 10:42:13)

...

> > > > +static int __init clk_starfive_jh7100_probe(struct platform_device *pdev)
> > >
> > > Drop __init as this can be called after kernel init is over.
> > 
> > Oh interesting, I'd like to know when that can happen. The comment for
> > the builtin_platform_driver macro says it's just a wrapper for
> 
> I thought this was using module_platform_driver() macro?
> 
> > device_initcall.
> > 
> > Won't we then need to remove all the __initconst tags too since the
> > probe function walks through jh7100_clk_data which eventually
> > references all __initconst data?
> 
> Yes. If it's builtin_platform_driver() it can't be a module/tristate
> Kconfig, in which case all the init markings can stay.

What about bind/unbind attribute?

-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 06/16] clk: starfive: Add JH7100 clock generator driver
@ 2021-10-27  9:30           ` Andy Shevchenko
  0 siblings, 0 replies; 143+ messages in thread
From: Andy Shevchenko @ 2021-10-27  9:30 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Emil Renner Berthing, devicetree, linux-clk, linux-gpio,
	linux-riscv, linux-serial, Geert Uytterhoeven, Palmer Dabbelt,
	Paul Walmsley, Rob Herring, Michael Turquette, Thomas Gleixner,
	Marc Zyngier, Philipp Zabel, Linus Walleij, Greg Kroah-Hartman,
	Daniel Lezcano, Jiri Slaby, Maximilian Luz, Sagar Kadam,
	Drew Fustini, Michael Zhu, Fu Wei, Anup Patel, Atish Patra,
	Matteo Croce, Linux Kernel Mailing List

On Tue, Oct 26, 2021 at 05:54:03PM -0700, Stephen Boyd wrote:
> Quoting Emil Renner Berthing (2021-10-26 15:35:36)
> > On Tue, 26 Oct 2021 at 22:20, Stephen Boyd <sboyd@kernel.org> wrote:
> > > Quoting Emil Renner Berthing (2021-10-21 10:42:13)

...

> > > > +static int __init clk_starfive_jh7100_probe(struct platform_device *pdev)
> > >
> > > Drop __init as this can be called after kernel init is over.
> > 
> > Oh interesting, I'd like to know when that can happen. The comment for
> > the builtin_platform_driver macro says it's just a wrapper for
> 
> I thought this was using module_platform_driver() macro?
> 
> > device_initcall.
> > 
> > Won't we then need to remove all the __initconst tags too since the
> > probe function walks through jh7100_clk_data which eventually
> > references all __initconst data?
> 
> Yes. If it's builtin_platform_driver() it can't be a module/tristate
> Kconfig, in which case all the init markings can stay.

What about bind/unbind attribute?

-- 
With Best Regards,
Andy Shevchenko



_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 06/16] clk: starfive: Add JH7100 clock generator driver
  2021-10-27  0:54         ` Stephen Boyd
@ 2021-10-27 10:24           ` Emil Renner Berthing
  -1 siblings, 0 replies; 143+ messages in thread
From: Emil Renner Berthing @ 2021-10-27 10:24 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	linux-clk, open list:GPIO SUBSYSTEM, linux-riscv,
	open list:SERIAL DRIVERS, Geert Uytterhoeven, Palmer Dabbelt,
	Paul Walmsley, Rob Herring, Michael Turquette, Thomas Gleixner,
	Marc Zyngier, Philipp Zabel, Linus Walleij, Greg Kroah-Hartman,
	Daniel Lezcano, Andy Shevchenko, Jiri Slaby, Maximilian Luz,
	Sagar Kadam, Drew Fustini, Michael Zhu, Fu Wei, Anup Patel,
	Atish Patra, Linux Kernel Mailing List

On Wed, 27 Oct 2021 at 02:54, Stephen Boyd <sboyd@kernel.org> wrote:
> Quoting Emil Renner Berthing (2021-10-26 15:35:36)
> > On Tue, 26 Oct 2021 at 22:20, Stephen Boyd <sboyd@kernel.org> wrote:
> > > Quoting Emil Renner Berthing (2021-10-21 10:42:13)
> > > > +};
> > > > +
> > > > +struct clk_starfive_jh7100_priv {
> > > > +       /* protect registers against overlapping read-modify-write */
> > > > +       spinlock_t rmw_lock;
> > >
> > > Does overlapping mean concurrent?
> >
> > Yes, sorry.
> >
> > > Do different clks share the same registers?
> >
> > No, each clock has their own register, but they use that register both
> > to gate the clock and other configuration. The Locking chapter of
> > Documentation/driver-api/clk.rst talks about the prepare lock and the
> > enable lock and then says:
> > "However, access to resources that are shared between operations of
> > the two groups needs to be protected by the drivers. An example of
> > such a resource would be a register that controls both the clock rate
> > and the clock enable/disable state."
>
> Alright got it. Maybe say "protect clk enable and set rate from
> happening at the same time".
>
> >
> > > > +               return ERR_PTR(-EINVAL);
> > > > +       }
> > > > +
> > > > +       if (idx >= JH7100_CLK_PLL0_OUT)
> > > > +               return priv->pll[idx - JH7100_CLK_PLL0_OUT];
> > > > +
> > > > +       return &priv->reg[idx].hw;
> > > > +}
> > > > +
> > > > +static int __init clk_starfive_jh7100_probe(struct platform_device *pdev)
> > >
> > > Drop __init as this can be called after kernel init is over.
> >
> > Oh interesting, I'd like to know when that can happen. The comment for
> > the builtin_platform_driver macro says it's just a wrapper for
>
> I thought this was using module_platform_driver() macro?
>
> > device_initcall.
> >
> > Won't we then need to remove all the __initconst tags too since the
> > probe function walks through jh7100_clk_data which eventually
> > references all __initconst data?
>
> Yes. If it's builtin_platform_driver() it can't be a module/tristate
> Kconfig, in which case all the init markings can stay.

Yes, it's already bool in the Kconfig file. After looking into this I
think it's better to do like the rockchip drivers and use
builtin_platform_driver_probe to make sure the probe function only
called at kernel init time:

static struct platform_driver clk_starfive_jh7100_driver = {
        .driver = {
                .name = "clk-starfive-jh7100",
                .of_match_table = clk_starfive_jh7100_match,
                .suppress_bind_attrs = true,
        },
};
builtin_platform_driver_probe(clk_starfive_jh7100_driver,
clk_starfive_jh7100_probe);

@Andy: is the supress_bind_attrs what you were asking about?

> > > > +
> > > > +               clk->hw.init = &init;
> > > > +               clk->idx = idx;
> > > > +               clk->max = jh7100_clk_data[idx].max;
> > > > +
> > > > +               ret = clk_hw_register(priv->dev, &clk->hw);
> > >
> > > Why not use devm_clk_hw_register()?
> >
> > I probably could. Just for my understanding that's just to avoid the
> > loop on error below, because as a builtin driver the device won't
> > otherwise go away, right?
>
> Yes
>
> >
> > > > +               if (ret)
> > > > +                       goto err;
> > > > +       }
> > > > +
> > > > +       ret = devm_of_clk_add_hw_provider(priv->dev, clk_starfive_jh7100_get, priv);
> > > > +       if (ret)
> > > > +               goto err;
> > > > +
> > > > +       return 0;
> > > > +err:
> > > > +       while (idx)
> > > > +               clk_hw_unregister(&priv->reg[--idx].hw);
> > > > +       return ret;
> > > > +}
> > > > +
> > > > +static const struct of_device_id clk_starfive_jh7100_match[] = {
> > > > +       { .compatible = "starfive,jh7100-clkgen" },
> > > > +       { /* sentinel */ }
> > > > +};
> > >
> > > Please add MODULE_DEVICE_TABLE()
> >
> > Will do!
>
> If it's never going to be a module then don't add any module_* things.

So does that just mean no MODULE_DEVICE_TABLE or should I also remove
MODULE_DESCRIPTION, MODULE_AUTHOR and MODULE_LICENSE? I'm just double
checking because the rockchip drivers seem to have MODULE_DESCRIPTION
and MODULE_LICENSE lines.

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 06/16] clk: starfive: Add JH7100 clock generator driver
@ 2021-10-27 10:24           ` Emil Renner Berthing
  0 siblings, 0 replies; 143+ messages in thread
From: Emil Renner Berthing @ 2021-10-27 10:24 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	linux-clk, open list:GPIO SUBSYSTEM, linux-riscv,
	open list:SERIAL DRIVERS, Geert Uytterhoeven, Palmer Dabbelt,
	Paul Walmsley, Rob Herring, Michael Turquette, Thomas Gleixner,
	Marc Zyngier, Philipp Zabel, Linus Walleij, Greg Kroah-Hartman,
	Daniel Lezcano, Andy Shevchenko, Jiri Slaby, Maximilian Luz,
	Sagar Kadam, Drew Fustini, Michael Zhu, Fu Wei, Anup Patel,
	Atish Patra, Linux Kernel Mailing List

On Wed, 27 Oct 2021 at 02:54, Stephen Boyd <sboyd@kernel.org> wrote:
> Quoting Emil Renner Berthing (2021-10-26 15:35:36)
> > On Tue, 26 Oct 2021 at 22:20, Stephen Boyd <sboyd@kernel.org> wrote:
> > > Quoting Emil Renner Berthing (2021-10-21 10:42:13)
> > > > +};
> > > > +
> > > > +struct clk_starfive_jh7100_priv {
> > > > +       /* protect registers against overlapping read-modify-write */
> > > > +       spinlock_t rmw_lock;
> > >
> > > Does overlapping mean concurrent?
> >
> > Yes, sorry.
> >
> > > Do different clks share the same registers?
> >
> > No, each clock has their own register, but they use that register both
> > to gate the clock and other configuration. The Locking chapter of
> > Documentation/driver-api/clk.rst talks about the prepare lock and the
> > enable lock and then says:
> > "However, access to resources that are shared between operations of
> > the two groups needs to be protected by the drivers. An example of
> > such a resource would be a register that controls both the clock rate
> > and the clock enable/disable state."
>
> Alright got it. Maybe say "protect clk enable and set rate from
> happening at the same time".
>
> >
> > > > +               return ERR_PTR(-EINVAL);
> > > > +       }
> > > > +
> > > > +       if (idx >= JH7100_CLK_PLL0_OUT)
> > > > +               return priv->pll[idx - JH7100_CLK_PLL0_OUT];
> > > > +
> > > > +       return &priv->reg[idx].hw;
> > > > +}
> > > > +
> > > > +static int __init clk_starfive_jh7100_probe(struct platform_device *pdev)
> > >
> > > Drop __init as this can be called after kernel init is over.
> >
> > Oh interesting, I'd like to know when that can happen. The comment for
> > the builtin_platform_driver macro says it's just a wrapper for
>
> I thought this was using module_platform_driver() macro?
>
> > device_initcall.
> >
> > Won't we then need to remove all the __initconst tags too since the
> > probe function walks through jh7100_clk_data which eventually
> > references all __initconst data?
>
> Yes. If it's builtin_platform_driver() it can't be a module/tristate
> Kconfig, in which case all the init markings can stay.

Yes, it's already bool in the Kconfig file. After looking into this I
think it's better to do like the rockchip drivers and use
builtin_platform_driver_probe to make sure the probe function only
called at kernel init time:

static struct platform_driver clk_starfive_jh7100_driver = {
        .driver = {
                .name = "clk-starfive-jh7100",
                .of_match_table = clk_starfive_jh7100_match,
                .suppress_bind_attrs = true,
        },
};
builtin_platform_driver_probe(clk_starfive_jh7100_driver,
clk_starfive_jh7100_probe);

@Andy: is the supress_bind_attrs what you were asking about?

> > > > +
> > > > +               clk->hw.init = &init;
> > > > +               clk->idx = idx;
> > > > +               clk->max = jh7100_clk_data[idx].max;
> > > > +
> > > > +               ret = clk_hw_register(priv->dev, &clk->hw);
> > >
> > > Why not use devm_clk_hw_register()?
> >
> > I probably could. Just for my understanding that's just to avoid the
> > loop on error below, because as a builtin driver the device won't
> > otherwise go away, right?
>
> Yes
>
> >
> > > > +               if (ret)
> > > > +                       goto err;
> > > > +       }
> > > > +
> > > > +       ret = devm_of_clk_add_hw_provider(priv->dev, clk_starfive_jh7100_get, priv);
> > > > +       if (ret)
> > > > +               goto err;
> > > > +
> > > > +       return 0;
> > > > +err:
> > > > +       while (idx)
> > > > +               clk_hw_unregister(&priv->reg[--idx].hw);
> > > > +       return ret;
> > > > +}
> > > > +
> > > > +static const struct of_device_id clk_starfive_jh7100_match[] = {
> > > > +       { .compatible = "starfive,jh7100-clkgen" },
> > > > +       { /* sentinel */ }
> > > > +};
> > >
> > > Please add MODULE_DEVICE_TABLE()
> >
> > Will do!
>
> If it's never going to be a module then don't add any module_* things.

So does that just mean no MODULE_DEVICE_TABLE or should I also remove
MODULE_DESCRIPTION, MODULE_AUTHOR and MODULE_LICENSE? I'm just double
checking because the rockchip drivers seem to have MODULE_DESCRIPTION
and MODULE_LICENSE lines.

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 06/16] clk: starfive: Add JH7100 clock generator driver
  2021-10-27 10:24           ` Emil Renner Berthing
@ 2021-10-27 10:32             ` Andy Shevchenko
  -1 siblings, 0 replies; 143+ messages in thread
From: Andy Shevchenko @ 2021-10-27 10:32 UTC (permalink / raw)
  To: Emil Renner Berthing
  Cc: Stephen Boyd,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	linux-clk, open list:GPIO SUBSYSTEM, linux-riscv,
	open list:SERIAL DRIVERS, Geert Uytterhoeven, Palmer Dabbelt,
	Paul Walmsley, Rob Herring, Michael Turquette, Thomas Gleixner,
	Marc Zyngier, Philipp Zabel, Linus Walleij, Greg Kroah-Hartman,
	Daniel Lezcano, Jiri Slaby, Maximilian Luz, Sagar Kadam,
	Drew Fustini, Michael Zhu, Fu Wei, Anup Patel, Atish Patra,
	Linux Kernel Mailing List

On Wed, Oct 27, 2021 at 12:24:07PM +0200, Emil Renner Berthing wrote:
> On Wed, 27 Oct 2021 at 02:54, Stephen Boyd <sboyd@kernel.org> wrote:
> > Quoting Emil Renner Berthing (2021-10-26 15:35:36)
> > > On Tue, 26 Oct 2021 at 22:20, Stephen Boyd <sboyd@kernel.org> wrote:
> > > > Quoting Emil Renner Berthing (2021-10-21 10:42:13)

...

> > > > > +static int __init clk_starfive_jh7100_probe(struct platform_device *pdev)
> > > >
> > > > Drop __init as this can be called after kernel init is over.
> > >
> > > Oh interesting, I'd like to know when that can happen. The comment for
> > > the builtin_platform_driver macro says it's just a wrapper for
> >
> > I thought this was using module_platform_driver() macro?
> >
> > > device_initcall.
> > >
> > > Won't we then need to remove all the __initconst tags too since the
> > > probe function walks through jh7100_clk_data which eventually
> > > references all __initconst data?
> >
> > Yes. If it's builtin_platform_driver() it can't be a module/tristate
> > Kconfig, in which case all the init markings can stay.
> 
> Yes, it's already bool in the Kconfig file. After looking into this I
> think it's better to do like the rockchip drivers and use
> builtin_platform_driver_probe to make sure the probe function only
> called at kernel init time:
> 
> static struct platform_driver clk_starfive_jh7100_driver = {
>         .driver = {
>                 .name = "clk-starfive-jh7100",
>                 .of_match_table = clk_starfive_jh7100_match,
>                 .suppress_bind_attrs = true,
>         },
> };
> builtin_platform_driver_probe(clk_starfive_jh7100_driver,
> clk_starfive_jh7100_probe);
> 
> @Andy: is the supress_bind_attrs what you were asking about?

Clever chap! :-)
Yes, that's what I have in mind.

...

> > If it's never going to be a module then don't add any module_* things.
> 
> So does that just mean no MODULE_DEVICE_TABLE or should I also remove
> MODULE_DESCRIPTION, MODULE_AUTHOR and MODULE_LICENSE? I'm just double
> checking because the rockchip drivers seem to have MODULE_DESCRIPTION
> and MODULE_LICENSE lines.

You may comment them out. Convert them to comments or so.
But in general yes, they are no-ops in such case.

-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 06/16] clk: starfive: Add JH7100 clock generator driver
@ 2021-10-27 10:32             ` Andy Shevchenko
  0 siblings, 0 replies; 143+ messages in thread
From: Andy Shevchenko @ 2021-10-27 10:32 UTC (permalink / raw)
  To: Emil Renner Berthing
  Cc: Stephen Boyd,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	linux-clk, open list:GPIO SUBSYSTEM, linux-riscv,
	open list:SERIAL DRIVERS, Geert Uytterhoeven, Palmer Dabbelt,
	Paul Walmsley, Rob Herring, Michael Turquette, Thomas Gleixner,
	Marc Zyngier, Philipp Zabel, Linus Walleij, Greg Kroah-Hartman,
	Daniel Lezcano, Jiri Slaby, Maximilian Luz, Sagar Kadam,
	Drew Fustini, Michael Zhu, Fu Wei, Anup Patel, Atish Patra,
	Linux Kernel Mailing List

On Wed, Oct 27, 2021 at 12:24:07PM +0200, Emil Renner Berthing wrote:
> On Wed, 27 Oct 2021 at 02:54, Stephen Boyd <sboyd@kernel.org> wrote:
> > Quoting Emil Renner Berthing (2021-10-26 15:35:36)
> > > On Tue, 26 Oct 2021 at 22:20, Stephen Boyd <sboyd@kernel.org> wrote:
> > > > Quoting Emil Renner Berthing (2021-10-21 10:42:13)

...

> > > > > +static int __init clk_starfive_jh7100_probe(struct platform_device *pdev)
> > > >
> > > > Drop __init as this can be called after kernel init is over.
> > >
> > > Oh interesting, I'd like to know when that can happen. The comment for
> > > the builtin_platform_driver macro says it's just a wrapper for
> >
> > I thought this was using module_platform_driver() macro?
> >
> > > device_initcall.
> > >
> > > Won't we then need to remove all the __initconst tags too since the
> > > probe function walks through jh7100_clk_data which eventually
> > > references all __initconst data?
> >
> > Yes. If it's builtin_platform_driver() it can't be a module/tristate
> > Kconfig, in which case all the init markings can stay.
> 
> Yes, it's already bool in the Kconfig file. After looking into this I
> think it's better to do like the rockchip drivers and use
> builtin_platform_driver_probe to make sure the probe function only
> called at kernel init time:
> 
> static struct platform_driver clk_starfive_jh7100_driver = {
>         .driver = {
>                 .name = "clk-starfive-jh7100",
>                 .of_match_table = clk_starfive_jh7100_match,
>                 .suppress_bind_attrs = true,
>         },
> };
> builtin_platform_driver_probe(clk_starfive_jh7100_driver,
> clk_starfive_jh7100_probe);
> 
> @Andy: is the supress_bind_attrs what you were asking about?

Clever chap! :-)
Yes, that's what I have in mind.

...

> > If it's never going to be a module then don't add any module_* things.
> 
> So does that just mean no MODULE_DEVICE_TABLE or should I also remove
> MODULE_DESCRIPTION, MODULE_AUTHOR and MODULE_LICENSE? I'm just double
> checking because the rockchip drivers seem to have MODULE_DESCRIPTION
> and MODULE_LICENSE lines.

You may comment them out. Convert them to comments or so.
But in general yes, they are no-ops in such case.

-- 
With Best Regards,
Andy Shevchenko



_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 06/16] clk: starfive: Add JH7100 clock generator driver
  2021-10-27 10:24           ` Emil Renner Berthing
@ 2021-10-27 11:22             ` Heiko Stübner
  -1 siblings, 0 replies; 143+ messages in thread
From: Heiko Stübner @ 2021-10-27 11:22 UTC (permalink / raw)
  To: Stephen Boyd, linux-riscv
  Cc: open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	linux-clk, open list:GPIO SUBSYSTEM, linux-riscv,
	open list:SERIAL DRIVERS, Geert Uytterhoeven, Palmer Dabbelt,
	Paul Walmsley, Rob Herring, Michael Turquette, Thomas Gleixner,
	Marc Zyngier, Philipp Zabel, Linus Walleij, Greg Kroah-Hartman,
	Daniel Lezcano, Andy Shevchenko, Jiri Slaby, Maximilian Luz,
	Sagar Kadam, Drew Fustini, Michael Zhu, Fu Wei, Anup Patel,
	Atish Patra, Linux Kernel Mailing List, Emil Renner Berthing

Am Mittwoch, 27. Oktober 2021, 12:24:07 CEST schrieb Emil Renner Berthing:
> On Wed, 27 Oct 2021 at 02:54, Stephen Boyd <sboyd@kernel.org> wrote:
> > Quoting Emil Renner Berthing (2021-10-26 15:35:36)
> > > On Tue, 26 Oct 2021 at 22:20, Stephen Boyd <sboyd@kernel.org> wrote:
> > > > Quoting Emil Renner Berthing (2021-10-21 10:42:13)
> > > > > +};
> > > > > +
> > > > > +struct clk_starfive_jh7100_priv {
> > > > > +       /* protect registers against overlapping read-modify-write */
> > > > > +       spinlock_t rmw_lock;
> > > >
> > > > Does overlapping mean concurrent?
> > >
> > > Yes, sorry.
> > >
> > > > Do different clks share the same registers?
> > >
> > > No, each clock has their own register, but they use that register both
> > > to gate the clock and other configuration. The Locking chapter of
> > > Documentation/driver-api/clk.rst talks about the prepare lock and the
> > > enable lock and then says:
> > > "However, access to resources that are shared between operations of
> > > the two groups needs to be protected by the drivers. An example of
> > > such a resource would be a register that controls both the clock rate
> > > and the clock enable/disable state."
> >
> > Alright got it. Maybe say "protect clk enable and set rate from
> > happening at the same time".
> >
> > >
> > > > > +               return ERR_PTR(-EINVAL);
> > > > > +       }
> > > > > +
> > > > > +       if (idx >= JH7100_CLK_PLL0_OUT)
> > > > > +               return priv->pll[idx - JH7100_CLK_PLL0_OUT];
> > > > > +
> > > > > +       return &priv->reg[idx].hw;
> > > > > +}
> > > > > +
> > > > > +static int __init clk_starfive_jh7100_probe(struct platform_device *pdev)
> > > >
> > > > Drop __init as this can be called after kernel init is over.
> > >
> > > Oh interesting, I'd like to know when that can happen. The comment for
> > > the builtin_platform_driver macro says it's just a wrapper for
> >
> > I thought this was using module_platform_driver() macro?
> >
> > > device_initcall.
> > >
> > > Won't we then need to remove all the __initconst tags too since the
> > > probe function walks through jh7100_clk_data which eventually
> > > references all __initconst data?
> >
> > Yes. If it's builtin_platform_driver() it can't be a module/tristate
> > Kconfig, in which case all the init markings can stay.
> 
> Yes, it's already bool in the Kconfig file. After looking into this I
> think it's better to do like the rockchip drivers and use
> builtin_platform_driver_probe to make sure the probe function only
> called at kernel init time:
> 
> static struct platform_driver clk_starfive_jh7100_driver = {
>         .driver = {
>                 .name = "clk-starfive-jh7100",
>                 .of_match_table = clk_starfive_jh7100_match,
>                 .suppress_bind_attrs = true,
>         },
> };
> builtin_platform_driver_probe(clk_starfive_jh7100_driver,
> clk_starfive_jh7100_probe);
> 
> @Andy: is the supress_bind_attrs what you were asking about?
> 
> > > > > +
> > > > > +               clk->hw.init = &init;
> > > > > +               clk->idx = idx;
> > > > > +               clk->max = jh7100_clk_data[idx].max;
> > > > > +
> > > > > +               ret = clk_hw_register(priv->dev, &clk->hw);
> > > >
> > > > Why not use devm_clk_hw_register()?
> > >
> > > I probably could. Just for my understanding that's just to avoid the
> > > loop on error below, because as a builtin driver the device won't
> > > otherwise go away, right?
> >
> > Yes
> >
> > >
> > > > > +               if (ret)
> > > > > +                       goto err;
> > > > > +       }
> > > > > +
> > > > > +       ret = devm_of_clk_add_hw_provider(priv->dev, clk_starfive_jh7100_get, priv);
> > > > > +       if (ret)
> > > > > +               goto err;
> > > > > +
> > > > > +       return 0;
> > > > > +err:
> > > > > +       while (idx)
> > > > > +               clk_hw_unregister(&priv->reg[--idx].hw);
> > > > > +       return ret;
> > > > > +}
> > > > > +
> > > > > +static const struct of_device_id clk_starfive_jh7100_match[] = {
> > > > > +       { .compatible = "starfive,jh7100-clkgen" },
> > > > > +       { /* sentinel */ }
> > > > > +};
> > > >
> > > > Please add MODULE_DEVICE_TABLE()
> > >
> > > Will do!
> >
> > If it's never going to be a module then don't add any module_* things.
> 
> So does that just mean no MODULE_DEVICE_TABLE or should I also remove
> MODULE_DESCRIPTION, MODULE_AUTHOR and MODULE_LICENSE? I'm just double
> checking because the rockchip drivers seem to have MODULE_DESCRIPTION
> and MODULE_LICENSE lines.

reading this I realized that the current implementation on the Rockchip side
is faulty :-) .

For one, there recently was a change for 5.16 that moved this to use
module_platform_driver, while keeping the initdata, which suggest that
the change was actually not tested at all in that context.

And secondly the kconfig is wrong to actually use tristate and should instead
use bool.

Of course this is also influenced by the recent GKI discussion [0] ;-)

I'm going to revert the one change and also adapt the kconfig to use bool
again.


Heiko

[0] https://lwn.net/Articles/872209/



^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 06/16] clk: starfive: Add JH7100 clock generator driver
@ 2021-10-27 11:22             ` Heiko Stübner
  0 siblings, 0 replies; 143+ messages in thread
From: Heiko Stübner @ 2021-10-27 11:22 UTC (permalink / raw)
  To: Stephen Boyd, linux-riscv
  Cc: open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	linux-clk, open list:GPIO SUBSYSTEM, linux-riscv,
	open list:SERIAL DRIVERS, Geert Uytterhoeven, Palmer Dabbelt,
	Paul Walmsley, Rob Herring, Michael Turquette, Thomas Gleixner,
	Marc Zyngier, Philipp Zabel, Linus Walleij, Greg Kroah-Hartman,
	Daniel Lezcano, Andy Shevchenko, Jiri Slaby, Maximilian Luz,
	Sagar Kadam, Drew Fustini, Michael Zhu, Fu Wei, Anup Patel,
	Atish Patra, Linux Kernel Mailing List, Emil Renner Berthing

Am Mittwoch, 27. Oktober 2021, 12:24:07 CEST schrieb Emil Renner Berthing:
> On Wed, 27 Oct 2021 at 02:54, Stephen Boyd <sboyd@kernel.org> wrote:
> > Quoting Emil Renner Berthing (2021-10-26 15:35:36)
> > > On Tue, 26 Oct 2021 at 22:20, Stephen Boyd <sboyd@kernel.org> wrote:
> > > > Quoting Emil Renner Berthing (2021-10-21 10:42:13)
> > > > > +};
> > > > > +
> > > > > +struct clk_starfive_jh7100_priv {
> > > > > +       /* protect registers against overlapping read-modify-write */
> > > > > +       spinlock_t rmw_lock;
> > > >
> > > > Does overlapping mean concurrent?
> > >
> > > Yes, sorry.
> > >
> > > > Do different clks share the same registers?
> > >
> > > No, each clock has their own register, but they use that register both
> > > to gate the clock and other configuration. The Locking chapter of
> > > Documentation/driver-api/clk.rst talks about the prepare lock and the
> > > enable lock and then says:
> > > "However, access to resources that are shared between operations of
> > > the two groups needs to be protected by the drivers. An example of
> > > such a resource would be a register that controls both the clock rate
> > > and the clock enable/disable state."
> >
> > Alright got it. Maybe say "protect clk enable and set rate from
> > happening at the same time".
> >
> > >
> > > > > +               return ERR_PTR(-EINVAL);
> > > > > +       }
> > > > > +
> > > > > +       if (idx >= JH7100_CLK_PLL0_OUT)
> > > > > +               return priv->pll[idx - JH7100_CLK_PLL0_OUT];
> > > > > +
> > > > > +       return &priv->reg[idx].hw;
> > > > > +}
> > > > > +
> > > > > +static int __init clk_starfive_jh7100_probe(struct platform_device *pdev)
> > > >
> > > > Drop __init as this can be called after kernel init is over.
> > >
> > > Oh interesting, I'd like to know when that can happen. The comment for
> > > the builtin_platform_driver macro says it's just a wrapper for
> >
> > I thought this was using module_platform_driver() macro?
> >
> > > device_initcall.
> > >
> > > Won't we then need to remove all the __initconst tags too since the
> > > probe function walks through jh7100_clk_data which eventually
> > > references all __initconst data?
> >
> > Yes. If it's builtin_platform_driver() it can't be a module/tristate
> > Kconfig, in which case all the init markings can stay.
> 
> Yes, it's already bool in the Kconfig file. After looking into this I
> think it's better to do like the rockchip drivers and use
> builtin_platform_driver_probe to make sure the probe function only
> called at kernel init time:
> 
> static struct platform_driver clk_starfive_jh7100_driver = {
>         .driver = {
>                 .name = "clk-starfive-jh7100",
>                 .of_match_table = clk_starfive_jh7100_match,
>                 .suppress_bind_attrs = true,
>         },
> };
> builtin_platform_driver_probe(clk_starfive_jh7100_driver,
> clk_starfive_jh7100_probe);
> 
> @Andy: is the supress_bind_attrs what you were asking about?
> 
> > > > > +
> > > > > +               clk->hw.init = &init;
> > > > > +               clk->idx = idx;
> > > > > +               clk->max = jh7100_clk_data[idx].max;
> > > > > +
> > > > > +               ret = clk_hw_register(priv->dev, &clk->hw);
> > > >
> > > > Why not use devm_clk_hw_register()?
> > >
> > > I probably could. Just for my understanding that's just to avoid the
> > > loop on error below, because as a builtin driver the device won't
> > > otherwise go away, right?
> >
> > Yes
> >
> > >
> > > > > +               if (ret)
> > > > > +                       goto err;
> > > > > +       }
> > > > > +
> > > > > +       ret = devm_of_clk_add_hw_provider(priv->dev, clk_starfive_jh7100_get, priv);
> > > > > +       if (ret)
> > > > > +               goto err;
> > > > > +
> > > > > +       return 0;
> > > > > +err:
> > > > > +       while (idx)
> > > > > +               clk_hw_unregister(&priv->reg[--idx].hw);
> > > > > +       return ret;
> > > > > +}
> > > > > +
> > > > > +static const struct of_device_id clk_starfive_jh7100_match[] = {
> > > > > +       { .compatible = "starfive,jh7100-clkgen" },
> > > > > +       { /* sentinel */ }
> > > > > +};
> > > >
> > > > Please add MODULE_DEVICE_TABLE()
> > >
> > > Will do!
> >
> > If it's never going to be a module then don't add any module_* things.
> 
> So does that just mean no MODULE_DEVICE_TABLE or should I also remove
> MODULE_DESCRIPTION, MODULE_AUTHOR and MODULE_LICENSE? I'm just double
> checking because the rockchip drivers seem to have MODULE_DESCRIPTION
> and MODULE_LICENSE lines.

reading this I realized that the current implementation on the Rockchip side
is faulty :-) .

For one, there recently was a change for 5.16 that moved this to use
module_platform_driver, while keeping the initdata, which suggest that
the change was actually not tested at all in that context.

And secondly the kconfig is wrong to actually use tristate and should instead
use bool.

Of course this is also influenced by the recent GKI discussion [0] ;-)

I'm going to revert the one change and also adapt the kconfig to use bool
again.


Heiko

[0] https://lwn.net/Articles/872209/



_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 12/16] pinctrl: starfive: Add pinctrl driver for StarFive SoCs
  2021-10-21 17:42   ` Emil Renner Berthing
  (?)
@ 2021-10-28 20:17     ` kernel test robot
  -1 siblings, 0 replies; 143+ messages in thread
From: kernel test robot @ 2021-10-28 20:17 UTC (permalink / raw)
  To: Emil Renner Berthing, linux-riscv, devicetree, linux-clk,
	linux-gpio, linux-serial
  Cc: kbuild-all, Emil Renner Berthing, Palmer Dabbelt, Paul Walmsley,
	Rob Herring, Michael Turquette

[-- Attachment #1: Type: text/plain, Size: 7523 bytes --]

Hi Emil,

I love your patch! Yet something to improve:

[auto build test ERROR on next-20211021]
[also build test ERROR on v5.15-rc7]
[cannot apply to robh/for-next clk/clk-next pza/reset/next linus/master v5.15-rc6 v5.15-rc5 v5.15-rc4]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Emil-Renner-Berthing/Basic-StarFive-JH7100-RISC-V-SoC-support/20211022-014605
base:    3196a52aff93186897f15f1a6c03220ce6523d82
config: alpha-randconfig-p002-20211028 (attached as .config)
compiler: alpha-linux-gcc (GCC) 11.2.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/2aa8169a8c5820ad5b70679777e7f6acd4fd4699
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Emil-Renner-Berthing/Basic-StarFive-JH7100-RISC-V-SoC-support/20211022-014605
        git checkout 2aa8169a8c5820ad5b70679777e7f6acd4fd4699
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross ARCH=alpha 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

   drivers/pinctrl/pinctrl-starfive.c: In function 'starfive_dt_node_to_map':
>> drivers/pinctrl/pinctrl-starfive.c:591:23: error: implicit declaration of function 'pinconf_generic_parse_dt_config'; did you mean 'pinconf_generic_dump_config'? [-Werror=implicit-function-declaration]
     591 |                 ret = pinconf_generic_parse_dt_config(child, pctldev,
         |                       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
         |                       pinconf_generic_dump_config
   cc1: some warnings being treated as errors

Kconfig warnings: (for reference only)
   WARNING: unmet direct dependencies detected for OF_GPIO
   Depends on GPIOLIB && OF && HAS_IOMEM
   Selected by
   - PINCTRL_STARFIVE && PINCTRL && (SOC_STARFIVE || COMPILE_TEST
   WARNING: unmet direct dependencies detected for GPIO_SYSCON
   Depends on GPIOLIB && HAS_IOMEM && MFD_SYSCON && OF
   Selected by
   - GPIO_SAMA5D2_PIOBU && GPIOLIB && HAS_IOMEM && MFD_SYSCON && OF_GPIO


vim +591 drivers/pinctrl/pinctrl-starfive.c

   475	
   476	static int starfive_dt_node_to_map(struct pinctrl_dev *pctldev,
   477					   struct device_node *np,
   478					   struct pinctrl_map **maps,
   479					   unsigned int *num_maps)
   480	{
   481		struct starfive_pinctrl *sfp = pinctrl_dev_get_drvdata(pctldev);
   482		struct device *dev = starfive_dev(sfp);
   483		const char **pgnames;
   484		struct pinctrl_map *map;
   485		struct device_node *child;
   486		const char *grpname;
   487		int *pins;
   488		u32 *pinmux;
   489		int nmaps;
   490		int ngroups;
   491		int ret;
   492	
   493		nmaps = 0;
   494		ngroups = 0;
   495		for_each_child_of_node(np, child) {
   496			int npinmux = of_property_count_u32_elems(child, "pinmux");
   497			int npins   = of_property_count_u32_elems(child, "pins");
   498	
   499			if (npinmux > 0 && npins > 0) {
   500				dev_err(dev, "invalid pinctrl group %pOFn.%pOFn: %s\n",
   501					np, child, "both pinmux and pins set");
   502				of_node_put(child);
   503				return -EINVAL;
   504			}
   505	
   506			if (npinmux > 0) {
   507				nmaps += 2;
   508			} else if (npins > 0) {
   509				nmaps += 1;
   510			} else {
   511				dev_err(dev, "invalid pinctrl group %pOFn.%pOFn: %s\n",
   512					np, child, "neither pinmux nor pins set");
   513				of_node_put(child);
   514				return -EINVAL;
   515			}
   516			ngroups += 1;
   517		}
   518	
   519		ret = -ENOMEM;
   520		pgnames = devm_kcalloc(dev, ngroups, sizeof(*pgnames), GFP_KERNEL);
   521		if (!pgnames)
   522			return ret;
   523	
   524		map = kcalloc(nmaps, sizeof(*map), GFP_KERNEL);
   525		if (!map)
   526			goto free_pgnames;
   527	
   528		nmaps = 0;
   529		ngroups = 0;
   530		for_each_child_of_node(np, child) {
   531			int npins;
   532			int i;
   533	
   534			ret = -ENOMEM;
   535			grpname = devm_kasprintf(dev, GFP_KERNEL, "%s.%s", np->name, child->name);
   536			if (!grpname)
   537				goto put_child;
   538	
   539			pgnames[ngroups++] = grpname;
   540	
   541			if ((npins = of_property_count_u32_elems(child, "pinmux")) > 0) {
   542				pins = devm_kcalloc(dev, npins, sizeof(*pins), GFP_KERNEL);
   543				if (!pins)
   544					goto free_grpname;
   545	
   546				pinmux = devm_kcalloc(dev, npins, sizeof(*pinmux), GFP_KERNEL);
   547				if (!pinmux)
   548					goto free_pins;
   549	
   550				for (i = 0; i < npins; i++) {
   551					u32 v;
   552	
   553					ret = of_property_read_u32_index(child, "pinmux", i, &v);
   554					if (ret)
   555						goto free_pinmux;
   556					pins[i] = starfive_gpio_to_pin(sfp, starfive_pinmux_to_gpio(v));
   557					pinmux[i] = v;
   558				}
   559	
   560				map[nmaps].type = PIN_MAP_TYPE_MUX_GROUP;
   561				map[nmaps].data.mux.function = np->name;
   562				map[nmaps].data.mux.group = grpname;
   563				nmaps += 1;
   564			} else if ((npins = of_property_count_u32_elems(child, "pins")) > 0) {
   565				pins = devm_kcalloc(dev, npins, sizeof(*pins), GFP_KERNEL);
   566				if (!pins)
   567					goto free_grpname;
   568	
   569				pinmux = NULL;
   570	
   571				for (i = 0; i < npins; i++) {
   572					u32 v;
   573	
   574					ret = of_property_read_u32_index(child, "pins", i, &v);
   575					if (ret)
   576						goto free_pins;
   577					pins[i] = v;
   578				}
   579			} else {
   580				ret = -EINVAL;
   581				goto free_grpname;
   582			}
   583	
   584			ret = pinctrl_generic_add_group(pctldev, grpname, pins, npins, pinmux);
   585			if (ret < 0) {
   586				dev_err(dev, "error adding group %pOFn.%pOFn: %d\n",
   587					np, child, ret);
   588				goto free_pinmux;
   589			}
   590	
 > 591			ret = pinconf_generic_parse_dt_config(child, pctldev,
   592							      &map[nmaps].data.configs.configs,
   593							      &map[nmaps].data.configs.num_configs);
   594			if (ret) {
   595				dev_err(dev, "invalid pinctrl group %pOFn.%pOFn: %s\n",
   596					np, child, "error parsing pin config");
   597				goto put_child;
   598			}
   599	
   600			/* don't create a map if there are no pinconf settings */
   601			if (map[nmaps].data.configs.num_configs == 0)
   602				continue;
   603	
   604			map[nmaps].type = PIN_MAP_TYPE_CONFIGS_GROUP;
   605			map[nmaps].data.configs.group_or_pin = grpname;
   606			nmaps += 1;
   607		}
   608	
   609		ret = pinmux_generic_add_function(pctldev, np->name, pgnames, ngroups, NULL);
   610		if (ret < 0) {
   611			dev_err(dev, "error adding function %pOFn: %d\n", np, ret);
   612			goto free_map;
   613		}
   614	
   615		*maps = map;
   616		*num_maps = nmaps;
   617		return 0;
   618	
   619	free_pinmux:
   620		devm_kfree(dev, pinmux);
   621	free_pins:
   622		devm_kfree(dev, pins);
   623	free_grpname:
   624		devm_kfree(dev, grpname);
   625	put_child:
   626		of_node_put(child);
   627	free_map:
   628		pinctrl_utils_free_map(pctldev, map, nmaps);
   629	free_pgnames:
   630		devm_kfree(dev, pgnames);
   631		return ret;
   632	}
   633	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 32651 bytes --]

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 12/16] pinctrl: starfive: Add pinctrl driver for StarFive SoCs
@ 2021-10-28 20:17     ` kernel test robot
  0 siblings, 0 replies; 143+ messages in thread
From: kernel test robot @ 2021-10-28 20:17 UTC (permalink / raw)
  To: Emil Renner Berthing, linux-riscv, devicetree, linux-clk,
	linux-gpio, linux-serial
  Cc: kbuild-all, Emil Renner Berthing, Palmer Dabbelt, Paul Walmsley,
	Rob Herring, Michael Turquette

[-- Attachment #1: Type: text/plain, Size: 7523 bytes --]

Hi Emil,

I love your patch! Yet something to improve:

[auto build test ERROR on next-20211021]
[also build test ERROR on v5.15-rc7]
[cannot apply to robh/for-next clk/clk-next pza/reset/next linus/master v5.15-rc6 v5.15-rc5 v5.15-rc4]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Emil-Renner-Berthing/Basic-StarFive-JH7100-RISC-V-SoC-support/20211022-014605
base:    3196a52aff93186897f15f1a6c03220ce6523d82
config: alpha-randconfig-p002-20211028 (attached as .config)
compiler: alpha-linux-gcc (GCC) 11.2.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/2aa8169a8c5820ad5b70679777e7f6acd4fd4699
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Emil-Renner-Berthing/Basic-StarFive-JH7100-RISC-V-SoC-support/20211022-014605
        git checkout 2aa8169a8c5820ad5b70679777e7f6acd4fd4699
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross ARCH=alpha 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

   drivers/pinctrl/pinctrl-starfive.c: In function 'starfive_dt_node_to_map':
>> drivers/pinctrl/pinctrl-starfive.c:591:23: error: implicit declaration of function 'pinconf_generic_parse_dt_config'; did you mean 'pinconf_generic_dump_config'? [-Werror=implicit-function-declaration]
     591 |                 ret = pinconf_generic_parse_dt_config(child, pctldev,
         |                       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
         |                       pinconf_generic_dump_config
   cc1: some warnings being treated as errors

Kconfig warnings: (for reference only)
   WARNING: unmet direct dependencies detected for OF_GPIO
   Depends on GPIOLIB && OF && HAS_IOMEM
   Selected by
   - PINCTRL_STARFIVE && PINCTRL && (SOC_STARFIVE || COMPILE_TEST
   WARNING: unmet direct dependencies detected for GPIO_SYSCON
   Depends on GPIOLIB && HAS_IOMEM && MFD_SYSCON && OF
   Selected by
   - GPIO_SAMA5D2_PIOBU && GPIOLIB && HAS_IOMEM && MFD_SYSCON && OF_GPIO


vim +591 drivers/pinctrl/pinctrl-starfive.c

   475	
   476	static int starfive_dt_node_to_map(struct pinctrl_dev *pctldev,
   477					   struct device_node *np,
   478					   struct pinctrl_map **maps,
   479					   unsigned int *num_maps)
   480	{
   481		struct starfive_pinctrl *sfp = pinctrl_dev_get_drvdata(pctldev);
   482		struct device *dev = starfive_dev(sfp);
   483		const char **pgnames;
   484		struct pinctrl_map *map;
   485		struct device_node *child;
   486		const char *grpname;
   487		int *pins;
   488		u32 *pinmux;
   489		int nmaps;
   490		int ngroups;
   491		int ret;
   492	
   493		nmaps = 0;
   494		ngroups = 0;
   495		for_each_child_of_node(np, child) {
   496			int npinmux = of_property_count_u32_elems(child, "pinmux");
   497			int npins   = of_property_count_u32_elems(child, "pins");
   498	
   499			if (npinmux > 0 && npins > 0) {
   500				dev_err(dev, "invalid pinctrl group %pOFn.%pOFn: %s\n",
   501					np, child, "both pinmux and pins set");
   502				of_node_put(child);
   503				return -EINVAL;
   504			}
   505	
   506			if (npinmux > 0) {
   507				nmaps += 2;
   508			} else if (npins > 0) {
   509				nmaps += 1;
   510			} else {
   511				dev_err(dev, "invalid pinctrl group %pOFn.%pOFn: %s\n",
   512					np, child, "neither pinmux nor pins set");
   513				of_node_put(child);
   514				return -EINVAL;
   515			}
   516			ngroups += 1;
   517		}
   518	
   519		ret = -ENOMEM;
   520		pgnames = devm_kcalloc(dev, ngroups, sizeof(*pgnames), GFP_KERNEL);
   521		if (!pgnames)
   522			return ret;
   523	
   524		map = kcalloc(nmaps, sizeof(*map), GFP_KERNEL);
   525		if (!map)
   526			goto free_pgnames;
   527	
   528		nmaps = 0;
   529		ngroups = 0;
   530		for_each_child_of_node(np, child) {
   531			int npins;
   532			int i;
   533	
   534			ret = -ENOMEM;
   535			grpname = devm_kasprintf(dev, GFP_KERNEL, "%s.%s", np->name, child->name);
   536			if (!grpname)
   537				goto put_child;
   538	
   539			pgnames[ngroups++] = grpname;
   540	
   541			if ((npins = of_property_count_u32_elems(child, "pinmux")) > 0) {
   542				pins = devm_kcalloc(dev, npins, sizeof(*pins), GFP_KERNEL);
   543				if (!pins)
   544					goto free_grpname;
   545	
   546				pinmux = devm_kcalloc(dev, npins, sizeof(*pinmux), GFP_KERNEL);
   547				if (!pinmux)
   548					goto free_pins;
   549	
   550				for (i = 0; i < npins; i++) {
   551					u32 v;
   552	
   553					ret = of_property_read_u32_index(child, "pinmux", i, &v);
   554					if (ret)
   555						goto free_pinmux;
   556					pins[i] = starfive_gpio_to_pin(sfp, starfive_pinmux_to_gpio(v));
   557					pinmux[i] = v;
   558				}
   559	
   560				map[nmaps].type = PIN_MAP_TYPE_MUX_GROUP;
   561				map[nmaps].data.mux.function = np->name;
   562				map[nmaps].data.mux.group = grpname;
   563				nmaps += 1;
   564			} else if ((npins = of_property_count_u32_elems(child, "pins")) > 0) {
   565				pins = devm_kcalloc(dev, npins, sizeof(*pins), GFP_KERNEL);
   566				if (!pins)
   567					goto free_grpname;
   568	
   569				pinmux = NULL;
   570	
   571				for (i = 0; i < npins; i++) {
   572					u32 v;
   573	
   574					ret = of_property_read_u32_index(child, "pins", i, &v);
   575					if (ret)
   576						goto free_pins;
   577					pins[i] = v;
   578				}
   579			} else {
   580				ret = -EINVAL;
   581				goto free_grpname;
   582			}
   583	
   584			ret = pinctrl_generic_add_group(pctldev, grpname, pins, npins, pinmux);
   585			if (ret < 0) {
   586				dev_err(dev, "error adding group %pOFn.%pOFn: %d\n",
   587					np, child, ret);
   588				goto free_pinmux;
   589			}
   590	
 > 591			ret = pinconf_generic_parse_dt_config(child, pctldev,
   592							      &map[nmaps].data.configs.configs,
   593							      &map[nmaps].data.configs.num_configs);
   594			if (ret) {
   595				dev_err(dev, "invalid pinctrl group %pOFn.%pOFn: %s\n",
   596					np, child, "error parsing pin config");
   597				goto put_child;
   598			}
   599	
   600			/* don't create a map if there are no pinconf settings */
   601			if (map[nmaps].data.configs.num_configs == 0)
   602				continue;
   603	
   604			map[nmaps].type = PIN_MAP_TYPE_CONFIGS_GROUP;
   605			map[nmaps].data.configs.group_or_pin = grpname;
   606			nmaps += 1;
   607		}
   608	
   609		ret = pinmux_generic_add_function(pctldev, np->name, pgnames, ngroups, NULL);
   610		if (ret < 0) {
   611			dev_err(dev, "error adding function %pOFn: %d\n", np, ret);
   612			goto free_map;
   613		}
   614	
   615		*maps = map;
   616		*num_maps = nmaps;
   617		return 0;
   618	
   619	free_pinmux:
   620		devm_kfree(dev, pinmux);
   621	free_pins:
   622		devm_kfree(dev, pins);
   623	free_grpname:
   624		devm_kfree(dev, grpname);
   625	put_child:
   626		of_node_put(child);
   627	free_map:
   628		pinctrl_utils_free_map(pctldev, map, nmaps);
   629	free_pgnames:
   630		devm_kfree(dev, pgnames);
   631		return ret;
   632	}
   633	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 32651 bytes --]

[-- Attachment #3: Type: text/plain, Size: 161 bytes --]

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 12/16] pinctrl: starfive: Add pinctrl driver for StarFive SoCs
@ 2021-10-28 20:17     ` kernel test robot
  0 siblings, 0 replies; 143+ messages in thread
From: kernel test robot @ 2021-10-28 20:17 UTC (permalink / raw)
  To: kbuild-all

[-- Attachment #1: Type: text/plain, Size: 7736 bytes --]

Hi Emil,

I love your patch! Yet something to improve:

[auto build test ERROR on next-20211021]
[also build test ERROR on v5.15-rc7]
[cannot apply to robh/for-next clk/clk-next pza/reset/next linus/master v5.15-rc6 v5.15-rc5 v5.15-rc4]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Emil-Renner-Berthing/Basic-StarFive-JH7100-RISC-V-SoC-support/20211022-014605
base:    3196a52aff93186897f15f1a6c03220ce6523d82
config: alpha-randconfig-p002-20211028 (attached as .config)
compiler: alpha-linux-gcc (GCC) 11.2.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/2aa8169a8c5820ad5b70679777e7f6acd4fd4699
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Emil-Renner-Berthing/Basic-StarFive-JH7100-RISC-V-SoC-support/20211022-014605
        git checkout 2aa8169a8c5820ad5b70679777e7f6acd4fd4699
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross ARCH=alpha 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

   drivers/pinctrl/pinctrl-starfive.c: In function 'starfive_dt_node_to_map':
>> drivers/pinctrl/pinctrl-starfive.c:591:23: error: implicit declaration of function 'pinconf_generic_parse_dt_config'; did you mean 'pinconf_generic_dump_config'? [-Werror=implicit-function-declaration]
     591 |                 ret = pinconf_generic_parse_dt_config(child, pctldev,
         |                       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
         |                       pinconf_generic_dump_config
   cc1: some warnings being treated as errors

Kconfig warnings: (for reference only)
   WARNING: unmet direct dependencies detected for OF_GPIO
   Depends on GPIOLIB && OF && HAS_IOMEM
   Selected by
   - PINCTRL_STARFIVE && PINCTRL && (SOC_STARFIVE || COMPILE_TEST
   WARNING: unmet direct dependencies detected for GPIO_SYSCON
   Depends on GPIOLIB && HAS_IOMEM && MFD_SYSCON && OF
   Selected by
   - GPIO_SAMA5D2_PIOBU && GPIOLIB && HAS_IOMEM && MFD_SYSCON && OF_GPIO


vim +591 drivers/pinctrl/pinctrl-starfive.c

   475	
   476	static int starfive_dt_node_to_map(struct pinctrl_dev *pctldev,
   477					   struct device_node *np,
   478					   struct pinctrl_map **maps,
   479					   unsigned int *num_maps)
   480	{
   481		struct starfive_pinctrl *sfp = pinctrl_dev_get_drvdata(pctldev);
   482		struct device *dev = starfive_dev(sfp);
   483		const char **pgnames;
   484		struct pinctrl_map *map;
   485		struct device_node *child;
   486		const char *grpname;
   487		int *pins;
   488		u32 *pinmux;
   489		int nmaps;
   490		int ngroups;
   491		int ret;
   492	
   493		nmaps = 0;
   494		ngroups = 0;
   495		for_each_child_of_node(np, child) {
   496			int npinmux = of_property_count_u32_elems(child, "pinmux");
   497			int npins   = of_property_count_u32_elems(child, "pins");
   498	
   499			if (npinmux > 0 && npins > 0) {
   500				dev_err(dev, "invalid pinctrl group %pOFn.%pOFn: %s\n",
   501					np, child, "both pinmux and pins set");
   502				of_node_put(child);
   503				return -EINVAL;
   504			}
   505	
   506			if (npinmux > 0) {
   507				nmaps += 2;
   508			} else if (npins > 0) {
   509				nmaps += 1;
   510			} else {
   511				dev_err(dev, "invalid pinctrl group %pOFn.%pOFn: %s\n",
   512					np, child, "neither pinmux nor pins set");
   513				of_node_put(child);
   514				return -EINVAL;
   515			}
   516			ngroups += 1;
   517		}
   518	
   519		ret = -ENOMEM;
   520		pgnames = devm_kcalloc(dev, ngroups, sizeof(*pgnames), GFP_KERNEL);
   521		if (!pgnames)
   522			return ret;
   523	
   524		map = kcalloc(nmaps, sizeof(*map), GFP_KERNEL);
   525		if (!map)
   526			goto free_pgnames;
   527	
   528		nmaps = 0;
   529		ngroups = 0;
   530		for_each_child_of_node(np, child) {
   531			int npins;
   532			int i;
   533	
   534			ret = -ENOMEM;
   535			grpname = devm_kasprintf(dev, GFP_KERNEL, "%s.%s", np->name, child->name);
   536			if (!grpname)
   537				goto put_child;
   538	
   539			pgnames[ngroups++] = grpname;
   540	
   541			if ((npins = of_property_count_u32_elems(child, "pinmux")) > 0) {
   542				pins = devm_kcalloc(dev, npins, sizeof(*pins), GFP_KERNEL);
   543				if (!pins)
   544					goto free_grpname;
   545	
   546				pinmux = devm_kcalloc(dev, npins, sizeof(*pinmux), GFP_KERNEL);
   547				if (!pinmux)
   548					goto free_pins;
   549	
   550				for (i = 0; i < npins; i++) {
   551					u32 v;
   552	
   553					ret = of_property_read_u32_index(child, "pinmux", i, &v);
   554					if (ret)
   555						goto free_pinmux;
   556					pins[i] = starfive_gpio_to_pin(sfp, starfive_pinmux_to_gpio(v));
   557					pinmux[i] = v;
   558				}
   559	
   560				map[nmaps].type = PIN_MAP_TYPE_MUX_GROUP;
   561				map[nmaps].data.mux.function = np->name;
   562				map[nmaps].data.mux.group = grpname;
   563				nmaps += 1;
   564			} else if ((npins = of_property_count_u32_elems(child, "pins")) > 0) {
   565				pins = devm_kcalloc(dev, npins, sizeof(*pins), GFP_KERNEL);
   566				if (!pins)
   567					goto free_grpname;
   568	
   569				pinmux = NULL;
   570	
   571				for (i = 0; i < npins; i++) {
   572					u32 v;
   573	
   574					ret = of_property_read_u32_index(child, "pins", i, &v);
   575					if (ret)
   576						goto free_pins;
   577					pins[i] = v;
   578				}
   579			} else {
   580				ret = -EINVAL;
   581				goto free_grpname;
   582			}
   583	
   584			ret = pinctrl_generic_add_group(pctldev, grpname, pins, npins, pinmux);
   585			if (ret < 0) {
   586				dev_err(dev, "error adding group %pOFn.%pOFn: %d\n",
   587					np, child, ret);
   588				goto free_pinmux;
   589			}
   590	
 > 591			ret = pinconf_generic_parse_dt_config(child, pctldev,
   592							      &map[nmaps].data.configs.configs,
   593							      &map[nmaps].data.configs.num_configs);
   594			if (ret) {
   595				dev_err(dev, "invalid pinctrl group %pOFn.%pOFn: %s\n",
   596					np, child, "error parsing pin config");
   597				goto put_child;
   598			}
   599	
   600			/* don't create a map if there are no pinconf settings */
   601			if (map[nmaps].data.configs.num_configs == 0)
   602				continue;
   603	
   604			map[nmaps].type = PIN_MAP_TYPE_CONFIGS_GROUP;
   605			map[nmaps].data.configs.group_or_pin = grpname;
   606			nmaps += 1;
   607		}
   608	
   609		ret = pinmux_generic_add_function(pctldev, np->name, pgnames, ngroups, NULL);
   610		if (ret < 0) {
   611			dev_err(dev, "error adding function %pOFn: %d\n", np, ret);
   612			goto free_map;
   613		}
   614	
   615		*maps = map;
   616		*num_maps = nmaps;
   617		return 0;
   618	
   619	free_pinmux:
   620		devm_kfree(dev, pinmux);
   621	free_pins:
   622		devm_kfree(dev, pins);
   623	free_grpname:
   624		devm_kfree(dev, grpname);
   625	put_child:
   626		of_node_put(child);
   627	free_map:
   628		pinctrl_utils_free_map(pctldev, map, nmaps);
   629	free_pgnames:
   630		devm_kfree(dev, pgnames);
   631		return ret;
   632	}
   633	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

[-- Attachment #2: config.gz --]
[-- Type: application/gzip, Size: 32651 bytes --]

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 03/16] dt-bindings: interrupt-controller: Add StarFive JH7100 plic
  2021-10-21 17:42   ` Emil Renner Berthing
@ 2021-10-29  1:37     ` Rob Herring
  -1 siblings, 0 replies; 143+ messages in thread
From: Rob Herring @ 2021-10-29  1:37 UTC (permalink / raw)
  To: Emil Renner Berthing
  Cc: Stephen Boyd, Michael Turquette, Palmer Dabbelt, Michael Zhu,
	Maximilian Luz, Paul Walmsley, Fu Wei, Rob Herring, Jiri Slaby,
	Thomas Gleixner, Greg Kroah-Hartman, linux-riscv, Linus Walleij,
	Anup Patel, Drew Fustini, linux-clk, Matteo Croce, Atish Patra,
	linux-kernel, devicetree, Philipp Zabel, linux-gpio,
	Andy Shevchenko, Daniel Lezcano, Geert Uytterhoeven,
	Marc Zyngier, Sagar Kadam, linux-serial

On Thu, 21 Oct 2021 19:42:10 +0200, Emil Renner Berthing wrote:
> Add compatible string for StarFive JH7100 plic.
> 
> Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
> Reviewed-by: Geert Uytterhoeven <geert@linux-m68k.org>
> ---
>  .../bindings/interrupt-controller/sifive,plic-1.0.0.yaml         | 1 +
>  1 file changed, 1 insertion(+)
> 

Acked-by: Rob Herring <robh@kernel.org>

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 03/16] dt-bindings: interrupt-controller: Add StarFive JH7100 plic
@ 2021-10-29  1:37     ` Rob Herring
  0 siblings, 0 replies; 143+ messages in thread
From: Rob Herring @ 2021-10-29  1:37 UTC (permalink / raw)
  To: Emil Renner Berthing
  Cc: Stephen Boyd, Michael Turquette, Palmer Dabbelt, Michael Zhu,
	Maximilian Luz, Paul Walmsley, Fu Wei, Rob Herring, Jiri Slaby,
	Thomas Gleixner, Greg Kroah-Hartman, linux-riscv, Linus Walleij,
	Anup Patel, Drew Fustini, linux-clk, Matteo Croce, Atish Patra,
	linux-kernel, devicetree, Philipp Zabel, linux-gpio,
	Andy Shevchenko, Daniel Lezcano, Geert Uytterhoeven,
	Marc Zyngier, Sagar Kadam, linux-serial

On Thu, 21 Oct 2021 19:42:10 +0200, Emil Renner Berthing wrote:
> Add compatible string for StarFive JH7100 plic.
> 
> Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
> Reviewed-by: Geert Uytterhoeven <geert@linux-m68k.org>
> ---
>  .../bindings/interrupt-controller/sifive,plic-1.0.0.yaml         | 1 +
>  1 file changed, 1 insertion(+)
> 

Acked-by: Rob Herring <robh@kernel.org>

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 04/16] dt-bindings: clock: starfive: Add JH7100 clock definitions
  2021-10-21 17:42   ` Emil Renner Berthing
@ 2021-10-29  1:42     ` Rob Herring
  -1 siblings, 0 replies; 143+ messages in thread
From: Rob Herring @ 2021-10-29  1:42 UTC (permalink / raw)
  To: Emil Renner Berthing
  Cc: Greg Kroah-Hartman, Matteo Croce, Atish Patra, Drew Fustini,
	linux-serial, Thomas Gleixner, Stephen Boyd, Paul Walmsley,
	Daniel Lezcano, devicetree, Geert Uytterhoeven, Palmer Dabbelt,
	Linus Walleij, Andy Shevchenko, linux-kernel, Maximilian Luz,
	Fu Wei, linux-clk, Philipp Zabel, Michael Turquette,
	Marc Zyngier, linux-gpio, Michael Zhu, Rob Herring, linux-riscv,
	Anup Patel, Jiri Slaby, Sagar Kadam

On Thu, 21 Oct 2021 19:42:11 +0200, Emil Renner Berthing wrote:
> From: Geert Uytterhoeven <geert@linux-m68k.org>
> 
> Add all clock outputs for the StarFive JH7100 clock generator.
> 
> Based on work by Ahmad Fatoum for Barebox, with "JH7100_" prefixes added
> to all definitions.
> 
> Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
> Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
> ---
>  include/dt-bindings/clock/starfive-jh7100.h | 202 ++++++++++++++++++++
>  1 file changed, 202 insertions(+)
>  create mode 100644 include/dt-bindings/clock/starfive-jh7100.h
> 

Acked-by: Rob Herring <robh@kernel.org>

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 04/16] dt-bindings: clock: starfive: Add JH7100 clock definitions
@ 2021-10-29  1:42     ` Rob Herring
  0 siblings, 0 replies; 143+ messages in thread
From: Rob Herring @ 2021-10-29  1:42 UTC (permalink / raw)
  To: Emil Renner Berthing
  Cc: Greg Kroah-Hartman, Matteo Croce, Atish Patra, Drew Fustini,
	linux-serial, Thomas Gleixner, Stephen Boyd, Paul Walmsley,
	Daniel Lezcano, devicetree, Geert Uytterhoeven, Palmer Dabbelt,
	Linus Walleij, Andy Shevchenko, linux-kernel, Maximilian Luz,
	Fu Wei, linux-clk, Philipp Zabel, Michael Turquette,
	Marc Zyngier, linux-gpio, Michael Zhu, Rob Herring, linux-riscv,
	Anup Patel, Jiri Slaby, Sagar Kadam

On Thu, 21 Oct 2021 19:42:11 +0200, Emil Renner Berthing wrote:
> From: Geert Uytterhoeven <geert@linux-m68k.org>
> 
> Add all clock outputs for the StarFive JH7100 clock generator.
> 
> Based on work by Ahmad Fatoum for Barebox, with "JH7100_" prefixes added
> to all definitions.
> 
> Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
> Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
> ---
>  include/dt-bindings/clock/starfive-jh7100.h | 202 ++++++++++++++++++++
>  1 file changed, 202 insertions(+)
>  create mode 100644 include/dt-bindings/clock/starfive-jh7100.h
> 

Acked-by: Rob Herring <robh@kernel.org>

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 05/16] dt-bindings: clock: starfive: Add JH7100 bindings
  2021-10-21 17:42   ` Emil Renner Berthing
@ 2021-10-29  1:42     ` Rob Herring
  -1 siblings, 0 replies; 143+ messages in thread
From: Rob Herring @ 2021-10-29  1:42 UTC (permalink / raw)
  To: Emil Renner Berthing
  Cc: devicetree, linux-clk, linux-serial, Philipp Zabel,
	Maximilian Luz, Drew Fustini, Atish Patra, Rob Herring,
	linux-riscv, Palmer Dabbelt, Michael Zhu, Daniel Lezcano,
	linux-gpio, Sagar Kadam, Matteo Croce, Marc Zyngier,
	Linus Walleij, Greg Kroah-Hartman, Andy Shevchenko,
	Michael Turquette, Anup Patel, Stephen Boyd, Thomas Gleixner,
	linux-kernel, Geert Uytterhoeven, Paul Walmsley, Fu Wei,
	Jiri Slaby

On Thu, 21 Oct 2021 19:42:12 +0200, Emil Renner Berthing wrote:
> From: Geert Uytterhoeven <geert@linux-m68k.org>
> 
> Add device tree bindings for the StarFive JH7100 clock generator.
> 
> Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
> Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
> ---
>  .../clock/starfive,jh7100-clkgen.yaml         | 56 +++++++++++++++++++
>  1 file changed, 56 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/clock/starfive,jh7100-clkgen.yaml
> 

Reviewed-by: Rob Herring <robh@kernel.org>

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 05/16] dt-bindings: clock: starfive: Add JH7100 bindings
@ 2021-10-29  1:42     ` Rob Herring
  0 siblings, 0 replies; 143+ messages in thread
From: Rob Herring @ 2021-10-29  1:42 UTC (permalink / raw)
  To: Emil Renner Berthing
  Cc: devicetree, linux-clk, linux-serial, Philipp Zabel,
	Maximilian Luz, Drew Fustini, Atish Patra, Rob Herring,
	linux-riscv, Palmer Dabbelt, Michael Zhu, Daniel Lezcano,
	linux-gpio, Sagar Kadam, Matteo Croce, Marc Zyngier,
	Linus Walleij, Greg Kroah-Hartman, Andy Shevchenko,
	Michael Turquette, Anup Patel, Stephen Boyd, Thomas Gleixner,
	linux-kernel, Geert Uytterhoeven, Paul Walmsley, Fu Wei,
	Jiri Slaby

On Thu, 21 Oct 2021 19:42:12 +0200, Emil Renner Berthing wrote:
> From: Geert Uytterhoeven <geert@linux-m68k.org>
> 
> Add device tree bindings for the StarFive JH7100 clock generator.
> 
> Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
> Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
> ---
>  .../clock/starfive,jh7100-clkgen.yaml         | 56 +++++++++++++++++++
>  1 file changed, 56 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/clock/starfive,jh7100-clkgen.yaml
> 

Reviewed-by: Rob Herring <robh@kernel.org>

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 07/16] dt-bindings: reset: Add StarFive JH7100 reset definitions
  2021-10-21 17:42   ` Emil Renner Berthing
@ 2021-10-29  1:42     ` Rob Herring
  -1 siblings, 0 replies; 143+ messages in thread
From: Rob Herring @ 2021-10-29  1:42 UTC (permalink / raw)
  To: Emil Renner Berthing
  Cc: Matteo Croce, Thomas Gleixner, Palmer Dabbelt,
	Greg Kroah-Hartman, Philipp Zabel, Marc Zyngier, Sagar Kadam,
	Atish Patra, Michael Zhu, linux-kernel, Paul Walmsley,
	Daniel Lezcano, Stephen Boyd, linux-gpio, devicetree,
	Andy Shevchenko, Linus Walleij, Rob Herring, Jiri Slaby,
	Anup Patel, Maximilian Luz, linux-serial, Fu Wei, linux-riscv,
	Michael Turquette, Drew Fustini, linux-clk, Geert Uytterhoeven

On Thu, 21 Oct 2021 19:42:14 +0200, Emil Renner Berthing wrote:
> From: Geert Uytterhoeven <geert@linux-m68k.org>
> 
> Add all resets for the StarFive JH7100 reset controller.
> 
> Based on work by Ahmad Fatoum for Barebox, with "JH7100_" prefixes added
> to all definitions.
> 
> Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
> Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
> ---
>  include/dt-bindings/reset/starfive-jh7100.h | 126 ++++++++++++++++++++
>  1 file changed, 126 insertions(+)
>  create mode 100644 include/dt-bindings/reset/starfive-jh7100.h
> 

Acked-by: Rob Herring <robh@kernel.org>

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 07/16] dt-bindings: reset: Add StarFive JH7100 reset definitions
@ 2021-10-29  1:42     ` Rob Herring
  0 siblings, 0 replies; 143+ messages in thread
From: Rob Herring @ 2021-10-29  1:42 UTC (permalink / raw)
  To: Emil Renner Berthing
  Cc: Matteo Croce, Thomas Gleixner, Palmer Dabbelt,
	Greg Kroah-Hartman, Philipp Zabel, Marc Zyngier, Sagar Kadam,
	Atish Patra, Michael Zhu, linux-kernel, Paul Walmsley,
	Daniel Lezcano, Stephen Boyd, linux-gpio, devicetree,
	Andy Shevchenko, Linus Walleij, Rob Herring, Jiri Slaby,
	Anup Patel, Maximilian Luz, linux-serial, Fu Wei, linux-riscv,
	Michael Turquette, Drew Fustini, linux-clk, Geert Uytterhoeven

On Thu, 21 Oct 2021 19:42:14 +0200, Emil Renner Berthing wrote:
> From: Geert Uytterhoeven <geert@linux-m68k.org>
> 
> Add all resets for the StarFive JH7100 reset controller.
> 
> Based on work by Ahmad Fatoum for Barebox, with "JH7100_" prefixes added
> to all definitions.
> 
> Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
> Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
> ---
>  include/dt-bindings/reset/starfive-jh7100.h | 126 ++++++++++++++++++++
>  1 file changed, 126 insertions(+)
>  create mode 100644 include/dt-bindings/reset/starfive-jh7100.h
> 

Acked-by: Rob Herring <robh@kernel.org>

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 08/16] dt-bindings: reset: Add Starfive JH7100 reset bindings
  2021-10-21 17:42   ` Emil Renner Berthing
@ 2021-10-29  1:43     ` Rob Herring
  -1 siblings, 0 replies; 143+ messages in thread
From: Rob Herring @ 2021-10-29  1:43 UTC (permalink / raw)
  To: Emil Renner Berthing
  Cc: linux-riscv, devicetree, linux-clk, linux-gpio, linux-serial,
	Palmer Dabbelt, Paul Walmsley, Michael Turquette, Stephen Boyd,
	Thomas Gleixner, Marc Zyngier, Philipp Zabel, Linus Walleij,
	Greg Kroah-Hartman, Daniel Lezcano, Andy Shevchenko, Jiri Slaby,
	Maximilian Luz, Sagar Kadam, Drew Fustini, Geert Uytterhoeven,
	Michael Zhu, Fu Wei, Anup Patel, Atish Patra, Matteo Croce,
	linux-kernel

On Thu, Oct 21, 2021 at 07:42:15PM +0200, Emil Renner Berthing wrote:
> Add device tree bindings for the StarFive JH7100 reset controller.
> 
> Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
> ---
>  .../bindings/reset/starfive,jh7100-reset.yaml | 38 +++++++++++++++++++
>  1 file changed, 38 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/reset/starfive,jh7100-reset.yaml
> 
> diff --git a/Documentation/devicetree/bindings/reset/starfive,jh7100-reset.yaml b/Documentation/devicetree/bindings/reset/starfive,jh7100-reset.yaml
> new file mode 100644
> index 000000000000..c6ad5d7ad100
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/reset/starfive,jh7100-reset.yaml
> @@ -0,0 +1,38 @@
> +# SPDX-License-Identifier: GPL-2.0

Dual license please.

> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/reset/starfive,jh7100-reset.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: StarFive JH7100 SoC Reset Controller Device Tree Bindings
> +
> +maintainers:
> +  - Emil Renner Berthing <kernel@esmil.dk>
> +
> +properties:
> +  compatible:
> +    enum:
> +      - starfive,jh7100-reset
> +
> +  reg:
> +    maxItems: 1
> +
> +  "#reset-cells":
> +    const: 1
> +
> +required:
> +  - compatible
> +  - reg
> +  - "#reset-cells"
> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +    rstgen: reset-controller@11840000 {

Drop unused labels.

> +        compatible = "starfive,jh7100-reset";
> +        reg = <0x11840000 0x10000>;
> +        #reset-cells = <1>;
> +    };
> +
> +...
> -- 
> 2.33.1
> 
> 

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 08/16] dt-bindings: reset: Add Starfive JH7100 reset bindings
@ 2021-10-29  1:43     ` Rob Herring
  0 siblings, 0 replies; 143+ messages in thread
From: Rob Herring @ 2021-10-29  1:43 UTC (permalink / raw)
  To: Emil Renner Berthing
  Cc: linux-riscv, devicetree, linux-clk, linux-gpio, linux-serial,
	Palmer Dabbelt, Paul Walmsley, Michael Turquette, Stephen Boyd,
	Thomas Gleixner, Marc Zyngier, Philipp Zabel, Linus Walleij,
	Greg Kroah-Hartman, Daniel Lezcano, Andy Shevchenko, Jiri Slaby,
	Maximilian Luz, Sagar Kadam, Drew Fustini, Geert Uytterhoeven,
	Michael Zhu, Fu Wei, Anup Patel, Atish Patra, Matteo Croce,
	linux-kernel

On Thu, Oct 21, 2021 at 07:42:15PM +0200, Emil Renner Berthing wrote:
> Add device tree bindings for the StarFive JH7100 reset controller.
> 
> Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
> ---
>  .../bindings/reset/starfive,jh7100-reset.yaml | 38 +++++++++++++++++++
>  1 file changed, 38 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/reset/starfive,jh7100-reset.yaml
> 
> diff --git a/Documentation/devicetree/bindings/reset/starfive,jh7100-reset.yaml b/Documentation/devicetree/bindings/reset/starfive,jh7100-reset.yaml
> new file mode 100644
> index 000000000000..c6ad5d7ad100
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/reset/starfive,jh7100-reset.yaml
> @@ -0,0 +1,38 @@
> +# SPDX-License-Identifier: GPL-2.0

Dual license please.

> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/reset/starfive,jh7100-reset.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: StarFive JH7100 SoC Reset Controller Device Tree Bindings
> +
> +maintainers:
> +  - Emil Renner Berthing <kernel@esmil.dk>
> +
> +properties:
> +  compatible:
> +    enum:
> +      - starfive,jh7100-reset
> +
> +  reg:
> +    maxItems: 1
> +
> +  "#reset-cells":
> +    const: 1
> +
> +required:
> +  - compatible
> +  - reg
> +  - "#reset-cells"
> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +    rstgen: reset-controller@11840000 {

Drop unused labels.

> +        compatible = "starfive,jh7100-reset";
> +        reg = <0x11840000 0x10000>;
> +        #reset-cells = <1>;
> +    };
> +
> +...
> -- 
> 2.33.1
> 
> 

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 10/16] dt-bindings: pinctrl: Add StarFive pinctrl definitions
  2021-10-21 17:42   ` Emil Renner Berthing
@ 2021-10-29  1:44     ` Rob Herring
  -1 siblings, 0 replies; 143+ messages in thread
From: Rob Herring @ 2021-10-29  1:44 UTC (permalink / raw)
  To: Emil Renner Berthing
  Cc: linux-riscv, devicetree, linux-clk, linux-gpio, linux-serial,
	Palmer Dabbelt, Paul Walmsley, Michael Turquette, Stephen Boyd,
	Thomas Gleixner, Marc Zyngier, Philipp Zabel, Linus Walleij,
	Greg Kroah-Hartman, Daniel Lezcano, Andy Shevchenko, Jiri Slaby,
	Maximilian Luz, Sagar Kadam, Drew Fustini, Geert Uytterhoeven,
	Michael Zhu, Fu Wei, Anup Patel, Atish Patra, Matteo Croce,
	linux-kernel

On Thu, Oct 21, 2021 at 07:42:17PM +0200, Emil Renner Berthing wrote:
> Add definitons for pins and GPIO input, output and output enable
> signals on the StarFive JH7100 SoC.
> 
> Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
> ---
>  .../dt-bindings/pinctrl/pinctrl-starfive.h    | 274 ++++++++++++++++++
>  1 file changed, 274 insertions(+)
>  create mode 100644 include/dt-bindings/pinctrl/pinctrl-starfive.h
> 
> diff --git a/include/dt-bindings/pinctrl/pinctrl-starfive.h b/include/dt-bindings/pinctrl/pinctrl-starfive.h
> new file mode 100644
> index 000000000000..f9b6caa83558
> --- /dev/null
> +++ b/include/dt-bindings/pinctrl/pinctrl-starfive.h
> @@ -0,0 +1,274 @@
> +/* SPDX-License-Identifier: GPL-2.0 */

Not consistent with other headers.

All the headers and dts files should have the same licenses.

> +/*
> + * Copyright (c) 2021 Emil Renner Berthing <kernel@esmil.dk>
> + */
> +#ifndef _DT_BINDINGS_PINCTRL_STARFIVE_H
> +#define _DT_BINDINGS_PINCTRL_STARFIVE_H
> +
> +#define PAD_GPIO_OFFSET		0
> +#define PAD_FUNC_SHARE_OFFSET	64
> +#define PAD_GPIO(x)		(PAD_GPIO_OFFSET + (x))
> +#define PAD_FUNC_SHARE(x)	(PAD_FUNC_SHARE_OFFSET + (x))
> +
> +/*
> + * GPIOMUX bits:
> + *  | 31 - 24 | 23 - 16 | 15 - 8 |     7    |     6    |  5 - 0  |
> + *  |  dout   |  doen   |  din   | dout rev | doen rev | gpio nr |
> + *
> + * dout:     output signal
> + * doen:     output enable signal
> + * din:      optional input signal, 0xff = none
> + * dout rev: output signal reverse bit
> + * doen rev: output enable signal reverse bit
> + * gpio nr:  gpio number, 0 - 63
> + */
> +#define GPIOMUX(n, dout, doen, din) ( \
> +		(((dout) & 0x80000000) >> (31 - 7)) | (((dout) & 0xff) << 24) | \
> +		(((doen) & 0x80000000) >> (31 - 6)) | (((doen) & 0xff) << 16) | \
> +		(((din) & 0xff) << 8) | \
> +		((n) & 0x3f))
> +
> +#define GPO_REVERSE				0x80000000
> +
> +#define GPO_LOW					0
> +#define GPO_HIGH				1
> +#define GPO_ENABLE				0
> +#define GPO_DISABLE				1
> +#define GPO_CLK_GMAC_PAPHYREF			2
> +#define GPO_JTAG_TDO				3
> +#define GPO_JTAG_TDO_OEN			4
> +#define GPO_DMIC_CLK_OUT			5
> +#define GPO_DSP_JTDOEN_PAD			6
> +#define GPO_DSP_JTDO_PAD			7
> +#define GPO_I2C0_PAD_SCK_OE			8
> +#define GPO_I2C0_PAD_SCK_OEN			(GPO_I2C0_PAD_SCK_OE | GPO_REVERSE)
> +#define GPO_I2C0_PAD_SDA_OE			9
> +#define GPO_I2C0_PAD_SDA_OEN			(GPO_I2C0_PAD_SDA_OE | GPO_REVERSE)
> +#define GPO_I2C1_PAD_SCK_OE			10
> +#define GPO_I2C1_PAD_SCK_OEN			(GPO_I2C1_PAD_SCK_OE | GPO_REVERSE)
> +#define GPO_I2C1_PAD_SDA_OE			11
> +#define GPO_I2C1_PAD_SDA_OEN			(GPO_I2C1_PAD_SDA_OE | GPO_REVERSE)
> +#define GPO_I2C2_PAD_SCK_OE			12
> +#define GPO_I2C2_PAD_SCK_OEN			(GPO_I2C2_PAD_SCK_OE | GPO_REVERSE)
> +#define GPO_I2C2_PAD_SDA_OE			13
> +#define GPO_I2C2_PAD_SDA_OEN			(GPO_I2C2_PAD_SDA_OE | GPO_REVERSE)
> +#define GPO_I2C3_PAD_SCK_OE			14
> +#define GPO_I2C3_PAD_SCK_OEN			(GPO_I2C3_PAD_SCK_OE | GPO_REVERSE)
> +#define GPO_I2C3_PAD_SDA_OE			15
> +#define GPO_I2C3_PAD_SDA_OEN			(GPO_I2C3_PAD_SDA_OE | GPO_REVERSE)
> +#define GPO_I2SRX_BCLK_OUT			16
> +#define GPO_I2SRX_BCLK_OUT_OEN			17
> +#define GPO_I2SRX_LRCK_OUT			18
> +#define GPO_I2SRX_LRCK_OUT_OEN			19
> +#define GPO_I2SRX_MCLK_OUT			20
> +#define GPO_I2STX_BCLK_OUT			21
> +#define GPO_I2STX_BCLK_OUT_OEN			22
> +#define GPO_I2STX_LRCK_OUT			23
> +#define GPO_I2STX_LRCK_OUT_OEN			24
> +#define GPO_I2STX_MCLK_OUT			25
> +#define GPO_I2STX_SDOUT0			26
> +#define GPO_I2STX_SDOUT1			27
> +#define GPO_LCD_PAD_CSM_N			28
> +#define GPO_PWM_PAD_OE_N_BIT0			29
> +#define GPO_PWM_PAD_OE_N_BIT1			30
> +#define GPO_PWM_PAD_OE_N_BIT2			31
> +#define GPO_PWM_PAD_OE_N_BIT3			32
> +#define GPO_PWM_PAD_OE_N_BIT4			33
> +#define GPO_PWM_PAD_OE_N_BIT5			34
> +#define GPO_PWM_PAD_OE_N_BIT6			35
> +#define GPO_PWM_PAD_OE_N_BIT7			36
> +#define GPO_PWM_PAD_OUT_BIT0			37
> +#define GPO_PWM_PAD_OUT_BIT1			38
> +#define GPO_PWM_PAD_OUT_BIT2			39
> +#define GPO_PWM_PAD_OUT_BIT3			40
> +#define GPO_PWM_PAD_OUT_BIT4			41
> +#define GPO_PWM_PAD_OUT_BIT5			42
> +#define GPO_PWM_PAD_OUT_BIT6			43
> +#define GPO_PWM_PAD_OUT_BIT7			44
> +#define GPO_PWMDAC_LEFT_OUT			45
> +#define GPO_PWMDAC_RIGHT_OUT			46
> +#define GPO_QSPI_CSN1_OUT			47
> +#define GPO_QSPI_CSN2_OUT			48
> +#define GPO_QSPI_CSN3_OUT			49
> +#define GPO_REGISTER23_SCFG_CMSENSOR_RST0	50
> +#define GPO_REGISTER23_SCFG_CMSENSOR_RST1	51
> +#define GPO_REGISTER32_SCFG_GMAC_PHY_RSTN	52
> +#define GPO_SDIO0_PAD_CARD_POWER_EN		53
> +#define GPO_SDIO0_PAD_CCLK_OUT			54
> +#define GPO_SDIO0_PAD_CCMD_OE			55
> +#define GPO_SDIO0_PAD_CCMD_OEN			(GPO_SDIO0_PAD_CCMD_OE | GPO_REVERSE)
> +#define GPO_SDIO0_PAD_CCMD_OUT			56
> +#define GPO_SDIO0_PAD_CDATA_OE_BIT0		57
> +#define GPO_SDIO0_PAD_CDATA_OEN_BIT0		(GPO_SDIO0_PAD_CDATA_OE_BIT0 | GPO_REVERSE)
> +#define GPO_SDIO0_PAD_CDATA_OE_BIT1		58
> +#define GPO_SDIO0_PAD_CDATA_OEN_BIT1		(GPO_SDIO0_PAD_CDATA_OE_BIT1 | GPO_REVERSE)
> +#define GPO_SDIO0_PAD_CDATA_OE_BIT2		59
> +#define GPO_SDIO0_PAD_CDATA_OEN_BIT2		(GPO_SDIO0_PAD_CDATA_OE_BIT2 | GPO_REVERSE)
> +#define GPO_SDIO0_PAD_CDATA_OE_BIT3		60
> +#define GPO_SDIO0_PAD_CDATA_OEN_BIT3		(GPO_SDIO0_PAD_CDATA_OE_BIT3 | GPO_REVERSE)
> +#define GPO_SDIO0_PAD_CDATA_OE_BIT4		61
> +#define GPO_SDIO0_PAD_CDATA_OEN_BIT4		(GPO_SDIO0_PAD_CDATA_OE_BIT4 | GPO_REVERSE)
> +#define GPO_SDIO0_PAD_CDATA_OE_BIT5		62
> +#define GPO_SDIO0_PAD_CDATA_OEN_BIT5		(GPO_SDIO0_PAD_CDATA_OE_BIT5 | GPO_REVERSE)
> +#define GPO_SDIO0_PAD_CDATA_OE_BIT6		63
> +#define GPO_SDIO0_PAD_CDATA_OEN_BIT6		(GPO_SDIO0_PAD_CDATA_OE_BIT6 | GPO_REVERSE)
> +#define GPO_SDIO0_PAD_CDATA_OE_BIT7		64
> +#define GPO_SDIO0_PAD_CDATA_OEN_BIT7		(GPO_SDIO0_PAD_CDATA_OE_BIT7 | GPO_REVERSE)
> +#define GPO_SDIO0_PAD_CDATA_OUT_BIT0		65
> +#define GPO_SDIO0_PAD_CDATA_OUT_BIT1		66
> +#define GPO_SDIO0_PAD_CDATA_OUT_BIT2		67
> +#define GPO_SDIO0_PAD_CDATA_OUT_BIT3		68
> +#define GPO_SDIO0_PAD_CDATA_OUT_BIT4		69
> +#define GPO_SDIO0_PAD_CDATA_OUT_BIT5		70
> +#define GPO_SDIO0_PAD_CDATA_OUT_BIT6		71
> +#define GPO_SDIO0_PAD_CDATA_OUT_BIT7		72
> +#define GPO_SDIO0_PAD_RST_N			73
> +#define GPO_SDIO1_PAD_CARD_POWER_EN		74
> +#define GPO_SDIO1_PAD_CCLK_OUT			75
> +#define GPO_SDIO1_PAD_CCMD_OE			76
> +#define GPO_SDIO1_PAD_CCMD_OEN			(GPO_SDIO1_PAD_CCMD_OE | GPO_REVERSE)
> +#define GPO_SDIO1_PAD_CCMD_OUT			77
> +#define GPO_SDIO1_PAD_CDATA_OE_BIT0		78
> +#define GPO_SDIO1_PAD_CDATA_OEN_BIT0		(GPO_SDIO1_PAD_CDATA_OE_BIT0 | GPO_REVERSE)
> +#define GPO_SDIO1_PAD_CDATA_OE_BIT1		79
> +#define GPO_SDIO1_PAD_CDATA_OEN_BIT1		(GPO_SDIO1_PAD_CDATA_OE_BIT1 | GPO_REVERSE)
> +#define GPO_SDIO1_PAD_CDATA_OE_BIT2		80
> +#define GPO_SDIO1_PAD_CDATA_OEN_BIT2		(GPO_SDIO1_PAD_CDATA_OE_BIT2 | GPO_REVERSE)
> +#define GPO_SDIO1_PAD_CDATA_OE_BIT3		81
> +#define GPO_SDIO1_PAD_CDATA_OEN_BIT3		(GPO_SDIO1_PAD_CDATA_OE_BIT3 | GPO_REVERSE)
> +#define GPO_SDIO1_PAD_CDATA_OE_BIT4		82
> +#define GPO_SDIO1_PAD_CDATA_OEN_BIT4		(GPO_SDIO1_PAD_CDATA_OE_BIT4 | GPO_REVERSE)
> +#define GPO_SDIO1_PAD_CDATA_OE_BIT5		83
> +#define GPO_SDIO1_PAD_CDATA_OEN_BIT5		(GPO_SDIO1_PAD_CDATA_OE_BIT5 | GPO_REVERSE)
> +#define GPO_SDIO1_PAD_CDATA_OE_BIT6		84
> +#define GPO_SDIO1_PAD_CDATA_OEN_BIT6		(GPO_SDIO1_PAD_CDATA_OE_BIT6 | GPO_REVERSE)
> +#define GPO_SDIO1_PAD_CDATA_OE_BIT7		85
> +#define GPO_SDIO1_PAD_CDATA_OEN_BIT7		(GPO_SDIO1_PAD_CDATA_OE_BIT7 | GPO_REVERSE)
> +#define GPO_SDIO1_PAD_CDATA_OUT_BIT0		86
> +#define GPO_SDIO1_PAD_CDATA_OUT_BIT1		87
> +#define GPO_SDIO1_PAD_CDATA_OUT_BIT2		88
> +#define GPO_SDIO1_PAD_CDATA_OUT_BIT3		89
> +#define GPO_SDIO1_PAD_CDATA_OUT_BIT4		90
> +#define GPO_SDIO1_PAD_CDATA_OUT_BIT5		91
> +#define GPO_SDIO1_PAD_CDATA_OUT_BIT6		92
> +#define GPO_SDIO1_PAD_CDATA_OUT_BIT7		93
> +#define GPO_SDIO1_PAD_RST_N			94
> +#define GPO_SPDIF_TX_SDOUT			95
> +#define GPO_SPDIF_TX_SDOUT_OEN			96
> +#define GPO_SPI0_PAD_OE_N			97
> +#define GPO_SPI0_PAD_SCK_OUT			98
> +#define GPO_SPI0_PAD_SS_0_N			99
> +#define GPO_SPI0_PAD_SS_1_N			100
> +#define GPO_SPI0_PAD_TXD			101
> +#define GPO_SPI1_PAD_OE_N			102
> +#define GPO_SPI1_PAD_SCK_OUT			103
> +#define GPO_SPI1_PAD_SS_0_N			104
> +#define GPO_SPI1_PAD_SS_1_N			105
> +#define GPO_SPI1_PAD_TXD			106
> +#define GPO_SPI2_PAD_OE_N			107
> +#define GPO_SPI2_PAD_SCK_OUT			108
> +#define GPO_SPI2_PAD_SS_0_N			109
> +#define GPO_SPI2_PAD_SS_1_N			110
> +#define GPO_SPI2_PAD_TXD			111
> +#define GPO_SPI2AHB_PAD_OE_N_BIT0		112
> +#define GPO_SPI2AHB_PAD_OE_N_BIT1		113
> +#define GPO_SPI2AHB_PAD_OE_N_BIT2		114
> +#define GPO_SPI2AHB_PAD_OE_N_BIT3		115
> +#define GPO_SPI2AHB_PAD_TXD_BIT0		116
> +#define GPO_SPI2AHB_PAD_TXD_BIT1		117
> +#define GPO_SPI2AHB_PAD_TXD_BIT2		118
> +#define GPO_SPI2AHB_PAD_TXD_BIT3		119
> +#define GPO_SPI3_PAD_OE_N			120
> +#define GPO_SPI3_PAD_SCK_OUT			121
> +#define GPO_SPI3_PAD_SS_0_N			122
> +#define GPO_SPI3_PAD_SS_1_N			123
> +#define GPO_SPI3_PAD_TXD			124
> +#define GPO_UART0_PAD_DTRN			125
> +#define GPO_UART0_PAD_RTSN			126
> +#define GPO_UART0_PAD_SOUT			127
> +#define GPO_UART1_PAD_SOUT			128
> +#define GPO_UART2_PAD_DTR_N			129
> +#define GPO_UART2_PAD_RTS_N			130
> +#define GPO_UART2_PAD_SOUT			131
> +#define GPO_UART3_PAD_SOUT			132
> +#define GPO_USB_DRV_BUS				133
> +
> +#define GPI_CPU_JTAG_TCK			0
> +#define GPI_CPU_JTAG_TDI			1
> +#define GPI_CPU_JTAG_TMS			2
> +#define GPI_CPU_JTAG_TRST			3
> +#define GPI_DMIC_SDIN_BIT0			4
> +#define GPI_DMIC_SDIN_BIT1			5
> +#define GPI_DSP_JTCK_PAD			6
> +#define GPI_DSP_JTDI_PAD			7
> +#define GPI_DSP_JTMS_PAD			8
> +#define GPI_DSP_TRST_PAD			9
> +#define GPI_I2C0_PAD_SCK_IN			10
> +#define GPI_I2C0_PAD_SDA_IN			11
> +#define GPI_I2C1_PAD_SCK_IN			12
> +#define GPI_I2C1_PAD_SDA_IN			13
> +#define GPI_I2C2_PAD_SCK_IN			14
> +#define GPI_I2C2_PAD_SDA_IN			15
> +#define GPI_I2C3_PAD_SCK_IN			16
> +#define GPI_I2C3_PAD_SDA_IN			17
> +#define GPI_I2SRX_BCLK_IN			18
> +#define GPI_I2SRX_LRCK_IN			19
> +#define GPI_I2SRX_SDIN_BIT0			20
> +#define GPI_I2SRX_SDIN_BIT1			21
> +#define GPI_I2SRX_SDIN_BIT2			22
> +#define GPI_I2STX_BCLK_IN			23
> +#define GPI_I2STX_LRCK_IN			24
> +#define GPI_SDIO0_PAD_CARD_DETECT_N		25
> +#define GPI_SDIO0_PAD_CARD_WRITE_PRT		26
> +#define GPI_SDIO0_PAD_CCMD_IN			27
> +#define GPI_SDIO0_PAD_CDATA_IN_BIT0		28
> +#define GPI_SDIO0_PAD_CDATA_IN_BIT1		29
> +#define GPI_SDIO0_PAD_CDATA_IN_BIT2		30
> +#define GPI_SDIO0_PAD_CDATA_IN_BIT3		31
> +#define GPI_SDIO0_PAD_CDATA_IN_BIT4		32
> +#define GPI_SDIO0_PAD_CDATA_IN_BIT5		33
> +#define GPI_SDIO0_PAD_CDATA_IN_BIT6		34
> +#define GPI_SDIO0_PAD_CDATA_IN_BIT7		35
> +#define GPI_SDIO1_PAD_CARD_DETECT_N		36
> +#define GPI_SDIO1_PAD_CARD_WRITE_PRT		37
> +#define GPI_SDIO1_PAD_CCMD_IN			38
> +#define GPI_SDIO1_PAD_CDATA_IN_BIT0		39
> +#define GPI_SDIO1_PAD_CDATA_IN_BIT1		40
> +#define GPI_SDIO1_PAD_CDATA_IN_BIT2		41
> +#define GPI_SDIO1_PAD_CDATA_IN_BIT3		42
> +#define GPI_SDIO1_PAD_CDATA_IN_BIT4		43
> +#define GPI_SDIO1_PAD_CDATA_IN_BIT5		44
> +#define GPI_SDIO1_PAD_CDATA_IN_BIT6		45
> +#define GPI_SDIO1_PAD_CDATA_IN_BIT7		46
> +#define GPI_SPDIF_RX_SDIN			47
> +#define GPI_SPI0_PAD_RXD			48
> +#define GPI_SPI0_PAD_SS_IN_N			49
> +#define GPI_SPI1_PAD_RXD			50
> +#define GPI_SPI1_PAD_SS_IN_N			51
> +#define GPI_SPI2_PAD_RXD			52
> +#define GPI_SPI2_PAD_SS_IN_N			53
> +#define GPI_SPI2AHB_PAD_RXD_BIT0		54
> +#define GPI_SPI2AHB_PAD_RXD_BIT1		55
> +#define GPI_SPI2AHB_PAD_RXD_BIT2		56
> +#define GPI_SPI2AHB_PAD_RXD_BIT3		57
> +#define GPI_SPI2AHB_PAD_SS_N			58
> +#define GPI_SPI2AHB_SLV_SCLKIN			59
> +#define GPI_SPI3_PAD_RXD			60
> +#define GPI_SPI3_PAD_SS_IN_N			61
> +#define GPI_UART0_PAD_CTSN			62
> +#define GPI_UART0_PAD_DCDN			63
> +#define GPI_UART0_PAD_DSRN			64
> +#define GPI_UART0_PAD_RIN			65
> +#define GPI_UART0_PAD_SIN			66
> +#define GPI_UART1_PAD_SIN			67
> +#define GPI_UART2_PAD_CTS_N			68
> +#define GPI_UART2_PAD_DCD_N			69
> +#define GPI_UART2_PAD_DSR_N			70
> +#define GPI_UART2_PAD_RI_N			71
> +#define GPI_UART2_PAD_SIN			72
> +#define GPI_UART3_PAD_SIN			73
> +#define GPI_USB_OVER_CURRENT			74
> +
> +#define GPI_NONE				0xff
> +
> +#endif
> -- 
> 2.33.1
> 
> 

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 10/16] dt-bindings: pinctrl: Add StarFive pinctrl definitions
@ 2021-10-29  1:44     ` Rob Herring
  0 siblings, 0 replies; 143+ messages in thread
From: Rob Herring @ 2021-10-29  1:44 UTC (permalink / raw)
  To: Emil Renner Berthing
  Cc: linux-riscv, devicetree, linux-clk, linux-gpio, linux-serial,
	Palmer Dabbelt, Paul Walmsley, Michael Turquette, Stephen Boyd,
	Thomas Gleixner, Marc Zyngier, Philipp Zabel, Linus Walleij,
	Greg Kroah-Hartman, Daniel Lezcano, Andy Shevchenko, Jiri Slaby,
	Maximilian Luz, Sagar Kadam, Drew Fustini, Geert Uytterhoeven,
	Michael Zhu, Fu Wei, Anup Patel, Atish Patra, Matteo Croce,
	linux-kernel

On Thu, Oct 21, 2021 at 07:42:17PM +0200, Emil Renner Berthing wrote:
> Add definitons for pins and GPIO input, output and output enable
> signals on the StarFive JH7100 SoC.
> 
> Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
> ---
>  .../dt-bindings/pinctrl/pinctrl-starfive.h    | 274 ++++++++++++++++++
>  1 file changed, 274 insertions(+)
>  create mode 100644 include/dt-bindings/pinctrl/pinctrl-starfive.h
> 
> diff --git a/include/dt-bindings/pinctrl/pinctrl-starfive.h b/include/dt-bindings/pinctrl/pinctrl-starfive.h
> new file mode 100644
> index 000000000000..f9b6caa83558
> --- /dev/null
> +++ b/include/dt-bindings/pinctrl/pinctrl-starfive.h
> @@ -0,0 +1,274 @@
> +/* SPDX-License-Identifier: GPL-2.0 */

Not consistent with other headers.

All the headers and dts files should have the same licenses.

> +/*
> + * Copyright (c) 2021 Emil Renner Berthing <kernel@esmil.dk>
> + */
> +#ifndef _DT_BINDINGS_PINCTRL_STARFIVE_H
> +#define _DT_BINDINGS_PINCTRL_STARFIVE_H
> +
> +#define PAD_GPIO_OFFSET		0
> +#define PAD_FUNC_SHARE_OFFSET	64
> +#define PAD_GPIO(x)		(PAD_GPIO_OFFSET + (x))
> +#define PAD_FUNC_SHARE(x)	(PAD_FUNC_SHARE_OFFSET + (x))
> +
> +/*
> + * GPIOMUX bits:
> + *  | 31 - 24 | 23 - 16 | 15 - 8 |     7    |     6    |  5 - 0  |
> + *  |  dout   |  doen   |  din   | dout rev | doen rev | gpio nr |
> + *
> + * dout:     output signal
> + * doen:     output enable signal
> + * din:      optional input signal, 0xff = none
> + * dout rev: output signal reverse bit
> + * doen rev: output enable signal reverse bit
> + * gpio nr:  gpio number, 0 - 63
> + */
> +#define GPIOMUX(n, dout, doen, din) ( \
> +		(((dout) & 0x80000000) >> (31 - 7)) | (((dout) & 0xff) << 24) | \
> +		(((doen) & 0x80000000) >> (31 - 6)) | (((doen) & 0xff) << 16) | \
> +		(((din) & 0xff) << 8) | \
> +		((n) & 0x3f))
> +
> +#define GPO_REVERSE				0x80000000
> +
> +#define GPO_LOW					0
> +#define GPO_HIGH				1
> +#define GPO_ENABLE				0
> +#define GPO_DISABLE				1
> +#define GPO_CLK_GMAC_PAPHYREF			2
> +#define GPO_JTAG_TDO				3
> +#define GPO_JTAG_TDO_OEN			4
> +#define GPO_DMIC_CLK_OUT			5
> +#define GPO_DSP_JTDOEN_PAD			6
> +#define GPO_DSP_JTDO_PAD			7
> +#define GPO_I2C0_PAD_SCK_OE			8
> +#define GPO_I2C0_PAD_SCK_OEN			(GPO_I2C0_PAD_SCK_OE | GPO_REVERSE)
> +#define GPO_I2C0_PAD_SDA_OE			9
> +#define GPO_I2C0_PAD_SDA_OEN			(GPO_I2C0_PAD_SDA_OE | GPO_REVERSE)
> +#define GPO_I2C1_PAD_SCK_OE			10
> +#define GPO_I2C1_PAD_SCK_OEN			(GPO_I2C1_PAD_SCK_OE | GPO_REVERSE)
> +#define GPO_I2C1_PAD_SDA_OE			11
> +#define GPO_I2C1_PAD_SDA_OEN			(GPO_I2C1_PAD_SDA_OE | GPO_REVERSE)
> +#define GPO_I2C2_PAD_SCK_OE			12
> +#define GPO_I2C2_PAD_SCK_OEN			(GPO_I2C2_PAD_SCK_OE | GPO_REVERSE)
> +#define GPO_I2C2_PAD_SDA_OE			13
> +#define GPO_I2C2_PAD_SDA_OEN			(GPO_I2C2_PAD_SDA_OE | GPO_REVERSE)
> +#define GPO_I2C3_PAD_SCK_OE			14
> +#define GPO_I2C3_PAD_SCK_OEN			(GPO_I2C3_PAD_SCK_OE | GPO_REVERSE)
> +#define GPO_I2C3_PAD_SDA_OE			15
> +#define GPO_I2C3_PAD_SDA_OEN			(GPO_I2C3_PAD_SDA_OE | GPO_REVERSE)
> +#define GPO_I2SRX_BCLK_OUT			16
> +#define GPO_I2SRX_BCLK_OUT_OEN			17
> +#define GPO_I2SRX_LRCK_OUT			18
> +#define GPO_I2SRX_LRCK_OUT_OEN			19
> +#define GPO_I2SRX_MCLK_OUT			20
> +#define GPO_I2STX_BCLK_OUT			21
> +#define GPO_I2STX_BCLK_OUT_OEN			22
> +#define GPO_I2STX_LRCK_OUT			23
> +#define GPO_I2STX_LRCK_OUT_OEN			24
> +#define GPO_I2STX_MCLK_OUT			25
> +#define GPO_I2STX_SDOUT0			26
> +#define GPO_I2STX_SDOUT1			27
> +#define GPO_LCD_PAD_CSM_N			28
> +#define GPO_PWM_PAD_OE_N_BIT0			29
> +#define GPO_PWM_PAD_OE_N_BIT1			30
> +#define GPO_PWM_PAD_OE_N_BIT2			31
> +#define GPO_PWM_PAD_OE_N_BIT3			32
> +#define GPO_PWM_PAD_OE_N_BIT4			33
> +#define GPO_PWM_PAD_OE_N_BIT5			34
> +#define GPO_PWM_PAD_OE_N_BIT6			35
> +#define GPO_PWM_PAD_OE_N_BIT7			36
> +#define GPO_PWM_PAD_OUT_BIT0			37
> +#define GPO_PWM_PAD_OUT_BIT1			38
> +#define GPO_PWM_PAD_OUT_BIT2			39
> +#define GPO_PWM_PAD_OUT_BIT3			40
> +#define GPO_PWM_PAD_OUT_BIT4			41
> +#define GPO_PWM_PAD_OUT_BIT5			42
> +#define GPO_PWM_PAD_OUT_BIT6			43
> +#define GPO_PWM_PAD_OUT_BIT7			44
> +#define GPO_PWMDAC_LEFT_OUT			45
> +#define GPO_PWMDAC_RIGHT_OUT			46
> +#define GPO_QSPI_CSN1_OUT			47
> +#define GPO_QSPI_CSN2_OUT			48
> +#define GPO_QSPI_CSN3_OUT			49
> +#define GPO_REGISTER23_SCFG_CMSENSOR_RST0	50
> +#define GPO_REGISTER23_SCFG_CMSENSOR_RST1	51
> +#define GPO_REGISTER32_SCFG_GMAC_PHY_RSTN	52
> +#define GPO_SDIO0_PAD_CARD_POWER_EN		53
> +#define GPO_SDIO0_PAD_CCLK_OUT			54
> +#define GPO_SDIO0_PAD_CCMD_OE			55
> +#define GPO_SDIO0_PAD_CCMD_OEN			(GPO_SDIO0_PAD_CCMD_OE | GPO_REVERSE)
> +#define GPO_SDIO0_PAD_CCMD_OUT			56
> +#define GPO_SDIO0_PAD_CDATA_OE_BIT0		57
> +#define GPO_SDIO0_PAD_CDATA_OEN_BIT0		(GPO_SDIO0_PAD_CDATA_OE_BIT0 | GPO_REVERSE)
> +#define GPO_SDIO0_PAD_CDATA_OE_BIT1		58
> +#define GPO_SDIO0_PAD_CDATA_OEN_BIT1		(GPO_SDIO0_PAD_CDATA_OE_BIT1 | GPO_REVERSE)
> +#define GPO_SDIO0_PAD_CDATA_OE_BIT2		59
> +#define GPO_SDIO0_PAD_CDATA_OEN_BIT2		(GPO_SDIO0_PAD_CDATA_OE_BIT2 | GPO_REVERSE)
> +#define GPO_SDIO0_PAD_CDATA_OE_BIT3		60
> +#define GPO_SDIO0_PAD_CDATA_OEN_BIT3		(GPO_SDIO0_PAD_CDATA_OE_BIT3 | GPO_REVERSE)
> +#define GPO_SDIO0_PAD_CDATA_OE_BIT4		61
> +#define GPO_SDIO0_PAD_CDATA_OEN_BIT4		(GPO_SDIO0_PAD_CDATA_OE_BIT4 | GPO_REVERSE)
> +#define GPO_SDIO0_PAD_CDATA_OE_BIT5		62
> +#define GPO_SDIO0_PAD_CDATA_OEN_BIT5		(GPO_SDIO0_PAD_CDATA_OE_BIT5 | GPO_REVERSE)
> +#define GPO_SDIO0_PAD_CDATA_OE_BIT6		63
> +#define GPO_SDIO0_PAD_CDATA_OEN_BIT6		(GPO_SDIO0_PAD_CDATA_OE_BIT6 | GPO_REVERSE)
> +#define GPO_SDIO0_PAD_CDATA_OE_BIT7		64
> +#define GPO_SDIO0_PAD_CDATA_OEN_BIT7		(GPO_SDIO0_PAD_CDATA_OE_BIT7 | GPO_REVERSE)
> +#define GPO_SDIO0_PAD_CDATA_OUT_BIT0		65
> +#define GPO_SDIO0_PAD_CDATA_OUT_BIT1		66
> +#define GPO_SDIO0_PAD_CDATA_OUT_BIT2		67
> +#define GPO_SDIO0_PAD_CDATA_OUT_BIT3		68
> +#define GPO_SDIO0_PAD_CDATA_OUT_BIT4		69
> +#define GPO_SDIO0_PAD_CDATA_OUT_BIT5		70
> +#define GPO_SDIO0_PAD_CDATA_OUT_BIT6		71
> +#define GPO_SDIO0_PAD_CDATA_OUT_BIT7		72
> +#define GPO_SDIO0_PAD_RST_N			73
> +#define GPO_SDIO1_PAD_CARD_POWER_EN		74
> +#define GPO_SDIO1_PAD_CCLK_OUT			75
> +#define GPO_SDIO1_PAD_CCMD_OE			76
> +#define GPO_SDIO1_PAD_CCMD_OEN			(GPO_SDIO1_PAD_CCMD_OE | GPO_REVERSE)
> +#define GPO_SDIO1_PAD_CCMD_OUT			77
> +#define GPO_SDIO1_PAD_CDATA_OE_BIT0		78
> +#define GPO_SDIO1_PAD_CDATA_OEN_BIT0		(GPO_SDIO1_PAD_CDATA_OE_BIT0 | GPO_REVERSE)
> +#define GPO_SDIO1_PAD_CDATA_OE_BIT1		79
> +#define GPO_SDIO1_PAD_CDATA_OEN_BIT1		(GPO_SDIO1_PAD_CDATA_OE_BIT1 | GPO_REVERSE)
> +#define GPO_SDIO1_PAD_CDATA_OE_BIT2		80
> +#define GPO_SDIO1_PAD_CDATA_OEN_BIT2		(GPO_SDIO1_PAD_CDATA_OE_BIT2 | GPO_REVERSE)
> +#define GPO_SDIO1_PAD_CDATA_OE_BIT3		81
> +#define GPO_SDIO1_PAD_CDATA_OEN_BIT3		(GPO_SDIO1_PAD_CDATA_OE_BIT3 | GPO_REVERSE)
> +#define GPO_SDIO1_PAD_CDATA_OE_BIT4		82
> +#define GPO_SDIO1_PAD_CDATA_OEN_BIT4		(GPO_SDIO1_PAD_CDATA_OE_BIT4 | GPO_REVERSE)
> +#define GPO_SDIO1_PAD_CDATA_OE_BIT5		83
> +#define GPO_SDIO1_PAD_CDATA_OEN_BIT5		(GPO_SDIO1_PAD_CDATA_OE_BIT5 | GPO_REVERSE)
> +#define GPO_SDIO1_PAD_CDATA_OE_BIT6		84
> +#define GPO_SDIO1_PAD_CDATA_OEN_BIT6		(GPO_SDIO1_PAD_CDATA_OE_BIT6 | GPO_REVERSE)
> +#define GPO_SDIO1_PAD_CDATA_OE_BIT7		85
> +#define GPO_SDIO1_PAD_CDATA_OEN_BIT7		(GPO_SDIO1_PAD_CDATA_OE_BIT7 | GPO_REVERSE)
> +#define GPO_SDIO1_PAD_CDATA_OUT_BIT0		86
> +#define GPO_SDIO1_PAD_CDATA_OUT_BIT1		87
> +#define GPO_SDIO1_PAD_CDATA_OUT_BIT2		88
> +#define GPO_SDIO1_PAD_CDATA_OUT_BIT3		89
> +#define GPO_SDIO1_PAD_CDATA_OUT_BIT4		90
> +#define GPO_SDIO1_PAD_CDATA_OUT_BIT5		91
> +#define GPO_SDIO1_PAD_CDATA_OUT_BIT6		92
> +#define GPO_SDIO1_PAD_CDATA_OUT_BIT7		93
> +#define GPO_SDIO1_PAD_RST_N			94
> +#define GPO_SPDIF_TX_SDOUT			95
> +#define GPO_SPDIF_TX_SDOUT_OEN			96
> +#define GPO_SPI0_PAD_OE_N			97
> +#define GPO_SPI0_PAD_SCK_OUT			98
> +#define GPO_SPI0_PAD_SS_0_N			99
> +#define GPO_SPI0_PAD_SS_1_N			100
> +#define GPO_SPI0_PAD_TXD			101
> +#define GPO_SPI1_PAD_OE_N			102
> +#define GPO_SPI1_PAD_SCK_OUT			103
> +#define GPO_SPI1_PAD_SS_0_N			104
> +#define GPO_SPI1_PAD_SS_1_N			105
> +#define GPO_SPI1_PAD_TXD			106
> +#define GPO_SPI2_PAD_OE_N			107
> +#define GPO_SPI2_PAD_SCK_OUT			108
> +#define GPO_SPI2_PAD_SS_0_N			109
> +#define GPO_SPI2_PAD_SS_1_N			110
> +#define GPO_SPI2_PAD_TXD			111
> +#define GPO_SPI2AHB_PAD_OE_N_BIT0		112
> +#define GPO_SPI2AHB_PAD_OE_N_BIT1		113
> +#define GPO_SPI2AHB_PAD_OE_N_BIT2		114
> +#define GPO_SPI2AHB_PAD_OE_N_BIT3		115
> +#define GPO_SPI2AHB_PAD_TXD_BIT0		116
> +#define GPO_SPI2AHB_PAD_TXD_BIT1		117
> +#define GPO_SPI2AHB_PAD_TXD_BIT2		118
> +#define GPO_SPI2AHB_PAD_TXD_BIT3		119
> +#define GPO_SPI3_PAD_OE_N			120
> +#define GPO_SPI3_PAD_SCK_OUT			121
> +#define GPO_SPI3_PAD_SS_0_N			122
> +#define GPO_SPI3_PAD_SS_1_N			123
> +#define GPO_SPI3_PAD_TXD			124
> +#define GPO_UART0_PAD_DTRN			125
> +#define GPO_UART0_PAD_RTSN			126
> +#define GPO_UART0_PAD_SOUT			127
> +#define GPO_UART1_PAD_SOUT			128
> +#define GPO_UART2_PAD_DTR_N			129
> +#define GPO_UART2_PAD_RTS_N			130
> +#define GPO_UART2_PAD_SOUT			131
> +#define GPO_UART3_PAD_SOUT			132
> +#define GPO_USB_DRV_BUS				133
> +
> +#define GPI_CPU_JTAG_TCK			0
> +#define GPI_CPU_JTAG_TDI			1
> +#define GPI_CPU_JTAG_TMS			2
> +#define GPI_CPU_JTAG_TRST			3
> +#define GPI_DMIC_SDIN_BIT0			4
> +#define GPI_DMIC_SDIN_BIT1			5
> +#define GPI_DSP_JTCK_PAD			6
> +#define GPI_DSP_JTDI_PAD			7
> +#define GPI_DSP_JTMS_PAD			8
> +#define GPI_DSP_TRST_PAD			9
> +#define GPI_I2C0_PAD_SCK_IN			10
> +#define GPI_I2C0_PAD_SDA_IN			11
> +#define GPI_I2C1_PAD_SCK_IN			12
> +#define GPI_I2C1_PAD_SDA_IN			13
> +#define GPI_I2C2_PAD_SCK_IN			14
> +#define GPI_I2C2_PAD_SDA_IN			15
> +#define GPI_I2C3_PAD_SCK_IN			16
> +#define GPI_I2C3_PAD_SDA_IN			17
> +#define GPI_I2SRX_BCLK_IN			18
> +#define GPI_I2SRX_LRCK_IN			19
> +#define GPI_I2SRX_SDIN_BIT0			20
> +#define GPI_I2SRX_SDIN_BIT1			21
> +#define GPI_I2SRX_SDIN_BIT2			22
> +#define GPI_I2STX_BCLK_IN			23
> +#define GPI_I2STX_LRCK_IN			24
> +#define GPI_SDIO0_PAD_CARD_DETECT_N		25
> +#define GPI_SDIO0_PAD_CARD_WRITE_PRT		26
> +#define GPI_SDIO0_PAD_CCMD_IN			27
> +#define GPI_SDIO0_PAD_CDATA_IN_BIT0		28
> +#define GPI_SDIO0_PAD_CDATA_IN_BIT1		29
> +#define GPI_SDIO0_PAD_CDATA_IN_BIT2		30
> +#define GPI_SDIO0_PAD_CDATA_IN_BIT3		31
> +#define GPI_SDIO0_PAD_CDATA_IN_BIT4		32
> +#define GPI_SDIO0_PAD_CDATA_IN_BIT5		33
> +#define GPI_SDIO0_PAD_CDATA_IN_BIT6		34
> +#define GPI_SDIO0_PAD_CDATA_IN_BIT7		35
> +#define GPI_SDIO1_PAD_CARD_DETECT_N		36
> +#define GPI_SDIO1_PAD_CARD_WRITE_PRT		37
> +#define GPI_SDIO1_PAD_CCMD_IN			38
> +#define GPI_SDIO1_PAD_CDATA_IN_BIT0		39
> +#define GPI_SDIO1_PAD_CDATA_IN_BIT1		40
> +#define GPI_SDIO1_PAD_CDATA_IN_BIT2		41
> +#define GPI_SDIO1_PAD_CDATA_IN_BIT3		42
> +#define GPI_SDIO1_PAD_CDATA_IN_BIT4		43
> +#define GPI_SDIO1_PAD_CDATA_IN_BIT5		44
> +#define GPI_SDIO1_PAD_CDATA_IN_BIT6		45
> +#define GPI_SDIO1_PAD_CDATA_IN_BIT7		46
> +#define GPI_SPDIF_RX_SDIN			47
> +#define GPI_SPI0_PAD_RXD			48
> +#define GPI_SPI0_PAD_SS_IN_N			49
> +#define GPI_SPI1_PAD_RXD			50
> +#define GPI_SPI1_PAD_SS_IN_N			51
> +#define GPI_SPI2_PAD_RXD			52
> +#define GPI_SPI2_PAD_SS_IN_N			53
> +#define GPI_SPI2AHB_PAD_RXD_BIT0		54
> +#define GPI_SPI2AHB_PAD_RXD_BIT1		55
> +#define GPI_SPI2AHB_PAD_RXD_BIT2		56
> +#define GPI_SPI2AHB_PAD_RXD_BIT3		57
> +#define GPI_SPI2AHB_PAD_SS_N			58
> +#define GPI_SPI2AHB_SLV_SCLKIN			59
> +#define GPI_SPI3_PAD_RXD			60
> +#define GPI_SPI3_PAD_SS_IN_N			61
> +#define GPI_UART0_PAD_CTSN			62
> +#define GPI_UART0_PAD_DCDN			63
> +#define GPI_UART0_PAD_DSRN			64
> +#define GPI_UART0_PAD_RIN			65
> +#define GPI_UART0_PAD_SIN			66
> +#define GPI_UART1_PAD_SIN			67
> +#define GPI_UART2_PAD_CTS_N			68
> +#define GPI_UART2_PAD_DCD_N			69
> +#define GPI_UART2_PAD_DSR_N			70
> +#define GPI_UART2_PAD_RI_N			71
> +#define GPI_UART2_PAD_SIN			72
> +#define GPI_UART3_PAD_SIN			73
> +#define GPI_USB_OVER_CURRENT			74
> +
> +#define GPI_NONE				0xff
> +
> +#endif
> -- 
> 2.33.1
> 
> 

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 11/16] dt-bindings: pinctrl: Add StarFive JH7100 bindings
  2021-10-21 17:42   ` Emil Renner Berthing
@ 2021-10-29  1:50     ` Rob Herring
  -1 siblings, 0 replies; 143+ messages in thread
From: Rob Herring @ 2021-10-29  1:50 UTC (permalink / raw)
  To: Emil Renner Berthing
  Cc: linux-riscv, devicetree, linux-clk, linux-gpio, linux-serial,
	Palmer Dabbelt, Paul Walmsley, Michael Turquette, Stephen Boyd,
	Thomas Gleixner, Marc Zyngier, Philipp Zabel, Linus Walleij,
	Greg Kroah-Hartman, Daniel Lezcano, Andy Shevchenko, Jiri Slaby,
	Maximilian Luz, Sagar Kadam, Drew Fustini, Geert Uytterhoeven,
	Michael Zhu, Fu Wei, Anup Patel, Atish Patra, Matteo Croce,
	linux-kernel

On Thu, Oct 21, 2021 at 07:42:18PM +0200, Emil Renner Berthing wrote:
> Add bindings for the StarFive JH7100 GPIO/pin controller.
> 
> Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
> ---
>  .../pinctrl/starfive,jh7100-pinctrl.yaml      | 274 ++++++++++++++++++
>  1 file changed, 274 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/pinctrl/starfive,jh7100-pinctrl.yaml
> 
> diff --git a/Documentation/devicetree/bindings/pinctrl/starfive,jh7100-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/starfive,jh7100-pinctrl.yaml
> new file mode 100644
> index 000000000000..342ecd91a3b0
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/pinctrl/starfive,jh7100-pinctrl.yaml
> @@ -0,0 +1,274 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/pinctrl/starfive,jh7100-pinctrl.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: StarFive JH7100 Pin Controller Device Tree Bindings
> +
> +maintainers:
> +  - Emil Renner Berthing <kernel@esmil.dk>
> +  - Drew Fustini <drew@beagleboard.org>
> +
> +properties:
> +  compatible:
> +    const: starfive,jh7100-pinctrl
> +
> +  reg:
> +    minItems: 2
> +    maxItems: 2
> +
> +  reg-names:
> +    items:
> +      - const: "gpio"
> +      - const: "padctl"

Don't need quotes.

> +
> +  clocks:
> +    maxItems: 1
> +
> +  resets:
> +    maxItems: 1
> +
> +  gpio-controller: true
> +
> +  "#gpio-cells":
> +    const: 2
> +    description: |
> +      Number of cells in GPIO specifier. Since the generic GPIO
> +      binding is used, the amount of cells must be specified as 2.
> +
> +  interrupts:
> +    maxItems: 1
> +    description: The GPIO parent interrupt.
> +
> +  interrupt-controller: true
> +
> +  "#interrupt-cells":
> +    const: 2
> +
> +  starfive,signal-group:
> +    description: |
> +      The SoC has a global setting selecting one of 7 different pinmux
> +      configurations of the pads named GPIO[0:63] and FUNC_SHARE[0:141]. After
> +      this global setting is chosen only the 64 "GPIO" pins can be further
> +      muxed by configuring them to be controlled by certain peripherals rather
> +      than software.
> +      Note that in configuration 0 none of GPIOs are routed to pads, and only
> +      in configuration 1 are the GPIOs routed to the pads named GPIO[0:63].
> +      If this property is not set it defaults to the configuration already
> +      chosen by the earlier boot stages.
> +    $ref: /schemas/types.yaml#/definitions/uint32
> +    enum: [0, 1, 2, 3, 4, 5, 6]
> +
> +required:
> +  - compatible
> +  - reg
> +  - reg-names
> +  - clocks
> +  - gpio-controller
> +  - "#gpio-cells"
> +  - interrupts
> +  - interrupt-controller
> +  - "#interrupt-cells"
> +
> +patternProperties:
> +  '-[0-9]*$':

Can you make this more specific. As-is, '-' and 'foo-' are valid.

> +    type: object
> +    patternProperties:
> +      '-pins*$':

So foo-pinsssssss is okay? Drop the '*' or use ? if you intend to 
support 'foo-pin'.

> +        type: object
> +        description: |
> +          A pinctrl node should contain at least one subnode representing the
> +          pinctrl groups available on the machine. Each subnode will list the
> +          pins it needs, and how they should be configured, with regard to
> +          muxer configuration, bias, input enable/disable, input schmitt
> +          trigger enable/disable, slew-rate and drive strength.
> +        $ref: "/schemas/pinctrl/pincfg-node.yaml"
> +
> +        properties:
> +          pins:
> +            description: |
> +              The list of pin identifiers that properties in the node apply to.
> +              This should be set using either the PAD_GPIO or PAD_FUNC_SHARE
> +              macro. Either this or "pinmux" has to be specified.
> +
> +          pinmux:
> +            description: |
> +              The list of GPIO identifiers and their mux settings that
> +              properties in the node apply to. This should be set using the
> +              GPIOMUX macro. Either this or "pins" has to be specified.
> +
> +          bias-disable: true
> +
> +          bias-pull-up:
> +            type: boolean

Already has a type. Need to reference the common schema.

> +
> +          bias-pull-down:
> +            type: boolean
> +
> +          drive-strength:
> +            enum: [ 14, 21, 28, 35, 42, 49, 56, 63 ]
> +
> +          input-enable: true
> +
> +          input-disable: true
> +
> +          input-schmitt-enable: true
> +
> +          input-schmitt-disable: true
> +
> +          slew-rate:
> +            maximum: 7
> +
> +          starfive,strong-pull-up:
> +            description: enable strong pull-up.
> +            type: boolean
> +
> +        additionalProperties: false
> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +    #include <dt-bindings/clock/starfive-jh7100.h>
> +    #include <dt-bindings/reset/starfive-jh7100.h>
> +    #include <dt-bindings/pinctrl/pinctrl-starfive.h>
> +
> +    soc {
> +        #address-cells = <2>;
> +        #size-cells = <2>;
> +
> +        gpio: pinctrl@11910000 {
> +            compatible = "starfive,jh7100-pinctrl";
> +            reg = <0x0 0x11910000 0x0 0x10000>,
> +                  <0x0 0x11858000 0x0 0x1000>;
> +            reg-names = "gpio", "padctl";
> +            clocks = <&clkgen JH7100_CLK_GPIO_APB>;
> +            resets = <&clkgen JH7100_RSTN_GPIO_APB>;
> +            interrupts = <32>;
> +            gpio-controller;
> +            #gpio-cells = <2>;
> +            interrupt-controller;
> +            #interrupt-cells = <2>;
> +            starfive,signal-group = <6>;
> +
> +            gmac_pins_default: gmac-0 {
> +                gtxclk-pins {
> +                    pins = <PAD_FUNC_SHARE(115)>;
> +                    bias-pull-up;
> +                    drive-strength = <35>;
> +                    input-enable;
> +                    input-schmitt-enable;
> +                    slew-rate = <0>;
> +                };
> +                miitxclk-pins {
> +                    pins = <PAD_FUNC_SHARE(116)>;
> +                    bias-pull-up;
> +                    drive-strength = <14>;
> +                    input-enable;
> +                    input-schmitt-disable;
> +                    slew-rate = <0>;
> +                };
> +                tx-pins {
> +                    pins = <PAD_FUNC_SHARE(117)>,
> +                           <PAD_FUNC_SHARE(119)>,
> +                           <PAD_FUNC_SHARE(120)>,
> +                           <PAD_FUNC_SHARE(121)>,
> +                           <PAD_FUNC_SHARE(122)>,
> +                           <PAD_FUNC_SHARE(123)>,
> +                           <PAD_FUNC_SHARE(124)>,
> +                           <PAD_FUNC_SHARE(125)>,
> +                           <PAD_FUNC_SHARE(126)>;
> +                    bias-disable;
> +                    drive-strength = <35>;
> +                    input-disable;
> +                    input-schmitt-disable;
> +                    slew-rate = <0>;
> +                };
> +                rxclk-pins {
> +                    pins = <PAD_FUNC_SHARE(127)>;
> +                    bias-pull-up;
> +                    drive-strength = <14>;
> +                    input-enable;
> +                    input-schmitt-disable;
> +                    slew-rate = <6>;
> +                };
> +                rxer-pins {
> +                    pins = <PAD_FUNC_SHARE(129)>;
> +                    bias-pull-up;
> +                    drive-strength = <14>;
> +                    input-enable;
> +                    input-schmitt-disable;
> +                    slew-rate = <0>;
> +                };
> +                rx-pins {
> +                    pins = <PAD_FUNC_SHARE(128)>,
> +                           <PAD_FUNC_SHARE(130)>,
> +                           <PAD_FUNC_SHARE(131)>,
> +                           <PAD_FUNC_SHARE(132)>,
> +                           <PAD_FUNC_SHARE(133)>,
> +                           <PAD_FUNC_SHARE(134)>,
> +                           <PAD_FUNC_SHARE(135)>,
> +                           <PAD_FUNC_SHARE(136)>,
> +                           <PAD_FUNC_SHARE(137)>,
> +                           <PAD_FUNC_SHARE(138)>,
> +                           <PAD_FUNC_SHARE(139)>,
> +                           <PAD_FUNC_SHARE(140)>,
> +                           <PAD_FUNC_SHARE(141)>;
> +                    bias-pull-up;
> +                    drive-strength = <14>;
> +                    input-enable;
> +                    input-schmitt-enable;
> +                    slew-rate = <0>;
> +                };
> +            };
> +
> +            i2c0_pins_default: i2c0-0 {
> +                i2c-pins {
> +                    pinmux = <GPIOMUX(62, GPO_LOW,
> +                              GPO_I2C0_PAD_SCK_OEN,
> +                              GPI_I2C0_PAD_SCK_IN)>,
> +                             <GPIOMUX(61, GPO_LOW,
> +                              GPO_I2C0_PAD_SDA_OEN,
> +                              GPI_I2C0_PAD_SDA_IN)>;
> +                    bias-disable; /* external pull-up */
> +                    input-enable;
> +                    input-schmitt-enable;
> +                };
> +            };
> +
> +            uart3_pins_default: uart3-0 {
> +                rx-pin {
> +                    pinmux = <GPIOMUX(13, GPO_LOW, GPO_DISABLE,
> +                              GPI_UART3_PAD_SIN)>;
> +                    bias-pull-up;
> +                    input-enable;
> +                    input-schmitt-enable;
> +                };
> +                tx-pin {
> +                    pinmux = <GPIOMUX(14, GPO_UART3_PAD_SOUT,
> +                              GPO_ENABLE, GPI_NONE)>;
> +                    bias-disable;
> +                    input-disable;
> +                    input-schmitt-disable;
> +                };
> +            };
> +        };
> +
> +        gmac {
> +            pinctrl-0 = <&gmac_pins_default>;
> +            pinctrl-names = "default";
> +        };
> +
> +        i2c0 {
> +            pinctrl-0 = <&i2c0_pins_default>;
> +            pinctrl-names = "default";
> +        };
> +
> +        uart3 {
> +            pinctrl-0 = <&uart3_pins_default>;
> +            pinctrl-names = "default";
> +        };
> +    };
> +
> +...
> -- 
> 2.33.1
> 
> 

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 11/16] dt-bindings: pinctrl: Add StarFive JH7100 bindings
@ 2021-10-29  1:50     ` Rob Herring
  0 siblings, 0 replies; 143+ messages in thread
From: Rob Herring @ 2021-10-29  1:50 UTC (permalink / raw)
  To: Emil Renner Berthing
  Cc: linux-riscv, devicetree, linux-clk, linux-gpio, linux-serial,
	Palmer Dabbelt, Paul Walmsley, Michael Turquette, Stephen Boyd,
	Thomas Gleixner, Marc Zyngier, Philipp Zabel, Linus Walleij,
	Greg Kroah-Hartman, Daniel Lezcano, Andy Shevchenko, Jiri Slaby,
	Maximilian Luz, Sagar Kadam, Drew Fustini, Geert Uytterhoeven,
	Michael Zhu, Fu Wei, Anup Patel, Atish Patra, Matteo Croce,
	linux-kernel

On Thu, Oct 21, 2021 at 07:42:18PM +0200, Emil Renner Berthing wrote:
> Add bindings for the StarFive JH7100 GPIO/pin controller.
> 
> Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
> ---
>  .../pinctrl/starfive,jh7100-pinctrl.yaml      | 274 ++++++++++++++++++
>  1 file changed, 274 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/pinctrl/starfive,jh7100-pinctrl.yaml
> 
> diff --git a/Documentation/devicetree/bindings/pinctrl/starfive,jh7100-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/starfive,jh7100-pinctrl.yaml
> new file mode 100644
> index 000000000000..342ecd91a3b0
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/pinctrl/starfive,jh7100-pinctrl.yaml
> @@ -0,0 +1,274 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/pinctrl/starfive,jh7100-pinctrl.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: StarFive JH7100 Pin Controller Device Tree Bindings
> +
> +maintainers:
> +  - Emil Renner Berthing <kernel@esmil.dk>
> +  - Drew Fustini <drew@beagleboard.org>
> +
> +properties:
> +  compatible:
> +    const: starfive,jh7100-pinctrl
> +
> +  reg:
> +    minItems: 2
> +    maxItems: 2
> +
> +  reg-names:
> +    items:
> +      - const: "gpio"
> +      - const: "padctl"

Don't need quotes.

> +
> +  clocks:
> +    maxItems: 1
> +
> +  resets:
> +    maxItems: 1
> +
> +  gpio-controller: true
> +
> +  "#gpio-cells":
> +    const: 2
> +    description: |
> +      Number of cells in GPIO specifier. Since the generic GPIO
> +      binding is used, the amount of cells must be specified as 2.
> +
> +  interrupts:
> +    maxItems: 1
> +    description: The GPIO parent interrupt.
> +
> +  interrupt-controller: true
> +
> +  "#interrupt-cells":
> +    const: 2
> +
> +  starfive,signal-group:
> +    description: |
> +      The SoC has a global setting selecting one of 7 different pinmux
> +      configurations of the pads named GPIO[0:63] and FUNC_SHARE[0:141]. After
> +      this global setting is chosen only the 64 "GPIO" pins can be further
> +      muxed by configuring them to be controlled by certain peripherals rather
> +      than software.
> +      Note that in configuration 0 none of GPIOs are routed to pads, and only
> +      in configuration 1 are the GPIOs routed to the pads named GPIO[0:63].
> +      If this property is not set it defaults to the configuration already
> +      chosen by the earlier boot stages.
> +    $ref: /schemas/types.yaml#/definitions/uint32
> +    enum: [0, 1, 2, 3, 4, 5, 6]
> +
> +required:
> +  - compatible
> +  - reg
> +  - reg-names
> +  - clocks
> +  - gpio-controller
> +  - "#gpio-cells"
> +  - interrupts
> +  - interrupt-controller
> +  - "#interrupt-cells"
> +
> +patternProperties:
> +  '-[0-9]*$':

Can you make this more specific. As-is, '-' and 'foo-' are valid.

> +    type: object
> +    patternProperties:
> +      '-pins*$':

So foo-pinsssssss is okay? Drop the '*' or use ? if you intend to 
support 'foo-pin'.

> +        type: object
> +        description: |
> +          A pinctrl node should contain at least one subnode representing the
> +          pinctrl groups available on the machine. Each subnode will list the
> +          pins it needs, and how they should be configured, with regard to
> +          muxer configuration, bias, input enable/disable, input schmitt
> +          trigger enable/disable, slew-rate and drive strength.
> +        $ref: "/schemas/pinctrl/pincfg-node.yaml"
> +
> +        properties:
> +          pins:
> +            description: |
> +              The list of pin identifiers that properties in the node apply to.
> +              This should be set using either the PAD_GPIO or PAD_FUNC_SHARE
> +              macro. Either this or "pinmux" has to be specified.
> +
> +          pinmux:
> +            description: |
> +              The list of GPIO identifiers and their mux settings that
> +              properties in the node apply to. This should be set using the
> +              GPIOMUX macro. Either this or "pins" has to be specified.
> +
> +          bias-disable: true
> +
> +          bias-pull-up:
> +            type: boolean

Already has a type. Need to reference the common schema.

> +
> +          bias-pull-down:
> +            type: boolean
> +
> +          drive-strength:
> +            enum: [ 14, 21, 28, 35, 42, 49, 56, 63 ]
> +
> +          input-enable: true
> +
> +          input-disable: true
> +
> +          input-schmitt-enable: true
> +
> +          input-schmitt-disable: true
> +
> +          slew-rate:
> +            maximum: 7
> +
> +          starfive,strong-pull-up:
> +            description: enable strong pull-up.
> +            type: boolean
> +
> +        additionalProperties: false
> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +    #include <dt-bindings/clock/starfive-jh7100.h>
> +    #include <dt-bindings/reset/starfive-jh7100.h>
> +    #include <dt-bindings/pinctrl/pinctrl-starfive.h>
> +
> +    soc {
> +        #address-cells = <2>;
> +        #size-cells = <2>;
> +
> +        gpio: pinctrl@11910000 {
> +            compatible = "starfive,jh7100-pinctrl";
> +            reg = <0x0 0x11910000 0x0 0x10000>,
> +                  <0x0 0x11858000 0x0 0x1000>;
> +            reg-names = "gpio", "padctl";
> +            clocks = <&clkgen JH7100_CLK_GPIO_APB>;
> +            resets = <&clkgen JH7100_RSTN_GPIO_APB>;
> +            interrupts = <32>;
> +            gpio-controller;
> +            #gpio-cells = <2>;
> +            interrupt-controller;
> +            #interrupt-cells = <2>;
> +            starfive,signal-group = <6>;
> +
> +            gmac_pins_default: gmac-0 {
> +                gtxclk-pins {
> +                    pins = <PAD_FUNC_SHARE(115)>;
> +                    bias-pull-up;
> +                    drive-strength = <35>;
> +                    input-enable;
> +                    input-schmitt-enable;
> +                    slew-rate = <0>;
> +                };
> +                miitxclk-pins {
> +                    pins = <PAD_FUNC_SHARE(116)>;
> +                    bias-pull-up;
> +                    drive-strength = <14>;
> +                    input-enable;
> +                    input-schmitt-disable;
> +                    slew-rate = <0>;
> +                };
> +                tx-pins {
> +                    pins = <PAD_FUNC_SHARE(117)>,
> +                           <PAD_FUNC_SHARE(119)>,
> +                           <PAD_FUNC_SHARE(120)>,
> +                           <PAD_FUNC_SHARE(121)>,
> +                           <PAD_FUNC_SHARE(122)>,
> +                           <PAD_FUNC_SHARE(123)>,
> +                           <PAD_FUNC_SHARE(124)>,
> +                           <PAD_FUNC_SHARE(125)>,
> +                           <PAD_FUNC_SHARE(126)>;
> +                    bias-disable;
> +                    drive-strength = <35>;
> +                    input-disable;
> +                    input-schmitt-disable;
> +                    slew-rate = <0>;
> +                };
> +                rxclk-pins {
> +                    pins = <PAD_FUNC_SHARE(127)>;
> +                    bias-pull-up;
> +                    drive-strength = <14>;
> +                    input-enable;
> +                    input-schmitt-disable;
> +                    slew-rate = <6>;
> +                };
> +                rxer-pins {
> +                    pins = <PAD_FUNC_SHARE(129)>;
> +                    bias-pull-up;
> +                    drive-strength = <14>;
> +                    input-enable;
> +                    input-schmitt-disable;
> +                    slew-rate = <0>;
> +                };
> +                rx-pins {
> +                    pins = <PAD_FUNC_SHARE(128)>,
> +                           <PAD_FUNC_SHARE(130)>,
> +                           <PAD_FUNC_SHARE(131)>,
> +                           <PAD_FUNC_SHARE(132)>,
> +                           <PAD_FUNC_SHARE(133)>,
> +                           <PAD_FUNC_SHARE(134)>,
> +                           <PAD_FUNC_SHARE(135)>,
> +                           <PAD_FUNC_SHARE(136)>,
> +                           <PAD_FUNC_SHARE(137)>,
> +                           <PAD_FUNC_SHARE(138)>,
> +                           <PAD_FUNC_SHARE(139)>,
> +                           <PAD_FUNC_SHARE(140)>,
> +                           <PAD_FUNC_SHARE(141)>;
> +                    bias-pull-up;
> +                    drive-strength = <14>;
> +                    input-enable;
> +                    input-schmitt-enable;
> +                    slew-rate = <0>;
> +                };
> +            };
> +
> +            i2c0_pins_default: i2c0-0 {
> +                i2c-pins {
> +                    pinmux = <GPIOMUX(62, GPO_LOW,
> +                              GPO_I2C0_PAD_SCK_OEN,
> +                              GPI_I2C0_PAD_SCK_IN)>,
> +                             <GPIOMUX(61, GPO_LOW,
> +                              GPO_I2C0_PAD_SDA_OEN,
> +                              GPI_I2C0_PAD_SDA_IN)>;
> +                    bias-disable; /* external pull-up */
> +                    input-enable;
> +                    input-schmitt-enable;
> +                };
> +            };
> +
> +            uart3_pins_default: uart3-0 {
> +                rx-pin {
> +                    pinmux = <GPIOMUX(13, GPO_LOW, GPO_DISABLE,
> +                              GPI_UART3_PAD_SIN)>;
> +                    bias-pull-up;
> +                    input-enable;
> +                    input-schmitt-enable;
> +                };
> +                tx-pin {
> +                    pinmux = <GPIOMUX(14, GPO_UART3_PAD_SOUT,
> +                              GPO_ENABLE, GPI_NONE)>;
> +                    bias-disable;
> +                    input-disable;
> +                    input-schmitt-disable;
> +                };
> +            };
> +        };
> +
> +        gmac {
> +            pinctrl-0 = <&gmac_pins_default>;
> +            pinctrl-names = "default";
> +        };
> +
> +        i2c0 {
> +            pinctrl-0 = <&i2c0_pins_default>;
> +            pinctrl-names = "default";
> +        };
> +
> +        uart3 {
> +            pinctrl-0 = <&uart3_pins_default>;
> +            pinctrl-names = "default";
> +        };
> +    };
> +
> +...
> -- 
> 2.33.1
> 
> 

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 13/16] dt-bindings: serial: snps-dw-apb-uart: Add JH7100 uarts
  2021-10-21 17:42   ` Emil Renner Berthing
@ 2021-10-29  1:50     ` Rob Herring
  -1 siblings, 0 replies; 143+ messages in thread
From: Rob Herring @ 2021-10-29  1:50 UTC (permalink / raw)
  To: Emil Renner Berthing
  Cc: linux-riscv, Daniel Lezcano, devicetree, Michael Zhu,
	Stephen Boyd, linux-gpio, Michael Turquette, Fu Wei,
	Philipp Zabel, Thomas Gleixner, Geert Uytterhoeven, Atish Patra,
	Rob Herring, Sagar Kadam, linux-serial, linux-clk, Linus Walleij,
	Greg Kroah-Hartman, Marc Zyngier, Palmer Dabbelt, Paul Walmsley,
	linux-kernel, Maximilian Luz, Andy Shevchenko, Anup Patel,
	Jiri Slaby, Drew Fustini, Matteo Croce

On Thu, 21 Oct 2021 19:42:20 +0200, Emil Renner Berthing wrote:
> Add compatibles for the StarFive JH7100 uarts.
> 
> Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
> Reviewed-by: Geert Uytterhoeven <geert@linux-m68k.org>
> ---
>  .../devicetree/bindings/serial/snps-dw-apb-uart.yaml         | 5 +++++
>  1 file changed, 5 insertions(+)
> 

Acked-by: Rob Herring <robh@kernel.org>

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 13/16] dt-bindings: serial: snps-dw-apb-uart: Add JH7100 uarts
@ 2021-10-29  1:50     ` Rob Herring
  0 siblings, 0 replies; 143+ messages in thread
From: Rob Herring @ 2021-10-29  1:50 UTC (permalink / raw)
  To: Emil Renner Berthing
  Cc: linux-riscv, Daniel Lezcano, devicetree, Michael Zhu,
	Stephen Boyd, linux-gpio, Michael Turquette, Fu Wei,
	Philipp Zabel, Thomas Gleixner, Geert Uytterhoeven, Atish Patra,
	Rob Herring, Sagar Kadam, linux-serial, linux-clk, Linus Walleij,
	Greg Kroah-Hartman, Marc Zyngier, Palmer Dabbelt, Paul Walmsley,
	linux-kernel, Maximilian Luz, Andy Shevchenko, Anup Patel,
	Jiri Slaby, Drew Fustini, Matteo Croce

On Thu, 21 Oct 2021 19:42:20 +0200, Emil Renner Berthing wrote:
> Add compatibles for the StarFive JH7100 uarts.
> 
> Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
> Reviewed-by: Geert Uytterhoeven <geert@linux-m68k.org>
> ---
>  .../devicetree/bindings/serial/snps-dw-apb-uart.yaml         | 5 +++++
>  1 file changed, 5 insertions(+)
> 

Acked-by: Rob Herring <robh@kernel.org>

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 11/16] dt-bindings: pinctrl: Add StarFive JH7100 bindings
  2021-10-29  1:50     ` Rob Herring
@ 2021-10-29 13:00       ` Emil Renner Berthing
  -1 siblings, 0 replies; 143+ messages in thread
From: Emil Renner Berthing @ 2021-10-29 13:00 UTC (permalink / raw)
  To: Rob Herring
  Cc: linux-riscv,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	linux-clk, open list:GPIO SUBSYSTEM, open list:SERIAL DRIVERS,
	Palmer Dabbelt, Paul Walmsley, Michael Turquette, Stephen Boyd,
	Thomas Gleixner, Marc Zyngier, Philipp Zabel, Linus Walleij,
	Greg Kroah-Hartman, Daniel Lezcano, Andy Shevchenko, Jiri Slaby,
	Maximilian Luz, Sagar Kadam, Drew Fustini, Geert Uytterhoeven,
	Michael Zhu, Fu Wei, Anup Patel, Atish Patra, Matteo Croce,
	Linux Kernel Mailing List

On Fri, 29 Oct 2021 at 03:50, Rob Herring <robh@kernel.org> wrote:
> On Thu, Oct 21, 2021 at 07:42:18PM +0200, Emil Renner Berthing wrote:
> > +patternProperties:
> > +  '-[0-9]*$':
>
> Can you make this more specific. As-is, '-' and 'foo-' are valid.
>
> > +    type: object
> > +    patternProperties:
> > +      '-pins*$':
>
> So foo-pinsssssss is okay? Drop the '*' or use ? if you intend to
> support 'foo-pin'.

Ah, thanks. Both this and the pattern above was taken from
pinctrl/mediatek,mt6779-pinctrl.yaml if anyone feels like fixing that
too. I see now that '-[0-9]+$' and '-pins$' is more common. I'll just
use that.

> > +        type: object
> > +        description: |
> > +          A pinctrl node should contain at least one subnode representing the
> > +          pinctrl groups available on the machine. Each subnode will list the
> > +          pins it needs, and how they should be configured, with regard to
> > +          muxer configuration, bias, input enable/disable, input schmitt
> > +          trigger enable/disable, slew-rate and drive strength.
> > +        $ref: "/schemas/pinctrl/pincfg-node.yaml"
> > +
> > +        properties:
> > +          pins:
> > +            description: |
> > +              The list of pin identifiers that properties in the node apply to.
> > +              This should be set using either the PAD_GPIO or PAD_FUNC_SHARE
> > +              macro. Either this or "pinmux" has to be specified.
> > +
> > +          pinmux:
> > +            description: |
> > +              The list of GPIO identifiers and their mux settings that
> > +              properties in the node apply to. This should be set using the
> > +              GPIOMUX macro. Either this or "pins" has to be specified.
> > +
> > +          bias-disable: true
> > +
> > +          bias-pull-up:
> > +            type: boolean
>
> Already has a type. Need to reference the common schema.

Right, but the common schema specifies one of boolean or uint32. Is
there a way to reference that, but still say that this binding
supports only the boolean version?

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 11/16] dt-bindings: pinctrl: Add StarFive JH7100 bindings
@ 2021-10-29 13:00       ` Emil Renner Berthing
  0 siblings, 0 replies; 143+ messages in thread
From: Emil Renner Berthing @ 2021-10-29 13:00 UTC (permalink / raw)
  To: Rob Herring
  Cc: linux-riscv,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	linux-clk, open list:GPIO SUBSYSTEM, open list:SERIAL DRIVERS,
	Palmer Dabbelt, Paul Walmsley, Michael Turquette, Stephen Boyd,
	Thomas Gleixner, Marc Zyngier, Philipp Zabel, Linus Walleij,
	Greg Kroah-Hartman, Daniel Lezcano, Andy Shevchenko, Jiri Slaby,
	Maximilian Luz, Sagar Kadam, Drew Fustini, Geert Uytterhoeven,
	Michael Zhu, Fu Wei, Anup Patel, Atish Patra, Matteo Croce,
	Linux Kernel Mailing List

On Fri, 29 Oct 2021 at 03:50, Rob Herring <robh@kernel.org> wrote:
> On Thu, Oct 21, 2021 at 07:42:18PM +0200, Emil Renner Berthing wrote:
> > +patternProperties:
> > +  '-[0-9]*$':
>
> Can you make this more specific. As-is, '-' and 'foo-' are valid.
>
> > +    type: object
> > +    patternProperties:
> > +      '-pins*$':
>
> So foo-pinsssssss is okay? Drop the '*' or use ? if you intend to
> support 'foo-pin'.

Ah, thanks. Both this and the pattern above was taken from
pinctrl/mediatek,mt6779-pinctrl.yaml if anyone feels like fixing that
too. I see now that '-[0-9]+$' and '-pins$' is more common. I'll just
use that.

> > +        type: object
> > +        description: |
> > +          A pinctrl node should contain at least one subnode representing the
> > +          pinctrl groups available on the machine. Each subnode will list the
> > +          pins it needs, and how they should be configured, with regard to
> > +          muxer configuration, bias, input enable/disable, input schmitt
> > +          trigger enable/disable, slew-rate and drive strength.
> > +        $ref: "/schemas/pinctrl/pincfg-node.yaml"
> > +
> > +        properties:
> > +          pins:
> > +            description: |
> > +              The list of pin identifiers that properties in the node apply to.
> > +              This should be set using either the PAD_GPIO or PAD_FUNC_SHARE
> > +              macro. Either this or "pinmux" has to be specified.
> > +
> > +          pinmux:
> > +            description: |
> > +              The list of GPIO identifiers and their mux settings that
> > +              properties in the node apply to. This should be set using the
> > +              GPIOMUX macro. Either this or "pins" has to be specified.
> > +
> > +          bias-disable: true
> > +
> > +          bias-pull-up:
> > +            type: boolean
>
> Already has a type. Need to reference the common schema.

Right, but the common schema specifies one of boolean or uint32. Is
there a way to reference that, but still say that this binding
supports only the boolean version?

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 05/16] dt-bindings: clock: starfive: Add JH7100 bindings
  2021-10-29  1:42     ` Rob Herring
@ 2021-10-29 13:05       ` Emil Renner Berthing
  -1 siblings, 0 replies; 143+ messages in thread
From: Emil Renner Berthing @ 2021-10-29 13:05 UTC (permalink / raw)
  To: Rob Herring
  Cc: open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	linux-clk, open list:SERIAL DRIVERS, Philipp Zabel,
	Maximilian Luz, Drew Fustini, Atish Patra, Rob Herring,
	linux-riscv, Palmer Dabbelt, Michael Zhu, Daniel Lezcano,
	open list:GPIO SUBSYSTEM, Sagar Kadam, Matteo Croce,
	Marc Zyngier, Linus Walleij, Greg Kroah-Hartman, Andy Shevchenko,
	Michael Turquette, Anup Patel, Stephen Boyd, Thomas Gleixner,
	Linux Kernel Mailing List, Geert Uytterhoeven, Paul Walmsley,
	Fu Wei, Jiri Slaby

On Fri, 29 Oct 2021 at 03:42, Rob Herring <robh@kernel.org> wrote:
> On Thu, 21 Oct 2021 19:42:12 +0200, Emil Renner Berthing wrote:
> > From: Geert Uytterhoeven <geert@linux-m68k.org>
> >
> > Add device tree bindings for the StarFive JH7100 clock generator.
> >
> > Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
> > Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
> > ---
> >  .../clock/starfive,jh7100-clkgen.yaml         | 56 +++++++++++++++++++
> >  1 file changed, 56 insertions(+)
> >  create mode 100644 Documentation/devicetree/bindings/clock/starfive,jh7100-clkgen.yaml
> >
>
> Reviewed-by: Rob Herring <robh@kernel.org>

Thank you! For the reset bindings you said to remove unused labels in
the example. If you don't mind I'll do that here too, but keep the
tag.

/Emil

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 05/16] dt-bindings: clock: starfive: Add JH7100 bindings
@ 2021-10-29 13:05       ` Emil Renner Berthing
  0 siblings, 0 replies; 143+ messages in thread
From: Emil Renner Berthing @ 2021-10-29 13:05 UTC (permalink / raw)
  To: Rob Herring
  Cc: open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	linux-clk, open list:SERIAL DRIVERS, Philipp Zabel,
	Maximilian Luz, Drew Fustini, Atish Patra, Rob Herring,
	linux-riscv, Palmer Dabbelt, Michael Zhu, Daniel Lezcano,
	open list:GPIO SUBSYSTEM, Sagar Kadam, Matteo Croce,
	Marc Zyngier, Linus Walleij, Greg Kroah-Hartman, Andy Shevchenko,
	Michael Turquette, Anup Patel, Stephen Boyd, Thomas Gleixner,
	Linux Kernel Mailing List, Geert Uytterhoeven, Paul Walmsley,
	Fu Wei, Jiri Slaby

On Fri, 29 Oct 2021 at 03:42, Rob Herring <robh@kernel.org> wrote:
> On Thu, 21 Oct 2021 19:42:12 +0200, Emil Renner Berthing wrote:
> > From: Geert Uytterhoeven <geert@linux-m68k.org>
> >
> > Add device tree bindings for the StarFive JH7100 clock generator.
> >
> > Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
> > Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
> > ---
> >  .../clock/starfive,jh7100-clkgen.yaml         | 56 +++++++++++++++++++
> >  1 file changed, 56 insertions(+)
> >  create mode 100644 Documentation/devicetree/bindings/clock/starfive,jh7100-clkgen.yaml
> >
>
> Reviewed-by: Rob Herring <robh@kernel.org>

Thank you! For the reset bindings you said to remove unused labels in
the example. If you don't mind I'll do that here too, but keep the
tag.

/Emil

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 11/16] dt-bindings: pinctrl: Add StarFive JH7100 bindings
  2021-10-29 13:00       ` Emil Renner Berthing
@ 2021-10-29 14:44         ` Rob Herring
  -1 siblings, 0 replies; 143+ messages in thread
From: Rob Herring @ 2021-10-29 14:44 UTC (permalink / raw)
  To: Emil Renner Berthing
  Cc: linux-riscv,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	linux-clk, open list:GPIO SUBSYSTEM, open list:SERIAL DRIVERS,
	Palmer Dabbelt, Paul Walmsley, Michael Turquette, Stephen Boyd,
	Thomas Gleixner, Marc Zyngier, Philipp Zabel, Linus Walleij,
	Greg Kroah-Hartman, Daniel Lezcano, Andy Shevchenko, Jiri Slaby,
	Maximilian Luz, Sagar Kadam, Drew Fustini, Geert Uytterhoeven,
	Michael Zhu, Fu Wei, Anup Patel, Atish Patra, Matteo Croce,
	Linux Kernel Mailing List

On Fri, Oct 29, 2021 at 8:00 AM Emil Renner Berthing <kernel@esmil.dk> wrote:
>
> On Fri, 29 Oct 2021 at 03:50, Rob Herring <robh@kernel.org> wrote:
> > On Thu, Oct 21, 2021 at 07:42:18PM +0200, Emil Renner Berthing wrote:
> > > +patternProperties:
> > > +  '-[0-9]*$':
> >
> > Can you make this more specific. As-is, '-' and 'foo-' are valid.
> >
> > > +    type: object
> > > +    patternProperties:
> > > +      '-pins*$':
> >
> > So foo-pinsssssss is okay? Drop the '*' or use ? if you intend to
> > support 'foo-pin'.
>
> Ah, thanks. Both this and the pattern above was taken from
> pinctrl/mediatek,mt6779-pinctrl.yaml if anyone feels like fixing that
> too. I see now that '-[0-9]+$' and '-pins$' is more common. I'll just
> use that.
>
> > > +        type: object
> > > +        description: |
> > > +          A pinctrl node should contain at least one subnode representing the
> > > +          pinctrl groups available on the machine. Each subnode will list the
> > > +          pins it needs, and how they should be configured, with regard to
> > > +          muxer configuration, bias, input enable/disable, input schmitt
> > > +          trigger enable/disable, slew-rate and drive strength.
> > > +        $ref: "/schemas/pinctrl/pincfg-node.yaml"
> > > +
> > > +        properties:
> > > +          pins:
> > > +            description: |
> > > +              The list of pin identifiers that properties in the node apply to.
> > > +              This should be set using either the PAD_GPIO or PAD_FUNC_SHARE
> > > +              macro. Either this or "pinmux" has to be specified.
> > > +
> > > +          pinmux:
> > > +            description: |
> > > +              The list of GPIO identifiers and their mux settings that
> > > +              properties in the node apply to. This should be set using the
> > > +              GPIOMUX macro. Either this or "pins" has to be specified.
> > > +
> > > +          bias-disable: true
> > > +
> > > +          bias-pull-up:
> > > +            type: boolean
> >
> > Already has a type. Need to reference the common schema.
>
> Right, but the common schema specifies one of boolean or uint32. Is
> there a way to reference that, but still say that this binding
> supports only the boolean version?

Okay, then keep this.

Rob

^ permalink raw reply	[flat|nested] 143+ messages in thread

* Re: [PATCH v2 11/16] dt-bindings: pinctrl: Add StarFive JH7100 bindings
@ 2021-10-29 14:44         ` Rob Herring
  0 siblings, 0 replies; 143+ messages in thread
From: Rob Herring @ 2021-10-29 14:44 UTC (permalink / raw)
  To: Emil Renner Berthing
  Cc: linux-riscv,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	linux-clk, open list:GPIO SUBSYSTEM, open list:SERIAL DRIVERS,
	Palmer Dabbelt, Paul Walmsley, Michael Turquette, Stephen Boyd,
	Thomas Gleixner, Marc Zyngier, Philipp Zabel, Linus Walleij,
	Greg Kroah-Hartman, Daniel Lezcano, Andy Shevchenko, Jiri Slaby,
	Maximilian Luz, Sagar Kadam, Drew Fustini, Geert Uytterhoeven,
	Michael Zhu, Fu Wei, Anup Patel, Atish Patra, Matteo Croce,
	Linux Kernel Mailing List

On Fri, Oct 29, 2021 at 8:00 AM Emil Renner Berthing <kernel@esmil.dk> wrote:
>
> On Fri, 29 Oct 2021 at 03:50, Rob Herring <robh@kernel.org> wrote:
> > On Thu, Oct 21, 2021 at 07:42:18PM +0200, Emil Renner Berthing wrote:
> > > +patternProperties:
> > > +  '-[0-9]*$':
> >
> > Can you make this more specific. As-is, '-' and 'foo-' are valid.
> >
> > > +    type: object
> > > +    patternProperties:
> > > +      '-pins*$':
> >
> > So foo-pinsssssss is okay? Drop the '*' or use ? if you intend to
> > support 'foo-pin'.
>
> Ah, thanks. Both this and the pattern above was taken from
> pinctrl/mediatek,mt6779-pinctrl.yaml if anyone feels like fixing that
> too. I see now that '-[0-9]+$' and '-pins$' is more common. I'll just
> use that.
>
> > > +        type: object
> > > +        description: |
> > > +          A pinctrl node should contain at least one subnode representing the
> > > +          pinctrl groups available on the machine. Each subnode will list the
> > > +          pins it needs, and how they should be configured, with regard to
> > > +          muxer configuration, bias, input enable/disable, input schmitt
> > > +          trigger enable/disable, slew-rate and drive strength.
> > > +        $ref: "/schemas/pinctrl/pincfg-node.yaml"
> > > +
> > > +        properties:
> > > +          pins:
> > > +            description: |
> > > +              The list of pin identifiers that properties in the node apply to.
> > > +              This should be set using either the PAD_GPIO or PAD_FUNC_SHARE
> > > +              macro. Either this or "pinmux" has to be specified.
> > > +
> > > +          pinmux:
> > > +            description: |
> > > +              The list of GPIO identifiers and their mux settings that
> > > +              properties in the node apply to. This should be set using the
> > > +              GPIOMUX macro. Either this or "pins" has to be specified.
> > > +
> > > +          bias-disable: true
> > > +
> > > +          bias-pull-up:
> > > +            type: boolean
> >
> > Already has a type. Need to reference the common schema.
>
> Right, but the common schema specifies one of boolean or uint32. Is
> there a way to reference that, but still say that this binding
> supports only the boolean version?

Okay, then keep this.

Rob

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 143+ messages in thread

end of thread, other threads:[~2021-10-29 14:45 UTC | newest]

Thread overview: 143+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-10-21 17:42 [PATCH v2 00/16] Basic StarFive JH7100 RISC-V SoC support Emil Renner Berthing
2021-10-21 17:42 ` Emil Renner Berthing
2021-10-21 17:42 ` [PATCH v2 01/16] RISC-V: Add StarFive SoC Kconfig option Emil Renner Berthing
2021-10-21 17:42   ` Emil Renner Berthing
2021-10-22  8:50   ` Andy Shevchenko
2021-10-22  8:50     ` Andy Shevchenko
2021-10-22  9:40     ` Emil Renner Berthing
2021-10-22  9:40       ` Emil Renner Berthing
2021-10-22 12:40       ` Andy Shevchenko
2021-10-22 12:40         ` Andy Shevchenko
2021-10-21 17:42 ` [PATCH v2 02/16] dt-bindings: timer: Add StarFive JH7100 clint Emil Renner Berthing
2021-10-21 17:42   ` Emil Renner Berthing
2021-10-21 17:42 ` [PATCH v2 03/16] dt-bindings: interrupt-controller: Add StarFive JH7100 plic Emil Renner Berthing
2021-10-21 17:42   ` Emil Renner Berthing
2021-10-29  1:37   ` Rob Herring
2021-10-29  1:37     ` Rob Herring
2021-10-21 17:42 ` [PATCH v2 04/16] dt-bindings: clock: starfive: Add JH7100 clock definitions Emil Renner Berthing
2021-10-21 17:42   ` Emil Renner Berthing
2021-10-29  1:42   ` Rob Herring
2021-10-29  1:42     ` Rob Herring
2021-10-21 17:42 ` [PATCH v2 05/16] dt-bindings: clock: starfive: Add JH7100 bindings Emil Renner Berthing
2021-10-21 17:42   ` Emil Renner Berthing
2021-10-29  1:42   ` Rob Herring
2021-10-29  1:42     ` Rob Herring
2021-10-29 13:05     ` Emil Renner Berthing
2021-10-29 13:05       ` Emil Renner Berthing
2021-10-21 17:42 ` [PATCH v2 06/16] clk: starfive: Add JH7100 clock generator driver Emil Renner Berthing
2021-10-21 17:42   ` Emil Renner Berthing
2021-10-22 12:33   ` Andy Shevchenko
2021-10-22 12:33     ` Andy Shevchenko
2021-10-22 12:44     ` Geert Uytterhoeven
2021-10-22 12:44       ` Geert Uytterhoeven
2021-10-22 13:13     ` Emil Renner Berthing
2021-10-22 13:13       ` Emil Renner Berthing
2021-10-22 13:35       ` Andy Shevchenko
2021-10-22 13:35         ` Andy Shevchenko
2021-10-26 20:19   ` Stephen Boyd
2021-10-26 20:19     ` Stephen Boyd
2021-10-26 22:35     ` Emil Renner Berthing
2021-10-26 22:35       ` Emil Renner Berthing
2021-10-27  0:54       ` Stephen Boyd
2021-10-27  0:54         ` Stephen Boyd
2021-10-27  9:30         ` Andy Shevchenko
2021-10-27  9:30           ` Andy Shevchenko
2021-10-27 10:24         ` Emil Renner Berthing
2021-10-27 10:24           ` Emil Renner Berthing
2021-10-27 10:32           ` Andy Shevchenko
2021-10-27 10:32             ` Andy Shevchenko
2021-10-27 11:22           ` Heiko Stübner
2021-10-27 11:22             ` Heiko Stübner
2021-10-21 17:42 ` [PATCH v2 07/16] dt-bindings: reset: Add StarFive JH7100 reset definitions Emil Renner Berthing
2021-10-21 17:42   ` Emil Renner Berthing
2021-10-29  1:42   ` Rob Herring
2021-10-29  1:42     ` Rob Herring
2021-10-21 17:42 ` [PATCH v2 08/16] dt-bindings: reset: Add Starfive JH7100 reset bindings Emil Renner Berthing
2021-10-21 17:42   ` Emil Renner Berthing
2021-10-29  1:43   ` Rob Herring
2021-10-29  1:43     ` Rob Herring
2021-10-21 17:42 ` [PATCH v2 09/16] reset: starfive-jh7100: Add StarFive JH7100 reset driver Emil Renner Berthing
2021-10-21 17:42   ` Emil Renner Berthing
2021-10-22 12:55   ` Andy Shevchenko
2021-10-22 12:55     ` Andy Shevchenko
2021-10-22 13:34     ` Emil Renner Berthing
2021-10-22 13:34       ` Emil Renner Berthing
2021-10-22 13:38       ` Andy Shevchenko
2021-10-22 13:38         ` Andy Shevchenko
2021-10-22 13:50         ` Emil Renner Berthing
2021-10-22 13:50           ` Emil Renner Berthing
2021-10-22 13:56           ` Andy Shevchenko
2021-10-22 13:56             ` Andy Shevchenko
2021-10-22 14:25         ` Emil Renner Berthing
2021-10-22 14:25           ` Emil Renner Berthing
2021-10-22 14:49           ` Andy Shevchenko
2021-10-22 14:49             ` Andy Shevchenko
2021-10-22 14:50             ` Andy Shevchenko
2021-10-22 14:50               ` Andy Shevchenko
2021-10-22 14:56             ` Emil Renner Berthing
2021-10-22 14:56               ` Emil Renner Berthing
2021-10-22 15:24               ` Andy Shevchenko
2021-10-22 15:24                 ` Andy Shevchenko
2021-10-22 15:36                 ` Emil Renner Berthing
2021-10-22 15:36                   ` Emil Renner Berthing
2021-10-22 15:54                   ` Andy Shevchenko
2021-10-22 15:54                     ` Andy Shevchenko
2021-10-22 15:59                     ` Emil Renner Berthing
2021-10-22 15:59                       ` Emil Renner Berthing
2021-10-22 13:06   ` Andreas Schwab
2021-10-22 13:06     ` Andreas Schwab
2021-10-22 13:41     ` Emil Renner Berthing
2021-10-22 13:41       ` Emil Renner Berthing
2021-10-21 17:42 ` [PATCH v2 10/16] dt-bindings: pinctrl: Add StarFive pinctrl definitions Emil Renner Berthing
2021-10-21 17:42   ` Emil Renner Berthing
2021-10-29  1:44   ` Rob Herring
2021-10-29  1:44     ` Rob Herring
2021-10-21 17:42 ` [PATCH v2 11/16] dt-bindings: pinctrl: Add StarFive JH7100 bindings Emil Renner Berthing
2021-10-21 17:42   ` Emil Renner Berthing
2021-10-24 23:11   ` Linus Walleij
2021-10-24 23:11     ` Linus Walleij
2021-10-25  0:35     ` Emil Renner Berthing
2021-10-25  0:35       ` Emil Renner Berthing
2021-10-29  1:50   ` Rob Herring
2021-10-29  1:50     ` Rob Herring
2021-10-29 13:00     ` Emil Renner Berthing
2021-10-29 13:00       ` Emil Renner Berthing
2021-10-29 14:44       ` Rob Herring
2021-10-29 14:44         ` Rob Herring
2021-10-21 17:42 ` [PATCH v2 12/16] pinctrl: starfive: Add pinctrl driver for StarFive SoCs Emil Renner Berthing
2021-10-21 17:42   ` Emil Renner Berthing
2021-10-21 19:01   ` Drew Fustini
2021-10-21 19:01     ` Drew Fustini
2021-10-21 19:50     ` Emil Renner Berthing
2021-10-21 19:50       ` Emil Renner Berthing
2021-10-22  2:06       ` Drew Fustini
2021-10-22  2:06         ` Drew Fustini
2021-10-22 13:31   ` Andy Shevchenko
2021-10-22 13:31     ` Andy Shevchenko
2021-10-23 18:45     ` Emil Renner Berthing
2021-10-23 18:45       ` Emil Renner Berthing
2021-10-23 20:28       ` Andy Shevchenko
2021-10-23 20:28         ` Andy Shevchenko
2021-10-23 21:02         ` Emil Renner Berthing
2021-10-23 21:02           ` Emil Renner Berthing
2021-10-24  9:29           ` Emil Renner Berthing
2021-10-24  9:29             ` Emil Renner Berthing
2021-10-25 10:15             ` Andy Shevchenko
2021-10-25 10:15               ` Andy Shevchenko
2021-10-25 10:24               ` Emil Renner Berthing
2021-10-25 10:24                 ` Emil Renner Berthing
2021-10-25 10:51                 ` Andy Shevchenko
2021-10-25 10:51                   ` Andy Shevchenko
2021-10-28 20:17   ` kernel test robot
2021-10-28 20:17     ` kernel test robot
2021-10-28 20:17     ` kernel test robot
2021-10-21 17:42 ` [PATCH v2 13/16] dt-bindings: serial: snps-dw-apb-uart: Add JH7100 uarts Emil Renner Berthing
2021-10-21 17:42   ` Emil Renner Berthing
2021-10-29  1:50   ` Rob Herring
2021-10-29  1:50     ` Rob Herring
2021-10-21 17:42 ` [PATCH v2 14/16] serial: 8250_dw: Add skip_clk_set_rate quirk Emil Renner Berthing
2021-10-21 17:42   ` Emil Renner Berthing
2021-10-21 17:42 ` [PATCH v2 15/16] RISC-V: Add initial StarFive JH7100 device tree Emil Renner Berthing
2021-10-21 17:42   ` Emil Renner Berthing
2021-10-21 17:42 ` [PATCH v2 16/16] RISC-V: Add BeagleV Starlight Beta " Emil Renner Berthing
2021-10-21 17:42   ` Emil Renner Berthing

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.