linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v1 00/16] Basic StarFive JH7100 RISC-V SoC support
@ 2021-10-12 13:40 Emil Renner Berthing
  2021-10-12 13:40 ` [PATCH v1 01/16] RISC-V: Add StarFive SoC Kconfig option Emil Renner Berthing
                   ` (16 more replies)
  0 siblings, 17 replies; 49+ messages in thread
From: Emil Renner Berthing @ 2021-10-12 13:40 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, 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 needs 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 non-coherent dma operations can
be found at
https://github.com/starfive-tech/linux/tree/starlight

/Emil

[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 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                  |   10 +
 drivers/clk/starfive/Makefile                 |    3 +
 drivers/clk/starfive/clk-starfive-jh7100.c    |  769 +++++++++
 drivers/pinctrl/Kconfig                       |   17 +
 drivers/pinctrl/Makefile                      |    1 +
 drivers/pinctrl/pinctrl-starfive.c            | 1439 +++++++++++++++++
 drivers/reset/Kconfig                         |    8 +
 drivers/reset/Makefile                        |    1 +
 drivers/reset/reset-starfive-jh7100.c         |  164 ++
 drivers/tty/serial/8250/8250_dw.c             |   32 +-
 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, 3833 insertions(+), 13 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.0


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

* [PATCH v1 01/16] RISC-V: Add StarFive SoC Kconfig option
  2021-10-12 13:40 [PATCH v1 00/16] Basic StarFive JH7100 RISC-V SoC support Emil Renner Berthing
@ 2021-10-12 13:40 ` Emil Renner Berthing
  2021-10-12 18:20   ` Andy Shevchenko
  2021-10-12 13:40 ` [PATCH v1 02/16] dt-bindings: timer: Add StarFive JH7100 clint Emil Renner Berthing
                   ` (15 subsequent siblings)
  16 siblings, 1 reply; 49+ messages in thread
From: Emil Renner Berthing @ 2021-10-12 13:40 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, 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..725e9a1b1ab6 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 SERIAL_8250_DW
+	select SIFIVE_PLIC
+	select PINCTRL
+	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.0


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

* [PATCH v1 02/16] dt-bindings: timer: Add StarFive JH7100 clint
  2021-10-12 13:40 [PATCH v1 00/16] Basic StarFive JH7100 RISC-V SoC support Emil Renner Berthing
  2021-10-12 13:40 ` [PATCH v1 01/16] RISC-V: Add StarFive SoC Kconfig option Emil Renner Berthing
@ 2021-10-12 13:40 ` Emil Renner Berthing
  2021-10-13  7:05   ` Geert Uytterhoeven
  2021-10-19 22:48   ` Rob Herring
  2021-10-12 13:40 ` [PATCH v1 03/16] dt-bindings: interrupt-controller: Add StarFive JH7100 plic Emil Renner Berthing
                   ` (14 subsequent siblings)
  16 siblings, 2 replies; 49+ messages in thread
From: Emil Renner Berthing @ 2021-10-12 13:40 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, Anup Patel, Atish Patra,
	Matteo Croce, linux-kernel

Add compatible string for the StarFive JH7100 clint.

Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
---
 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.0


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

* [PATCH v1 03/16] dt-bindings: interrupt-controller: Add StarFive JH7100 plic
  2021-10-12 13:40 [PATCH v1 00/16] Basic StarFive JH7100 RISC-V SoC support Emil Renner Berthing
  2021-10-12 13:40 ` [PATCH v1 01/16] RISC-V: Add StarFive SoC Kconfig option Emil Renner Berthing
  2021-10-12 13:40 ` [PATCH v1 02/16] dt-bindings: timer: Add StarFive JH7100 clint Emil Renner Berthing
@ 2021-10-12 13:40 ` Emil Renner Berthing
  2021-10-13  7:05   ` Geert Uytterhoeven
  2021-10-12 13:40 ` [PATCH v1 04/16] dt-bindings: clock: starfive: Add JH7100 clock definitions Emil Renner Berthing
                   ` (13 subsequent siblings)
  16 siblings, 1 reply; 49+ messages in thread
From: Emil Renner Berthing @ 2021-10-12 13:40 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, Anup Patel, Atish Patra,
	Matteo Croce, linux-kernel

Add compatible string for StarFive JH7100 plic.

Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
---
 .../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.0


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

* [PATCH v1 04/16] dt-bindings: clock: starfive: Add JH7100 clock definitions
  2021-10-12 13:40 [PATCH v1 00/16] Basic StarFive JH7100 RISC-V SoC support Emil Renner Berthing
                   ` (2 preceding siblings ...)
  2021-10-12 13:40 ` [PATCH v1 03/16] dt-bindings: interrupt-controller: Add StarFive JH7100 plic Emil Renner Berthing
@ 2021-10-12 13:40 ` Emil Renner Berthing
  2021-10-13 18:39   ` Stephen Boyd
  2021-10-12 13:40 ` [PATCH v1 05/16] dt-bindings: clock: starfive: Add JH7100 bindings Emil Renner Berthing
                   ` (12 subsequent siblings)
  16 siblings, 1 reply; 49+ messages in thread
From: Emil Renner Berthing @ 2021-10-12 13:40 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, Anup Patel, Atish Patra, Matteo Croce,
	linux-kernel

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>
---
 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.0


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

* [PATCH v1 05/16] dt-bindings: clock: starfive: Add JH7100 bindings
  2021-10-12 13:40 [PATCH v1 00/16] Basic StarFive JH7100 RISC-V SoC support Emil Renner Berthing
                   ` (3 preceding siblings ...)
  2021-10-12 13:40 ` [PATCH v1 04/16] dt-bindings: clock: starfive: Add JH7100 clock definitions Emil Renner Berthing
@ 2021-10-12 13:40 ` Emil Renner Berthing
  2021-10-12 13:40 ` [PATCH v1 06/16] clk: starfive: Add JH7100 clock generator driver Emil Renner Berthing
                   ` (11 subsequent siblings)
  16 siblings, 0 replies; 49+ messages in thread
From: Emil Renner Berthing @ 2021-10-12 13:40 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, 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.0


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

* [PATCH v1 06/16] clk: starfive: Add JH7100 clock generator driver
  2021-10-12 13:40 [PATCH v1 00/16] Basic StarFive JH7100 RISC-V SoC support Emil Renner Berthing
                   ` (4 preceding siblings ...)
  2021-10-12 13:40 ` [PATCH v1 05/16] dt-bindings: clock: starfive: Add JH7100 bindings Emil Renner Berthing
@ 2021-10-12 13:40 ` Emil Renner Berthing
  2021-10-12 18:40   ` Andy Shevchenko
  2021-10-12 13:40 ` [PATCH v1 07/16] dt-bindings: reset: Add StarFive JH7100 reset definitions Emil Renner Berthing
                   ` (10 subsequent siblings)
  16 siblings, 1 reply; 49+ messages in thread
From: Emil Renner Berthing @ 2021-10-12 13:40 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, 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               |  10 +
 drivers/clk/starfive/Makefile              |   3 +
 drivers/clk/starfive/clk-starfive-jh7100.c | 769 +++++++++++++++++++++
 6 files changed, 791 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 a4a0c2baaf27..d2b95b96f0ec 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -17847,6 +17847,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..801326c18327
--- /dev/null
+++ b/drivers/clk/starfive/Kconfig
@@ -0,0 +1,10 @@
+# SPDX-License-Identifier: GPL-2.0
+
+config CLK_STARFIVE_JH7100
+	bool "StarFive JH7100 clock support"
+	depends on SOC_STARFIVE || COMPILE_TEST
+	depends on OF
+	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..ce1ec8155da3
--- /dev/null
+++ b/drivers/clk/starfive/clk-starfive-jh7100.c
@@ -0,0 +1,769 @@
+// 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/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/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);
+
+	if (div > max)
+		div = max;
+
+	return div;
+}
+
+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);
+
+	rate = parent / div;
+	if (rate < req->min_rate && div > 1) {
+		div -= 1;
+		rate = 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, rate, div);
+
+	req->rate = rate;
+	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, "%s: invalid index %u\n", __func__, 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++) {
+		struct clk_init_data init = {
+			.name = jh7100_clk_data[idx].name,
+			.ops = jh7100_clk_data[idx].ops,
+			.num_parents = ((jh7100_clk_data[idx].max & JH7100_CLK_MUX_MASK)
+					>> JH7100_CLK_MUX_SHIFT) + 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 > 0)
+		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 = {
+	.driver = {
+		.name = "clk-starfive-jh7100",
+		.of_match_table = clk_starfive_jh7100_match,
+	},
+};
+
+static int __init clk_starfive_jh7100_init(void)
+{
+	return platform_driver_probe(&clk_starfive_jh7100_driver,
+				     clk_starfive_jh7100_probe);
+}
+
+subsys_initcall(clk_starfive_jh7100_init);
+
+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.0


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

* [PATCH v1 07/16] dt-bindings: reset: Add StarFive JH7100 reset definitions
  2021-10-12 13:40 [PATCH v1 00/16] Basic StarFive JH7100 RISC-V SoC support Emil Renner Berthing
                   ` (5 preceding siblings ...)
  2021-10-12 13:40 ` [PATCH v1 06/16] clk: starfive: Add JH7100 clock generator driver Emil Renner Berthing
@ 2021-10-12 13:40 ` Emil Renner Berthing
  2021-10-12 13:40 ` [PATCH v1 08/16] dt-bindings: reset: Add Starfive JH7100 reset bindings Emil Renner Berthing
                   ` (9 subsequent siblings)
  16 siblings, 0 replies; 49+ messages in thread
From: Emil Renner Berthing @ 2021-10-12 13:40 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, Anup Patel, Atish Patra, Matteo Croce,
	linux-kernel

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>
---
 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.0


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

* [PATCH v1 08/16] dt-bindings: reset: Add Starfive JH7100 reset bindings
  2021-10-12 13:40 [PATCH v1 00/16] Basic StarFive JH7100 RISC-V SoC support Emil Renner Berthing
                   ` (6 preceding siblings ...)
  2021-10-12 13:40 ` [PATCH v1 07/16] dt-bindings: reset: Add StarFive JH7100 reset definitions Emil Renner Berthing
@ 2021-10-12 13:40 ` Emil Renner Berthing
  2021-10-12 14:08   ` Philipp Zabel
  2021-10-12 13:40 ` [PATCH v1 09/16] reset: starfive-jh7100: Add StarFive JH7100 reset driver Emil Renner Berthing
                   ` (8 subsequent siblings)
  16 siblings, 1 reply; 49+ messages in thread
From: Emil Renner Berthing @ 2021-10-12 13:40 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, 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..1985ccaf8605
--- /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@11840000 {
+        compatible = "starfive,jh7100-reset";
+        reg = <0x11840000 0x10000>;
+        #reset-cells = <1>;
+    };
+
+...
-- 
2.33.0


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

* [PATCH v1 09/16] reset: starfive-jh7100: Add StarFive JH7100 reset driver
  2021-10-12 13:40 [PATCH v1 00/16] Basic StarFive JH7100 RISC-V SoC support Emil Renner Berthing
                   ` (7 preceding siblings ...)
  2021-10-12 13:40 ` [PATCH v1 08/16] dt-bindings: reset: Add Starfive JH7100 reset bindings Emil Renner Berthing
@ 2021-10-12 13:40 ` Emil Renner Berthing
  2021-10-12 14:06   ` Philipp Zabel
  2021-10-12 14:31   ` Philipp Zabel
  2021-10-12 13:40 ` [PATCH v1 10/16] dt-bindings: pinctrl: Add StarFive pinctrl definitions Emil Renner Berthing
                   ` (7 subsequent siblings)
  16 siblings, 2 replies; 49+ messages in thread
From: Emil Renner Berthing @ 2021-10-12 13:40 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, 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 | 164 ++++++++++++++++++++++++++
 4 files changed, 180 insertions(+)
 create mode 100644 drivers/reset/reset-starfive-jh7100.c

diff --git a/MAINTAINERS b/MAINTAINERS
index d2b95b96f0ec..f7883377895e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -17854,6 +17854,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..8345521744b3 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -92,6 +92,14 @@ config RESET_INTEL_GW
 	  Say Y to control the reset signals provided by reset controller.
 	  Otherwise, say N.
 
+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_K210
 	bool "Reset controller driver for Canaan Kendryte K210 SoC"
 	depends on (SOC_CANAAN || COMPILE_TEST) && OF
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index 21d46d8869ff..021eff3525de 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_RESET_BRCMSTB_RESCAL) += reset-brcmstb-rescal.o
 obj-$(CONFIG_RESET_HSDK) += reset-hsdk.o
 obj-$(CONFIG_RESET_IMX7) += reset-imx7.o
 obj-$(CONFIG_RESET_INTEL_GW) += reset-intel-gw.o
+obj-$(CONFIG_RESET_STARFIVE_JH7100) += reset-starfive-jh7100.o
 obj-$(CONFIG_RESET_K210) += reset-k210.o
 obj-$(CONFIG_RESET_LANTIQ) += reset-lantiq.o
 obj-$(CONFIG_RESET_LPC18XX) += reset-lpc18xx.o
diff --git a/drivers/reset/reset-starfive-jh7100.c b/drivers/reset/reset-starfive-jh7100.c
new file mode 100644
index 000000000000..26bc5b59c1f3
--- /dev/null
+++ b/drivers/reset/reset-starfive-jh7100.c
@@ -0,0 +1,164 @@
+// 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/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_MASK(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;
+
+	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);
+
+	do {
+		value = readl(reg_status) & mask;
+	} while (value != done);
+
+	spin_unlock_irqrestore(&data->lock, flags);
+	return 0;
+}
+
+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.0


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

* [PATCH v1 10/16] dt-bindings: pinctrl: Add StarFive pinctrl definitions
  2021-10-12 13:40 [PATCH v1 00/16] Basic StarFive JH7100 RISC-V SoC support Emil Renner Berthing
                   ` (8 preceding siblings ...)
  2021-10-12 13:40 ` [PATCH v1 09/16] reset: starfive-jh7100: Add StarFive JH7100 reset driver Emil Renner Berthing
@ 2021-10-12 13:40 ` Emil Renner Berthing
  2021-10-12 13:40 ` [PATCH v1 11/16] dt-bindings: pinctrl: Add StarFive JH7100 bindings Emil Renner Berthing
                   ` (6 subsequent siblings)
  16 siblings, 0 replies; 49+ messages in thread
From: Emil Renner Berthing @ 2021-10-12 13:40 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, 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..3dd2a886b95b
--- /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_NONE				0xffffffff
+
+#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
+
+#endif
-- 
2.33.0


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

* [PATCH v1 11/16] dt-bindings: pinctrl: Add StarFive JH7100 bindings
  2021-10-12 13:40 [PATCH v1 00/16] Basic StarFive JH7100 RISC-V SoC support Emil Renner Berthing
                   ` (9 preceding siblings ...)
  2021-10-12 13:40 ` [PATCH v1 10/16] dt-bindings: pinctrl: Add StarFive pinctrl definitions Emil Renner Berthing
@ 2021-10-12 13:40 ` Emil Renner Berthing
  2021-10-12 13:40 ` [PATCH v1 12/16] pinctrl: starfive: Add pinctrl driver for StarFive SoCs Emil Renner Berthing
                   ` (5 subsequent siblings)
  16 siblings, 0 replies; 49+ messages in thread
From: Emil Renner Berthing @ 2021-10-12 13:40 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, 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.0


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

* [PATCH v1 12/16] pinctrl: starfive: Add pinctrl driver for StarFive SoCs
  2021-10-12 13:40 [PATCH v1 00/16] Basic StarFive JH7100 RISC-V SoC support Emil Renner Berthing
                   ` (10 preceding siblings ...)
  2021-10-12 13:40 ` [PATCH v1 11/16] dt-bindings: pinctrl: Add StarFive JH7100 bindings Emil Renner Berthing
@ 2021-10-12 13:40 ` Emil Renner Berthing
  2021-10-12 20:02   ` Andy Shevchenko
  2021-10-12 13:40 ` [PATCH v1 13/16] dt-bindings: serial: snps-dw-apb-uart: Add JH7100 uarts Emil Renner Berthing
                   ` (4 subsequent siblings)
  16 siblings, 1 reply; 49+ messages in thread
From: Emil Renner Berthing @ 2021-10-12 13:40 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, 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.

Co-developed-by: Huan Feng <huan.feng@starfivetech.com>
Signed-off-by: Huan Feng <huan.feng@starfivetech.com>
Co-developed-by: Drew Fustini <drew@beagleboard.org>
Signed-off-by: Drew Fustini <drew@beagleboard.org>
Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
---
 MAINTAINERS                        |    8 +
 drivers/pinctrl/Kconfig            |   17 +
 drivers/pinctrl/Makefile           |    1 +
 drivers/pinctrl/pinctrl-starfive.c | 1439 ++++++++++++++++++++++++++++
 4 files changed, 1465 insertions(+)
 create mode 100644 drivers/pinctrl/pinctrl-starfive.c

diff --git a/MAINTAINERS b/MAINTAINERS
index f7883377895e..4a34a8a9c987 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -17854,6 +17854,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..2f3d37b075c5 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -265,6 +265,23 @@ config PINCTRL_ST
 	select PINCONF
 	select GPIOLIB_IRQCHIP
 
+config PINCTRL_STARFIVE
+	bool "Pinctrl and GPIO driver for the StarFive JH7100 SoC"
+	depends on SOC_STARFIVE || COMPILE_TEST
+	depends on OF
+	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..e3b5a2f53fe1
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-starfive.c
@@ -0,0 +1,1439 @@
+// 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/clk.h>
+#include <linux/gpio/driver.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+#include <linux/spinlock.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 JH7100 datasheet:
+ * https://github.com/starfive-tech/StarLight_Docs
+ */
+#define MAX_GPIO	64
+
+/*
+ * Global enable for GPIO interrupts, offset: 0x0, field: GPIOEN
+ * set to 1 if GPIO interrupts are enabled, set to 0 to disable
+ */
+#define IRQ_GLOBAL_EN		0x0
+
+/*
+ * Interrupt Type for GPIO[31:0], offset: 0x10, field: GPIOS_0
+ * set to 1 if edge-triggered, set to 0 for level-triggered
+ */
+#define IRQ_TYPE_LOW		0x10
+
+/*
+ * Interrupt Type for GPIO[63:32], offset: 0x14, field: GPIOS_1
+ */
+#define IRQ_TYPE_HIGH		0x14
+
+/*
+ * Edge-Triggered Interrupt Type for GPIO[31:0], offset: 0x18, field: GPIOIBE_0
+ * set to 1 if both positive and negative edge, set to 0 if single edge
+ */
+#define IRQ_EDGE_BOTH_LOW	0x18
+
+/*
+ * Edge-Triggered Interrupt Type for GPIO[63:32], offset: 0x1c, field: GPIOIBE_1
+ */
+#define IRQ_EDGE_BOTH_HIGH	0x1c
+
+/*
+ * Interrupt Trigger Polarity for GPIO[31:0], offset: 0x20, field: GPIOEV_0
+ * for edge-triggered on single edge, set to 1 for rising edge, 0 for falling edge
+ * for edge-triggered on both edges, this field is ignored
+ * for level-triggered, set to 1 for high level, 0 for low level
+ */
+#define IRQ_POLARITY_LOW	0x20
+
+/*
+ * Interrupt Trigger Polarity for GPIO[63:32], offset: 0x24, field: GPIOEV_1
+ */
+#define IRQ_POLARITY_HIGH	0x24
+
+/*
+ * Interrupt Enable for GPIO[31:0], offset: 0x28, field: GPIOIE_0
+ * set to 1 to enable (unmask) the interrupt, set to 0 to disable (mask)
+ */
+#define IRQ_ENABLE_LOW		0x28
+
+/*
+ * Interrupt Mask for GPIO[63:32], offset: 0x2c, field: GPIOIE_1
+ */
+#define IRQ_ENABLE_HIGH		0x2c
+
+/*
+ * Clear Edge-Triggered Interrupts GPIO[31:0], offset: 0x30, field: GPIOC_0
+ * set to 1 to clear edge-triggered interrupt
+ */
+#define IRQ_CLEAR_EDGE_LOW	0x30
+
+/*
+ * Clear Edge-Triggered Interrupts GPIO[63:32], offset: 0x34, field: GPIOC_1
+ */
+#define IRQ_CLEAR_EDGE_HIGH	0x34
+
+/*
+ * Edge-Triggered Interrupt Status GPIO[31:0], offset: 0x38, field: GPIORIS_0
+ * value of 1 means edge detected, value of 0 means no edge detected
+ */
+#define IRQ_EDGE_STATUS_LOW	0x38
+
+/*
+ * Edge-Triggered Interrupt Status GPIO[63:32], offset: 0x3C, field: GPIORIS_1
+ */
+#define IRQ_EDGE_STATUS_HIGH	0x3c
+
+/*
+ * Interrupt Status after Masking GPIO[31:0], offset: 0x40, field: GPIOMIS_0
+ * status of edge-triggered or level-triggered after masking
+ * value of 1 means edge or level was detected, value of 0 menas not detected
+ */
+#define IRQ_MASKED_STATUS_LOW	0x40
+
+/*
+ * Interrupt Status after Masking GPIO[63:32], offset: 0x44, field: GPIOMIS_1
+ */
+#define IRQ_MASKED_STATUS_HIGH	0x44
+
+/*
+ * Data Value of GPIO for GPIO[31:0], offest: 0x48, field: GPIODIN_0
+ * dynamically reflects value on the GPIO pin
+ */
+#define GPIO_DIN_LOW		0x48
+
+/*
+ * Data Value of GPIO for GPIO[63:32], offest: 0x4C, field: GPIODIN_1
+ */
+#define GPIO_DIN_HIGH		0x4c
+
+/*
+ * From datasheet section 12.2, there are 64 output data config registers which
+ * are 4 bytes wide. There are 64 output enable config registers which are 4
+ * bytes wide too. Output data and output enable registers for a given GPIO pad
+ * are contiguous. Thus GPIO0_DOUT_CFG is 0x50 and GPIO0_DOEN_CFG is 0x54 while
+ * GPIO1_DOUT_CFG is 0x58 and GPIO1_DOEN_CFG is 0x5C. The stride between GPIO
+ * GPIO pads is effectively 8, thus: GPIOn_DOUT_CFG is 0x50+8n
+ */
+#define GPIO_N_DOUT_CFG		0x50
+
+/*
+ * GPIO0_DOEN_CFG is 0x54, GPIOn_DOEN_CFG is 0x54+8n
+ */
+#define GPIO_N_DOEN_CFG		0x54
+
+/*
+ * 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 GPIO_IN_OFFSET		0x250
+
+/*
+ * From Section 11, IO_PADSHARE_SEL register can be programmed to select one of
+ * pre-defined multiplexed signal groups on PAD_FUNC_SHARE and PAD_GPIO pads.
+ * This is a global setting. Per Table 11-1, setting IO_PADSHARE_SEL to 6 would
+ * result in GPIO[63:0] being mapped to PAD_FUNC_SHARE[63:0]
+ */
+#define IO_PADSHARE_SEL		0x1a0
+
+#define PAD_SLEW_RATE_MASK		0xe00U
+#define PAD_SLEW_RATE_POS		9
+#define PAD_BIAS_STRONG_PULL_UP		0x100U
+#define PAD_INPUT_ENABLE		0x080U
+#define PAD_INPUT_SCHMITT_ENABLE	0x040U
+#define PAD_BIAS_DISABLE		0x020U
+#define PAD_BIAS_PULL_DOWN		0x010U
+#define PAD_BIAS_MASK			0x130U
+#define PAD_DRIVE_STRENGTH_MASK		0x007U
+#define PAD_DRIVE_STRENGTH_POS		0
+
+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 >= MAX_GPIO)
+		return;
+
+	reg = sfp->base + GPIO_N_DOUT_CFG + 8 * gpio;
+	dout = readl_relaxed(reg);
+	reg += 4;
+	doen = readl_relaxed(reg);
+
+	seq_printf(s, "dout=%u%s doen=%u%s",
+		   dout & 0xffU, (dout & 0x80000000U) ? "r" : "",
+		   doen & 0xffU, (doen & 0x80000000U) ? "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) {
+		const __be32 *pinmux_list;
+		const __be32 *pins_list;
+		int pinmux_size;
+		int pins_size;
+
+		pinmux_list = of_get_property(child, "pinmux", &pinmux_size);
+		pins_list   = of_get_property(child, "pins",   &pins_size);
+		if (pinmux_list && pins_list) {
+			dev_err(dev, "invalid pinctrl group %pOFn.%pOFn: %s\n",
+				np, child, "both pinmux and pins set");
+			of_node_put(child);
+			return -EINVAL;
+		}
+
+		if (pinmux_list && pinmux_size > 0) {
+			nmaps += 2;
+		} else if (pins_list && pins_size > 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)
+		goto out;
+
+	map = kcalloc(nmaps, sizeof(*map), GFP_KERNEL);
+	if (!map)
+		goto free_pgnames;
+
+	nmaps = 0;
+	ngroups = 0;
+	for_each_child_of_node(np, child) {
+		const __be32 *list;
+		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 ((list = of_get_property(child, "pinmux", &npins))) {
+			npins /= sizeof(*list);
+
+			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 = be32_to_cpu(*list++);
+
+				pins[i] = starfive_gpio_to_pin(sfp, v & (MAX_GPIO - 1));
+				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 ((list = of_get_property(child, "pins", &npins))) {
+			npins /= sizeof(*list);
+
+			pins = devm_kcalloc(dev, npins, sizeof(*pins), GFP_KERNEL);
+			if (!pins)
+				goto free_grpname;
+
+			pinmux = NULL;
+
+			for (i = 0; i < npins; i++)
+				pins[i] = be32_to_cpu(*list++);
+		} 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);
+out:
+	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 (unlikely(!group))
+		return -EINVAL;
+
+	pinmux = group->data;
+	for (i = 0; i < group->num_pins; i++) {
+		unsigned int gpio = starfive_pin_to_gpio(sfp, group->pins[i]);
+		void __iomem *reg_dout;
+		void __iomem *reg_doen;
+		void __iomem *reg_din;
+		u32 v, dout, doen, din;
+		unsigned long flags;
+
+		if (dev_WARN_ONCE(dev, gpio >= MAX_GPIO,
+				  "%s: invalid gpiomux pin", group->name))
+			continue;
+
+		v = pinmux[i];
+		dout = ((v & BIT(7)) << (31 - 7)) | ((v >> 24) & 0xffU);
+		doen = ((v & BIT(6)) << (31 - 6)) | ((v >> 16) & 0xffU);
+		din  = (v >> 8) & 0xffU;
+
+		dev_dbg(dev, "GPIO%u: dout=0x%x doen=0x%x din=0x%x\n",
+			gpio, dout, doen, din);
+
+		reg_dout = sfp->base + GPIO_N_DOUT_CFG + 8 * gpio;
+		reg_doen = sfp->base + GPIO_N_DOEN_CFG + 8 * gpio;
+		if (din != 0xff)
+			reg_din = sfp->base + GPIO_IN_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);
+	u32 value = readl_relaxed(reg);
+
+	if (pin & 1U)
+		value >>= 16;
+	return value;
+}
+
+static void starfive_padctl_rmw(struct starfive_pinctrl *sfp,
+				unsigned int pin,
+				u16 _mask, u16 _value)
+{
+	void __iomem *reg = sfp->padctl + 4 * (pin / 2);
+	u32 mask = _mask;
+	u32 value = _value;
+	unsigned long flags;
+
+	dev_dbg(starfive_dev(sfp),
+		"padctl_rmw(%u, 0x%03x, 0x%03x)\n", pin, mask, value);
+
+	if (pin & 1U) {
+		value <<= 16;
+		mask <<= 16;
+	}
+
+	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[ARRAY_SIZE(starfive_pinconf_custom_params)] = {
+	PCONFDUMP(PIN_CONFIG_STARFIVE_STRONG_PULL_UP, "input bias strong pull-up", NULL, false),
+};
+#else
+#define starfive_pinconf_custom_conf_items NULL
+#endif
+
+static const unsigned char starfive_drive_strength[] = {
+	14, 21, 28, 35, 42, 49, 56, 63,
+};
+
+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[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 (unlikely(!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 (unlikely(!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]);
+		u16 ds;
+
+		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:
+			for (ds = 0; ds < PAD_DRIVE_STRENGTH_MASK; ds++) {
+				if (arg < starfive_drive_strength[ds + 1])
+					break;
+			}
+			mask |= PAD_DRIVE_STRENGTH_MASK;
+			value = (value & ~PAD_DRIVE_STRENGTH_MASK) | ds;
+			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 >= MAX_GPIO)
+		return -EINVAL;
+
+	/* return GPIO_LINE_DIRECTION_OUT (0) only if doen == GPO_ENABLE (0) */
+	return readl_relaxed(sfp->base + GPIO_N_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);
+	unsigned long flags;
+
+	if (gpio >= MAX_GPIO)
+		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);
+
+	raw_spin_lock_irqsave(&sfp->lock, flags);
+	writel_relaxed(GPO_DISABLE, sfp->base + GPIO_N_DOEN_CFG + 8 * gpio);
+	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);
+	unsigned long flags;
+
+	if (gpio >= MAX_GPIO)
+		return -EINVAL;
+
+	raw_spin_lock_irqsave(&sfp->lock, flags);
+	writel_relaxed(value, sfp->base + GPIO_N_DOUT_CFG + 8 * gpio);
+	writel_relaxed(GPO_ENABLE, sfp->base + GPIO_N_DOEN_CFG + 8 * gpio);
+	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);
+	u32 value;
+
+	if (gpio >= MAX_GPIO)
+		return -EINVAL;
+
+	if (gpio < 32) {
+		value = readl_relaxed(sfp->base + GPIO_DIN_LOW);
+		value = (value >> gpio) & 1U;
+	} else {
+		value = readl_relaxed(sfp->base + GPIO_DIN_HIGH);
+		value = (value >> (gpio - 32)) & 1U;
+	}
+
+	return value;
+}
+
+static void starfive_gpio_set(struct gpio_chip *gc, unsigned int gpio,
+			      int value)
+{
+	struct starfive_pinctrl *sfp = starfive_from_gc(gc);
+	unsigned long flags;
+
+	if (gpio >= MAX_GPIO)
+		return;
+
+	raw_spin_lock_irqsave(&sfp->lock, flags);
+	writel_relaxed(value, sfp->base + GPIO_N_DOUT_CFG + 8 * gpio);
+	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 = MAX_GPIO;
+	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);
+	unsigned long flags;
+	void __iomem *ic;
+	u32 mask;
+
+	if (gpio < 0 || gpio >= MAX_GPIO)
+		return;
+
+	if (gpio < 32) {
+		ic = sfp->base + IRQ_CLEAR_EDGE_LOW;
+		mask = BIT(gpio);
+	} else {
+		ic = sfp->base + IRQ_CLEAR_EDGE_HIGH;
+		mask = BIT(gpio - 32);
+	}
+
+	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);
+	unsigned long flags;
+	void __iomem *ie;
+	u32 mask, value;
+
+	if (gpio < 0 || gpio >= MAX_GPIO)
+		return;
+
+	if (gpio < 32) {
+		ie = sfp->base + IRQ_ENABLE_LOW;
+		mask = BIT(gpio);
+	} else {
+		ie = sfp->base + IRQ_ENABLE_HIGH;
+		mask = BIT(gpio - 32);
+	}
+
+	raw_spin_lock_irqsave(&sfp->lock, flags);
+	value = readl_relaxed(ie);
+	value &= ~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);
+	unsigned long flags;
+	void __iomem *ie;
+	void __iomem *ic;
+	u32 mask, value;
+
+	if (gpio < 0 || gpio >= MAX_GPIO)
+		return;
+
+	if (gpio < 32) {
+		ie = sfp->base + IRQ_ENABLE_LOW;
+		ic = sfp->base + IRQ_CLEAR_EDGE_LOW;
+		mask = BIT(gpio);
+	} else {
+		ie = sfp->base + IRQ_ENABLE_HIGH;
+		ic = sfp->base + IRQ_CLEAR_EDGE_HIGH;
+		mask = BIT(gpio - 32);
+	}
+
+	raw_spin_lock_irqsave(&sfp->lock, flags);
+	value = readl_relaxed(ie);
+	value &= ~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);
+	unsigned long flags;
+	void __iomem *ie;
+	u32 mask, value;
+
+	if (gpio < 0 || gpio >= MAX_GPIO)
+		return;
+
+	if (gpio < 32) {
+		ie = sfp->base + IRQ_ENABLE_LOW;
+		mask = BIT(gpio);
+	} else {
+		ie = sfp->base + IRQ_ENABLE_HIGH;
+		mask = BIT(gpio - 32);
+	}
+
+	raw_spin_lock_irqsave(&sfp->lock, flags);
+	value = readl_relaxed(ie);
+	value |= 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);
+	unsigned long flags;
+	void __iomem *base;
+	u32 mask, irq_type, edge_both, polarity;
+
+	if (gpio < 0 || gpio >= MAX_GPIO)
+		return -EINVAL;
+
+	if (gpio < 32) {
+		base = sfp->base;
+		mask = BIT(gpio);
+	} else {
+		base = sfp->base + 4;
+		mask = BIT(gpio - 32);
+	}
+
+	switch (trigger) {
+	case IRQ_TYPE_EDGE_RISING:
+		irq_set_handler_locked(d, handle_edge_irq);
+		irq_type  = mask; /* 1: edge triggered */
+		edge_both = 0;    /* 0: single edge */
+		polarity  = mask; /* 1: rising edge */
+		break;
+	case IRQ_TYPE_EDGE_FALLING:
+		irq_set_handler_locked(d, handle_edge_irq);
+		irq_type  = mask; /* 1: edge triggered */
+		edge_both = 0;    /* 0: single edge */
+		polarity  = 0;    /* 0: falling edge */
+		break;
+	case IRQ_TYPE_EDGE_BOTH:
+		irq_set_handler_locked(d, handle_edge_irq);
+		irq_type  = mask; /* 1: edge triggered */
+		edge_both = mask; /* 1: both edges */
+		polarity  = 0;    /* 0: ignored */
+		break;
+	case IRQ_TYPE_LEVEL_HIGH:
+		irq_set_handler_locked(d, handle_level_irq);
+		irq_type  = 0;    /* 0: level trigged */
+		edge_both = 0;    /* 0: ignored */
+		polarity  = mask; /* 1: high level */
+		break;
+	case IRQ_TYPE_LEVEL_LOW:
+		irq_set_handler_locked(d, handle_level_irq);
+		irq_type  = 0;    /* 0: level triggered */
+		edge_both = 0;    /* 0: ignored */
+		polarity  = 0;    /* 0: low level */
+		break;
+	default:
+		irq_set_handler_locked(d, handle_bad_irq);
+		return -ENOTSUPP;
+	}
+
+	raw_spin_lock_irqsave(&sfp->lock, flags);
+	irq_type |= readl_relaxed(base + IRQ_TYPE_LOW) & ~mask;
+	writel_relaxed(irq_type, base + IRQ_TYPE_LOW);
+	edge_both |= readl_relaxed(base + IRQ_EDGE_BOTH_LOW) & ~mask;
+	writel_relaxed(edge_both, base + IRQ_EDGE_BOTH_LOW);
+	polarity |= readl_relaxed(base + IRQ_POLARITY_LOW) & ~mask;
+	writel_relaxed(polarity, base + IRQ_POLARITY_LOW);
+	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 + IRQ_MASKED_STATUS_LOW);
+	for_each_set_bit(pin, &mis, 32)
+		generic_handle_domain_irq(sfp->gc.irq.domain, pin);
+
+	mis = readl_relaxed(sfp->base + IRQ_MASKED_STATUS_HIGH);
+	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 + IRQ_ENABLE_LOW);
+	writel(0, sfp->base + IRQ_ENABLE_HIGH);
+	/* clear edge interrupt flags */
+	writel(~0U, sfp->base + IRQ_CLEAR_EDGE_LOW);
+	writel(~0U, sfp->base + IRQ_CLEAR_EDGE_HIGH);
+	/* enable GPIO interrupts */
+	writel(1, sfp->base + IRQ_GLOBAL_EN);
+	return 0;
+}
+
+static int __init 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);
+		dev_err(dev, "could not get clock: %d\n", ret);
+		return ret;
+	}
+
+	rst = devm_reset_control_get_exclusive(dev, NULL);
+	if (IS_ERR(rst)) {
+		ret = PTR_ERR(rst);
+		dev_err(dev, "could not get reset: %d\n", ret);
+		return ret;
+	}
+
+	ret = reset_control_assert(rst);
+	if (ret) {
+		dev_err(dev, "could not assert reset: %d\n", ret);
+		return ret;
+	}
+
+	ret = clk_prepare_enable(clk);
+	if (ret) {
+		reset_control_deassert(rst);
+		dev_err(dev, "could not enable clock: %d\n", ret);
+		return ret;
+	}
+
+	ret = reset_control_deassert(rst);
+	if (ret) {
+		dev_err(dev, "could not deassert reset: %d\n", ret);
+		return 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) {
+		dev_err(dev, "could not register pinctrl driver: %d\n", ret);
+		return ret;
+	}
+
+	if (!of_property_read_u32(dev->of_node, "starfive,signal-group", &value)) {
+		if (value <= 6)
+			writel(value, sfp->padctl + IO_PADSHARE_SEL);
+		else
+			dev_err(dev, "invalid signal group %u\n", value);
+	}
+
+	value = readl(sfp->padctl + IO_PADSHARE_SEL);
+	switch (value) {
+	case 0:
+		sfp->gpios.pin_base = 0x10000;
+		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.of_node = dev->of_node;
+	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 = MAX_GPIO;
+
+	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.parents =
+		devm_kcalloc(dev, 1, sizeof(*sfp->gc.irq.parents), GFP_KERNEL);
+	if (!sfp->gc.irq.parents)
+		return -ENOMEM;
+	sfp->gc.irq.num_parents = 1;
+	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;
+	}
+
+	dev_info(dev, "StarFive GPIO chip registered %d GPIOs\n", sfp->gc.ngpio);
+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.0


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

* [PATCH v1 13/16] dt-bindings: serial: snps-dw-apb-uart: Add JH7100 uarts
  2021-10-12 13:40 [PATCH v1 00/16] Basic StarFive JH7100 RISC-V SoC support Emil Renner Berthing
                   ` (11 preceding siblings ...)
  2021-10-12 13:40 ` [PATCH v1 12/16] pinctrl: starfive: Add pinctrl driver for StarFive SoCs Emil Renner Berthing
@ 2021-10-12 13:40 ` Emil Renner Berthing
  2021-10-13  7:09   ` Geert Uytterhoeven
  2021-10-12 13:40 ` [PATCH v1 14/16] serial: 8250_dw: Add skip_clk_set_rate quirk Emil Renner Berthing
                   ` (3 subsequent siblings)
  16 siblings, 1 reply; 49+ messages in thread
From: Emil Renner Berthing @ 2021-10-12 13:40 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, Anup Patel, Atish Patra,
	Matteo Croce, linux-kernel

Add compatibles for the StarFive JH7100 uarts.

Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
---
 .../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.0


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

* [PATCH v1 14/16] serial: 8250_dw: Add skip_clk_set_rate quirk
  2021-10-12 13:40 [PATCH v1 00/16] Basic StarFive JH7100 RISC-V SoC support Emil Renner Berthing
                   ` (12 preceding siblings ...)
  2021-10-12 13:40 ` [PATCH v1 13/16] dt-bindings: serial: snps-dw-apb-uart: Add JH7100 uarts Emil Renner Berthing
@ 2021-10-12 13:40 ` Emil Renner Berthing
  2021-10-12 20:08   ` Andy Shevchenko
  2021-10-12 13:40 ` [PATCH v1 15/16] RISC-V: Add initial StarFive JH7100 device tree Emil Renner Berthing
                   ` (2 subsequent siblings)
  16 siblings, 1 reply; 49+ messages in thread
From: Emil Renner Berthing @ 2021-10-12 13:40 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, 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 | 32 ++++++++++++++++++-------------
 1 file changed, 19 insertions(+), 13 deletions(-)

diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c
index a3a0154da567..dee26c0909fd 100644
--- a/drivers/tty/serial/8250/8250_dw.c
+++ b/drivers/tty/serial/8250/8250_dw.c
@@ -51,6 +51,7 @@ struct dw8250_data {
 
 	unsigned int		skip_autocfg:1;
 	unsigned int		uart_16550_compatible:1;
+	unsigned int		skip_clk_set_rate:1;
 };
 
 static inline struct dw8250_data *to_dw8250_data(struct dw8250_port_data *data)
@@ -334,21 +335,23 @@ static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios,
 	long rate;
 	int ret;
 
-	clk_disable_unprepare(d->clk);
-	rate = clk_round_rate(d->clk, newrate);
-	if (rate > 0) {
-		/*
-		 * Premilinary set the uartclk to the new clock rate so the
-		 * clock update event handler caused by the clk_set_rate()
-		 * calling wouldn't actually update the UART divisor since
-		 * we about to do this anyway.
-		 */
-		swap(p->uartclk, rate);
-		ret = clk_set_rate(d->clk, newrate);
-		if (ret)
+	if (!d->skip_clk_set_rate) {
+		clk_disable_unprepare(d->clk);
+		rate = clk_round_rate(d->clk, newrate);
+		if (rate > 0) {
+			/*
+			 * Premilinary set the uartclk to the new clock rate so
+			 * the clock update event handler caused by the
+			 * clk_set_rate() calling wouldn't actually update the
+			 * UART divisor since we about to do this anyway.
+			 */
 			swap(p->uartclk, rate);
+			ret = clk_set_rate(d->clk, newrate);
+			if (ret)
+				swap(p->uartclk, rate);
+		}
+		clk_prepare_enable(d->clk);
 	}
-	clk_prepare_enable(d->clk);
 
 	p->status &= ~UPSTAT_AUTOCTS;
 	if (termios->c_cflag & CRTSCTS)
@@ -418,6 +421,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;
@@ -700,6 +705,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.0


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

* [PATCH v1 15/16] RISC-V: Add initial StarFive JH7100 device tree
  2021-10-12 13:40 [PATCH v1 00/16] Basic StarFive JH7100 RISC-V SoC support Emil Renner Berthing
                   ` (13 preceding siblings ...)
  2021-10-12 13:40 ` [PATCH v1 14/16] serial: 8250_dw: Add skip_clk_set_rate quirk Emil Renner Berthing
@ 2021-10-12 13:40 ` Emil Renner Berthing
  2021-10-12 13:40 ` [PATCH v1 16/16] RISC-V: Add BeagleV Starlight Beta " Emil Renner Berthing
  2021-10-13 23:32 ` [PATCH v1 00/16] Basic StarFive JH7100 RISC-V SoC support Linus Walleij
  16 siblings, 0 replies; 49+ messages in thread
From: Emil Renner Berthing @ 2021-10-12 13:40 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, 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..ee3d23ef0fe8
--- /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@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.0


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

* [PATCH v1 16/16] RISC-V: Add BeagleV Starlight Beta device tree
  2021-10-12 13:40 [PATCH v1 00/16] Basic StarFive JH7100 RISC-V SoC support Emil Renner Berthing
                   ` (14 preceding siblings ...)
  2021-10-12 13:40 ` [PATCH v1 15/16] RISC-V: Add initial StarFive JH7100 device tree Emil Renner Berthing
@ 2021-10-12 13:40 ` Emil Renner Berthing
  2021-10-13 23:32 ` [PATCH v1 00/16] Basic StarFive JH7100 RISC-V SoC support Linus Walleij
  16 siblings, 0 replies; 49+ messages in thread
From: Emil Renner Berthing @ 2021-10-12 13:40 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, 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.0


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

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

Hi Emil,

On Tue, 2021-10-12 at 15:40 +0200, Emil Renner Berthing wrote:
> 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 | 164 ++++++++++++++++++++++++++
>  4 files changed, 180 insertions(+)
>  create mode 100644 drivers/reset/reset-starfive-jh7100.c
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index d2b95b96f0ec..f7883377895e 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -17854,6 +17854,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..8345521744b3 100644
> --- a/drivers/reset/Kconfig
> +++ b/drivers/reset/Kconfig
> @@ -92,6 +92,14 @@ config RESET_INTEL_GW
>  	  Say Y to control the reset signals provided by reset controller.
>  	  Otherwise, say N.
>  
> +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.
> +

Please keep these in alphabetical (config symbol name) order.

regards
Philipp

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

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

On Tue, 12 Oct 2021 at 16:06, Philipp Zabel <p.zabel@pengutronix.de> wrote:
>
> Hi Emil,
>
> On Tue, 2021-10-12 at 15:40 +0200, Emil Renner Berthing wrote:
> > 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 | 164 ++++++++++++++++++++++++++
> >  4 files changed, 180 insertions(+)
> >  create mode 100644 drivers/reset/reset-starfive-jh7100.c
> >
> > diff --git a/MAINTAINERS b/MAINTAINERS
> > index d2b95b96f0ec..f7883377895e 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -17854,6 +17854,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..8345521744b3 100644
> > --- a/drivers/reset/Kconfig
> > +++ b/drivers/reset/Kconfig
> > @@ -92,6 +92,14 @@ config RESET_INTEL_GW
> >         Say Y to control the reset signals provided by reset controller.
> >         Otherwise, say N.
> >
> > +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.
> > +
>
> Please keep these in alphabetical (config symbol name) order.

Argh, sorry. I injected the _STARFIVE_ late and forgot about ordering.
Will fix, thanks!

> regards
> Philipp

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

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

On Tue, 2021-10-12 at 15:40 +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..1985ccaf8605
> --- /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@11840000 {

Better call this reset-controller@11840000, same in the .dtsi.

regards
Philipp

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

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

On Tue, 2021-10-12 at 15:40 +0200, Emil Renner Berthing wrote:
> 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 | 164 ++++++++++++++++++++++++++
>  4 files changed, 180 insertions(+)
>  create mode 100644 drivers/reset/reset-starfive-jh7100.c
> 
[...]
> diff --git a/drivers/reset/reset-starfive-jh7100.c b/drivers/reset/reset-starfive-jh7100.c
> new file mode 100644
> index 000000000000..26bc5b59c1f3
> --- /dev/null
> +++ b/drivers/reset/reset-starfive-jh7100.c
> @@ -0,0 +1,164 @@
[...]
> +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;
> +
> +	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);
> +
> +	do {
> +		value = readl(reg_status) & mask;
> +	} while (value != done);

Looking at the barebox driver, this could loop indefinitely if the
caller forgets to enable the corresponding peripheral clock. Maybe
use readl_poll_timeout() as a safety net.

regards
Philipp

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

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

On Tue, 12 Oct 2021 at 16:31, Philipp Zabel <p.zabel@pengutronix.de> wrote:
>
> On Tue, 2021-10-12 at 15:40 +0200, Emil Renner Berthing wrote:
> > 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 | 164 ++++++++++++++++++++++++++
> >  4 files changed, 180 insertions(+)
> >  create mode 100644 drivers/reset/reset-starfive-jh7100.c
> >
> [...]
> > diff --git a/drivers/reset/reset-starfive-jh7100.c b/drivers/reset/reset-starfive-jh7100.c
> > new file mode 100644
> > index 000000000000..26bc5b59c1f3
> > --- /dev/null
> > +++ b/drivers/reset/reset-starfive-jh7100.c
> > @@ -0,0 +1,164 @@
> [...]
> > +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;
> > +
> > +     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);
> > +
> > +     do {
> > +             value = readl(reg_status) & mask;
> > +     } while (value != done);
>
> Looking at the barebox driver, this could loop indefinitely if the
> caller forgets to enable the corresponding peripheral clock. Maybe
> use readl_poll_timeout() as a safety net.

You're right. Asserting without the clock enabled is fine, but
deasserting will hang forever. At least for the temperature sensor
clock/resets I tried it with. I'll add the timeout, thanks!

/Emil

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

* Re: [PATCH v1 01/16] RISC-V: Add StarFive SoC Kconfig option
  2021-10-12 13:40 ` [PATCH v1 01/16] RISC-V: Add StarFive SoC Kconfig option Emil Renner Berthing
@ 2021-10-12 18:20   ` Andy Shevchenko
  0 siblings, 0 replies; 49+ messages in thread
From: Andy Shevchenko @ 2021-10-12 18:20 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, Anup Patel,
	Atish Patra, Matteo Croce, Linux Kernel Mailing List

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

...

> +       select SERIAL_8250_DW

Is it critical for boot? Why?

-- 
With Best Regards,
Andy Shevchenko

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

* Re: [PATCH v1 06/16] clk: starfive: Add JH7100 clock generator driver
  2021-10-12 13:40 ` [PATCH v1 06/16] clk: starfive: Add JH7100 clock generator driver Emil Renner Berthing
@ 2021-10-12 18:40   ` Andy Shevchenko
  2021-10-12 20:07     ` Emil Renner Berthing
  0 siblings, 1 reply; 49+ messages in thread
From: Andy Shevchenko @ 2021-10-12 18:40 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, Anup Patel,
	Atish Patra, Matteo Croce, Linux Kernel Mailing List

On Tue, Oct 12, 2021 at 4:42 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
>
> From: Geert Uytterhoeven <geert@linux-m68k.org>
>
> Add a driver for the StarFive JH7100 clock generator.

...

> +config CLK_STARFIVE_JH7100
> +       bool "StarFive JH7100 clock support"
> +       depends on SOC_STARFIVE || COMPILE_TEST

> +       depends on OF

Why? I haven't found a compile dependency, so you reduce the test
scope (when COMPILE_TEST=y).

...

You are using
bits.h
mod_devicetable.h
which are not here

> +#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/module.h>
> +#include <linux/overflow.h>
> +#include <linux/platform_device.h>

...

> +       value |= readl_relaxed(reg) & ~mask;

value is not masked, is it okay?

Usual pattern for this kind of operations is

value = (current & ~mask) | (value & mask);

> +       writel_relaxed(value, reg);

...

> +       if (div > max)
> +               div = max;
> +
> +       return div;

return min(div, max); ?

...

> +       rate = parent / div;
> +       if (rate < req->min_rate && div > 1) {
> +               div -= 1;
> +               rate = parent / div;
> +       }

Seems like homegrown DIV_ROUND_UP() or so. Who will guarantee that
decreasing div by 1 will satisfy the conditional again?

...

> +#ifdef CONFIG_DEBUG_FS

Perhaps __maybe_unused?

> +#else
> +#define jh7100_clk_debug_init NULL
> +#endif

...

> +       if (idx >= JH7100_CLK_END) {

> +               dev_err(priv->dev, "%s: invalid index %u\n", __func__, idx);

__func__ means that the message has no value on its own. Make it
unique without using __func__, or drop completely.

> +               return ERR_PTR(-EINVAL);
> +       }

...

> +       for (idx = 0; idx < JH7100_CLK_PLL0_OUT; idx++) {
> +               struct clk_init_data init = {
> +                       .name = jh7100_clk_data[idx].name,
> +                       .ops = jh7100_clk_data[idx].ops,

> +                       .num_parents = ((jh7100_clk_data[idx].max & JH7100_CLK_MUX_MASK)
> +                                       >> JH7100_CLK_MUX_SHIFT) + 1,

With temporary variable this can be better written, or consider
something like this

                       .num_parents =
                               ((jh7100_clk_data[idx].max &
JH7100_CLK_MUX_MASK) >> JH7100_CLK_MUX_SHIFT) + 1,

> +                       .flags = jh7100_clk_data[idx].flags,
> +               };
> +               struct jh7100_clk *clk = &priv->reg[idx];

...

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

The

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

is slightly better to read.

> +       return ret;
> +}

...

> +static int __init clk_starfive_jh7100_init(void)
> +{
> +       return platform_driver_probe(&clk_starfive_jh7100_driver,
> +                                    clk_starfive_jh7100_probe);
> +}

> +

No need to have this blank line.
> +subsys_initcall(clk_starfive_jh7100_init);

Any  explanation why subsys_initcall() is in use?

-- 
With Best Regards,
Andy Shevchenko

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

* Re: [PATCH v1 12/16] pinctrl: starfive: Add pinctrl driver for StarFive SoCs
  2021-10-12 13:40 ` [PATCH v1 12/16] pinctrl: starfive: Add pinctrl driver for StarFive SoCs Emil Renner Berthing
@ 2021-10-12 20:02   ` Andy Shevchenko
  2021-10-13 16:38     ` Emil Renner Berthing
  2021-10-18 15:35     ` Emil Renner Berthing
  0 siblings, 2 replies; 49+ messages in thread
From: Andy Shevchenko @ 2021-10-12 20:02 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, Anup Patel,
	Atish Patra, Matteo Croce, Linux Kernel Mailing List, Huan Feng

On Tue, Oct 12, 2021 at 4:43 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
> 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.

s/gpio/GPIO/g

...

> +config PINCTRL_STARFIVE

> +       bool "Pinctrl and GPIO driver for the StarFive JH7100 SoC"

Why not module?

> +       depends on SOC_STARFIVE || COMPILE_TEST

> +       depends on OF

Do you really need this taking into account...

> +       default SOC_STARFIVE
> +       select GENERIC_PINCTRL_GROUPS
> +       select GENERIC_PINMUX_FUNCTIONS
> +       select GENERIC_PINCONF
> +       select GPIOLIB
> +       select GPIOLIB_IRQCHIP

> +       select OF_GPIO

...this one?

...

bits.h ?

> +#include <linux/clk.h>
> +#include <linux/gpio/driver.h>
> +#include <linux/io.h>
> +#include <linux/module.h>


mod_devicetable.h ?

> +#include <linux/pinctrl/pinctrl.h>
> +#include <linux/pinctrl/pinmux.h>

Can you move these as a group after generic linux/* ones?

> +#include <linux/platform_device.h>
> +#include <linux/reset.h>
> +#include <linux/spinlock.h>

...

> +/*
> + * refer to Section 12. GPIO Registers in JH7100 datasheet:

Be consistent in your style, here for example missed capitalization.

> + * https://github.com/starfive-tech/StarLight_Docs

Is it possible to have the datasheet to be provided as Datasheet: tag
in the commit message?

> + */

...

> +/*
> + * Global enable for GPIO interrupts, offset: 0x0, field: GPIOEN
> + * set to 1 if GPIO interrupts are enabled, set to 0 to disable
> + */
> +#define IRQ_GLOBAL_EN          0x0

s/0x0/0x00/g

...

> +/*
> + * Interrupt Type for GPIO[31:0], offset: 0x10, field: GPIOS_0
> + * set to 1 if edge-triggered, set to 0 for level-triggered
> + */
> +#define IRQ_TYPE_LOW           0x10
> +
> +/*
> + * Interrupt Type for GPIO[63:32], offset: 0x14, field: GPIOS_1
> + */
> +#define IRQ_TYPE_HIGH          0x14

As I reviewed below, the IRQ is represented by a few registers in a
row, no need to define low and high separately. Ditto for the rest
register pairs.

...

> +/*
> + * Interrupt Status after Masking GPIO[31:0], offset: 0x40, field: GPIOMIS_0
> + * status of edge-triggered or level-triggered after masking
> + * value of 1 means edge or level was detected, value of 0 menas not detected

menas?!

> + */

...

> +/*
> + * Data Value of GPIO for GPIO[31:0], offest: 0x48, field: GPIODIN_0

offest?!

> + * dynamically reflects value on the GPIO pin
> + */

Please, run a spellchecker.

...

> +#define IO_PADSHARE_SEL                0x1a0

Okay, make all registers to be fixed width, i.e. 0x000 for IRQ global
enabling and so on.

...

> +#define PAD_SLEW_RATE_MASK             0xe00U

GENMASK()

> +#define PAD_BIAS_STRONG_PULL_UP                0x100U
> +#define PAD_INPUT_ENABLE               0x080U
> +#define PAD_INPUT_SCHMITT_ENABLE       0x040U
> +#define PAD_BIAS_DISABLE               0x020U
> +#define PAD_BIAS_PULL_DOWN             0x010U

All above seems like BIT(_something_).

> +#define PAD_BIAS_MASK                  0x130U
> +#define PAD_DRIVE_STRENGTH_MASK                0x007U

GENMASK()

...

> +#ifdef CONFIG_DEBUG_FS

__maybe_unused ?

> +#else
> +#define starfive_pin_dbg_show NULL
> +#endif

...

> +       dout = readl_relaxed(reg);

readl_relaxed(reg + 0x00)

> +       reg += 4;

> +       doen = readl_relaxed(reg);

readl_relaxed(reg + 0x04);

...

> +       seq_printf(s, "dout=%u%s doen=%u%s",
> +                  dout & 0xffU, (dout & 0x80000000U) ? "r" : "",
> +                  doen & 0xffU, (doen & 0x80000000U) ? "r" : "");

GENMASK()
BIT()

...

> +       for_each_child_of_node(np, child) {
> +               const __be32 *pinmux_list;
> +               const __be32 *pins_list;
> +               int pinmux_size;
> +               int pins_size;
> +
> +               pinmux_list = of_get_property(child, "pinmux", &pinmux_size);
> +               pins_list   = of_get_property(child, "pins",   &pins_size);
> +               if (pinmux_list && pins_list) {
> +                       dev_err(dev, "invalid pinctrl group %pOFn.%pOFn: %s\n",
> +                               np, child, "both pinmux and pins set");
> +                       of_node_put(child);
> +                       return -EINVAL;
> +               }
> +
> +               if (pinmux_list && pinmux_size > 0) {
> +                       nmaps += 2;
> +               } else if (pins_list && pins_size > 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;
> +       }

This entire loop seems like
1) it should be based on something from pin control core;
2) it's using some low level APIs instead of better ones like
of_property_read_uXX();
3) smells like unoptimized NIH.

...

> +               if ((list = of_get_property(child, "pinmux", &npins))) {

Why not of_property_read_...() ?

...

> +                               u32 v = be32_to_cpu(*list++);

My gosh!

...

> +                       for (i = 0; i < npins; i++)
> +                               pins[i] = be32_to_cpu(*list++);

Ditto.
Even for this we have something in byteorder headers.

Summary, make sure you use much better _existing_ APIs instead of the
above crap.

...

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

What the heck?!

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

Ditto.

...

> +out:

Useless label.

> +       return ret;

...

> +       for (i = 0; i < group->num_pins; i++) {
> +               unsigned int gpio = starfive_pin_to_gpio(sfp, group->pins[i]);
> +               void __iomem *reg_dout;
> +               void __iomem *reg_doen;
> +               void __iomem *reg_din;
> +               u32 v, dout, doen, din;
> +               unsigned long flags;

> +               if (dev_WARN_ONCE(dev, gpio >= MAX_GPIO,

What?!

> +                                 "%s: invalid gpiomux pin", group->name))
> +                       continue;
> +
> +               v = pinmux[i];
> +               dout = ((v & BIT(7)) << (31 - 7)) | ((v >> 24) & 0xffU);
> +               doen = ((v & BIT(6)) << (31 - 6)) | ((v >> 16) & 0xffU);
> +               din  = (v >> 8) & 0xffU;

What is this voodoo for?

> +               if (din != 0xff)
> +                       reg_din = sfp->base + GPIO_IN_OFFSET + 4 * din;
> +               else
> +                       reg_din = NULL;

This looks like you maybe use gpio-regmap instead?

...

> +       void __iomem *reg = sfp->padctl + 4 * (pin / 2);
> +       u32 value = readl_relaxed(reg);
> +
> +       if (pin & 1U)
> +               value >>= 16;
> +       return value;

u8 shift = 16 * (pin % 2);

return readl_relaxed() >> shift;

?

Something similar for below code.

...

> +#ifdef CONFIG_DEBUG_FS
> +static const struct pin_config_item
> +starfive_pinconf_custom_conf_items[ARRAY_SIZE(starfive_pinconf_custom_params)] = {

Instead of using ARAY_SIZE() here, use static_assert().

__maybe_unused?

> +       PCONFDUMP(PIN_CONFIG_STARFIVE_STRONG_PULL_UP, "input bias strong pull-up", NULL, false),
> +};
> +#else
> +#define starfive_pinconf_custom_conf_items NULL
> +#endif

...

> +static const unsigned char starfive_drive_strength[] = {
> +       14, 21, 28, 35, 42, 49, 56, 63,

Why table? Can you simply use the formula?!

> +};

...

> +       if (unlikely(!group))

Why unlikely() Must be justified here and everywhere where you are using it.

> +               return -EINVAL;
> +
> +       return starfive_pinconf_get(pctldev, group->pins[0], config);
> +}

...

> +               case PIN_CONFIG_BIAS_DISABLE:

> +                       mask |= PAD_BIAS_MASK;

Use it...

> +                       value = (value & ~PAD_BIAS_MASK) | PAD_BIAS_DISABLE;

...here. Ditto for the similar cases in this function and elsewhere.

After done this, you will see how you can simplify and deduplicate the
switch-cases.

...

> +#ifdef CONFIG_DEBUG_FS

__maybe_unused ?

> +#else
> +#define starfive_pinconf_dbg_show NULL
> +#endif

...

> +       if (gpio < 32) {
> +               value = readl_relaxed(sfp->base + GPIO_DIN_LOW);

> +               value = (value >> gpio) & 1U;

Drop

> +       } else {
> +               value = readl_relaxed(sfp->base + GPIO_DIN_HIGH);

> +               value = (value >> (gpio - 32)) & 1U;

Drop

> +       }

> +       return value;

return !!(value & BIT(gpio % 32));

...

> +               if (arg == 0)

> +                       return -ENOTSUPP;

Shouldn't we return something else and pin control core will change it
to something else if needed?

> +               if (arg == 0)
> +                       return -ENOTSUPP;

Ditto.

> +       default:
> +               return -ENOTSUPP;

...

> +       if (gpio < 0 || gpio >= MAX_GPIO)
> +               return;
> +
> +       if (gpio < 32) {
> +               ie = sfp->base + IRQ_ENABLE_LOW;
> +               mask = BIT(gpio);
> +       } else {
> +               ie = sfp->base + IRQ_ENABLE_HIGH;
> +               mask = BIT(gpio - 32);
> +       }

See below. And update all occurrences of these lines accordingly and
everywhere. Also for IRQ may use helper functions if needed (but I
don't believe the high and low register have stride more than 4).

...

> +       if (gpio < 0 || gpio >= MAX_GPIO)
> +               return -EINVAL;

How is it possible to be ever triggered?

...

> +       if (gpio < 32) {
> +               base = sfp->base;
> +               mask = BIT(gpio);
> +       } else {
> +               base = sfp->base + 4;
> +               mask = BIT(gpio - 32);
> +       }

base = sfp_base + 4 * (gpio / 32);
mask = BIT(gpio % 32);

...

> +               irq_set_handler_locked(d, handle_edge_irq);

> +               irq_set_handler_locked(d, handle_edge_irq);

Dup.

...

> +               irq_set_handler_locked(d, handle_edge_irq);

> +               irq_set_handler_locked(d, handle_level_irq);

> +               irq_set_handler_locked(d, handle_level_irq);

Ditto.

...

> +               irq_set_handler_locked(d, handle_bad_irq);

Why is this here? Move it to ->probe().

...

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

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

Thank you for spamming logs with this noise.

> +               return ret;

Hint: return dev_err_probe(). Ditto for the rest in this function.

> +       }

...

> +       ret = clk_prepare_enable(clk);
> +       if (ret) {

> +               reset_control_deassert(rst);

Use devm_add_action_or_reset().

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

...

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

Can be refactored without conditional. Also, why not to use
device_property_read_u32()?

> +               if (value <= 6)
> +                       writel(value, sfp->padctl + IO_PADSHARE_SEL);
> +               else

> +                       dev_err(dev, "invalid signal group %u\n", value);

Why _err if you not bail out here?

> +       }

...

> +       value = readl(sfp->padctl + IO_PADSHARE_SEL);
> +       switch (value) {
> +       case 0:
> +               sfp->gpios.pin_base = 0x10000;

Magic number!

> +               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.of_node = dev->of_node;

Isn't GPIO library do this for you?

...

> +       starfive_irq_chip.parent_device = dev;

Ditto?

...

> +       sfp->gc.irq.parents =
> +               devm_kcalloc(dev, 1, sizeof(*sfp->gc.irq.parents), GFP_KERNEL);

1 -> sfp->gc.irq.num_parents
And hence move below line up.

> +       if (!sfp->gc.irq.parents)
> +               return -ENOMEM;

> +       sfp->gc.irq.num_parents = 1;

...

> +       dev_info(dev, "StarFive GPIO chip registered %d GPIOs\n", sfp->gc.ngpio);

Redundant noise.

...

> +static const struct of_device_id starfive_of_match[] = {
> +       { .compatible = "starfive,jh7100-pinctrl" },

> +       { /* sentinel */ },

No comma needed for terminator entry.

> +};

-- 
With Best Regards,
Andy Shevchenko

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

* Re: [PATCH v1 06/16] clk: starfive: Add JH7100 clock generator driver
  2021-10-12 18:40   ` Andy Shevchenko
@ 2021-10-12 20:07     ` Emil Renner Berthing
  2021-10-12 21:20       ` Andy Shevchenko
  0 siblings, 1 reply; 49+ messages in thread
From: Emil Renner Berthing @ 2021-10-12 20:07 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, Anup Patel,
	Atish Patra, Matteo Croce, Linux Kernel Mailing List

On Tue, 12 Oct 2021 at 17:40, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
>
> On Tue, Oct 12, 2021 at 4:42 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> >
> > From: Geert Uytterhoeven <geert@linux-m68k.org>
> >
> > Add a driver for the StarFive JH7100 clock generator.
>
> ...
>
> > +config CLK_STARFIVE_JH7100
> > +       bool "StarFive JH7100 clock support"
> > +       depends on SOC_STARFIVE || COMPILE_TEST
>
> > +       depends on OF
>
> Why? I haven't found a compile dependency, so you reduce the test
> scope (when COMPILE_TEST=y).

My thinking was that it can't ever be loaded on a !OF system, but
you're right it'll just restrict compile testing. I'll remove, thanks.

> ...
>
> You are using
> bits.h
> mod_devicetable.h
> which are not here
>
> > +#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/module.h>
> > +#include <linux/overflow.h>
> > +#include <linux/platform_device.h>
>
> ...
>
> > +       value |= readl_relaxed(reg) & ~mask;
>
> value is not masked, is it okay?
>
> Usual pattern for this kind of operations is
>
> value = (current & ~mask) | (value & mask);

This function is only ever called with constants, already masked
values or the parent number from the clk framework, so it should be
ok.

> > +       writel_relaxed(value, reg);
>
> ...
>
> > +       if (div > max)
> > +               div = max;
> > +
> > +       return div;
>
> return min(div, max); ?
>
> ...
>
> > +       rate = parent / div;
> > +       if (rate < req->min_rate && div > 1) {
> > +               div -= 1;
> > +               rate = parent / div;
> > +       }
>
> Seems like homegrown DIV_ROUND_UP() or so. Who will guarantee that
> decreasing div by 1 will satisfy the conditional again?

Maths unless I'm mistaken: div = DIV_ROUND_UP(parent, target), so in
rational numbers
  div - 1 < parent / target
But the target is clamped by min_rate and max_rate, so
  min_rate <= target < parent / (div - 1) = rate

Sorry, re-using the rate varable for both the target and result is
confusing. I'll fix that.

> ...
>
> > +#ifdef CONFIG_DEBUG_FS
>
> Perhaps __maybe_unused?

I can definitely use __maybe_unused for the function declaration, but
then I'll need a conditional every time clk_ops.debug_init needs to be
initialized to either the function or NULL depending on
CONFIG_DEBUG_FS below. Is that better?

> > +#else
> > +#define jh7100_clk_debug_init NULL
> > +#endif
>
> ...
>
> > +       if (idx >= JH7100_CLK_END) {
>
> > +               dev_err(priv->dev, "%s: invalid index %u\n", __func__, idx);
>
> __func__ means that the message has no value on its own. Make it
> unique without using __func__, or drop completely.
>
> > +               return ERR_PTR(-EINVAL);
> > +       }
>
> ...
>
> > +       for (idx = 0; idx < JH7100_CLK_PLL0_OUT; idx++) {
> > +               struct clk_init_data init = {
> > +                       .name = jh7100_clk_data[idx].name,
> > +                       .ops = jh7100_clk_data[idx].ops,
>
> > +                       .num_parents = ((jh7100_clk_data[idx].max & JH7100_CLK_MUX_MASK)
> > +                                       >> JH7100_CLK_MUX_SHIFT) + 1,
>
> With temporary variable this can be better written, or consider
> something like this
>
>                        .num_parents =
>                                ((jh7100_clk_data[idx].max &
> JH7100_CLK_MUX_MASK) >> JH7100_CLK_MUX_SHIFT) + 1,
>
> > +                       .flags = jh7100_clk_data[idx].flags,
> > +               };
> > +               struct jh7100_clk *clk = &priv->reg[idx];
>
> ...
>
> > +       while (idx > 0)
> > +               clk_hw_unregister(&priv->reg[--idx].hw);
>
> The
>
>        while (idx--)
>                clk_hw_unregister(&priv->reg[idx].hw);
>
> is slightly better to read.

It's not something I'll insist hard on, but I must admit I disagree.
To me the above looks like cartoon characters running off a cliff and
back. As a middle ground could we maybe do this?

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

> > +       return ret;
> > +}
>
> ...
>
> > +static int __init clk_starfive_jh7100_init(void)
> > +{
> > +       return platform_driver_probe(&clk_starfive_jh7100_driver,
> > +                                    clk_starfive_jh7100_probe);
> > +}
>
> > +
>
> No need to have this blank line.
> > +subsys_initcall(clk_starfive_jh7100_init);
>
> Any  explanation why subsys_initcall() is in use?

TBH I just inherited that from Geert's first mock driver and never
thought to question it. What would be a better alternative to try?

Thanks!
/Emil

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

* Re: [PATCH v1 14/16] serial: 8250_dw: Add skip_clk_set_rate quirk
  2021-10-12 13:40 ` [PATCH v1 14/16] serial: 8250_dw: Add skip_clk_set_rate quirk Emil Renner Berthing
@ 2021-10-12 20:08   ` Andy Shevchenko
  0 siblings, 0 replies; 49+ messages in thread
From: Andy Shevchenko @ 2021-10-12 20:08 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, Anup Patel,
	Atish Patra, Matteo Croce, Linux Kernel Mailing List

On Tue, Oct 12, 2021 at 4:43 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
>
> 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.

s/uart/UART/g

...

>         unsigned int            skip_autocfg:1;
>         unsigned int            uart_16550_compatible:1;
> +       unsigned int            skip_clk_set_rate:1;

Keep skip_* bitfields grouped.

...

> +       if (!d->skip_clk_set_rate) {

I believe you have to rebase this patch on top of tty/tty-next.
Besides that, please, avoid indentation changes, i.e. refactor your
patch accordgingly.

>         }

-- 
With Best Regards,
Andy Shevchenko

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

* Re: [PATCH v1 06/16] clk: starfive: Add JH7100 clock generator driver
  2021-10-12 20:07     ` Emil Renner Berthing
@ 2021-10-12 21:20       ` Andy Shevchenko
  2021-10-12 21:26         ` Emil Renner Berthing
  0 siblings, 1 reply; 49+ messages in thread
From: Andy Shevchenko @ 2021-10-12 21:20 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, Anup Patel,
	Atish Patra, Matteo Croce, Linux Kernel Mailing List

On Tue, Oct 12, 2021 at 11:08 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> On Tue, 12 Oct 2021 at 17:40, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > On Tue, Oct 12, 2021 at 4:42 PM Emil Renner Berthing <kernel@esmil.dk> wrote:

...

> > > +       value |= readl_relaxed(reg) & ~mask;
> >
> > value is not masked, is it okay?
> >
> > Usual pattern for this kind of operations is
> >
> > value = (current & ~mask) | (value & mask);
>
> This function is only ever called with constants, already masked
> values or the parent number from the clk framework, so it should be
> ok.

Up to you, but I think it's better to have a usual pattern.

> > > +       writel_relaxed(value, reg);

...

> > > +       rate = parent / div;
> > > +       if (rate < req->min_rate && div > 1) {
> > > +               div -= 1;
> > > +               rate = parent / div;
> > > +       }
> >
> > Seems like homegrown DIV_ROUND_UP() or so. Who will guarantee that
> > decreasing div by 1 will satisfy the conditional again?
>
> Maths unless I'm mistaken: div = DIV_ROUND_UP(parent, target), so in
> rational numbers
>   div - 1 < parent / target
> But the target is clamped by min_rate and max_rate, so
>   min_rate <= target < parent / (div - 1) = rate
>
> Sorry, re-using the rate varable for both the target and result is
> confusing. I'll fix that.

Also needs a comment, I believe.

...

> > > +#ifdef CONFIG_DEBUG_FS
> >
> > Perhaps __maybe_unused?
>
> I can definitely use __maybe_unused for the function declaration, but
> then I'll need a conditional every time clk_ops.debug_init needs to be
> initialized to either the function or NULL depending on
> CONFIG_DEBUG_FS below. Is that better?

Actually, why can't you always initialize the field? Shouldn't CLK
core take care about this conditional?

> > > +#else
> > > +#define jh7100_clk_debug_init NULL
> > > +#endif

...

> > > +       while (idx > 0)
> > > +               clk_hw_unregister(&priv->reg[--idx].hw);
> >
> > The
> >
> >        while (idx--)
> >                clk_hw_unregister(&priv->reg[idx].hw);
> >
> > is slightly better to read.
>
> It's not something I'll insist hard on, but I must admit I disagree.
> To me the above looks like cartoon characters running off a cliff and
> back. As a middle ground could we maybe do this?
>
>   while (idx)
>     clk_hw_unregister(&priv->reg[--idx].hw);

My point is exactly in having the common pattern for error paths, i.e.

  while (counter--)
    ...bla-bla-bla...

Your second approach is better, but I think that proposed by me is even better.

...

> > > +subsys_initcall(clk_starfive_jh7100_init);
> >
> > Any  explanation why subsys_initcall() is in use?
>
> TBH I just inherited that from Geert's first mock driver and never
> thought to question it. What would be a better alternative to try?

At least add a comment to explain the choice.

-- 
With Best Regards,
Andy Shevchenko

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

* Re: [PATCH v1 06/16] clk: starfive: Add JH7100 clock generator driver
  2021-10-12 21:20       ` Andy Shevchenko
@ 2021-10-12 21:26         ` Emil Renner Berthing
  0 siblings, 0 replies; 49+ messages in thread
From: Emil Renner Berthing @ 2021-10-12 21:26 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, Anup Patel,
	Atish Patra, Matteo Croce, Linux Kernel Mailing List

On Tue, 12 Oct 2021 at 23:21, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
>
> On Tue, Oct 12, 2021 at 11:08 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> > On Tue, 12 Oct 2021 at 17:40, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > > On Tue, Oct 12, 2021 at 4:42 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
>
> ...
>
> > > > +       value |= readl_relaxed(reg) & ~mask;
> > >
> > > value is not masked, is it okay?
> > >
> > > Usual pattern for this kind of operations is
> > >
> > > value = (current & ~mask) | (value & mask);
> >
> > This function is only ever called with constants, already masked
> > values or the parent number from the clk framework, so it should be
> > ok.
>
> Up to you, but I think it's better to have a usual pattern.
>
> > > > +       writel_relaxed(value, reg);
>
> ...
>
> > > > +       rate = parent / div;
> > > > +       if (rate < req->min_rate && div > 1) {
> > > > +               div -= 1;
> > > > +               rate = parent / div;
> > > > +       }
> > >
> > > Seems like homegrown DIV_ROUND_UP() or so. Who will guarantee that
> > > decreasing div by 1 will satisfy the conditional again?
> >
> > Maths unless I'm mistaken: div = DIV_ROUND_UP(parent, target), so in
> > rational numbers
> >   div - 1 < parent / target
> > But the target is clamped by min_rate and max_rate, so
> >   min_rate <= target < parent / (div - 1) = rate
> >
> > Sorry, re-using the rate varable for both the target and result is
> > confusing. I'll fix that.
>
> Also needs a comment, I believe.

Will add.

> ...
>
> > > > +#ifdef CONFIG_DEBUG_FS
> > >
> > > Perhaps __maybe_unused?
> >
> > I can definitely use __maybe_unused for the function declaration, but
> > then I'll need a conditional every time clk_ops.debug_init needs to be
> > initialized to either the function or NULL depending on
> > CONFIG_DEBUG_FS below. Is that better?
>
> Actually, why can't you always initialize the field? Shouldn't CLK
> core take care about this conditional?

It could, but I see other drivers avoiding the code bloat when debugfs
is not enabled, so I thought I'd copy that.

> > > > +#else
> > > > +#define jh7100_clk_debug_init NULL
> > > > +#endif
>
> ...
>
> > > > +       while (idx > 0)
> > > > +               clk_hw_unregister(&priv->reg[--idx].hw);
> > >
> > > The
> > >
> > >        while (idx--)
> > >                clk_hw_unregister(&priv->reg[idx].hw);
> > >
> > > is slightly better to read.
> >
> > It's not something I'll insist hard on, but I must admit I disagree.
> > To me the above looks like cartoon characters running off a cliff and
> > back. As a middle ground could we maybe do this?
> >
> >   while (idx)
> >     clk_hw_unregister(&priv->reg[--idx].hw);
>
> My point is exactly in having the common pattern for error paths, i.e.
>
>   while (counter--)
>     ...bla-bla-bla...
>
> Your second approach is better, but I think that proposed by me is even better.
>
> ...
>
> > > > +subsys_initcall(clk_starfive_jh7100_init);
> > >
> > > Any  explanation why subsys_initcall() is in use?
> >
> > TBH I just inherited that from Geert's first mock driver and never
> > thought to question it. What would be a better alternative to try?
>
> At least add a comment to explain the choice.
>
> --
> With Best Regards,
> Andy Shevchenko

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

* Re: [PATCH v1 02/16] dt-bindings: timer: Add StarFive JH7100 clint
  2021-10-12 13:40 ` [PATCH v1 02/16] dt-bindings: timer: Add StarFive JH7100 clint Emil Renner Berthing
@ 2021-10-13  7:05   ` Geert Uytterhoeven
  2021-10-19 22:48   ` Rob Herring
  1 sibling, 0 replies; 49+ messages in thread
From: Geert Uytterhoeven @ 2021-10-13  7:05 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, Anup Patel, Atish Patra, Matteo Croce,
	Linux Kernel Mailing List

On Tue, Oct 12, 2021 at 3:41 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> 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>

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] 49+ messages in thread

* Re: [PATCH v1 03/16] dt-bindings: interrupt-controller: Add StarFive JH7100 plic
  2021-10-12 13:40 ` [PATCH v1 03/16] dt-bindings: interrupt-controller: Add StarFive JH7100 plic Emil Renner Berthing
@ 2021-10-13  7:05   ` Geert Uytterhoeven
  0 siblings, 0 replies; 49+ messages in thread
From: Geert Uytterhoeven @ 2021-10-13  7:05 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, Anup Patel, Atish Patra, Matteo Croce,
	Linux Kernel Mailing List

On Tue, Oct 12, 2021 at 3:41 PM Emil Renner Berthing <kernel@esmil.dk> 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>

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] 49+ messages in thread

* Re: [PATCH v1 13/16] dt-bindings: serial: snps-dw-apb-uart: Add JH7100 uarts
  2021-10-12 13:40 ` [PATCH v1 13/16] dt-bindings: serial: snps-dw-apb-uart: Add JH7100 uarts Emil Renner Berthing
@ 2021-10-13  7:09   ` Geert Uytterhoeven
  0 siblings, 0 replies; 49+ messages in thread
From: Geert Uytterhoeven @ 2021-10-13  7:09 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, Anup Patel, Atish Patra, Matteo Croce,
	Linux Kernel Mailing List

On Tue, Oct 12, 2021 at 3:42 PM Emil Renner Berthing <kernel@esmil.dk> 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>

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] 49+ messages in thread

* Re: [PATCH v1 12/16] pinctrl: starfive: Add pinctrl driver for StarFive SoCs
  2021-10-12 20:02   ` Andy Shevchenko
@ 2021-10-13 16:38     ` Emil Renner Berthing
  2021-10-13 19:55       ` Andy Shevchenko
  2021-10-18 15:35     ` Emil Renner Berthing
  1 sibling, 1 reply; 49+ messages in thread
From: Emil Renner Berthing @ 2021-10-13 16:38 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, Anup Patel,
	Atish Patra, Matteo Croce, Linux Kernel Mailing List, Huan Feng

On Tue, 12 Oct 2021 at 19:03, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> On Tue, Oct 12, 2021 at 4:43 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
> > 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.
>
> s/gpio/GPIO/g
>
> ...
>
> > +config PINCTRL_STARFIVE
>
> > +       bool "Pinctrl and GPIO driver for the StarFive JH7100 SoC"
>
> Why not module?
>
> > +       depends on SOC_STARFIVE || COMPILE_TEST
>
> > +       depends on OF
>
> Do you really need this taking into account...
>
> > +       default SOC_STARFIVE
> > +       select GENERIC_PINCTRL_GROUPS
> > +       select GENERIC_PINMUX_FUNCTIONS
> > +       select GENERIC_PINCONF
> > +       select GPIOLIB
> > +       select GPIOLIB_IRQCHIP
>
> > +       select OF_GPIO
>
> ...this one?
>
> ...
>
> bits.h ?
>
> > +#include <linux/clk.h>
> > +#include <linux/gpio/driver.h>
> > +#include <linux/io.h>
> > +#include <linux/module.h>
>
>
> mod_devicetable.h ?
>
> > +#include <linux/pinctrl/pinctrl.h>
> > +#include <linux/pinctrl/pinmux.h>
>
> Can you move these as a group after generic linux/* ones?
>
> > +#include <linux/platform_device.h>
> > +#include <linux/reset.h>
> > +#include <linux/spinlock.h>
>
> ...
>
> > +/*
> > + * refer to Section 12. GPIO Registers in JH7100 datasheet:
>
> Be consistent in your style, here for example missed capitalization.
>
> > + * https://github.com/starfive-tech/StarLight_Docs
>
> Is it possible to have the datasheet to be provided as Datasheet: tag
> in the commit message?

Oh neat. Didn't know about that. I'll also check with StarFive if this
is the best address for it.

> > + */
>
> ...
>
> > +/*
> > + * Global enable for GPIO interrupts, offset: 0x0, field: GPIOEN
> > + * set to 1 if GPIO interrupts are enabled, set to 0 to disable
> > + */
> > +#define IRQ_GLOBAL_EN          0x0
>
> s/0x0/0x00/g
>
> ...
>
> > +/*
> > + * Interrupt Type for GPIO[31:0], offset: 0x10, field: GPIOS_0
> > + * set to 1 if edge-triggered, set to 0 for level-triggered
> > + */
> > +#define IRQ_TYPE_LOW           0x10
> > +
> > +/*
> > + * Interrupt Type for GPIO[63:32], offset: 0x14, field: GPIOS_1
> > + */
> > +#define IRQ_TYPE_HIGH          0x14
>
> As I reviewed below, the IRQ is represented by a few registers in a
> row, no need to define low and high separately. Ditto for the rest
> register pairs.
>
> ...
>
> > +/*
> > + * Interrupt Status after Masking GPIO[31:0], offset: 0x40, field: GPIOMIS_0
> > + * status of edge-triggered or level-triggered after masking
> > + * value of 1 means edge or level was detected, value of 0 menas not detected
>
> menas?!
>
> > + */
>
> ...
>
> > +/*
> > + * Data Value of GPIO for GPIO[31:0], offest: 0x48, field: GPIODIN_0
>
> offest?!
>
> > + * dynamically reflects value on the GPIO pin
> > + */
>
> Please, run a spellchecker.
>
> ...
>
> > +#define IO_PADSHARE_SEL                0x1a0
>
> Okay, make all registers to be fixed width, i.e. 0x000 for IRQ global
> enabling and so on.
>
> ...
>
> > +#define PAD_SLEW_RATE_MASK             0xe00U
>
> GENMASK()
>
> > +#define PAD_BIAS_STRONG_PULL_UP                0x100U
> > +#define PAD_INPUT_ENABLE               0x080U
> > +#define PAD_INPUT_SCHMITT_ENABLE       0x040U
> > +#define PAD_BIAS_DISABLE               0x020U
> > +#define PAD_BIAS_PULL_DOWN             0x010U
>
> All above seems like BIT(_something_).
>
> > +#define PAD_BIAS_MASK                  0x130U
> > +#define PAD_DRIVE_STRENGTH_MASK                0x007U
>
> GENMASK()
>
> ...
>
> > +#ifdef CONFIG_DEBUG_FS
>
> __maybe_unused ?

This is the same as the clock driver. If we don't have the ifdef here
we'll need it when populating the ops structure later or live with the
code bloat when debugfs is not enabled. Other driver don't seem to do
that.

> > +#else
> > +#define starfive_pin_dbg_show NULL
> > +#endif
>
> ...
>
> > +       dout = readl_relaxed(reg);
>
> readl_relaxed(reg + 0x00)
>
> > +       reg += 4;
>
> > +       doen = readl_relaxed(reg);
>
> readl_relaxed(reg + 0x04);
>
> ...
>
> > +       seq_printf(s, "dout=%u%s doen=%u%s",
> > +                  dout & 0xffU, (dout & 0x80000000U) ? "r" : "",
> > +                  doen & 0xffU, (doen & 0x80000000U) ? "r" : "");
>
> GENMASK()
> BIT()
>
> ...
>
> > +       for_each_child_of_node(np, child) {
> > +               const __be32 *pinmux_list;
> > +               const __be32 *pins_list;
> > +               int pinmux_size;
> > +               int pins_size;
> > +
> > +               pinmux_list = of_get_property(child, "pinmux", &pinmux_size);
> > +               pins_list   = of_get_property(child, "pins",   &pins_size);
> > +               if (pinmux_list && pins_list) {
> > +                       dev_err(dev, "invalid pinctrl group %pOFn.%pOFn: %s\n",
> > +                               np, child, "both pinmux and pins set");
> > +                       of_node_put(child);
> > +                       return -EINVAL;
> > +               }
> > +
> > +               if (pinmux_list && pinmux_size > 0) {
> > +                       nmaps += 2;
> > +               } else if (pins_list && pins_size > 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;
> > +       }
>
> This entire loop seems like
> 1) it should be based on something from pin control core;
> 2) it's using some low level APIs instead of better ones like
> of_property_read_uXX();
> 3) smells like unoptimized NIH.
>
> ...
>
> > +               if ((list = of_get_property(child, "pinmux", &npins))) {
>
> Why not of_property_read_...() ?
>
> ...
>
> > +                               u32 v = be32_to_cpu(*list++);
>
> My gosh!
>
> ...
>
> > +                       for (i = 0; i < npins; i++)
> > +                               pins[i] = be32_to_cpu(*list++);
>
> Ditto.
> Even for this we have something in byteorder headers.
>
> Summary, make sure you use much better _existing_ APIs instead of the
> above crap.
>
> ...
>
> > +free_pinmux:
> > +       devm_kfree(dev, pinmux);
> > +free_pins:
> > +       devm_kfree(dev, pins);
> > +free_grpname:
> > +       devm_kfree(dev, grpname);
>
> What the heck?!

Just to be clear. You mean we don't need to explicitly free them
because they're tied to the device right? I don't think the device
will go away just because a single device tree entry can't be parsed,
so on such errors this garbage would be left behind. You can still
argue we shouldn't optimize for broken device trees, I just want to
make it at conscious decision.

> > +free_pgnames:
> > +       devm_kfree(dev, pgnames);
>
> Ditto.
>
> ...
>
> > +out:
>
> Useless label.

Hmm.. my compiler disagrees.

> > +       return ret;
>
> ...
>
> > +       for (i = 0; i < group->num_pins; i++) {
> > +               unsigned int gpio = starfive_pin_to_gpio(sfp, group->pins[i]);
> > +               void __iomem *reg_dout;
> > +               void __iomem *reg_doen;
> > +               void __iomem *reg_din;
> > +               u32 v, dout, doen, din;
> > +               unsigned long flags;
>
> > +               if (dev_WARN_ONCE(dev, gpio >= MAX_GPIO,
>
> What?!
>
> > +                                 "%s: invalid gpiomux pin", group->name))
> > +                       continue;
> > +
> > +               v = pinmux[i];
> > +               dout = ((v & BIT(7)) << (31 - 7)) | ((v >> 24) & 0xffU);
> > +               doen = ((v & BIT(6)) << (31 - 6)) | ((v >> 16) & 0xffU);
> > +               din  = (v >> 8) & 0xffU;
>
> What is this voodoo for?

In order to do pinmux we need the following pieces of information from
the device tree for each pin ("GPIO" they call it):

output signal: 0-133 + 1bit reverse flag
output enable signal: 0-133 + 1bit reverse flag
optional input signal: 0-74 + special "none" value, right now 0xff
gpio number: 0-63

As the code is now all that info is packed into a u32 for each pin
using the GPIOMUX macro defined in the dt-binding header added in
patch 10. There is also a diagram for how this packing is done. The
above voodoo is for unpacking that.

I'd very much like to hear if you have a better solution for how to
convey that information from the device tree to here.

> > +               if (din != 0xff)
> > +                       reg_din = sfp->base + GPIO_IN_OFFSET + 4 * din;
> > +               else
> > +                       reg_din = NULL;
>
> This looks like you maybe use gpio-regmap instead?

This was discussed at length when Drew sent in the GPIO part of this code:
https://lore.kernel.org/linux-riscv/20210701002037.912625-1-drew@beagleboard.org/
The conclusion was that because pinmux and controlling the pins from
software in GPIO mode uses the same registers it is better to do a
combined driver like this that can share the lock among other things.

> ...
>
> > +       void __iomem *reg = sfp->padctl + 4 * (pin / 2);
> > +       u32 value = readl_relaxed(reg);
> > +
> > +       if (pin & 1U)
> > +               value >>= 16;
> > +       return value;
>
> u8 shift = 16 * (pin % 2);
>
> return readl_relaxed() >> shift;
>
> ?
>
> Something similar for below code.
>
> ...
>
> > +#ifdef CONFIG_DEBUG_FS
> > +static const struct pin_config_item
> > +starfive_pinconf_custom_conf_items[ARRAY_SIZE(starfive_pinconf_custom_params)] = {
>
> Instead of using ARAY_SIZE() here, use static_assert().
>
> __maybe_unused?

As above.

> > +       PCONFDUMP(PIN_CONFIG_STARFIVE_STRONG_PULL_UP, "input bias strong pull-up", NULL, false),
> > +};
> > +#else
> > +#define starfive_pinconf_custom_conf_items NULL
> > +#endif
>
> ...
>
> > +static const unsigned char starfive_drive_strength[] = {
> > +       14, 21, 28, 35, 42, 49, 56, 63,
>
> Why table? Can you simply use the formula?!

Heh, yeah. So these are rounded values from a table and I never
noticed that after rounding they follow a nice arithmetic progression.
It'll probably still be nice to have an explanation in the comments
about the formula then.

> > +};
>
> ...
>
> > +       if (unlikely(!group))
>
> Why unlikely() Must be justified here and everywhere where you are using it.
>
> > +               return -EINVAL;
> > +
> > +       return starfive_pinconf_get(pctldev, group->pins[0], config);
> > +}
>
> ...
>
> > +               case PIN_CONFIG_BIAS_DISABLE:
>
> > +                       mask |= PAD_BIAS_MASK;
>
> Use it...
>
> > +                       value = (value & ~PAD_BIAS_MASK) | PAD_BIAS_DISABLE;
>
> ...here. Ditto for the similar cases in this function and elsewhere.
>
> After done this, you will see how you can simplify and deduplicate the
> switch-cases.
>
> ...
>
> > +#ifdef CONFIG_DEBUG_FS
>
> __maybe_unused ?
>
> > +#else
> > +#define starfive_pinconf_dbg_show NULL
> > +#endif
>
> ...
>
> > +       if (gpio < 32) {
> > +               value = readl_relaxed(sfp->base + GPIO_DIN_LOW);
>
> > +               value = (value >> gpio) & 1U;
>
> Drop
>
> > +       } else {
> > +               value = readl_relaxed(sfp->base + GPIO_DIN_HIGH);
>
> > +               value = (value >> (gpio - 32)) & 1U;
>
> Drop
>
> > +       }
>
> > +       return value;
>
> return !!(value & BIT(gpio % 32));
>
> ...
>
> > +               if (arg == 0)
>
> > +                       return -ENOTSUPP;
>
> Shouldn't we return something else and pin control core will change it
> to something else if needed?

The documentation include/linux/pinctrl/pinconf.h has rules for when
to return -ENOTSUPP and -EINVAL.

> > +               if (arg == 0)
> > +                       return -ENOTSUPP;
>
> Ditto.
>
> > +       default:
> > +               return -ENOTSUPP;
>
> ...
>
> > +       if (gpio < 0 || gpio >= MAX_GPIO)
> > +               return;
> > +
> > +       if (gpio < 32) {
> > +               ie = sfp->base + IRQ_ENABLE_LOW;
> > +               mask = BIT(gpio);
> > +       } else {
> > +               ie = sfp->base + IRQ_ENABLE_HIGH;
> > +               mask = BIT(gpio - 32);
> > +       }
>
> See below. And update all occurrences of these lines accordingly and
> everywhere. Also for IRQ may use helper functions if needed (but I
> don't believe the high and low register have stride more than 4).
>
> ...
>
> > +       if (gpio < 0 || gpio >= MAX_GPIO)
> > +               return -EINVAL;
>
> How is it possible to be ever triggered?
>
> ...
>
> > +       if (gpio < 32) {
> > +               base = sfp->base;
> > +               mask = BIT(gpio);
> > +       } else {
> > +               base = sfp->base + 4;
> > +               mask = BIT(gpio - 32);
> > +       }
>
> base = sfp_base + 4 * (gpio / 32);
> mask = BIT(gpio % 32);
>
> ...
>
> > +               irq_set_handler_locked(d, handle_edge_irq);
>
> > +               irq_set_handler_locked(d, handle_edge_irq);
>
> Dup.
>
> ...
>
> > +               irq_set_handler_locked(d, handle_edge_irq);
>
> > +               irq_set_handler_locked(d, handle_level_irq);
>
> > +               irq_set_handler_locked(d, handle_level_irq);
>
> Ditto.
>
> ...
>
> > +               irq_set_handler_locked(d, handle_bad_irq);
>
> Why is this here? Move it to ->probe().

My thinking was that if something tries to set a an unsupported irq
type, we should make sure the caller doesn't get spurious interrupts
because we left the handler at its old value.

> ...
>
> > +       clk = devm_clk_get(dev, NULL);
> > +       if (IS_ERR(clk)) {
> > +               ret = PTR_ERR(clk);
>
> > +               dev_err(dev, "could not get clock: %d\n", ret);
>
> Thank you for spamming logs with this noise.
>
> > +               return ret;
>
> Hint: return dev_err_probe(). Ditto for the rest in this function.
>
> > +       }
>
> ...
>
> > +       ret = clk_prepare_enable(clk);
> > +       if (ret) {
>
> > +               reset_control_deassert(rst);
>
> Use devm_add_action_or_reset().
>
> > +               dev_err(dev, "could not enable clock: %d\n", ret);
> > +               return ret;
> > +       }
>
> ...
>
> > +       if (!of_property_read_u32(dev->of_node, "starfive,signal-group", &value)) {
>
> Can be refactored without conditional. Also, why not to use
> device_property_read_u32()?
>
> > +               if (value <= 6)
> > +                       writel(value, sfp->padctl + IO_PADSHARE_SEL);
> > +               else
>
> > +                       dev_err(dev, "invalid signal group %u\n", value);
>
> Why _err if you not bail out here?

My thinking was that if the device tree specifies an invalid signal
group we should just leave the setting alone and not break booting,
but still be loud about it. Maybe that's too lenient and it's better
to crash and burn immediately if someone does that.

> > +       }
>
> ...
>
> > +       value = readl(sfp->padctl + IO_PADSHARE_SEL);
> > +       switch (value) {
> > +       case 0:
> > +               sfp->gpios.pin_base = 0x10000;
>
> Magic number!
>
> > +               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.of_node = dev->of_node;
>
> Isn't GPIO library do this for you?
>
> ...
>
> > +       starfive_irq_chip.parent_device = dev;
>
> Ditto?
>
> ...
>
> > +       sfp->gc.irq.parents =
> > +               devm_kcalloc(dev, 1, sizeof(*sfp->gc.irq.parents), GFP_KERNEL);
>
> 1 -> sfp->gc.irq.num_parents
> And hence move below line up.
>
> > +       if (!sfp->gc.irq.parents)
> > +               return -ENOMEM;
>
> > +       sfp->gc.irq.num_parents = 1;
>
> ...
>
> > +       dev_info(dev, "StarFive GPIO chip registered %d GPIOs\n", sfp->gc.ngpio);
>
> Redundant noise.
>
> ...
>
> > +static const struct of_device_id starfive_of_match[] = {
> > +       { .compatible = "starfive,jh7100-pinctrl" },
>
> > +       { /* sentinel */ },
>
> No comma needed for terminator entry.
>
> > +};
>
> --
> With Best Regards,
> Andy Shevchenko

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

* Re: [PATCH v1 12/16] pinctrl: starfive: Add pinctrl driver for StarFive SoCs
  2021-10-13 19:55       ` Andy Shevchenko
@ 2021-10-13 17:37         ` Emil Renner Berthing
  2021-10-13 17:50         ` Geert Uytterhoeven
  1 sibling, 0 replies; 49+ messages in thread
From: Emil Renner Berthing @ 2021-10-13 17:37 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, Anup Patel, Atish Patra,
	Matteo Croce, Linux Kernel Mailing List, Huan Feng

On Wed, 13 Oct 2021 at 18:59, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> On Wed, Oct 13, 2021 at 06:38:14PM +0200, Emil Renner Berthing wrote:
> > On Tue, 12 Oct 2021 at 19:03, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > > On Tue, Oct 12, 2021 at 4:43 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
>
> ...
>
> > > > +free_pinmux:
> > > > +       devm_kfree(dev, pinmux);
> > > > +free_pins:
> > > > +       devm_kfree(dev, pins);
> > > > +free_grpname:
> > > > +       devm_kfree(dev, grpname);
> > >
> > > What the heck?!
> >
> > Just to be clear. You mean we don't need to explicitly free them
> > because they're tied to the device right? I don't think the device
> > will go away just because a single device tree entry can't be parsed,
> > so on such errors this garbage would be left behind. You can still
> > argue we shouldn't optimize for broken device trees, I just want to
> > make it at conscious decision.
>
> If you are using devm_kfree() it is quite likely shows either of the following
> issues:
>
> * you mustn't use devm_*() in the first place due to object lifetime;
> * you shouldn't use devm_kfree() since this is the whole point of devm.

Hmm.. it seems like other drivers that dynamically builds the groups
and functions either also uses devm_kcalloc/devm_kfree like fx.
pinctrl-single or implements their own code to clean up groups and
functions when unloaded. There are no group destroy or function
destroy callbacks. I like devm_kcalloc/devm_kfree version better since
it's less code to write.

> > > > +free_pgnames:
> > > > +       devm_kfree(dev, pgnames);
> > >
> > > Ditto.
>
> ...
>
> > > > +out:
> > >
> > > Useless label.
> >
> > Hmm.. my compiler disagrees.
>
> The comment implies that you return directly instead of using `goto out;`.
>
> > > > +       return ret;
>
> ...
>
> > > > +               v = pinmux[i];
> > > > +               dout = ((v & BIT(7)) << (31 - 7)) | ((v >> 24) & 0xffU);
> > > > +               doen = ((v & BIT(6)) << (31 - 6)) | ((v >> 16) & 0xffU);
> > > > +               din  = (v >> 8) & 0xffU;
> > >
> > > What is this voodoo for?
> >
> > In order to do pinmux we need the following pieces of information from
> > the device tree for each pin ("GPIO" they call it):
> >
> > output signal: 0-133 + 1bit reverse flag
> > output enable signal: 0-133 + 1bit reverse flag
> > optional input signal: 0-74 + special "none" value, right now 0xff
> > gpio number: 0-63
> >
> > As the code is now all that info is packed into a u32 for each pin
> > using the GPIOMUX macro defined in the dt-binding header added in
> > patch 10. There is also a diagram for how this packing is done. The
> > above voodoo is for unpacking that.
> >
> > I'd very much like to hear if you have a better solution for how to
> > convey that information from the device tree to here.
>
> At very least this code should have something like above in the comment.

Will add!

> ...
>
> > > > +               if (din != 0xff)
> > > > +                       reg_din = sfp->base + GPIO_IN_OFFSET + 4 * din;
> > > > +               else
> > > > +                       reg_din = NULL;
> > >
> > > This looks like you maybe use gpio-regmap instead?
> >
> > This was discussed at length when Drew sent in the GPIO part of this code:
> > https://lore.kernel.org/linux-riscv/20210701002037.912625-1-drew@beagleboard.org/
> > The conclusion was that because pinmux and controlling the pins from
> > software in GPIO mode uses the same registers it is better to do a
> > combined driver like this that can share the lock among other things.
>
> And what does prevent exactly to base the GPIO part on gpio-regmap?

Other reasons are that gpio-regmap doesn't implement the .set_config
and .add_pin_ranges callbacks. add_pin_ranges is needed because the 64
GPIOs map to different pin numbers depending on the chosen "signal
group".

> ...
>
> > > > +static const unsigned char starfive_drive_strength[] = {
> > > > +       14, 21, 28, 35, 42, 49, 56, 63,
> > >
> > > Why table? Can you simply use the formula?!
> >
> > Heh, yeah. So these are rounded values from a table and I never
> > noticed that after rounding they follow a nice arithmetic progression.
> > It'll probably still be nice to have an explanation in the comments
> > about the formula then.
>
> Yup!
>
> > > > +};
>
> ...
>
> > > > +               irq_set_handler_locked(d, handle_bad_irq);
> > >
> > > Why is this here? Move it to ->probe().
> >
> > My thinking was that if something tries to set a an unsupported irq
> > type, we should make sure the caller doesn't get spurious interrupts
> > because we left the handler at its old value.
>
> You already assigned to this handler in the ->probe(), what's this then?

But userspace could fx. first request IRQ_TYPE_EDGE_BOTH through the
gpio api and later load a driver that might request an unsupported irq
type right? Or am I missing something.

> ...
>
> > > > +               if (value <= 6)
> > > > +                       writel(value, sfp->padctl + IO_PADSHARE_SEL);
> > > > +               else
> > >
> > > > +                       dev_err(dev, "invalid signal group %u\n", value);
> > >
> > > Why _err if you not bail out here?
> >
> > My thinking was that if the device tree specifies an invalid signal
> > group we should just leave the setting alone and not break booting,
> > but still be loud about it. Maybe that's too lenient and it's better
> > to crash and burn immediately if someone does that.
>
> Here is inconsistency between level of the message and following action.
> There are (rare!) cases when it's justified, but I believe it's not the
> case here. You have two choices or justify why you have to use error
> level without stopping process.
>
> ...
>
> All uncommented stuff you agreed on, correct?

Yes, thank you! (.. or at least I'll get back to you if something comes up ;)

>
> --
> 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] 49+ messages in thread

* Re: [PATCH v1 12/16] pinctrl: starfive: Add pinctrl driver for StarFive SoCs
  2021-10-13 19:55       ` Andy Shevchenko
  2021-10-13 17:37         ` Emil Renner Berthing
@ 2021-10-13 17:50         ` Geert Uytterhoeven
  1 sibling, 0 replies; 49+ messages in thread
From: Geert Uytterhoeven @ 2021-10-13 17:50 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, Jiri Slaby,
	Maximilian Luz, Sagar Kadam, Drew Fustini, Anup Patel,
	Atish Patra, Matteo Croce, Linux Kernel Mailing List, Huan Feng

On Wed, Oct 13, 2021 at 6:58 PM Andy Shevchenko
<andy.shevchenko@gmail.com> wrote:
> On Wed, Oct 13, 2021 at 06:38:14PM +0200, Emil Renner Berthing wrote:
> > On Tue, 12 Oct 2021 at 19:03, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > > On Tue, Oct 12, 2021 at 4:43 PM Emil Renner Berthing <kernel@esmil.dk> wrote:

> > > > +               v = pinmux[i];
> > > > +               dout = ((v & BIT(7)) << (31 - 7)) | ((v >> 24) & 0xffU);
> > > > +               doen = ((v & BIT(6)) << (31 - 6)) | ((v >> 16) & 0xffU);
> > > > +               din  = (v >> 8) & 0xffU;
> > >
> > > What is this voodoo for?
> >
> > In order to do pinmux we need the following pieces of information from
> > the device tree for each pin ("GPIO" they call it):
> >
> > output signal: 0-133 + 1bit reverse flag
> > output enable signal: 0-133 + 1bit reverse flag
> > optional input signal: 0-74 + special "none" value, right now 0xff
> > gpio number: 0-63
> >
> > As the code is now all that info is packed into a u32 for each pin
> > using the GPIOMUX macro defined in the dt-binding header added in
> > patch 10. There is also a diagram for how this packing is done. The
> > above voodoo is for unpacking that.
> >
> > I'd very much like to hear if you have a better solution for how to
> > convey that information from the device tree to here.
>
> At very least this code should have something like above in the comment.

And perhaps introduce some helper macros to access the fields?

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] 49+ messages in thread

* Re: [PATCH v1 04/16] dt-bindings: clock: starfive: Add JH7100 clock definitions
  2021-10-12 13:40 ` [PATCH v1 04/16] dt-bindings: clock: starfive: Add JH7100 clock definitions Emil Renner Berthing
@ 2021-10-13 18:39   ` Stephen Boyd
  0 siblings, 0 replies; 49+ messages in thread
From: Stephen Boyd @ 2021-10-13 18:39 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, Anup Patel, Atish Patra, Matteo Croce,
	linux-kernel

Quoting Emil Renner Berthing (2021-10-12 06:40:15)
> 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>

You need to add your Signed-off-by here.

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

* Re: [PATCH v1 12/16] pinctrl: starfive: Add pinctrl driver for StarFive SoCs
  2021-10-13 16:38     ` Emil Renner Berthing
@ 2021-10-13 19:55       ` Andy Shevchenko
  2021-10-13 17:37         ` Emil Renner Berthing
  2021-10-13 17:50         ` Geert Uytterhoeven
  0 siblings, 2 replies; 49+ messages in thread
From: Andy Shevchenko @ 2021-10-13 19: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, Jiri Slaby, Maximilian Luz, Sagar Kadam,
	Drew Fustini, Geert Uytterhoeven, Anup Patel, Atish Patra,
	Matteo Croce, Linux Kernel Mailing List, Huan Feng

On Wed, Oct 13, 2021 at 06:38:14PM +0200, Emil Renner Berthing wrote:
> On Tue, 12 Oct 2021 at 19:03, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > On Tue, Oct 12, 2021 at 4:43 PM Emil Renner Berthing <kernel@esmil.dk> wrote:

...

> > > +free_pinmux:
> > > +       devm_kfree(dev, pinmux);
> > > +free_pins:
> > > +       devm_kfree(dev, pins);
> > > +free_grpname:
> > > +       devm_kfree(dev, grpname);
> >
> > What the heck?!
> 
> Just to be clear. You mean we don't need to explicitly free them
> because they're tied to the device right? I don't think the device
> will go away just because a single device tree entry can't be parsed,
> so on such errors this garbage would be left behind. You can still
> argue we shouldn't optimize for broken device trees, I just want to
> make it at conscious decision.

If you are using devm_kfree() it is quite likely shows either of the following
issues:

* you mustn't use devm_*() in the first place due to object lifetime;
* you shouldn't use devm_kfree() since this is the whole point of devm.

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

...

> > > +out:
> >
> > Useless label.
> 
> Hmm.. my compiler disagrees.

The comment implies that you return directly instead of using `goto out;`.

> > > +       return ret;

...

> > > +               v = pinmux[i];
> > > +               dout = ((v & BIT(7)) << (31 - 7)) | ((v >> 24) & 0xffU);
> > > +               doen = ((v & BIT(6)) << (31 - 6)) | ((v >> 16) & 0xffU);
> > > +               din  = (v >> 8) & 0xffU;
> >
> > What is this voodoo for?
> 
> In order to do pinmux we need the following pieces of information from
> the device tree for each pin ("GPIO" they call it):
> 
> output signal: 0-133 + 1bit reverse flag
> output enable signal: 0-133 + 1bit reverse flag
> optional input signal: 0-74 + special "none" value, right now 0xff
> gpio number: 0-63
> 
> As the code is now all that info is packed into a u32 for each pin
> using the GPIOMUX macro defined in the dt-binding header added in
> patch 10. There is also a diagram for how this packing is done. The
> above voodoo is for unpacking that.
> 
> I'd very much like to hear if you have a better solution for how to
> convey that information from the device tree to here.

At very least this code should have something like above in the comment.

...

> > > +               if (din != 0xff)
> > > +                       reg_din = sfp->base + GPIO_IN_OFFSET + 4 * din;
> > > +               else
> > > +                       reg_din = NULL;
> >
> > This looks like you maybe use gpio-regmap instead?
> 
> This was discussed at length when Drew sent in the GPIO part of this code:
> https://lore.kernel.org/linux-riscv/20210701002037.912625-1-drew@beagleboard.org/
> The conclusion was that because pinmux and controlling the pins from
> software in GPIO mode uses the same registers it is better to do a
> combined driver like this that can share the lock among other things.

And what does prevent exactly to base the GPIO part on gpio-regmap?

...

> > > +static const unsigned char starfive_drive_strength[] = {
> > > +       14, 21, 28, 35, 42, 49, 56, 63,
> >
> > Why table? Can you simply use the formula?!
> 
> Heh, yeah. So these are rounded values from a table and I never
> noticed that after rounding they follow a nice arithmetic progression.
> It'll probably still be nice to have an explanation in the comments
> about the formula then.

Yup!

> > > +};

...

> > > +               irq_set_handler_locked(d, handle_bad_irq);
> >
> > Why is this here? Move it to ->probe().
> 
> My thinking was that if something tries to set a an unsupported irq
> type, we should make sure the caller doesn't get spurious interrupts
> because we left the handler at its old value.

You already assigned to this handler in the ->probe(), what's this then?

...

> > > +               if (value <= 6)
> > > +                       writel(value, sfp->padctl + IO_PADSHARE_SEL);
> > > +               else
> >
> > > +                       dev_err(dev, "invalid signal group %u\n", value);
> >
> > Why _err if you not bail out here?
> 
> My thinking was that if the device tree specifies an invalid signal
> group we should just leave the setting alone and not break booting,
> but still be loud about it. Maybe that's too lenient and it's better
> to crash and burn immediately if someone does that.

Here is inconsistency between level of the message and following action.
There are (rare!) cases when it's justified, but I believe it's not the
case here. You have two choices or justify why you have to use error
level without stopping process.

...

All uncommented stuff you agreed on, correct?

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [PATCH v1 00/16] Basic StarFive JH7100 RISC-V SoC support
  2021-10-12 13:40 [PATCH v1 00/16] Basic StarFive JH7100 RISC-V SoC support Emil Renner Berthing
                   ` (15 preceding siblings ...)
  2021-10-12 13:40 ` [PATCH v1 16/16] RISC-V: Add BeagleV Starlight Beta " Emil Renner Berthing
@ 2021-10-13 23:32 ` Linus Walleij
  2021-10-14 10:46   ` Emil Renner Berthing
  16 siblings, 1 reply; 49+ messages in thread
From: Linus Walleij @ 2021-10-13 23:32 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,
	Anup Patel, Atish Patra, Matteo Croce, linux-kernel

On Tue, Oct 12, 2021 at 3:41 PM Emil Renner Berthing <kernel@esmil.dk> wrote:

>   dt-bindings: pinctrl: Add StarFive pinctrl definitions
>   dt-bindings: pinctrl: Add StarFive JH7100 bindings
>   pinctrl: starfive: Add pinctrl driver for StarFive SoCs

I'd be happy to apply these to the pinctrl tree if everybody is
happy.
If you prefer some other merge path:
Acked-by: Linus Walleij <linus.walleij@linaro.org>

Yours,
Linus Walleij

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

* Re: [PATCH v1 00/16] Basic StarFive JH7100 RISC-V SoC support
  2021-10-13 23:32 ` [PATCH v1 00/16] Basic StarFive JH7100 RISC-V SoC support Linus Walleij
@ 2021-10-14 10:46   ` Emil Renner Berthing
  0 siblings, 0 replies; 49+ messages in thread
From: Emil Renner Berthing @ 2021-10-14 10:46 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,
	Anup Patel, Atish Patra, Matteo Croce, linux-kernel

On Thu, 14 Oct 2021 at 01:32, Linus Walleij <linus.walleij@linaro.org> wrote:
> On Tue, Oct 12, 2021 at 3:41 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
>
> >   dt-bindings: pinctrl: Add StarFive pinctrl definitions
> >   dt-bindings: pinctrl: Add StarFive JH7100 bindings
> >   pinctrl: starfive: Add pinctrl driver for StarFive SoCs
>
> I'd be happy to apply these to the pinctrl tree if everybody is
> happy.
> If you prefer some other merge path:
> Acked-by: Linus Walleij <linus.walleij@linaro.org>

Thank you, that sounds great to me. Let me post v2 to address Andy and
Geerts comments though.

/Emil

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

* Re: [PATCH v1 12/16] pinctrl: starfive: Add pinctrl driver for StarFive SoCs
  2021-10-12 20:02   ` Andy Shevchenko
  2021-10-13 16:38     ` Emil Renner Berthing
@ 2021-10-18 15:35     ` Emil Renner Berthing
  2021-10-18 15:47       ` Andy Shevchenko
  1 sibling, 1 reply; 49+ messages in thread
From: Emil Renner Berthing @ 2021-10-18 15:35 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, Anup Patel,
	Atish Patra, Matteo Croce, Linux Kernel Mailing List, Huan Feng

On Tue, 12 Oct 2021 at 19:03, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> On Tue, Oct 12, 2021 at 4:43 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
> > 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.
>
> s/gpio/GPIO/g
>
> ...
>
> > +config PINCTRL_STARFIVE
>
> > +       bool "Pinctrl and GPIO driver for the StarFive JH7100 SoC"
>
> Why not module?
>
> > +       depends on SOC_STARFIVE || COMPILE_TEST
>
> > +       depends on OF
>
> Do you really need this taking into account...
>
> > +       default SOC_STARFIVE
> > +       select GENERIC_PINCTRL_GROUPS
> > +       select GENERIC_PINMUX_FUNCTIONS
> > +       select GENERIC_PINCONF
> > +       select GPIOLIB
> > +       select GPIOLIB_IRQCHIP
>
> > +       select OF_GPIO
>
> ...this one?
>
> ...
>
> bits.h ?
>
> > +#include <linux/clk.h>
> > +#include <linux/gpio/driver.h>
> > +#include <linux/io.h>
> > +#include <linux/module.h>
>
>
> mod_devicetable.h ?
>
> > +#include <linux/pinctrl/pinctrl.h>
> > +#include <linux/pinctrl/pinmux.h>
>
> Can you move these as a group after generic linux/* ones?
>
> > +#include <linux/platform_device.h>
> > +#include <linux/reset.h>
> > +#include <linux/spinlock.h>
>
> ...
>
> > +/*
> > + * refer to Section 12. GPIO Registers in JH7100 datasheet:
>
> Be consistent in your style, here for example missed capitalization.
>
> > + * https://github.com/starfive-tech/StarLight_Docs
>
> Is it possible to have the datasheet to be provided as Datasheet: tag
> in the commit message?
>
> > + */
>
> ...
>
> > +/*
> > + * Global enable for GPIO interrupts, offset: 0x0, field: GPIOEN
> > + * set to 1 if GPIO interrupts are enabled, set to 0 to disable
> > + */
> > +#define IRQ_GLOBAL_EN          0x0
>
> s/0x0/0x00/g
>
> ...
>
> > +/*
> > + * Interrupt Type for GPIO[31:0], offset: 0x10, field: GPIOS_0
> > + * set to 1 if edge-triggered, set to 0 for level-triggered
> > + */
> > +#define IRQ_TYPE_LOW           0x10
> > +
> > +/*
> > + * Interrupt Type for GPIO[63:32], offset: 0x14, field: GPIOS_1
> > + */
> > +#define IRQ_TYPE_HIGH          0x14
>
> As I reviewed below, the IRQ is represented by a few registers in a
> row, no need to define low and high separately. Ditto for the rest
> register pairs.
>
> ...
>
> > +/*
> > + * Interrupt Status after Masking GPIO[31:0], offset: 0x40, field: GPIOMIS_0
> > + * status of edge-triggered or level-triggered after masking
> > + * value of 1 means edge or level was detected, value of 0 menas not detected
>
> menas?!
>
> > + */
>
> ...
>
> > +/*
> > + * Data Value of GPIO for GPIO[31:0], offest: 0x48, field: GPIODIN_0
>
> offest?!
>
> > + * dynamically reflects value on the GPIO pin
> > + */
>
> Please, run a spellchecker.
>
> ...
>
> > +#define IO_PADSHARE_SEL                0x1a0
>
> Okay, make all registers to be fixed width, i.e. 0x000 for IRQ global
> enabling and so on.
>
> ...
>
> > +#define PAD_SLEW_RATE_MASK             0xe00U
>
> GENMASK()
>
> > +#define PAD_BIAS_STRONG_PULL_UP                0x100U
> > +#define PAD_INPUT_ENABLE               0x080U
> > +#define PAD_INPUT_SCHMITT_ENABLE       0x040U
> > +#define PAD_BIAS_DISABLE               0x020U
> > +#define PAD_BIAS_PULL_DOWN             0x010U
>
> All above seems like BIT(_something_).
>
> > +#define PAD_BIAS_MASK                  0x130U
> > +#define PAD_DRIVE_STRENGTH_MASK                0x007U
>
> GENMASK()
>
> ...
>
> > +#ifdef CONFIG_DEBUG_FS
>
> __maybe_unused ?
>
> > +#else
> > +#define starfive_pin_dbg_show NULL
> > +#endif
>
> ...
>
> > +       dout = readl_relaxed(reg);
>
> readl_relaxed(reg + 0x00)
>
> > +       reg += 4;
>
> > +       doen = readl_relaxed(reg);
>
> readl_relaxed(reg + 0x04);
>
> ...
>
> > +       seq_printf(s, "dout=%u%s doen=%u%s",
> > +                  dout & 0xffU, (dout & 0x80000000U) ? "r" : "",
> > +                  doen & 0xffU, (doen & 0x80000000U) ? "r" : "");
>
> GENMASK()
> BIT()
>
> ...
>
> > +       for_each_child_of_node(np, child) {
> > +               const __be32 *pinmux_list;
> > +               const __be32 *pins_list;
> > +               int pinmux_size;
> > +               int pins_size;
> > +
> > +               pinmux_list = of_get_property(child, "pinmux", &pinmux_size);
> > +               pins_list   = of_get_property(child, "pins",   &pins_size);
> > +               if (pinmux_list && pins_list) {
> > +                       dev_err(dev, "invalid pinctrl group %pOFn.%pOFn: %s\n",
> > +                               np, child, "both pinmux and pins set");
> > +                       of_node_put(child);
> > +                       return -EINVAL;
> > +               }
> > +
> > +               if (pinmux_list && pinmux_size > 0) {
> > +                       nmaps += 2;
> > +               } else if (pins_list && pins_size > 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;
> > +       }
>
> This entire loop seems like
> 1) it should be based on something from pin control core;
> 2) it's using some low level APIs instead of better ones like
> of_property_read_uXX();
> 3) smells like unoptimized NIH.
>
> ...
>
> > +               if ((list = of_get_property(child, "pinmux", &npins))) {
>
> Why not of_property_read_...() ?
>
> ...
>
> > +                               u32 v = be32_to_cpu(*list++);
>
> My gosh!
>
> ...
>
> > +                       for (i = 0; i < npins; i++)
> > +                               pins[i] = be32_to_cpu(*list++);
>
> Ditto.
> Even for this we have something in byteorder headers.
>
> Summary, make sure you use much better _existing_ APIs instead of the
> above crap.
>
> ...
>
> > +free_pinmux:
> > +       devm_kfree(dev, pinmux);
> > +free_pins:
> > +       devm_kfree(dev, pins);
> > +free_grpname:
> > +       devm_kfree(dev, grpname);
>
> What the heck?!
>
> > +free_pgnames:
> > +       devm_kfree(dev, pgnames);
>
> Ditto.
>
> ...
>
> > +out:
>
> Useless label.
>
> > +       return ret;
>
> ...
>
> > +       for (i = 0; i < group->num_pins; i++) {
> > +               unsigned int gpio = starfive_pin_to_gpio(sfp, group->pins[i]);
> > +               void __iomem *reg_dout;
> > +               void __iomem *reg_doen;
> > +               void __iomem *reg_din;
> > +               u32 v, dout, doen, din;
> > +               unsigned long flags;
>
> > +               if (dev_WARN_ONCE(dev, gpio >= MAX_GPIO,
>
> What?!
>
> > +                                 "%s: invalid gpiomux pin", group->name))
> > +                       continue;
> > +
> > +               v = pinmux[i];
> > +               dout = ((v & BIT(7)) << (31 - 7)) | ((v >> 24) & 0xffU);
> > +               doen = ((v & BIT(6)) << (31 - 6)) | ((v >> 16) & 0xffU);
> > +               din  = (v >> 8) & 0xffU;
>
> What is this voodoo for?
>
> > +               if (din != 0xff)
> > +                       reg_din = sfp->base + GPIO_IN_OFFSET + 4 * din;
> > +               else
> > +                       reg_din = NULL;
>
> This looks like you maybe use gpio-regmap instead?
>
> ...
>
> > +       void __iomem *reg = sfp->padctl + 4 * (pin / 2);
> > +       u32 value = readl_relaxed(reg);
> > +
> > +       if (pin & 1U)
> > +               value >>= 16;
> > +       return value;
>
> u8 shift = 16 * (pin % 2);
>
> return readl_relaxed() >> shift;
>
> ?
>
> Something similar for below code.
>
> ...
>
> > +#ifdef CONFIG_DEBUG_FS
> > +static const struct pin_config_item
> > +starfive_pinconf_custom_conf_items[ARRAY_SIZE(starfive_pinconf_custom_params)] = {
>
> Instead of using ARAY_SIZE() here, use static_assert().
>
> __maybe_unused?
>
> > +       PCONFDUMP(PIN_CONFIG_STARFIVE_STRONG_PULL_UP, "input bias strong pull-up", NULL, false),
> > +};
> > +#else
> > +#define starfive_pinconf_custom_conf_items NULL
> > +#endif
>
> ...
>
> > +static const unsigned char starfive_drive_strength[] = {
> > +       14, 21, 28, 35, 42, 49, 56, 63,
>
> Why table? Can you simply use the formula?!
>
> > +};
>
> ...
>
> > +       if (unlikely(!group))
>
> Why unlikely() Must be justified here and everywhere where you are using it.
>
> > +               return -EINVAL;
> > +
> > +       return starfive_pinconf_get(pctldev, group->pins[0], config);
> > +}
>
> ...
>
> > +               case PIN_CONFIG_BIAS_DISABLE:
>
> > +                       mask |= PAD_BIAS_MASK;
>
> Use it...
>
> > +                       value = (value & ~PAD_BIAS_MASK) | PAD_BIAS_DISABLE;
>
> ...here. Ditto for the similar cases in this function and elsewhere.

I don't follow. How do you want me to use mask? If I did value =
(value & ~mask) | PAD_BIAS_DISABLE; then I'd wipe the previous
configuration. Eg. suppose the first config is the drive strength and
second disables bias. Then on the 2nd loop mask =
PAD_DRIVE_STRENGTH_MASK | PAD_BIAS_MASK and the drive strength value
would be wiped.

> After done this, you will see how you can simplify and deduplicate the
> switch-cases.
>
> ...
>
> > +#ifdef CONFIG_DEBUG_FS
>
> __maybe_unused ?
>
> > +#else
> > +#define starfive_pinconf_dbg_show NULL
> > +#endif
>
> ...
>
> > +       if (gpio < 32) {
> > +               value = readl_relaxed(sfp->base + GPIO_DIN_LOW);
>
> > +               value = (value >> gpio) & 1U;
>
> Drop
>
> > +       } else {
> > +               value = readl_relaxed(sfp->base + GPIO_DIN_HIGH);
>
> > +               value = (value >> (gpio - 32)) & 1U;
>
> Drop
>
> > +       }
>
> > +       return value;
>
> return !!(value & BIT(gpio % 32));
>
> ...
>
> > +               if (arg == 0)
>
> > +                       return -ENOTSUPP;
>
> Shouldn't we return something else and pin control core will change it
> to something else if needed?
>
> > +               if (arg == 0)
> > +                       return -ENOTSUPP;
>
> Ditto.
>
> > +       default:
> > +               return -ENOTSUPP;
>
> ...
>
> > +       if (gpio < 0 || gpio >= MAX_GPIO)
> > +               return;
> > +
> > +       if (gpio < 32) {
> > +               ie = sfp->base + IRQ_ENABLE_LOW;
> > +               mask = BIT(gpio);
> > +       } else {
> > +               ie = sfp->base + IRQ_ENABLE_HIGH;
> > +               mask = BIT(gpio - 32);
> > +       }
>
> See below. And update all occurrences of these lines accordingly and
> everywhere. Also for IRQ may use helper functions if needed (but I
> don't believe the high and low register have stride more than 4).
>
> ...
>
> > +       if (gpio < 0 || gpio >= MAX_GPIO)
> > +               return -EINVAL;
>
> How is it possible to be ever triggered?
>
> ...
>
> > +       if (gpio < 32) {
> > +               base = sfp->base;
> > +               mask = BIT(gpio);
> > +       } else {
> > +               base = sfp->base + 4;
> > +               mask = BIT(gpio - 32);
> > +       }
>
> base = sfp_base + 4 * (gpio / 32);
> mask = BIT(gpio % 32);
>
> ...
>
> > +               irq_set_handler_locked(d, handle_edge_irq);
>
> > +               irq_set_handler_locked(d, handle_edge_irq);
>
> Dup.
>
> ...
>
> > +               irq_set_handler_locked(d, handle_edge_irq);
>
> > +               irq_set_handler_locked(d, handle_level_irq);
>
> > +               irq_set_handler_locked(d, handle_level_irq);
>
> Ditto.
>
> ...
>
> > +               irq_set_handler_locked(d, handle_bad_irq);
>
> Why is this here? Move it to ->probe().
>
> ...
>
> > +       clk = devm_clk_get(dev, NULL);
> > +       if (IS_ERR(clk)) {
> > +               ret = PTR_ERR(clk);
>
> > +               dev_err(dev, "could not get clock: %d\n", ret);
>
> Thank you for spamming logs with this noise.
>
> > +               return ret;
>
> Hint: return dev_err_probe(). Ditto for the rest in this function.
>
> > +       }
>
> ...
>
> > +       ret = clk_prepare_enable(clk);
> > +       if (ret) {
>
> > +               reset_control_deassert(rst);
>
> Use devm_add_action_or_reset().

I don't see how that is better. Then I'd first need to call that and
check for errors, but just on the line below enabling the clock the
reset line is deasserted anyway, so then the action isn't needed any
longer. So that 3 lines of code for devm_add_action_or_reset +
lingering unneeded action or code to remove it again vs. just the line
above.

> > +               dev_err(dev, "could not enable clock: %d\n", ret);
> > +               return ret;
> > +       }
>
> ...
>
> > +       if (!of_property_read_u32(dev->of_node, "starfive,signal-group", &value)) {
>
> Can be refactored without conditional. Also, why not to use
> device_property_read_u32()?
>
> > +               if (value <= 6)
> > +                       writel(value, sfp->padctl + IO_PADSHARE_SEL);
> > +               else
>
> > +                       dev_err(dev, "invalid signal group %u\n", value);
>
> Why _err if you not bail out here?
>
> > +       }
>
> ...
>
> > +       value = readl(sfp->padctl + IO_PADSHARE_SEL);
> > +       switch (value) {
> > +       case 0:
> > +               sfp->gpios.pin_base = 0x10000;
>
> Magic number!
>
> > +               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.of_node = dev->of_node;
>
> Isn't GPIO library do this for you?

If it does I can't find it.

>
> ...
>
> > +       starfive_irq_chip.parent_device = dev;
>
> Ditto?
>
> ...
>
> > +       sfp->gc.irq.parents =
> > +               devm_kcalloc(dev, 1, sizeof(*sfp->gc.irq.parents), GFP_KERNEL);
>
> 1 -> sfp->gc.irq.num_parents
> And hence move below line up.
>
> > +       if (!sfp->gc.irq.parents)
> > +               return -ENOMEM;
>
> > +       sfp->gc.irq.num_parents = 1;
>
> ...
>
> > +       dev_info(dev, "StarFive GPIO chip registered %d GPIOs\n", sfp->gc.ngpio);
>
> Redundant noise.
>
> ...
>
> > +static const struct of_device_id starfive_of_match[] = {
> > +       { .compatible = "starfive,jh7100-pinctrl" },
>
> > +       { /* sentinel */ },
>
> No comma needed for terminator entry.
>
> > +};
>
> --
> With Best Regards,
> Andy Shevchenko

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

* Re: [PATCH v1 12/16] pinctrl: starfive: Add pinctrl driver for StarFive SoCs
  2021-10-18 15:35     ` Emil Renner Berthing
@ 2021-10-18 15:47       ` Andy Shevchenko
  2021-10-18 15:56         ` Emil Renner Berthing
  0 siblings, 1 reply; 49+ messages in thread
From: Andy Shevchenko @ 2021-10-18 15:47 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, Anup Patel,
	Atish Patra, Matteo Croce, Linux Kernel Mailing List, Huan Feng

On Mon, Oct 18, 2021 at 6:35 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> On Tue, 12 Oct 2021 at 19:03, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > On Tue, Oct 12, 2021 at 4:43 PM Emil Renner Berthing <kernel@esmil.dk> wrote:

When answering, cut down your message to the point, please! It's a bit
annoying to remove overquoting...

...

> > > +               case PIN_CONFIG_BIAS_DISABLE:
> >
> > > +                       mask |= PAD_BIAS_MASK;
> >
> > Use it...
> >
> > > +                       value = (value & ~PAD_BIAS_MASK) | PAD_BIAS_DISABLE;
> >
> > ...here. Ditto for the similar cases in this function and elsewhere.
>
> I don't follow. How do you want me to use mask? If I did value =
> (value & ~mask) | PAD_BIAS_DISABLE; then I'd wipe the previous
> configuration. Eg. suppose the first config is the drive strength and
> second disables bias. Then on the 2nd loop mask =
> PAD_DRIVE_STRENGTH_MASK | PAD_BIAS_MASK and the drive strength value
> would be wiped.

Collect masks and new values in temporary variables and apply them
once after the loop is done, no?

...

> > > +       ret = clk_prepare_enable(clk);
> > > +       if (ret) {
> >
> > > +               reset_control_deassert(rst);
> >
> > Use devm_add_action_or_reset().
>
> I don't see how that is better.

Pity. The rule of thumb is to either try to use devm_*() everywhere in
the probe, or don't use it at all. Above is the more-or-less standard
pattern where devn_add_action_or_reset() is being used in the entire
kernel.

> Then I'd first need to call that and
> check for errors, but just on the line below enabling the clock the
> reset line is deasserted anyway, so then the action isn't needed any
> longer. So that 3 lines of code for devm_add_action_or_reset +
> lingering unneeded action or code to remove it again vs. just the line
> above.

Then don't use devm_*() at all. What's the point?

...

> > > +       sfp->gc.of_node = dev->of_node;
> >
> > Isn't GPIO library do this for you?
>
> If it does I can't find it.

Heh... `man git grep`
Hint: `git grep -n 'of_node = .*of_node' -- drivers/gpio/gpiolib*`

-- 
With Best Regards,
Andy Shevchenko

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

* Re: [PATCH v1 12/16] pinctrl: starfive: Add pinctrl driver for StarFive SoCs
  2021-10-18 15:47       ` Andy Shevchenko
@ 2021-10-18 15:56         ` Emil Renner Berthing
  2021-10-18 16:23           ` Andy Shevchenko
  0 siblings, 1 reply; 49+ messages in thread
From: Emil Renner Berthing @ 2021-10-18 15: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, Anup Patel,
	Atish Patra, Matteo Croce, Linux Kernel Mailing List, Huan Feng

On Mon, 18 Oct 2021 at 17:48, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> On Mon, Oct 18, 2021 at 6:35 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> > On Tue, 12 Oct 2021 at 19:03, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > > On Tue, Oct 12, 2021 at 4:43 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
>
> When answering, cut down your message to the point, please! It's a bit
> annoying to remove overquoting...
>
> ...
>
> > > > +               case PIN_CONFIG_BIAS_DISABLE:
> > >
> > > > +                       mask |= PAD_BIAS_MASK;
> > >
> > > Use it...
> > >
> > > > +                       value = (value & ~PAD_BIAS_MASK) | PAD_BIAS_DISABLE;
> > >
> > > ...here. Ditto for the similar cases in this function and elsewhere.
> >
> > I don't follow. How do you want me to use mask? If I did value =
> > (value & ~mask) | PAD_BIAS_DISABLE; then I'd wipe the previous
> > configuration. Eg. suppose the first config is the drive strength and
> > second disables bias. Then on the 2nd loop mask =
> > PAD_DRIVE_STRENGTH_MASK | PAD_BIAS_MASK and the drive strength value
> > would be wiped.
>
> Collect masks and new values in temporary variables and apply them
> once after the loop is done, no?

But that's exactly what the code does. It merges all the config
options into a single mask and value so we only need to do rmw on the
register once.

> ...
>
> > > > +       ret = clk_prepare_enable(clk);
> > > > +       if (ret) {
> > >
> > > > +               reset_control_deassert(rst);
> > >
> > > Use devm_add_action_or_reset().
> >
> > I don't see how that is better.
>
> Pity. The rule of thumb is to either try to use devm_*() everywhere in
> the probe, or don't use it at all. Above is the more-or-less standard
> pattern where devn_add_action_or_reset() is being used in the entire
> kernel.
>
> > Then I'd first need to call that and
> > check for errors, but just on the line below enabling the clock the
> > reset line is deasserted anyway, so then the action isn't needed any
> > longer. So that 3 lines of code for devm_add_action_or_reset +
> > lingering unneeded action or code to remove it again vs. just the line
> > above.
>
> Then don't use devm_*() at all. What's the point?

I'm confused. So you wan't an unneeded action to linger because the
probe function temporarily asserts reset for 3 lines of code?

> ...
>
> > > > +       sfp->gc.of_node = dev->of_node;
> > >
> > > Isn't GPIO library do this for you?
> >
> > If it does I can't find it.
>
> Heh... `man git grep`
> Hint: `git grep -n 'of_node = .*of_node' -- drivers/gpio/gpiolib*`

That's exactly what I did.

> --
> With Best Regards,
> Andy Shevchenko

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

* Re: [PATCH v1 12/16] pinctrl: starfive: Add pinctrl driver for StarFive SoCs
  2021-10-18 15:56         ` Emil Renner Berthing
@ 2021-10-18 16:23           ` Andy Shevchenko
  2021-10-18 16:28             ` Andy Shevchenko
  2021-10-18 16:35             ` Emil Renner Berthing
  0 siblings, 2 replies; 49+ messages in thread
From: Andy Shevchenko @ 2021-10-18 16:23 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, Anup Patel,
	Atish Patra, Matteo Croce, Linux Kernel Mailing List, Huan Feng

On Mon, Oct 18, 2021 at 6:56 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> On Mon, 18 Oct 2021 at 17:48, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > On Mon, Oct 18, 2021 at 6:35 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> > > On Tue, 12 Oct 2021 at 19:03, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > > > On Tue, Oct 12, 2021 at 4:43 PM Emil Renner Berthing <kernel@esmil.dk> wrote:

...

> > > > > +               case PIN_CONFIG_BIAS_DISABLE:
> > > >
> > > > > +                       mask |= PAD_BIAS_MASK;
> > > >
> > > > Use it...
> > > >
> > > > > +                       value = (value & ~PAD_BIAS_MASK) | PAD_BIAS_DISABLE;
> > > >
> > > > ...here. Ditto for the similar cases in this function and elsewhere.
> > >
> > > I don't follow. How do you want me to use mask? If I did value =
> > > (value & ~mask) | PAD_BIAS_DISABLE; then I'd wipe the previous
> > > configuration. Eg. suppose the first config is the drive strength and
> > > second disables bias. Then on the 2nd loop mask =
> > > PAD_DRIVE_STRENGTH_MASK | PAD_BIAS_MASK and the drive strength value
> > > would be wiped.
> >
> > Collect masks and new values in temporary variables and apply them
> > once after the loop is done, no?
>
> But that's exactly what the code does. It merges all the config
> options into a single mask and value so we only need to do rmw on the
> register once.

Then masking the value makes no sense.
What you should have is simply as

  mask |= FOO;
  value |= BAR;

...

> > > > > +       ret = clk_prepare_enable(clk);
> > > > > +       if (ret) {
> > > >
> > > > > +               reset_control_deassert(rst);
> > > >
> > > > Use devm_add_action_or_reset().
> > >
> > > I don't see how that is better.
> >
> > Pity. The rule of thumb is to either try to use devm_*() everywhere in
> > the probe, or don't use it at all. Above is the more-or-less standard
> > pattern where devn_add_action_or_reset() is being used in the entire
> > kernel.
> >
> > > Then I'd first need to call that and
> > > check for errors, but just on the line below enabling the clock the
> > > reset line is deasserted anyway, so then the action isn't needed any
> > > longer. So that 3 lines of code for devm_add_action_or_reset +
> > > lingering unneeded action or code to remove it again vs. just the line
> > > above.
> >
> > Then don't use devm_*() at all. What's the point?
>
> I'm confused. So you wan't an unneeded action to linger because the
> probe function temporarily asserts reset for 3 lines of code?

I;m talking about clk_prepare_enable().

...

> > > > > +       sfp->gc.of_node = dev->of_node;
> > > >
> > > > Isn't GPIO library do this for you?
> > >
> > > If it does I can't find it.
> >
> > Heh... `man git grep`
> > Hint: `git grep -n 'of_node = .*of_node' -- drivers/gpio/gpiolib*`
>
> That's exactly what I did.

Now look at the result and find the correct place where it's done.
Btw, all hits are in the very same function.

-- 
With Best Regards,
Andy Shevchenko

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

* Re: [PATCH v1 12/16] pinctrl: starfive: Add pinctrl driver for StarFive SoCs
  2021-10-18 16:23           ` Andy Shevchenko
@ 2021-10-18 16:28             ` Andy Shevchenko
  2021-10-18 17:02               ` Emil Renner Berthing
  2021-10-18 16:35             ` Emil Renner Berthing
  1 sibling, 1 reply; 49+ messages in thread
From: Andy Shevchenko @ 2021-10-18 16: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, Anup Patel,
	Atish Patra, Matteo Croce, Linux Kernel Mailing List, Huan Feng

On Mon, Oct 18, 2021 at 7:23 PM Andy Shevchenko
<andy.shevchenko@gmail.com> wrote:
> On Mon, Oct 18, 2021 at 6:56 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> > On Mon, 18 Oct 2021 at 17:48, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > > On Mon, Oct 18, 2021 at 6:35 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> > > > On Tue, 12 Oct 2021 at 19:03, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > > > > On Tue, Oct 12, 2021 at 4:43 PM Emil Renner Berthing <kernel@esmil.dk> wrote:

...

> > > > > > +       ret = clk_prepare_enable(clk);
> > > > > > +       if (ret) {
> > > > >
> > > > > > +               reset_control_deassert(rst);
> > > > >
> > > > > Use devm_add_action_or_reset().
> > > >
> > > > I don't see how that is better.
> > >
> > > Pity. The rule of thumb is to either try to use devm_*() everywhere in
> > > the probe, or don't use it at all. Above is the more-or-less standard
> > > pattern where devn_add_action_or_reset() is being used in the entire
> > > kernel.
> > >
> > > > Then I'd first need to call that and
> > > > check for errors, but just on the line below enabling the clock the
> > > > reset line is deasserted anyway, so then the action isn't needed any
> > > > longer. So that 3 lines of code for devm_add_action_or_reset +
> > > > lingering unneeded action or code to remove it again vs. just the line
> > > > above.
> > >
> > > Then don't use devm_*() at all. What's the point?
> >
> > I'm confused. So you wan't an unneeded action to linger because the
> > probe function temporarily asserts reset for 3 lines of code?
>
> I;m talking about clk_prepare_enable().

Having a second look I found even problematic error paths because of
mixing devm_*() with non-devm_*() calls, which only assures me that
your ->probe() error path is broken and should be revisited.

-- 
With Best Regards,
Andy Shevchenko

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

* Re: [PATCH v1 12/16] pinctrl: starfive: Add pinctrl driver for StarFive SoCs
  2021-10-18 16:23           ` Andy Shevchenko
  2021-10-18 16:28             ` Andy Shevchenko
@ 2021-10-18 16:35             ` Emil Renner Berthing
  2021-10-18 18:37               ` Andy Shevchenko
  1 sibling, 1 reply; 49+ messages in thread
From: Emil Renner Berthing @ 2021-10-18 16:35 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, Anup Patel,
	Atish Patra, Matteo Croce, Linux Kernel Mailing List, Huan Feng

On Mon, 18 Oct 2021 at 18:24, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> On Mon, Oct 18, 2021 at 6:56 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> > On Mon, 18 Oct 2021 at 17:48, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > > On Mon, Oct 18, 2021 at 6:35 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> > > > On Tue, 12 Oct 2021 at 19:03, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > > > > On Tue, Oct 12, 2021 at 4:43 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
>
> ...
>
> > > > > > +               case PIN_CONFIG_BIAS_DISABLE:
> > > > >
> > > > > > +                       mask |= PAD_BIAS_MASK;
> > > > >
> > > > > Use it...
> > > > >
> > > > > > +                       value = (value & ~PAD_BIAS_MASK) | PAD_BIAS_DISABLE;
> > > > >
> > > > > ...here. Ditto for the similar cases in this function and elsewhere.
> > > >
> > > > I don't follow. How do you want me to use mask? If I did value =
> > > > (value & ~mask) | PAD_BIAS_DISABLE; then I'd wipe the previous
> > > > configuration. Eg. suppose the first config is the drive strength and
> > > > second disables bias. Then on the 2nd loop mask =
> > > > PAD_DRIVE_STRENGTH_MASK | PAD_BIAS_MASK and the drive strength value
> > > > would be wiped.
> > >
> > > Collect masks and new values in temporary variables and apply them
> > > once after the loop is done, no?
> >
> > But that's exactly what the code does. It merges all the config
> > options into a single mask and value so we only need to do rmw on the
> > register once.
>
> Then masking the value makes no sense.
> What you should have is simply as
>
>   mask |= FOO;
>   value |= BAR;

Yeah, but then we could get into weird states if the device tree
specifies both bias-disable and bias-pull-up by mistake. This code is
written so that only the last valid state is chosen.


> ...
>
> > > > > > +       ret = clk_prepare_enable(clk);
> > > > > > +       if (ret) {
> > > > >
> > > > > > +               reset_control_deassert(rst);
> > > > >
> > > > > Use devm_add_action_or_reset().
> > > >
> > > > I don't see how that is better.
> > >
> > > Pity. The rule of thumb is to either try to use devm_*() everywhere in
> > > the probe, or don't use it at all. Above is the more-or-less standard
> > > pattern where devn_add_action_or_reset() is being used in the entire
> > > kernel.
> > >
> > > > Then I'd first need to call that and
> > > > check for errors, but just on the line below enabling the clock the
> > > > reset line is deasserted anyway, so then the action isn't needed any
> > > > longer. So that 3 lines of code for devm_add_action_or_reset +
> > > > lingering unneeded action or code to remove it again vs. just the line
> > > > above.
> > >
> > > Then don't use devm_*() at all. What's the point?
> >
> > I'm confused. So you wan't an unneeded action to linger because the
> > probe function temporarily asserts reset for 3 lines of code?
>
> I;m talking about clk_prepare_enable().

Ok, you wrote your comment under the reset_control_deassert call. How
would devm_add_action_or_reset for clk_prepare_enable work?

> ...
>
> > > > > > +       sfp->gc.of_node = dev->of_node;
> > > > >
> > > > > Isn't GPIO library do this for you?
> > > >
> > > > If it does I can't find it.
> > >
> > > Heh... `man git grep`
> > > Hint: `git grep -n 'of_node = .*of_node' -- drivers/gpio/gpiolib*`
> >
> > That's exactly what I did.
>
> Now look at the result and find the correct place where it's done.
> Btw, all hits are in the very same function.
>
> --
> With Best Regards,
> Andy Shevchenko

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

* Re: [PATCH v1 12/16] pinctrl: starfive: Add pinctrl driver for StarFive SoCs
  2021-10-18 16:28             ` Andy Shevchenko
@ 2021-10-18 17:02               ` Emil Renner Berthing
  2021-10-19  9:52                 ` Andy Shevchenko
  0 siblings, 1 reply; 49+ messages in thread
From: Emil Renner Berthing @ 2021-10-18 17: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, Anup Patel,
	Atish Patra, Matteo Croce, Linux Kernel Mailing List, Huan Feng

On Mon, 18 Oct 2021 at 18:29, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> On Mon, Oct 18, 2021 at 7:23 PM Andy Shevchenko
> <andy.shevchenko@gmail.com> wrote:
> > On Mon, Oct 18, 2021 at 6:56 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> > > On Mon, 18 Oct 2021 at 17:48, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > > > On Mon, Oct 18, 2021 at 6:35 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> > > > > On Tue, 12 Oct 2021 at 19:03, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > > > > > On Tue, Oct 12, 2021 at 4:43 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
>
> ...
>
> > > > > > > +       ret = clk_prepare_enable(clk);
> > > > > > > +       if (ret) {
> > > > > >
> > > > > > > +               reset_control_deassert(rst);
> > > > > >
> > > > > > Use devm_add_action_or_reset().
> > > > >
> > > > > I don't see how that is better.
> > > >
> > > > Pity. The rule of thumb is to either try to use devm_*() everywhere in
> > > > the probe, or don't use it at all. Above is the more-or-less standard
> > > > pattern where devn_add_action_or_reset() is being used in the entire
> > > > kernel.
> > > >
> > > > > Then I'd first need to call that and
> > > > > check for errors, but just on the line below enabling the clock the
> > > > > reset line is deasserted anyway, so then the action isn't needed any
> > > > > longer. So that 3 lines of code for devm_add_action_or_reset +
> > > > > lingering unneeded action or code to remove it again vs. just the line
> > > > > above.
> > > >
> > > > Then don't use devm_*() at all. What's the point?
> > >
> > > I'm confused. So you wan't an unneeded action to linger because the
> > > probe function temporarily asserts reset for 3 lines of code?
> >
> > I;m talking about clk_prepare_enable().
>
> Having a second look I found even problematic error paths because of
> mixing devm_*() with non-devm_*() calls, which only assures me that
> your ->probe() error path is broken and should be revisited.

So do you want to expand on that now or should I send v2 first?

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

* Re: [PATCH v1 12/16] pinctrl: starfive: Add pinctrl driver for StarFive SoCs
  2021-10-18 16:35             ` Emil Renner Berthing
@ 2021-10-18 18:37               ` Andy Shevchenko
  0 siblings, 0 replies; 49+ messages in thread
From: Andy Shevchenko @ 2021-10-18 18:37 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, Anup Patel, Atish Patra,
	Matteo Croce, Linux Kernel Mailing List, Huan Feng

On Mon, Oct 18, 2021 at 06:35:10PM +0200, Emil Renner Berthing wrote:
> On Mon, 18 Oct 2021 at 18:24, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > On Mon, Oct 18, 2021 at 6:56 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> > > On Mon, 18 Oct 2021 at 17:48, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > > > On Mon, Oct 18, 2021 at 6:35 PM Emil Renner Berthing <kernel@esmil.dk> wrote:
> > > > > On Tue, 12 Oct 2021 at 19:03, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > > > > > On Tue, Oct 12, 2021 at 4:43 PM Emil Renner Berthing <kernel@esmil.dk> wrote:

...

> > > > > > > +               case PIN_CONFIG_BIAS_DISABLE:
> > > > > >
> > > > > > > +                       mask |= PAD_BIAS_MASK;
> > > > > >
> > > > > > Use it...
> > > > > >
> > > > > > > +                       value = (value & ~PAD_BIAS_MASK) | PAD_BIAS_DISABLE;
> > > > > >
> > > > > > ...here. Ditto for the similar cases in this function and elsewhere.
> > > > >
> > > > > I don't follow. How do you want me to use mask? If I did value =
> > > > > (value & ~mask) | PAD_BIAS_DISABLE; then I'd wipe the previous
> > > > > configuration. Eg. suppose the first config is the drive strength and
> > > > > second disables bias. Then on the 2nd loop mask =
> > > > > PAD_DRIVE_STRENGTH_MASK | PAD_BIAS_MASK and the drive strength value
> > > > > would be wiped.
> > > >
> > > > Collect masks and new values in temporary variables and apply them
> > > > once after the loop is done, no?
> > >
> > > But that's exactly what the code does. It merges all the config
> > > options into a single mask and value so we only need to do rmw on the
> > > register once.
> >
> > Then masking the value makes no sense.
> > What you should have is simply as
> >
> >   mask |= FOO;
> >   value |= BAR;
> 
> Yeah, but then we could get into weird states if the device tree
> specifies both bias-disable and bias-pull-up by mistake. This code is
> written so that only the last valid state is chosen.

But shouldn't it be disallowed by:
 1) DTC validator (Rob?)
 2) GPIO / pin control (Linus, Bart?)
?

...

> > > > > > > +       ret = clk_prepare_enable(clk);
> > > > > > > +       if (ret) {
> > > > > >
> > > > > > > +               reset_control_deassert(rst);
> > > > > >
> > > > > > Use devm_add_action_or_reset().
> > > > >
> > > > > I don't see how that is better.
> > > >
> > > > Pity. The rule of thumb is to either try to use devm_*() everywhere in
> > > > the probe, or don't use it at all. Above is the more-or-less standard
> > > > pattern where devn_add_action_or_reset() is being used in the entire
> > > > kernel.
> > > >
> > > > > Then I'd first need to call that and
> > > > > check for errors, but just on the line below enabling the clock the
> > > > > reset line is deasserted anyway, so then the action isn't needed any
> > > > > longer. So that 3 lines of code for devm_add_action_or_reset +
> > > > > lingering unneeded action or code to remove it again vs. just the line
> > > > > above.
> > > >
> > > > Then don't use devm_*() at all. What's the point?
> > >
> > > I'm confused. So you wan't an unneeded action to linger because the
> > > probe function temporarily asserts reset for 3 lines of code?
> >
> > I;m talking about clk_prepare_enable().
> 
> Ok, you wrote your comment under the reset_control_deassert call. How
> would devm_add_action_or_reset for clk_prepare_enable work?

It seems both are needed to be converted, otherwise _everything_ after
reset_assert() should not be devm_*().

TL;DR: the rule is
  Allowed:	devm_*() followed by non-devm_*()
  NOT allowed:	devm_*() followed by non-devm_*() followed by devm_*()

Of course, you may try to work the latter one, but it diminishes the whole
idea behind it, that's why I told that may be not using devm_*() is the
correct approach here and that what you meant (?).

The example how to use above mentioned API, just grep for it.

# See [1] for the sources of the used script
$ gl4func.sh devm_add_action_or_reset clk_prepare_enable | wc -l
101


[1]: https://github.com/andy-shev/home-bin-tools/blob/master/gl4func.sh

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [PATCH v1 12/16] pinctrl: starfive: Add pinctrl driver for StarFive SoCs
  2021-10-18 17:02               ` Emil Renner Berthing
@ 2021-10-19  9:52                 ` Andy Shevchenko
  0 siblings, 0 replies; 49+ messages in thread
From: Andy Shevchenko @ 2021-10-19  9:52 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, Anup Patel, Atish Patra,
	Matteo Croce, Linux Kernel Mailing List, Huan Feng

On Mon, Oct 18, 2021 at 07:02:43PM +0200, Emil Renner Berthing wrote:
> On Mon, 18 Oct 2021 at 18:29, Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> > On Mon, Oct 18, 2021 at 7:23 PM Andy Shevchenko
> > <andy.shevchenko@gmail.com> wrote:

...

> > Having a second look I found even problematic error paths because of
> > mixing devm_*() with non-devm_*() calls, which only assures me that
> > your ->probe() error path is broken and should be revisited.
> 
> So do you want to expand on that now or should I send v2 first?

Here is not enough context anymore to point out. I expect one to have done
their homework anyway.

-- 
With Best Regards,
Andy Shevchenko



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

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

On Tue, 12 Oct 2021 15:40:13 +0200, Emil Renner Berthing wrote:
> Add compatible string for the StarFive JH7100 clint.
> 
> Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
> ---
>  Documentation/devicetree/bindings/timer/sifive,clint.yaml | 1 +
>  1 file changed, 1 insertion(+)
> 

Acked-by: Rob Herring <robh@kernel.org>

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

end of thread, other threads:[~2021-10-19 22:48 UTC | newest]

Thread overview: 49+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-10-12 13:40 [PATCH v1 00/16] Basic StarFive JH7100 RISC-V SoC support Emil Renner Berthing
2021-10-12 13:40 ` [PATCH v1 01/16] RISC-V: Add StarFive SoC Kconfig option Emil Renner Berthing
2021-10-12 18:20   ` Andy Shevchenko
2021-10-12 13:40 ` [PATCH v1 02/16] dt-bindings: timer: Add StarFive JH7100 clint Emil Renner Berthing
2021-10-13  7:05   ` Geert Uytterhoeven
2021-10-19 22:48   ` Rob Herring
2021-10-12 13:40 ` [PATCH v1 03/16] dt-bindings: interrupt-controller: Add StarFive JH7100 plic Emil Renner Berthing
2021-10-13  7:05   ` Geert Uytterhoeven
2021-10-12 13:40 ` [PATCH v1 04/16] dt-bindings: clock: starfive: Add JH7100 clock definitions Emil Renner Berthing
2021-10-13 18:39   ` Stephen Boyd
2021-10-12 13:40 ` [PATCH v1 05/16] dt-bindings: clock: starfive: Add JH7100 bindings Emil Renner Berthing
2021-10-12 13:40 ` [PATCH v1 06/16] clk: starfive: Add JH7100 clock generator driver Emil Renner Berthing
2021-10-12 18:40   ` Andy Shevchenko
2021-10-12 20:07     ` Emil Renner Berthing
2021-10-12 21:20       ` Andy Shevchenko
2021-10-12 21:26         ` Emil Renner Berthing
2021-10-12 13:40 ` [PATCH v1 07/16] dt-bindings: reset: Add StarFive JH7100 reset definitions Emil Renner Berthing
2021-10-12 13:40 ` [PATCH v1 08/16] dt-bindings: reset: Add Starfive JH7100 reset bindings Emil Renner Berthing
2021-10-12 14:08   ` Philipp Zabel
2021-10-12 13:40 ` [PATCH v1 09/16] reset: starfive-jh7100: Add StarFive JH7100 reset driver Emil Renner Berthing
2021-10-12 14:06   ` Philipp Zabel
2021-10-12 14:08     ` Emil Renner Berthing
2021-10-12 14:31   ` Philipp Zabel
2021-10-12 15:04     ` Emil Renner Berthing
2021-10-12 13:40 ` [PATCH v1 10/16] dt-bindings: pinctrl: Add StarFive pinctrl definitions Emil Renner Berthing
2021-10-12 13:40 ` [PATCH v1 11/16] dt-bindings: pinctrl: Add StarFive JH7100 bindings Emil Renner Berthing
2021-10-12 13:40 ` [PATCH v1 12/16] pinctrl: starfive: Add pinctrl driver for StarFive SoCs Emil Renner Berthing
2021-10-12 20:02   ` Andy Shevchenko
2021-10-13 16:38     ` Emil Renner Berthing
2021-10-13 19:55       ` Andy Shevchenko
2021-10-13 17:37         ` Emil Renner Berthing
2021-10-13 17:50         ` Geert Uytterhoeven
2021-10-18 15:35     ` Emil Renner Berthing
2021-10-18 15:47       ` Andy Shevchenko
2021-10-18 15:56         ` Emil Renner Berthing
2021-10-18 16:23           ` Andy Shevchenko
2021-10-18 16:28             ` Andy Shevchenko
2021-10-18 17:02               ` Emil Renner Berthing
2021-10-19  9:52                 ` Andy Shevchenko
2021-10-18 16:35             ` Emil Renner Berthing
2021-10-18 18:37               ` Andy Shevchenko
2021-10-12 13:40 ` [PATCH v1 13/16] dt-bindings: serial: snps-dw-apb-uart: Add JH7100 uarts Emil Renner Berthing
2021-10-13  7:09   ` Geert Uytterhoeven
2021-10-12 13:40 ` [PATCH v1 14/16] serial: 8250_dw: Add skip_clk_set_rate quirk Emil Renner Berthing
2021-10-12 20:08   ` Andy Shevchenko
2021-10-12 13:40 ` [PATCH v1 15/16] RISC-V: Add initial StarFive JH7100 device tree Emil Renner Berthing
2021-10-12 13:40 ` [PATCH v1 16/16] RISC-V: Add BeagleV Starlight Beta " Emil Renner Berthing
2021-10-13 23:32 ` [PATCH v1 00/16] Basic StarFive JH7100 RISC-V SoC support Linus Walleij
2021-10-14 10:46   ` Emil Renner Berthing

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).