All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/8] Nuvoton WPCM450 pinctrl and GPIO driver
@ 2021-12-07 21:08 ` Jonathan Neuschäfer
  0 siblings, 0 replies; 53+ messages in thread
From: Jonathan Neuschäfer @ 2021-12-07 21:08 UTC (permalink / raw)
  To: linux-gpio, devicetree
  Cc: Linus Walleij, Rob Herring, openbmc, Tomer Maimon, Joel Stanley,
	linux-kernel, Jonathan Neuschäfer

It's been a while, but here is finally version 2 of the WPCM450 GPIO driver.

The biggest change since v1 has been the restructuring of the DT binding to
give each GPIO bank its own node.

Another thing that changed is how pins are muxed to GPIO mode: In v1, this
happened automatically when the corresponding GPIO was used. I copied this
feature from the pinctrl-npcm7xx driver, but removed it along with the
.gpio_request_enable and .gpio_disable_free callbacks. Instead, pins can now
be switched to GPIO explicitly, if needed.

Everything else is noted in the individual patches.

I hope I didn't miss anything that was requested in response to v1. If I did,
please make your comment again.


Best regards,
Jonathan Neuschäfer


v1:
- https://lore.kernel.org/lkml/20210602120329.2444672-1-j.neuschaefer@gmx.net/

> This series adds support for pinctrl and GPIO in the Nuvoton WPCM450 SoC.
> Both my DT bindings and my driver are based on the work done by others for
> the newer Nuvoton NPCM7xx SoC, and I've tried to keep both similar.
>
> Instead of extending the pinctrl-npcm7xx driver to add WPCM450 support,
> I copied/forked it. The pinmux mechanism is very similar (using MFSEL1 and
> MFSEL2 registers), but the GPIO register interface has been redesigned for
> NPCM7xx; adding support for the older GPIO controller would make the driver
> harder to understand, while only enabling a small amount of code sharing.
>
> The DT binding in YAML format might make a good template for also converting
> the nuvoton,npcm7xx-pinctrl binding to YAML.
>
> Both in the DT binding and in the driver I kept the name "pinctrl". For the
> driver, I find it accurate enough because it handles pinctrl and GPIO. For
> the DT node, it's a bit less accurate because the register block at 0xb8003000
> is about GPIOs, and pin control happens in the global control registers (GCR)
> block, except for input debouncing. So, "GPIO" might be the more appropriate
> name component there.


Jonathan Neuschäfer (8):
  dt-bindings: arm/npcm: Add binding for global control registers (GCR)
  MAINTAINERS: Match all of bindings/arm/npcm/ as part of NPCM
    architecture
  ARM: dts: wpcm450: Add global control registers (GCR) node
  dt-bindings: pinctrl: Add Nuvoton WPCM450
  pinctrl: nuvoton: Add driver for WPCM450
  ARM: dts: wpcm450: Add pinctrl and GPIO nodes
  ARM: dts: wpcm450: Add pin functions
  ARM: dts: wpcm450-supermicro-x9sci-ln4f: Add GPIO LEDs and buttons

 .../bindings/arm/npcm/nuvoton,gcr.yaml        |   45 +
 .../pinctrl/nuvoton,wpcm450-pinctrl.yaml      |  190 +++
 MAINTAINERS                                   |    2 +
 .../nuvoton-wpcm450-supermicro-x9sci-ln4f.dts |   43 +
 arch/arm/boot/dts/nuvoton-wpcm450.dtsi        |  384 ++++++
 drivers/pinctrl/Makefile                      |    2 +-
 drivers/pinctrl/nuvoton/Kconfig               |   18 +
 drivers/pinctrl/nuvoton/Makefile              |    1 +
 drivers/pinctrl/nuvoton/pinctrl-wpcm450.c     | 1134 +++++++++++++++++
 9 files changed, 1818 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/arm/npcm/nuvoton,gcr.yaml
 create mode 100644 Documentation/devicetree/bindings/pinctrl/nuvoton,wpcm450-pinctrl.yaml
 create mode 100644 drivers/pinctrl/nuvoton/pinctrl-wpcm450.c

--
2.30.2


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

* [PATCH v2 0/8] Nuvoton WPCM450 pinctrl and GPIO driver
@ 2021-12-07 21:08 ` Jonathan Neuschäfer
  0 siblings, 0 replies; 53+ messages in thread
From: Jonathan Neuschäfer @ 2021-12-07 21:08 UTC (permalink / raw)
  To: linux-gpio, devicetree
  Cc: Tomer Maimon, Linus Walleij, linux-kernel,
	Jonathan Neuschäfer, Rob Herring, openbmc

It's been a while, but here is finally version 2 of the WPCM450 GPIO driver.

The biggest change since v1 has been the restructuring of the DT binding to
give each GPIO bank its own node.

Another thing that changed is how pins are muxed to GPIO mode: In v1, this
happened automatically when the corresponding GPIO was used. I copied this
feature from the pinctrl-npcm7xx driver, but removed it along with the
.gpio_request_enable and .gpio_disable_free callbacks. Instead, pins can now
be switched to GPIO explicitly, if needed.

Everything else is noted in the individual patches.

I hope I didn't miss anything that was requested in response to v1. If I did,
please make your comment again.


Best regards,
Jonathan Neuschäfer


v1:
- https://lore.kernel.org/lkml/20210602120329.2444672-1-j.neuschaefer@gmx.net/

> This series adds support for pinctrl and GPIO in the Nuvoton WPCM450 SoC.
> Both my DT bindings and my driver are based on the work done by others for
> the newer Nuvoton NPCM7xx SoC, and I've tried to keep both similar.
>
> Instead of extending the pinctrl-npcm7xx driver to add WPCM450 support,
> I copied/forked it. The pinmux mechanism is very similar (using MFSEL1 and
> MFSEL2 registers), but the GPIO register interface has been redesigned for
> NPCM7xx; adding support for the older GPIO controller would make the driver
> harder to understand, while only enabling a small amount of code sharing.
>
> The DT binding in YAML format might make a good template for also converting
> the nuvoton,npcm7xx-pinctrl binding to YAML.
>
> Both in the DT binding and in the driver I kept the name "pinctrl". For the
> driver, I find it accurate enough because it handles pinctrl and GPIO. For
> the DT node, it's a bit less accurate because the register block at 0xb8003000
> is about GPIOs, and pin control happens in the global control registers (GCR)
> block, except for input debouncing. So, "GPIO" might be the more appropriate
> name component there.


Jonathan Neuschäfer (8):
  dt-bindings: arm/npcm: Add binding for global control registers (GCR)
  MAINTAINERS: Match all of bindings/arm/npcm/ as part of NPCM
    architecture
  ARM: dts: wpcm450: Add global control registers (GCR) node
  dt-bindings: pinctrl: Add Nuvoton WPCM450
  pinctrl: nuvoton: Add driver for WPCM450
  ARM: dts: wpcm450: Add pinctrl and GPIO nodes
  ARM: dts: wpcm450: Add pin functions
  ARM: dts: wpcm450-supermicro-x9sci-ln4f: Add GPIO LEDs and buttons

 .../bindings/arm/npcm/nuvoton,gcr.yaml        |   45 +
 .../pinctrl/nuvoton,wpcm450-pinctrl.yaml      |  190 +++
 MAINTAINERS                                   |    2 +
 .../nuvoton-wpcm450-supermicro-x9sci-ln4f.dts |   43 +
 arch/arm/boot/dts/nuvoton-wpcm450.dtsi        |  384 ++++++
 drivers/pinctrl/Makefile                      |    2 +-
 drivers/pinctrl/nuvoton/Kconfig               |   18 +
 drivers/pinctrl/nuvoton/Makefile              |    1 +
 drivers/pinctrl/nuvoton/pinctrl-wpcm450.c     | 1134 +++++++++++++++++
 9 files changed, 1818 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/arm/npcm/nuvoton,gcr.yaml
 create mode 100644 Documentation/devicetree/bindings/pinctrl/nuvoton,wpcm450-pinctrl.yaml
 create mode 100644 drivers/pinctrl/nuvoton/pinctrl-wpcm450.c

--
2.30.2


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

* [PATCH v2 1/8] dt-bindings: arm/npcm: Add binding for global control registers (GCR)
  2021-12-07 21:08 ` Jonathan Neuschäfer
@ 2021-12-07 21:08   ` Jonathan Neuschäfer
  -1 siblings, 0 replies; 53+ messages in thread
From: Jonathan Neuschäfer @ 2021-12-07 21:08 UTC (permalink / raw)
  To: linux-gpio, devicetree
  Cc: Linus Walleij, Rob Herring, openbmc, Tomer Maimon, Joel Stanley,
	linux-kernel, Jonathan Neuschäfer, Avi Fishman, Tali Perry,
	Patrick Venture, Nancy Yuen, Benjamin Fair

A nuvoton,*-gcr node is present in nuvoton-common-npcm7xx.dtsi and will
be added to nuvoton-wpcm450.dtsi. It is necessary for the NPCM7xx and
WPCM450 pinctrl drivers, and may later be used to retrieve SoC model and
version information.

This patch adds a binding to describe this node.

Signed-off-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>

---
v2:
- Rename node in example to syscon@800000
- Add subnode to example

v1:
- https://lore.kernel.org/lkml/20210602120329.2444672-2-j.neuschaefer@gmx.net/
---
 .../bindings/arm/npcm/nuvoton,gcr.yaml        | 45 +++++++++++++++++++
 1 file changed, 45 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/npcm/nuvoton,gcr.yaml

diff --git a/Documentation/devicetree/bindings/arm/npcm/nuvoton,gcr.yaml b/Documentation/devicetree/bindings/arm/npcm/nuvoton,gcr.yaml
new file mode 100644
index 0000000000000..62020d7ac305b
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/npcm/nuvoton,gcr.yaml
@@ -0,0 +1,45 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/arm/npcm/nuvoton,gcr.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Global Control Registers block in Nuvoton SoCs
+
+maintainers:
+  - Jonathan Neuschäfer <j.neuschaefer@gmx.net>
+
+description: |
+  The Global Control Registers (GCR) are a block of registers in Nuvoton SoCs
+  that expose misc functionality such as chip model and version information or
+  pinmux settings.
+
+properties:
+  compatible:
+    items:
+      - enum:
+          - nuvoton,wpcm450-gcr
+          - nuvoton,npcm750-gcr
+      - const: syscon
+      - const: simple-mfd
+  reg: true
+
+required:
+  - compatible
+  - reg
+
+additionalProperties: false
+
+examples:
+  - |
+    gcr: syscon@800000 {
+      compatible = "nuvoton,npcm750-gcr", "syscon", "simple-mfd";
+      reg = <0x800000 0x1000>;
+
+      uart-mux-controller {
+        compatible = "mmio-mux";
+        #mux-control-cells = <1>;
+        mux-reg-masks = <0x38 0x07>;
+        idle-states = <2>;
+      };
+    };
--
2.30.2


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

* [PATCH v2 1/8] dt-bindings: arm/npcm: Add binding for global control registers (GCR)
@ 2021-12-07 21:08   ` Jonathan Neuschäfer
  0 siblings, 0 replies; 53+ messages in thread
From: Jonathan Neuschäfer @ 2021-12-07 21:08 UTC (permalink / raw)
  To: linux-gpio, devicetree
  Cc: Tomer Maimon, Avi Fishman, Patrick Venture, Linus Walleij,
	linux-kernel, Jonathan Neuschäfer, Rob Herring, Tali Perry,
	openbmc, Benjamin Fair

A nuvoton,*-gcr node is present in nuvoton-common-npcm7xx.dtsi and will
be added to nuvoton-wpcm450.dtsi. It is necessary for the NPCM7xx and
WPCM450 pinctrl drivers, and may later be used to retrieve SoC model and
version information.

This patch adds a binding to describe this node.

Signed-off-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>

---
v2:
- Rename node in example to syscon@800000
- Add subnode to example

v1:
- https://lore.kernel.org/lkml/20210602120329.2444672-2-j.neuschaefer@gmx.net/
---
 .../bindings/arm/npcm/nuvoton,gcr.yaml        | 45 +++++++++++++++++++
 1 file changed, 45 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/npcm/nuvoton,gcr.yaml

diff --git a/Documentation/devicetree/bindings/arm/npcm/nuvoton,gcr.yaml b/Documentation/devicetree/bindings/arm/npcm/nuvoton,gcr.yaml
new file mode 100644
index 0000000000000..62020d7ac305b
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/npcm/nuvoton,gcr.yaml
@@ -0,0 +1,45 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/arm/npcm/nuvoton,gcr.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Global Control Registers block in Nuvoton SoCs
+
+maintainers:
+  - Jonathan Neuschäfer <j.neuschaefer@gmx.net>
+
+description: |
+  The Global Control Registers (GCR) are a block of registers in Nuvoton SoCs
+  that expose misc functionality such as chip model and version information or
+  pinmux settings.
+
+properties:
+  compatible:
+    items:
+      - enum:
+          - nuvoton,wpcm450-gcr
+          - nuvoton,npcm750-gcr
+      - const: syscon
+      - const: simple-mfd
+  reg: true
+
+required:
+  - compatible
+  - reg
+
+additionalProperties: false
+
+examples:
+  - |
+    gcr: syscon@800000 {
+      compatible = "nuvoton,npcm750-gcr", "syscon", "simple-mfd";
+      reg = <0x800000 0x1000>;
+
+      uart-mux-controller {
+        compatible = "mmio-mux";
+        #mux-control-cells = <1>;
+        mux-reg-masks = <0x38 0x07>;
+        idle-states = <2>;
+      };
+    };
--
2.30.2


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

* [PATCH v2 2/8] MAINTAINERS: Match all of bindings/arm/npcm/ as part of NPCM architecture
  2021-12-07 21:08 ` Jonathan Neuschäfer
@ 2021-12-07 21:08   ` Jonathan Neuschäfer
  -1 siblings, 0 replies; 53+ messages in thread
From: Jonathan Neuschäfer @ 2021-12-07 21:08 UTC (permalink / raw)
  To: linux-gpio, devicetree
  Cc: Linus Walleij, Rob Herring, openbmc, Tomer Maimon, Joel Stanley,
	linux-kernel, Jonathan Neuschäfer

All files in Documentation/devicetree/bindings/arm/npcm/ belong to the
Nuvoton NPCM architecture, even when their names might not spell it out
explicitly.

Signed-off-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>
---

v2:
- no changes

v1:
- https://lore.kernel.org/lkml/20210602120329.2444672-3-j.neuschaefer@gmx.net/
---
 MAINTAINERS | 1 +
 1 file changed, 1 insertion(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 360e9aa0205d6..eff3edafd8814 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2338,6 +2338,7 @@ L:	openbmc@lists.ozlabs.org (moderated for non-subscribers)
 S:	Supported
 F:	Documentation/devicetree/bindings/*/*/*npcm*
 F:	Documentation/devicetree/bindings/*/*npcm*
+F:	Documentation/devicetree/bindings/arm/npcm/*
 F:	arch/arm/boot/dts/nuvoton-npcm*
 F:	arch/arm/mach-npcm/
 F:	drivers/*/*npcm*
--
2.30.2


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

* [PATCH v2 2/8] MAINTAINERS: Match all of bindings/arm/npcm/ as part of NPCM architecture
@ 2021-12-07 21:08   ` Jonathan Neuschäfer
  0 siblings, 0 replies; 53+ messages in thread
From: Jonathan Neuschäfer @ 2021-12-07 21:08 UTC (permalink / raw)
  To: linux-gpio, devicetree
  Cc: Tomer Maimon, Linus Walleij, linux-kernel,
	Jonathan Neuschäfer, Rob Herring, openbmc

All files in Documentation/devicetree/bindings/arm/npcm/ belong to the
Nuvoton NPCM architecture, even when their names might not spell it out
explicitly.

Signed-off-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>
---

v2:
- no changes

v1:
- https://lore.kernel.org/lkml/20210602120329.2444672-3-j.neuschaefer@gmx.net/
---
 MAINTAINERS | 1 +
 1 file changed, 1 insertion(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 360e9aa0205d6..eff3edafd8814 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2338,6 +2338,7 @@ L:	openbmc@lists.ozlabs.org (moderated for non-subscribers)
 S:	Supported
 F:	Documentation/devicetree/bindings/*/*/*npcm*
 F:	Documentation/devicetree/bindings/*/*npcm*
+F:	Documentation/devicetree/bindings/arm/npcm/*
 F:	arch/arm/boot/dts/nuvoton-npcm*
 F:	arch/arm/mach-npcm/
 F:	drivers/*/*npcm*
--
2.30.2


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

* [PATCH v2 3/8] ARM: dts: wpcm450: Add global control registers (GCR) node
  2021-12-07 21:08 ` Jonathan Neuschäfer
@ 2021-12-07 21:08   ` Jonathan Neuschäfer
  -1 siblings, 0 replies; 53+ messages in thread
From: Jonathan Neuschäfer @ 2021-12-07 21:08 UTC (permalink / raw)
  To: linux-gpio, devicetree
  Cc: Linus Walleij, Rob Herring, openbmc, Tomer Maimon, Joel Stanley,
	linux-kernel, Jonathan Neuschäfer

The Global Control Registers (GCR) are a block of registers in Nuvoton
SoCs that expose misc functionality such as chip model and version
information or pinmux settings.

This patch adds a GCR node to nuvoton-wpcm450.dtsi in preparation for
enabling pinctrl on this SoC.

Signed-off-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>


---
v2:
- Rename node to syscon@b0000000

v1:
- https://lore.kernel.org/lkml/20210602120329.2444672-4-j.neuschaefer@gmx.net/
---
 arch/arm/boot/dts/nuvoton-wpcm450.dtsi | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/arm/boot/dts/nuvoton-wpcm450.dtsi b/arch/arm/boot/dts/nuvoton-wpcm450.dtsi
index d7cbeb1874840..a17ee70085dd0 100644
--- a/arch/arm/boot/dts/nuvoton-wpcm450.dtsi
+++ b/arch/arm/boot/dts/nuvoton-wpcm450.dtsi
@@ -33,6 +33,11 @@ soc {
 		interrupt-parent = <&aic>;
 		ranges;

+		gcr: syscon@b0000000 {
+			compatible = "nuvoton,wpcm450-gcr", "syscon", "simple-mfd";
+			reg = <0xb0000000 0x200>;
+		};
+
 		serial0: serial@b8000000 {
 			compatible = "nuvoton,wpcm450-uart";
 			reg = <0xb8000000 0x20>;
--
2.30.2


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

* [PATCH v2 3/8] ARM: dts: wpcm450: Add global control registers (GCR) node
@ 2021-12-07 21:08   ` Jonathan Neuschäfer
  0 siblings, 0 replies; 53+ messages in thread
From: Jonathan Neuschäfer @ 2021-12-07 21:08 UTC (permalink / raw)
  To: linux-gpio, devicetree
  Cc: Tomer Maimon, Linus Walleij, linux-kernel,
	Jonathan Neuschäfer, Rob Herring, openbmc

The Global Control Registers (GCR) are a block of registers in Nuvoton
SoCs that expose misc functionality such as chip model and version
information or pinmux settings.

This patch adds a GCR node to nuvoton-wpcm450.dtsi in preparation for
enabling pinctrl on this SoC.

Signed-off-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>


---
v2:
- Rename node to syscon@b0000000

v1:
- https://lore.kernel.org/lkml/20210602120329.2444672-4-j.neuschaefer@gmx.net/
---
 arch/arm/boot/dts/nuvoton-wpcm450.dtsi | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/arm/boot/dts/nuvoton-wpcm450.dtsi b/arch/arm/boot/dts/nuvoton-wpcm450.dtsi
index d7cbeb1874840..a17ee70085dd0 100644
--- a/arch/arm/boot/dts/nuvoton-wpcm450.dtsi
+++ b/arch/arm/boot/dts/nuvoton-wpcm450.dtsi
@@ -33,6 +33,11 @@ soc {
 		interrupt-parent = <&aic>;
 		ranges;

+		gcr: syscon@b0000000 {
+			compatible = "nuvoton,wpcm450-gcr", "syscon", "simple-mfd";
+			reg = <0xb0000000 0x200>;
+		};
+
 		serial0: serial@b8000000 {
 			compatible = "nuvoton,wpcm450-uart";
 			reg = <0xb8000000 0x20>;
--
2.30.2


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

* [PATCH v2 4/8] dt-bindings: pinctrl: Add Nuvoton WPCM450
  2021-12-07 21:08 ` Jonathan Neuschäfer
@ 2021-12-07 21:08   ` Jonathan Neuschäfer
  -1 siblings, 0 replies; 53+ messages in thread
From: Jonathan Neuschäfer @ 2021-12-07 21:08 UTC (permalink / raw)
  To: linux-gpio, devicetree
  Cc: Linus Walleij, Rob Herring, openbmc, Tomer Maimon, Joel Stanley,
	linux-kernel, Jonathan Neuschäfer

This binding is heavily based on the one for NPCM7xx, because the
hardware is similar. There are some notable differences, however:

- The addresses of GPIO banks are not physical addresses but simple
  indices (0 to 7), because the GPIO registers are not laid out in
  convenient blocks.
- Pinmux settings can explicitly specify that the GPIO mode is used.

Certain pins support blink patterns in hardware. This is currently not
modelled in the DT binding.

Signed-off-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>


---
v2:
- Move GPIO into subnodes
- Improve use of quotes
- Remove unnecessary minItems/maxItems lines
- Remove "phandle: true"
- Use separate prefixes for pinmux and pincfg nodes
- Add nuvoton,interrupt-map property
- Make it possible to set pinmux to GPIO explicitly

v1:
- https://lore.kernel.org/lkml/20210602120329.2444672-5-j.neuschaefer@gmx.net/
---
 .../pinctrl/nuvoton,wpcm450-pinctrl.yaml      | 190 ++++++++++++++++++
 1 file changed, 190 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/pinctrl/nuvoton,wpcm450-pinctrl.yaml

diff --git a/Documentation/devicetree/bindings/pinctrl/nuvoton,wpcm450-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/nuvoton,wpcm450-pinctrl.yaml
new file mode 100644
index 0000000000000..2b783597794d7
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/nuvoton,wpcm450-pinctrl.yaml
@@ -0,0 +1,190 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pinctrl/nuvoton,wpcm450-pinctrl.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Nuvoton WPCM450 pin control and GPIO
+
+maintainers:
+  - Jonathan Neuschäfer <j.neuschaefer@gmx.net>
+
+properties:
+  compatible:
+    const: nuvoton,wpcm450-pinctrl
+
+  reg:
+    maxItems: 1
+
+patternProperties:
+  # There are three kinds of subnodes:
+  # 1. a GPIO controller node for each GPIO bank
+  # 2. a pinmux node configures pin muxing for a group of pins (e.g. rmii2)
+  # 3. a pinconf node configures properties of a single pin
+
+  "^gpio@.*$":
+    if:
+      type: object
+    then:
+      description:
+        Eight GPIO banks (gpio@0 to gpio@7), that each contain between 14 and 18
+        GPIOs. Some GPIOs support interrupts.
+
+      allOf:
+        - $ref: pinmux-node.yaml#
+
+      properties:
+        reg:
+          description: GPIO bank number (0-7)
+
+        gpio-controller: true
+
+        "#gpio-cells":
+          const: 2
+
+        interrupt-controller: true
+
+        "#interrupt-cells":
+          const: 2
+
+        interrupts:
+          maxItems: 4
+
+        nuvoton,interrupt-map:
+          description:
+            This property defines which bits in the interrupt registers
+            correspond to which GPIOs.
+          $ref: /schemas/types.yaml#/definitions/uint32-array
+          items:
+            - description: First interrupt bit
+            - description: Number of interrupt bits
+            - description: First GPIO associated with an interrupt
+
+      required:
+        - reg
+        - gpio-controller
+        - '#gpio-cells'
+
+  "^mux_.*$":
+    if:
+      type: object
+    then:
+      allOf:
+        - $ref: pinmux-node.yaml#
+      properties:
+        groups:
+          description:
+            One or more groups of pins to mux to a certain function
+          items:
+            enum: [ smb3, smb4, smb5, scs1, scs2, scs3, smb0, smb1, smb2, bsp,
+                    hsp1, hsp2, r1err, r1md, rmii2, r2err, r2md, kbcc, dvo,
+                    clko, smi, uinc, gspi, mben, xcs2, xcs1, sdio, sspi, fi0,
+                    fi1, fi2, fi3, fi4, fi5, fi6, fi7, fi8, fi9, fi10, fi11,
+                    fi12, fi13, fi14, fi15, pwm0, pwm1, pwm2, pwm3, pwm4, pwm5,
+                    pwm6, pwm7, hg0, hg1, hg2, hg3, hg4, hg5, hg6, hg7 ]
+        function:
+          description:
+            The function that a group of pins is muxed to
+          enum: [ smb3, smb4, smb5, scs1, scs2, scs3, smb0, smb1, smb2, bsp,
+                  hsp1, hsp2, r1err, r1md, rmii2, r2err, r2md, kbcc, dvo0,
+                  dvo1, dvo2, dvo3, dvo4, dvo5, dvo6, dvo7, clko, smi, uinc,
+                  gspi, mben, xcs2, xcs1, sdio, sspi, fi0, fi1, fi2, fi3, fi4,
+                  fi5, fi6, fi7, fi8, fi9, fi10, fi11, fi12, fi13, fi14, fi15,
+                  pwm0, pwm1, pwm2, pwm3, pwm4, pwm5, pwm6, pwm7, hg0, hg1,
+                  hg2, hg3, hg4, hg5, hg6, hg7, gpio ]
+
+      dependencies:
+        groups: [ function ]
+        function: [ groups ]
+
+      additionalProperties: false
+
+  "^cfg_.*$":
+    if:
+      type: object
+    then:
+      allOf:
+        - $ref: pincfg-node.yaml#
+      properties:
+        pins:
+          description:
+            A list of pins to configure in certain ways, such as enabling
+            debouncing
+          items:
+            enum: [ gpio0, gpio1, gpio2, gpio3, gpio4, gpio5, gpio6, gpio7,
+                    gpio8, gpio9, gpio10, gpio11, gpio12, gpio13, gpio14,
+                    gpio15, gpio16, gpio17, gpio18, gpio19, gpio20, gpio21,
+                    gpio22, gpio23, gpio24, gpio25, gpio26, gpio27, gpio28,
+                    gpio29, gpio30, gpio31, gpio32, gpio33, gpio34, gpio35,
+                    gpio36, gpio37, gpio38, gpio39, gpio40, gpio41, gpio42,
+                    gpio43, gpio44, gpio45, gpio46, gpio47, gpio48, gpio49,
+                    gpio50, gpio51, gpio52, gpio53, gpio54, gpio55, gpio56,
+                    gpio57, gpio58, gpio59, gpio60, gpio61, gpio62, gpio63,
+                    gpio64, gpio65, gpio66, gpio67, gpio68, gpio69, gpio70,
+                    gpio71, gpio72, gpio73, gpio74, gpio75, gpio76, gpio77,
+                    gpio78, gpio79, gpio80, gpio81, gpio82, gpio83, gpio84,
+                    gpio85, gpio86, gpio87, gpio88, gpio89, gpio90, gpio91,
+                    gpio92, gpio93, gpio94, gpio95, gpio96, gpio97, gpio98,
+                    gpio99, gpio100, gpio101, gpio102, gpio103, gpio104,
+                    gpio105, gpio106, gpio107, gpio108, gpio109, gpio110,
+                    gpio111, gpio112, gpio113, gpio114, gpio115, gpio116,
+                    gpio117, gpio118, gpio119, gpio120, gpio121, gpio122,
+                    gpio123, gpio124, gpio125, gpio126, gpio127 ]
+
+        input-debounce: true
+
+      additionalProperties: false
+
+required:
+  - compatible
+  - reg
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/irq.h>
+    #include <dt-bindings/gpio/gpio.h>
+    pinctrl: pinctrl@b8003000 {
+      compatible = "nuvoton,wpcm450-pinctrl";
+      reg = <0xb8003000 0x1000>;
+      #address-cells = <1>;
+      #size-cells = <0>;
+
+      gpio0: gpio@0 {
+        reg = <0>;
+        gpio-controller;
+        #gpio-cells = <2>;
+        interrupts = <2 IRQ_TYPE_LEVEL_HIGH
+                      3 IRQ_TYPE_LEVEL_HIGH
+                      4 IRQ_TYPE_LEVEL_HIGH>;
+        nuvoton,interrupt-map = <0 16 0>;
+      };
+
+      mux_rmii2 {
+        groups = "rmii2";
+        function = "rmii2";
+      };
+
+      pinmux_uid: mux_uid {
+        groups = "gspi", "sspi";
+        function = "gpio";
+      };
+
+      pinctrl_uid: cfg_uid {
+        pins = "gpio14";
+        input-debounce = <1>;
+      };
+    };
+
+    gpio-keys {
+      compatible = "gpio-keys";
+      pinctrl-names = "default";
+      pinctrl-0 = <&pinctrl_uid>, <&pinmux_uid>;
+
+      uid {
+        label = "UID";
+        linux,code = <102>;
+        gpios = <&gpio0 14 GPIO_ACTIVE_HIGH>;
+      };
+    };
--
2.30.2


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

* [PATCH v2 4/8] dt-bindings: pinctrl: Add Nuvoton WPCM450
@ 2021-12-07 21:08   ` Jonathan Neuschäfer
  0 siblings, 0 replies; 53+ messages in thread
From: Jonathan Neuschäfer @ 2021-12-07 21:08 UTC (permalink / raw)
  To: linux-gpio, devicetree
  Cc: Tomer Maimon, Linus Walleij, linux-kernel,
	Jonathan Neuschäfer, Rob Herring, openbmc

This binding is heavily based on the one for NPCM7xx, because the
hardware is similar. There are some notable differences, however:

- The addresses of GPIO banks are not physical addresses but simple
  indices (0 to 7), because the GPIO registers are not laid out in
  convenient blocks.
- Pinmux settings can explicitly specify that the GPIO mode is used.

Certain pins support blink patterns in hardware. This is currently not
modelled in the DT binding.

Signed-off-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>


---
v2:
- Move GPIO into subnodes
- Improve use of quotes
- Remove unnecessary minItems/maxItems lines
- Remove "phandle: true"
- Use separate prefixes for pinmux and pincfg nodes
- Add nuvoton,interrupt-map property
- Make it possible to set pinmux to GPIO explicitly

v1:
- https://lore.kernel.org/lkml/20210602120329.2444672-5-j.neuschaefer@gmx.net/
---
 .../pinctrl/nuvoton,wpcm450-pinctrl.yaml      | 190 ++++++++++++++++++
 1 file changed, 190 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/pinctrl/nuvoton,wpcm450-pinctrl.yaml

diff --git a/Documentation/devicetree/bindings/pinctrl/nuvoton,wpcm450-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/nuvoton,wpcm450-pinctrl.yaml
new file mode 100644
index 0000000000000..2b783597794d7
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/nuvoton,wpcm450-pinctrl.yaml
@@ -0,0 +1,190 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pinctrl/nuvoton,wpcm450-pinctrl.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Nuvoton WPCM450 pin control and GPIO
+
+maintainers:
+  - Jonathan Neuschäfer <j.neuschaefer@gmx.net>
+
+properties:
+  compatible:
+    const: nuvoton,wpcm450-pinctrl
+
+  reg:
+    maxItems: 1
+
+patternProperties:
+  # There are three kinds of subnodes:
+  # 1. a GPIO controller node for each GPIO bank
+  # 2. a pinmux node configures pin muxing for a group of pins (e.g. rmii2)
+  # 3. a pinconf node configures properties of a single pin
+
+  "^gpio@.*$":
+    if:
+      type: object
+    then:
+      description:
+        Eight GPIO banks (gpio@0 to gpio@7), that each contain between 14 and 18
+        GPIOs. Some GPIOs support interrupts.
+
+      allOf:
+        - $ref: pinmux-node.yaml#
+
+      properties:
+        reg:
+          description: GPIO bank number (0-7)
+
+        gpio-controller: true
+
+        "#gpio-cells":
+          const: 2
+
+        interrupt-controller: true
+
+        "#interrupt-cells":
+          const: 2
+
+        interrupts:
+          maxItems: 4
+
+        nuvoton,interrupt-map:
+          description:
+            This property defines which bits in the interrupt registers
+            correspond to which GPIOs.
+          $ref: /schemas/types.yaml#/definitions/uint32-array
+          items:
+            - description: First interrupt bit
+            - description: Number of interrupt bits
+            - description: First GPIO associated with an interrupt
+
+      required:
+        - reg
+        - gpio-controller
+        - '#gpio-cells'
+
+  "^mux_.*$":
+    if:
+      type: object
+    then:
+      allOf:
+        - $ref: pinmux-node.yaml#
+      properties:
+        groups:
+          description:
+            One or more groups of pins to mux to a certain function
+          items:
+            enum: [ smb3, smb4, smb5, scs1, scs2, scs3, smb0, smb1, smb2, bsp,
+                    hsp1, hsp2, r1err, r1md, rmii2, r2err, r2md, kbcc, dvo,
+                    clko, smi, uinc, gspi, mben, xcs2, xcs1, sdio, sspi, fi0,
+                    fi1, fi2, fi3, fi4, fi5, fi6, fi7, fi8, fi9, fi10, fi11,
+                    fi12, fi13, fi14, fi15, pwm0, pwm1, pwm2, pwm3, pwm4, pwm5,
+                    pwm6, pwm7, hg0, hg1, hg2, hg3, hg4, hg5, hg6, hg7 ]
+        function:
+          description:
+            The function that a group of pins is muxed to
+          enum: [ smb3, smb4, smb5, scs1, scs2, scs3, smb0, smb1, smb2, bsp,
+                  hsp1, hsp2, r1err, r1md, rmii2, r2err, r2md, kbcc, dvo0,
+                  dvo1, dvo2, dvo3, dvo4, dvo5, dvo6, dvo7, clko, smi, uinc,
+                  gspi, mben, xcs2, xcs1, sdio, sspi, fi0, fi1, fi2, fi3, fi4,
+                  fi5, fi6, fi7, fi8, fi9, fi10, fi11, fi12, fi13, fi14, fi15,
+                  pwm0, pwm1, pwm2, pwm3, pwm4, pwm5, pwm6, pwm7, hg0, hg1,
+                  hg2, hg3, hg4, hg5, hg6, hg7, gpio ]
+
+      dependencies:
+        groups: [ function ]
+        function: [ groups ]
+
+      additionalProperties: false
+
+  "^cfg_.*$":
+    if:
+      type: object
+    then:
+      allOf:
+        - $ref: pincfg-node.yaml#
+      properties:
+        pins:
+          description:
+            A list of pins to configure in certain ways, such as enabling
+            debouncing
+          items:
+            enum: [ gpio0, gpio1, gpio2, gpio3, gpio4, gpio5, gpio6, gpio7,
+                    gpio8, gpio9, gpio10, gpio11, gpio12, gpio13, gpio14,
+                    gpio15, gpio16, gpio17, gpio18, gpio19, gpio20, gpio21,
+                    gpio22, gpio23, gpio24, gpio25, gpio26, gpio27, gpio28,
+                    gpio29, gpio30, gpio31, gpio32, gpio33, gpio34, gpio35,
+                    gpio36, gpio37, gpio38, gpio39, gpio40, gpio41, gpio42,
+                    gpio43, gpio44, gpio45, gpio46, gpio47, gpio48, gpio49,
+                    gpio50, gpio51, gpio52, gpio53, gpio54, gpio55, gpio56,
+                    gpio57, gpio58, gpio59, gpio60, gpio61, gpio62, gpio63,
+                    gpio64, gpio65, gpio66, gpio67, gpio68, gpio69, gpio70,
+                    gpio71, gpio72, gpio73, gpio74, gpio75, gpio76, gpio77,
+                    gpio78, gpio79, gpio80, gpio81, gpio82, gpio83, gpio84,
+                    gpio85, gpio86, gpio87, gpio88, gpio89, gpio90, gpio91,
+                    gpio92, gpio93, gpio94, gpio95, gpio96, gpio97, gpio98,
+                    gpio99, gpio100, gpio101, gpio102, gpio103, gpio104,
+                    gpio105, gpio106, gpio107, gpio108, gpio109, gpio110,
+                    gpio111, gpio112, gpio113, gpio114, gpio115, gpio116,
+                    gpio117, gpio118, gpio119, gpio120, gpio121, gpio122,
+                    gpio123, gpio124, gpio125, gpio126, gpio127 ]
+
+        input-debounce: true
+
+      additionalProperties: false
+
+required:
+  - compatible
+  - reg
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/irq.h>
+    #include <dt-bindings/gpio/gpio.h>
+    pinctrl: pinctrl@b8003000 {
+      compatible = "nuvoton,wpcm450-pinctrl";
+      reg = <0xb8003000 0x1000>;
+      #address-cells = <1>;
+      #size-cells = <0>;
+
+      gpio0: gpio@0 {
+        reg = <0>;
+        gpio-controller;
+        #gpio-cells = <2>;
+        interrupts = <2 IRQ_TYPE_LEVEL_HIGH
+                      3 IRQ_TYPE_LEVEL_HIGH
+                      4 IRQ_TYPE_LEVEL_HIGH>;
+        nuvoton,interrupt-map = <0 16 0>;
+      };
+
+      mux_rmii2 {
+        groups = "rmii2";
+        function = "rmii2";
+      };
+
+      pinmux_uid: mux_uid {
+        groups = "gspi", "sspi";
+        function = "gpio";
+      };
+
+      pinctrl_uid: cfg_uid {
+        pins = "gpio14";
+        input-debounce = <1>;
+      };
+    };
+
+    gpio-keys {
+      compatible = "gpio-keys";
+      pinctrl-names = "default";
+      pinctrl-0 = <&pinctrl_uid>, <&pinmux_uid>;
+
+      uid {
+        label = "UID";
+        linux,code = <102>;
+        gpios = <&gpio0 14 GPIO_ACTIVE_HIGH>;
+      };
+    };
--
2.30.2


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

* [PATCH v2 5/8] pinctrl: nuvoton: Add driver for WPCM450
  2021-12-07 21:08 ` Jonathan Neuschäfer
@ 2021-12-07 21:08   ` Jonathan Neuschäfer
  -1 siblings, 0 replies; 53+ messages in thread
From: Jonathan Neuschäfer @ 2021-12-07 21:08 UTC (permalink / raw)
  To: linux-gpio, devicetree
  Cc: Linus Walleij, Rob Herring, openbmc, Tomer Maimon, Joel Stanley,
	linux-kernel, Jonathan Neuschäfer

This driver is based on the one for NPCM7xx, because the WPCM450 is a
predecessor of those SoCs. Notable differences:

- WPCM450, the GPIO registers are not organized in multiple banks, but
  rather placed continually into the same register block. This affects
  how register offsets are computed.
- Pinmux nodes can explicitly select GPIO mode, whereas, in the npcm7xx
  driver, this happens automatically when a GPIO is requested.

Some functionality implemented in the hardware was (for now) left unused
in the driver, specifically blinking and pull-up/down.

Signed-off-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>
---

This patch has a few checkpatch warnings, which are inherited from the
pinctrl-npcm7xx driver. I decided to ignore those. Specifically:
(1) WPCM450_GRPS is an unwrapped list; (2) use of -ENOTSUPP is discouraged.


v2:
- Adjust to binding change which put each GPIO bank into its own node
- Use generic GPIO support
- Make it possible to set pinmux to GPIO explicitly
- Allow building the driver as a module
- Fix spelling of "spin lock" in text
- Include <linux/mod_devicetable.h>
- Move linux/pinctrl/* headers to the end of the #include block
- Remove/rework comments and printk messages
- Switch to fwnode API
- Remove comma after sentinel {}
- Use dev_err_probe
- Improve Kconfig help message
- Declare for_each_set_bit iterator as unsigned int
- Use __assign_bit
- Set parent irq handler in set_irq_type callback
- Use struct group_desc
- Don't hide sysfs bind attributes
- Remove unnecessary check for gpio-controller property
- Use module_platform_driver()

v1:
- https://lore.kernel.org/lkml/20210602120329.2444672-6-j.neuschaefer@gmx.net/
---
 MAINTAINERS                               |    1 +
 drivers/pinctrl/Makefile                  |    2 +-
 drivers/pinctrl/nuvoton/Kconfig           |   18 +
 drivers/pinctrl/nuvoton/Makefile          |    1 +
 drivers/pinctrl/nuvoton/pinctrl-wpcm450.c | 1134 +++++++++++++++++++++
 5 files changed, 1155 insertions(+), 1 deletion(-)
 create mode 100644 drivers/pinctrl/nuvoton/pinctrl-wpcm450.c

diff --git a/MAINTAINERS b/MAINTAINERS
index eff3edafd8814..56c5c394877e1 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2352,6 +2352,7 @@ S:	Maintained
 F:	Documentation/devicetree/bindings/*/*wpcm*
 F:	arch/arm/boot/dts/nuvoton-wpcm450*
 F:	arch/arm/mach-npcm/wpcm450.c
+F:	drivers/*/*/*wpcm*
 F:	drivers/*/*wpcm*

 ARM/NXP S32G ARCHITECTURE
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index 5e63de2ffcf41..823ff12847ed3 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -58,7 +58,7 @@ obj-y				+= freescale/
 obj-$(CONFIG_X86)		+= intel/
 obj-y				+= mvebu/
 obj-y				+= nomadik/
-obj-$(CONFIG_ARCH_NPCM7XX)	+= nuvoton/
+obj-y				+= nuvoton/
 obj-$(CONFIG_PINCTRL_PXA)	+= pxa/
 obj-$(CONFIG_ARCH_QCOM)		+= qcom/
 obj-$(CONFIG_PINCTRL_RALINK)	+= ralink/
diff --git a/drivers/pinctrl/nuvoton/Kconfig b/drivers/pinctrl/nuvoton/Kconfig
index 48ba0469edda6..6a3c6f2a73f2d 100644
--- a/drivers/pinctrl/nuvoton/Kconfig
+++ b/drivers/pinctrl/nuvoton/Kconfig
@@ -1,4 +1,22 @@
 # SPDX-License-Identifier: GPL-2.0-only
+
+config PINCTRL_WPCM450
+	tristate "Pinctrl and GPIO driver for Nuvoton WPCM450"
+	depends on ARCH_WPCM450 || COMPILE_TEST
+	select PINMUX
+	select PINCONF
+	select GENERIC_PINCONF
+	select GPIOLIB
+	select GPIO_GENERIC
+	select GPIOLIB_IRQCHIP
+	help
+	  Say Y or M here to enable pin controller and GPIO support for
+	  the Nuvoton WPCM450 SoC. This is strongly recommended when
+	  building a kernel that will run on this chip.
+
+	  If this driver is compiled as a module, it will be named
+	  pinctrl-wpcm450.
+
 config PINCTRL_NPCM7XX
 	bool "Pinctrl and GPIO driver for Nuvoton NPCM7XX"
 	depends on (ARCH_NPCM7XX || COMPILE_TEST) && OF
diff --git a/drivers/pinctrl/nuvoton/Makefile b/drivers/pinctrl/nuvoton/Makefile
index 886d00784cef5..9e66f5dc74bfc 100644
--- a/drivers/pinctrl/nuvoton/Makefile
+++ b/drivers/pinctrl/nuvoton/Makefile
@@ -1,4 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0
 # Nuvoton pinctrl support

+obj-$(CONFIG_PINCTRL_WPCM450)	+= pinctrl-wpcm450.o
 obj-$(CONFIG_PINCTRL_NPCM7XX)	+= pinctrl-npcm7xx.o
diff --git a/drivers/pinctrl/nuvoton/pinctrl-wpcm450.c b/drivers/pinctrl/nuvoton/pinctrl-wpcm450.c
new file mode 100644
index 0000000000000..b1e190e45af93
--- /dev/null
+++ b/drivers/pinctrl/nuvoton/pinctrl-wpcm450.c
@@ -0,0 +1,1134 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2016-2018 Nuvoton Technology corporation.
+// Copyright (c) 2016, Dell Inc
+// Copyright (c) 2021 Jonathan Neuschäfer
+//
+// This driver uses the following registers:
+// - Pin mux registers, in the GCR (general control registers) block
+// - GPIO registers, specific to each GPIO bank
+// - GPIO event (interrupt) registers, located centrally in the GPIO register
+//   block, shared between all GPIO banks
+
+#include <linux/device.h>
+#include <linux/fwnode.h>
+#include <linux/gpio/driver.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+
+#include "../core.h"
+
+/* GCR registers */
+#define WPCM450_GCR_MFSEL1	0x0C
+#define WPCM450_GCR_MFSEL2	0x10
+#define WPCM450_GCR_NONE	0
+
+/* GPIO event (interrupt) registers */
+#define WPCM450_GPEVTYPE	0x00
+#define WPCM450_GPEVPOL		0x04
+#define WPCM450_GPEVDBNC	0x08
+#define WPCM450_GPEVEN		0x0c
+#define WPCM450_GPEVST		0x10
+
+#define WPCM450_NUM_BANKS	8
+#define WPCM450_NUM_GPIOS	128
+#define WPCM450_NUM_GPIO_IRQS	4
+
+struct wpcm450_pinctrl;
+
+struct wpcm450_gpio {
+	struct wpcm450_pinctrl	*pctrl;
+	struct gpio_chip	gc;
+	struct irq_chip		irqc;
+	unsigned int		first_irq_bit;
+	unsigned int		num_irqs;
+	unsigned int		first_irq_gpio;
+};
+
+struct wpcm450_pinctrl {
+	struct pinctrl_dev	*pctldev;
+	struct device		*dev;
+	struct irq_domain	*domain;
+	struct regmap		*gcr_regmap;
+	void __iomem		*gpio_base;
+	struct wpcm450_gpio	gpio_bank[WPCM450_NUM_BANKS];
+	unsigned long		both_edges;
+
+	/*
+	 * This spin lock protects registers and struct wpcm450_pinctrl fields
+	 * against concurrent access.
+	 */
+	spinlock_t		lock;
+};
+
+struct wpcm450_bank {
+	/* Range of GPIOs in this port */
+	u8 base;
+	u8 length;
+
+	/* Register offsets (0 = register doesn't exist in this port) */
+	u8 cfg0, cfg1, cfg2;
+	u8 blink;
+	u8 dataout, datain;
+};
+
+static const struct wpcm450_bank wpcm450_banks[WPCM450_NUM_BANKS] = {
+	/*  range   cfg0  cfg1  cfg2 blink  out   in  */
+	{   0, 16,  0x14, 0x18,    0,    0, 0x1c, 0x20 },
+	{  16, 16,  0x24, 0x28, 0x2c, 0x30, 0x34, 0x38 },
+	{  32, 16,  0x3c, 0x40, 0x44,    0, 0x48, 0x4c },
+	{  48, 16,  0x50, 0x54, 0x58,    0, 0x5c, 0x60 },
+	{  64, 16,  0x64, 0x68, 0x6c,    0, 0x70, 0x74 },
+	{  80, 16,  0x78, 0x7c, 0x80,    0, 0x84, 0x88 },
+	{  96, 18,     0,    0,    0,    0,    0, 0x8c },
+	{ 114, 14,  0x90, 0x94, 0x98,    0, 0x9c, 0xa0 },
+};
+
+static int wpcm450_gpio_irq_bitnum(struct wpcm450_gpio *gpio, struct irq_data *d)
+{
+	int hwirq = irqd_to_hwirq(d);
+
+	if (hwirq < gpio->first_irq_gpio)
+		return -EINVAL;
+
+	if (hwirq - gpio->first_irq_gpio >= gpio->num_irqs)
+		return -EINVAL;
+
+	return hwirq - gpio->first_irq_gpio + gpio->first_irq_bit;
+}
+
+static int wpcm450_irq_bitnum_to_gpio(struct wpcm450_gpio *gpio, int bitnum)
+{
+	if (bitnum < gpio->first_irq_bit)
+		return -EINVAL;
+
+	if (bitnum - gpio->first_irq_bit > gpio->num_irqs)
+		return -EINVAL;
+
+	return bitnum - gpio->first_irq_bit + gpio->first_irq_gpio;
+}
+
+static void wpcm450_gpio_irq_ack(struct irq_data *d)
+{
+	struct wpcm450_gpio *gpio = gpiochip_get_data(irq_data_get_irq_chip_data(d));
+	struct wpcm450_pinctrl *pctrl = gpio->pctrl;
+	unsigned long flags;
+	int bit;
+
+	bit = wpcm450_gpio_irq_bitnum(gpio, d);
+	if (bit < 0)
+		return;
+
+	spin_lock_irqsave(&pctrl->lock, flags);
+	iowrite32(BIT(bit), pctrl->gpio_base + WPCM450_GPEVST);
+	spin_unlock_irqrestore(&pctrl->lock, flags);
+}
+
+static void wpcm450_gpio_irq_mask(struct irq_data *d)
+{
+	struct wpcm450_gpio *gpio = gpiochip_get_data(irq_data_get_irq_chip_data(d));
+	struct wpcm450_pinctrl *pctrl = gpio->pctrl;
+	unsigned long flags;
+	unsigned long even;
+	int bit;
+
+	bit = wpcm450_gpio_irq_bitnum(gpio, d);
+	if (bit < 0)
+		return;
+
+	spin_lock_irqsave(&pctrl->lock, flags);
+	even = ioread32(pctrl->gpio_base + WPCM450_GPEVEN);
+	__assign_bit(bit, &even, 0);
+	iowrite32(even, pctrl->gpio_base + WPCM450_GPEVEN);
+	spin_unlock_irqrestore(&pctrl->lock, flags);
+}
+
+static void wpcm450_gpio_irq_unmask(struct irq_data *d)
+{
+	struct wpcm450_gpio *gpio = gpiochip_get_data(irq_data_get_irq_chip_data(d));
+	struct wpcm450_pinctrl *pctrl = gpio->pctrl;
+	unsigned long flags;
+	unsigned long even;
+	int bit;
+
+	bit = wpcm450_gpio_irq_bitnum(gpio, d);
+	if (bit < 0)
+		return;
+
+	spin_lock_irqsave(&pctrl->lock, flags);
+	even = ioread32(pctrl->gpio_base + WPCM450_GPEVEN);
+	__assign_bit(bit, &even, 1);
+	iowrite32(even, pctrl->gpio_base + WPCM450_GPEVEN);
+	spin_unlock_irqrestore(&pctrl->lock, flags);
+}
+
+static void wpcm450_gpio_fix_evpol(struct wpcm450_gpio *gpio, unsigned long all)
+{
+	struct wpcm450_pinctrl *pctrl = gpio->pctrl;
+	unsigned long flags;
+	unsigned int bit;
+
+	for_each_set_bit(bit, &all, 32) {
+		int offset = wpcm450_irq_bitnum_to_gpio(gpio, bit);
+		unsigned long evpol;
+		int level;
+
+		spin_lock_irqsave(&gpio->gc.bgpio_lock, flags);
+		do {
+			evpol = ioread32(pctrl->gpio_base + WPCM450_GPEVPOL);
+			level = gpio->gc.get(&gpio->gc, offset);
+
+			/* Switch event polarity to the opposite of the current level */
+			__assign_bit(bit, &evpol, !level);
+
+			iowrite32(evpol, pctrl->gpio_base + WPCM450_GPEVPOL);
+		} while (gpio->gc.get(&gpio->gc, offset) != level);
+		spin_unlock_irqrestore(&gpio->gc.bgpio_lock, flags);
+	}
+}
+
+static int wpcm450_gpio_set_irq_type(struct irq_data *d, unsigned int flow_type)
+{
+	struct wpcm450_gpio *gpio = gpiochip_get_data(irq_data_get_irq_chip_data(d));
+	struct wpcm450_pinctrl *pctrl = gpio->pctrl;
+	unsigned long evtype, evpol;
+	unsigned long flags;
+	int ret = 0;
+	int bit;
+
+	bit = wpcm450_gpio_irq_bitnum(gpio, d);
+	if (bit < 0)
+		return bit;
+
+	irq_set_handler_locked(d, handle_level_irq);
+
+	spin_lock_irqsave(&pctrl->lock, flags);
+	evtype = ioread32(pctrl->gpio_base + WPCM450_GPEVTYPE);
+	evpol = ioread32(pctrl->gpio_base + WPCM450_GPEVPOL);
+	__assign_bit(bit, &pctrl->both_edges, 0);
+	switch (flow_type) {
+	case IRQ_TYPE_LEVEL_LOW:
+		__assign_bit(bit, &evtype, 1);
+		__assign_bit(bit, &evpol, 0);
+		break;
+	case IRQ_TYPE_LEVEL_HIGH:
+		__assign_bit(bit, &evtype, 1);
+		__assign_bit(bit, &evpol, 1);
+		break;
+	case IRQ_TYPE_EDGE_FALLING:
+		__assign_bit(bit, &evtype, 0);
+		__assign_bit(bit, &evpol, 0);
+		break;
+	case IRQ_TYPE_EDGE_RISING:
+		__assign_bit(bit, &evtype, 0);
+		__assign_bit(bit, &evpol, 1);
+		break;
+	case IRQ_TYPE_EDGE_BOTH:
+		__assign_bit(bit, &evtype, 0);
+		__assign_bit(bit, &pctrl->both_edges, 1);
+		break;
+	default:
+		ret = -EINVAL;
+	}
+	iowrite32(evtype, pctrl->gpio_base + WPCM450_GPEVTYPE);
+	iowrite32(evpol, pctrl->gpio_base + WPCM450_GPEVPOL);
+
+	/* clear the event status for good measure */
+	iowrite32(BIT(bit), pctrl->gpio_base + WPCM450_GPEVST);
+
+	/* fix event polarity after clearing event status */
+	wpcm450_gpio_fix_evpol(gpio, BIT(bit));
+
+	spin_unlock_irqrestore(&pctrl->lock, flags);
+
+	return ret;
+}
+
+static const struct irq_chip wpcm450_gpio_irqchip = {
+	.name = "WPCM450-GPIO-IRQ",
+	.irq_ack = wpcm450_gpio_irq_ack,
+	.irq_unmask = wpcm450_gpio_irq_unmask,
+	.irq_mask = wpcm450_gpio_irq_mask,
+	.irq_set_type = wpcm450_gpio_set_irq_type,
+};
+
+static void wpcm450_gpio_irqhandler(struct irq_desc *desc)
+{
+	struct wpcm450_gpio *gpio = gpiochip_get_data(irq_desc_get_handler_data(desc));
+	struct wpcm450_pinctrl *pctrl = gpio->pctrl;
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+	unsigned long pending;
+	unsigned long flags;
+	unsigned long ours;
+	unsigned int bit;
+
+	ours = ((1UL << gpio->num_irqs) - 1) << gpio->first_irq_bit;
+
+	spin_lock_irqsave(&pctrl->lock, flags);
+
+	pending = ioread32(pctrl->gpio_base + WPCM450_GPEVST);
+	pending &= ioread32(pctrl->gpio_base + WPCM450_GPEVEN);
+	pending &= ours;
+
+	if (pending & pctrl->both_edges)
+		wpcm450_gpio_fix_evpol(gpio, pending & pctrl->both_edges);
+
+	spin_unlock_irqrestore(&pctrl->lock, flags);
+
+	chained_irq_enter(chip, desc);
+	for_each_set_bit(bit, &pending, 32) {
+		int offset = wpcm450_irq_bitnum_to_gpio(gpio, bit);
+		int irq = irq_find_mapping(gpio->gc.irq.domain, offset);
+
+		generic_handle_irq(irq);
+	}
+	chained_irq_exit(chip, desc);
+}
+
+static int smb0_pins[]  = { 115, 114 };
+static int smb1_pins[]  = { 117, 116 };
+static int smb2_pins[]  = { 119, 118 };
+static int smb3_pins[]  = { 30, 31 };
+static int smb4_pins[]  = { 28, 29 };
+static int smb5_pins[]  = { 26, 27 };
+
+static int scs1_pins[] = { 32 };
+static int scs2_pins[] = { 33 };
+static int scs3_pins[] = { 34 };
+
+static int bsp_pins[] = { 41, 42 };
+static int hsp1_pins[] = { 43, 44, 45, 46, 47, 61, 62, 63 };
+static int hsp2_pins[] = { 48, 49, 50, 51, 52, 53, 54, 55 };
+
+static int r1err_pins[] = { 56 };
+static int r1md_pins[] = { 57, 58 };
+static int rmii2_pins[] = { 84, 85, 86, 87, 88, 89 };
+static int r2err_pins[] = { 90 };
+static int r2md_pins[] = { 91, 92 };
+
+static int kbcc_pins[] = { 94, 93 };
+static int clko_pins[] = { 96 };
+static int smi_pins[] = { 97 };
+static int uinc_pins[] = { 19 };
+static int mben_pins[] = {};
+
+static int gspi_pins[] = { 12, 13, 14, 15 };
+static int sspi_pins[] = { 12, 13, 14, 15 };
+
+static int xcs1_pins[] = { 35 };
+static int xcs2_pins[] = { 36 };
+
+static int sdio_pins[] = { 7, 22, 43, 44, 45, 46, 47, 60 };
+
+static int fi0_pins[] = { 64 };
+static int fi1_pins[] = { 65 };
+static int fi2_pins[] = { 66 };
+static int fi3_pins[] = { 67 };
+static int fi4_pins[] = { 68 };
+static int fi5_pins[] = { 69 };
+static int fi6_pins[] = { 70 };
+static int fi7_pins[] = { 71 };
+static int fi8_pins[] = { 72 };
+static int fi9_pins[] = { 73 };
+static int fi10_pins[] = { 74 };
+static int fi11_pins[] = { 75 };
+static int fi12_pins[] = { 76 };
+static int fi13_pins[] = { 77 };
+static int fi14_pins[] = { 78 };
+static int fi15_pins[] = { 79 };
+
+static int pwm0_pins[] = { 80 };
+static int pwm1_pins[] = { 81 };
+static int pwm2_pins[] = { 82 };
+static int pwm3_pins[] = { 83 };
+static int pwm4_pins[] = { 20 };
+static int pwm5_pins[] = { 21 };
+static int pwm6_pins[] = { 16 };
+static int pwm7_pins[] = { 17 };
+
+static int hg0_pins[] = { 20 };
+static int hg1_pins[] = { 21 };
+static int hg2_pins[] = { 22 };
+static int hg3_pins[] = { 23 };
+static int hg4_pins[] = { 24 };
+static int hg5_pins[] = { 25 };
+static int hg6_pins[] = { 59 };
+static int hg7_pins[] = { 60 };
+
+#define WPCM450_GRPS \
+	WPCM450_GRP(smb3), \
+	WPCM450_GRP(smb4), \
+	WPCM450_GRP(smb5), \
+	WPCM450_GRP(scs1), \
+	WPCM450_GRP(scs2), \
+	WPCM450_GRP(scs3), \
+	WPCM450_GRP(smb0), \
+	WPCM450_GRP(smb1), \
+	WPCM450_GRP(smb2), \
+	WPCM450_GRP(bsp), \
+	WPCM450_GRP(hsp1), \
+	WPCM450_GRP(hsp2), \
+	WPCM450_GRP(r1err), \
+	WPCM450_GRP(r1md), \
+	WPCM450_GRP(rmii2), \
+	WPCM450_GRP(r2err), \
+	WPCM450_GRP(r2md), \
+	WPCM450_GRP(kbcc), \
+	WPCM450_GRP(clko), \
+	WPCM450_GRP(smi), \
+	WPCM450_GRP(uinc), \
+	WPCM450_GRP(gspi), \
+	WPCM450_GRP(mben), \
+	WPCM450_GRP(xcs2), \
+	WPCM450_GRP(xcs1), \
+	WPCM450_GRP(sdio), \
+	WPCM450_GRP(sspi), \
+	WPCM450_GRP(fi0), \
+	WPCM450_GRP(fi1), \
+	WPCM450_GRP(fi2), \
+	WPCM450_GRP(fi3), \
+	WPCM450_GRP(fi4), \
+	WPCM450_GRP(fi5), \
+	WPCM450_GRP(fi6), \
+	WPCM450_GRP(fi7), \
+	WPCM450_GRP(fi8), \
+	WPCM450_GRP(fi9), \
+	WPCM450_GRP(fi10), \
+	WPCM450_GRP(fi11), \
+	WPCM450_GRP(fi12), \
+	WPCM450_GRP(fi13), \
+	WPCM450_GRP(fi14), \
+	WPCM450_GRP(fi15), \
+	WPCM450_GRP(pwm0), \
+	WPCM450_GRP(pwm1), \
+	WPCM450_GRP(pwm2), \
+	WPCM450_GRP(pwm3), \
+	WPCM450_GRP(pwm4), \
+	WPCM450_GRP(pwm5), \
+	WPCM450_GRP(pwm6), \
+	WPCM450_GRP(pwm7), \
+	WPCM450_GRP(hg0), \
+	WPCM450_GRP(hg1), \
+	WPCM450_GRP(hg2), \
+	WPCM450_GRP(hg3), \
+	WPCM450_GRP(hg4), \
+	WPCM450_GRP(hg5), \
+	WPCM450_GRP(hg6), \
+	WPCM450_GRP(hg7), \
+
+enum {
+#define WPCM450_GRP(x) fn_ ## x
+	WPCM450_GRPS
+	/* add placeholder for none/gpio */
+	WPCM450_GRP(gpio),
+	WPCM450_GRP(none),
+#undef WPCM450_GRP
+};
+
+static struct group_desc wpcm450_groups[] = {
+#define WPCM450_GRP(x) { .name = #x, .pins = x ## _pins, \
+			.num_pins = ARRAY_SIZE(x ## _pins) }
+	WPCM450_GRPS
+#undef WPCM450_GRP
+};
+
+#define WPCM450_SFUNC(a) WPCM450_FUNC(a, #a)
+#define WPCM450_FUNC(a, b...) static const char *a ## _grp[] = { b }
+#define WPCM450_MKFUNC(nm) { .name = #nm, .ngroups = ARRAY_SIZE(nm ## _grp), \
+			.groups = nm ## _grp }
+struct wpcm450_func {
+	const char *name;
+	const unsigned int ngroups;
+	const char *const *groups;
+};
+
+WPCM450_SFUNC(smb3);
+WPCM450_SFUNC(smb4);
+WPCM450_SFUNC(smb5);
+WPCM450_SFUNC(scs1);
+WPCM450_SFUNC(scs2);
+WPCM450_SFUNC(scs3);
+WPCM450_SFUNC(smb0);
+WPCM450_SFUNC(smb1);
+WPCM450_SFUNC(smb2);
+WPCM450_SFUNC(bsp);
+WPCM450_SFUNC(hsp1);
+WPCM450_SFUNC(hsp2);
+WPCM450_SFUNC(r1err);
+WPCM450_SFUNC(r1md);
+WPCM450_SFUNC(rmii2);
+WPCM450_SFUNC(r2err);
+WPCM450_SFUNC(r2md);
+WPCM450_SFUNC(kbcc);
+WPCM450_SFUNC(clko);
+WPCM450_SFUNC(smi);
+WPCM450_SFUNC(uinc);
+WPCM450_SFUNC(gspi);
+WPCM450_SFUNC(mben);
+WPCM450_SFUNC(xcs2);
+WPCM450_SFUNC(xcs1);
+WPCM450_SFUNC(sdio);
+WPCM450_SFUNC(sspi);
+WPCM450_SFUNC(fi0);
+WPCM450_SFUNC(fi1);
+WPCM450_SFUNC(fi2);
+WPCM450_SFUNC(fi3);
+WPCM450_SFUNC(fi4);
+WPCM450_SFUNC(fi5);
+WPCM450_SFUNC(fi6);
+WPCM450_SFUNC(fi7);
+WPCM450_SFUNC(fi8);
+WPCM450_SFUNC(fi9);
+WPCM450_SFUNC(fi10);
+WPCM450_SFUNC(fi11);
+WPCM450_SFUNC(fi12);
+WPCM450_SFUNC(fi13);
+WPCM450_SFUNC(fi14);
+WPCM450_SFUNC(fi15);
+WPCM450_SFUNC(pwm0);
+WPCM450_SFUNC(pwm1);
+WPCM450_SFUNC(pwm2);
+WPCM450_SFUNC(pwm3);
+WPCM450_SFUNC(pwm4);
+WPCM450_SFUNC(pwm5);
+WPCM450_SFUNC(pwm6);
+WPCM450_SFUNC(pwm7);
+WPCM450_SFUNC(hg0);
+WPCM450_SFUNC(hg1);
+WPCM450_SFUNC(hg2);
+WPCM450_SFUNC(hg3);
+WPCM450_SFUNC(hg4);
+WPCM450_SFUNC(hg5);
+WPCM450_SFUNC(hg6);
+WPCM450_SFUNC(hg7);
+
+#define WPCM450_GRP(x) #x
+WPCM450_FUNC(gpio, WPCM450_GRPS);
+#undef WPCM450_GRP
+
+/* Function names */
+static struct wpcm450_func wpcm450_funcs[] = {
+	WPCM450_MKFUNC(smb3),
+	WPCM450_MKFUNC(smb4),
+	WPCM450_MKFUNC(smb5),
+	WPCM450_MKFUNC(scs1),
+	WPCM450_MKFUNC(scs2),
+	WPCM450_MKFUNC(scs3),
+	WPCM450_MKFUNC(smb0),
+	WPCM450_MKFUNC(smb1),
+	WPCM450_MKFUNC(smb2),
+	WPCM450_MKFUNC(bsp),
+	WPCM450_MKFUNC(hsp1),
+	WPCM450_MKFUNC(hsp2),
+	WPCM450_MKFUNC(r1err),
+	WPCM450_MKFUNC(r1md),
+	WPCM450_MKFUNC(rmii2),
+	WPCM450_MKFUNC(r2err),
+	WPCM450_MKFUNC(r2md),
+	WPCM450_MKFUNC(kbcc),
+	WPCM450_MKFUNC(clko),
+	WPCM450_MKFUNC(smi),
+	WPCM450_MKFUNC(uinc),
+	WPCM450_MKFUNC(gspi),
+	WPCM450_MKFUNC(mben),
+	WPCM450_MKFUNC(xcs2),
+	WPCM450_MKFUNC(xcs1),
+	WPCM450_MKFUNC(sdio),
+	WPCM450_MKFUNC(sspi),
+	WPCM450_MKFUNC(fi0),
+	WPCM450_MKFUNC(fi1),
+	WPCM450_MKFUNC(fi2),
+	WPCM450_MKFUNC(fi3),
+	WPCM450_MKFUNC(fi4),
+	WPCM450_MKFUNC(fi5),
+	WPCM450_MKFUNC(fi6),
+	WPCM450_MKFUNC(fi7),
+	WPCM450_MKFUNC(fi8),
+	WPCM450_MKFUNC(fi9),
+	WPCM450_MKFUNC(fi10),
+	WPCM450_MKFUNC(fi11),
+	WPCM450_MKFUNC(fi12),
+	WPCM450_MKFUNC(fi13),
+	WPCM450_MKFUNC(fi14),
+	WPCM450_MKFUNC(fi15),
+	WPCM450_MKFUNC(pwm0),
+	WPCM450_MKFUNC(pwm1),
+	WPCM450_MKFUNC(pwm2),
+	WPCM450_MKFUNC(pwm3),
+	WPCM450_MKFUNC(pwm4),
+	WPCM450_MKFUNC(pwm5),
+	WPCM450_MKFUNC(pwm6),
+	WPCM450_MKFUNC(pwm7),
+	WPCM450_MKFUNC(hg0),
+	WPCM450_MKFUNC(hg1),
+	WPCM450_MKFUNC(hg2),
+	WPCM450_MKFUNC(hg3),
+	WPCM450_MKFUNC(hg4),
+	WPCM450_MKFUNC(hg5),
+	WPCM450_MKFUNC(hg6),
+	WPCM450_MKFUNC(hg7),
+	WPCM450_MKFUNC(gpio),
+};
+
+#define WPCM450_PINCFG(a, b, c, d, e, f, g) \
+	[a] { .fn0 = fn_ ## b, .reg0 = WPCM450_GCR_ ## c, .bit0 = d, \
+	      .fn1 = fn_ ## e, .reg1 = WPCM450_GCR_ ## f, .bit1 = g }
+
+struct wpcm450_pincfg {
+	int fn0, reg0, bit0;
+	int fn1, reg1, bit1;
+};
+
+static const struct wpcm450_pincfg pincfg[] = {
+	/*		PIN	  FUNCTION 1		   FUNCTION 2 */
+	WPCM450_PINCFG(0,	 none, NONE, 0,		  none, NONE, 0),
+	WPCM450_PINCFG(1,	 none, NONE, 0,		  none, NONE, 0),
+	WPCM450_PINCFG(2,	 none, NONE, 0,		  none, NONE, 0),
+	WPCM450_PINCFG(3,	 none, NONE, 0,		  none, NONE, 0),
+	WPCM450_PINCFG(4,	 none, NONE, 0,		  none, NONE, 0),
+	WPCM450_PINCFG(5,	 none, NONE, 0,		  none, NONE, 0),
+	WPCM450_PINCFG(6,	 none, NONE, 0,		  none, NONE, 0),
+	WPCM450_PINCFG(7,	 none, NONE, 0,		  sdio, MFSEL1, 30),
+	WPCM450_PINCFG(8,	 none, NONE, 0,		  none, NONE, 0),
+	WPCM450_PINCFG(9,	 none, NONE, 0,		  none, NONE, 0),
+	WPCM450_PINCFG(10,	 none, NONE, 0,		  none, NONE, 0),
+	WPCM450_PINCFG(11,	 none, NONE, 0,		  none, NONE, 0),
+	WPCM450_PINCFG(12,	 gspi, MFSEL1, 24,	  sspi, MFSEL1, 31),
+	WPCM450_PINCFG(13,	 gspi, MFSEL1, 24,	  sspi, MFSEL1, 31),
+	WPCM450_PINCFG(14,	 gspi, MFSEL1, 24,	  sspi, MFSEL1, 31),
+	WPCM450_PINCFG(15,	 gspi, MFSEL1, 24,	  sspi, MFSEL1, 31),
+	WPCM450_PINCFG(16,	 none, NONE, 0,		  pwm6, MFSEL2, 22),
+	WPCM450_PINCFG(17,	 none, NONE, 0,		  pwm7, MFSEL2, 23),
+	WPCM450_PINCFG(18,	 none, NONE, 0,		  none, NONE, 0),
+	WPCM450_PINCFG(19,	 uinc, MFSEL1, 23,	  none, NONE, 0),
+	WPCM450_PINCFG(20,	  hg0, MFSEL2, 24,	  pwm4, MFSEL2, 20),
+	WPCM450_PINCFG(21,	  hg1, MFSEL2, 25,	  pwm5, MFSEL2, 21),
+	WPCM450_PINCFG(22,	  hg2, MFSEL2, 26,	  none, NONE, 0),
+	WPCM450_PINCFG(23,	  hg3, MFSEL2, 27,	  none, NONE, 0),
+	WPCM450_PINCFG(24,	  hg4, MFSEL2, 28,	  none, NONE, 0),
+	WPCM450_PINCFG(25,	  hg5, MFSEL2, 29,	  none, NONE, 0),
+	WPCM450_PINCFG(26,	 smb5, MFSEL1, 2,	  none, NONE, 0),
+	WPCM450_PINCFG(27,	 smb5, MFSEL1, 2,	  none, NONE, 0),
+	WPCM450_PINCFG(28,	 smb4, MFSEL1, 1,	  none, NONE, 0),
+	WPCM450_PINCFG(29,	 smb4, MFSEL1, 1,	  none, NONE, 0),
+	WPCM450_PINCFG(30,	 smb3, MFSEL1, 0,	  none, NONE, 0),
+	WPCM450_PINCFG(31,	 smb3, MFSEL1, 0,	  none, NONE, 0),
+
+	WPCM450_PINCFG(32,	 scs1, MFSEL1, 3,	  none, NONE, 0),
+	WPCM450_PINCFG(33,	 scs2, MFSEL1, 4,	  none, NONE, 0),
+	WPCM450_PINCFG(34,	 scs3, MFSEL1, 5,	  none, NONE, 0),
+	WPCM450_PINCFG(35,	 xcs1, MFSEL1, 29,	  none, NONE, 0),
+	WPCM450_PINCFG(36,	 xcs2, MFSEL1, 28,	  none, NONE, 0),
+	WPCM450_PINCFG(37,	 none, NONE, 0,		  none, NONE, 0), /* DVO */
+	WPCM450_PINCFG(38,	 none, NONE, 0,		  none, NONE, 0), /* DVO */
+	WPCM450_PINCFG(39,	 none, NONE, 0,		  none, NONE, 0), /* DVO */
+	WPCM450_PINCFG(40,	 none, NONE, 0,		  none, NONE, 0), /* DVO */
+	WPCM450_PINCFG(41,	  bsp, MFSEL1, 9,	  none, NONE, 0),
+	WPCM450_PINCFG(42,	  bsp, MFSEL1, 9,	  none, NONE, 0),
+	WPCM450_PINCFG(43,	 hsp1, MFSEL1, 10,	  sdio, MFSEL1, 30),
+	WPCM450_PINCFG(44,	 hsp1, MFSEL1, 10,	  sdio, MFSEL1, 30),
+	WPCM450_PINCFG(45,	 hsp1, MFSEL1, 10,	  sdio, MFSEL1, 30),
+	WPCM450_PINCFG(46,	 hsp1, MFSEL1, 10,	  sdio, MFSEL1, 30),
+	WPCM450_PINCFG(47,	 hsp1, MFSEL1, 10,	  sdio, MFSEL1, 30),
+	WPCM450_PINCFG(48,	 hsp2, MFSEL1, 11,	  none, NONE, 0),
+	WPCM450_PINCFG(49,	 hsp2, MFSEL1, 11,	  none, NONE, 0),
+	WPCM450_PINCFG(50,	 hsp2, MFSEL1, 11,	  none, NONE, 0),
+	WPCM450_PINCFG(51,	 hsp2, MFSEL1, 11,	  none, NONE, 0),
+	WPCM450_PINCFG(52,	 hsp2, MFSEL1, 11,	  none, NONE, 0),
+	WPCM450_PINCFG(53,	 hsp2, MFSEL1, 11,	  none, NONE, 0),
+	WPCM450_PINCFG(54,	 hsp2, MFSEL1, 11,	  none, NONE, 0),
+	WPCM450_PINCFG(55,	 hsp2, MFSEL1, 11,	  none, NONE, 0),
+	WPCM450_PINCFG(56,	r1err, MFSEL1, 12,	  none, NONE, 0),
+	WPCM450_PINCFG(57,	 r1md, MFSEL1, 13,	  none, NONE, 0),
+	WPCM450_PINCFG(58,	 r1md, MFSEL1, 13,	  none, NONE, 0),
+	WPCM450_PINCFG(59,	  hg6, MFSEL2, 30,	  none, NONE, 0),
+	WPCM450_PINCFG(60,	  hg7, MFSEL2, 31,	  sdio, MFSEL1, 30),
+	WPCM450_PINCFG(61,	 hsp1, MFSEL1, 10,	  none, NONE, 0),
+	WPCM450_PINCFG(62,	 hsp1, MFSEL1, 10,	  none, NONE, 0),
+	WPCM450_PINCFG(63,	 hsp1, MFSEL1, 10,	  none, NONE, 0),
+
+	WPCM450_PINCFG(64,	  fi0, MFSEL2, 0,	  none, NONE, 0),
+	WPCM450_PINCFG(65,	  fi1, MFSEL2, 1,	  none, NONE, 0),
+	WPCM450_PINCFG(66,	  fi2, MFSEL2, 2,	  none, NONE, 0),
+	WPCM450_PINCFG(67,	  fi3, MFSEL2, 3,	  none, NONE, 0),
+	WPCM450_PINCFG(68,	  fi4, MFSEL2, 4,	  none, NONE, 0),
+	WPCM450_PINCFG(69,	  fi5, MFSEL2, 5,	  none, NONE, 0),
+	WPCM450_PINCFG(70,	  fi6, MFSEL2, 6,	  none, NONE, 0),
+	WPCM450_PINCFG(71,	  fi7, MFSEL2, 7,	  none, NONE, 0),
+	WPCM450_PINCFG(72,	  fi8, MFSEL2, 8,	  none, NONE, 0),
+	WPCM450_PINCFG(73,	  fi9, MFSEL2, 9,	  none, NONE, 0),
+	WPCM450_PINCFG(74,	 fi10, MFSEL2, 10,	  none, NONE, 0),
+	WPCM450_PINCFG(75,	 fi11, MFSEL2, 11,	  none, NONE, 0),
+	WPCM450_PINCFG(76,	 fi12, MFSEL2, 12,	  none, NONE, 0),
+	WPCM450_PINCFG(77,	 fi13, MFSEL2, 13,	  none, NONE, 0),
+	WPCM450_PINCFG(78,	 fi14, MFSEL2, 14,	  none, NONE, 0),
+	WPCM450_PINCFG(79,	 fi15, MFSEL2, 15,	  none, NONE, 0),
+	WPCM450_PINCFG(80,	 pwm0, MFSEL2, 16,	  none, NONE, 0),
+	WPCM450_PINCFG(81,	 pwm1, MFSEL2, 17,	  none, NONE, 0),
+	WPCM450_PINCFG(82,	 pwm2, MFSEL2, 18,	  none, NONE, 0),
+	WPCM450_PINCFG(83,	 pwm3, MFSEL2, 19,	  none, NONE, 0),
+	WPCM450_PINCFG(84,	rmii2, MFSEL1, 14,	  none, NONE, 0),
+	WPCM450_PINCFG(85,	rmii2, MFSEL1, 14,	  none, NONE, 0),
+	WPCM450_PINCFG(86,	rmii2, MFSEL1, 14,	  none, NONE, 0),
+	WPCM450_PINCFG(87,	rmii2, MFSEL1, 14,	  none, NONE, 0),
+	WPCM450_PINCFG(88,	rmii2, MFSEL1, 14,	  none, NONE, 0),
+	WPCM450_PINCFG(89,	rmii2, MFSEL1, 14,	  none, NONE, 0),
+	WPCM450_PINCFG(90,	r2err, MFSEL1, 15,	  none, NONE, 0),
+	WPCM450_PINCFG(91,	 r2md, MFSEL1, 16,	  none, NONE, 0),
+	WPCM450_PINCFG(92,	 r2md, MFSEL1, 16,	  none, NONE, 0),
+	WPCM450_PINCFG(93,	 kbcc, MFSEL1, 17,	  none, NONE, 0),
+	WPCM450_PINCFG(94,	 kbcc, MFSEL1, 17,	  none, NONE, 0),
+	WPCM450_PINCFG(95,	 none, NONE, 0,		  none, NONE, 0),
+
+	WPCM450_PINCFG(96,	 none, NONE, 0,		  none, NONE, 0),
+	WPCM450_PINCFG(97,	 none, NONE, 0,		  none, NONE, 0),
+	WPCM450_PINCFG(98,	 none, NONE, 0,		  none, NONE, 0),
+	WPCM450_PINCFG(99,	 none, NONE, 0,		  none, NONE, 0),
+	WPCM450_PINCFG(100,	 none, NONE, 0,		  none, NONE, 0),
+	WPCM450_PINCFG(101,	 none, NONE, 0,		  none, NONE, 0),
+	WPCM450_PINCFG(102,	 none, NONE, 0,		  none, NONE, 0),
+	WPCM450_PINCFG(103,	 none, NONE, 0,		  none, NONE, 0),
+	WPCM450_PINCFG(104,	 none, NONE, 0,		  none, NONE, 0),
+	WPCM450_PINCFG(105,	 none, NONE, 0,		  none, NONE, 0),
+	WPCM450_PINCFG(106,	 none, NONE, 0,		  none, NONE, 0),
+	WPCM450_PINCFG(107,	 none, NONE, 0,		  none, NONE, 0),
+	WPCM450_PINCFG(108,	 none, NONE, 0,		  none, NONE, 0), /* DVO */
+	WPCM450_PINCFG(109,	 none, NONE, 0,		  none, NONE, 0), /* DVO */
+	WPCM450_PINCFG(110,	 none, NONE, 0,		  none, NONE, 0), /* DVO */
+	WPCM450_PINCFG(111,	 none, NONE, 0,		  none, NONE, 0), /* DVO */
+	WPCM450_PINCFG(112,	 none, NONE, 0,		  none, NONE, 0), /* DVO */
+	WPCM450_PINCFG(113,	 none, NONE, 0,		  none, NONE, 0), /* DVO */
+	WPCM450_PINCFG(114,	 smb0, MFSEL1, 6,	  none, NONE, 0),
+	WPCM450_PINCFG(115,	 smb0, MFSEL1, 6,	  none, NONE, 0),
+	WPCM450_PINCFG(116,	 smb1, MFSEL1, 7,	  none, NONE, 0),
+	WPCM450_PINCFG(117,	 smb1, MFSEL1, 7,	  none, NONE, 0),
+	WPCM450_PINCFG(118,	 smb2, MFSEL1, 8,	  none, NONE, 0),
+	WPCM450_PINCFG(119,	 smb2, MFSEL1, 8,	  none, NONE, 0),
+	WPCM450_PINCFG(120,	 none, NONE, 0,		  none, NONE, 0), /* DVO */
+	WPCM450_PINCFG(121,	 none, NONE, 0,		  none, NONE, 0), /* DVO */
+	WPCM450_PINCFG(122,	 none, NONE, 0,		  none, NONE, 0), /* DVO */
+	WPCM450_PINCFG(123,	 none, NONE, 0,		  none, NONE, 0), /* DVO */
+	WPCM450_PINCFG(124,	 none, NONE, 0,		  none, NONE, 0), /* DVO */
+	WPCM450_PINCFG(125,	 none, NONE, 0,		  none, NONE, 0), /* DVO */
+	WPCM450_PINCFG(126,	 none, NONE, 0,		  none, NONE, 0), /* DVO */
+	WPCM450_PINCFG(127,	 none, NONE, 0,		  none, NONE, 0), /* DVO */
+};
+
+#define WPCM450_PIN(n)		PINCTRL_PIN(n, "gpio" #n)
+
+static const struct pinctrl_pin_desc wpcm450_pins[] = {
+	WPCM450_PIN(0),   WPCM450_PIN(1),   WPCM450_PIN(2),   WPCM450_PIN(3),
+	WPCM450_PIN(4),   WPCM450_PIN(5),   WPCM450_PIN(6),   WPCM450_PIN(7),
+	WPCM450_PIN(8),   WPCM450_PIN(9),   WPCM450_PIN(10),  WPCM450_PIN(11),
+	WPCM450_PIN(12),  WPCM450_PIN(13),  WPCM450_PIN(14),  WPCM450_PIN(15),
+	WPCM450_PIN(16),  WPCM450_PIN(17),  WPCM450_PIN(18),  WPCM450_PIN(19),
+	WPCM450_PIN(20),  WPCM450_PIN(21),  WPCM450_PIN(22),  WPCM450_PIN(23),
+	WPCM450_PIN(24),  WPCM450_PIN(25),  WPCM450_PIN(26),  WPCM450_PIN(27),
+	WPCM450_PIN(28),  WPCM450_PIN(29),  WPCM450_PIN(30),  WPCM450_PIN(31),
+	WPCM450_PIN(32),  WPCM450_PIN(33),  WPCM450_PIN(34),  WPCM450_PIN(35),
+	WPCM450_PIN(36),  WPCM450_PIN(37),  WPCM450_PIN(38),  WPCM450_PIN(39),
+	WPCM450_PIN(40),  WPCM450_PIN(41),  WPCM450_PIN(42),  WPCM450_PIN(43),
+	WPCM450_PIN(44),  WPCM450_PIN(45),  WPCM450_PIN(46),  WPCM450_PIN(47),
+	WPCM450_PIN(48),  WPCM450_PIN(49),  WPCM450_PIN(50),  WPCM450_PIN(51),
+	WPCM450_PIN(52),  WPCM450_PIN(53),  WPCM450_PIN(54),  WPCM450_PIN(55),
+	WPCM450_PIN(56),  WPCM450_PIN(57),  WPCM450_PIN(58),  WPCM450_PIN(59),
+	WPCM450_PIN(60),  WPCM450_PIN(61),  WPCM450_PIN(62),  WPCM450_PIN(63),
+	WPCM450_PIN(64),  WPCM450_PIN(65),  WPCM450_PIN(66),  WPCM450_PIN(67),
+	WPCM450_PIN(68),  WPCM450_PIN(69),  WPCM450_PIN(70),  WPCM450_PIN(71),
+	WPCM450_PIN(72),  WPCM450_PIN(73),  WPCM450_PIN(74),  WPCM450_PIN(75),
+	WPCM450_PIN(76),  WPCM450_PIN(77),  WPCM450_PIN(78),  WPCM450_PIN(79),
+	WPCM450_PIN(80),  WPCM450_PIN(81),  WPCM450_PIN(82),  WPCM450_PIN(83),
+	WPCM450_PIN(84),  WPCM450_PIN(85),  WPCM450_PIN(86),  WPCM450_PIN(87),
+	WPCM450_PIN(88),  WPCM450_PIN(89),  WPCM450_PIN(90),  WPCM450_PIN(91),
+	WPCM450_PIN(92),  WPCM450_PIN(93),  WPCM450_PIN(94),  WPCM450_PIN(95),
+	WPCM450_PIN(96),  WPCM450_PIN(97),  WPCM450_PIN(98),  WPCM450_PIN(99),
+	WPCM450_PIN(100), WPCM450_PIN(101), WPCM450_PIN(102), WPCM450_PIN(103),
+	WPCM450_PIN(104), WPCM450_PIN(105), WPCM450_PIN(106), WPCM450_PIN(107),
+	WPCM450_PIN(108), WPCM450_PIN(109), WPCM450_PIN(110), WPCM450_PIN(111),
+	WPCM450_PIN(112), WPCM450_PIN(113), WPCM450_PIN(114), WPCM450_PIN(115),
+	WPCM450_PIN(116), WPCM450_PIN(117), WPCM450_PIN(118), WPCM450_PIN(119),
+	WPCM450_PIN(120), WPCM450_PIN(121), WPCM450_PIN(122), WPCM450_PIN(123),
+	WPCM450_PIN(124), WPCM450_PIN(125), WPCM450_PIN(126), WPCM450_PIN(127),
+};
+
+/* Enable mode in pin group */
+static void wpcm450_setfunc(struct regmap *gcr_regmap, const unsigned int *pin,
+			    int npins, int func)
+{
+	const struct wpcm450_pincfg *cfg;
+	int i;
+
+	for (i = 0; i < npins; i++) {
+		cfg = &pincfg[pin[i]];
+		if (func == fn_gpio || cfg->fn0 == func || cfg->fn1 == func) {
+			if (cfg->reg0)
+				regmap_update_bits(gcr_regmap, cfg->reg0,
+						   BIT(cfg->bit0),
+						   (cfg->fn0 == func) ?  BIT(cfg->bit0) : 0);
+			if (cfg->reg1)
+				regmap_update_bits(gcr_regmap, cfg->reg1,
+						   BIT(cfg->bit1),
+						   (cfg->fn1 == func) ?  BIT(cfg->bit1) : 0);
+		}
+	}
+}
+
+static int wpcm450_get_groups_count(struct pinctrl_dev *pctldev)
+{
+	return ARRAY_SIZE(wpcm450_groups);
+}
+
+static const char *wpcm450_get_group_name(struct pinctrl_dev *pctldev,
+					  unsigned int selector)
+{
+	return wpcm450_groups[selector].name;
+}
+
+static int wpcm450_get_group_pins(struct pinctrl_dev *pctldev,
+				  unsigned int selector,
+				  const unsigned int **pins,
+				  unsigned int *npins)
+{
+	*npins = wpcm450_groups[selector].num_pins;
+	*pins  = wpcm450_groups[selector].pins;
+
+	return 0;
+}
+
+static int wpcm450_dt_node_to_map(struct pinctrl_dev *pctldev,
+				  struct device_node *np_config,
+				  struct pinctrl_map **map,
+				  u32 *num_maps)
+{
+	return pinconf_generic_dt_node_to_map(pctldev, np_config,
+					      map, num_maps,
+					      PIN_MAP_TYPE_INVALID);
+}
+
+static void wpcm450_dt_free_map(struct pinctrl_dev *pctldev,
+				struct pinctrl_map *map, u32 num_maps)
+{
+	kfree(map);
+}
+
+static const struct pinctrl_ops wpcm450_pinctrl_ops = {
+	.get_groups_count = wpcm450_get_groups_count,
+	.get_group_name = wpcm450_get_group_name,
+	.get_group_pins = wpcm450_get_group_pins,
+	.dt_node_to_map = wpcm450_dt_node_to_map,
+	.dt_free_map = wpcm450_dt_free_map,
+};
+
+static int wpcm450_get_functions_count(struct pinctrl_dev *pctldev)
+{
+	return ARRAY_SIZE(wpcm450_funcs);
+}
+
+static const char *wpcm450_get_function_name(struct pinctrl_dev *pctldev,
+					     unsigned int function)
+{
+	return wpcm450_funcs[function].name;
+}
+
+static int wpcm450_get_function_groups(struct pinctrl_dev *pctldev,
+				       unsigned int function,
+				       const char * const **groups,
+				       unsigned int * const ngroups)
+{
+	*ngroups = wpcm450_funcs[function].ngroups;
+	*groups	 = wpcm450_funcs[function].groups;
+
+	return 0;
+}
+
+static int wpcm450_pinmux_set_mux(struct pinctrl_dev *pctldev,
+				  unsigned int function,
+				  unsigned int group)
+{
+	struct wpcm450_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
+
+	wpcm450_setfunc(pctrl->gcr_regmap, wpcm450_groups[group].pins,
+			wpcm450_groups[group].num_pins, function);
+
+	return 0;
+}
+
+static const struct pinmux_ops wpcm450_pinmux_ops = {
+	.get_functions_count = wpcm450_get_functions_count,
+	.get_function_name = wpcm450_get_function_name,
+	.get_function_groups = wpcm450_get_function_groups,
+	.set_mux = wpcm450_pinmux_set_mux,
+};
+
+static int debounce_bitnum(int gpio)
+{
+	if (gpio >= 0 && gpio < 16)
+		return gpio;
+	return -EINVAL;
+}
+
+static int wpcm450_config_get(struct pinctrl_dev *pctldev, unsigned int pin,
+			      unsigned long *config)
+{
+	struct wpcm450_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
+	enum pin_config_param param = pinconf_to_config_param(*config);
+	unsigned long flags;
+	int bit;
+	u32 reg;
+
+	switch (param) {
+	case PIN_CONFIG_INPUT_DEBOUNCE:
+		bit = debounce_bitnum(pin);
+		if (bit < 0)
+			return bit;
+
+		spin_lock_irqsave(&pctrl->lock, flags);
+		reg = ioread32(pctrl->gpio_base + WPCM450_GPEVDBNC);
+		spin_unlock_irqrestore(&pctrl->lock, flags);
+
+		*config = pinconf_to_config_packed(param, !!(reg & BIT(bit)));
+		break;
+	default:
+		return -ENOTSUPP;
+	}
+
+	return 0;
+}
+
+static int wpcm450_config_set_one(struct wpcm450_pinctrl *pctrl,
+				  unsigned int pin, unsigned long config)
+{
+	enum pin_config_param param = pinconf_to_config_param(config);
+	unsigned long flags;
+	unsigned long reg;
+	int bit;
+	int arg;
+
+	switch (param) {
+	case PIN_CONFIG_INPUT_DEBOUNCE:
+		bit = debounce_bitnum(pin);
+		if (bit < 0)
+			return bit;
+
+		arg = pinconf_to_config_argument(config);
+
+		spin_lock_irqsave(&pctrl->lock, flags);
+		reg = ioread32(pctrl->gpio_base + WPCM450_GPEVDBNC);
+		__assign_bit(bit, &reg, arg);
+		iowrite32(reg, pctrl->gpio_base + WPCM450_GPEVDBNC);
+		spin_unlock_irqrestore(&pctrl->lock, flags);
+		break;
+	default:
+		return -ENOTSUPP;
+	}
+
+	return 0;
+}
+
+static int wpcm450_config_set(struct pinctrl_dev *pctldev, unsigned int pin,
+			      unsigned long *configs, unsigned int num_configs)
+{
+	struct wpcm450_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
+	int ret;
+
+	while (num_configs--) {
+		ret = wpcm450_config_set_one(pctrl, pin, *configs++);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static const struct pinconf_ops wpcm450_pinconf_ops = {
+	.is_generic = true,
+	.pin_config_get = wpcm450_config_get,
+	.pin_config_set = wpcm450_config_set,
+};
+
+static struct pinctrl_desc wpcm450_pinctrl_desc = {
+	.name = "wpcm450-pinctrl",
+	.pins = wpcm450_pins,
+	.npins = ARRAY_SIZE(wpcm450_pins),
+	.pctlops = &wpcm450_pinctrl_ops,
+	.pmxops = &wpcm450_pinmux_ops,
+	.confops = &wpcm450_pinconf_ops,
+	.owner = THIS_MODULE,
+};
+
+static int wpcm450_gpio_set_config(struct gpio_chip *chip,
+				   unsigned int offset, unsigned long config)
+{
+	struct wpcm450_gpio *gpio = gpiochip_get_data(chip);
+
+	return wpcm450_config_set_one(gpio->pctrl, offset, config);
+}
+
+static int wpcm450_gpio_register(struct platform_device *pdev,
+				 struct wpcm450_pinctrl *pctrl)
+{
+	int ret = 0;
+	struct fwnode_handle *np;
+
+	pctrl->gpio_base = devm_platform_ioremap_resource(pdev, 0);
+	if (!pctrl->gpio_base) {
+		dev_err(pctrl->dev, "Resource fail for GPIO controller\n");
+		return -ENOMEM;
+	}
+
+	fwnode_for_each_available_child_node(pctrl->dev->fwnode, np) {
+		void __iomem *dat = NULL;
+		void __iomem *set = NULL;
+		void __iomem *dirout = NULL;
+		unsigned long flags = 0;
+		const struct wpcm450_bank *bank;
+		struct wpcm450_gpio *gpio;
+		struct gpio_irq_chip *girq;
+		u32 interrupt_map[3];
+		int reg, i;
+
+		if (!fwnode_property_read_bool(np, "gpio-controller"))
+			continue;
+
+		ret = fwnode_property_read_u32(np, "reg", &reg);
+		if (ret < 0)
+			return ret;
+
+		gpio = &pctrl->gpio_bank[reg];
+		gpio->pctrl = pctrl;
+
+		if (reg < 0 || reg > WPCM450_NUM_BANKS) {
+			dev_err(pctrl->dev, "GPIO index %d out of range!\n", reg);
+			return -EINVAL;
+		}
+
+		bank = &wpcm450_banks[reg];
+
+		dat = pctrl->gpio_base + bank->datain;
+		if (bank->dataout) {
+			set = pctrl->gpio_base + bank->dataout;
+			dirout = pctrl->gpio_base + bank->cfg0;
+		} else {
+			flags = BGPIOF_NO_OUTPUT;
+		}
+		ret = bgpio_init(&gpio->gc, pctrl->dev, 4,
+				 dat, set, NULL, dirout, NULL, flags);
+		if (ret < 0) {
+			dev_err(pctrl->dev, "GPIO initialization failed: %d\n", ret);
+			return ret;
+		}
+
+		gpio->gc.ngpio = bank->length;
+		gpio->gc.set_config = wpcm450_gpio_set_config;
+		gpio->gc.of_node = to_of_node(np);
+		gpio->gc.parent = pctrl->dev;
+
+		gpio->irqc = wpcm450_gpio_irqchip;
+		girq = &gpio->gc.irq;
+		girq->chip = &gpio->irqc;
+		girq->parent_handler = wpcm450_gpio_irqhandler;
+		girq->parents = devm_kcalloc(pctrl->dev, WPCM450_NUM_GPIO_IRQS,
+					     sizeof(*girq->parents), GFP_KERNEL);
+		if (!girq->parents)
+			return -ENOMEM;
+		girq->default_type = IRQ_TYPE_NONE;
+		girq->handler = handle_bad_irq;
+
+		girq->num_parents = 0;
+		for (i = 0; i < WPCM450_NUM_GPIO_IRQS; i++) {
+			int irq = fwnode_irq_get(np, i);
+
+			if (irq < 0)
+				break;
+
+			girq->parents[i] = irq;
+			girq->num_parents++;
+		}
+
+		ret = fwnode_property_read_u32_array(np, "nuvoton,interrupt-map",
+						     interrupt_map, ARRAY_SIZE(interrupt_map));
+		if (ret == 0) {
+			gpio->first_irq_bit = interrupt_map[0];
+			gpio->num_irqs = interrupt_map[1];
+			gpio->first_irq_gpio = interrupt_map[2];
+		}
+
+		ret = devm_gpiochip_add_data(pctrl->dev, &gpio->gc, gpio);
+		if (ret) {
+			dev_err(pctrl->dev, "Failed to add GPIO chip: %d\n", ret);
+			return ret;
+		}
+
+		ret = gpiochip_add_pin_range(&gpio->gc, dev_name(pctrl->dev),
+					     0, bank->base, bank->length);
+		if (ret) {
+			dev_err(pctrl->dev, "Failed to add pin range for GPIO bank %u\n", reg);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+static int wpcm450_pinctrl_probe(struct platform_device *pdev)
+{
+	struct wpcm450_pinctrl *pctrl;
+	int ret;
+
+	pctrl = devm_kzalloc(&pdev->dev, sizeof(*pctrl), GFP_KERNEL);
+	if (!pctrl)
+		return -ENOMEM;
+
+	pctrl->dev = &pdev->dev;
+	spin_lock_init(&pctrl->lock);
+	dev_set_drvdata(&pdev->dev, pctrl);
+
+	pctrl->gcr_regmap =
+		syscon_regmap_lookup_by_compatible("nuvoton,wpcm450-gcr");
+	if (IS_ERR(pctrl->gcr_regmap)) {
+		dev_err_probe(pctrl->dev, PTR_ERR(pctrl->gcr_regmap),
+			      "Failed to find nuvoton,wpcm450-gcr\n");
+		return PTR_ERR(pctrl->gcr_regmap);
+	}
+
+	pctrl->pctldev = devm_pinctrl_register(&pdev->dev,
+					       &wpcm450_pinctrl_desc, pctrl);
+	if (IS_ERR(pctrl->pctldev)) {
+		dev_err_probe(&pdev->dev, PTR_ERR(pctrl->pctldev),
+			      "Failed to register pinctrl device\n");
+		return PTR_ERR(pctrl->pctldev);
+	}
+
+	ret = wpcm450_gpio_register(pdev, pctrl);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static const struct of_device_id wpcm450_pinctrl_match[] = {
+	{ .compatible = "nuvoton,wpcm450-pinctrl" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, wpcm450_pinctrl_match);
+
+static struct platform_driver wpcm450_pinctrl_driver = {
+	.probe = wpcm450_pinctrl_probe,
+	.driver = {
+		.name = "wpcm450-pinctrl",
+		.of_match_table = wpcm450_pinctrl_match,
+	},
+};
+module_platform_driver(wpcm450_pinctrl_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Jonathan Neuschäfer <j.neuschaefer@gmx.net>");
+MODULE_DESCRIPTION("Nuvoton WPCM450 Pinctrl and GPIO driver");
--
2.30.2


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

* [PATCH v2 5/8] pinctrl: nuvoton: Add driver for WPCM450
@ 2021-12-07 21:08   ` Jonathan Neuschäfer
  0 siblings, 0 replies; 53+ messages in thread
From: Jonathan Neuschäfer @ 2021-12-07 21:08 UTC (permalink / raw)
  To: linux-gpio, devicetree
  Cc: Tomer Maimon, Linus Walleij, linux-kernel,
	Jonathan Neuschäfer, Rob Herring, openbmc

This driver is based on the one for NPCM7xx, because the WPCM450 is a
predecessor of those SoCs. Notable differences:

- WPCM450, the GPIO registers are not organized in multiple banks, but
  rather placed continually into the same register block. This affects
  how register offsets are computed.
- Pinmux nodes can explicitly select GPIO mode, whereas, in the npcm7xx
  driver, this happens automatically when a GPIO is requested.

Some functionality implemented in the hardware was (for now) left unused
in the driver, specifically blinking and pull-up/down.

Signed-off-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>
---

This patch has a few checkpatch warnings, which are inherited from the
pinctrl-npcm7xx driver. I decided to ignore those. Specifically:
(1) WPCM450_GRPS is an unwrapped list; (2) use of -ENOTSUPP is discouraged.


v2:
- Adjust to binding change which put each GPIO bank into its own node
- Use generic GPIO support
- Make it possible to set pinmux to GPIO explicitly
- Allow building the driver as a module
- Fix spelling of "spin lock" in text
- Include <linux/mod_devicetable.h>
- Move linux/pinctrl/* headers to the end of the #include block
- Remove/rework comments and printk messages
- Switch to fwnode API
- Remove comma after sentinel {}
- Use dev_err_probe
- Improve Kconfig help message
- Declare for_each_set_bit iterator as unsigned int
- Use __assign_bit
- Set parent irq handler in set_irq_type callback
- Use struct group_desc
- Don't hide sysfs bind attributes
- Remove unnecessary check for gpio-controller property
- Use module_platform_driver()

v1:
- https://lore.kernel.org/lkml/20210602120329.2444672-6-j.neuschaefer@gmx.net/
---
 MAINTAINERS                               |    1 +
 drivers/pinctrl/Makefile                  |    2 +-
 drivers/pinctrl/nuvoton/Kconfig           |   18 +
 drivers/pinctrl/nuvoton/Makefile          |    1 +
 drivers/pinctrl/nuvoton/pinctrl-wpcm450.c | 1134 +++++++++++++++++++++
 5 files changed, 1155 insertions(+), 1 deletion(-)
 create mode 100644 drivers/pinctrl/nuvoton/pinctrl-wpcm450.c

diff --git a/MAINTAINERS b/MAINTAINERS
index eff3edafd8814..56c5c394877e1 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2352,6 +2352,7 @@ S:	Maintained
 F:	Documentation/devicetree/bindings/*/*wpcm*
 F:	arch/arm/boot/dts/nuvoton-wpcm450*
 F:	arch/arm/mach-npcm/wpcm450.c
+F:	drivers/*/*/*wpcm*
 F:	drivers/*/*wpcm*

 ARM/NXP S32G ARCHITECTURE
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index 5e63de2ffcf41..823ff12847ed3 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -58,7 +58,7 @@ obj-y				+= freescale/
 obj-$(CONFIG_X86)		+= intel/
 obj-y				+= mvebu/
 obj-y				+= nomadik/
-obj-$(CONFIG_ARCH_NPCM7XX)	+= nuvoton/
+obj-y				+= nuvoton/
 obj-$(CONFIG_PINCTRL_PXA)	+= pxa/
 obj-$(CONFIG_ARCH_QCOM)		+= qcom/
 obj-$(CONFIG_PINCTRL_RALINK)	+= ralink/
diff --git a/drivers/pinctrl/nuvoton/Kconfig b/drivers/pinctrl/nuvoton/Kconfig
index 48ba0469edda6..6a3c6f2a73f2d 100644
--- a/drivers/pinctrl/nuvoton/Kconfig
+++ b/drivers/pinctrl/nuvoton/Kconfig
@@ -1,4 +1,22 @@
 # SPDX-License-Identifier: GPL-2.0-only
+
+config PINCTRL_WPCM450
+	tristate "Pinctrl and GPIO driver for Nuvoton WPCM450"
+	depends on ARCH_WPCM450 || COMPILE_TEST
+	select PINMUX
+	select PINCONF
+	select GENERIC_PINCONF
+	select GPIOLIB
+	select GPIO_GENERIC
+	select GPIOLIB_IRQCHIP
+	help
+	  Say Y or M here to enable pin controller and GPIO support for
+	  the Nuvoton WPCM450 SoC. This is strongly recommended when
+	  building a kernel that will run on this chip.
+
+	  If this driver is compiled as a module, it will be named
+	  pinctrl-wpcm450.
+
 config PINCTRL_NPCM7XX
 	bool "Pinctrl and GPIO driver for Nuvoton NPCM7XX"
 	depends on (ARCH_NPCM7XX || COMPILE_TEST) && OF
diff --git a/drivers/pinctrl/nuvoton/Makefile b/drivers/pinctrl/nuvoton/Makefile
index 886d00784cef5..9e66f5dc74bfc 100644
--- a/drivers/pinctrl/nuvoton/Makefile
+++ b/drivers/pinctrl/nuvoton/Makefile
@@ -1,4 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0
 # Nuvoton pinctrl support

+obj-$(CONFIG_PINCTRL_WPCM450)	+= pinctrl-wpcm450.o
 obj-$(CONFIG_PINCTRL_NPCM7XX)	+= pinctrl-npcm7xx.o
diff --git a/drivers/pinctrl/nuvoton/pinctrl-wpcm450.c b/drivers/pinctrl/nuvoton/pinctrl-wpcm450.c
new file mode 100644
index 0000000000000..b1e190e45af93
--- /dev/null
+++ b/drivers/pinctrl/nuvoton/pinctrl-wpcm450.c
@@ -0,0 +1,1134 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2016-2018 Nuvoton Technology corporation.
+// Copyright (c) 2016, Dell Inc
+// Copyright (c) 2021 Jonathan Neuschäfer
+//
+// This driver uses the following registers:
+// - Pin mux registers, in the GCR (general control registers) block
+// - GPIO registers, specific to each GPIO bank
+// - GPIO event (interrupt) registers, located centrally in the GPIO register
+//   block, shared between all GPIO banks
+
+#include <linux/device.h>
+#include <linux/fwnode.h>
+#include <linux/gpio/driver.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+
+#include "../core.h"
+
+/* GCR registers */
+#define WPCM450_GCR_MFSEL1	0x0C
+#define WPCM450_GCR_MFSEL2	0x10
+#define WPCM450_GCR_NONE	0
+
+/* GPIO event (interrupt) registers */
+#define WPCM450_GPEVTYPE	0x00
+#define WPCM450_GPEVPOL		0x04
+#define WPCM450_GPEVDBNC	0x08
+#define WPCM450_GPEVEN		0x0c
+#define WPCM450_GPEVST		0x10
+
+#define WPCM450_NUM_BANKS	8
+#define WPCM450_NUM_GPIOS	128
+#define WPCM450_NUM_GPIO_IRQS	4
+
+struct wpcm450_pinctrl;
+
+struct wpcm450_gpio {
+	struct wpcm450_pinctrl	*pctrl;
+	struct gpio_chip	gc;
+	struct irq_chip		irqc;
+	unsigned int		first_irq_bit;
+	unsigned int		num_irqs;
+	unsigned int		first_irq_gpio;
+};
+
+struct wpcm450_pinctrl {
+	struct pinctrl_dev	*pctldev;
+	struct device		*dev;
+	struct irq_domain	*domain;
+	struct regmap		*gcr_regmap;
+	void __iomem		*gpio_base;
+	struct wpcm450_gpio	gpio_bank[WPCM450_NUM_BANKS];
+	unsigned long		both_edges;
+
+	/*
+	 * This spin lock protects registers and struct wpcm450_pinctrl fields
+	 * against concurrent access.
+	 */
+	spinlock_t		lock;
+};
+
+struct wpcm450_bank {
+	/* Range of GPIOs in this port */
+	u8 base;
+	u8 length;
+
+	/* Register offsets (0 = register doesn't exist in this port) */
+	u8 cfg0, cfg1, cfg2;
+	u8 blink;
+	u8 dataout, datain;
+};
+
+static const struct wpcm450_bank wpcm450_banks[WPCM450_NUM_BANKS] = {
+	/*  range   cfg0  cfg1  cfg2 blink  out   in  */
+	{   0, 16,  0x14, 0x18,    0,    0, 0x1c, 0x20 },
+	{  16, 16,  0x24, 0x28, 0x2c, 0x30, 0x34, 0x38 },
+	{  32, 16,  0x3c, 0x40, 0x44,    0, 0x48, 0x4c },
+	{  48, 16,  0x50, 0x54, 0x58,    0, 0x5c, 0x60 },
+	{  64, 16,  0x64, 0x68, 0x6c,    0, 0x70, 0x74 },
+	{  80, 16,  0x78, 0x7c, 0x80,    0, 0x84, 0x88 },
+	{  96, 18,     0,    0,    0,    0,    0, 0x8c },
+	{ 114, 14,  0x90, 0x94, 0x98,    0, 0x9c, 0xa0 },
+};
+
+static int wpcm450_gpio_irq_bitnum(struct wpcm450_gpio *gpio, struct irq_data *d)
+{
+	int hwirq = irqd_to_hwirq(d);
+
+	if (hwirq < gpio->first_irq_gpio)
+		return -EINVAL;
+
+	if (hwirq - gpio->first_irq_gpio >= gpio->num_irqs)
+		return -EINVAL;
+
+	return hwirq - gpio->first_irq_gpio + gpio->first_irq_bit;
+}
+
+static int wpcm450_irq_bitnum_to_gpio(struct wpcm450_gpio *gpio, int bitnum)
+{
+	if (bitnum < gpio->first_irq_bit)
+		return -EINVAL;
+
+	if (bitnum - gpio->first_irq_bit > gpio->num_irqs)
+		return -EINVAL;
+
+	return bitnum - gpio->first_irq_bit + gpio->first_irq_gpio;
+}
+
+static void wpcm450_gpio_irq_ack(struct irq_data *d)
+{
+	struct wpcm450_gpio *gpio = gpiochip_get_data(irq_data_get_irq_chip_data(d));
+	struct wpcm450_pinctrl *pctrl = gpio->pctrl;
+	unsigned long flags;
+	int bit;
+
+	bit = wpcm450_gpio_irq_bitnum(gpio, d);
+	if (bit < 0)
+		return;
+
+	spin_lock_irqsave(&pctrl->lock, flags);
+	iowrite32(BIT(bit), pctrl->gpio_base + WPCM450_GPEVST);
+	spin_unlock_irqrestore(&pctrl->lock, flags);
+}
+
+static void wpcm450_gpio_irq_mask(struct irq_data *d)
+{
+	struct wpcm450_gpio *gpio = gpiochip_get_data(irq_data_get_irq_chip_data(d));
+	struct wpcm450_pinctrl *pctrl = gpio->pctrl;
+	unsigned long flags;
+	unsigned long even;
+	int bit;
+
+	bit = wpcm450_gpio_irq_bitnum(gpio, d);
+	if (bit < 0)
+		return;
+
+	spin_lock_irqsave(&pctrl->lock, flags);
+	even = ioread32(pctrl->gpio_base + WPCM450_GPEVEN);
+	__assign_bit(bit, &even, 0);
+	iowrite32(even, pctrl->gpio_base + WPCM450_GPEVEN);
+	spin_unlock_irqrestore(&pctrl->lock, flags);
+}
+
+static void wpcm450_gpio_irq_unmask(struct irq_data *d)
+{
+	struct wpcm450_gpio *gpio = gpiochip_get_data(irq_data_get_irq_chip_data(d));
+	struct wpcm450_pinctrl *pctrl = gpio->pctrl;
+	unsigned long flags;
+	unsigned long even;
+	int bit;
+
+	bit = wpcm450_gpio_irq_bitnum(gpio, d);
+	if (bit < 0)
+		return;
+
+	spin_lock_irqsave(&pctrl->lock, flags);
+	even = ioread32(pctrl->gpio_base + WPCM450_GPEVEN);
+	__assign_bit(bit, &even, 1);
+	iowrite32(even, pctrl->gpio_base + WPCM450_GPEVEN);
+	spin_unlock_irqrestore(&pctrl->lock, flags);
+}
+
+static void wpcm450_gpio_fix_evpol(struct wpcm450_gpio *gpio, unsigned long all)
+{
+	struct wpcm450_pinctrl *pctrl = gpio->pctrl;
+	unsigned long flags;
+	unsigned int bit;
+
+	for_each_set_bit(bit, &all, 32) {
+		int offset = wpcm450_irq_bitnum_to_gpio(gpio, bit);
+		unsigned long evpol;
+		int level;
+
+		spin_lock_irqsave(&gpio->gc.bgpio_lock, flags);
+		do {
+			evpol = ioread32(pctrl->gpio_base + WPCM450_GPEVPOL);
+			level = gpio->gc.get(&gpio->gc, offset);
+
+			/* Switch event polarity to the opposite of the current level */
+			__assign_bit(bit, &evpol, !level);
+
+			iowrite32(evpol, pctrl->gpio_base + WPCM450_GPEVPOL);
+		} while (gpio->gc.get(&gpio->gc, offset) != level);
+		spin_unlock_irqrestore(&gpio->gc.bgpio_lock, flags);
+	}
+}
+
+static int wpcm450_gpio_set_irq_type(struct irq_data *d, unsigned int flow_type)
+{
+	struct wpcm450_gpio *gpio = gpiochip_get_data(irq_data_get_irq_chip_data(d));
+	struct wpcm450_pinctrl *pctrl = gpio->pctrl;
+	unsigned long evtype, evpol;
+	unsigned long flags;
+	int ret = 0;
+	int bit;
+
+	bit = wpcm450_gpio_irq_bitnum(gpio, d);
+	if (bit < 0)
+		return bit;
+
+	irq_set_handler_locked(d, handle_level_irq);
+
+	spin_lock_irqsave(&pctrl->lock, flags);
+	evtype = ioread32(pctrl->gpio_base + WPCM450_GPEVTYPE);
+	evpol = ioread32(pctrl->gpio_base + WPCM450_GPEVPOL);
+	__assign_bit(bit, &pctrl->both_edges, 0);
+	switch (flow_type) {
+	case IRQ_TYPE_LEVEL_LOW:
+		__assign_bit(bit, &evtype, 1);
+		__assign_bit(bit, &evpol, 0);
+		break;
+	case IRQ_TYPE_LEVEL_HIGH:
+		__assign_bit(bit, &evtype, 1);
+		__assign_bit(bit, &evpol, 1);
+		break;
+	case IRQ_TYPE_EDGE_FALLING:
+		__assign_bit(bit, &evtype, 0);
+		__assign_bit(bit, &evpol, 0);
+		break;
+	case IRQ_TYPE_EDGE_RISING:
+		__assign_bit(bit, &evtype, 0);
+		__assign_bit(bit, &evpol, 1);
+		break;
+	case IRQ_TYPE_EDGE_BOTH:
+		__assign_bit(bit, &evtype, 0);
+		__assign_bit(bit, &pctrl->both_edges, 1);
+		break;
+	default:
+		ret = -EINVAL;
+	}
+	iowrite32(evtype, pctrl->gpio_base + WPCM450_GPEVTYPE);
+	iowrite32(evpol, pctrl->gpio_base + WPCM450_GPEVPOL);
+
+	/* clear the event status for good measure */
+	iowrite32(BIT(bit), pctrl->gpio_base + WPCM450_GPEVST);
+
+	/* fix event polarity after clearing event status */
+	wpcm450_gpio_fix_evpol(gpio, BIT(bit));
+
+	spin_unlock_irqrestore(&pctrl->lock, flags);
+
+	return ret;
+}
+
+static const struct irq_chip wpcm450_gpio_irqchip = {
+	.name = "WPCM450-GPIO-IRQ",
+	.irq_ack = wpcm450_gpio_irq_ack,
+	.irq_unmask = wpcm450_gpio_irq_unmask,
+	.irq_mask = wpcm450_gpio_irq_mask,
+	.irq_set_type = wpcm450_gpio_set_irq_type,
+};
+
+static void wpcm450_gpio_irqhandler(struct irq_desc *desc)
+{
+	struct wpcm450_gpio *gpio = gpiochip_get_data(irq_desc_get_handler_data(desc));
+	struct wpcm450_pinctrl *pctrl = gpio->pctrl;
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+	unsigned long pending;
+	unsigned long flags;
+	unsigned long ours;
+	unsigned int bit;
+
+	ours = ((1UL << gpio->num_irqs) - 1) << gpio->first_irq_bit;
+
+	spin_lock_irqsave(&pctrl->lock, flags);
+
+	pending = ioread32(pctrl->gpio_base + WPCM450_GPEVST);
+	pending &= ioread32(pctrl->gpio_base + WPCM450_GPEVEN);
+	pending &= ours;
+
+	if (pending & pctrl->both_edges)
+		wpcm450_gpio_fix_evpol(gpio, pending & pctrl->both_edges);
+
+	spin_unlock_irqrestore(&pctrl->lock, flags);
+
+	chained_irq_enter(chip, desc);
+	for_each_set_bit(bit, &pending, 32) {
+		int offset = wpcm450_irq_bitnum_to_gpio(gpio, bit);
+		int irq = irq_find_mapping(gpio->gc.irq.domain, offset);
+
+		generic_handle_irq(irq);
+	}
+	chained_irq_exit(chip, desc);
+}
+
+static int smb0_pins[]  = { 115, 114 };
+static int smb1_pins[]  = { 117, 116 };
+static int smb2_pins[]  = { 119, 118 };
+static int smb3_pins[]  = { 30, 31 };
+static int smb4_pins[]  = { 28, 29 };
+static int smb5_pins[]  = { 26, 27 };
+
+static int scs1_pins[] = { 32 };
+static int scs2_pins[] = { 33 };
+static int scs3_pins[] = { 34 };
+
+static int bsp_pins[] = { 41, 42 };
+static int hsp1_pins[] = { 43, 44, 45, 46, 47, 61, 62, 63 };
+static int hsp2_pins[] = { 48, 49, 50, 51, 52, 53, 54, 55 };
+
+static int r1err_pins[] = { 56 };
+static int r1md_pins[] = { 57, 58 };
+static int rmii2_pins[] = { 84, 85, 86, 87, 88, 89 };
+static int r2err_pins[] = { 90 };
+static int r2md_pins[] = { 91, 92 };
+
+static int kbcc_pins[] = { 94, 93 };
+static int clko_pins[] = { 96 };
+static int smi_pins[] = { 97 };
+static int uinc_pins[] = { 19 };
+static int mben_pins[] = {};
+
+static int gspi_pins[] = { 12, 13, 14, 15 };
+static int sspi_pins[] = { 12, 13, 14, 15 };
+
+static int xcs1_pins[] = { 35 };
+static int xcs2_pins[] = { 36 };
+
+static int sdio_pins[] = { 7, 22, 43, 44, 45, 46, 47, 60 };
+
+static int fi0_pins[] = { 64 };
+static int fi1_pins[] = { 65 };
+static int fi2_pins[] = { 66 };
+static int fi3_pins[] = { 67 };
+static int fi4_pins[] = { 68 };
+static int fi5_pins[] = { 69 };
+static int fi6_pins[] = { 70 };
+static int fi7_pins[] = { 71 };
+static int fi8_pins[] = { 72 };
+static int fi9_pins[] = { 73 };
+static int fi10_pins[] = { 74 };
+static int fi11_pins[] = { 75 };
+static int fi12_pins[] = { 76 };
+static int fi13_pins[] = { 77 };
+static int fi14_pins[] = { 78 };
+static int fi15_pins[] = { 79 };
+
+static int pwm0_pins[] = { 80 };
+static int pwm1_pins[] = { 81 };
+static int pwm2_pins[] = { 82 };
+static int pwm3_pins[] = { 83 };
+static int pwm4_pins[] = { 20 };
+static int pwm5_pins[] = { 21 };
+static int pwm6_pins[] = { 16 };
+static int pwm7_pins[] = { 17 };
+
+static int hg0_pins[] = { 20 };
+static int hg1_pins[] = { 21 };
+static int hg2_pins[] = { 22 };
+static int hg3_pins[] = { 23 };
+static int hg4_pins[] = { 24 };
+static int hg5_pins[] = { 25 };
+static int hg6_pins[] = { 59 };
+static int hg7_pins[] = { 60 };
+
+#define WPCM450_GRPS \
+	WPCM450_GRP(smb3), \
+	WPCM450_GRP(smb4), \
+	WPCM450_GRP(smb5), \
+	WPCM450_GRP(scs1), \
+	WPCM450_GRP(scs2), \
+	WPCM450_GRP(scs3), \
+	WPCM450_GRP(smb0), \
+	WPCM450_GRP(smb1), \
+	WPCM450_GRP(smb2), \
+	WPCM450_GRP(bsp), \
+	WPCM450_GRP(hsp1), \
+	WPCM450_GRP(hsp2), \
+	WPCM450_GRP(r1err), \
+	WPCM450_GRP(r1md), \
+	WPCM450_GRP(rmii2), \
+	WPCM450_GRP(r2err), \
+	WPCM450_GRP(r2md), \
+	WPCM450_GRP(kbcc), \
+	WPCM450_GRP(clko), \
+	WPCM450_GRP(smi), \
+	WPCM450_GRP(uinc), \
+	WPCM450_GRP(gspi), \
+	WPCM450_GRP(mben), \
+	WPCM450_GRP(xcs2), \
+	WPCM450_GRP(xcs1), \
+	WPCM450_GRP(sdio), \
+	WPCM450_GRP(sspi), \
+	WPCM450_GRP(fi0), \
+	WPCM450_GRP(fi1), \
+	WPCM450_GRP(fi2), \
+	WPCM450_GRP(fi3), \
+	WPCM450_GRP(fi4), \
+	WPCM450_GRP(fi5), \
+	WPCM450_GRP(fi6), \
+	WPCM450_GRP(fi7), \
+	WPCM450_GRP(fi8), \
+	WPCM450_GRP(fi9), \
+	WPCM450_GRP(fi10), \
+	WPCM450_GRP(fi11), \
+	WPCM450_GRP(fi12), \
+	WPCM450_GRP(fi13), \
+	WPCM450_GRP(fi14), \
+	WPCM450_GRP(fi15), \
+	WPCM450_GRP(pwm0), \
+	WPCM450_GRP(pwm1), \
+	WPCM450_GRP(pwm2), \
+	WPCM450_GRP(pwm3), \
+	WPCM450_GRP(pwm4), \
+	WPCM450_GRP(pwm5), \
+	WPCM450_GRP(pwm6), \
+	WPCM450_GRP(pwm7), \
+	WPCM450_GRP(hg0), \
+	WPCM450_GRP(hg1), \
+	WPCM450_GRP(hg2), \
+	WPCM450_GRP(hg3), \
+	WPCM450_GRP(hg4), \
+	WPCM450_GRP(hg5), \
+	WPCM450_GRP(hg6), \
+	WPCM450_GRP(hg7), \
+
+enum {
+#define WPCM450_GRP(x) fn_ ## x
+	WPCM450_GRPS
+	/* add placeholder for none/gpio */
+	WPCM450_GRP(gpio),
+	WPCM450_GRP(none),
+#undef WPCM450_GRP
+};
+
+static struct group_desc wpcm450_groups[] = {
+#define WPCM450_GRP(x) { .name = #x, .pins = x ## _pins, \
+			.num_pins = ARRAY_SIZE(x ## _pins) }
+	WPCM450_GRPS
+#undef WPCM450_GRP
+};
+
+#define WPCM450_SFUNC(a) WPCM450_FUNC(a, #a)
+#define WPCM450_FUNC(a, b...) static const char *a ## _grp[] = { b }
+#define WPCM450_MKFUNC(nm) { .name = #nm, .ngroups = ARRAY_SIZE(nm ## _grp), \
+			.groups = nm ## _grp }
+struct wpcm450_func {
+	const char *name;
+	const unsigned int ngroups;
+	const char *const *groups;
+};
+
+WPCM450_SFUNC(smb3);
+WPCM450_SFUNC(smb4);
+WPCM450_SFUNC(smb5);
+WPCM450_SFUNC(scs1);
+WPCM450_SFUNC(scs2);
+WPCM450_SFUNC(scs3);
+WPCM450_SFUNC(smb0);
+WPCM450_SFUNC(smb1);
+WPCM450_SFUNC(smb2);
+WPCM450_SFUNC(bsp);
+WPCM450_SFUNC(hsp1);
+WPCM450_SFUNC(hsp2);
+WPCM450_SFUNC(r1err);
+WPCM450_SFUNC(r1md);
+WPCM450_SFUNC(rmii2);
+WPCM450_SFUNC(r2err);
+WPCM450_SFUNC(r2md);
+WPCM450_SFUNC(kbcc);
+WPCM450_SFUNC(clko);
+WPCM450_SFUNC(smi);
+WPCM450_SFUNC(uinc);
+WPCM450_SFUNC(gspi);
+WPCM450_SFUNC(mben);
+WPCM450_SFUNC(xcs2);
+WPCM450_SFUNC(xcs1);
+WPCM450_SFUNC(sdio);
+WPCM450_SFUNC(sspi);
+WPCM450_SFUNC(fi0);
+WPCM450_SFUNC(fi1);
+WPCM450_SFUNC(fi2);
+WPCM450_SFUNC(fi3);
+WPCM450_SFUNC(fi4);
+WPCM450_SFUNC(fi5);
+WPCM450_SFUNC(fi6);
+WPCM450_SFUNC(fi7);
+WPCM450_SFUNC(fi8);
+WPCM450_SFUNC(fi9);
+WPCM450_SFUNC(fi10);
+WPCM450_SFUNC(fi11);
+WPCM450_SFUNC(fi12);
+WPCM450_SFUNC(fi13);
+WPCM450_SFUNC(fi14);
+WPCM450_SFUNC(fi15);
+WPCM450_SFUNC(pwm0);
+WPCM450_SFUNC(pwm1);
+WPCM450_SFUNC(pwm2);
+WPCM450_SFUNC(pwm3);
+WPCM450_SFUNC(pwm4);
+WPCM450_SFUNC(pwm5);
+WPCM450_SFUNC(pwm6);
+WPCM450_SFUNC(pwm7);
+WPCM450_SFUNC(hg0);
+WPCM450_SFUNC(hg1);
+WPCM450_SFUNC(hg2);
+WPCM450_SFUNC(hg3);
+WPCM450_SFUNC(hg4);
+WPCM450_SFUNC(hg5);
+WPCM450_SFUNC(hg6);
+WPCM450_SFUNC(hg7);
+
+#define WPCM450_GRP(x) #x
+WPCM450_FUNC(gpio, WPCM450_GRPS);
+#undef WPCM450_GRP
+
+/* Function names */
+static struct wpcm450_func wpcm450_funcs[] = {
+	WPCM450_MKFUNC(smb3),
+	WPCM450_MKFUNC(smb4),
+	WPCM450_MKFUNC(smb5),
+	WPCM450_MKFUNC(scs1),
+	WPCM450_MKFUNC(scs2),
+	WPCM450_MKFUNC(scs3),
+	WPCM450_MKFUNC(smb0),
+	WPCM450_MKFUNC(smb1),
+	WPCM450_MKFUNC(smb2),
+	WPCM450_MKFUNC(bsp),
+	WPCM450_MKFUNC(hsp1),
+	WPCM450_MKFUNC(hsp2),
+	WPCM450_MKFUNC(r1err),
+	WPCM450_MKFUNC(r1md),
+	WPCM450_MKFUNC(rmii2),
+	WPCM450_MKFUNC(r2err),
+	WPCM450_MKFUNC(r2md),
+	WPCM450_MKFUNC(kbcc),
+	WPCM450_MKFUNC(clko),
+	WPCM450_MKFUNC(smi),
+	WPCM450_MKFUNC(uinc),
+	WPCM450_MKFUNC(gspi),
+	WPCM450_MKFUNC(mben),
+	WPCM450_MKFUNC(xcs2),
+	WPCM450_MKFUNC(xcs1),
+	WPCM450_MKFUNC(sdio),
+	WPCM450_MKFUNC(sspi),
+	WPCM450_MKFUNC(fi0),
+	WPCM450_MKFUNC(fi1),
+	WPCM450_MKFUNC(fi2),
+	WPCM450_MKFUNC(fi3),
+	WPCM450_MKFUNC(fi4),
+	WPCM450_MKFUNC(fi5),
+	WPCM450_MKFUNC(fi6),
+	WPCM450_MKFUNC(fi7),
+	WPCM450_MKFUNC(fi8),
+	WPCM450_MKFUNC(fi9),
+	WPCM450_MKFUNC(fi10),
+	WPCM450_MKFUNC(fi11),
+	WPCM450_MKFUNC(fi12),
+	WPCM450_MKFUNC(fi13),
+	WPCM450_MKFUNC(fi14),
+	WPCM450_MKFUNC(fi15),
+	WPCM450_MKFUNC(pwm0),
+	WPCM450_MKFUNC(pwm1),
+	WPCM450_MKFUNC(pwm2),
+	WPCM450_MKFUNC(pwm3),
+	WPCM450_MKFUNC(pwm4),
+	WPCM450_MKFUNC(pwm5),
+	WPCM450_MKFUNC(pwm6),
+	WPCM450_MKFUNC(pwm7),
+	WPCM450_MKFUNC(hg0),
+	WPCM450_MKFUNC(hg1),
+	WPCM450_MKFUNC(hg2),
+	WPCM450_MKFUNC(hg3),
+	WPCM450_MKFUNC(hg4),
+	WPCM450_MKFUNC(hg5),
+	WPCM450_MKFUNC(hg6),
+	WPCM450_MKFUNC(hg7),
+	WPCM450_MKFUNC(gpio),
+};
+
+#define WPCM450_PINCFG(a, b, c, d, e, f, g) \
+	[a] { .fn0 = fn_ ## b, .reg0 = WPCM450_GCR_ ## c, .bit0 = d, \
+	      .fn1 = fn_ ## e, .reg1 = WPCM450_GCR_ ## f, .bit1 = g }
+
+struct wpcm450_pincfg {
+	int fn0, reg0, bit0;
+	int fn1, reg1, bit1;
+};
+
+static const struct wpcm450_pincfg pincfg[] = {
+	/*		PIN	  FUNCTION 1		   FUNCTION 2 */
+	WPCM450_PINCFG(0,	 none, NONE, 0,		  none, NONE, 0),
+	WPCM450_PINCFG(1,	 none, NONE, 0,		  none, NONE, 0),
+	WPCM450_PINCFG(2,	 none, NONE, 0,		  none, NONE, 0),
+	WPCM450_PINCFG(3,	 none, NONE, 0,		  none, NONE, 0),
+	WPCM450_PINCFG(4,	 none, NONE, 0,		  none, NONE, 0),
+	WPCM450_PINCFG(5,	 none, NONE, 0,		  none, NONE, 0),
+	WPCM450_PINCFG(6,	 none, NONE, 0,		  none, NONE, 0),
+	WPCM450_PINCFG(7,	 none, NONE, 0,		  sdio, MFSEL1, 30),
+	WPCM450_PINCFG(8,	 none, NONE, 0,		  none, NONE, 0),
+	WPCM450_PINCFG(9,	 none, NONE, 0,		  none, NONE, 0),
+	WPCM450_PINCFG(10,	 none, NONE, 0,		  none, NONE, 0),
+	WPCM450_PINCFG(11,	 none, NONE, 0,		  none, NONE, 0),
+	WPCM450_PINCFG(12,	 gspi, MFSEL1, 24,	  sspi, MFSEL1, 31),
+	WPCM450_PINCFG(13,	 gspi, MFSEL1, 24,	  sspi, MFSEL1, 31),
+	WPCM450_PINCFG(14,	 gspi, MFSEL1, 24,	  sspi, MFSEL1, 31),
+	WPCM450_PINCFG(15,	 gspi, MFSEL1, 24,	  sspi, MFSEL1, 31),
+	WPCM450_PINCFG(16,	 none, NONE, 0,		  pwm6, MFSEL2, 22),
+	WPCM450_PINCFG(17,	 none, NONE, 0,		  pwm7, MFSEL2, 23),
+	WPCM450_PINCFG(18,	 none, NONE, 0,		  none, NONE, 0),
+	WPCM450_PINCFG(19,	 uinc, MFSEL1, 23,	  none, NONE, 0),
+	WPCM450_PINCFG(20,	  hg0, MFSEL2, 24,	  pwm4, MFSEL2, 20),
+	WPCM450_PINCFG(21,	  hg1, MFSEL2, 25,	  pwm5, MFSEL2, 21),
+	WPCM450_PINCFG(22,	  hg2, MFSEL2, 26,	  none, NONE, 0),
+	WPCM450_PINCFG(23,	  hg3, MFSEL2, 27,	  none, NONE, 0),
+	WPCM450_PINCFG(24,	  hg4, MFSEL2, 28,	  none, NONE, 0),
+	WPCM450_PINCFG(25,	  hg5, MFSEL2, 29,	  none, NONE, 0),
+	WPCM450_PINCFG(26,	 smb5, MFSEL1, 2,	  none, NONE, 0),
+	WPCM450_PINCFG(27,	 smb5, MFSEL1, 2,	  none, NONE, 0),
+	WPCM450_PINCFG(28,	 smb4, MFSEL1, 1,	  none, NONE, 0),
+	WPCM450_PINCFG(29,	 smb4, MFSEL1, 1,	  none, NONE, 0),
+	WPCM450_PINCFG(30,	 smb3, MFSEL1, 0,	  none, NONE, 0),
+	WPCM450_PINCFG(31,	 smb3, MFSEL1, 0,	  none, NONE, 0),
+
+	WPCM450_PINCFG(32,	 scs1, MFSEL1, 3,	  none, NONE, 0),
+	WPCM450_PINCFG(33,	 scs2, MFSEL1, 4,	  none, NONE, 0),
+	WPCM450_PINCFG(34,	 scs3, MFSEL1, 5,	  none, NONE, 0),
+	WPCM450_PINCFG(35,	 xcs1, MFSEL1, 29,	  none, NONE, 0),
+	WPCM450_PINCFG(36,	 xcs2, MFSEL1, 28,	  none, NONE, 0),
+	WPCM450_PINCFG(37,	 none, NONE, 0,		  none, NONE, 0), /* DVO */
+	WPCM450_PINCFG(38,	 none, NONE, 0,		  none, NONE, 0), /* DVO */
+	WPCM450_PINCFG(39,	 none, NONE, 0,		  none, NONE, 0), /* DVO */
+	WPCM450_PINCFG(40,	 none, NONE, 0,		  none, NONE, 0), /* DVO */
+	WPCM450_PINCFG(41,	  bsp, MFSEL1, 9,	  none, NONE, 0),
+	WPCM450_PINCFG(42,	  bsp, MFSEL1, 9,	  none, NONE, 0),
+	WPCM450_PINCFG(43,	 hsp1, MFSEL1, 10,	  sdio, MFSEL1, 30),
+	WPCM450_PINCFG(44,	 hsp1, MFSEL1, 10,	  sdio, MFSEL1, 30),
+	WPCM450_PINCFG(45,	 hsp1, MFSEL1, 10,	  sdio, MFSEL1, 30),
+	WPCM450_PINCFG(46,	 hsp1, MFSEL1, 10,	  sdio, MFSEL1, 30),
+	WPCM450_PINCFG(47,	 hsp1, MFSEL1, 10,	  sdio, MFSEL1, 30),
+	WPCM450_PINCFG(48,	 hsp2, MFSEL1, 11,	  none, NONE, 0),
+	WPCM450_PINCFG(49,	 hsp2, MFSEL1, 11,	  none, NONE, 0),
+	WPCM450_PINCFG(50,	 hsp2, MFSEL1, 11,	  none, NONE, 0),
+	WPCM450_PINCFG(51,	 hsp2, MFSEL1, 11,	  none, NONE, 0),
+	WPCM450_PINCFG(52,	 hsp2, MFSEL1, 11,	  none, NONE, 0),
+	WPCM450_PINCFG(53,	 hsp2, MFSEL1, 11,	  none, NONE, 0),
+	WPCM450_PINCFG(54,	 hsp2, MFSEL1, 11,	  none, NONE, 0),
+	WPCM450_PINCFG(55,	 hsp2, MFSEL1, 11,	  none, NONE, 0),
+	WPCM450_PINCFG(56,	r1err, MFSEL1, 12,	  none, NONE, 0),
+	WPCM450_PINCFG(57,	 r1md, MFSEL1, 13,	  none, NONE, 0),
+	WPCM450_PINCFG(58,	 r1md, MFSEL1, 13,	  none, NONE, 0),
+	WPCM450_PINCFG(59,	  hg6, MFSEL2, 30,	  none, NONE, 0),
+	WPCM450_PINCFG(60,	  hg7, MFSEL2, 31,	  sdio, MFSEL1, 30),
+	WPCM450_PINCFG(61,	 hsp1, MFSEL1, 10,	  none, NONE, 0),
+	WPCM450_PINCFG(62,	 hsp1, MFSEL1, 10,	  none, NONE, 0),
+	WPCM450_PINCFG(63,	 hsp1, MFSEL1, 10,	  none, NONE, 0),
+
+	WPCM450_PINCFG(64,	  fi0, MFSEL2, 0,	  none, NONE, 0),
+	WPCM450_PINCFG(65,	  fi1, MFSEL2, 1,	  none, NONE, 0),
+	WPCM450_PINCFG(66,	  fi2, MFSEL2, 2,	  none, NONE, 0),
+	WPCM450_PINCFG(67,	  fi3, MFSEL2, 3,	  none, NONE, 0),
+	WPCM450_PINCFG(68,	  fi4, MFSEL2, 4,	  none, NONE, 0),
+	WPCM450_PINCFG(69,	  fi5, MFSEL2, 5,	  none, NONE, 0),
+	WPCM450_PINCFG(70,	  fi6, MFSEL2, 6,	  none, NONE, 0),
+	WPCM450_PINCFG(71,	  fi7, MFSEL2, 7,	  none, NONE, 0),
+	WPCM450_PINCFG(72,	  fi8, MFSEL2, 8,	  none, NONE, 0),
+	WPCM450_PINCFG(73,	  fi9, MFSEL2, 9,	  none, NONE, 0),
+	WPCM450_PINCFG(74,	 fi10, MFSEL2, 10,	  none, NONE, 0),
+	WPCM450_PINCFG(75,	 fi11, MFSEL2, 11,	  none, NONE, 0),
+	WPCM450_PINCFG(76,	 fi12, MFSEL2, 12,	  none, NONE, 0),
+	WPCM450_PINCFG(77,	 fi13, MFSEL2, 13,	  none, NONE, 0),
+	WPCM450_PINCFG(78,	 fi14, MFSEL2, 14,	  none, NONE, 0),
+	WPCM450_PINCFG(79,	 fi15, MFSEL2, 15,	  none, NONE, 0),
+	WPCM450_PINCFG(80,	 pwm0, MFSEL2, 16,	  none, NONE, 0),
+	WPCM450_PINCFG(81,	 pwm1, MFSEL2, 17,	  none, NONE, 0),
+	WPCM450_PINCFG(82,	 pwm2, MFSEL2, 18,	  none, NONE, 0),
+	WPCM450_PINCFG(83,	 pwm3, MFSEL2, 19,	  none, NONE, 0),
+	WPCM450_PINCFG(84,	rmii2, MFSEL1, 14,	  none, NONE, 0),
+	WPCM450_PINCFG(85,	rmii2, MFSEL1, 14,	  none, NONE, 0),
+	WPCM450_PINCFG(86,	rmii2, MFSEL1, 14,	  none, NONE, 0),
+	WPCM450_PINCFG(87,	rmii2, MFSEL1, 14,	  none, NONE, 0),
+	WPCM450_PINCFG(88,	rmii2, MFSEL1, 14,	  none, NONE, 0),
+	WPCM450_PINCFG(89,	rmii2, MFSEL1, 14,	  none, NONE, 0),
+	WPCM450_PINCFG(90,	r2err, MFSEL1, 15,	  none, NONE, 0),
+	WPCM450_PINCFG(91,	 r2md, MFSEL1, 16,	  none, NONE, 0),
+	WPCM450_PINCFG(92,	 r2md, MFSEL1, 16,	  none, NONE, 0),
+	WPCM450_PINCFG(93,	 kbcc, MFSEL1, 17,	  none, NONE, 0),
+	WPCM450_PINCFG(94,	 kbcc, MFSEL1, 17,	  none, NONE, 0),
+	WPCM450_PINCFG(95,	 none, NONE, 0,		  none, NONE, 0),
+
+	WPCM450_PINCFG(96,	 none, NONE, 0,		  none, NONE, 0),
+	WPCM450_PINCFG(97,	 none, NONE, 0,		  none, NONE, 0),
+	WPCM450_PINCFG(98,	 none, NONE, 0,		  none, NONE, 0),
+	WPCM450_PINCFG(99,	 none, NONE, 0,		  none, NONE, 0),
+	WPCM450_PINCFG(100,	 none, NONE, 0,		  none, NONE, 0),
+	WPCM450_PINCFG(101,	 none, NONE, 0,		  none, NONE, 0),
+	WPCM450_PINCFG(102,	 none, NONE, 0,		  none, NONE, 0),
+	WPCM450_PINCFG(103,	 none, NONE, 0,		  none, NONE, 0),
+	WPCM450_PINCFG(104,	 none, NONE, 0,		  none, NONE, 0),
+	WPCM450_PINCFG(105,	 none, NONE, 0,		  none, NONE, 0),
+	WPCM450_PINCFG(106,	 none, NONE, 0,		  none, NONE, 0),
+	WPCM450_PINCFG(107,	 none, NONE, 0,		  none, NONE, 0),
+	WPCM450_PINCFG(108,	 none, NONE, 0,		  none, NONE, 0), /* DVO */
+	WPCM450_PINCFG(109,	 none, NONE, 0,		  none, NONE, 0), /* DVO */
+	WPCM450_PINCFG(110,	 none, NONE, 0,		  none, NONE, 0), /* DVO */
+	WPCM450_PINCFG(111,	 none, NONE, 0,		  none, NONE, 0), /* DVO */
+	WPCM450_PINCFG(112,	 none, NONE, 0,		  none, NONE, 0), /* DVO */
+	WPCM450_PINCFG(113,	 none, NONE, 0,		  none, NONE, 0), /* DVO */
+	WPCM450_PINCFG(114,	 smb0, MFSEL1, 6,	  none, NONE, 0),
+	WPCM450_PINCFG(115,	 smb0, MFSEL1, 6,	  none, NONE, 0),
+	WPCM450_PINCFG(116,	 smb1, MFSEL1, 7,	  none, NONE, 0),
+	WPCM450_PINCFG(117,	 smb1, MFSEL1, 7,	  none, NONE, 0),
+	WPCM450_PINCFG(118,	 smb2, MFSEL1, 8,	  none, NONE, 0),
+	WPCM450_PINCFG(119,	 smb2, MFSEL1, 8,	  none, NONE, 0),
+	WPCM450_PINCFG(120,	 none, NONE, 0,		  none, NONE, 0), /* DVO */
+	WPCM450_PINCFG(121,	 none, NONE, 0,		  none, NONE, 0), /* DVO */
+	WPCM450_PINCFG(122,	 none, NONE, 0,		  none, NONE, 0), /* DVO */
+	WPCM450_PINCFG(123,	 none, NONE, 0,		  none, NONE, 0), /* DVO */
+	WPCM450_PINCFG(124,	 none, NONE, 0,		  none, NONE, 0), /* DVO */
+	WPCM450_PINCFG(125,	 none, NONE, 0,		  none, NONE, 0), /* DVO */
+	WPCM450_PINCFG(126,	 none, NONE, 0,		  none, NONE, 0), /* DVO */
+	WPCM450_PINCFG(127,	 none, NONE, 0,		  none, NONE, 0), /* DVO */
+};
+
+#define WPCM450_PIN(n)		PINCTRL_PIN(n, "gpio" #n)
+
+static const struct pinctrl_pin_desc wpcm450_pins[] = {
+	WPCM450_PIN(0),   WPCM450_PIN(1),   WPCM450_PIN(2),   WPCM450_PIN(3),
+	WPCM450_PIN(4),   WPCM450_PIN(5),   WPCM450_PIN(6),   WPCM450_PIN(7),
+	WPCM450_PIN(8),   WPCM450_PIN(9),   WPCM450_PIN(10),  WPCM450_PIN(11),
+	WPCM450_PIN(12),  WPCM450_PIN(13),  WPCM450_PIN(14),  WPCM450_PIN(15),
+	WPCM450_PIN(16),  WPCM450_PIN(17),  WPCM450_PIN(18),  WPCM450_PIN(19),
+	WPCM450_PIN(20),  WPCM450_PIN(21),  WPCM450_PIN(22),  WPCM450_PIN(23),
+	WPCM450_PIN(24),  WPCM450_PIN(25),  WPCM450_PIN(26),  WPCM450_PIN(27),
+	WPCM450_PIN(28),  WPCM450_PIN(29),  WPCM450_PIN(30),  WPCM450_PIN(31),
+	WPCM450_PIN(32),  WPCM450_PIN(33),  WPCM450_PIN(34),  WPCM450_PIN(35),
+	WPCM450_PIN(36),  WPCM450_PIN(37),  WPCM450_PIN(38),  WPCM450_PIN(39),
+	WPCM450_PIN(40),  WPCM450_PIN(41),  WPCM450_PIN(42),  WPCM450_PIN(43),
+	WPCM450_PIN(44),  WPCM450_PIN(45),  WPCM450_PIN(46),  WPCM450_PIN(47),
+	WPCM450_PIN(48),  WPCM450_PIN(49),  WPCM450_PIN(50),  WPCM450_PIN(51),
+	WPCM450_PIN(52),  WPCM450_PIN(53),  WPCM450_PIN(54),  WPCM450_PIN(55),
+	WPCM450_PIN(56),  WPCM450_PIN(57),  WPCM450_PIN(58),  WPCM450_PIN(59),
+	WPCM450_PIN(60),  WPCM450_PIN(61),  WPCM450_PIN(62),  WPCM450_PIN(63),
+	WPCM450_PIN(64),  WPCM450_PIN(65),  WPCM450_PIN(66),  WPCM450_PIN(67),
+	WPCM450_PIN(68),  WPCM450_PIN(69),  WPCM450_PIN(70),  WPCM450_PIN(71),
+	WPCM450_PIN(72),  WPCM450_PIN(73),  WPCM450_PIN(74),  WPCM450_PIN(75),
+	WPCM450_PIN(76),  WPCM450_PIN(77),  WPCM450_PIN(78),  WPCM450_PIN(79),
+	WPCM450_PIN(80),  WPCM450_PIN(81),  WPCM450_PIN(82),  WPCM450_PIN(83),
+	WPCM450_PIN(84),  WPCM450_PIN(85),  WPCM450_PIN(86),  WPCM450_PIN(87),
+	WPCM450_PIN(88),  WPCM450_PIN(89),  WPCM450_PIN(90),  WPCM450_PIN(91),
+	WPCM450_PIN(92),  WPCM450_PIN(93),  WPCM450_PIN(94),  WPCM450_PIN(95),
+	WPCM450_PIN(96),  WPCM450_PIN(97),  WPCM450_PIN(98),  WPCM450_PIN(99),
+	WPCM450_PIN(100), WPCM450_PIN(101), WPCM450_PIN(102), WPCM450_PIN(103),
+	WPCM450_PIN(104), WPCM450_PIN(105), WPCM450_PIN(106), WPCM450_PIN(107),
+	WPCM450_PIN(108), WPCM450_PIN(109), WPCM450_PIN(110), WPCM450_PIN(111),
+	WPCM450_PIN(112), WPCM450_PIN(113), WPCM450_PIN(114), WPCM450_PIN(115),
+	WPCM450_PIN(116), WPCM450_PIN(117), WPCM450_PIN(118), WPCM450_PIN(119),
+	WPCM450_PIN(120), WPCM450_PIN(121), WPCM450_PIN(122), WPCM450_PIN(123),
+	WPCM450_PIN(124), WPCM450_PIN(125), WPCM450_PIN(126), WPCM450_PIN(127),
+};
+
+/* Enable mode in pin group */
+static void wpcm450_setfunc(struct regmap *gcr_regmap, const unsigned int *pin,
+			    int npins, int func)
+{
+	const struct wpcm450_pincfg *cfg;
+	int i;
+
+	for (i = 0; i < npins; i++) {
+		cfg = &pincfg[pin[i]];
+		if (func == fn_gpio || cfg->fn0 == func || cfg->fn1 == func) {
+			if (cfg->reg0)
+				regmap_update_bits(gcr_regmap, cfg->reg0,
+						   BIT(cfg->bit0),
+						   (cfg->fn0 == func) ?  BIT(cfg->bit0) : 0);
+			if (cfg->reg1)
+				regmap_update_bits(gcr_regmap, cfg->reg1,
+						   BIT(cfg->bit1),
+						   (cfg->fn1 == func) ?  BIT(cfg->bit1) : 0);
+		}
+	}
+}
+
+static int wpcm450_get_groups_count(struct pinctrl_dev *pctldev)
+{
+	return ARRAY_SIZE(wpcm450_groups);
+}
+
+static const char *wpcm450_get_group_name(struct pinctrl_dev *pctldev,
+					  unsigned int selector)
+{
+	return wpcm450_groups[selector].name;
+}
+
+static int wpcm450_get_group_pins(struct pinctrl_dev *pctldev,
+				  unsigned int selector,
+				  const unsigned int **pins,
+				  unsigned int *npins)
+{
+	*npins = wpcm450_groups[selector].num_pins;
+	*pins  = wpcm450_groups[selector].pins;
+
+	return 0;
+}
+
+static int wpcm450_dt_node_to_map(struct pinctrl_dev *pctldev,
+				  struct device_node *np_config,
+				  struct pinctrl_map **map,
+				  u32 *num_maps)
+{
+	return pinconf_generic_dt_node_to_map(pctldev, np_config,
+					      map, num_maps,
+					      PIN_MAP_TYPE_INVALID);
+}
+
+static void wpcm450_dt_free_map(struct pinctrl_dev *pctldev,
+				struct pinctrl_map *map, u32 num_maps)
+{
+	kfree(map);
+}
+
+static const struct pinctrl_ops wpcm450_pinctrl_ops = {
+	.get_groups_count = wpcm450_get_groups_count,
+	.get_group_name = wpcm450_get_group_name,
+	.get_group_pins = wpcm450_get_group_pins,
+	.dt_node_to_map = wpcm450_dt_node_to_map,
+	.dt_free_map = wpcm450_dt_free_map,
+};
+
+static int wpcm450_get_functions_count(struct pinctrl_dev *pctldev)
+{
+	return ARRAY_SIZE(wpcm450_funcs);
+}
+
+static const char *wpcm450_get_function_name(struct pinctrl_dev *pctldev,
+					     unsigned int function)
+{
+	return wpcm450_funcs[function].name;
+}
+
+static int wpcm450_get_function_groups(struct pinctrl_dev *pctldev,
+				       unsigned int function,
+				       const char * const **groups,
+				       unsigned int * const ngroups)
+{
+	*ngroups = wpcm450_funcs[function].ngroups;
+	*groups	 = wpcm450_funcs[function].groups;
+
+	return 0;
+}
+
+static int wpcm450_pinmux_set_mux(struct pinctrl_dev *pctldev,
+				  unsigned int function,
+				  unsigned int group)
+{
+	struct wpcm450_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
+
+	wpcm450_setfunc(pctrl->gcr_regmap, wpcm450_groups[group].pins,
+			wpcm450_groups[group].num_pins, function);
+
+	return 0;
+}
+
+static const struct pinmux_ops wpcm450_pinmux_ops = {
+	.get_functions_count = wpcm450_get_functions_count,
+	.get_function_name = wpcm450_get_function_name,
+	.get_function_groups = wpcm450_get_function_groups,
+	.set_mux = wpcm450_pinmux_set_mux,
+};
+
+static int debounce_bitnum(int gpio)
+{
+	if (gpio >= 0 && gpio < 16)
+		return gpio;
+	return -EINVAL;
+}
+
+static int wpcm450_config_get(struct pinctrl_dev *pctldev, unsigned int pin,
+			      unsigned long *config)
+{
+	struct wpcm450_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
+	enum pin_config_param param = pinconf_to_config_param(*config);
+	unsigned long flags;
+	int bit;
+	u32 reg;
+
+	switch (param) {
+	case PIN_CONFIG_INPUT_DEBOUNCE:
+		bit = debounce_bitnum(pin);
+		if (bit < 0)
+			return bit;
+
+		spin_lock_irqsave(&pctrl->lock, flags);
+		reg = ioread32(pctrl->gpio_base + WPCM450_GPEVDBNC);
+		spin_unlock_irqrestore(&pctrl->lock, flags);
+
+		*config = pinconf_to_config_packed(param, !!(reg & BIT(bit)));
+		break;
+	default:
+		return -ENOTSUPP;
+	}
+
+	return 0;
+}
+
+static int wpcm450_config_set_one(struct wpcm450_pinctrl *pctrl,
+				  unsigned int pin, unsigned long config)
+{
+	enum pin_config_param param = pinconf_to_config_param(config);
+	unsigned long flags;
+	unsigned long reg;
+	int bit;
+	int arg;
+
+	switch (param) {
+	case PIN_CONFIG_INPUT_DEBOUNCE:
+		bit = debounce_bitnum(pin);
+		if (bit < 0)
+			return bit;
+
+		arg = pinconf_to_config_argument(config);
+
+		spin_lock_irqsave(&pctrl->lock, flags);
+		reg = ioread32(pctrl->gpio_base + WPCM450_GPEVDBNC);
+		__assign_bit(bit, &reg, arg);
+		iowrite32(reg, pctrl->gpio_base + WPCM450_GPEVDBNC);
+		spin_unlock_irqrestore(&pctrl->lock, flags);
+		break;
+	default:
+		return -ENOTSUPP;
+	}
+
+	return 0;
+}
+
+static int wpcm450_config_set(struct pinctrl_dev *pctldev, unsigned int pin,
+			      unsigned long *configs, unsigned int num_configs)
+{
+	struct wpcm450_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
+	int ret;
+
+	while (num_configs--) {
+		ret = wpcm450_config_set_one(pctrl, pin, *configs++);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static const struct pinconf_ops wpcm450_pinconf_ops = {
+	.is_generic = true,
+	.pin_config_get = wpcm450_config_get,
+	.pin_config_set = wpcm450_config_set,
+};
+
+static struct pinctrl_desc wpcm450_pinctrl_desc = {
+	.name = "wpcm450-pinctrl",
+	.pins = wpcm450_pins,
+	.npins = ARRAY_SIZE(wpcm450_pins),
+	.pctlops = &wpcm450_pinctrl_ops,
+	.pmxops = &wpcm450_pinmux_ops,
+	.confops = &wpcm450_pinconf_ops,
+	.owner = THIS_MODULE,
+};
+
+static int wpcm450_gpio_set_config(struct gpio_chip *chip,
+				   unsigned int offset, unsigned long config)
+{
+	struct wpcm450_gpio *gpio = gpiochip_get_data(chip);
+
+	return wpcm450_config_set_one(gpio->pctrl, offset, config);
+}
+
+static int wpcm450_gpio_register(struct platform_device *pdev,
+				 struct wpcm450_pinctrl *pctrl)
+{
+	int ret = 0;
+	struct fwnode_handle *np;
+
+	pctrl->gpio_base = devm_platform_ioremap_resource(pdev, 0);
+	if (!pctrl->gpio_base) {
+		dev_err(pctrl->dev, "Resource fail for GPIO controller\n");
+		return -ENOMEM;
+	}
+
+	fwnode_for_each_available_child_node(pctrl->dev->fwnode, np) {
+		void __iomem *dat = NULL;
+		void __iomem *set = NULL;
+		void __iomem *dirout = NULL;
+		unsigned long flags = 0;
+		const struct wpcm450_bank *bank;
+		struct wpcm450_gpio *gpio;
+		struct gpio_irq_chip *girq;
+		u32 interrupt_map[3];
+		int reg, i;
+
+		if (!fwnode_property_read_bool(np, "gpio-controller"))
+			continue;
+
+		ret = fwnode_property_read_u32(np, "reg", &reg);
+		if (ret < 0)
+			return ret;
+
+		gpio = &pctrl->gpio_bank[reg];
+		gpio->pctrl = pctrl;
+
+		if (reg < 0 || reg > WPCM450_NUM_BANKS) {
+			dev_err(pctrl->dev, "GPIO index %d out of range!\n", reg);
+			return -EINVAL;
+		}
+
+		bank = &wpcm450_banks[reg];
+
+		dat = pctrl->gpio_base + bank->datain;
+		if (bank->dataout) {
+			set = pctrl->gpio_base + bank->dataout;
+			dirout = pctrl->gpio_base + bank->cfg0;
+		} else {
+			flags = BGPIOF_NO_OUTPUT;
+		}
+		ret = bgpio_init(&gpio->gc, pctrl->dev, 4,
+				 dat, set, NULL, dirout, NULL, flags);
+		if (ret < 0) {
+			dev_err(pctrl->dev, "GPIO initialization failed: %d\n", ret);
+			return ret;
+		}
+
+		gpio->gc.ngpio = bank->length;
+		gpio->gc.set_config = wpcm450_gpio_set_config;
+		gpio->gc.of_node = to_of_node(np);
+		gpio->gc.parent = pctrl->dev;
+
+		gpio->irqc = wpcm450_gpio_irqchip;
+		girq = &gpio->gc.irq;
+		girq->chip = &gpio->irqc;
+		girq->parent_handler = wpcm450_gpio_irqhandler;
+		girq->parents = devm_kcalloc(pctrl->dev, WPCM450_NUM_GPIO_IRQS,
+					     sizeof(*girq->parents), GFP_KERNEL);
+		if (!girq->parents)
+			return -ENOMEM;
+		girq->default_type = IRQ_TYPE_NONE;
+		girq->handler = handle_bad_irq;
+
+		girq->num_parents = 0;
+		for (i = 0; i < WPCM450_NUM_GPIO_IRQS; i++) {
+			int irq = fwnode_irq_get(np, i);
+
+			if (irq < 0)
+				break;
+
+			girq->parents[i] = irq;
+			girq->num_parents++;
+		}
+
+		ret = fwnode_property_read_u32_array(np, "nuvoton,interrupt-map",
+						     interrupt_map, ARRAY_SIZE(interrupt_map));
+		if (ret == 0) {
+			gpio->first_irq_bit = interrupt_map[0];
+			gpio->num_irqs = interrupt_map[1];
+			gpio->first_irq_gpio = interrupt_map[2];
+		}
+
+		ret = devm_gpiochip_add_data(pctrl->dev, &gpio->gc, gpio);
+		if (ret) {
+			dev_err(pctrl->dev, "Failed to add GPIO chip: %d\n", ret);
+			return ret;
+		}
+
+		ret = gpiochip_add_pin_range(&gpio->gc, dev_name(pctrl->dev),
+					     0, bank->base, bank->length);
+		if (ret) {
+			dev_err(pctrl->dev, "Failed to add pin range for GPIO bank %u\n", reg);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+static int wpcm450_pinctrl_probe(struct platform_device *pdev)
+{
+	struct wpcm450_pinctrl *pctrl;
+	int ret;
+
+	pctrl = devm_kzalloc(&pdev->dev, sizeof(*pctrl), GFP_KERNEL);
+	if (!pctrl)
+		return -ENOMEM;
+
+	pctrl->dev = &pdev->dev;
+	spin_lock_init(&pctrl->lock);
+	dev_set_drvdata(&pdev->dev, pctrl);
+
+	pctrl->gcr_regmap =
+		syscon_regmap_lookup_by_compatible("nuvoton,wpcm450-gcr");
+	if (IS_ERR(pctrl->gcr_regmap)) {
+		dev_err_probe(pctrl->dev, PTR_ERR(pctrl->gcr_regmap),
+			      "Failed to find nuvoton,wpcm450-gcr\n");
+		return PTR_ERR(pctrl->gcr_regmap);
+	}
+
+	pctrl->pctldev = devm_pinctrl_register(&pdev->dev,
+					       &wpcm450_pinctrl_desc, pctrl);
+	if (IS_ERR(pctrl->pctldev)) {
+		dev_err_probe(&pdev->dev, PTR_ERR(pctrl->pctldev),
+			      "Failed to register pinctrl device\n");
+		return PTR_ERR(pctrl->pctldev);
+	}
+
+	ret = wpcm450_gpio_register(pdev, pctrl);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static const struct of_device_id wpcm450_pinctrl_match[] = {
+	{ .compatible = "nuvoton,wpcm450-pinctrl" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, wpcm450_pinctrl_match);
+
+static struct platform_driver wpcm450_pinctrl_driver = {
+	.probe = wpcm450_pinctrl_probe,
+	.driver = {
+		.name = "wpcm450-pinctrl",
+		.of_match_table = wpcm450_pinctrl_match,
+	},
+};
+module_platform_driver(wpcm450_pinctrl_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Jonathan Neuschäfer <j.neuschaefer@gmx.net>");
+MODULE_DESCRIPTION("Nuvoton WPCM450 Pinctrl and GPIO driver");
--
2.30.2


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

* [PATCH v2 6/8] ARM: dts: wpcm450: Add pinctrl and GPIO nodes
  2021-12-07 21:08 ` Jonathan Neuschäfer
@ 2021-12-07 21:08   ` Jonathan Neuschäfer
  -1 siblings, 0 replies; 53+ messages in thread
From: Jonathan Neuschäfer @ 2021-12-07 21:08 UTC (permalink / raw)
  To: linux-gpio, devicetree
  Cc: Linus Walleij, Rob Herring, openbmc, Tomer Maimon, Joel Stanley,
	linux-kernel, Jonathan Neuschäfer

This patch adds the pin controller and GPIO banks to the devicetree for the
WPCM450 SoC.

Signed-off-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>


---
v2:
- Move GPIO banks into subnodes
- Add /alias/gpio*

v1:
- https://lore.kernel.org/lkml/20210602120329.2444672-7-j.neuschaefer@gmx.net/
---
 arch/arm/boot/dts/nuvoton-wpcm450.dtsi | 74 ++++++++++++++++++++++++++
 1 file changed, 74 insertions(+)

diff --git a/arch/arm/boot/dts/nuvoton-wpcm450.dtsi b/arch/arm/boot/dts/nuvoton-wpcm450.dtsi
index a17ee70085dd0..a795cc4128654 100644
--- a/arch/arm/boot/dts/nuvoton-wpcm450.dtsi
+++ b/arch/arm/boot/dts/nuvoton-wpcm450.dtsi
@@ -8,6 +8,17 @@ / {
 	#address-cells = <1>;
 	#size-cells = <1>;

+	aliases {
+		gpio0 = &gpio0;
+		gpio1 = &gpio1;
+		gpio2 = &gpio2;
+		gpio3 = &gpio3;
+		gpio4 = &gpio4;
+		gpio5 = &gpio5;
+		gpio6 = &gpio6;
+		gpio7 = &gpio7;
+	};
+
 	cpus {
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -77,5 +88,68 @@ aic: interrupt-controller@b8002000 {
 			interrupt-controller;
 			#interrupt-cells = <2>;
 		};
+
+		pinctrl: pinctrl@b8003000 {
+			compatible = "nuvoton,wpcm450-pinctrl";
+			reg = <0xb8003000 0x1000>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			gpio0: gpio@0 {
+				reg = <0>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupts = <2 IRQ_TYPE_LEVEL_HIGH
+					      3 IRQ_TYPE_LEVEL_HIGH
+					      4 IRQ_TYPE_LEVEL_HIGH>;
+				interrupt-controller;
+				nuvoton,interrupt-map = <0 16 0>;
+			};
+
+			gpio1: gpio@1 {
+				reg = <1>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupts = <5 IRQ_TYPE_LEVEL_HIGH>;
+				interrupt-controller;
+				nuvoton,interrupt-map = <16 2 8>;
+			};
+
+			gpio2: gpio@2 {
+				reg = <2>;
+				gpio-controller;
+				#gpio-cells = <2>;
+			};
+
+			gpio3: gpio@3 {
+				reg = <3>;
+				gpio-controller;
+				#gpio-cells = <2>;
+			};
+
+			gpio4: gpio@4 {
+				reg = <4>;
+				gpio-controller;
+				#gpio-cells = <2>;
+			};
+
+			gpio5: gpio@5 {
+				reg = <5>;
+				gpio-controller;
+				#gpio-cells = <2>;
+			};
+
+			gpio6: gpio@6 {
+				reg = <6>;
+				gpio-controller;
+				#gpio-cells = <2>;
+			};
+
+			gpio7: gpio@7 {
+				reg = <7>;
+				gpio-controller;
+				#gpio-cells = <2>;
+			};
+		};
 	};
 };
--
2.30.2


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

* [PATCH v2 6/8] ARM: dts: wpcm450: Add pinctrl and GPIO nodes
@ 2021-12-07 21:08   ` Jonathan Neuschäfer
  0 siblings, 0 replies; 53+ messages in thread
From: Jonathan Neuschäfer @ 2021-12-07 21:08 UTC (permalink / raw)
  To: linux-gpio, devicetree
  Cc: Tomer Maimon, Linus Walleij, linux-kernel,
	Jonathan Neuschäfer, Rob Herring, openbmc

This patch adds the pin controller and GPIO banks to the devicetree for the
WPCM450 SoC.

Signed-off-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>


---
v2:
- Move GPIO banks into subnodes
- Add /alias/gpio*

v1:
- https://lore.kernel.org/lkml/20210602120329.2444672-7-j.neuschaefer@gmx.net/
---
 arch/arm/boot/dts/nuvoton-wpcm450.dtsi | 74 ++++++++++++++++++++++++++
 1 file changed, 74 insertions(+)

diff --git a/arch/arm/boot/dts/nuvoton-wpcm450.dtsi b/arch/arm/boot/dts/nuvoton-wpcm450.dtsi
index a17ee70085dd0..a795cc4128654 100644
--- a/arch/arm/boot/dts/nuvoton-wpcm450.dtsi
+++ b/arch/arm/boot/dts/nuvoton-wpcm450.dtsi
@@ -8,6 +8,17 @@ / {
 	#address-cells = <1>;
 	#size-cells = <1>;

+	aliases {
+		gpio0 = &gpio0;
+		gpio1 = &gpio1;
+		gpio2 = &gpio2;
+		gpio3 = &gpio3;
+		gpio4 = &gpio4;
+		gpio5 = &gpio5;
+		gpio6 = &gpio6;
+		gpio7 = &gpio7;
+	};
+
 	cpus {
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -77,5 +88,68 @@ aic: interrupt-controller@b8002000 {
 			interrupt-controller;
 			#interrupt-cells = <2>;
 		};
+
+		pinctrl: pinctrl@b8003000 {
+			compatible = "nuvoton,wpcm450-pinctrl";
+			reg = <0xb8003000 0x1000>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			gpio0: gpio@0 {
+				reg = <0>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupts = <2 IRQ_TYPE_LEVEL_HIGH
+					      3 IRQ_TYPE_LEVEL_HIGH
+					      4 IRQ_TYPE_LEVEL_HIGH>;
+				interrupt-controller;
+				nuvoton,interrupt-map = <0 16 0>;
+			};
+
+			gpio1: gpio@1 {
+				reg = <1>;
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupts = <5 IRQ_TYPE_LEVEL_HIGH>;
+				interrupt-controller;
+				nuvoton,interrupt-map = <16 2 8>;
+			};
+
+			gpio2: gpio@2 {
+				reg = <2>;
+				gpio-controller;
+				#gpio-cells = <2>;
+			};
+
+			gpio3: gpio@3 {
+				reg = <3>;
+				gpio-controller;
+				#gpio-cells = <2>;
+			};
+
+			gpio4: gpio@4 {
+				reg = <4>;
+				gpio-controller;
+				#gpio-cells = <2>;
+			};
+
+			gpio5: gpio@5 {
+				reg = <5>;
+				gpio-controller;
+				#gpio-cells = <2>;
+			};
+
+			gpio6: gpio@6 {
+				reg = <6>;
+				gpio-controller;
+				#gpio-cells = <2>;
+			};
+
+			gpio7: gpio@7 {
+				reg = <7>;
+				gpio-controller;
+				#gpio-cells = <2>;
+			};
+		};
 	};
 };
--
2.30.2


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

* [PATCH v2 7/8] ARM: dts: wpcm450: Add pin functions
  2021-12-07 21:08 ` Jonathan Neuschäfer
@ 2021-12-07 21:08   ` Jonathan Neuschäfer
  -1 siblings, 0 replies; 53+ messages in thread
From: Jonathan Neuschäfer @ 2021-12-07 21:08 UTC (permalink / raw)
  To: linux-gpio, devicetree
  Cc: Linus Walleij, Rob Herring, openbmc, Tomer Maimon, Joel Stanley,
	linux-kernel, Jonathan Neuschäfer

As done in nuvoton-common-npcm7xx.dtsi, this patch adds pinmux nodes for
all pin functions to nuvoton-wpcm450.dtsi.

Signed-off-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>
---

I'm not quite convinced of the value of this patch, as the pin functions
could easily be specified in board.dts files when needed.


v2:
- no changes

v1:
- https://lore.kernel.org/lkml/20210602120329.2444672-8-j.neuschaefer@gmx.net/
---
 arch/arm/boot/dts/nuvoton-wpcm450.dtsi | 305 +++++++++++++++++++++++++
 1 file changed, 305 insertions(+)

diff --git a/arch/arm/boot/dts/nuvoton-wpcm450.dtsi b/arch/arm/boot/dts/nuvoton-wpcm450.dtsi
index a795cc4128654..b377e61714bcb 100644
--- a/arch/arm/boot/dts/nuvoton-wpcm450.dtsi
+++ b/arch/arm/boot/dts/nuvoton-wpcm450.dtsi
@@ -150,6 +150,311 @@ gpio7: gpio@7 {
 				gpio-controller;
 				#gpio-cells = <2>;
 			};
+
+			smb3_pins: smb3-pins {
+				groups = "smb3";
+				function = "smb3";
+			};
+
+			smb4_pins: smb4-pins {
+				groups = "smb4";
+				function = "smb4";
+			};
+
+			smb5_pins: smb5-pins {
+				groups = "smb5";
+				function = "smb5";
+			};
+
+			scs1_pins: scs1-pins {
+				groups = "scs1";
+				function = "scs1";
+			};
+
+			scs2_pins: scs2-pins {
+				groups = "scs2";
+				function = "scs2";
+			};
+
+			scs3_pins: scs3-pins {
+				groups = "scs3";
+				function = "scs3";
+			};
+
+			smb0_pins: smb0-pins {
+				groups = "smb0";
+				function = "smb0";
+			};
+
+			smb1_pins: smb1-pins {
+				groups = "smb1";
+				function = "smb1";
+			};
+
+			smb2_pins: smb2-pins {
+				groups = "smb2";
+				function = "smb2";
+			};
+
+			bsp_pins: bsp-pins {
+				groups = "bsp";
+				function = "bsp";
+			};
+
+			hsp1_pins: hsp1-pins {
+				groups = "hsp1";
+				function = "hsp1";
+			};
+
+			hsp2_pins: hsp2-pins {
+				groups = "hsp2";
+				function = "hsp2";
+			};
+
+			r1err_pins: r1err-pins {
+				groups = "r1err";
+				function = "r1err";
+			};
+
+			r1md_pins: r1md-pins {
+				groups = "r1md";
+				function = "r1md";
+			};
+
+			rmii2_pins: rmii2-pins {
+				groups = "rmii2";
+				function = "rmii2";
+			};
+
+			r2err_pins: r2err-pins {
+				groups = "r2err";
+				function = "r2err";
+			};
+
+			r2md_pins: r2md-pins {
+				groups = "r2md";
+				function = "r2md";
+			};
+
+			kbcc_pins: kbcc-pins {
+				groups = "kbcc";
+				function = "kbcc";
+			};
+
+			dvo0_pins: dvo0-pins {
+				groups = "dvo";
+				function = "dvo0";
+			};
+
+			dvo3_pins: dvo3-pins {
+				groups = "dvo";
+				function = "dvo3";
+			};
+
+			clko_pins: clko-pins {
+				groups = "clko";
+				function = "clko";
+			};
+
+			smi_pins: smi-pins {
+				groups = "smi";
+				function = "smi";
+			};
+
+			uinc_pins: uinc-pins {
+				groups = "uinc";
+				function = "uinc";
+			};
+
+			gspi_pins: gspi-pins {
+				groups = "gspi";
+				function = "gspi";
+			};
+
+			mben_pins: mben-pins {
+				groups = "mben";
+				function = "mben";
+			};
+
+			xcs2_pins: xcs2-pins {
+				groups = "xcs2";
+				function = "xcs2";
+			};
+
+			xcs1_pins: xcs1-pins {
+				groups = "xcs1";
+				function = "xcs1";
+			};
+
+			sdio_pins: sdio-pins {
+				groups = "sdio";
+				function = "sdio";
+			};
+
+			sspi_pins: sspi-pins {
+				groups = "sspi";
+				function = "sspi";
+			};
+
+			fi0_pins: fi0-pins {
+				groups = "fi0";
+				function = "fi0";
+			};
+
+			fi1_pins: fi1-pins {
+				groups = "fi1";
+				function = "fi1";
+			};
+
+			fi2_pins: fi2-pins {
+				groups = "fi2";
+				function = "fi2";
+			};
+
+			fi3_pins: fi3-pins {
+				groups = "fi3";
+				function = "fi3";
+			};
+
+			fi4_pins: fi4-pins {
+				groups = "fi4";
+				function = "fi4";
+			};
+
+			fi5_pins: fi5-pins {
+				groups = "fi5";
+				function = "fi5";
+			};
+
+			fi6_pins: fi6-pins {
+				groups = "fi6";
+				function = "fi6";
+			};
+
+			fi7_pins: fi7-pins {
+				groups = "fi7";
+				function = "fi7";
+			};
+
+			fi8_pins: fi8-pins {
+				groups = "fi8";
+				function = "fi8";
+			};
+
+			fi9_pins: fi9-pins {
+				groups = "fi9";
+				function = "fi9";
+			};
+
+			fi10_pins: fi10-pins {
+				groups = "fi10";
+				function = "fi10";
+			};
+
+			fi11_pins: fi11-pins {
+				groups = "fi11";
+				function = "fi11";
+			};
+
+			fi12_pins: fi12-pins {
+				groups = "fi12";
+				function = "fi12";
+			};
+
+			fi13_pins: fi13-pins {
+				groups = "fi13";
+				function = "fi13";
+			};
+
+			fi14_pins: fi14-pins {
+				groups = "fi14";
+				function = "fi14";
+			};
+
+			fi15_pins: fi15-pins {
+				groups = "fi15";
+				function = "fi15";
+			};
+
+			pwm0_pins: pwm0-pins {
+				groups = "pwm0";
+				function = "pwm0";
+			};
+
+			pwm1_pins: pwm1-pins {
+				groups = "pwm1";
+				function = "pwm1";
+			};
+
+			pwm2_pins: pwm2-pins {
+				groups = "pwm2";
+				function = "pwm2";
+			};
+
+			pwm3_pins: pwm3-pins {
+				groups = "pwm3";
+				function = "pwm3";
+			};
+
+			pwm4_pins: pwm4-pins {
+				groups = "pwm4";
+				function = "pwm4";
+			};
+
+			pwm5_pins: pwm5-pins {
+				groups = "pwm5";
+				function = "pwm5";
+			};
+
+			pwm6_pins: pwm6-pins {
+				groups = "pwm6";
+				function = "pwm6";
+			};
+
+			pwm7_pins: pwm7-pins {
+				groups = "pwm7";
+				function = "pwm7";
+			};
+
+			hg0_pins: hg0-pins {
+				groups = "hg0";
+				function = "hg0";
+			};
+
+			hg1_pins: hg1-pins {
+				groups = "hg1";
+				function = "hg1";
+			};
+
+			hg2_pins: hg2-pins {
+				groups = "hg2";
+				function = "hg2";
+			};
+
+			hg3_pins: hg3-pins {
+				groups = "hg3";
+				function = "hg3";
+			};
+
+			hg4_pins: hg4-pins {
+				groups = "hg4";
+				function = "hg4";
+			};
+
+			hg5_pins: hg5-pins {
+				groups = "hg5";
+				function = "hg5";
+			};
+
+			hg6_pins: hg6-pins {
+				groups = "hg6";
+				function = "hg6";
+			};
+
+			hg7_pins: hg7-pins {
+				groups = "hg7";
+				function = "hg7";
+			};
 		};
 	};
 };
--
2.30.2


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

* [PATCH v2 7/8] ARM: dts: wpcm450: Add pin functions
@ 2021-12-07 21:08   ` Jonathan Neuschäfer
  0 siblings, 0 replies; 53+ messages in thread
From: Jonathan Neuschäfer @ 2021-12-07 21:08 UTC (permalink / raw)
  To: linux-gpio, devicetree
  Cc: Tomer Maimon, Linus Walleij, linux-kernel,
	Jonathan Neuschäfer, Rob Herring, openbmc

As done in nuvoton-common-npcm7xx.dtsi, this patch adds pinmux nodes for
all pin functions to nuvoton-wpcm450.dtsi.

Signed-off-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>
---

I'm not quite convinced of the value of this patch, as the pin functions
could easily be specified in board.dts files when needed.


v2:
- no changes

v1:
- https://lore.kernel.org/lkml/20210602120329.2444672-8-j.neuschaefer@gmx.net/
---
 arch/arm/boot/dts/nuvoton-wpcm450.dtsi | 305 +++++++++++++++++++++++++
 1 file changed, 305 insertions(+)

diff --git a/arch/arm/boot/dts/nuvoton-wpcm450.dtsi b/arch/arm/boot/dts/nuvoton-wpcm450.dtsi
index a795cc4128654..b377e61714bcb 100644
--- a/arch/arm/boot/dts/nuvoton-wpcm450.dtsi
+++ b/arch/arm/boot/dts/nuvoton-wpcm450.dtsi
@@ -150,6 +150,311 @@ gpio7: gpio@7 {
 				gpio-controller;
 				#gpio-cells = <2>;
 			};
+
+			smb3_pins: smb3-pins {
+				groups = "smb3";
+				function = "smb3";
+			};
+
+			smb4_pins: smb4-pins {
+				groups = "smb4";
+				function = "smb4";
+			};
+
+			smb5_pins: smb5-pins {
+				groups = "smb5";
+				function = "smb5";
+			};
+
+			scs1_pins: scs1-pins {
+				groups = "scs1";
+				function = "scs1";
+			};
+
+			scs2_pins: scs2-pins {
+				groups = "scs2";
+				function = "scs2";
+			};
+
+			scs3_pins: scs3-pins {
+				groups = "scs3";
+				function = "scs3";
+			};
+
+			smb0_pins: smb0-pins {
+				groups = "smb0";
+				function = "smb0";
+			};
+
+			smb1_pins: smb1-pins {
+				groups = "smb1";
+				function = "smb1";
+			};
+
+			smb2_pins: smb2-pins {
+				groups = "smb2";
+				function = "smb2";
+			};
+
+			bsp_pins: bsp-pins {
+				groups = "bsp";
+				function = "bsp";
+			};
+
+			hsp1_pins: hsp1-pins {
+				groups = "hsp1";
+				function = "hsp1";
+			};
+
+			hsp2_pins: hsp2-pins {
+				groups = "hsp2";
+				function = "hsp2";
+			};
+
+			r1err_pins: r1err-pins {
+				groups = "r1err";
+				function = "r1err";
+			};
+
+			r1md_pins: r1md-pins {
+				groups = "r1md";
+				function = "r1md";
+			};
+
+			rmii2_pins: rmii2-pins {
+				groups = "rmii2";
+				function = "rmii2";
+			};
+
+			r2err_pins: r2err-pins {
+				groups = "r2err";
+				function = "r2err";
+			};
+
+			r2md_pins: r2md-pins {
+				groups = "r2md";
+				function = "r2md";
+			};
+
+			kbcc_pins: kbcc-pins {
+				groups = "kbcc";
+				function = "kbcc";
+			};
+
+			dvo0_pins: dvo0-pins {
+				groups = "dvo";
+				function = "dvo0";
+			};
+
+			dvo3_pins: dvo3-pins {
+				groups = "dvo";
+				function = "dvo3";
+			};
+
+			clko_pins: clko-pins {
+				groups = "clko";
+				function = "clko";
+			};
+
+			smi_pins: smi-pins {
+				groups = "smi";
+				function = "smi";
+			};
+
+			uinc_pins: uinc-pins {
+				groups = "uinc";
+				function = "uinc";
+			};
+
+			gspi_pins: gspi-pins {
+				groups = "gspi";
+				function = "gspi";
+			};
+
+			mben_pins: mben-pins {
+				groups = "mben";
+				function = "mben";
+			};
+
+			xcs2_pins: xcs2-pins {
+				groups = "xcs2";
+				function = "xcs2";
+			};
+
+			xcs1_pins: xcs1-pins {
+				groups = "xcs1";
+				function = "xcs1";
+			};
+
+			sdio_pins: sdio-pins {
+				groups = "sdio";
+				function = "sdio";
+			};
+
+			sspi_pins: sspi-pins {
+				groups = "sspi";
+				function = "sspi";
+			};
+
+			fi0_pins: fi0-pins {
+				groups = "fi0";
+				function = "fi0";
+			};
+
+			fi1_pins: fi1-pins {
+				groups = "fi1";
+				function = "fi1";
+			};
+
+			fi2_pins: fi2-pins {
+				groups = "fi2";
+				function = "fi2";
+			};
+
+			fi3_pins: fi3-pins {
+				groups = "fi3";
+				function = "fi3";
+			};
+
+			fi4_pins: fi4-pins {
+				groups = "fi4";
+				function = "fi4";
+			};
+
+			fi5_pins: fi5-pins {
+				groups = "fi5";
+				function = "fi5";
+			};
+
+			fi6_pins: fi6-pins {
+				groups = "fi6";
+				function = "fi6";
+			};
+
+			fi7_pins: fi7-pins {
+				groups = "fi7";
+				function = "fi7";
+			};
+
+			fi8_pins: fi8-pins {
+				groups = "fi8";
+				function = "fi8";
+			};
+
+			fi9_pins: fi9-pins {
+				groups = "fi9";
+				function = "fi9";
+			};
+
+			fi10_pins: fi10-pins {
+				groups = "fi10";
+				function = "fi10";
+			};
+
+			fi11_pins: fi11-pins {
+				groups = "fi11";
+				function = "fi11";
+			};
+
+			fi12_pins: fi12-pins {
+				groups = "fi12";
+				function = "fi12";
+			};
+
+			fi13_pins: fi13-pins {
+				groups = "fi13";
+				function = "fi13";
+			};
+
+			fi14_pins: fi14-pins {
+				groups = "fi14";
+				function = "fi14";
+			};
+
+			fi15_pins: fi15-pins {
+				groups = "fi15";
+				function = "fi15";
+			};
+
+			pwm0_pins: pwm0-pins {
+				groups = "pwm0";
+				function = "pwm0";
+			};
+
+			pwm1_pins: pwm1-pins {
+				groups = "pwm1";
+				function = "pwm1";
+			};
+
+			pwm2_pins: pwm2-pins {
+				groups = "pwm2";
+				function = "pwm2";
+			};
+
+			pwm3_pins: pwm3-pins {
+				groups = "pwm3";
+				function = "pwm3";
+			};
+
+			pwm4_pins: pwm4-pins {
+				groups = "pwm4";
+				function = "pwm4";
+			};
+
+			pwm5_pins: pwm5-pins {
+				groups = "pwm5";
+				function = "pwm5";
+			};
+
+			pwm6_pins: pwm6-pins {
+				groups = "pwm6";
+				function = "pwm6";
+			};
+
+			pwm7_pins: pwm7-pins {
+				groups = "pwm7";
+				function = "pwm7";
+			};
+
+			hg0_pins: hg0-pins {
+				groups = "hg0";
+				function = "hg0";
+			};
+
+			hg1_pins: hg1-pins {
+				groups = "hg1";
+				function = "hg1";
+			};
+
+			hg2_pins: hg2-pins {
+				groups = "hg2";
+				function = "hg2";
+			};
+
+			hg3_pins: hg3-pins {
+				groups = "hg3";
+				function = "hg3";
+			};
+
+			hg4_pins: hg4-pins {
+				groups = "hg4";
+				function = "hg4";
+			};
+
+			hg5_pins: hg5-pins {
+				groups = "hg5";
+				function = "hg5";
+			};
+
+			hg6_pins: hg6-pins {
+				groups = "hg6";
+				function = "hg6";
+			};
+
+			hg7_pins: hg7-pins {
+				groups = "hg7";
+				function = "hg7";
+			};
 		};
 	};
 };
--
2.30.2


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

* [PATCH v2 8/8] ARM: dts: wpcm450-supermicro-x9sci-ln4f: Add GPIO LEDs and buttons
  2021-12-07 21:08 ` Jonathan Neuschäfer
@ 2021-12-07 21:08   ` Jonathan Neuschäfer
  -1 siblings, 0 replies; 53+ messages in thread
From: Jonathan Neuschäfer @ 2021-12-07 21:08 UTC (permalink / raw)
  To: linux-gpio, devicetree
  Cc: Linus Walleij, Rob Herring, openbmc, Tomer Maimon, Joel Stanley,
	linux-kernel, Jonathan Neuschäfer

The Supermicro X9SCi-LN4F server mainboard has a two LEDs and a button
under the control of the BMC. This patch makes them accessible under
Linux running on the BMC.

Signed-off-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>


---
v2:
- Adjust to new GPIO controller names
- Explicitly set pinmux to GPIO for GPIO keys and LEDs

v1:
- https://lore.kernel.org/lkml/20210602120329.2444672-9-j.neuschaefer@gmx.net/
---
 .../nuvoton-wpcm450-supermicro-x9sci-ln4f.dts | 43 +++++++++++++++++++
 1 file changed, 43 insertions(+)

diff --git a/arch/arm/boot/dts/nuvoton-wpcm450-supermicro-x9sci-ln4f.dts b/arch/arm/boot/dts/nuvoton-wpcm450-supermicro-x9sci-ln4f.dts
index 83f27fbf4e939..cd8d3a6bbf853 100644
--- a/arch/arm/boot/dts/nuvoton-wpcm450-supermicro-x9sci-ln4f.dts
+++ b/arch/arm/boot/dts/nuvoton-wpcm450-supermicro-x9sci-ln4f.dts
@@ -8,6 +8,9 @@

 #include "nuvoton-wpcm450.dtsi"

+#include <dt-bindings/input/linux-event-codes.h>
+#include <dt-bindings/gpio/gpio.h>
+
 / {
 	model = "Supermicro X9SCi-LN4F BMC";
 	compatible = "supermicro,x9sci-ln4f-bmc", "nuvoton,wpcm450";
@@ -20,6 +23,46 @@ memory@0 {
 		device_type = "memory";
 		reg = <0 0x08000000>; /* 128 MiB */
 	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+		pinctrl-names = "default";
+		pinctrl-0 = <&key_pins>;
+
+		uid {
+			label = "UID button";
+			linux,code = <KEY_HOME>;
+			gpios = <&gpio0 14 GPIO_ACTIVE_HIGH>;
+		};
+	};
+
+	gpio-leds {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&led_pins>;
+
+		uid {
+			label = "UID";
+			gpios = <&gpio1 7 GPIO_ACTIVE_HIGH>;
+		};
+
+		heartbeat {
+			label = "heartbeat";
+			gpios = <&gpio1 4 GPIO_ACTIVE_LOW>;
+		};
+	};
+};
+
+&pinctrl {
+	key_pins: mux_keys {
+		groups = "gspi", "sspi";
+		function = "gpio";
+	};
+
+	led_pins: mux_leds {
+		groups = "hg3", "hg0", "pwm4";
+		function = "gpio";
+	};
 };

 &serial0 {
--
2.30.2


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

* [PATCH v2 8/8] ARM: dts: wpcm450-supermicro-x9sci-ln4f: Add GPIO LEDs and buttons
@ 2021-12-07 21:08   ` Jonathan Neuschäfer
  0 siblings, 0 replies; 53+ messages in thread
From: Jonathan Neuschäfer @ 2021-12-07 21:08 UTC (permalink / raw)
  To: linux-gpio, devicetree
  Cc: Tomer Maimon, Linus Walleij, linux-kernel,
	Jonathan Neuschäfer, Rob Herring, openbmc

The Supermicro X9SCi-LN4F server mainboard has a two LEDs and a button
under the control of the BMC. This patch makes them accessible under
Linux running on the BMC.

Signed-off-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>


---
v2:
- Adjust to new GPIO controller names
- Explicitly set pinmux to GPIO for GPIO keys and LEDs

v1:
- https://lore.kernel.org/lkml/20210602120329.2444672-9-j.neuschaefer@gmx.net/
---
 .../nuvoton-wpcm450-supermicro-x9sci-ln4f.dts | 43 +++++++++++++++++++
 1 file changed, 43 insertions(+)

diff --git a/arch/arm/boot/dts/nuvoton-wpcm450-supermicro-x9sci-ln4f.dts b/arch/arm/boot/dts/nuvoton-wpcm450-supermicro-x9sci-ln4f.dts
index 83f27fbf4e939..cd8d3a6bbf853 100644
--- a/arch/arm/boot/dts/nuvoton-wpcm450-supermicro-x9sci-ln4f.dts
+++ b/arch/arm/boot/dts/nuvoton-wpcm450-supermicro-x9sci-ln4f.dts
@@ -8,6 +8,9 @@

 #include "nuvoton-wpcm450.dtsi"

+#include <dt-bindings/input/linux-event-codes.h>
+#include <dt-bindings/gpio/gpio.h>
+
 / {
 	model = "Supermicro X9SCi-LN4F BMC";
 	compatible = "supermicro,x9sci-ln4f-bmc", "nuvoton,wpcm450";
@@ -20,6 +23,46 @@ memory@0 {
 		device_type = "memory";
 		reg = <0 0x08000000>; /* 128 MiB */
 	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+		pinctrl-names = "default";
+		pinctrl-0 = <&key_pins>;
+
+		uid {
+			label = "UID button";
+			linux,code = <KEY_HOME>;
+			gpios = <&gpio0 14 GPIO_ACTIVE_HIGH>;
+		};
+	};
+
+	gpio-leds {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&led_pins>;
+
+		uid {
+			label = "UID";
+			gpios = <&gpio1 7 GPIO_ACTIVE_HIGH>;
+		};
+
+		heartbeat {
+			label = "heartbeat";
+			gpios = <&gpio1 4 GPIO_ACTIVE_LOW>;
+		};
+	};
+};
+
+&pinctrl {
+	key_pins: mux_keys {
+		groups = "gspi", "sspi";
+		function = "gpio";
+	};
+
+	led_pins: mux_leds {
+		groups = "hg3", "hg0", "pwm4";
+		function = "gpio";
+	};
 };

 &serial0 {
--
2.30.2


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

* Re: [PATCH v2 5/8] pinctrl: nuvoton: Add driver for WPCM450
  2021-12-07 21:08   ` Jonathan Neuschäfer
  (?)
@ 2021-12-08  0:51     ` kernel test robot
  -1 siblings, 0 replies; 53+ messages in thread
From: kernel test robot @ 2021-12-08  0:51 UTC (permalink / raw)
  To: Jonathan Neuschäfer, linux-gpio, devicetree
  Cc: kbuild-all, Linus Walleij, Rob Herring, openbmc, Tomer Maimon,
	Joel Stanley, linux-kernel, Jonathan Neuschäfer

Hi "Jonathan,

I love your patch! Perhaps something to improve:

[auto build test WARNING on linusw-pinctrl/devel]
[also build test WARNING on robh/for-next linus/master v5.16-rc4 next-20211207]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Jonathan-Neusch-fer/Nuvoton-WPCM450-pinctrl-and-GPIO-driver/20211208-051101
base:   https://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl.git devel
config: h8300-randconfig-r024-20211207 (https://download.01.org/0day-ci/archive/20211208/202112080810.lGBV2yEm-lkp@intel.com/config)
compiler: h8300-linux-gcc (GCC) 11.2.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/c08fb0aafb60234854aa86433da809fe5112f55e
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Jonathan-Neusch-fer/Nuvoton-WPCM450-pinctrl-and-GPIO-driver/20211208-051101
        git checkout c08fb0aafb60234854aa86433da809fe5112f55e
        # save the config file to linux build tree
        mkdir build_dir
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross O=build_dir ARCH=h8300 SHELL=/bin/bash drivers/pinctrl/nuvoton/

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

   In file included from include/linux/device.h:15,
                    from drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c:5:
   drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c: In function 'npcm7xx_get_groups_count':
>> drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c:1564:28: warning: format '%d' expects argument of type 'int', but argument 4 has type 'long unsigned int' [-Wformat=]
    1564 |         dev_dbg(npcm->dev, "group size: %d\n", ARRAY_SIZE(npcm7xx_groups));
         |                            ^~~~~~~~~~~~~~~~~~
   include/linux/dev_printk.h:129:41: note: in definition of macro 'dev_printk'
     129 |                 _dev_printk(level, dev, fmt, ##__VA_ARGS__);            \
         |                                         ^~~
   include/linux/dev_printk.h:158:37: note: in expansion of macro 'dev_fmt'
     158 |         dev_printk(KERN_DEBUG, dev, dev_fmt(fmt), ##__VA_ARGS__)
         |                                     ^~~~~~~
   drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c:1564:9: note: in expansion of macro 'dev_dbg'
    1564 |         dev_dbg(npcm->dev, "group size: %d\n", ARRAY_SIZE(npcm7xx_groups));
         |         ^~~~~~~
   drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c:1564:42: note: format string is defined here
    1564 |         dev_dbg(npcm->dev, "group size: %d\n", ARRAY_SIZE(npcm7xx_groups));
         |                                         ~^
         |                                          |
         |                                          int
         |                                         %ld


vim +1564 drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c

3b588e43ee5c7a Tomer Maimon 2018-08-08  1559  
3b588e43ee5c7a Tomer Maimon 2018-08-08  1560  static int npcm7xx_get_groups_count(struct pinctrl_dev *pctldev)
3b588e43ee5c7a Tomer Maimon 2018-08-08  1561  {
3b588e43ee5c7a Tomer Maimon 2018-08-08  1562  	struct npcm7xx_pinctrl *npcm = pinctrl_dev_get_drvdata(pctldev);
3b588e43ee5c7a Tomer Maimon 2018-08-08  1563  
3b588e43ee5c7a Tomer Maimon 2018-08-08 @1564  	dev_dbg(npcm->dev, "group size: %d\n", ARRAY_SIZE(npcm7xx_groups));
3b588e43ee5c7a Tomer Maimon 2018-08-08  1565  	return ARRAY_SIZE(npcm7xx_groups);
3b588e43ee5c7a Tomer Maimon 2018-08-08  1566  }
3b588e43ee5c7a Tomer Maimon 2018-08-08  1567  

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

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

* Re: [PATCH v2 5/8] pinctrl: nuvoton: Add driver for WPCM450
@ 2021-12-08  0:51     ` kernel test robot
  0 siblings, 0 replies; 53+ messages in thread
From: kernel test robot @ 2021-12-08  0:51 UTC (permalink / raw)
  To: Jonathan Neuschäfer, linux-gpio, devicetree
  Cc: kbuild-all, Tomer Maimon, Linus Walleij, linux-kernel,
	Jonathan Neuschäfer, Rob Herring, openbmc

Hi "Jonathan,

I love your patch! Perhaps something to improve:

[auto build test WARNING on linusw-pinctrl/devel]
[also build test WARNING on robh/for-next linus/master v5.16-rc4 next-20211207]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Jonathan-Neusch-fer/Nuvoton-WPCM450-pinctrl-and-GPIO-driver/20211208-051101
base:   https://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl.git devel
config: h8300-randconfig-r024-20211207 (https://download.01.org/0day-ci/archive/20211208/202112080810.lGBV2yEm-lkp@intel.com/config)
compiler: h8300-linux-gcc (GCC) 11.2.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/c08fb0aafb60234854aa86433da809fe5112f55e
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Jonathan-Neusch-fer/Nuvoton-WPCM450-pinctrl-and-GPIO-driver/20211208-051101
        git checkout c08fb0aafb60234854aa86433da809fe5112f55e
        # save the config file to linux build tree
        mkdir build_dir
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross O=build_dir ARCH=h8300 SHELL=/bin/bash drivers/pinctrl/nuvoton/

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

   In file included from include/linux/device.h:15,
                    from drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c:5:
   drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c: In function 'npcm7xx_get_groups_count':
>> drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c:1564:28: warning: format '%d' expects argument of type 'int', but argument 4 has type 'long unsigned int' [-Wformat=]
    1564 |         dev_dbg(npcm->dev, "group size: %d\n", ARRAY_SIZE(npcm7xx_groups));
         |                            ^~~~~~~~~~~~~~~~~~
   include/linux/dev_printk.h:129:41: note: in definition of macro 'dev_printk'
     129 |                 _dev_printk(level, dev, fmt, ##__VA_ARGS__);            \
         |                                         ^~~
   include/linux/dev_printk.h:158:37: note: in expansion of macro 'dev_fmt'
     158 |         dev_printk(KERN_DEBUG, dev, dev_fmt(fmt), ##__VA_ARGS__)
         |                                     ^~~~~~~
   drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c:1564:9: note: in expansion of macro 'dev_dbg'
    1564 |         dev_dbg(npcm->dev, "group size: %d\n", ARRAY_SIZE(npcm7xx_groups));
         |         ^~~~~~~
   drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c:1564:42: note: format string is defined here
    1564 |         dev_dbg(npcm->dev, "group size: %d\n", ARRAY_SIZE(npcm7xx_groups));
         |                                         ~^
         |                                          |
         |                                          int
         |                                         %ld


vim +1564 drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c

3b588e43ee5c7a Tomer Maimon 2018-08-08  1559  
3b588e43ee5c7a Tomer Maimon 2018-08-08  1560  static int npcm7xx_get_groups_count(struct pinctrl_dev *pctldev)
3b588e43ee5c7a Tomer Maimon 2018-08-08  1561  {
3b588e43ee5c7a Tomer Maimon 2018-08-08  1562  	struct npcm7xx_pinctrl *npcm = pinctrl_dev_get_drvdata(pctldev);
3b588e43ee5c7a Tomer Maimon 2018-08-08  1563  
3b588e43ee5c7a Tomer Maimon 2018-08-08 @1564  	dev_dbg(npcm->dev, "group size: %d\n", ARRAY_SIZE(npcm7xx_groups));
3b588e43ee5c7a Tomer Maimon 2018-08-08  1565  	return ARRAY_SIZE(npcm7xx_groups);
3b588e43ee5c7a Tomer Maimon 2018-08-08  1566  }
3b588e43ee5c7a Tomer Maimon 2018-08-08  1567  

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

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

* Re: [PATCH v2 5/8] pinctrl: nuvoton: Add driver for WPCM450
@ 2021-12-08  0:51     ` kernel test robot
  0 siblings, 0 replies; 53+ messages in thread
From: kernel test robot @ 2021-12-08  0:51 UTC (permalink / raw)
  To: kbuild-all

[-- Attachment #1: Type: text/plain, Size: 4080 bytes --]

Hi "Jonathan,

I love your patch! Perhaps something to improve:

[auto build test WARNING on linusw-pinctrl/devel]
[also build test WARNING on robh/for-next linus/master v5.16-rc4 next-20211207]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Jonathan-Neusch-fer/Nuvoton-WPCM450-pinctrl-and-GPIO-driver/20211208-051101
base:   https://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl.git devel
config: h8300-randconfig-r024-20211207 (https://download.01.org/0day-ci/archive/20211208/202112080810.lGBV2yEm-lkp(a)intel.com/config)
compiler: h8300-linux-gcc (GCC) 11.2.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/c08fb0aafb60234854aa86433da809fe5112f55e
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Jonathan-Neusch-fer/Nuvoton-WPCM450-pinctrl-and-GPIO-driver/20211208-051101
        git checkout c08fb0aafb60234854aa86433da809fe5112f55e
        # save the config file to linux build tree
        mkdir build_dir
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross O=build_dir ARCH=h8300 SHELL=/bin/bash drivers/pinctrl/nuvoton/

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

   In file included from include/linux/device.h:15,
                    from drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c:5:
   drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c: In function 'npcm7xx_get_groups_count':
>> drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c:1564:28: warning: format '%d' expects argument of type 'int', but argument 4 has type 'long unsigned int' [-Wformat=]
    1564 |         dev_dbg(npcm->dev, "group size: %d\n", ARRAY_SIZE(npcm7xx_groups));
         |                            ^~~~~~~~~~~~~~~~~~
   include/linux/dev_printk.h:129:41: note: in definition of macro 'dev_printk'
     129 |                 _dev_printk(level, dev, fmt, ##__VA_ARGS__);            \
         |                                         ^~~
   include/linux/dev_printk.h:158:37: note: in expansion of macro 'dev_fmt'
     158 |         dev_printk(KERN_DEBUG, dev, dev_fmt(fmt), ##__VA_ARGS__)
         |                                     ^~~~~~~
   drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c:1564:9: note: in expansion of macro 'dev_dbg'
    1564 |         dev_dbg(npcm->dev, "group size: %d\n", ARRAY_SIZE(npcm7xx_groups));
         |         ^~~~~~~
   drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c:1564:42: note: format string is defined here
    1564 |         dev_dbg(npcm->dev, "group size: %d\n", ARRAY_SIZE(npcm7xx_groups));
         |                                         ~^
         |                                          |
         |                                          int
         |                                         %ld


vim +1564 drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c

3b588e43ee5c7a Tomer Maimon 2018-08-08  1559  
3b588e43ee5c7a Tomer Maimon 2018-08-08  1560  static int npcm7xx_get_groups_count(struct pinctrl_dev *pctldev)
3b588e43ee5c7a Tomer Maimon 2018-08-08  1561  {
3b588e43ee5c7a Tomer Maimon 2018-08-08  1562  	struct npcm7xx_pinctrl *npcm = pinctrl_dev_get_drvdata(pctldev);
3b588e43ee5c7a Tomer Maimon 2018-08-08  1563  
3b588e43ee5c7a Tomer Maimon 2018-08-08 @1564  	dev_dbg(npcm->dev, "group size: %d\n", ARRAY_SIZE(npcm7xx_groups));
3b588e43ee5c7a Tomer Maimon 2018-08-08  1565  	return ARRAY_SIZE(npcm7xx_groups);
3b588e43ee5c7a Tomer Maimon 2018-08-08  1566  }
3b588e43ee5c7a Tomer Maimon 2018-08-08  1567  

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org

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

* Re: [PATCH v2 5/8] pinctrl: nuvoton: Add driver for WPCM450
  2021-12-07 21:08   ` Jonathan Neuschäfer
  (?)
@ 2021-12-08  2:34     ` kernel test robot
  -1 siblings, 0 replies; 53+ messages in thread
From: kernel test robot @ 2021-12-08  2:34 UTC (permalink / raw)
  To: Jonathan Neuschäfer, linux-gpio, devicetree
  Cc: llvm, kbuild-all, Linus Walleij, Rob Herring, openbmc,
	Tomer Maimon, Joel Stanley, linux-kernel,
	Jonathan Neuschäfer

Hi "Jonathan,

I love your patch! Perhaps something to improve:

[auto build test WARNING on linusw-pinctrl/devel]
[also build test WARNING on robh/for-next linus/master v5.16-rc4 next-20211207]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Jonathan-Neusch-fer/Nuvoton-WPCM450-pinctrl-and-GPIO-driver/20211208-051101
base:   https://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl.git devel
config: arm64-randconfig-r014-20211207 (https://download.01.org/0day-ci/archive/20211208/202112081056.4i0VFldF-lkp@intel.com/config)
compiler: clang version 14.0.0 (https://github.com/llvm/llvm-project 097a1cb1d5ebb3a0ec4bcaed8ba3ff6a8e33c00a)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # install arm64 cross compiling tool for clang build
        # apt-get install binutils-aarch64-linux-gnu
        # https://github.com/0day-ci/linux/commit/c08fb0aafb60234854aa86433da809fe5112f55e
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Jonathan-Neusch-fer/Nuvoton-WPCM450-pinctrl-and-GPIO-driver/20211208-051101
        git checkout c08fb0aafb60234854aa86433da809fe5112f55e
        # save the config file to linux build tree
        mkdir build_dir
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=arm64 SHELL=/bin/bash drivers/pinctrl/nuvoton/

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

>> drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c:1564:41: warning: format specifies type 'int' but the argument has type 'unsigned long' [-Wformat]
           dev_dbg(npcm->dev, "group size: %d\n", ARRAY_SIZE(npcm7xx_groups));
                                           ~~     ^~~~~~~~~~~~~~~~~~~~~~~~~~
                                           %lu
   include/linux/dev_printk.h:163:47: note: expanded from macro 'dev_dbg'
                   dev_printk(KERN_DEBUG, dev, dev_fmt(fmt), ##__VA_ARGS__); \
                                                       ~~~     ^~~~~~~~~~~
   include/linux/dev_printk.h:129:34: note: expanded from macro 'dev_printk'
                   _dev_printk(level, dev, fmt, ##__VA_ARGS__);            \
                                           ~~~    ^~~~~~~~~~~
   include/linux/kernel.h:46:25: note: expanded from macro 'ARRAY_SIZE'
   #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr))
                           ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1 warning generated.


vim +1564 drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c

3b588e43ee5c7ad Tomer Maimon 2018-08-08  1559  
3b588e43ee5c7ad Tomer Maimon 2018-08-08  1560  static int npcm7xx_get_groups_count(struct pinctrl_dev *pctldev)
3b588e43ee5c7ad Tomer Maimon 2018-08-08  1561  {
3b588e43ee5c7ad Tomer Maimon 2018-08-08  1562  	struct npcm7xx_pinctrl *npcm = pinctrl_dev_get_drvdata(pctldev);
3b588e43ee5c7ad Tomer Maimon 2018-08-08  1563  
3b588e43ee5c7ad Tomer Maimon 2018-08-08 @1564  	dev_dbg(npcm->dev, "group size: %d\n", ARRAY_SIZE(npcm7xx_groups));
3b588e43ee5c7ad Tomer Maimon 2018-08-08  1565  	return ARRAY_SIZE(npcm7xx_groups);
3b588e43ee5c7ad Tomer Maimon 2018-08-08  1566  }
3b588e43ee5c7ad Tomer Maimon 2018-08-08  1567  

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

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

* Re: [PATCH v2 5/8] pinctrl: nuvoton: Add driver for WPCM450
@ 2021-12-08  2:34     ` kernel test robot
  0 siblings, 0 replies; 53+ messages in thread
From: kernel test robot @ 2021-12-08  2:34 UTC (permalink / raw)
  To: Jonathan Neuschäfer, linux-gpio, devicetree
  Cc: kbuild-all, Tomer Maimon, Linus Walleij, llvm, linux-kernel,
	Jonathan Neuschäfer, Rob Herring, openbmc

Hi "Jonathan,

I love your patch! Perhaps something to improve:

[auto build test WARNING on linusw-pinctrl/devel]
[also build test WARNING on robh/for-next linus/master v5.16-rc4 next-20211207]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Jonathan-Neusch-fer/Nuvoton-WPCM450-pinctrl-and-GPIO-driver/20211208-051101
base:   https://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl.git devel
config: arm64-randconfig-r014-20211207 (https://download.01.org/0day-ci/archive/20211208/202112081056.4i0VFldF-lkp@intel.com/config)
compiler: clang version 14.0.0 (https://github.com/llvm/llvm-project 097a1cb1d5ebb3a0ec4bcaed8ba3ff6a8e33c00a)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # install arm64 cross compiling tool for clang build
        # apt-get install binutils-aarch64-linux-gnu
        # https://github.com/0day-ci/linux/commit/c08fb0aafb60234854aa86433da809fe5112f55e
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Jonathan-Neusch-fer/Nuvoton-WPCM450-pinctrl-and-GPIO-driver/20211208-051101
        git checkout c08fb0aafb60234854aa86433da809fe5112f55e
        # save the config file to linux build tree
        mkdir build_dir
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=arm64 SHELL=/bin/bash drivers/pinctrl/nuvoton/

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

>> drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c:1564:41: warning: format specifies type 'int' but the argument has type 'unsigned long' [-Wformat]
           dev_dbg(npcm->dev, "group size: %d\n", ARRAY_SIZE(npcm7xx_groups));
                                           ~~     ^~~~~~~~~~~~~~~~~~~~~~~~~~
                                           %lu
   include/linux/dev_printk.h:163:47: note: expanded from macro 'dev_dbg'
                   dev_printk(KERN_DEBUG, dev, dev_fmt(fmt), ##__VA_ARGS__); \
                                                       ~~~     ^~~~~~~~~~~
   include/linux/dev_printk.h:129:34: note: expanded from macro 'dev_printk'
                   _dev_printk(level, dev, fmt, ##__VA_ARGS__);            \
                                           ~~~    ^~~~~~~~~~~
   include/linux/kernel.h:46:25: note: expanded from macro 'ARRAY_SIZE'
   #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr))
                           ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1 warning generated.


vim +1564 drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c

3b588e43ee5c7ad Tomer Maimon 2018-08-08  1559  
3b588e43ee5c7ad Tomer Maimon 2018-08-08  1560  static int npcm7xx_get_groups_count(struct pinctrl_dev *pctldev)
3b588e43ee5c7ad Tomer Maimon 2018-08-08  1561  {
3b588e43ee5c7ad Tomer Maimon 2018-08-08  1562  	struct npcm7xx_pinctrl *npcm = pinctrl_dev_get_drvdata(pctldev);
3b588e43ee5c7ad Tomer Maimon 2018-08-08  1563  
3b588e43ee5c7ad Tomer Maimon 2018-08-08 @1564  	dev_dbg(npcm->dev, "group size: %d\n", ARRAY_SIZE(npcm7xx_groups));
3b588e43ee5c7ad Tomer Maimon 2018-08-08  1565  	return ARRAY_SIZE(npcm7xx_groups);
3b588e43ee5c7ad Tomer Maimon 2018-08-08  1566  }
3b588e43ee5c7ad Tomer Maimon 2018-08-08  1567  

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

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

* Re: [PATCH v2 5/8] pinctrl: nuvoton: Add driver for WPCM450
@ 2021-12-08  2:34     ` kernel test robot
  0 siblings, 0 replies; 53+ messages in thread
From: kernel test robot @ 2021-12-08  2:34 UTC (permalink / raw)
  To: kbuild-all

[-- Attachment #1: Type: text/plain, Size: 3779 bytes --]

Hi "Jonathan,

I love your patch! Perhaps something to improve:

[auto build test WARNING on linusw-pinctrl/devel]
[also build test WARNING on robh/for-next linus/master v5.16-rc4 next-20211207]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Jonathan-Neusch-fer/Nuvoton-WPCM450-pinctrl-and-GPIO-driver/20211208-051101
base:   https://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl.git devel
config: arm64-randconfig-r014-20211207 (https://download.01.org/0day-ci/archive/20211208/202112081056.4i0VFldF-lkp(a)intel.com/config)
compiler: clang version 14.0.0 (https://github.com/llvm/llvm-project 097a1cb1d5ebb3a0ec4bcaed8ba3ff6a8e33c00a)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # install arm64 cross compiling tool for clang build
        # apt-get install binutils-aarch64-linux-gnu
        # https://github.com/0day-ci/linux/commit/c08fb0aafb60234854aa86433da809fe5112f55e
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Jonathan-Neusch-fer/Nuvoton-WPCM450-pinctrl-and-GPIO-driver/20211208-051101
        git checkout c08fb0aafb60234854aa86433da809fe5112f55e
        # save the config file to linux build tree
        mkdir build_dir
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=arm64 SHELL=/bin/bash drivers/pinctrl/nuvoton/

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

>> drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c:1564:41: warning: format specifies type 'int' but the argument has type 'unsigned long' [-Wformat]
           dev_dbg(npcm->dev, "group size: %d\n", ARRAY_SIZE(npcm7xx_groups));
                                           ~~     ^~~~~~~~~~~~~~~~~~~~~~~~~~
                                           %lu
   include/linux/dev_printk.h:163:47: note: expanded from macro 'dev_dbg'
                   dev_printk(KERN_DEBUG, dev, dev_fmt(fmt), ##__VA_ARGS__); \
                                                       ~~~     ^~~~~~~~~~~
   include/linux/dev_printk.h:129:34: note: expanded from macro 'dev_printk'
                   _dev_printk(level, dev, fmt, ##__VA_ARGS__);            \
                                           ~~~    ^~~~~~~~~~~
   include/linux/kernel.h:46:25: note: expanded from macro 'ARRAY_SIZE'
   #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr))
                           ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   1 warning generated.


vim +1564 drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c

3b588e43ee5c7ad Tomer Maimon 2018-08-08  1559  
3b588e43ee5c7ad Tomer Maimon 2018-08-08  1560  static int npcm7xx_get_groups_count(struct pinctrl_dev *pctldev)
3b588e43ee5c7ad Tomer Maimon 2018-08-08  1561  {
3b588e43ee5c7ad Tomer Maimon 2018-08-08  1562  	struct npcm7xx_pinctrl *npcm = pinctrl_dev_get_drvdata(pctldev);
3b588e43ee5c7ad Tomer Maimon 2018-08-08  1563  
3b588e43ee5c7ad Tomer Maimon 2018-08-08 @1564  	dev_dbg(npcm->dev, "group size: %d\n", ARRAY_SIZE(npcm7xx_groups));
3b588e43ee5c7ad Tomer Maimon 2018-08-08  1565  	return ARRAY_SIZE(npcm7xx_groups);
3b588e43ee5c7ad Tomer Maimon 2018-08-08  1566  }
3b588e43ee5c7ad Tomer Maimon 2018-08-08  1567  

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org

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

* Re: [PATCH v2 5/8] pinctrl: nuvoton: Add driver for WPCM450
  2021-12-07 21:08   ` Jonathan Neuschäfer
                     ` (2 preceding siblings ...)
  (?)
@ 2021-12-08 11:24   ` Andy Shevchenko
  2021-12-08 13:58       ` Jonathan Neuschäfer
  -1 siblings, 1 reply; 53+ messages in thread
From: Andy Shevchenko @ 2021-12-08 11:24 UTC (permalink / raw)
  To: Jonathan Neuschäfer
  Cc: devicetree, Tomer Maimon, Linus Walleij, linux-kernel,
	linux-gpio, Rob Herring, openbmc

[-- Attachment #1: Type: text/plain, Size: 53988 bytes --]

On Tuesday, December 7, 2021, Jonathan Neuschäfer <j.neuschaefer@gmx.net>
wrote:

> This driver is based on the one for NPCM7xx, because the WPCM450 is a
> predecessor of those SoCs. Notable differences:
>
> - WPCM450, the GPIO registers are not organized in multiple banks, but
>   rather placed continually into the same register block. This affects
>   how register offsets are computed.
> - Pinmux nodes can explicitly select GPIO mode, whereas, in the npcm7xx
>   driver, this happens automatically when a GPIO is requested.
>
> Some functionality implemented in the hardware was (for now) left unused
> in the driver, specifically blinking and pull-up/down.
>
> Signed-off-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>
> ---
>
> This patch has a few checkpatch warnings, which are inherited from the
> pinctrl-npcm7xx driver. I decided to ignore those. Specifically:
> (1) WPCM450_GRPS is an unwrapped list; (2) use of -ENOTSUPP is discouraged.
>
>
> v2:
> - Adjust to binding change which put each GPIO bank into its own node
> - Use generic GPIO support
> - Make it possible to set pinmux to GPIO explicitly
> - Allow building the driver as a module
> - Fix spelling of "spin lock" in text
> - Include <linux/mod_devicetable.h>
> - Move linux/pinctrl/* headers to the end of the #include block
> - Remove/rework comments and printk messages
> - Switch to fwnode API
> - Remove comma after sentinel {}
> - Use dev_err_probe
> - Improve Kconfig help message
> - Declare for_each_set_bit iterator as unsigned int
> - Use __assign_bit
> - Set parent irq handler in set_irq_type callback
> - Use struct group_desc
> - Don't hide sysfs bind attributes
> - Remove unnecessary check for gpio-controller property
> - Use module_platform_driver()
>
> v1:
> - https://lore.kernel.org/lkml/20210602120329.2444672-6-j.
> neuschaefer@gmx.net/
> ---
>  MAINTAINERS                               |    1 +
>  drivers/pinctrl/Makefile                  |    2 +-
>  drivers/pinctrl/nuvoton/Kconfig           |   18 +
>  drivers/pinctrl/nuvoton/Makefile          |    1 +
>  drivers/pinctrl/nuvoton/pinctrl-wpcm450.c | 1134 +++++++++++++++++++++
>  5 files changed, 1155 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/pinctrl/nuvoton/pinctrl-wpcm450.c
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index eff3edafd8814..56c5c394877e1 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -2352,6 +2352,7 @@ S:        Maintained
>  F:     Documentation/devicetree/bindings/*/*wpcm*
>  F:     arch/arm/boot/dts/nuvoton-wpcm450*
>  F:     arch/arm/mach-npcm/wpcm450.c
> +F:     drivers/*/*/*wpcm*
>  F:     drivers/*/*wpcm*
>
>  ARM/NXP S32G ARCHITECTURE
> diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
> index 5e63de2ffcf41..823ff12847ed3 100644
> --- a/drivers/pinctrl/Makefile
> +++ b/drivers/pinctrl/Makefile
> @@ -58,7 +58,7 @@ obj-y                         += freescale/
>  obj-$(CONFIG_X86)              += intel/
>  obj-y                          += mvebu/
>  obj-y                          += nomadik/
> -obj-$(CONFIG_ARCH_NPCM7XX)     += nuvoton/
> +obj-y                          += nuvoton/
>  obj-$(CONFIG_PINCTRL_PXA)      += pxa/
>  obj-$(CONFIG_ARCH_QCOM)                += qcom/
>  obj-$(CONFIG_PINCTRL_RALINK)   += ralink/
> diff --git a/drivers/pinctrl/nuvoton/Kconfig b/drivers/pinctrl/nuvoton/
> Kconfig
> index 48ba0469edda6..6a3c6f2a73f2d 100644
> --- a/drivers/pinctrl/nuvoton/Kconfig
> +++ b/drivers/pinctrl/nuvoton/Kconfig
> @@ -1,4 +1,22 @@
>  # SPDX-License-Identifier: GPL-2.0-only
> +
> +config PINCTRL_WPCM450
> +       tristate "Pinctrl and GPIO driver for Nuvoton WPCM450"
> +       depends on ARCH_WPCM450 || COMPILE_TEST
> +       select PINMUX
> +       select PINCONF
> +       select GENERIC_PINCONF
> +       select GPIOLIB
> +       select GPIO_GENERIC
> +       select GPIOLIB_IRQCHIP
> +       help
> +         Say Y or M here to enable pin controller and GPIO support for
> +         the Nuvoton WPCM450 SoC. This is strongly recommended when
> +         building a kernel that will run on this chip.
> +
> +         If this driver is compiled as a module, it will be named
> +         pinctrl-wpcm450.
> +
>  config PINCTRL_NPCM7XX
>         bool "Pinctrl and GPIO driver for Nuvoton NPCM7XX"
>         depends on (ARCH_NPCM7XX || COMPILE_TEST) && OF
> diff --git a/drivers/pinctrl/nuvoton/Makefile b/drivers/pinctrl/nuvoton/
> Makefile
> index 886d00784cef5..9e66f5dc74bfc 100644
> --- a/drivers/pinctrl/nuvoton/Makefile
> +++ b/drivers/pinctrl/nuvoton/Makefile
> @@ -1,4 +1,5 @@
>  # SPDX-License-Identifier: GPL-2.0
>  # Nuvoton pinctrl support
>
> +obj-$(CONFIG_PINCTRL_WPCM450)  += pinctrl-wpcm450.o
>  obj-$(CONFIG_PINCTRL_NPCM7XX)  += pinctrl-npcm7xx.o
> diff --git a/drivers/pinctrl/nuvoton/pinctrl-wpcm450.c
> b/drivers/pinctrl/nuvoton/pinctrl-wpcm450.c
> new file mode 100644
> index 0000000000000..b1e190e45af93
> --- /dev/null
> +++ b/drivers/pinctrl/nuvoton/pinctrl-wpcm450.c
> @@ -0,0 +1,1134 @@
> +// SPDX-License-Identifier: GPL-2.0
> +// Copyright (c) 2016-2018 Nuvoton Technology corporation.
> +// Copyright (c) 2016, Dell Inc
> +// Copyright (c) 2021 Jonathan Neuschäfer
> +//
> +// This driver uses the following registers:
> +// - Pin mux registers, in the GCR (general control registers) block
> +// - GPIO registers, specific to each GPIO bank
> +// - GPIO event (interrupt) registers, located centrally in the GPIO
> register
> +//   block, shared between all GPIO banks
> +
> +#include <linux/device.h>
> +#include <linux/fwnode.h>
> +#include <linux/gpio/driver.h>
> +#include <linux/interrupt.h>
> +#include <linux/irq.h>
> +#include <linux/mfd/syscon.h>
> +#include <linux/module.h>
> +#include <linux/mod_devicetable.h>
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>


+ blank line?


> +#include <linux/pinctrl/pinconf.h>
> +#include <linux/pinctrl/pinconf-generic.h>
> +#include <linux/pinctrl/pinctrl.h>
> +#include <linux/pinctrl/pinmux.h>
> +
> +#include "../core.h"
> +
> +/* GCR registers */
> +#define WPCM450_GCR_MFSEL1     0x0C
> +#define WPCM450_GCR_MFSEL2     0x10
> +#define WPCM450_GCR_NONE       0
> +
> +/* GPIO event (interrupt) registers */
> +#define WPCM450_GPEVTYPE       0x00
> +#define WPCM450_GPEVPOL                0x04
> +#define WPCM450_GPEVDBNC       0x08
> +#define WPCM450_GPEVEN         0x0c
> +#define WPCM450_GPEVST         0x10
> +
> +#define WPCM450_NUM_BANKS      8
> +#define WPCM450_NUM_GPIOS      128
> +#define WPCM450_NUM_GPIO_IRQS  4
> +
> +struct wpcm450_pinctrl;
> +
> +struct wpcm450_gpio {
> +       struct wpcm450_pinctrl  *pctrl;
> +       struct gpio_chip        gc;


Making this first speeds up pointer arithmetics by making it no-op at
compile time.


> +       struct irq_chip         irqc;
> +       unsigned int            first_irq_bit;
> +       unsigned int            num_irqs;
> +       unsigned int            first_irq_gpio;
> +};
> +
> +struct wpcm450_pinctrl {
> +       struct pinctrl_dev      *pctldev;
> +       struct device           *dev;
> +       struct irq_domain       *domain;
> +       struct regmap           *gcr_regmap;
> +       void __iomem            *gpio_base;
> +       struct wpcm450_gpio     gpio_bank[WPCM450_NUM_BANKS];
> +       unsigned long           both_edges;
> +
> +       /*
> +        * This spin lock protects registers and struct wpcm450_pinctrl
> fields
> +        * against concurrent access.
> +        */
> +       spinlock_t              lock;
> +};
> +
> +struct wpcm450_bank {
> +       /* Range of GPIOs in this port */
> +       u8 base;
> +       u8 length;
> +
> +       /* Register offsets (0 = register doesn't exist in this port) */
> +       u8 cfg0, cfg1, cfg2;
> +       u8 blink;
> +       u8 dataout, datain;
> +};
> +
> +static const struct wpcm450_bank wpcm450_banks[WPCM450_NUM_BANKS] = {
> +       /*  range   cfg0  cfg1  cfg2 blink  out   in  */
> +       {   0, 16,  0x14, 0x18,    0,    0, 0x1c, 0x20 },
> +       {  16, 16,  0x24, 0x28, 0x2c, 0x30, 0x34, 0x38 },
> +       {  32, 16,  0x3c, 0x40, 0x44,    0, 0x48, 0x4c },
> +       {  48, 16,  0x50, 0x54, 0x58,    0, 0x5c, 0x60 },
> +       {  64, 16,  0x64, 0x68, 0x6c,    0, 0x70, 0x74 },
> +       {  80, 16,  0x78, 0x7c, 0x80,    0, 0x84, 0x88 },
> +       {  96, 18,     0,    0,    0,    0,    0, 0x8c },
> +       { 114, 14,  0x90, 0x94, 0x98,    0, 0x9c, 0xa0 },
> +};
> +
> +static int wpcm450_gpio_irq_bitnum(struct wpcm450_gpio *gpio, struct
> irq_data *d)
> +{
> +       int hwirq = irqd_to_hwirq(d);
> +
> +       if (hwirq < gpio->first_irq_gpio)
> +               return -EINVAL;
> +
> +       if (hwirq - gpio->first_irq_gpio >= gpio->num_irqs)
> +               return -EINVAL;
> +
> +       return hwirq - gpio->first_irq_gpio + gpio->first_irq_bit;
> +}
> +
> +static int wpcm450_irq_bitnum_to_gpio(struct wpcm450_gpio *gpio, int
> bitnum)
> +{
> +       if (bitnum < gpio->first_irq_bit)
> +               return -EINVAL;
> +
> +       if (bitnum - gpio->first_irq_bit > gpio->num_irqs)
> +               return -EINVAL;
> +
> +       return bitnum - gpio->first_irq_bit + gpio->first_irq_gpio;
> +}
>


Have you chance to look at bitmap_remap() and bitmap_bitremap() APIs? I’m
pretty sure you can make this all cleaner by switching to those calls and
represent the GPIOs as continuous bitmap on the Linux side while on the
hardware it will be sparse. Check gpio-Xilinx for the details of use.


> +static void wpcm450_gpio_irq_ack(struct irq_data *d)
> +{
> +       struct wpcm450_gpio *gpio = gpiochip_get_data(irq_data_
> get_irq_chip_data(d));
> +       struct wpcm450_pinctrl *pctrl = gpio->pctrl;
> +       unsigned long flags;
> +       int bit;
> +
> +       bit = wpcm450_gpio_irq_bitnum(gpio, d);
> +       if (bit < 0)
> +               return;
> +
> +       spin_lock_irqsave(&pctrl->lock, flags);
> +       iowrite32(BIT(bit), pctrl->gpio_base + WPCM450_GPEVST);
> +       spin_unlock_irqrestore(&pctrl->lock, flags);
> +}
> +
> +static void wpcm450_gpio_irq_mask(struct irq_data *d)
> +{
> +       struct wpcm450_gpio *gpio = gpiochip_get_data(irq_data_
> get_irq_chip_data(d));
> +       struct wpcm450_pinctrl *pctrl = gpio->pctrl;
> +       unsigned long flags;
> +       unsigned long even;
> +       int bit;
> +
> +       bit = wpcm450_gpio_irq_bitnum(gpio, d);
> +       if (bit < 0)
> +               return;
> +
> +       spin_lock_irqsave(&pctrl->lock, flags);
> +       even = ioread32(pctrl->gpio_base + WPCM450_GPEVEN);
> +       __assign_bit(bit, &even, 0);
> +       iowrite32(even, pctrl->gpio_base + WPCM450_GPEVEN);
> +       spin_unlock_irqrestore(&pctrl->lock, flags);
> +}
> +
> +static void wpcm450_gpio_irq_unmask(struct irq_data *d)
> +{
> +       struct wpcm450_gpio *gpio = gpiochip_get_data(irq_data_
> get_irq_chip_data(d));
> +       struct wpcm450_pinctrl *pctrl = gpio->pctrl;
> +       unsigned long flags;
> +       unsigned long even;
> +       int bit;
> +
> +       bit = wpcm450_gpio_irq_bitnum(gpio, d);
> +       if (bit < 0)
> +               return;
> +
> +       spin_lock_irqsave(&pctrl->lock, flags);
> +       even = ioread32(pctrl->gpio_base + WPCM450_GPEVEN);
> +       __assign_bit(bit, &even, 1);
> +       iowrite32(even, pctrl->gpio_base + WPCM450_GPEVEN);
> +       spin_unlock_irqrestore(&pctrl->lock, flags);
> +}
> +
> +static void wpcm450_gpio_fix_evpol(struct wpcm450_gpio *gpio, unsigned
> long all)
> +{



What is this quirk (?) for? Please add a comment.


> +       struct wpcm450_pinctrl *pctrl = gpio->pctrl;
> +       unsigned long flags;
> +       unsigned int bit;
> +
> +       for_each_set_bit(bit, &all, 32) {
> +               int offset = wpcm450_irq_bitnum_to_gpio(gpio, bit);
> +               unsigned long evpol;
> +               int level;
> +
> +               spin_lock_irqsave(&gpio->gc.bgpio_lock, flags);
> +               do {
> +                       evpol = ioread32(pctrl->gpio_base +
> WPCM450_GPEVPOL);
> +                       level = gpio->gc.get(&gpio->gc, offset);
> +
> +                       /* Switch event polarity to the opposite of the
> current level */
> +                       __assign_bit(bit, &evpol, !level);
> +
> +                       iowrite32(evpol, pctrl->gpio_base +
> WPCM450_GPEVPOL);
> +               } while (gpio->gc.get(&gpio->gc, offset) != level);
> +               spin_unlock_irqrestore(&gpio->gc.bgpio_lock, flags);
> +       }
> +}
> +
> +static int wpcm450_gpio_set_irq_type(struct irq_data *d, unsigned int
> flow_type)
> +{
> +       struct wpcm450_gpio *gpio = gpiochip_get_data(irq_data_
> get_irq_chip_data(d));
> +       struct wpcm450_pinctrl *pctrl = gpio->pctrl;
> +       unsigned long evtype, evpol;
> +       unsigned long flags;
> +       int ret = 0;
> +       int bit;
> +
> +       bit = wpcm450_gpio_irq_bitnum(gpio, d);
> +       if (bit < 0)
> +               return bit;
> +
> +       irq_set_handler_locked(d, handle_level_irq);
> +
> +       spin_lock_irqsave(&pctrl->lock, flags);
> +       evtype = ioread32(pctrl->gpio_base + WPCM450_GPEVTYPE);
> +       evpol = ioread32(pctrl->gpio_base + WPCM450_GPEVPOL);
> +       __assign_bit(bit, &pctrl->both_edges, 0);
> +       switch (flow_type) {
> +       case IRQ_TYPE_LEVEL_LOW:
> +               __assign_bit(bit, &evtype, 1);
> +               __assign_bit(bit, &evpol, 0);
> +               break;
> +       case IRQ_TYPE_LEVEL_HIGH:
> +               __assign_bit(bit, &evtype, 1);
> +               __assign_bit(bit, &evpol, 1);
> +               break;
> +       case IRQ_TYPE_EDGE_FALLING:
> +               __assign_bit(bit, &evtype, 0);
> +               __assign_bit(bit, &evpol, 0);
> +               break;
> +       case IRQ_TYPE_EDGE_RISING:
> +               __assign_bit(bit, &evtype, 0);
> +               __assign_bit(bit, &evpol, 1);
> +               break;
> +       case IRQ_TYPE_EDGE_BOTH:
> +               __assign_bit(bit, &evtype, 0);
> +               __assign_bit(bit, &pctrl->both_edges, 1);
> +               break;
> +       default:
> +               ret = -EINVAL;
> +       }
> +       iowrite32(evtype, pctrl->gpio_base + WPCM450_GPEVTYPE);
> +       iowrite32(evpol, pctrl->gpio_base + WPCM450_GPEVPOL);
> +
> +       /* clear the event status for good measure */
> +       iowrite32(BIT(bit), pctrl->gpio_base + WPCM450_GPEVST);
> +
> +       /* fix event polarity after clearing event status */
> +       wpcm450_gpio_fix_evpol(gpio, BIT(bit));
> +
> +       spin_unlock_irqrestore(&pctrl->lock, flags);
> +
> +       return ret;
> +}
> +
> +static const struct irq_chip wpcm450_gpio_irqchip = {
> +       .name = "WPCM450-GPIO-IRQ",
> +       .irq_ack = wpcm450_gpio_irq_ack,
> +       .irq_unmask = wpcm450_gpio_irq_unmask,
> +       .irq_mask = wpcm450_gpio_irq_mask,
> +       .irq_set_type = wpcm450_gpio_set_irq_type,
> +};
> +
> +static void wpcm450_gpio_irqhandler(struct irq_desc *desc)
> +{
> +       struct wpcm450_gpio *gpio = gpiochip_get_data(irq_desc_
> get_handler_data(desc));
> +       struct wpcm450_pinctrl *pctrl = gpio->pctrl;
> +       struct irq_chip *chip = irq_desc_get_chip(desc);
> +       unsigned long pending;
> +       unsigned long flags;
> +       unsigned long ours;
> +       unsigned int bit;
> +
> +       ours = ((1UL << gpio->num_irqs) - 1) << gpio->first_irq_bit;


BIT()


> +
> +       spin_lock_irqsave(&pctrl->lock, flags);
> +
> +       pending = ioread32(pctrl->gpio_base + WPCM450_GPEVST);
> +       pending &= ioread32(pctrl->gpio_base + WPCM450_GPEVEN);
> +       pending &= ours;
> +
> +       if (pending & pctrl->both_edges)
> +               wpcm450_gpio_fix_evpol(gpio, pending & pctrl->both_edges);
> +
> +       spin_unlock_irqrestore(&pctrl->lock, flags);
> +
> +       chained_irq_enter(chip, desc);
> +       for_each_set_bit(bit, &pending, 32) {
> +               int offset = wpcm450_irq_bitnum_to_gpio(gpio, bit);
> +               int irq = irq_find_mapping(gpio->gc.irq.domain, offset);
> +
> +               generic_handle_irq(irq);


Above two are now represented by another generic IRQ handle call, check
relatively recently updated drivers around.


> +       }
> +       chained_irq_exit(chip, desc);
> +}
> +
> +static int smb0_pins[]  = { 115, 114 };
> +static int smb1_pins[]  = { 117, 116 };
> +static int smb2_pins[]  = { 119, 118 };
> +static int smb3_pins[]  = { 30, 31 };
> +static int smb4_pins[]  = { 28, 29 };
> +static int smb5_pins[]  = { 26, 27 };
> +
> +static int scs1_pins[] = { 32 };
> +static int scs2_pins[] = { 33 };
> +static int scs3_pins[] = { 34 };
> +
> +static int bsp_pins[] = { 41, 42 };
> +static int hsp1_pins[] = { 43, 44, 45, 46, 47, 61, 62, 63 };
> +static int hsp2_pins[] = { 48, 49, 50, 51, 52, 53, 54, 55 };
> +
> +static int r1err_pins[] = { 56 };
> +static int r1md_pins[] = { 57, 58 };
> +static int rmii2_pins[] = { 84, 85, 86, 87, 88, 89 };
> +static int r2err_pins[] = { 90 };
> +static int r2md_pins[] = { 91, 92 };
> +
> +static int kbcc_pins[] = { 94, 93 };
> +static int clko_pins[] = { 96 };
> +static int smi_pins[] = { 97 };
> +static int uinc_pins[] = { 19 };
> +static int mben_pins[] = {};
> +
> +static int gspi_pins[] = { 12, 13, 14, 15 };
> +static int sspi_pins[] = { 12, 13, 14, 15 };
> +
> +static int xcs1_pins[] = { 35 };
> +static int xcs2_pins[] = { 36 };
> +
> +static int sdio_pins[] = { 7, 22, 43, 44, 45, 46, 47, 60 };
> +
> +static int fi0_pins[] = { 64 };
> +static int fi1_pins[] = { 65 };
> +static int fi2_pins[] = { 66 };
> +static int fi3_pins[] = { 67 };
> +static int fi4_pins[] = { 68 };
> +static int fi5_pins[] = { 69 };
> +static int fi6_pins[] = { 70 };
> +static int fi7_pins[] = { 71 };
> +static int fi8_pins[] = { 72 };
> +static int fi9_pins[] = { 73 };
> +static int fi10_pins[] = { 74 };
> +static int fi11_pins[] = { 75 };
> +static int fi12_pins[] = { 76 };
> +static int fi13_pins[] = { 77 };
> +static int fi14_pins[] = { 78 };
> +static int fi15_pins[] = { 79 };
> +
> +static int pwm0_pins[] = { 80 };
> +static int pwm1_pins[] = { 81 };
> +static int pwm2_pins[] = { 82 };
> +static int pwm3_pins[] = { 83 };
> +static int pwm4_pins[] = { 20 };
> +static int pwm5_pins[] = { 21 };
> +static int pwm6_pins[] = { 16 };
> +static int pwm7_pins[] = { 17 };
> +
> +static int hg0_pins[] = { 20 };
> +static int hg1_pins[] = { 21 };
> +static int hg2_pins[] = { 22 };
> +static int hg3_pins[] = { 23 };
> +static int hg4_pins[] = { 24 };
> +static int hg5_pins[] = { 25 };
> +static int hg6_pins[] = { 59 };
> +static int hg7_pins[] = { 60 };
> +
> +#define WPCM450_GRPS \
> +       WPCM450_GRP(smb3), \
> +       WPCM450_GRP(smb4), \
> +       WPCM450_GRP(smb5), \
> +       WPCM450_GRP(scs1), \
> +       WPCM450_GRP(scs2), \
> +       WPCM450_GRP(scs3), \
> +       WPCM450_GRP(smb0), \
> +       WPCM450_GRP(smb1), \
> +       WPCM450_GRP(smb2), \
> +       WPCM450_GRP(bsp), \
> +       WPCM450_GRP(hsp1), \
> +       WPCM450_GRP(hsp2), \
> +       WPCM450_GRP(r1err), \
> +       WPCM450_GRP(r1md), \
> +       WPCM450_GRP(rmii2), \
> +       WPCM450_GRP(r2err), \
> +       WPCM450_GRP(r2md), \
> +       WPCM450_GRP(kbcc), \
> +       WPCM450_GRP(clko), \
> +       WPCM450_GRP(smi), \
> +       WPCM450_GRP(uinc), \
> +       WPCM450_GRP(gspi), \
> +       WPCM450_GRP(mben), \
> +       WPCM450_GRP(xcs2), \
> +       WPCM450_GRP(xcs1), \
> +       WPCM450_GRP(sdio), \
> +       WPCM450_GRP(sspi), \
> +       WPCM450_GRP(fi0), \
> +       WPCM450_GRP(fi1), \
> +       WPCM450_GRP(fi2), \
> +       WPCM450_GRP(fi3), \
> +       WPCM450_GRP(fi4), \
> +       WPCM450_GRP(fi5), \
> +       WPCM450_GRP(fi6), \
> +       WPCM450_GRP(fi7), \
> +       WPCM450_GRP(fi8), \
> +       WPCM450_GRP(fi9), \
> +       WPCM450_GRP(fi10), \
> +       WPCM450_GRP(fi11), \
> +       WPCM450_GRP(fi12), \
> +       WPCM450_GRP(fi13), \
> +       WPCM450_GRP(fi14), \
> +       WPCM450_GRP(fi15), \
> +       WPCM450_GRP(pwm0), \
> +       WPCM450_GRP(pwm1), \
> +       WPCM450_GRP(pwm2), \
> +       WPCM450_GRP(pwm3), \
> +       WPCM450_GRP(pwm4), \
> +       WPCM450_GRP(pwm5), \
> +       WPCM450_GRP(pwm6), \
> +       WPCM450_GRP(pwm7), \
> +       WPCM450_GRP(hg0), \
> +       WPCM450_GRP(hg1), \
> +       WPCM450_GRP(hg2), \
> +       WPCM450_GRP(hg3), \
> +       WPCM450_GRP(hg4), \
> +       WPCM450_GRP(hg5), \
> +       WPCM450_GRP(hg6), \
> +       WPCM450_GRP(hg7), \
> +
> +enum {
> +#define WPCM450_GRP(x) fn_ ## x
> +       WPCM450_GRPS
> +       /* add placeholder for none/gpio */
> +       WPCM450_GRP(gpio),
> +       WPCM450_GRP(none),
> +#undef WPCM450_GRP
> +};
> +
> +static struct group_desc wpcm450_groups[] = {
> +#define WPCM450_GRP(x) { .name = #x, .pins = x ## _pins, \
> +                       .num_pins = ARRAY_SIZE(x ## _pins) }
> +       WPCM450_GRPS
> +#undef WPCM450_GRP
> +};
> +
> +#define WPCM450_SFUNC(a) WPCM450_FUNC(a, #a)
> +#define WPCM450_FUNC(a, b...) static const char *a ## _grp[] = { b }
> +#define WPCM450_MKFUNC(nm) { .name = #nm, .ngroups = ARRAY_SIZE(nm ##
> _grp), \
> +                       .groups = nm ## _grp }
> +struct wpcm450_func {
> +       const char *name;
> +       const unsigned int ngroups;
> +       const char *const *groups;
> +};
> +
> +WPCM450_SFUNC(smb3);
> +WPCM450_SFUNC(smb4);
> +WPCM450_SFUNC(smb5);
> +WPCM450_SFUNC(scs1);
> +WPCM450_SFUNC(scs2);
> +WPCM450_SFUNC(scs3);
> +WPCM450_SFUNC(smb0);
> +WPCM450_SFUNC(smb1);
> +WPCM450_SFUNC(smb2);
> +WPCM450_SFUNC(bsp);
> +WPCM450_SFUNC(hsp1);
> +WPCM450_SFUNC(hsp2);
> +WPCM450_SFUNC(r1err);
> +WPCM450_SFUNC(r1md);
> +WPCM450_SFUNC(rmii2);
> +WPCM450_SFUNC(r2err);
> +WPCM450_SFUNC(r2md);
> +WPCM450_SFUNC(kbcc);
> +WPCM450_SFUNC(clko);
> +WPCM450_SFUNC(smi);
> +WPCM450_SFUNC(uinc);
> +WPCM450_SFUNC(gspi);
> +WPCM450_SFUNC(mben);
> +WPCM450_SFUNC(xcs2);
> +WPCM450_SFUNC(xcs1);
> +WPCM450_SFUNC(sdio);
> +WPCM450_SFUNC(sspi);
> +WPCM450_SFUNC(fi0);
> +WPCM450_SFUNC(fi1);
> +WPCM450_SFUNC(fi2);
> +WPCM450_SFUNC(fi3);
> +WPCM450_SFUNC(fi4);
> +WPCM450_SFUNC(fi5);
> +WPCM450_SFUNC(fi6);
> +WPCM450_SFUNC(fi7);
> +WPCM450_SFUNC(fi8);
> +WPCM450_SFUNC(fi9);
> +WPCM450_SFUNC(fi10);
> +WPCM450_SFUNC(fi11);
> +WPCM450_SFUNC(fi12);
> +WPCM450_SFUNC(fi13);
> +WPCM450_SFUNC(fi14);
> +WPCM450_SFUNC(fi15);
> +WPCM450_SFUNC(pwm0);
> +WPCM450_SFUNC(pwm1);
> +WPCM450_SFUNC(pwm2);
> +WPCM450_SFUNC(pwm3);
> +WPCM450_SFUNC(pwm4);
> +WPCM450_SFUNC(pwm5);
> +WPCM450_SFUNC(pwm6);
> +WPCM450_SFUNC(pwm7);
> +WPCM450_SFUNC(hg0);
> +WPCM450_SFUNC(hg1);
> +WPCM450_SFUNC(hg2);
> +WPCM450_SFUNC(hg3);
> +WPCM450_SFUNC(hg4);
> +WPCM450_SFUNC(hg5);
> +WPCM450_SFUNC(hg6);
> +WPCM450_SFUNC(hg7);
> +
> +#define WPCM450_GRP(x) #x
> +WPCM450_FUNC(gpio, WPCM450_GRPS);
> +#undef WPCM450_GRP
> +
> +/* Function names */
> +static struct wpcm450_func wpcm450_funcs[] = {
> +       WPCM450_MKFUNC(smb3),
> +       WPCM450_MKFUNC(smb4),
> +       WPCM450_MKFUNC(smb5),
> +       WPCM450_MKFUNC(scs1),
> +       WPCM450_MKFUNC(scs2),
> +       WPCM450_MKFUNC(scs3),
> +       WPCM450_MKFUNC(smb0),
> +       WPCM450_MKFUNC(smb1),
> +       WPCM450_MKFUNC(smb2),
> +       WPCM450_MKFUNC(bsp),
> +       WPCM450_MKFUNC(hsp1),
> +       WPCM450_MKFUNC(hsp2),
> +       WPCM450_MKFUNC(r1err),
> +       WPCM450_MKFUNC(r1md),
> +       WPCM450_MKFUNC(rmii2),
> +       WPCM450_MKFUNC(r2err),
> +       WPCM450_MKFUNC(r2md),
> +       WPCM450_MKFUNC(kbcc),
> +       WPCM450_MKFUNC(clko),
> +       WPCM450_MKFUNC(smi),
> +       WPCM450_MKFUNC(uinc),
> +       WPCM450_MKFUNC(gspi),
> +       WPCM450_MKFUNC(mben),
> +       WPCM450_MKFUNC(xcs2),
> +       WPCM450_MKFUNC(xcs1),
> +       WPCM450_MKFUNC(sdio),
> +       WPCM450_MKFUNC(sspi),
> +       WPCM450_MKFUNC(fi0),
> +       WPCM450_MKFUNC(fi1),
> +       WPCM450_MKFUNC(fi2),
> +       WPCM450_MKFUNC(fi3),
> +       WPCM450_MKFUNC(fi4),
> +       WPCM450_MKFUNC(fi5),
> +       WPCM450_MKFUNC(fi6),
> +       WPCM450_MKFUNC(fi7),
> +       WPCM450_MKFUNC(fi8),
> +       WPCM450_MKFUNC(fi9),
> +       WPCM450_MKFUNC(fi10),
> +       WPCM450_MKFUNC(fi11),
> +       WPCM450_MKFUNC(fi12),
> +       WPCM450_MKFUNC(fi13),
> +       WPCM450_MKFUNC(fi14),
> +       WPCM450_MKFUNC(fi15),
> +       WPCM450_MKFUNC(pwm0),
> +       WPCM450_MKFUNC(pwm1),
> +       WPCM450_MKFUNC(pwm2),
> +       WPCM450_MKFUNC(pwm3),
> +       WPCM450_MKFUNC(pwm4),
> +       WPCM450_MKFUNC(pwm5),
> +       WPCM450_MKFUNC(pwm6),
> +       WPCM450_MKFUNC(pwm7),
> +       WPCM450_MKFUNC(hg0),
> +       WPCM450_MKFUNC(hg1),
> +       WPCM450_MKFUNC(hg2),
> +       WPCM450_MKFUNC(hg3),
> +       WPCM450_MKFUNC(hg4),
> +       WPCM450_MKFUNC(hg5),
> +       WPCM450_MKFUNC(hg6),
> +       WPCM450_MKFUNC(hg7),
> +       WPCM450_MKFUNC(gpio),
> +};
> +
> +#define WPCM450_PINCFG(a, b, c, d, e, f, g) \
> +       [a] { .fn0 = fn_ ## b, .reg0 = WPCM450_GCR_ ## c, .bit0 = d, \
> +             .fn1 = fn_ ## e, .reg1 = WPCM450_GCR_ ## f, .bit1 = g }
> +
> +struct wpcm450_pincfg {
> +       int fn0, reg0, bit0;
> +       int fn1, reg1, bit1;
> +};
> +
> +static const struct wpcm450_pincfg pincfg[] = {
> +       /*              PIN       FUNCTION 1               FUNCTION 2 */
> +       WPCM450_PINCFG(0,        none, NONE, 0,           none, NONE, 0),
> +       WPCM450_PINCFG(1,        none, NONE, 0,           none, NONE, 0),
> +       WPCM450_PINCFG(2,        none, NONE, 0,           none, NONE, 0),
> +       WPCM450_PINCFG(3,        none, NONE, 0,           none, NONE, 0),
> +       WPCM450_PINCFG(4,        none, NONE, 0,           none, NONE, 0),
> +       WPCM450_PINCFG(5,        none, NONE, 0,           none, NONE, 0),
> +       WPCM450_PINCFG(6,        none, NONE, 0,           none, NONE, 0),
> +       WPCM450_PINCFG(7,        none, NONE, 0,           sdio, MFSEL1,
> 30),
> +       WPCM450_PINCFG(8,        none, NONE, 0,           none, NONE, 0),
> +       WPCM450_PINCFG(9,        none, NONE, 0,           none, NONE, 0),
> +       WPCM450_PINCFG(10,       none, NONE, 0,           none, NONE, 0),
> +       WPCM450_PINCFG(11,       none, NONE, 0,           none, NONE, 0),
> +       WPCM450_PINCFG(12,       gspi, MFSEL1, 24,        sspi, MFSEL1,
> 31),
> +       WPCM450_PINCFG(13,       gspi, MFSEL1, 24,        sspi, MFSEL1,
> 31),
> +       WPCM450_PINCFG(14,       gspi, MFSEL1, 24,        sspi, MFSEL1,
> 31),
> +       WPCM450_PINCFG(15,       gspi, MFSEL1, 24,        sspi, MFSEL1,
> 31),
> +       WPCM450_PINCFG(16,       none, NONE, 0,           pwm6, MFSEL2,
> 22),
> +       WPCM450_PINCFG(17,       none, NONE, 0,           pwm7, MFSEL2,
> 23),
> +       WPCM450_PINCFG(18,       none, NONE, 0,           none, NONE, 0),
> +       WPCM450_PINCFG(19,       uinc, MFSEL1, 23,        none, NONE, 0),
> +       WPCM450_PINCFG(20,        hg0, MFSEL2, 24,        pwm4, MFSEL2,
> 20),
> +       WPCM450_PINCFG(21,        hg1, MFSEL2, 25,        pwm5, MFSEL2,
> 21),
> +       WPCM450_PINCFG(22,        hg2, MFSEL2, 26,        none, NONE, 0),
> +       WPCM450_PINCFG(23,        hg3, MFSEL2, 27,        none, NONE, 0),
> +       WPCM450_PINCFG(24,        hg4, MFSEL2, 28,        none, NONE, 0),
> +       WPCM450_PINCFG(25,        hg5, MFSEL2, 29,        none, NONE, 0),
> +       WPCM450_PINCFG(26,       smb5, MFSEL1, 2,         none, NONE, 0),
> +       WPCM450_PINCFG(27,       smb5, MFSEL1, 2,         none, NONE, 0),
> +       WPCM450_PINCFG(28,       smb4, MFSEL1, 1,         none, NONE, 0),
> +       WPCM450_PINCFG(29,       smb4, MFSEL1, 1,         none, NONE, 0),
> +       WPCM450_PINCFG(30,       smb3, MFSEL1, 0,         none, NONE, 0),
> +       WPCM450_PINCFG(31,       smb3, MFSEL1, 0,         none, NONE, 0),
> +
> +       WPCM450_PINCFG(32,       scs1, MFSEL1, 3,         none, NONE, 0),
> +       WPCM450_PINCFG(33,       scs2, MFSEL1, 4,         none, NONE, 0),
> +       WPCM450_PINCFG(34,       scs3, MFSEL1, 5,         none, NONE, 0),
> +       WPCM450_PINCFG(35,       xcs1, MFSEL1, 29,        none, NONE, 0),
> +       WPCM450_PINCFG(36,       xcs2, MFSEL1, 28,        none, NONE, 0),
> +       WPCM450_PINCFG(37,       none, NONE, 0,           none, NONE, 0),
> /* DVO */
> +       WPCM450_PINCFG(38,       none, NONE, 0,           none, NONE, 0),
> /* DVO */
> +       WPCM450_PINCFG(39,       none, NONE, 0,           none, NONE, 0),
> /* DVO */
> +       WPCM450_PINCFG(40,       none, NONE, 0,           none, NONE, 0),
> /* DVO */
> +       WPCM450_PINCFG(41,        bsp, MFSEL1, 9,         none, NONE, 0),
> +       WPCM450_PINCFG(42,        bsp, MFSEL1, 9,         none, NONE, 0),
> +       WPCM450_PINCFG(43,       hsp1, MFSEL1, 10,        sdio, MFSEL1,
> 30),
> +       WPCM450_PINCFG(44,       hsp1, MFSEL1, 10,        sdio, MFSEL1,
> 30),
> +       WPCM450_PINCFG(45,       hsp1, MFSEL1, 10,        sdio, MFSEL1,
> 30),
> +       WPCM450_PINCFG(46,       hsp1, MFSEL1, 10,        sdio, MFSEL1,
> 30),
> +       WPCM450_PINCFG(47,       hsp1, MFSEL1, 10,        sdio, MFSEL1,
> 30),
> +       WPCM450_PINCFG(48,       hsp2, MFSEL1, 11,        none, NONE, 0),
> +       WPCM450_PINCFG(49,       hsp2, MFSEL1, 11,        none, NONE, 0),
> +       WPCM450_PINCFG(50,       hsp2, MFSEL1, 11,        none, NONE, 0),
> +       WPCM450_PINCFG(51,       hsp2, MFSEL1, 11,        none, NONE, 0),
> +       WPCM450_PINCFG(52,       hsp2, MFSEL1, 11,        none, NONE, 0),
> +       WPCM450_PINCFG(53,       hsp2, MFSEL1, 11,        none, NONE, 0),
> +       WPCM450_PINCFG(54,       hsp2, MFSEL1, 11,        none, NONE, 0),
> +       WPCM450_PINCFG(55,       hsp2, MFSEL1, 11,        none, NONE, 0),
> +       WPCM450_PINCFG(56,      r1err, MFSEL1, 12,        none, NONE, 0),
> +       WPCM450_PINCFG(57,       r1md, MFSEL1, 13,        none, NONE, 0),
> +       WPCM450_PINCFG(58,       r1md, MFSEL1, 13,        none, NONE, 0),
> +       WPCM450_PINCFG(59,        hg6, MFSEL2, 30,        none, NONE, 0),
> +       WPCM450_PINCFG(60,        hg7, MFSEL2, 31,        sdio, MFSEL1,
> 30),
> +       WPCM450_PINCFG(61,       hsp1, MFSEL1, 10,        none, NONE, 0),
> +       WPCM450_PINCFG(62,       hsp1, MFSEL1, 10,        none, NONE, 0),
> +       WPCM450_PINCFG(63,       hsp1, MFSEL1, 10,        none, NONE, 0),
> +
> +       WPCM450_PINCFG(64,        fi0, MFSEL2, 0,         none, NONE, 0),
> +       WPCM450_PINCFG(65,        fi1, MFSEL2, 1,         none, NONE, 0),
> +       WPCM450_PINCFG(66,        fi2, MFSEL2, 2,         none, NONE, 0),
> +       WPCM450_PINCFG(67,        fi3, MFSEL2, 3,         none, NONE, 0),
> +       WPCM450_PINCFG(68,        fi4, MFSEL2, 4,         none, NONE, 0),
> +       WPCM450_PINCFG(69,        fi5, MFSEL2, 5,         none, NONE, 0),
> +       WPCM450_PINCFG(70,        fi6, MFSEL2, 6,         none, NONE, 0),
> +       WPCM450_PINCFG(71,        fi7, MFSEL2, 7,         none, NONE, 0),
> +       WPCM450_PINCFG(72,        fi8, MFSEL2, 8,         none, NONE, 0),
> +       WPCM450_PINCFG(73,        fi9, MFSEL2, 9,         none, NONE, 0),
> +       WPCM450_PINCFG(74,       fi10, MFSEL2, 10,        none, NONE, 0),
> +       WPCM450_PINCFG(75,       fi11, MFSEL2, 11,        none, NONE, 0),
> +       WPCM450_PINCFG(76,       fi12, MFSEL2, 12,        none, NONE, 0),
> +       WPCM450_PINCFG(77,       fi13, MFSEL2, 13,        none, NONE, 0),
> +       WPCM450_PINCFG(78,       fi14, MFSEL2, 14,        none, NONE, 0),
> +       WPCM450_PINCFG(79,       fi15, MFSEL2, 15,        none, NONE, 0),
> +       WPCM450_PINCFG(80,       pwm0, MFSEL2, 16,        none, NONE, 0),
> +       WPCM450_PINCFG(81,       pwm1, MFSEL2, 17,        none, NONE, 0),
> +       WPCM450_PINCFG(82,       pwm2, MFSEL2, 18,        none, NONE, 0),
> +       WPCM450_PINCFG(83,       pwm3, MFSEL2, 19,        none, NONE, 0),
> +       WPCM450_PINCFG(84,      rmii2, MFSEL1, 14,        none, NONE, 0),
> +       WPCM450_PINCFG(85,      rmii2, MFSEL1, 14,        none, NONE, 0),
> +       WPCM450_PINCFG(86,      rmii2, MFSEL1, 14,        none, NONE, 0),
> +       WPCM450_PINCFG(87,      rmii2, MFSEL1, 14,        none, NONE, 0),
> +       WPCM450_PINCFG(88,      rmii2, MFSEL1, 14,        none, NONE, 0),
> +       WPCM450_PINCFG(89,      rmii2, MFSEL1, 14,        none, NONE, 0),
> +       WPCM450_PINCFG(90,      r2err, MFSEL1, 15,        none, NONE, 0),
> +       WPCM450_PINCFG(91,       r2md, MFSEL1, 16,        none, NONE, 0),
> +       WPCM450_PINCFG(92,       r2md, MFSEL1, 16,        none, NONE, 0),
> +       WPCM450_PINCFG(93,       kbcc, MFSEL1, 17,        none, NONE, 0),
> +       WPCM450_PINCFG(94,       kbcc, MFSEL1, 17,        none, NONE, 0),
> +       WPCM450_PINCFG(95,       none, NONE, 0,           none, NONE, 0),
> +
> +       WPCM450_PINCFG(96,       none, NONE, 0,           none, NONE, 0),
> +       WPCM450_PINCFG(97,       none, NONE, 0,           none, NONE, 0),
> +       WPCM450_PINCFG(98,       none, NONE, 0,           none, NONE, 0),
> +       WPCM450_PINCFG(99,       none, NONE, 0,           none, NONE, 0),
> +       WPCM450_PINCFG(100,      none, NONE, 0,           none, NONE, 0),
> +       WPCM450_PINCFG(101,      none, NONE, 0,           none, NONE, 0),
> +       WPCM450_PINCFG(102,      none, NONE, 0,           none, NONE, 0),
> +       WPCM450_PINCFG(103,      none, NONE, 0,           none, NONE, 0),
> +       WPCM450_PINCFG(104,      none, NONE, 0,           none, NONE, 0),
> +       WPCM450_PINCFG(105,      none, NONE, 0,           none, NONE, 0),
> +       WPCM450_PINCFG(106,      none, NONE, 0,           none, NONE, 0),
> +       WPCM450_PINCFG(107,      none, NONE, 0,           none, NONE, 0),
> +       WPCM450_PINCFG(108,      none, NONE, 0,           none, NONE, 0),
> /* DVO */
> +       WPCM450_PINCFG(109,      none, NONE, 0,           none, NONE, 0),
> /* DVO */
> +       WPCM450_PINCFG(110,      none, NONE, 0,           none, NONE, 0),
> /* DVO */
> +       WPCM450_PINCFG(111,      none, NONE, 0,           none, NONE, 0),
> /* DVO */
> +       WPCM450_PINCFG(112,      none, NONE, 0,           none, NONE, 0),
> /* DVO */
> +       WPCM450_PINCFG(113,      none, NONE, 0,           none, NONE, 0),
> /* DVO */
> +       WPCM450_PINCFG(114,      smb0, MFSEL1, 6,         none, NONE, 0),
> +       WPCM450_PINCFG(115,      smb0, MFSEL1, 6,         none, NONE, 0),
> +       WPCM450_PINCFG(116,      smb1, MFSEL1, 7,         none, NONE, 0),
> +       WPCM450_PINCFG(117,      smb1, MFSEL1, 7,         none, NONE, 0),
> +       WPCM450_PINCFG(118,      smb2, MFSEL1, 8,         none, NONE, 0),
> +       WPCM450_PINCFG(119,      smb2, MFSEL1, 8,         none, NONE, 0),
> +       WPCM450_PINCFG(120,      none, NONE, 0,           none, NONE, 0),
> /* DVO */
> +       WPCM450_PINCFG(121,      none, NONE, 0,           none, NONE, 0),
> /* DVO */
> +       WPCM450_PINCFG(122,      none, NONE, 0,           none, NONE, 0),
> /* DVO */
> +       WPCM450_PINCFG(123,      none, NONE, 0,           none, NONE, 0),
> /* DVO */
> +       WPCM450_PINCFG(124,      none, NONE, 0,           none, NONE, 0),
> /* DVO */
> +       WPCM450_PINCFG(125,      none, NONE, 0,           none, NONE, 0),
> /* DVO */
> +       WPCM450_PINCFG(126,      none, NONE, 0,           none, NONE, 0),
> /* DVO */
> +       WPCM450_PINCFG(127,      none, NONE, 0,           none, NONE, 0),
> /* DVO */
> +};
> +
> +#define WPCM450_PIN(n)         PINCTRL_PIN(n, "gpio" #n)
> +
> +static const struct pinctrl_pin_desc wpcm450_pins[] = {
> +       WPCM450_PIN(0),   WPCM450_PIN(1),   WPCM450_PIN(2),
>  WPCM450_PIN(3),
> +       WPCM450_PIN(4),   WPCM450_PIN(5),   WPCM450_PIN(6),
>  WPCM450_PIN(7),
> +       WPCM450_PIN(8),   WPCM450_PIN(9),   WPCM450_PIN(10),
> WPCM450_PIN(11),
> +       WPCM450_PIN(12),  WPCM450_PIN(13),  WPCM450_PIN(14),
> WPCM450_PIN(15),
> +       WPCM450_PIN(16),  WPCM450_PIN(17),  WPCM450_PIN(18),
> WPCM450_PIN(19),
> +       WPCM450_PIN(20),  WPCM450_PIN(21),  WPCM450_PIN(22),
> WPCM450_PIN(23),
> +       WPCM450_PIN(24),  WPCM450_PIN(25),  WPCM450_PIN(26),
> WPCM450_PIN(27),
> +       WPCM450_PIN(28),  WPCM450_PIN(29),  WPCM450_PIN(30),
> WPCM450_PIN(31),
> +       WPCM450_PIN(32),  WPCM450_PIN(33),  WPCM450_PIN(34),
> WPCM450_PIN(35),
> +       WPCM450_PIN(36),  WPCM450_PIN(37),  WPCM450_PIN(38),
> WPCM450_PIN(39),
> +       WPCM450_PIN(40),  WPCM450_PIN(41),  WPCM450_PIN(42),
> WPCM450_PIN(43),
> +       WPCM450_PIN(44),  WPCM450_PIN(45),  WPCM450_PIN(46),
> WPCM450_PIN(47),
> +       WPCM450_PIN(48),  WPCM450_PIN(49),  WPCM450_PIN(50),
> WPCM450_PIN(51),
> +       WPCM450_PIN(52),  WPCM450_PIN(53),  WPCM450_PIN(54),
> WPCM450_PIN(55),
> +       WPCM450_PIN(56),  WPCM450_PIN(57),  WPCM450_PIN(58),
> WPCM450_PIN(59),
> +       WPCM450_PIN(60),  WPCM450_PIN(61),  WPCM450_PIN(62),
> WPCM450_PIN(63),
> +       WPCM450_PIN(64),  WPCM450_PIN(65),  WPCM450_PIN(66),
> WPCM450_PIN(67),
> +       WPCM450_PIN(68),  WPCM450_PIN(69),  WPCM450_PIN(70),
> WPCM450_PIN(71),
> +       WPCM450_PIN(72),  WPCM450_PIN(73),  WPCM450_PIN(74),
> WPCM450_PIN(75),
> +       WPCM450_PIN(76),  WPCM450_PIN(77),  WPCM450_PIN(78),
> WPCM450_PIN(79),
> +       WPCM450_PIN(80),  WPCM450_PIN(81),  WPCM450_PIN(82),
> WPCM450_PIN(83),
> +       WPCM450_PIN(84),  WPCM450_PIN(85),  WPCM450_PIN(86),
> WPCM450_PIN(87),
> +       WPCM450_PIN(88),  WPCM450_PIN(89),  WPCM450_PIN(90),
> WPCM450_PIN(91),
> +       WPCM450_PIN(92),  WPCM450_PIN(93),  WPCM450_PIN(94),
> WPCM450_PIN(95),
> +       WPCM450_PIN(96),  WPCM450_PIN(97),  WPCM450_PIN(98),
> WPCM450_PIN(99),
> +       WPCM450_PIN(100), WPCM450_PIN(101), WPCM450_PIN(102),
> WPCM450_PIN(103),
> +       WPCM450_PIN(104), WPCM450_PIN(105), WPCM450_PIN(106),
> WPCM450_PIN(107),
> +       WPCM450_PIN(108), WPCM450_PIN(109), WPCM450_PIN(110),
> WPCM450_PIN(111),
> +       WPCM450_PIN(112), WPCM450_PIN(113), WPCM450_PIN(114),
> WPCM450_PIN(115),
> +       WPCM450_PIN(116), WPCM450_PIN(117), WPCM450_PIN(118),
> WPCM450_PIN(119),
> +       WPCM450_PIN(120), WPCM450_PIN(121), WPCM450_PIN(122),
> WPCM450_PIN(123),
> +       WPCM450_PIN(124), WPCM450_PIN(125), WPCM450_PIN(126),
> WPCM450_PIN(127),
> +};
> +
> +/* Enable mode in pin group */
> +static void wpcm450_setfunc(struct regmap *gcr_regmap, const unsigned int
> *pin,
> +                           int npins, int func)
> +{
> +       const struct wpcm450_pincfg *cfg;
> +       int i;
> +
> +       for (i = 0; i < npins; i++) {
> +               cfg = &pincfg[pin[i]];
> +               if (func == fn_gpio || cfg->fn0 == func || cfg->fn1 ==
> func) {
> +                       if (cfg->reg0)
> +                               regmap_update_bits(gcr_regmap, cfg->reg0,
> +                                                  BIT(cfg->bit0),
> +                                                  (cfg->fn0 == func) ?
> BIT(cfg->bit0) : 0);
> +                       if (cfg->reg1)
> +                               regmap_update_bits(gcr_regmap, cfg->reg1,
> +                                                  BIT(cfg->bit1),
> +                                                  (cfg->fn1 == func) ?
> BIT(cfg->bit1) : 0);
> +               }
> +       }
> +}
> +
> +static int wpcm450_get_groups_count(struct pinctrl_dev *pctldev)
> +{
> +       return ARRAY_SIZE(wpcm450_groups);
> +}
> +
> +static const char *wpcm450_get_group_name(struct pinctrl_dev *pctldev,
> +                                         unsigned int selector)
> +{
> +       return wpcm450_groups[selector].name;
> +}
> +
> +static int wpcm450_get_group_pins(struct pinctrl_dev *pctldev,
> +                                 unsigned int selector,
> +                                 const unsigned int **pins,
> +                                 unsigned int *npins)
> +{
> +       *npins = wpcm450_groups[selector].num_pins;
> +       *pins  = wpcm450_groups[selector].pins;
> +
> +       return 0;
> +}
> +
> +static int wpcm450_dt_node_to_map(struct pinctrl_dev *pctldev,
> +                                 struct device_node *np_config,
> +                                 struct pinctrl_map **map,
> +                                 u32 *num_maps)
> +{
> +       return pinconf_generic_dt_node_to_map(pctldev, np_config,
> +                                             map, num_maps,
> +                                             PIN_MAP_TYPE_INVALID);
> +}
> +
> +static void wpcm450_dt_free_map(struct pinctrl_dev *pctldev,
> +                               struct pinctrl_map *map, u32 num_maps)
> +{
> +       kfree(map);
> +}
> +
> +static const struct pinctrl_ops wpcm450_pinctrl_ops = {
> +       .get_groups_count = wpcm450_get_groups_count,
> +       .get_group_name = wpcm450_get_group_name,
> +       .get_group_pins = wpcm450_get_group_pins,
> +       .dt_node_to_map = wpcm450_dt_node_to_map,
> +       .dt_free_map = wpcm450_dt_free_map,
> +};
> +
> +static int wpcm450_get_functions_count(struct pinctrl_dev *pctldev)
> +{
> +       return ARRAY_SIZE(wpcm450_funcs);
> +}
> +
> +static const char *wpcm450_get_function_name(struct pinctrl_dev *pctldev,
> +                                            unsigned int function)
> +{
> +       return wpcm450_funcs[function].name;
> +}
> +
> +static int wpcm450_get_function_groups(struct pinctrl_dev *pctldev,
> +                                      unsigned int function,
> +                                      const char * const **groups,
> +                                      unsigned int * const ngroups)
> +{
> +       *ngroups = wpcm450_funcs[function].ngroups;
> +       *groups  = wpcm450_funcs[function].groups;
> +
> +       return 0;
> +}
> +
> +static int wpcm450_pinmux_set_mux(struct pinctrl_dev *pctldev,
> +                                 unsigned int function,
> +                                 unsigned int group)
> +{
> +       struct wpcm450_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
> +
> +       wpcm450_setfunc(pctrl->gcr_regmap, wpcm450_groups[group].pins,
> +                       wpcm450_groups[group].num_pins, function);
> +
> +       return 0;
> +}
> +
> +static const struct pinmux_ops wpcm450_pinmux_ops = {
> +       .get_functions_count = wpcm450_get_functions_count,
> +       .get_function_name = wpcm450_get_function_name,
> +       .get_function_groups = wpcm450_get_function_groups,
> +       .set_mux = wpcm450_pinmux_set_mux,
> +};
> +
> +static int debounce_bitnum(int gpio)
> +{
> +       if (gpio >= 0 && gpio < 16)
> +               return gpio;
> +       return -EINVAL;
> +}
> +
> +static int wpcm450_config_get(struct pinctrl_dev *pctldev, unsigned int
> pin,
> +                             unsigned long *config)
> +{
> +       struct wpcm450_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
> +       enum pin_config_param param = pinconf_to_config_param(*config);
> +       unsigned long flags;
> +       int bit;
> +       u32 reg;
> +
> +       switch (param) {
> +       case PIN_CONFIG_INPUT_DEBOUNCE:
> +               bit = debounce_bitnum(pin);
> +               if (bit < 0)
> +                       return bit;
> +
> +               spin_lock_irqsave(&pctrl->lock, flags);
> +               reg = ioread32(pctrl->gpio_base + WPCM450_GPEVDBNC);
> +               spin_unlock_irqrestore(&pctrl->lock, flags);
> +
> +               *config = pinconf_to_config_packed(param, !!(reg &
> BIT(bit)));
> +               break;
> +       default:
> +               return -ENOTSUPP;
> +       }
> +
> +       return 0;
> +}
> +
> +static int wpcm450_config_set_one(struct wpcm450_pinctrl *pctrl,
> +                                 unsigned int pin, unsigned long config)
> +{
> +       enum pin_config_param param = pinconf_to_config_param(config);
> +       unsigned long flags;
> +       unsigned long reg;
> +       int bit;
> +       int arg;
> +
> +       switch (param) {
> +       case PIN_CONFIG_INPUT_DEBOUNCE:
> +               bit = debounce_bitnum(pin);
> +               if (bit < 0)
> +                       return bit;
> +
> +               arg = pinconf_to_config_argument(config);
> +
> +               spin_lock_irqsave(&pctrl->lock, flags);
> +               reg = ioread32(pctrl->gpio_base + WPCM450_GPEVDBNC);
> +               __assign_bit(bit, &reg, arg);


 In all these cases are you really need to use __assign_bit() APIs? I don’t
see that this goes any higher than 32-bit.

It’s not a big deal though.

+               iowrite32(reg, pctrl->gpio_base + WPCM450_GPEVDBNC);
> +               spin_unlock_irqrestore(&pctrl->lock, flags);
> +               break;
> +       default:
> +               return -ENOTSUPP;
> +       }
> +
> +       return 0;
> +}
> +
> +static int wpcm450_config_set(struct pinctrl_dev *pctldev, unsigned int
> pin,
> +                             unsigned long *configs, unsigned int
> num_configs)
> +{
> +       struct wpcm450_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
> +       int ret;
> +
> +       while (num_configs--) {
> +               ret = wpcm450_config_set_one(pctrl, pin, *configs++);
> +               if (ret)
> +                       return ret;
> +       }
> +
> +       return 0;
> +}
> +
> +static const struct pinconf_ops wpcm450_pinconf_ops = {
> +       .is_generic = true,
> +       .pin_config_get = wpcm450_config_get,
> +       .pin_config_set = wpcm450_config_set,
> +};
> +
> +static struct pinctrl_desc wpcm450_pinctrl_desc = {
> +       .name = "wpcm450-pinctrl",
> +       .pins = wpcm450_pins,
> +       .npins = ARRAY_SIZE(wpcm450_pins),
> +       .pctlops = &wpcm450_pinctrl_ops,
> +       .pmxops = &wpcm450_pinmux_ops,
> +       .confops = &wpcm450_pinconf_ops,
> +       .owner = THIS_MODULE,
> +};
> +
> +static int wpcm450_gpio_set_config(struct gpio_chip *chip,
> +                                  unsigned int offset, unsigned long
> config)
> +{
> +       struct wpcm450_gpio *gpio = gpiochip_get_data(chip);
> +
> +       return wpcm450_config_set_one(gpio->pctrl, offset, config);
> +}
> +
> +static int wpcm450_gpio_register(struct platform_device *pdev,
> +                                struct wpcm450_pinctrl *pctrl)
> +{
> +       int ret = 0;
> +       struct fwnode_handle *np;


 Either be fully OF, or don’t name ‘np' here. We usually use fwnode or
‘child’ in this case.


> +
> +       pctrl->gpio_base = devm_platform_ioremap_resource(pdev, 0);
> +       if (!pctrl->gpio_base) {
> +               dev_err(pctrl->dev, "Resource fail for GPIO controller\n");
> +               return -ENOMEM;


dev_err_probe(), ditto for the rest in ->probe().


> +       }
> +
> +       fwnode_for_each_available_child_node(pctrl->dev->fwnode, np) {


Please, do not dereference fwnode, instead use analogue from device_*()
APIs. Hence, replace fwnode.h with property.h.


> +               void __iomem *dat = NULL;
> +               void __iomem *set = NULL;
> +               void __iomem *dirout = NULL;
> +               unsigned long flags = 0;
> +               const struct wpcm450_bank *bank;
> +               struct wpcm450_gpio *gpio;
> +               struct gpio_irq_chip *girq;
> +               u32 interrupt_map[3];
> +               int reg, i;
> +
> +               if (!fwnode_property_read_bool(np, "gpio-controller"))
> +                       continue;
> +
> +               ret = fwnode_property_read_u32(np, "reg", &reg);
> +               if (ret < 0)
> +                       return ret;
> +
> +               gpio = &pctrl->gpio_bank[reg];
> +               gpio->pctrl = pctrl;
> +
> +               if (reg < 0 || reg > WPCM450_NUM_BANKS) {
> +                       dev_err(pctrl->dev, "GPIO index %d out of
> range!\n", reg);
> +                       return -EINVAL;
> +               }
> +
> +               bank = &wpcm450_banks[reg];
> +
> +               dat = pctrl->gpio_base + bank->datain;
> +               if (bank->dataout) {
> +                       set = pctrl->gpio_base + bank->dataout;
> +                       dirout = pctrl->gpio_base + bank->cfg0;
> +               } else {
> +                       flags = BGPIOF_NO_OUTPUT;
> +               }
> +               ret = bgpio_init(&gpio->gc, pctrl->dev, 4,
> +                                dat, set, NULL, dirout, NULL, flags);
> +               if (ret < 0) {
> +                       dev_err(pctrl->dev, "GPIO initialization failed:
> %d\n", ret);
> +                       return ret;
> +               }
> +
> +               gpio->gc.ngpio = bank->length;
> +               gpio->gc.set_config = wpcm450_gpio_set_config;



> +               gpio->gc.of_node = to_of_node(np);


I hope we will soon have fwnode in gpio_chip.



> +               gpio->gc.parent = pctrl->dev;
>
>
Set by bgpio_init(), also check for other potential duplications.



> +               gpio->irqc = wpcm450_gpio_irqchip;
> +               girq = &gpio->gc.irq;
> +               girq->chip = &gpio->irqc;
> +               girq->parent_handler = wpcm450_gpio_irqhandler;
> +               girq->parents = devm_kcalloc(pctrl->dev,
> WPCM450_NUM_GPIO_IRQS,
> +                                            sizeof(*girq->parents),
> GFP_KERNEL);
> +               if (!girq->parents)
> +                       return -ENOMEM;
> +               girq->default_type = IRQ_TYPE_NONE;
> +               girq->handler = handle_bad_irq;
> +
> +               girq->num_parents = 0;
> +               for (i = 0; i < WPCM450_NUM_GPIO_IRQS; i++) {
> +                       int irq = fwnode_irq_get(np, i);
> +
> +                       if (irq < 0)
> +                               break;
> +
> +                       girq->parents[i] = irq;
> +                       girq->num_parents++;
> +               }
> +
> +               ret = fwnode_property_read_u32_array(np,
> "nuvoton,interrupt-map",
> +                                                    interrupt_map,
> ARRAY_SIZE(interrupt_map));
> +               if (ret == 0) {
> +                       gpio->first_irq_bit = interrupt_map[0];
> +                       gpio->num_irqs = interrupt_map[1];
> +                       gpio->first_irq_gpio = interrupt_map[2];
> +               }
> +
> +               ret = devm_gpiochip_add_data(pctrl->dev, &gpio->gc, gpio);
> +               if (ret) {
> +                       dev_err(pctrl->dev, "Failed to add GPIO chip:
> %d\n", ret);
> +                       return ret;
> +               }
> +
> +               ret = gpiochip_add_pin_range(&gpio->gc,
> dev_name(pctrl->dev),
> +                                            0, bank->base, bank->length);
> +               if (ret) {
> +                       dev_err(pctrl->dev, "Failed to add pin range for
> GPIO bank %u\n", reg);
> +                       return ret;
> +               }



Please move it to the corresponding callback.


> +       }
> +
> +       return 0;
> +}
> +
> +static int wpcm450_pinctrl_probe(struct platform_device *pdev)
> +{
> +       struct wpcm450_pinctrl *pctrl;
> +       int ret;
> +
> +       pctrl = devm_kzalloc(&pdev->dev, sizeof(*pctrl), GFP_KERNEL);
> +       if (!pctrl)
> +               return -ENOMEM;
> +
> +       pctrl->dev = &pdev->dev;
> +       spin_lock_init(&pctrl->lock);
> +       dev_set_drvdata(&pdev->dev, pctrl);
> +
> +       pctrl->gcr_regmap =
> +               syscon_regmap_lookup_by_compatible("nuvoton,wpcm450-gcr");
> +       if (IS_ERR(pctrl->gcr_regmap)) {
> +               dev_err_probe(pctrl->dev, PTR_ERR(pctrl->gcr_regmap),
> +                             "Failed to find nuvoton,wpcm450-gcr\n");
> +               return PTR_ERR(pctrl->gcr_regmap);
> +       }
> +
> +       pctrl->pctldev = devm_pinctrl_register(&pdev->dev,
> +                                              &wpcm450_pinctrl_desc,
> pctrl);
> +       if (IS_ERR(pctrl->pctldev)) {





> +               dev_err_probe(&pdev->dev, PTR_ERR(pctrl->pctldev),
> +                             "Failed to register pinctrl device\n");
> +               return PTR_ERR(pctrl->pctldev);


You may combine those two in one return statement.


> +       }
> +
> +       ret = wpcm450_gpio_register(pdev, pctrl);
> +       if (ret < 0)
> +               return ret;
> +
> +       return 0;
> +}
> +
> +static const struct of_device_id wpcm450_pinctrl_match[] = {
> +       { .compatible = "nuvoton,wpcm450-pinctrl" },
> +       { }
> +};
> +MODULE_DEVICE_TABLE(of, wpcm450_pinctrl_match);
> +
> +static struct platform_driver wpcm450_pinctrl_driver = {
> +       .probe = wpcm450_pinctrl_probe,
> +       .driver = {
> +               .name = "wpcm450-pinctrl",
> +               .of_match_table = wpcm450_pinctrl_match,
> +       },
> +};
> +module_platform_driver(wpcm450_pinctrl_driver);
> +
> +MODULE_LICENSE("GPL v2");
> +MODULE_AUTHOR("Jonathan Neuschäfer <j.neuschaefer@gmx.net>");
> +MODULE_DESCRIPTION("Nuvoton WPCM450 Pinctrl and GPIO driver");
> --
> 2.30.2
>
>

-- 
With Best Regards,
Andy Shevchenko

[-- Attachment #2: Type: text/html, Size: 66111 bytes --]

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

* Re: [PATCH v2 1/8] dt-bindings: arm/npcm: Add binding for global control registers (GCR)
  2021-12-07 21:08   ` Jonathan Neuschäfer
@ 2021-12-08 13:44     ` Rob Herring
  -1 siblings, 0 replies; 53+ messages in thread
From: Rob Herring @ 2021-12-08 13:44 UTC (permalink / raw)
  To: Jonathan Neuschäfer
  Cc: Nancy Yuen, linux-gpio, Tali Perry, openbmc, Patrick Venture,
	linux-kernel, devicetree, Linus Walleij, Tomer Maimon,
	Rob Herring, Benjamin Fair, Joel Stanley, Avi Fishman

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 2026 bytes --]

On Tue, 07 Dec 2021 22:08:16 +0100, Jonathan Neuschäfer wrote:
> A nuvoton,*-gcr node is present in nuvoton-common-npcm7xx.dtsi and will
> be added to nuvoton-wpcm450.dtsi. It is necessary for the NPCM7xx and
> WPCM450 pinctrl drivers, and may later be used to retrieve SoC model and
> version information.
> 
> This patch adds a binding to describe this node.
> 
> Signed-off-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>
> 
> ---
> v2:
> - Rename node in example to syscon@800000
> - Add subnode to example
> 
> v1:
> - https://lore.kernel.org/lkml/20210602120329.2444672-2-j.neuschaefer@gmx.net/
> ---
>  .../bindings/arm/npcm/nuvoton,gcr.yaml        | 45 +++++++++++++++++++
>  1 file changed, 45 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/arm/npcm/nuvoton,gcr.yaml
> 

My bot found errors running 'make DT_CHECKER_FLAGS=-m dt_binding_check'
on your patch (DT_CHECKER_FLAGS is new in v5.13):

yamllint warnings/errors:

dtschema/dtc warnings/errors:
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/arm/npcm/nuvoton,gcr.example.dt.yaml: syscon@800000: 'uart-mux-controller' does not match any of the regexes: 'pinctrl-[0-9]+'
	From schema: /builds/robherring/linux-dt-review/Documentation/devicetree/bindings/arm/npcm/nuvoton,gcr.yaml
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/arm/npcm/nuvoton,gcr.example.dt.yaml: uart-mux-controller: $nodename:0: 'uart-mux-controller' does not match '^mux-controller(@.*|-[0-9a-f]+)?$'
	From schema: /builds/robherring/linux-dt-review/Documentation/devicetree/bindings/mux/mux-controller.yaml

doc reference errors (make refcheckdocs):

See https://patchwork.ozlabs.org/patch/1564899

This check can fail if there are any dependencies. The base for a patch
series is generally the most recent rc1.

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:

pip3 install dtschema --upgrade

Please check and re-submit.


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

* Re: [PATCH v2 4/8] dt-bindings: pinctrl: Add Nuvoton WPCM450
  2021-12-07 21:08   ` Jonathan Neuschäfer
@ 2021-12-08 13:44     ` Rob Herring
  -1 siblings, 0 replies; 53+ messages in thread
From: Rob Herring @ 2021-12-08 13:44 UTC (permalink / raw)
  To: Jonathan Neuschäfer
  Cc: linux-gpio, Linus Walleij, devicetree, linux-kernel,
	Joel Stanley, Tomer Maimon, Rob Herring, openbmc

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 3143 bytes --]

On Tue, 07 Dec 2021 22:08:19 +0100, Jonathan Neuschäfer wrote:
> This binding is heavily based on the one for NPCM7xx, because the
> hardware is similar. There are some notable differences, however:
> 
> - The addresses of GPIO banks are not physical addresses but simple
>   indices (0 to 7), because the GPIO registers are not laid out in
>   convenient blocks.
> - Pinmux settings can explicitly specify that the GPIO mode is used.
> 
> Certain pins support blink patterns in hardware. This is currently not
> modelled in the DT binding.
> 
> Signed-off-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>
> 
> 
> ---
> v2:
> - Move GPIO into subnodes
> - Improve use of quotes
> - Remove unnecessary minItems/maxItems lines
> - Remove "phandle: true"
> - Use separate prefixes for pinmux and pincfg nodes
> - Add nuvoton,interrupt-map property
> - Make it possible to set pinmux to GPIO explicitly
> 
> v1:
> - https://lore.kernel.org/lkml/20210602120329.2444672-5-j.neuschaefer@gmx.net/
> ---
>  .../pinctrl/nuvoton,wpcm450-pinctrl.yaml      | 190 ++++++++++++++++++
>  1 file changed, 190 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/pinctrl/nuvoton,wpcm450-pinctrl.yaml
> 

My bot found errors running 'make DT_CHECKER_FLAGS=-m dt_binding_check'
on your patch (DT_CHECKER_FLAGS is new in v5.13):

yamllint warnings/errors:

dtschema/dtc warnings/errors:
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/pinctrl/nuvoton,wpcm450-pinctrl.example.dt.yaml: pinctrl@b8003000: gpio@0:interrupts: [[2, 4, 3, 4, 4, 4]] is too short
	From schema: /builds/robherring/linux-dt-review/Documentation/devicetree/bindings/pinctrl/nuvoton,wpcm450-pinctrl.yaml
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/pinctrl/nuvoton,wpcm450-pinctrl.example.dt.yaml: pinctrl@b8003000: mux_uid: Additional properties are not allowed ('phandle' was unexpected)
	From schema: /builds/robherring/linux-dt-review/Documentation/devicetree/bindings/pinctrl/nuvoton,wpcm450-pinctrl.yaml
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/pinctrl/nuvoton,wpcm450-pinctrl.example.dt.yaml: pinctrl@b8003000: cfg_uid: Additional properties are not allowed ('phandle' was unexpected)
	From schema: /builds/robherring/linux-dt-review/Documentation/devicetree/bindings/pinctrl/nuvoton,wpcm450-pinctrl.yaml
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/pinctrl/nuvoton,wpcm450-pinctrl.example.dt.yaml: pinctrl@b8003000: '#address-cells', '#size-cells' do not match any of the regexes: '^cfg_.*$', '^gpio@.*$', '^mux_.*$', 'pinctrl-[0-9]+'
	From schema: /builds/robherring/linux-dt-review/Documentation/devicetree/bindings/pinctrl/nuvoton,wpcm450-pinctrl.yaml

doc reference errors (make refcheckdocs):

See https://patchwork.ozlabs.org/patch/1564902

This check can fail if there are any dependencies. The base for a patch
series is generally the most recent rc1.

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:

pip3 install dtschema --upgrade

Please check and re-submit.


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

* Re: [PATCH v2 1/8] dt-bindings: arm/npcm: Add binding for global control registers (GCR)
@ 2021-12-08 13:44     ` Rob Herring
  0 siblings, 0 replies; 53+ messages in thread
From: Rob Herring @ 2021-12-08 13:44 UTC (permalink / raw)
  To: Jonathan Neuschäfer
  Cc: devicetree, Tomer Maimon, linux-gpio, Avi Fishman,
	Patrick Venture, openbmc, linux-kernel, Tali Perry, Rob Herring,
	Linus Walleij, Benjamin Fair

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 2026 bytes --]

On Tue, 07 Dec 2021 22:08:16 +0100, Jonathan Neuschäfer wrote:
> A nuvoton,*-gcr node is present in nuvoton-common-npcm7xx.dtsi and will
> be added to nuvoton-wpcm450.dtsi. It is necessary for the NPCM7xx and
> WPCM450 pinctrl drivers, and may later be used to retrieve SoC model and
> version information.
> 
> This patch adds a binding to describe this node.
> 
> Signed-off-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>
> 
> ---
> v2:
> - Rename node in example to syscon@800000
> - Add subnode to example
> 
> v1:
> - https://lore.kernel.org/lkml/20210602120329.2444672-2-j.neuschaefer@gmx.net/
> ---
>  .../bindings/arm/npcm/nuvoton,gcr.yaml        | 45 +++++++++++++++++++
>  1 file changed, 45 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/arm/npcm/nuvoton,gcr.yaml
> 

My bot found errors running 'make DT_CHECKER_FLAGS=-m dt_binding_check'
on your patch (DT_CHECKER_FLAGS is new in v5.13):

yamllint warnings/errors:

dtschema/dtc warnings/errors:
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/arm/npcm/nuvoton,gcr.example.dt.yaml: syscon@800000: 'uart-mux-controller' does not match any of the regexes: 'pinctrl-[0-9]+'
	From schema: /builds/robherring/linux-dt-review/Documentation/devicetree/bindings/arm/npcm/nuvoton,gcr.yaml
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/arm/npcm/nuvoton,gcr.example.dt.yaml: uart-mux-controller: $nodename:0: 'uart-mux-controller' does not match '^mux-controller(@.*|-[0-9a-f]+)?$'
	From schema: /builds/robherring/linux-dt-review/Documentation/devicetree/bindings/mux/mux-controller.yaml

doc reference errors (make refcheckdocs):

See https://patchwork.ozlabs.org/patch/1564899

This check can fail if there are any dependencies. The base for a patch
series is generally the most recent rc1.

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:

pip3 install dtschema --upgrade

Please check and re-submit.


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

* Re: [PATCH v2 4/8] dt-bindings: pinctrl: Add Nuvoton WPCM450
@ 2021-12-08 13:44     ` Rob Herring
  0 siblings, 0 replies; 53+ messages in thread
From: Rob Herring @ 2021-12-08 13:44 UTC (permalink / raw)
  To: Jonathan Neuschäfer
  Cc: devicetree, Tomer Maimon, Linus Walleij, linux-kernel,
	linux-gpio, Rob Herring, openbmc

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 3143 bytes --]

On Tue, 07 Dec 2021 22:08:19 +0100, Jonathan Neuschäfer wrote:
> This binding is heavily based on the one for NPCM7xx, because the
> hardware is similar. There are some notable differences, however:
> 
> - The addresses of GPIO banks are not physical addresses but simple
>   indices (0 to 7), because the GPIO registers are not laid out in
>   convenient blocks.
> - Pinmux settings can explicitly specify that the GPIO mode is used.
> 
> Certain pins support blink patterns in hardware. This is currently not
> modelled in the DT binding.
> 
> Signed-off-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>
> 
> 
> ---
> v2:
> - Move GPIO into subnodes
> - Improve use of quotes
> - Remove unnecessary minItems/maxItems lines
> - Remove "phandle: true"
> - Use separate prefixes for pinmux and pincfg nodes
> - Add nuvoton,interrupt-map property
> - Make it possible to set pinmux to GPIO explicitly
> 
> v1:
> - https://lore.kernel.org/lkml/20210602120329.2444672-5-j.neuschaefer@gmx.net/
> ---
>  .../pinctrl/nuvoton,wpcm450-pinctrl.yaml      | 190 ++++++++++++++++++
>  1 file changed, 190 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/pinctrl/nuvoton,wpcm450-pinctrl.yaml
> 

My bot found errors running 'make DT_CHECKER_FLAGS=-m dt_binding_check'
on your patch (DT_CHECKER_FLAGS is new in v5.13):

yamllint warnings/errors:

dtschema/dtc warnings/errors:
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/pinctrl/nuvoton,wpcm450-pinctrl.example.dt.yaml: pinctrl@b8003000: gpio@0:interrupts: [[2, 4, 3, 4, 4, 4]] is too short
	From schema: /builds/robherring/linux-dt-review/Documentation/devicetree/bindings/pinctrl/nuvoton,wpcm450-pinctrl.yaml
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/pinctrl/nuvoton,wpcm450-pinctrl.example.dt.yaml: pinctrl@b8003000: mux_uid: Additional properties are not allowed ('phandle' was unexpected)
	From schema: /builds/robherring/linux-dt-review/Documentation/devicetree/bindings/pinctrl/nuvoton,wpcm450-pinctrl.yaml
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/pinctrl/nuvoton,wpcm450-pinctrl.example.dt.yaml: pinctrl@b8003000: cfg_uid: Additional properties are not allowed ('phandle' was unexpected)
	From schema: /builds/robherring/linux-dt-review/Documentation/devicetree/bindings/pinctrl/nuvoton,wpcm450-pinctrl.yaml
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/pinctrl/nuvoton,wpcm450-pinctrl.example.dt.yaml: pinctrl@b8003000: '#address-cells', '#size-cells' do not match any of the regexes: '^cfg_.*$', '^gpio@.*$', '^mux_.*$', 'pinctrl-[0-9]+'
	From schema: /builds/robherring/linux-dt-review/Documentation/devicetree/bindings/pinctrl/nuvoton,wpcm450-pinctrl.yaml

doc reference errors (make refcheckdocs):

See https://patchwork.ozlabs.org/patch/1564902

This check can fail if there are any dependencies. The base for a patch
series is generally the most recent rc1.

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:

pip3 install dtschema --upgrade

Please check and re-submit.


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

* Re: [PATCH v2 5/8] pinctrl: nuvoton: Add driver for WPCM450
  2021-12-08 11:24   ` Andy Shevchenko
@ 2021-12-08 13:58       ` Jonathan Neuschäfer
  0 siblings, 0 replies; 53+ messages in thread
From: Jonathan Neuschäfer @ 2021-12-08 13:58 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Jonathan Neuschäfer, linux-gpio, devicetree, Linus Walleij,
	Rob Herring, openbmc, Tomer Maimon, Joel Stanley, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 7225 bytes --]

Hi,

On Wed, Dec 08, 2021 at 01:24:18PM +0200, Andy Shevchenko wrote:
> On Tuesday, December 7, 2021, Jonathan Neuschäfer <j.neuschaefer@gmx.net>
> wrote:
> 
> > This driver is based on the one for NPCM7xx, because the WPCM450 is a
> > predecessor of those SoCs. Notable differences:
> >
> > - WPCM450, the GPIO registers are not organized in multiple banks, but
> >   rather placed continually into the same register block. This affects
> >   how register offsets are computed.
> > - Pinmux nodes can explicitly select GPIO mode, whereas, in the npcm7xx
> >   driver, this happens automatically when a GPIO is requested.
> >
> > Some functionality implemented in the hardware was (for now) left unused
> > in the driver, specifically blinking and pull-up/down.
> >
> > Signed-off-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>
> > ---
[...]
> > +
> > +#include <linux/device.h>
> > +#include <linux/fwnode.h>
> > +#include <linux/gpio/driver.h>
> > +#include <linux/interrupt.h>
> > +#include <linux/irq.h>
> > +#include <linux/mfd/syscon.h>
> > +#include <linux/module.h>
> > +#include <linux/mod_devicetable.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/regmap.h>
> 
> 
> + blank line?

Sounds reasonable, I'll add it.


> > +struct wpcm450_gpio {
> > +       struct wpcm450_pinctrl  *pctrl;
> > +       struct gpio_chip        gc;
> 
> 
> Making this first speeds up pointer arithmetics by making it no-op at
> compile time.

Will do.


> > +static int wpcm450_gpio_irq_bitnum(struct wpcm450_gpio *gpio, struct
> > irq_data *d)
> > +{
> > +       int hwirq = irqd_to_hwirq(d);
> > +
> > +       if (hwirq < gpio->first_irq_gpio)
> > +               return -EINVAL;
> > +
> > +       if (hwirq - gpio->first_irq_gpio >= gpio->num_irqs)
> > +               return -EINVAL;
> > +
> > +       return hwirq - gpio->first_irq_gpio + gpio->first_irq_bit;
> > +}
> > +
> > +static int wpcm450_irq_bitnum_to_gpio(struct wpcm450_gpio *gpio, int
> > bitnum)
> > +{
> > +       if (bitnum < gpio->first_irq_bit)
> > +               return -EINVAL;
> > +
> > +       if (bitnum - gpio->first_irq_bit > gpio->num_irqs)
> > +               return -EINVAL;
> > +
> > +       return bitnum - gpio->first_irq_bit + gpio->first_irq_gpio;
> > +}
> >
> 
> 
> Have you chance to look at bitmap_remap() and bitmap_bitremap() APIs? I’m
> pretty sure you can make this all cleaner by switching to those calls and
> represent the GPIOs as continuous bitmap on the Linux side while on the
> hardware it will be sparse. Check gpio-Xilinx for the details of use.

I haven't looked at it yet in detail, but I'll consider it for the next
iteration.

> > +static void wpcm450_gpio_fix_evpol(struct wpcm450_gpio *gpio, unsigned
> > long all)
> > +{
> 
> 
> 
> What is this quirk (?) for? Please add a comment.

The hardware does not support triggering on both edges, so the trigger
edge polarity has to be adjusted before the next interrupt can work
properly.

I'll add a comment.


> > +static void wpcm450_gpio_irqhandler(struct irq_desc *desc)
> > +{
> > +       struct wpcm450_gpio *gpio = gpiochip_get_data(irq_desc_
> > get_handler_data(desc));
> > +       struct wpcm450_pinctrl *pctrl = gpio->pctrl;
> > +       struct irq_chip *chip = irq_desc_get_chip(desc);
> > +       unsigned long pending;
> > +       unsigned long flags;
> > +       unsigned long ours;
> > +       unsigned int bit;
> > +
> > +       ours = ((1UL << gpio->num_irqs) - 1) << gpio->first_irq_bit;
> 
> 
> BIT()

I'll use it, but in this case, I think it doesn't simplify much the
whole expression all that much. Is there perhaps a macro that
constructs a continuous bitmask of N bits, perhaps additionally
left-shifted by M bits?

Maybe somewhere in the bitmap_* API...


> > +       chained_irq_enter(chip, desc);
> > +       for_each_set_bit(bit, &pending, 32) {
> > +               int offset = wpcm450_irq_bitnum_to_gpio(gpio, bit);
> > +               int irq = irq_find_mapping(gpio->gc.irq.domain, offset);
> > +
> > +               generic_handle_irq(irq);
> 
> 
> Above two are now represented by another generic IRQ handle call, check
> relatively recently updated drivers around.

Will do.

> > +       }
> > +       chained_irq_exit(chip, desc);



> > +               spin_lock_irqsave(&pctrl->lock, flags);
> > +               reg = ioread32(pctrl->gpio_base + WPCM450_GPEVDBNC);
> > +               __assign_bit(bit, &reg, arg);
> 
> 
>  In all these cases are you really need to use __assign_bit() APIs? I don’t
> see that this goes any higher than 32-bit.
> 
> It’s not a big deal though.

Not really necessary, it just seemed short and good, because it saved
having to spent multiple lines setting/resetting the bit in the variable.


> > +static int wpcm450_gpio_register(struct platform_device *pdev,
> > +                                struct wpcm450_pinctrl *pctrl)
> > +{
> > +       int ret = 0;
> > +       struct fwnode_handle *np;
> 
> 
>  Either be fully OF, or don’t name ‘np' here. We usually use fwnode or
> ‘child’ in this case.

Ah, I thought "np" (= node pointer) was still appropriate because I'm
dealing with firmware _nodes_. My intention was indeed to switch fully
to the fwnode API.


> > +
> > +       pctrl->gpio_base = devm_platform_ioremap_resource(pdev, 0);
> > +       if (!pctrl->gpio_base) {
> > +               dev_err(pctrl->dev, "Resource fail for GPIO controller\n");
> > +               return -ENOMEM;
> 
> 
> dev_err_probe(), ditto for the rest in ->probe().

Oh, I missed these error paths when I changed wpcm450_pinctrl_probe to
dev_err_probe(). I'll go through the rest of the dev_err calls.


> > +       fwnode_for_each_available_child_node(pctrl->dev->fwnode, np) {
> 
> 
> Please, do not dereference fwnode, instead use analogue from device_*()
> APIs. Hence, replace fwnode.h with property.h.

Ok, I'll use device_for_each_child_node() for iteration.


> > +               gpio->gc.of_node = to_of_node(np);
> 
> 
> I hope we will soon have fwnode in gpio_chip.

Yes, that would be good.



> > +               gpio->gc.parent = pctrl->dev;
> >
> >
> Set by bgpio_init(), also check for other potential duplications.

Good catch, I'll check the assignments again.


> > +               ret = gpiochip_add_pin_range(&gpio->gc,
> > dev_name(pctrl->dev),
> > +                                            0, bank->base, bank->length);
> > +               if (ret) {
> > +                       dev_err(pctrl->dev, "Failed to add pin range for
> > GPIO bank %u\n", reg);
> > +                       return ret;
> > +               }
> 
> 
> 
> Please move it to the corresponding callback.

What's the corresponding callback?


> > +               dev_err_probe(&pdev->dev, PTR_ERR(pctrl->pctldev),
> > +                             "Failed to register pinctrl device\n");
> > +               return PTR_ERR(pctrl->pctldev);
> 
> 
> You may combine those two in one return statement.

Good catch, will do.


Thanks for your review,
Jonathan

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v2 5/8] pinctrl: nuvoton: Add driver for WPCM450
@ 2021-12-08 13:58       ` Jonathan Neuschäfer
  0 siblings, 0 replies; 53+ messages in thread
From: Jonathan Neuschäfer @ 2021-12-08 13:58 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: devicetree, Tomer Maimon, openbmc, Jonathan Neuschäfer,
	linux-kernel, linux-gpio, Rob Herring, Linus Walleij

[-- Attachment #1: Type: text/plain, Size: 7225 bytes --]

Hi,

On Wed, Dec 08, 2021 at 01:24:18PM +0200, Andy Shevchenko wrote:
> On Tuesday, December 7, 2021, Jonathan Neuschäfer <j.neuschaefer@gmx.net>
> wrote:
> 
> > This driver is based on the one for NPCM7xx, because the WPCM450 is a
> > predecessor of those SoCs. Notable differences:
> >
> > - WPCM450, the GPIO registers are not organized in multiple banks, but
> >   rather placed continually into the same register block. This affects
> >   how register offsets are computed.
> > - Pinmux nodes can explicitly select GPIO mode, whereas, in the npcm7xx
> >   driver, this happens automatically when a GPIO is requested.
> >
> > Some functionality implemented in the hardware was (for now) left unused
> > in the driver, specifically blinking and pull-up/down.
> >
> > Signed-off-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>
> > ---
[...]
> > +
> > +#include <linux/device.h>
> > +#include <linux/fwnode.h>
> > +#include <linux/gpio/driver.h>
> > +#include <linux/interrupt.h>
> > +#include <linux/irq.h>
> > +#include <linux/mfd/syscon.h>
> > +#include <linux/module.h>
> > +#include <linux/mod_devicetable.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/regmap.h>
> 
> 
> + blank line?

Sounds reasonable, I'll add it.


> > +struct wpcm450_gpio {
> > +       struct wpcm450_pinctrl  *pctrl;
> > +       struct gpio_chip        gc;
> 
> 
> Making this first speeds up pointer arithmetics by making it no-op at
> compile time.

Will do.


> > +static int wpcm450_gpio_irq_bitnum(struct wpcm450_gpio *gpio, struct
> > irq_data *d)
> > +{
> > +       int hwirq = irqd_to_hwirq(d);
> > +
> > +       if (hwirq < gpio->first_irq_gpio)
> > +               return -EINVAL;
> > +
> > +       if (hwirq - gpio->first_irq_gpio >= gpio->num_irqs)
> > +               return -EINVAL;
> > +
> > +       return hwirq - gpio->first_irq_gpio + gpio->first_irq_bit;
> > +}
> > +
> > +static int wpcm450_irq_bitnum_to_gpio(struct wpcm450_gpio *gpio, int
> > bitnum)
> > +{
> > +       if (bitnum < gpio->first_irq_bit)
> > +               return -EINVAL;
> > +
> > +       if (bitnum - gpio->first_irq_bit > gpio->num_irqs)
> > +               return -EINVAL;
> > +
> > +       return bitnum - gpio->first_irq_bit + gpio->first_irq_gpio;
> > +}
> >
> 
> 
> Have you chance to look at bitmap_remap() and bitmap_bitremap() APIs? I’m
> pretty sure you can make this all cleaner by switching to those calls and
> represent the GPIOs as continuous bitmap on the Linux side while on the
> hardware it will be sparse. Check gpio-Xilinx for the details of use.

I haven't looked at it yet in detail, but I'll consider it for the next
iteration.

> > +static void wpcm450_gpio_fix_evpol(struct wpcm450_gpio *gpio, unsigned
> > long all)
> > +{
> 
> 
> 
> What is this quirk (?) for? Please add a comment.

The hardware does not support triggering on both edges, so the trigger
edge polarity has to be adjusted before the next interrupt can work
properly.

I'll add a comment.


> > +static void wpcm450_gpio_irqhandler(struct irq_desc *desc)
> > +{
> > +       struct wpcm450_gpio *gpio = gpiochip_get_data(irq_desc_
> > get_handler_data(desc));
> > +       struct wpcm450_pinctrl *pctrl = gpio->pctrl;
> > +       struct irq_chip *chip = irq_desc_get_chip(desc);
> > +       unsigned long pending;
> > +       unsigned long flags;
> > +       unsigned long ours;
> > +       unsigned int bit;
> > +
> > +       ours = ((1UL << gpio->num_irqs) - 1) << gpio->first_irq_bit;
> 
> 
> BIT()

I'll use it, but in this case, I think it doesn't simplify much the
whole expression all that much. Is there perhaps a macro that
constructs a continuous bitmask of N bits, perhaps additionally
left-shifted by M bits?

Maybe somewhere in the bitmap_* API...


> > +       chained_irq_enter(chip, desc);
> > +       for_each_set_bit(bit, &pending, 32) {
> > +               int offset = wpcm450_irq_bitnum_to_gpio(gpio, bit);
> > +               int irq = irq_find_mapping(gpio->gc.irq.domain, offset);
> > +
> > +               generic_handle_irq(irq);
> 
> 
> Above two are now represented by another generic IRQ handle call, check
> relatively recently updated drivers around.

Will do.

> > +       }
> > +       chained_irq_exit(chip, desc);



> > +               spin_lock_irqsave(&pctrl->lock, flags);
> > +               reg = ioread32(pctrl->gpio_base + WPCM450_GPEVDBNC);
> > +               __assign_bit(bit, &reg, arg);
> 
> 
>  In all these cases are you really need to use __assign_bit() APIs? I don’t
> see that this goes any higher than 32-bit.
> 
> It’s not a big deal though.

Not really necessary, it just seemed short and good, because it saved
having to spent multiple lines setting/resetting the bit in the variable.


> > +static int wpcm450_gpio_register(struct platform_device *pdev,
> > +                                struct wpcm450_pinctrl *pctrl)
> > +{
> > +       int ret = 0;
> > +       struct fwnode_handle *np;
> 
> 
>  Either be fully OF, or don’t name ‘np' here. We usually use fwnode or
> ‘child’ in this case.

Ah, I thought "np" (= node pointer) was still appropriate because I'm
dealing with firmware _nodes_. My intention was indeed to switch fully
to the fwnode API.


> > +
> > +       pctrl->gpio_base = devm_platform_ioremap_resource(pdev, 0);
> > +       if (!pctrl->gpio_base) {
> > +               dev_err(pctrl->dev, "Resource fail for GPIO controller\n");
> > +               return -ENOMEM;
> 
> 
> dev_err_probe(), ditto for the rest in ->probe().

Oh, I missed these error paths when I changed wpcm450_pinctrl_probe to
dev_err_probe(). I'll go through the rest of the dev_err calls.


> > +       fwnode_for_each_available_child_node(pctrl->dev->fwnode, np) {
> 
> 
> Please, do not dereference fwnode, instead use analogue from device_*()
> APIs. Hence, replace fwnode.h with property.h.

Ok, I'll use device_for_each_child_node() for iteration.


> > +               gpio->gc.of_node = to_of_node(np);
> 
> 
> I hope we will soon have fwnode in gpio_chip.

Yes, that would be good.



> > +               gpio->gc.parent = pctrl->dev;
> >
> >
> Set by bgpio_init(), also check for other potential duplications.

Good catch, I'll check the assignments again.


> > +               ret = gpiochip_add_pin_range(&gpio->gc,
> > dev_name(pctrl->dev),
> > +                                            0, bank->base, bank->length);
> > +               if (ret) {
> > +                       dev_err(pctrl->dev, "Failed to add pin range for
> > GPIO bank %u\n", reg);
> > +                       return ret;
> > +               }
> 
> 
> 
> Please move it to the corresponding callback.

What's the corresponding callback?


> > +               dev_err_probe(&pdev->dev, PTR_ERR(pctrl->pctldev),
> > +                             "Failed to register pinctrl device\n");
> > +               return PTR_ERR(pctrl->pctldev);
> 
> 
> You may combine those two in one return statement.

Good catch, will do.


Thanks for your review,
Jonathan

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v2 5/8] pinctrl: nuvoton: Add driver for WPCM450
  2021-12-08 13:58       ` Jonathan Neuschäfer
@ 2021-12-08 14:14         ` Andy Shevchenko
  -1 siblings, 0 replies; 53+ messages in thread
From: Andy Shevchenko @ 2021-12-08 14:14 UTC (permalink / raw)
  To: Jonathan Neuschäfer
  Cc: linux-gpio, devicetree, Linus Walleij, Rob Herring, openbmc,
	Tomer Maimon, Joel Stanley, linux-kernel

On Wed, Dec 8, 2021 at 3:58 PM Jonathan Neuschäfer
<j.neuschaefer@gmx.net> wrote:
> On Wed, Dec 08, 2021 at 01:24:18PM +0200, Andy Shevchenko wrote:
> > On Tuesday, December 7, 2021, Jonathan Neuschäfer <j.neuschaefer@gmx.net>
> > wrote:

...

> > > +       ours = ((1UL << gpio->num_irqs) - 1) << gpio->first_irq_bit;
> >
> > BIT()
>
> I'll use it, but in this case, I think it doesn't simplify much the
> whole expression all that much.

It is still better to use in my opinion.

> Is there perhaps a macro that
> constructs a continuous bitmask of N bits, perhaps additionally
> left-shifted by M bits?

> Maybe somewhere in the bitmap_* API...

Maybe, I dunno since I haven't clearly got this code anyway, so up to
you to check and see what to do about it.

...

> > > +       struct fwnode_handle *np;
> >
> >  Either be fully OF, or don’t name ‘np' here. We usually use fwnode or
> > ‘child’ in this case.
>
> Ah, I thought "np" (= node pointer) was still appropriate because I'm
> dealing with firmware _nodes_. My intention was indeed to switch fully
> to the fwnode API.

Just a convention "de facto".

...

> > > +               ret = gpiochip_add_pin_range(&gpio->gc,
> > > dev_name(pctrl->dev),
> > > +                                            0, bank->base, bank->length);
> > > +               if (ret) {
> > > +                       dev_err(pctrl->dev, "Failed to add pin range for
> > > GPIO bank %u\n", reg);
> > > +                       return ret;
> > > +               }
> >
> > Please move it to the corresponding callback.
>
> What's the corresponding callback?

https://elixir.bootlin.com/linux/latest/source/include/linux/gpio/driver.h#L400

-- 
With Best Regards,
Andy Shevchenko

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

* Re: [PATCH v2 5/8] pinctrl: nuvoton: Add driver for WPCM450
@ 2021-12-08 14:14         ` Andy Shevchenko
  0 siblings, 0 replies; 53+ messages in thread
From: Andy Shevchenko @ 2021-12-08 14:14 UTC (permalink / raw)
  To: Jonathan Neuschäfer
  Cc: devicetree, Tomer Maimon, Linus Walleij, linux-kernel,
	linux-gpio, Rob Herring, openbmc

On Wed, Dec 8, 2021 at 3:58 PM Jonathan Neuschäfer
<j.neuschaefer@gmx.net> wrote:
> On Wed, Dec 08, 2021 at 01:24:18PM +0200, Andy Shevchenko wrote:
> > On Tuesday, December 7, 2021, Jonathan Neuschäfer <j.neuschaefer@gmx.net>
> > wrote:

...

> > > +       ours = ((1UL << gpio->num_irqs) - 1) << gpio->first_irq_bit;
> >
> > BIT()
>
> I'll use it, but in this case, I think it doesn't simplify much the
> whole expression all that much.

It is still better to use in my opinion.

> Is there perhaps a macro that
> constructs a continuous bitmask of N bits, perhaps additionally
> left-shifted by M bits?

> Maybe somewhere in the bitmap_* API...

Maybe, I dunno since I haven't clearly got this code anyway, so up to
you to check and see what to do about it.

...

> > > +       struct fwnode_handle *np;
> >
> >  Either be fully OF, or don’t name ‘np' here. We usually use fwnode or
> > ‘child’ in this case.
>
> Ah, I thought "np" (= node pointer) was still appropriate because I'm
> dealing with firmware _nodes_. My intention was indeed to switch fully
> to the fwnode API.

Just a convention "de facto".

...

> > > +               ret = gpiochip_add_pin_range(&gpio->gc,
> > > dev_name(pctrl->dev),
> > > +                                            0, bank->base, bank->length);
> > > +               if (ret) {
> > > +                       dev_err(pctrl->dev, "Failed to add pin range for
> > > GPIO bank %u\n", reg);
> > > +                       return ret;
> > > +               }
> >
> > Please move it to the corresponding callback.
>
> What's the corresponding callback?

https://elixir.bootlin.com/linux/latest/source/include/linux/gpio/driver.h#L400

-- 
With Best Regards,
Andy Shevchenko

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

* Re: [PATCH v2 5/8] pinctrl: nuvoton: Add driver for WPCM450
  2021-12-08 13:58       ` Jonathan Neuschäfer
@ 2021-12-09  8:26         ` Zev Weiss
  -1 siblings, 0 replies; 53+ messages in thread
From: Zev Weiss @ 2021-12-09  8:26 UTC (permalink / raw)
  To: Jonathan Neuschäfer
  Cc: devicetree, Tomer Maimon, openbmc, linux-kernel, linux-gpio,
	Andy Shevchenko, Rob Herring, Linus Walleij

On Wed, Dec 08, 2021 at 05:58:30AM PST, Jonathan Neuschäfer wrote:
>Hi,
>
>On Wed, Dec 08, 2021 at 01:24:18PM +0200, Andy Shevchenko wrote:
>> On Tuesday, December 7, 2021, Jonathan Neuschäfer <j.neuschaefer@gmx.net>
>
><snip>
>
>> > +static void wpcm450_gpio_irqhandler(struct irq_desc *desc)
>> > +{
>> > +       struct wpcm450_gpio *gpio = gpiochip_get_data(irq_desc_
>> > get_handler_data(desc));
>> > +       struct wpcm450_pinctrl *pctrl = gpio->pctrl;
>> > +       struct irq_chip *chip = irq_desc_get_chip(desc);
>> > +       unsigned long pending;
>> > +       unsigned long flags;
>> > +       unsigned long ours;
>> > +       unsigned int bit;
>> > +
>> > +       ours = ((1UL << gpio->num_irqs) - 1) << gpio->first_irq_bit;
>>
>>
>> BIT()
>
>I'll use it, but in this case, I think it doesn't simplify much the
>whole expression all that much. Is there perhaps a macro that
>constructs a continuous bitmask of N bits, perhaps additionally
>left-shifted by M bits?
>
>Maybe somewhere in the bitmap_* API...
>

There's GENMASK(), though it takes a high bit and low bit rather than a
bit position and count, so it'd require a small bit of arithmetic, e.g.

  lastbit = gpio->first_irq_bit + gpio->num_irqs - 1;
  ours = GENMASK(lastbit, gpio->first_irq_bit);

or a manual shift:

  ours = GENMASK(gpio->num_irqs - 1, 0) << gpio->first_irq_bit;

(I don't have any terribly strong opinions on which of these is best,
personally.)



Zev

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

* Re: [PATCH v2 5/8] pinctrl: nuvoton: Add driver for WPCM450
@ 2021-12-09  8:26         ` Zev Weiss
  0 siblings, 0 replies; 53+ messages in thread
From: Zev Weiss @ 2021-12-09  8:26 UTC (permalink / raw)
  To: Jonathan Neuschäfer
  Cc: Andy Shevchenko, devicetree, Tomer Maimon, openbmc, linux-kernel,
	linux-gpio, Rob Herring, Linus Walleij

On Wed, Dec 08, 2021 at 05:58:30AM PST, Jonathan Neuschäfer wrote:
>Hi,
>
>On Wed, Dec 08, 2021 at 01:24:18PM +0200, Andy Shevchenko wrote:
>> On Tuesday, December 7, 2021, Jonathan Neuschäfer <j.neuschaefer@gmx.net>
>
><snip>
>
>> > +static void wpcm450_gpio_irqhandler(struct irq_desc *desc)
>> > +{
>> > +       struct wpcm450_gpio *gpio = gpiochip_get_data(irq_desc_
>> > get_handler_data(desc));
>> > +       struct wpcm450_pinctrl *pctrl = gpio->pctrl;
>> > +       struct irq_chip *chip = irq_desc_get_chip(desc);
>> > +       unsigned long pending;
>> > +       unsigned long flags;
>> > +       unsigned long ours;
>> > +       unsigned int bit;
>> > +
>> > +       ours = ((1UL << gpio->num_irqs) - 1) << gpio->first_irq_bit;
>>
>>
>> BIT()
>
>I'll use it, but in this case, I think it doesn't simplify much the
>whole expression all that much. Is there perhaps a macro that
>constructs a continuous bitmask of N bits, perhaps additionally
>left-shifted by M bits?
>
>Maybe somewhere in the bitmap_* API...
>

There's GENMASK(), though it takes a high bit and low bit rather than a
bit position and count, so it'd require a small bit of arithmetic, e.g.

  lastbit = gpio->first_irq_bit + gpio->num_irqs - 1;
  ours = GENMASK(lastbit, gpio->first_irq_bit);

or a manual shift:

  ours = GENMASK(gpio->num_irqs - 1, 0) << gpio->first_irq_bit;

(I don't have any terribly strong opinions on which of these is best,
personally.)



Zev

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

* Re: [PATCH v2 5/8] pinctrl: nuvoton: Add driver for WPCM450
  2021-12-09  8:26         ` Zev Weiss
@ 2021-12-10  1:41           ` Linus Walleij
  -1 siblings, 0 replies; 53+ messages in thread
From: Linus Walleij @ 2021-12-10  1:41 UTC (permalink / raw)
  To: zweiss
  Cc: Jonathan Neuschäfer, Andy Shevchenko, devicetree,
	Tomer Maimon, openbmc, linux-kernel, linux-gpio, Rob Herring

On Thu, Dec 9, 2021 at 9:26 AM Zev Weiss <zweiss@equinix.com> wrote:
> On Wed, Dec 08, 2021 at 05:58:30AM PST, Jonathan Neuschäfer wrote:

> >> BIT()
> >
> >I'll use it, but in this case, I think it doesn't simplify much the
> >whole expression all that much. Is there perhaps a macro that
> >constructs a continuous bitmask of N bits, perhaps additionally
> >left-shifted by M bits?
> >
> >Maybe somewhere in the bitmap_* API...
> >
>
> There's GENMASK(), though it takes a high bit and low bit rather than a
> bit position and count, so it'd require a small bit of arithmetic, e.g.
>
>   lastbit = gpio->first_irq_bit + gpio->num_irqs - 1;
>   ours = GENMASK(lastbit, gpio->first_irq_bit);
>
> or a manual shift:
>
>   ours = GENMASK(gpio->num_irqs - 1, 0) << gpio->first_irq_bit;

I think this can be handled with FIELD_PREP() from
<linux/bitfield.h>? Some examples at the top of the
header.

Yours,
Linus Walleij

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

* Re: [PATCH v2 5/8] pinctrl: nuvoton: Add driver for WPCM450
@ 2021-12-10  1:41           ` Linus Walleij
  0 siblings, 0 replies; 53+ messages in thread
From: Linus Walleij @ 2021-12-10  1:41 UTC (permalink / raw)
  To: zweiss
  Cc: devicetree, Tomer Maimon, openbmc, Jonathan Neuschäfer,
	linux-kernel, linux-gpio, Andy Shevchenko, Rob Herring

On Thu, Dec 9, 2021 at 9:26 AM Zev Weiss <zweiss@equinix.com> wrote:
> On Wed, Dec 08, 2021 at 05:58:30AM PST, Jonathan Neuschäfer wrote:

> >> BIT()
> >
> >I'll use it, but in this case, I think it doesn't simplify much the
> >whole expression all that much. Is there perhaps a macro that
> >constructs a continuous bitmask of N bits, perhaps additionally
> >left-shifted by M bits?
> >
> >Maybe somewhere in the bitmap_* API...
> >
>
> There's GENMASK(), though it takes a high bit and low bit rather than a
> bit position and count, so it'd require a small bit of arithmetic, e.g.
>
>   lastbit = gpio->first_irq_bit + gpio->num_irqs - 1;
>   ours = GENMASK(lastbit, gpio->first_irq_bit);
>
> or a manual shift:
>
>   ours = GENMASK(gpio->num_irqs - 1, 0) << gpio->first_irq_bit;

I think this can be handled with FIELD_PREP() from
<linux/bitfield.h>? Some examples at the top of the
header.

Yours,
Linus Walleij

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

* Re: [PATCH v2 6/8] ARM: dts: wpcm450: Add pinctrl and GPIO nodes
  2021-12-07 21:08   ` Jonathan Neuschäfer
@ 2021-12-10  1:42     ` Linus Walleij
  -1 siblings, 0 replies; 53+ messages in thread
From: Linus Walleij @ 2021-12-10  1:42 UTC (permalink / raw)
  To: Jonathan Neuschäfer
  Cc: linux-gpio, devicetree, Rob Herring, openbmc, Tomer Maimon,
	Joel Stanley, linux-kernel

On Tue, Dec 7, 2021 at 10:08 PM Jonathan Neuschäfer
<j.neuschaefer@gmx.net> wrote:

> This patch adds the pin controller and GPIO banks to the devicetree for the
> WPCM450 SoC.
>
> Signed-off-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>

This looks good.
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>

Yours,
Linus Walleij

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

* Re: [PATCH v2 6/8] ARM: dts: wpcm450: Add pinctrl and GPIO nodes
@ 2021-12-10  1:42     ` Linus Walleij
  0 siblings, 0 replies; 53+ messages in thread
From: Linus Walleij @ 2021-12-10  1:42 UTC (permalink / raw)
  To: Jonathan Neuschäfer
  Cc: devicetree, Tomer Maimon, openbmc, linux-kernel, linux-gpio, Rob Herring

On Tue, Dec 7, 2021 at 10:08 PM Jonathan Neuschäfer
<j.neuschaefer@gmx.net> wrote:

> This patch adds the pin controller and GPIO banks to the devicetree for the
> WPCM450 SoC.
>
> Signed-off-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>

This looks good.
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>

Yours,
Linus Walleij

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

* Re: [PATCH v2 1/8] dt-bindings: arm/npcm: Add binding for global control registers (GCR)
  2021-12-07 21:08   ` Jonathan Neuschäfer
@ 2021-12-10 14:54     ` Rob Herring
  -1 siblings, 0 replies; 53+ messages in thread
From: Rob Herring @ 2021-12-10 14:54 UTC (permalink / raw)
  To: Jonathan Neuschäfer
  Cc: linux-gpio, devicetree, Linus Walleij, openbmc, Tomer Maimon,
	Joel Stanley, linux-kernel, Avi Fishman, Tali Perry,
	Patrick Venture, Nancy Yuen, Benjamin Fair

On Tue, Dec 07, 2021 at 10:08:16PM +0100, Jonathan Neuschäfer wrote:
> A nuvoton,*-gcr node is present in nuvoton-common-npcm7xx.dtsi and will
> be added to nuvoton-wpcm450.dtsi. It is necessary for the NPCM7xx and
> WPCM450 pinctrl drivers, and may later be used to retrieve SoC model and
> version information.
> 
> This patch adds a binding to describe this node.
> 
> Signed-off-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>
> 
> ---
> v2:
> - Rename node in example to syscon@800000
> - Add subnode to example
> 
> v1:
> - https://lore.kernel.org/lkml/20210602120329.2444672-2-j.neuschaefer@gmx.net/
> ---
>  .../bindings/arm/npcm/nuvoton,gcr.yaml        | 45 +++++++++++++++++++
>  1 file changed, 45 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/arm/npcm/nuvoton,gcr.yaml
> 
> diff --git a/Documentation/devicetree/bindings/arm/npcm/nuvoton,gcr.yaml b/Documentation/devicetree/bindings/arm/npcm/nuvoton,gcr.yaml
> new file mode 100644
> index 0000000000000..62020d7ac305b
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/arm/npcm/nuvoton,gcr.yaml
> @@ -0,0 +1,45 @@
> +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/arm/npcm/nuvoton,gcr.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Global Control Registers block in Nuvoton SoCs
> +
> +maintainers:
> +  - Jonathan Neuschäfer <j.neuschaefer@gmx.net>
> +
> +description: |

Don't need '|' if no formatting.

> +  The Global Control Registers (GCR) are a block of registers in Nuvoton SoCs
> +  that expose misc functionality such as chip model and version information or
> +  pinmux settings.
> +
> +properties:
> +  compatible:
> +    items:
> +      - enum:
> +          - nuvoton,wpcm450-gcr
> +          - nuvoton,npcm750-gcr
> +      - const: syscon
> +      - const: simple-mfd

blank line

> +  reg: true

Need to define how many entries:

maxItems: 1


> +
> +required:
> +  - compatible
> +  - reg
> +
> +additionalProperties: false

Ideally, you should define the child node names, but you can do this:

additionalProperties:
  type: object

which means anything undefined must be a node.

> +
> +examples:
> +  - |
> +    gcr: syscon@800000 {
> +      compatible = "nuvoton,npcm750-gcr", "syscon", "simple-mfd";
> +      reg = <0x800000 0x1000>;
> +
> +      uart-mux-controller {
> +        compatible = "mmio-mux";
> +        #mux-control-cells = <1>;
> +        mux-reg-masks = <0x38 0x07>;
> +        idle-states = <2>;
> +      };
> +    };
> --
> 2.30.2
> 
> 

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

* Re: [PATCH v2 1/8] dt-bindings: arm/npcm: Add binding for global control registers (GCR)
@ 2021-12-10 14:54     ` Rob Herring
  0 siblings, 0 replies; 53+ messages in thread
From: Rob Herring @ 2021-12-10 14:54 UTC (permalink / raw)
  To: Jonathan Neuschäfer
  Cc: devicetree, Tomer Maimon, Avi Fishman, Patrick Venture,
	Linus Walleij, linux-kernel, Tali Perry, linux-gpio, openbmc,
	Benjamin Fair

On Tue, Dec 07, 2021 at 10:08:16PM +0100, Jonathan Neuschäfer wrote:
> A nuvoton,*-gcr node is present in nuvoton-common-npcm7xx.dtsi and will
> be added to nuvoton-wpcm450.dtsi. It is necessary for the NPCM7xx and
> WPCM450 pinctrl drivers, and may later be used to retrieve SoC model and
> version information.
> 
> This patch adds a binding to describe this node.
> 
> Signed-off-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>
> 
> ---
> v2:
> - Rename node in example to syscon@800000
> - Add subnode to example
> 
> v1:
> - https://lore.kernel.org/lkml/20210602120329.2444672-2-j.neuschaefer@gmx.net/
> ---
>  .../bindings/arm/npcm/nuvoton,gcr.yaml        | 45 +++++++++++++++++++
>  1 file changed, 45 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/arm/npcm/nuvoton,gcr.yaml
> 
> diff --git a/Documentation/devicetree/bindings/arm/npcm/nuvoton,gcr.yaml b/Documentation/devicetree/bindings/arm/npcm/nuvoton,gcr.yaml
> new file mode 100644
> index 0000000000000..62020d7ac305b
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/arm/npcm/nuvoton,gcr.yaml
> @@ -0,0 +1,45 @@
> +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/arm/npcm/nuvoton,gcr.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Global Control Registers block in Nuvoton SoCs
> +
> +maintainers:
> +  - Jonathan Neuschäfer <j.neuschaefer@gmx.net>
> +
> +description: |

Don't need '|' if no formatting.

> +  The Global Control Registers (GCR) are a block of registers in Nuvoton SoCs
> +  that expose misc functionality such as chip model and version information or
> +  pinmux settings.
> +
> +properties:
> +  compatible:
> +    items:
> +      - enum:
> +          - nuvoton,wpcm450-gcr
> +          - nuvoton,npcm750-gcr
> +      - const: syscon
> +      - const: simple-mfd

blank line

> +  reg: true

Need to define how many entries:

maxItems: 1


> +
> +required:
> +  - compatible
> +  - reg
> +
> +additionalProperties: false

Ideally, you should define the child node names, but you can do this:

additionalProperties:
  type: object

which means anything undefined must be a node.

> +
> +examples:
> +  - |
> +    gcr: syscon@800000 {
> +      compatible = "nuvoton,npcm750-gcr", "syscon", "simple-mfd";
> +      reg = <0x800000 0x1000>;
> +
> +      uart-mux-controller {
> +        compatible = "mmio-mux";
> +        #mux-control-cells = <1>;
> +        mux-reg-masks = <0x38 0x07>;
> +        idle-states = <2>;
> +      };
> +    };
> --
> 2.30.2
> 
> 

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

* Re: [PATCH v2 4/8] dt-bindings: pinctrl: Add Nuvoton WPCM450
  2021-12-07 21:08   ` Jonathan Neuschäfer
@ 2021-12-10 15:18     ` Rob Herring
  -1 siblings, 0 replies; 53+ messages in thread
From: Rob Herring @ 2021-12-10 15:18 UTC (permalink / raw)
  To: Jonathan Neuschäfer
  Cc: linux-gpio, devicetree, Linus Walleij, openbmc, Tomer Maimon,
	Joel Stanley, linux-kernel

On Tue, Dec 07, 2021 at 10:08:19PM +0100, Jonathan Neuschäfer wrote:
> This binding is heavily based on the one for NPCM7xx, because the
> hardware is similar. There are some notable differences, however:
> 
> - The addresses of GPIO banks are not physical addresses but simple
>   indices (0 to 7), because the GPIO registers are not laid out in
>   convenient blocks.
> - Pinmux settings can explicitly specify that the GPIO mode is used.
> 
> Certain pins support blink patterns in hardware. This is currently not
> modelled in the DT binding.
> 
> Signed-off-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>
> 
> 
> ---
> v2:
> - Move GPIO into subnodes
> - Improve use of quotes
> - Remove unnecessary minItems/maxItems lines
> - Remove "phandle: true"
> - Use separate prefixes for pinmux and pincfg nodes
> - Add nuvoton,interrupt-map property
> - Make it possible to set pinmux to GPIO explicitly
> 
> v1:
> - https://lore.kernel.org/lkml/20210602120329.2444672-5-j.neuschaefer@gmx.net/
> ---
>  .../pinctrl/nuvoton,wpcm450-pinctrl.yaml      | 190 ++++++++++++++++++
>  1 file changed, 190 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/pinctrl/nuvoton,wpcm450-pinctrl.yaml
> 
> diff --git a/Documentation/devicetree/bindings/pinctrl/nuvoton,wpcm450-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/nuvoton,wpcm450-pinctrl.yaml
> new file mode 100644
> index 0000000000000..2b783597794d7
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/pinctrl/nuvoton,wpcm450-pinctrl.yaml
> @@ -0,0 +1,190 @@
> +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/pinctrl/nuvoton,wpcm450-pinctrl.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Nuvoton WPCM450 pin control and GPIO
> +
> +maintainers:
> +  - Jonathan Neuschäfer <j.neuschaefer@gmx.net>
> +
> +properties:
> +  compatible:
> +    const: nuvoton,wpcm450-pinctrl
> +
> +  reg:
> +    maxItems: 1
> +
> +patternProperties:
> +  # There are three kinds of subnodes:
> +  # 1. a GPIO controller node for each GPIO bank
> +  # 2. a pinmux node configures pin muxing for a group of pins (e.g. rmii2)
> +  # 3. a pinconf node configures properties of a single pin
> +
> +  "^gpio@.*$":
> +    if:

Not necessary because you can't have a property with '@' in it.

> +      type: object
> +    then:
> +      description:
> +        Eight GPIO banks (gpio@0 to gpio@7), that each contain between 14 and 18
> +        GPIOs. Some GPIOs support interrupts.
> +
> +      allOf:
> +        - $ref: pinmux-node.yaml#
> +
> +      properties:
> +        reg:
> +          description: GPIO bank number (0-7)
> +
> +        gpio-controller: true
> +
> +        "#gpio-cells":
> +          const: 2
> +
> +        interrupt-controller: true
> +
> +        "#interrupt-cells":
> +          const: 2
> +
> +        interrupts:
> +          maxItems: 4

Need to define what each interrupt is.

> +
> +        nuvoton,interrupt-map:

Reusing 'interrupt-map' with a different definition bothers me... 

> +          description:
> +            This property defines which bits in the interrupt registers
> +            correspond to which GPIOs.
> +          $ref: /schemas/types.yaml#/definitions/uint32-array
> +          items:
> +            - description: First interrupt bit
> +            - description: Number of interrupt bits
> +            - description: First GPIO associated with an interrupt
> +
> +      required:
> +        - reg
> +        - gpio-controller
> +        - '#gpio-cells'
> +
> +  "^mux_.*$":

Use '-' rather than '_' and the '.*' is not necessary.

"^mux-"

> +    if:

Don't need this.

> +      type: object
> +    then:
> +      allOf:
> +        - $ref: pinmux-node.yaml#
> +      properties:
> +        groups:
> +          description:
> +            One or more groups of pins to mux to a certain function
> +          items:
> +            enum: [ smb3, smb4, smb5, scs1, scs2, scs3, smb0, smb1, smb2, bsp,
> +                    hsp1, hsp2, r1err, r1md, rmii2, r2err, r2md, kbcc, dvo,
> +                    clko, smi, uinc, gspi, mben, xcs2, xcs1, sdio, sspi, fi0,
> +                    fi1, fi2, fi3, fi4, fi5, fi6, fi7, fi8, fi9, fi10, fi11,
> +                    fi12, fi13, fi14, fi15, pwm0, pwm1, pwm2, pwm3, pwm4, pwm5,
> +                    pwm6, pwm7, hg0, hg1, hg2, hg3, hg4, hg5, hg6, hg7 ]
> +        function:
> +          description:
> +            The function that a group of pins is muxed to
> +          enum: [ smb3, smb4, smb5, scs1, scs2, scs3, smb0, smb1, smb2, bsp,
> +                  hsp1, hsp2, r1err, r1md, rmii2, r2err, r2md, kbcc, dvo0,
> +                  dvo1, dvo2, dvo3, dvo4, dvo5, dvo6, dvo7, clko, smi, uinc,
> +                  gspi, mben, xcs2, xcs1, sdio, sspi, fi0, fi1, fi2, fi3, fi4,
> +                  fi5, fi6, fi7, fi8, fi9, fi10, fi11, fi12, fi13, fi14, fi15,
> +                  pwm0, pwm1, pwm2, pwm3, pwm4, pwm5, pwm6, pwm7, hg0, hg1,
> +                  hg2, hg3, hg4, hg5, hg6, hg7, gpio ]
> +
> +      dependencies:
> +        groups: [ function ]
> +        function: [ groups ]
> +
> +      additionalProperties: false
> +
> +  "^cfg_.*$":
> +    if:

Same comments here

> +      type: object
> +    then:
> +      allOf:
> +        - $ref: pincfg-node.yaml#
> +      properties:
> +        pins:
> +          description:
> +            A list of pins to configure in certain ways, such as enabling
> +            debouncing
> +          items:
> +            enum: [ gpio0, gpio1, gpio2, gpio3, gpio4, gpio5, gpio6, gpio7,
> +                    gpio8, gpio9, gpio10, gpio11, gpio12, gpio13, gpio14,
> +                    gpio15, gpio16, gpio17, gpio18, gpio19, gpio20, gpio21,
> +                    gpio22, gpio23, gpio24, gpio25, gpio26, gpio27, gpio28,
> +                    gpio29, gpio30, gpio31, gpio32, gpio33, gpio34, gpio35,
> +                    gpio36, gpio37, gpio38, gpio39, gpio40, gpio41, gpio42,
> +                    gpio43, gpio44, gpio45, gpio46, gpio47, gpio48, gpio49,
> +                    gpio50, gpio51, gpio52, gpio53, gpio54, gpio55, gpio56,
> +                    gpio57, gpio58, gpio59, gpio60, gpio61, gpio62, gpio63,
> +                    gpio64, gpio65, gpio66, gpio67, gpio68, gpio69, gpio70,
> +                    gpio71, gpio72, gpio73, gpio74, gpio75, gpio76, gpio77,
> +                    gpio78, gpio79, gpio80, gpio81, gpio82, gpio83, gpio84,
> +                    gpio85, gpio86, gpio87, gpio88, gpio89, gpio90, gpio91,
> +                    gpio92, gpio93, gpio94, gpio95, gpio96, gpio97, gpio98,
> +                    gpio99, gpio100, gpio101, gpio102, gpio103, gpio104,
> +                    gpio105, gpio106, gpio107, gpio108, gpio109, gpio110,
> +                    gpio111, gpio112, gpio113, gpio114, gpio115, gpio116,
> +                    gpio117, gpio118, gpio119, gpio120, gpio121, gpio122,
> +                    gpio123, gpio124, gpio125, gpio126, gpio127 ]

pattern: '^gpio1?[0-9]{1,2}$'

Feel free to tweak it more to limit to 127 if you want.

> +
> +        input-debounce: true
> +
> +      additionalProperties: false
> +
> +required:
> +  - compatible
> +  - reg
> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +    #include <dt-bindings/interrupt-controller/irq.h>
> +    #include <dt-bindings/gpio/gpio.h>
> +    pinctrl: pinctrl@b8003000 {
> +      compatible = "nuvoton,wpcm450-pinctrl";
> +      reg = <0xb8003000 0x1000>;
> +      #address-cells = <1>;
> +      #size-cells = <0>;
> +
> +      gpio0: gpio@0 {
> +        reg = <0>;
> +        gpio-controller;
> +        #gpio-cells = <2>;
> +        interrupts = <2 IRQ_TYPE_LEVEL_HIGH
> +                      3 IRQ_TYPE_LEVEL_HIGH
> +                      4 IRQ_TYPE_LEVEL_HIGH>;
> +        nuvoton,interrupt-map = <0 16 0>;

Based on the example, you don't need this as it is 1:1.

> +      };
> +
> +      mux_rmii2 {
> +        groups = "rmii2";
> +        function = "rmii2";
> +      };
> +
> +      pinmux_uid: mux_uid {
> +        groups = "gspi", "sspi";
> +        function = "gpio";
> +      };
> +
> +      pinctrl_uid: cfg_uid {
> +        pins = "gpio14";
> +        input-debounce = <1>;
> +      };
> +    };
> +
> +    gpio-keys {
> +      compatible = "gpio-keys";
> +      pinctrl-names = "default";
> +      pinctrl-0 = <&pinctrl_uid>, <&pinmux_uid>;
> +
> +      uid {
> +        label = "UID";
> +        linux,code = <102>;
> +        gpios = <&gpio0 14 GPIO_ACTIVE_HIGH>;
> +      };
> +    };
> --
> 2.30.2
> 
> 

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

* Re: [PATCH v2 4/8] dt-bindings: pinctrl: Add Nuvoton WPCM450
@ 2021-12-10 15:18     ` Rob Herring
  0 siblings, 0 replies; 53+ messages in thread
From: Rob Herring @ 2021-12-10 15:18 UTC (permalink / raw)
  To: Jonathan Neuschäfer
  Cc: devicetree, Tomer Maimon, Linus Walleij, linux-kernel,
	linux-gpio, openbmc

On Tue, Dec 07, 2021 at 10:08:19PM +0100, Jonathan Neuschäfer wrote:
> This binding is heavily based on the one for NPCM7xx, because the
> hardware is similar. There are some notable differences, however:
> 
> - The addresses of GPIO banks are not physical addresses but simple
>   indices (0 to 7), because the GPIO registers are not laid out in
>   convenient blocks.
> - Pinmux settings can explicitly specify that the GPIO mode is used.
> 
> Certain pins support blink patterns in hardware. This is currently not
> modelled in the DT binding.
> 
> Signed-off-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>
> 
> 
> ---
> v2:
> - Move GPIO into subnodes
> - Improve use of quotes
> - Remove unnecessary minItems/maxItems lines
> - Remove "phandle: true"
> - Use separate prefixes for pinmux and pincfg nodes
> - Add nuvoton,interrupt-map property
> - Make it possible to set pinmux to GPIO explicitly
> 
> v1:
> - https://lore.kernel.org/lkml/20210602120329.2444672-5-j.neuschaefer@gmx.net/
> ---
>  .../pinctrl/nuvoton,wpcm450-pinctrl.yaml      | 190 ++++++++++++++++++
>  1 file changed, 190 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/pinctrl/nuvoton,wpcm450-pinctrl.yaml
> 
> diff --git a/Documentation/devicetree/bindings/pinctrl/nuvoton,wpcm450-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/nuvoton,wpcm450-pinctrl.yaml
> new file mode 100644
> index 0000000000000..2b783597794d7
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/pinctrl/nuvoton,wpcm450-pinctrl.yaml
> @@ -0,0 +1,190 @@
> +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/pinctrl/nuvoton,wpcm450-pinctrl.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Nuvoton WPCM450 pin control and GPIO
> +
> +maintainers:
> +  - Jonathan Neuschäfer <j.neuschaefer@gmx.net>
> +
> +properties:
> +  compatible:
> +    const: nuvoton,wpcm450-pinctrl
> +
> +  reg:
> +    maxItems: 1
> +
> +patternProperties:
> +  # There are three kinds of subnodes:
> +  # 1. a GPIO controller node for each GPIO bank
> +  # 2. a pinmux node configures pin muxing for a group of pins (e.g. rmii2)
> +  # 3. a pinconf node configures properties of a single pin
> +
> +  "^gpio@.*$":
> +    if:

Not necessary because you can't have a property with '@' in it.

> +      type: object
> +    then:
> +      description:
> +        Eight GPIO banks (gpio@0 to gpio@7), that each contain between 14 and 18
> +        GPIOs. Some GPIOs support interrupts.
> +
> +      allOf:
> +        - $ref: pinmux-node.yaml#
> +
> +      properties:
> +        reg:
> +          description: GPIO bank number (0-7)
> +
> +        gpio-controller: true
> +
> +        "#gpio-cells":
> +          const: 2
> +
> +        interrupt-controller: true
> +
> +        "#interrupt-cells":
> +          const: 2
> +
> +        interrupts:
> +          maxItems: 4

Need to define what each interrupt is.

> +
> +        nuvoton,interrupt-map:

Reusing 'interrupt-map' with a different definition bothers me... 

> +          description:
> +            This property defines which bits in the interrupt registers
> +            correspond to which GPIOs.
> +          $ref: /schemas/types.yaml#/definitions/uint32-array
> +          items:
> +            - description: First interrupt bit
> +            - description: Number of interrupt bits
> +            - description: First GPIO associated with an interrupt
> +
> +      required:
> +        - reg
> +        - gpio-controller
> +        - '#gpio-cells'
> +
> +  "^mux_.*$":

Use '-' rather than '_' and the '.*' is not necessary.

"^mux-"

> +    if:

Don't need this.

> +      type: object
> +    then:
> +      allOf:
> +        - $ref: pinmux-node.yaml#
> +      properties:
> +        groups:
> +          description:
> +            One or more groups of pins to mux to a certain function
> +          items:
> +            enum: [ smb3, smb4, smb5, scs1, scs2, scs3, smb0, smb1, smb2, bsp,
> +                    hsp1, hsp2, r1err, r1md, rmii2, r2err, r2md, kbcc, dvo,
> +                    clko, smi, uinc, gspi, mben, xcs2, xcs1, sdio, sspi, fi0,
> +                    fi1, fi2, fi3, fi4, fi5, fi6, fi7, fi8, fi9, fi10, fi11,
> +                    fi12, fi13, fi14, fi15, pwm0, pwm1, pwm2, pwm3, pwm4, pwm5,
> +                    pwm6, pwm7, hg0, hg1, hg2, hg3, hg4, hg5, hg6, hg7 ]
> +        function:
> +          description:
> +            The function that a group of pins is muxed to
> +          enum: [ smb3, smb4, smb5, scs1, scs2, scs3, smb0, smb1, smb2, bsp,
> +                  hsp1, hsp2, r1err, r1md, rmii2, r2err, r2md, kbcc, dvo0,
> +                  dvo1, dvo2, dvo3, dvo4, dvo5, dvo6, dvo7, clko, smi, uinc,
> +                  gspi, mben, xcs2, xcs1, sdio, sspi, fi0, fi1, fi2, fi3, fi4,
> +                  fi5, fi6, fi7, fi8, fi9, fi10, fi11, fi12, fi13, fi14, fi15,
> +                  pwm0, pwm1, pwm2, pwm3, pwm4, pwm5, pwm6, pwm7, hg0, hg1,
> +                  hg2, hg3, hg4, hg5, hg6, hg7, gpio ]
> +
> +      dependencies:
> +        groups: [ function ]
> +        function: [ groups ]
> +
> +      additionalProperties: false
> +
> +  "^cfg_.*$":
> +    if:

Same comments here

> +      type: object
> +    then:
> +      allOf:
> +        - $ref: pincfg-node.yaml#
> +      properties:
> +        pins:
> +          description:
> +            A list of pins to configure in certain ways, such as enabling
> +            debouncing
> +          items:
> +            enum: [ gpio0, gpio1, gpio2, gpio3, gpio4, gpio5, gpio6, gpio7,
> +                    gpio8, gpio9, gpio10, gpio11, gpio12, gpio13, gpio14,
> +                    gpio15, gpio16, gpio17, gpio18, gpio19, gpio20, gpio21,
> +                    gpio22, gpio23, gpio24, gpio25, gpio26, gpio27, gpio28,
> +                    gpio29, gpio30, gpio31, gpio32, gpio33, gpio34, gpio35,
> +                    gpio36, gpio37, gpio38, gpio39, gpio40, gpio41, gpio42,
> +                    gpio43, gpio44, gpio45, gpio46, gpio47, gpio48, gpio49,
> +                    gpio50, gpio51, gpio52, gpio53, gpio54, gpio55, gpio56,
> +                    gpio57, gpio58, gpio59, gpio60, gpio61, gpio62, gpio63,
> +                    gpio64, gpio65, gpio66, gpio67, gpio68, gpio69, gpio70,
> +                    gpio71, gpio72, gpio73, gpio74, gpio75, gpio76, gpio77,
> +                    gpio78, gpio79, gpio80, gpio81, gpio82, gpio83, gpio84,
> +                    gpio85, gpio86, gpio87, gpio88, gpio89, gpio90, gpio91,
> +                    gpio92, gpio93, gpio94, gpio95, gpio96, gpio97, gpio98,
> +                    gpio99, gpio100, gpio101, gpio102, gpio103, gpio104,
> +                    gpio105, gpio106, gpio107, gpio108, gpio109, gpio110,
> +                    gpio111, gpio112, gpio113, gpio114, gpio115, gpio116,
> +                    gpio117, gpio118, gpio119, gpio120, gpio121, gpio122,
> +                    gpio123, gpio124, gpio125, gpio126, gpio127 ]

pattern: '^gpio1?[0-9]{1,2}$'

Feel free to tweak it more to limit to 127 if you want.

> +
> +        input-debounce: true
> +
> +      additionalProperties: false
> +
> +required:
> +  - compatible
> +  - reg
> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +    #include <dt-bindings/interrupt-controller/irq.h>
> +    #include <dt-bindings/gpio/gpio.h>
> +    pinctrl: pinctrl@b8003000 {
> +      compatible = "nuvoton,wpcm450-pinctrl";
> +      reg = <0xb8003000 0x1000>;
> +      #address-cells = <1>;
> +      #size-cells = <0>;
> +
> +      gpio0: gpio@0 {
> +        reg = <0>;
> +        gpio-controller;
> +        #gpio-cells = <2>;
> +        interrupts = <2 IRQ_TYPE_LEVEL_HIGH
> +                      3 IRQ_TYPE_LEVEL_HIGH
> +                      4 IRQ_TYPE_LEVEL_HIGH>;
> +        nuvoton,interrupt-map = <0 16 0>;

Based on the example, you don't need this as it is 1:1.

> +      };
> +
> +      mux_rmii2 {
> +        groups = "rmii2";
> +        function = "rmii2";
> +      };
> +
> +      pinmux_uid: mux_uid {
> +        groups = "gspi", "sspi";
> +        function = "gpio";
> +      };
> +
> +      pinctrl_uid: cfg_uid {
> +        pins = "gpio14";
> +        input-debounce = <1>;
> +      };
> +    };
> +
> +    gpio-keys {
> +      compatible = "gpio-keys";
> +      pinctrl-names = "default";
> +      pinctrl-0 = <&pinctrl_uid>, <&pinmux_uid>;
> +
> +      uid {
> +        label = "UID";
> +        linux,code = <102>;
> +        gpios = <&gpio0 14 GPIO_ACTIVE_HIGH>;
> +      };
> +    };
> --
> 2.30.2
> 
> 

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

* Re: [PATCH v2 5/8] pinctrl: nuvoton: Add driver for WPCM450
  2021-12-08 14:14         ` Andy Shevchenko
@ 2021-12-12 23:02           ` Jonathan Neuschäfer
  -1 siblings, 0 replies; 53+ messages in thread
From: Jonathan Neuschäfer @ 2021-12-12 23:02 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Jonathan Neuschäfer, linux-gpio, devicetree, Linus Walleij,
	Rob Herring, openbmc, Tomer Maimon, Joel Stanley, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 2023 bytes --]

On Wed, Dec 08, 2021 at 04:14:38PM +0200, Andy Shevchenko wrote:
> On Wed, Dec 8, 2021 at 3:58 PM Jonathan Neuschäfer <j.neuschaefer@gmx.net> wrote:
> > On Wed, Dec 08, 2021 at 01:24:18PM +0200, Andy Shevchenko wrote:
> > > On Tuesday, December 7, 2021, Jonathan Neuschäfer <j.neuschaefer@gmx.net>
> > > wrote:
> 
> ...
> 
> > > > +       ours = ((1UL << gpio->num_irqs) - 1) << gpio->first_irq_bit;
> > >
> > > BIT()
> >
> > I'll use it, but in this case, I think it doesn't simplify much the
> > whole expression all that much.
> 
> It is still better to use in my opinion.

Ok.

> 
> > Is there perhaps a macro that
> > constructs a continuous bitmask of N bits, perhaps additionally
> > left-shifted by M bits?
> 
> > Maybe somewhere in the bitmap_* API...
> 
> Maybe, I dunno since I haven't clearly got this code anyway, so up to
> you to check and see what to do about it.

Right, I'll evaluate my options and come up with something.

> ...
> 
> > > > +       struct fwnode_handle *np;
> > >
> > >  Either be fully OF, or don’t name ‘np' here. We usually use fwnode or
> > > ‘child’ in this case.
> >
> > Ah, I thought "np" (= node pointer) was still appropriate because I'm
> > dealing with firmware _nodes_. My intention was indeed to switch fully
> > to the fwnode API.
> 
> Just a convention "de facto".

Ok, I'll change it.


> > > > +               ret = gpiochip_add_pin_range(&gpio->gc, dev_name(pctrl->dev),
> > > > +                                            0, bank->base, bank->length);
> > > > +               if (ret) {
> > > > +                       dev_err(pctrl->dev, "Failed to add pin range for GPIO bank %u\n", reg);
> > > > +                       return ret;
> > > > +               }
> > >
> > > Please move it to the corresponding callback.
> >
> > What's the corresponding callback?
> 
> https://elixir.bootlin.com/linux/latest/source/include/linux/gpio/driver.h#L400

Thanks.


Best regards,
Jonathan Neuschäfer

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v2 5/8] pinctrl: nuvoton: Add driver for WPCM450
@ 2021-12-12 23:02           ` Jonathan Neuschäfer
  0 siblings, 0 replies; 53+ messages in thread
From: Jonathan Neuschäfer @ 2021-12-12 23:02 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: devicetree, Tomer Maimon, openbmc, Jonathan Neuschäfer,
	linux-kernel, linux-gpio, Rob Herring, Linus Walleij

[-- Attachment #1: Type: text/plain, Size: 2023 bytes --]

On Wed, Dec 08, 2021 at 04:14:38PM +0200, Andy Shevchenko wrote:
> On Wed, Dec 8, 2021 at 3:58 PM Jonathan Neuschäfer <j.neuschaefer@gmx.net> wrote:
> > On Wed, Dec 08, 2021 at 01:24:18PM +0200, Andy Shevchenko wrote:
> > > On Tuesday, December 7, 2021, Jonathan Neuschäfer <j.neuschaefer@gmx.net>
> > > wrote:
> 
> ...
> 
> > > > +       ours = ((1UL << gpio->num_irqs) - 1) << gpio->first_irq_bit;
> > >
> > > BIT()
> >
> > I'll use it, but in this case, I think it doesn't simplify much the
> > whole expression all that much.
> 
> It is still better to use in my opinion.

Ok.

> 
> > Is there perhaps a macro that
> > constructs a continuous bitmask of N bits, perhaps additionally
> > left-shifted by M bits?
> 
> > Maybe somewhere in the bitmap_* API...
> 
> Maybe, I dunno since I haven't clearly got this code anyway, so up to
> you to check and see what to do about it.

Right, I'll evaluate my options and come up with something.

> ...
> 
> > > > +       struct fwnode_handle *np;
> > >
> > >  Either be fully OF, or don’t name ‘np' here. We usually use fwnode or
> > > ‘child’ in this case.
> >
> > Ah, I thought "np" (= node pointer) was still appropriate because I'm
> > dealing with firmware _nodes_. My intention was indeed to switch fully
> > to the fwnode API.
> 
> Just a convention "de facto".

Ok, I'll change it.


> > > > +               ret = gpiochip_add_pin_range(&gpio->gc, dev_name(pctrl->dev),
> > > > +                                            0, bank->base, bank->length);
> > > > +               if (ret) {
> > > > +                       dev_err(pctrl->dev, "Failed to add pin range for GPIO bank %u\n", reg);
> > > > +                       return ret;
> > > > +               }
> > >
> > > Please move it to the corresponding callback.
> >
> > What's the corresponding callback?
> 
> https://elixir.bootlin.com/linux/latest/source/include/linux/gpio/driver.h#L400

Thanks.


Best regards,
Jonathan Neuschäfer

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v2 5/8] pinctrl: nuvoton: Add driver for WPCM450
  2021-12-10  1:41           ` Linus Walleij
@ 2021-12-12 23:03             ` Jonathan Neuschäfer
  -1 siblings, 0 replies; 53+ messages in thread
From: Jonathan Neuschäfer @ 2021-12-12 23:03 UTC (permalink / raw)
  To: Linus Walleij
  Cc: zweiss, Jonathan Neuschäfer, Andy Shevchenko, devicetree,
	Tomer Maimon, openbmc, linux-kernel, linux-gpio, Rob Herring

[-- Attachment #1: Type: text/plain, Size: 1084 bytes --]

On Fri, Dec 10, 2021 at 02:41:45AM +0100, Linus Walleij wrote:
> On Thu, Dec 9, 2021 at 9:26 AM Zev Weiss <zweiss@equinix.com> wrote:
> > On Wed, Dec 08, 2021 at 05:58:30AM PST, Jonathan Neuschäfer wrote:
> 
> > >> BIT()
> > >
> > >I'll use it, but in this case, I think it doesn't simplify much the
> > >whole expression all that much. Is there perhaps a macro that
> > >constructs a continuous bitmask of N bits, perhaps additionally
> > >left-shifted by M bits?
> > >
> > >Maybe somewhere in the bitmap_* API...
> > >
> >
> > There's GENMASK(), though it takes a high bit and low bit rather than a
> > bit position and count, so it'd require a small bit of arithmetic, e.g.
> >
> >   lastbit = gpio->first_irq_bit + gpio->num_irqs - 1;
> >   ours = GENMASK(lastbit, gpio->first_irq_bit);
> >
> > or a manual shift:
> >
> >   ours = GENMASK(gpio->num_irqs - 1, 0) << gpio->first_irq_bit;
> 
> I think this can be handled with FIELD_PREP() from
> <linux/bitfield.h>? Some examples at the top of the
> header.

Thank you both!

Best regards,
Jonathan

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v2 5/8] pinctrl: nuvoton: Add driver for WPCM450
@ 2021-12-12 23:03             ` Jonathan Neuschäfer
  0 siblings, 0 replies; 53+ messages in thread
From: Jonathan Neuschäfer @ 2021-12-12 23:03 UTC (permalink / raw)
  To: Linus Walleij
  Cc: devicetree, Tomer Maimon, openbmc, Jonathan Neuschäfer,
	linux-kernel, linux-gpio, Andy Shevchenko, Rob Herring, zweiss

[-- Attachment #1: Type: text/plain, Size: 1084 bytes --]

On Fri, Dec 10, 2021 at 02:41:45AM +0100, Linus Walleij wrote:
> On Thu, Dec 9, 2021 at 9:26 AM Zev Weiss <zweiss@equinix.com> wrote:
> > On Wed, Dec 08, 2021 at 05:58:30AM PST, Jonathan Neuschäfer wrote:
> 
> > >> BIT()
> > >
> > >I'll use it, but in this case, I think it doesn't simplify much the
> > >whole expression all that much. Is there perhaps a macro that
> > >constructs a continuous bitmask of N bits, perhaps additionally
> > >left-shifted by M bits?
> > >
> > >Maybe somewhere in the bitmap_* API...
> > >
> >
> > There's GENMASK(), though it takes a high bit and low bit rather than a
> > bit position and count, so it'd require a small bit of arithmetic, e.g.
> >
> >   lastbit = gpio->first_irq_bit + gpio->num_irqs - 1;
> >   ours = GENMASK(lastbit, gpio->first_irq_bit);
> >
> > or a manual shift:
> >
> >   ours = GENMASK(gpio->num_irqs - 1, 0) << gpio->first_irq_bit;
> 
> I think this can be handled with FIELD_PREP() from
> <linux/bitfield.h>? Some examples at the top of the
> header.

Thank you both!

Best regards,
Jonathan

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v2 1/8] dt-bindings: arm/npcm: Add binding for global control registers (GCR)
  2021-12-10 14:54     ` Rob Herring
@ 2021-12-12 23:12       ` Jonathan Neuschäfer
  -1 siblings, 0 replies; 53+ messages in thread
From: Jonathan Neuschäfer @ 2021-12-12 23:12 UTC (permalink / raw)
  To: Rob Herring
  Cc: Jonathan Neuschäfer, linux-gpio, devicetree, Linus Walleij,
	openbmc, Tomer Maimon, Joel Stanley, linux-kernel, Avi Fishman,
	Tali Perry, Patrick Venture, Nancy Yuen, Benjamin Fair

[-- Attachment #1: Type: text/plain, Size: 1575 bytes --]

On Fri, Dec 10, 2021 at 08:54:33AM -0600, Rob Herring wrote:
> On Tue, Dec 07, 2021 at 10:08:16PM +0100, Jonathan Neuschäfer wrote:
> > A nuvoton,*-gcr node is present in nuvoton-common-npcm7xx.dtsi and will
> > be added to nuvoton-wpcm450.dtsi. It is necessary for the NPCM7xx and
> > WPCM450 pinctrl drivers, and may later be used to retrieve SoC model and
> > version information.
> > 
> > This patch adds a binding to describe this node.
> > 
> > Signed-off-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>
> > 
> > ---
[...]
> > +description: |
> 
> Don't need '|' if no formatting.

Ok, I'll drop it.

> > +  The Global Control Registers (GCR) are a block of registers in Nuvoton SoCs
> > +  that expose misc functionality such as chip model and version information or
> > +  pinmux settings.
> > +
> > +properties:
> > +  compatible:
> > +    items:
> > +      - enum:
> > +          - nuvoton,wpcm450-gcr
> > +          - nuvoton,npcm750-gcr
> > +      - const: syscon
> > +      - const: simple-mfd
> 
> blank line

I'll add it.

> > +  reg: true
> 
> Need to define how many entries:
> 
> maxItems: 1

Ok

> > +required:
> > +  - compatible
> > +  - reg
> > +
> > +additionalProperties: false

Ah, oops, I missed that I still had this line, when I added the child
node to the example.

> Ideally, you should define the child node names, but you can do this:
> 
> additionalProperties:
>   type: object
> 
> which means anything undefined must be a node.

Ok, makes sense, thanks.


Thanks,
Jonathan

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v2 1/8] dt-bindings: arm/npcm: Add binding for global control registers (GCR)
@ 2021-12-12 23:12       ` Jonathan Neuschäfer
  0 siblings, 0 replies; 53+ messages in thread
From: Jonathan Neuschäfer @ 2021-12-12 23:12 UTC (permalink / raw)
  To: Rob Herring
  Cc: devicetree, Tomer Maimon, Avi Fishman, Patrick Venture, openbmc,
	Jonathan Neuschäfer, linux-kernel, linux-gpio, Tali Perry,
	Linus Walleij, Benjamin Fair

[-- Attachment #1: Type: text/plain, Size: 1575 bytes --]

On Fri, Dec 10, 2021 at 08:54:33AM -0600, Rob Herring wrote:
> On Tue, Dec 07, 2021 at 10:08:16PM +0100, Jonathan Neuschäfer wrote:
> > A nuvoton,*-gcr node is present in nuvoton-common-npcm7xx.dtsi and will
> > be added to nuvoton-wpcm450.dtsi. It is necessary for the NPCM7xx and
> > WPCM450 pinctrl drivers, and may later be used to retrieve SoC model and
> > version information.
> > 
> > This patch adds a binding to describe this node.
> > 
> > Signed-off-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>
> > 
> > ---
[...]
> > +description: |
> 
> Don't need '|' if no formatting.

Ok, I'll drop it.

> > +  The Global Control Registers (GCR) are a block of registers in Nuvoton SoCs
> > +  that expose misc functionality such as chip model and version information or
> > +  pinmux settings.
> > +
> > +properties:
> > +  compatible:
> > +    items:
> > +      - enum:
> > +          - nuvoton,wpcm450-gcr
> > +          - nuvoton,npcm750-gcr
> > +      - const: syscon
> > +      - const: simple-mfd
> 
> blank line

I'll add it.

> > +  reg: true
> 
> Need to define how many entries:
> 
> maxItems: 1

Ok

> > +required:
> > +  - compatible
> > +  - reg
> > +
> > +additionalProperties: false

Ah, oops, I missed that I still had this line, when I added the child
node to the example.

> Ideally, you should define the child node names, but you can do this:
> 
> additionalProperties:
>   type: object
> 
> which means anything undefined must be a node.

Ok, makes sense, thanks.


Thanks,
Jonathan

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v2 4/8] dt-bindings: pinctrl: Add Nuvoton WPCM450
  2021-12-10 15:18     ` Rob Herring
@ 2021-12-12 23:38       ` Jonathan Neuschäfer
  -1 siblings, 0 replies; 53+ messages in thread
From: Jonathan Neuschäfer @ 2021-12-12 23:38 UTC (permalink / raw)
  To: Rob Herring
  Cc: Jonathan Neuschäfer, linux-gpio, devicetree, Linus Walleij,
	openbmc, Tomer Maimon, Joel Stanley, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 4743 bytes --]

Hello,

On Fri, Dec 10, 2021 at 09:18:01AM -0600, Rob Herring wrote:
> On Tue, Dec 07, 2021 at 10:08:19PM +0100, Jonathan Neuschäfer wrote:
> > This binding is heavily based on the one for NPCM7xx, because the
> > hardware is similar. There are some notable differences, however:
> > 
> > - The addresses of GPIO banks are not physical addresses but simple
> >   indices (0 to 7), because the GPIO registers are not laid out in
> >   convenient blocks.
> > - Pinmux settings can explicitly specify that the GPIO mode is used.
> > 
> > Certain pins support blink patterns in hardware. This is currently not
> > modelled in the DT binding.
> > 
> > Signed-off-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>
> > 
> > 
> > ---
[...]
> > +patternProperties:
> > +  # There are three kinds of subnodes:
> > +  # 1. a GPIO controller node for each GPIO bank
> > +  # 2. a pinmux node configures pin muxing for a group of pins (e.g. rmii2)
> > +  # 3. a pinconf node configures properties of a single pin
> > +
> > +  "^gpio@.*$":
> > +    if:
> 
> Not necessary because you can't have a property with '@' in it.

Ok, I'll change it to "^gpio".


> > +        interrupts:
> > +          maxItems: 4
> 
> Need to define what each interrupt is.

I think in this case one description for all interrupts would be more
useful, e.g.:

  interrupts:
    maxItems: 4
    description: The interrupts associated with this GPIO bank.


> > +        nuvoton,interrupt-map:
> 
> Reusing 'interrupt-map' with a different definition bothers me... 

I'm open to tweaking the name, perhaps to something like
nuvoton,gpio-interrupt-map. (Or dropping it entirely — see below.)


> > +  "^mux_.*$":
> 
> Use '-' rather than '_' and the '.*' is not necessary.
> 
> "^mux-"

Ok

> 
> > +    if:
> 
> Don't need this.

Ok, I'll remove the if/type/then lines throughout the file.


> > +        pins:
> > +          description:
> > +            A list of pins to configure in certain ways, such as enabling
> > +            debouncing
> > +          items:
> > +            enum: [ gpio0, gpio1, gpio2, gpio3, gpio4, gpio5, gpio6, gpio7,
> > +                    gpio8, gpio9, gpio10, gpio11, gpio12, gpio13, gpio14,
> > +                    gpio15, gpio16, gpio17, gpio18, gpio19, gpio20, gpio21,
> > +                    gpio22, gpio23, gpio24, gpio25, gpio26, gpio27, gpio28,
> > +                    gpio29, gpio30, gpio31, gpio32, gpio33, gpio34, gpio35,
> > +                    gpio36, gpio37, gpio38, gpio39, gpio40, gpio41, gpio42,
> > +                    gpio43, gpio44, gpio45, gpio46, gpio47, gpio48, gpio49,
> > +                    gpio50, gpio51, gpio52, gpio53, gpio54, gpio55, gpio56,
> > +                    gpio57, gpio58, gpio59, gpio60, gpio61, gpio62, gpio63,
> > +                    gpio64, gpio65, gpio66, gpio67, gpio68, gpio69, gpio70,
> > +                    gpio71, gpio72, gpio73, gpio74, gpio75, gpio76, gpio77,
> > +                    gpio78, gpio79, gpio80, gpio81, gpio82, gpio83, gpio84,
> > +                    gpio85, gpio86, gpio87, gpio88, gpio89, gpio90, gpio91,
> > +                    gpio92, gpio93, gpio94, gpio95, gpio96, gpio97, gpio98,
> > +                    gpio99, gpio100, gpio101, gpio102, gpio103, gpio104,
> > +                    gpio105, gpio106, gpio107, gpio108, gpio109, gpio110,
> > +                    gpio111, gpio112, gpio113, gpio114, gpio115, gpio116,
> > +                    gpio117, gpio118, gpio119, gpio120, gpio121, gpio122,
> > +                    gpio123, gpio124, gpio125, gpio126, gpio127 ]
> 
> pattern: '^gpio1?[0-9]{1,2}$'

Indeed, that looks better.

> Feel free to tweak it more to limit to 127 if you want.

Ok.


> > +      gpio0: gpio@0 {
> > +        reg = <0>;
> > +        gpio-controller;
> > +        #gpio-cells = <2>;
> > +        interrupts = <2 IRQ_TYPE_LEVEL_HIGH
> > +                      3 IRQ_TYPE_LEVEL_HIGH
> > +                      4 IRQ_TYPE_LEVEL_HIGH>;
> > +        nuvoton,interrupt-map = <0 16 0>;
> 
> Based on the example, you don't need this as it is 1:1.

Ah, it's a bad example. The real chip also has this node:


	gpio1: gpio@1 {
		reg = <1>;
		gpio-controller;
		#gpio-cells = <2>;
		interrupts = <5 IRQ_TYPE_LEVEL_HIGH>;
		interrupt-controller;
		nuvoton,interrupt-map = <16 2 8>;
	};

... meaning that bits 16 and 17 in the GPIO controller's interrupt
status register correspond to pins 8 and 9 of GPIO bank 1.

I'm not completely sure this is a good property to have in the
devicetree, I could also hide it in the driver (just like the register
offsets are not part of this binding).



Thanks,
Jonathan

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v2 4/8] dt-bindings: pinctrl: Add Nuvoton WPCM450
@ 2021-12-12 23:38       ` Jonathan Neuschäfer
  0 siblings, 0 replies; 53+ messages in thread
From: Jonathan Neuschäfer @ 2021-12-12 23:38 UTC (permalink / raw)
  To: Rob Herring
  Cc: devicetree, Tomer Maimon, openbmc, Jonathan Neuschäfer,
	linux-kernel, linux-gpio, Linus Walleij

[-- Attachment #1: Type: text/plain, Size: 4743 bytes --]

Hello,

On Fri, Dec 10, 2021 at 09:18:01AM -0600, Rob Herring wrote:
> On Tue, Dec 07, 2021 at 10:08:19PM +0100, Jonathan Neuschäfer wrote:
> > This binding is heavily based on the one for NPCM7xx, because the
> > hardware is similar. There are some notable differences, however:
> > 
> > - The addresses of GPIO banks are not physical addresses but simple
> >   indices (0 to 7), because the GPIO registers are not laid out in
> >   convenient blocks.
> > - Pinmux settings can explicitly specify that the GPIO mode is used.
> > 
> > Certain pins support blink patterns in hardware. This is currently not
> > modelled in the DT binding.
> > 
> > Signed-off-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>
> > 
> > 
> > ---
[...]
> > +patternProperties:
> > +  # There are three kinds of subnodes:
> > +  # 1. a GPIO controller node for each GPIO bank
> > +  # 2. a pinmux node configures pin muxing for a group of pins (e.g. rmii2)
> > +  # 3. a pinconf node configures properties of a single pin
> > +
> > +  "^gpio@.*$":
> > +    if:
> 
> Not necessary because you can't have a property with '@' in it.

Ok, I'll change it to "^gpio".


> > +        interrupts:
> > +          maxItems: 4
> 
> Need to define what each interrupt is.

I think in this case one description for all interrupts would be more
useful, e.g.:

  interrupts:
    maxItems: 4
    description: The interrupts associated with this GPIO bank.


> > +        nuvoton,interrupt-map:
> 
> Reusing 'interrupt-map' with a different definition bothers me... 

I'm open to tweaking the name, perhaps to something like
nuvoton,gpio-interrupt-map. (Or dropping it entirely — see below.)


> > +  "^mux_.*$":
> 
> Use '-' rather than '_' and the '.*' is not necessary.
> 
> "^mux-"

Ok

> 
> > +    if:
> 
> Don't need this.

Ok, I'll remove the if/type/then lines throughout the file.


> > +        pins:
> > +          description:
> > +            A list of pins to configure in certain ways, such as enabling
> > +            debouncing
> > +          items:
> > +            enum: [ gpio0, gpio1, gpio2, gpio3, gpio4, gpio5, gpio6, gpio7,
> > +                    gpio8, gpio9, gpio10, gpio11, gpio12, gpio13, gpio14,
> > +                    gpio15, gpio16, gpio17, gpio18, gpio19, gpio20, gpio21,
> > +                    gpio22, gpio23, gpio24, gpio25, gpio26, gpio27, gpio28,
> > +                    gpio29, gpio30, gpio31, gpio32, gpio33, gpio34, gpio35,
> > +                    gpio36, gpio37, gpio38, gpio39, gpio40, gpio41, gpio42,
> > +                    gpio43, gpio44, gpio45, gpio46, gpio47, gpio48, gpio49,
> > +                    gpio50, gpio51, gpio52, gpio53, gpio54, gpio55, gpio56,
> > +                    gpio57, gpio58, gpio59, gpio60, gpio61, gpio62, gpio63,
> > +                    gpio64, gpio65, gpio66, gpio67, gpio68, gpio69, gpio70,
> > +                    gpio71, gpio72, gpio73, gpio74, gpio75, gpio76, gpio77,
> > +                    gpio78, gpio79, gpio80, gpio81, gpio82, gpio83, gpio84,
> > +                    gpio85, gpio86, gpio87, gpio88, gpio89, gpio90, gpio91,
> > +                    gpio92, gpio93, gpio94, gpio95, gpio96, gpio97, gpio98,
> > +                    gpio99, gpio100, gpio101, gpio102, gpio103, gpio104,
> > +                    gpio105, gpio106, gpio107, gpio108, gpio109, gpio110,
> > +                    gpio111, gpio112, gpio113, gpio114, gpio115, gpio116,
> > +                    gpio117, gpio118, gpio119, gpio120, gpio121, gpio122,
> > +                    gpio123, gpio124, gpio125, gpio126, gpio127 ]
> 
> pattern: '^gpio1?[0-9]{1,2}$'

Indeed, that looks better.

> Feel free to tweak it more to limit to 127 if you want.

Ok.


> > +      gpio0: gpio@0 {
> > +        reg = <0>;
> > +        gpio-controller;
> > +        #gpio-cells = <2>;
> > +        interrupts = <2 IRQ_TYPE_LEVEL_HIGH
> > +                      3 IRQ_TYPE_LEVEL_HIGH
> > +                      4 IRQ_TYPE_LEVEL_HIGH>;
> > +        nuvoton,interrupt-map = <0 16 0>;
> 
> Based on the example, you don't need this as it is 1:1.

Ah, it's a bad example. The real chip also has this node:


	gpio1: gpio@1 {
		reg = <1>;
		gpio-controller;
		#gpio-cells = <2>;
		interrupts = <5 IRQ_TYPE_LEVEL_HIGH>;
		interrupt-controller;
		nuvoton,interrupt-map = <16 2 8>;
	};

... meaning that bits 16 and 17 in the GPIO controller's interrupt
status register correspond to pins 8 and 9 of GPIO bank 1.

I'm not completely sure this is a good property to have in the
devicetree, I could also hide it in the driver (just like the register
offsets are not part of this binding).



Thanks,
Jonathan

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v2 5/8] pinctrl: nuvoton: Add driver for WPCM450
@ 2021-12-19  1:24 kernel test robot
  0 siblings, 0 replies; 53+ messages in thread
From: kernel test robot @ 2021-12-19  1:24 UTC (permalink / raw)
  To: kbuild

[-- Attachment #1: Type: text/plain, Size: 15100 bytes --]

CC: llvm(a)lists.linux.dev
CC: kbuild-all(a)lists.01.org
In-Reply-To: <20211207210823.1975632-6-j.neuschaefer@gmx.net>
References: <20211207210823.1975632-6-j.neuschaefer@gmx.net>
TO: "Jonathan Neuschäfer" <j.neuschaefer@gmx.net>
TO: linux-gpio(a)vger.kernel.org
TO: devicetree(a)vger.kernel.org
CC: Linus Walleij <linus.walleij@linaro.org>
CC: Rob Herring <robh+dt@kernel.org>
CC: openbmc(a)lists.ozlabs.org
CC: Tomer Maimon <tmaimon77@gmail.com>
CC: Joel Stanley <joel@jms.id.au>
CC: linux-kernel(a)vger.kernel.org
CC: "Jonathan Neuschäfer" <j.neuschaefer@gmx.net>

Hi "Jonathan,

I love your patch! Perhaps something to improve:

[auto build test WARNING on linusw-pinctrl/devel]
[also build test WARNING on robh/for-next linus/master v5.16-rc5 next-20211217]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Jonathan-Neusch-fer/Nuvoton-WPCM450-pinctrl-and-GPIO-driver/20211208-051101
base:   https://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl.git devel
:::::: branch date: 11 days ago
:::::: commit date: 11 days ago
config: arm-randconfig-c002-20211209 (https://download.01.org/0day-ci/archive/20211219/202112190905.PgqrgXiI-lkp(a)intel.com/config)
compiler: clang version 14.0.0 (https://github.com/llvm/llvm-project 097a1cb1d5ebb3a0ec4bcaed8ba3ff6a8e33c00a)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # install arm cross compiling tool for clang build
        # apt-get install binutils-arm-linux-gnueabi
        # https://github.com/0day-ci/linux/commit/c08fb0aafb60234854aa86433da809fe5112f55e
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Jonathan-Neusch-fer/Nuvoton-WPCM450-pinctrl-and-GPIO-driver/20211208-051101
        git checkout c08fb0aafb60234854aa86433da809fe5112f55e
        # save the config file to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross ARCH=arm clang-analyzer 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>


clang-analyzer warnings: (new ones prefixed by >>)
           ^
   include/linux/printk.h:387:14: note: expanded from macro '__printk_index_emit'
                                   .level = __builtin_constant_p(_level) ? (_level) : NULL, \
                                            ^
   drivers/bus/intel-ixp4xx-eb.c:195:2: note: Loop condition is false.  Exiting loop
           dev_info(eb->dev, "CS%d at %#08x, size %#08x, config before: %#08x\n",
           ^
   include/linux/dev_printk.h:150:2: note: expanded from macro 'dev_info'
           dev_printk_index_wrap(_dev_info, KERN_INFO, dev, dev_fmt(fmt), ##__VA_ARGS__)
           ^
   include/linux/dev_printk.h:109:3: note: expanded from macro 'dev_printk_index_wrap'
                   dev_printk_index_emit(level, fmt);                      \
                   ^
   include/linux/dev_printk.h:105:2: note: expanded from macro 'dev_printk_index_emit'
           printk_index_subsys_emit("%s %s: ", level, fmt)
           ^
   include/linux/printk.h:417:2: note: expanded from macro 'printk_index_subsys_emit'
           __printk_index_emit(fmt, level, subsys_fmt_prefix)
           ^
   include/linux/printk.h:373:2: note: expanded from macro '__printk_index_emit'
           do {                                                            \
           ^
   drivers/bus/intel-ixp4xx-eb.c:200:15: note: '?' condition is false
           cur_cssize = roundup_pow_of_two(cur_cssize);
                        ^
   include/linux/log2.h:176:2: note: expanded from macro 'roundup_pow_of_two'
           __builtin_constant_p(n) ? (             \
           ^
   drivers/bus/intel-ixp4xx-eb.c:200:15: note: Calling '__roundup_pow_of_two'
           cur_cssize = roundup_pow_of_two(cur_cssize);
                        ^
   include/linux/log2.h:180:2: note: expanded from macro 'roundup_pow_of_two'
           __roundup_pow_of_two(n)                 \
           ^~~~~~~~~~~~~~~~~~~~~~~
   include/linux/log2.h:57:16: note: Calling 'fls_long'
           return 1UL << fls_long(n - 1);
                         ^~~~~~~~~~~~~~~
   include/linux/bitops.h:188:2: note: Taking true branch
           if (sizeof(l) == 4)
           ^
   include/linux/bitops.h:189:10: note: Calling 'fls'
                   return fls(l);
                          ^~~~~~
   include/asm-generic/bitops/fls.h:15:2: note: 'r' initialized to 32
           int r = 32;
           ^~~~~
   include/asm-generic/bitops/fls.h:17:6: note: Assuming 'x' is not equal to 0, which participates in a condition later
           if (!x)
               ^~
   include/asm-generic/bitops/fls.h:17:2: note: Taking false branch
           if (!x)
           ^
   include/asm-generic/bitops/fls.h:19:6: note: Assuming the condition is false
           if (!(x & 0xffff0000u)) {
               ^~~~~~~~~~~~~~~~~~
   include/asm-generic/bitops/fls.h:19:2: note: Taking false branch
           if (!(x & 0xffff0000u)) {
           ^
   include/asm-generic/bitops/fls.h:23:6: note: Assuming the condition is false
           if (!(x & 0xff000000u)) {
               ^~~~~~~~~~~~~~~~~~
   include/asm-generic/bitops/fls.h:23:2: note: Taking false branch
           if (!(x & 0xff000000u)) {
           ^
   include/asm-generic/bitops/fls.h:27:6: note: Assuming the condition is false
           if (!(x & 0xf0000000u)) {
               ^~~~~~~~~~~~~~~~~~
   include/asm-generic/bitops/fls.h:27:2: note: Taking false branch
           if (!(x & 0xf0000000u)) {
           ^
   include/asm-generic/bitops/fls.h:31:6: note: Assuming the condition is false
           if (!(x & 0xc0000000u)) {
               ^~~~~~~~~~~~~~~~~~
   include/asm-generic/bitops/fls.h:31:2: note: Taking false branch
           if (!(x & 0xc0000000u)) {
           ^
   include/asm-generic/bitops/fls.h:35:6: note: Assuming the condition is false
           if (!(x & 0x80000000u)) {
               ^~~~~~~~~~~~~~~~~~
   include/asm-generic/bitops/fls.h:35:2: note: Taking false branch
           if (!(x & 0x80000000u)) {
           ^
   include/asm-generic/bitops/fls.h:39:2: note: Returning the value 32 (loaded from 'r')
           return r;
           ^~~~~~~~
   include/linux/bitops.h:189:10: note: Returning from 'fls'
                   return fls(l);
                          ^~~~~~
   include/linux/bitops.h:189:3: note: Returning the value 32
                   return fls(l);
                   ^~~~~~~~~~~~~
   include/linux/log2.h:57:16: note: Returning from 'fls_long'
           return 1UL << fls_long(n - 1);
                         ^~~~~~~~~~~~~~~
   include/linux/log2.h:57:13: note: The result of the left shift is undefined due to shifting by '32', which is greater or equal to the width of type 'unsigned long'
           return 1UL << fls_long(n - 1);
                      ^  ~~~~~~~~~~~~~~~
   Suppressed 2 warnings (2 in non-user code).
   Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.
   10 warnings generated.
>> drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c:1562:26: warning: Value stored to 'npcm' during its initialization is never read [clang-analyzer-deadcode.DeadStores]
           struct npcm7xx_pinctrl *npcm = pinctrl_dev_get_drvdata(pctldev);
                                   ^~~~   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c:1562:26: note: Value stored to 'npcm' during its initialization is never read
           struct npcm7xx_pinctrl *npcm = pinctrl_dev_get_drvdata(pctldev);
                                   ^~~~   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c:1590:26: warning: Value stored to 'npcm' during its initialization is never read [clang-analyzer-deadcode.DeadStores]
           struct npcm7xx_pinctrl *npcm = pinctrl_dev_get_drvdata(pctldev);
                                   ^~~~   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c:1590:26: note: Value stored to 'npcm' during its initialization is never read
           struct npcm7xx_pinctrl *npcm = pinctrl_dev_get_drvdata(pctldev);
                                   ^~~~   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   Suppressed 8 warnings (8 in non-user code).
   Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.
   10 warnings generated.
   drivers/pinctrl/samsung/pinctrl-samsung.c:1065:19: warning: Assigned value is garbage or undefined [clang-analyzer-core.uninitialized.Assign]
                   bank->eint_base = virt_base[0];
                                   ^
   drivers/pinctrl/samsung/pinctrl-samsung.c:1102:6: note: Assuming 'drvdata' is non-null
           if (!drvdata)
               ^~~~~~~~
   drivers/pinctrl/samsung/pinctrl-samsung.c:1102:2: note: Taking false branch
           if (!drvdata)
           ^
   drivers/pinctrl/samsung/pinctrl-samsung.c:1105:9: note: Calling 'samsung_pinctrl_get_soc_data'
           ctrl = samsung_pinctrl_get_soc_data(drvdata, pdev);
                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/pinctrl/samsung/pinctrl-samsung.c:1019:9: note: Calling 'samsung_pinctrl_get_soc_data_for_of_alias'
           ctrl = samsung_pinctrl_get_soc_data_for_of_alias(pdev);
                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/pinctrl/samsung/pinctrl-samsung.c:991:6: note: Assuming 'id' is >= 0
           if (id < 0) {
               ^~~~~~
   drivers/pinctrl/samsung/pinctrl-samsung.c:991:2: note: Taking false branch
           if (id < 0) {
           ^
   drivers/pinctrl/samsung/pinctrl-samsung.c:997:6: note: Assuming 'id' is < field 'num_ctrl'
           if (id >= of_data->num_ctrl) {
               ^~~~~~~~~~~~~~~~~~~~~~~
   drivers/pinctrl/samsung/pinctrl-samsung.c:997:2: note: Taking false branch
           if (id >= of_data->num_ctrl) {
           ^
   drivers/pinctrl/samsung/pinctrl-samsung.c:1002:2: note: Returning pointer, which participates in a condition later
           return &(of_data->ctrl[id]);
           ^~~~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/pinctrl/samsung/pinctrl-samsung.c:1019:9: note: Returning from 'samsung_pinctrl_get_soc_data_for_of_alias'
           ctrl = samsung_pinctrl_get_soc_data_for_of_alias(pdev);
                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/pinctrl/samsung/pinctrl-samsung.c:1020:6: note: Assuming 'ctrl' is non-null
           if (!ctrl)
               ^~~~~
   drivers/pinctrl/samsung/pinctrl-samsung.c:1020:2: note: Taking false branch
           if (!ctrl)
           ^
   drivers/pinctrl/samsung/pinctrl-samsung.c:1026:17: note: Calling 'devm_kcalloc'
           d->pin_banks = devm_kcalloc(&pdev->dev, d->nr_banks,
                          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/device.h:223:9: note: Calling 'devm_kmalloc_array'
           return devm_kmalloc_array(dev, n, size, flags | __GFP_ZERO);
                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/device.h:215:2: note: Taking false branch
           if (unlikely(check_mul_overflow(n, size, &bytes)))
           ^
   include/linux/device.h:218:2: note: Returning pointer, which participates in a condition later
           return devm_kmalloc(dev, bytes, flags);
           ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/device.h:223:9: note: Returning from 'devm_kmalloc_array'
           return devm_kmalloc_array(dev, n, size, flags | __GFP_ZERO);
                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/device.h:223:2: note: Returning pointer, which participates in a condition later
           return devm_kmalloc_array(dev, n, size, flags | __GFP_ZERO);
           ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/pinctrl/samsung/pinctrl-samsung.c:1026:17: note: Returning from 'devm_kcalloc'
           d->pin_banks = devm_kcalloc(&pdev->dev, d->nr_banks,
                          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/pinctrl/samsung/pinctrl-samsung.c:1028:6: note: Assuming field 'pin_banks' is non-null
           if (!d->pin_banks)
               ^~~~~~~~~~~~~
   drivers/pinctrl/samsung/pinctrl-samsung.c:1028:2: note: Taking false branch
           if (!d->pin_banks)
           ^
   drivers/pinctrl/samsung/pinctrl-samsung.c:1031:6: note: Assuming the condition is false
           if (ctrl->nr_ext_resources + 1 > SAMSUNG_PINCTRL_NUM_RESOURCES)
               ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/pinctrl/samsung/pinctrl-samsung.c:1031:2: note: Taking false branch
           if (ctrl->nr_ext_resources + 1 > SAMSUNG_PINCTRL_NUM_RESOURCES)
           ^
   drivers/pinctrl/samsung/pinctrl-samsung.c:1034:14: note: Assuming the condition is false
           for (i = 0; i < ctrl->nr_ext_resources + 1; i++) {
                       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/pinctrl/samsung/pinctrl-samsung.c:1034:2: note: Loop condition is false. Execution continues on line 1048
           for (i = 0; i < ctrl->nr_ext_resources + 1; i++) {
           ^
   drivers/pinctrl/samsung/pinctrl-samsung.c:1050:14: note: Assuming 'i' is < field 'nr_banks'
           for (i = 0; i < ctrl->nr_banks; ++i, ++bdata, ++bank) {
                       ^~~~~~~~~~~~~~~~~~
   drivers/pinctrl/samsung/pinctrl-samsung.c:1050:2: note: Loop condition is true.  Entering loop body
           for (i = 0; i < ctrl->nr_banks; ++i, ++bdata, ++bank) {
           ^
   drivers/pinctrl/samsung/pinctrl-samsung.c:1060:3: note: Loop condition is false.  Exiting loop
                   raw_spin_lock_init(&bank->slock);

vim +/npcm +1562 drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c

3b588e43ee5c7a Tomer Maimon 2018-08-08  1559  
3b588e43ee5c7a Tomer Maimon 2018-08-08  1560  static int npcm7xx_get_groups_count(struct pinctrl_dev *pctldev)
3b588e43ee5c7a Tomer Maimon 2018-08-08  1561  {
3b588e43ee5c7a Tomer Maimon 2018-08-08 @1562  	struct npcm7xx_pinctrl *npcm = pinctrl_dev_get_drvdata(pctldev);
3b588e43ee5c7a Tomer Maimon 2018-08-08  1563  
3b588e43ee5c7a Tomer Maimon 2018-08-08  1564  	dev_dbg(npcm->dev, "group size: %d\n", ARRAY_SIZE(npcm7xx_groups));
3b588e43ee5c7a Tomer Maimon 2018-08-08  1565  	return ARRAY_SIZE(npcm7xx_groups);
3b588e43ee5c7a Tomer Maimon 2018-08-08  1566  }
3b588e43ee5c7a Tomer Maimon 2018-08-08  1567  

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org

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

* Re: [PATCH v2 5/8] pinctrl: nuvoton: Add driver for WPCM450
@ 2021-12-09 18:40 kernel test robot
  0 siblings, 0 replies; 53+ messages in thread
From: kernel test robot @ 2021-12-09 18:40 UTC (permalink / raw)
  To: kbuild

[-- Attachment #1: Type: text/plain, Size: 28782 bytes --]

CC: kbuild-all(a)lists.01.org
In-Reply-To: <20211207210823.1975632-6-j.neuschaefer@gmx.net>
References: <20211207210823.1975632-6-j.neuschaefer@gmx.net>
TO: "Jonathan Neuschäfer" <j.neuschaefer@gmx.net>
TO: linux-gpio(a)vger.kernel.org
TO: devicetree(a)vger.kernel.org
CC: Linus Walleij <linus.walleij@linaro.org>
CC: Rob Herring <robh+dt@kernel.org>
CC: openbmc(a)lists.ozlabs.org
CC: Tomer Maimon <tmaimon77@gmail.com>
CC: Joel Stanley <joel@jms.id.au>
CC: linux-kernel(a)vger.kernel.org
CC: "Jonathan Neuschäfer" <j.neuschaefer@gmx.net>

Hi "Jonathan,

I love your patch! Perhaps something to improve:

[auto build test WARNING on linusw-pinctrl/devel]
[also build test WARNING on robh/for-next linus/master v5.16-rc4 next-20211208]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Jonathan-Neusch-fer/Nuvoton-WPCM450-pinctrl-and-GPIO-driver/20211208-051101
base:   https://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl.git devel
:::::: branch date: 2 days ago
:::::: commit date: 2 days ago
config: arm-randconfig-s031-20211209 (https://download.01.org/0day-ci/archive/20211210/202112100257.YCgv17TU-lkp(a)intel.com/config)
compiler: arm-linux-gnueabi-gcc (GCC) 11.2.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # apt-get install sparse
        # sparse version: v0.6.4-dirty
        # https://github.com/0day-ci/linux/commit/c08fb0aafb60234854aa86433da809fe5112f55e
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Jonathan-Neusch-fer/Nuvoton-WPCM450-pinctrl-and-GPIO-driver/20211208-051101
        git checkout c08fb0aafb60234854aa86433da809fe5112f55e
        # save the config file to linux build tree
        mkdir build_dir
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' O=build_dir ARCH=arm SHELL=/bin/bash drivers/net/bonding/ drivers/net/dsa/ drivers/pinctrl/nuvoton/

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>


sparse warnings: (new ones prefixed by >>)
>> drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:592:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:593:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:594:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:595:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:596:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:597:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:598:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:599:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:600:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:601:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:602:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:603:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:604:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:605:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:606:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:607:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:608:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:609:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:610:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:611:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:612:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:613:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:614:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:615:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:616:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:617:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:618:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:619:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:620:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:621:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:622:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:623:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:625:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:626:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:627:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:628:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:629:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:630:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:631:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:632:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:633:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:634:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:635:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:636:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:637:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:638:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:639:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:640:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:641:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:642:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:643:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:644:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:645:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:646:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:647:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:648:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:649:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:650:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:651:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:652:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:653:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:654:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:655:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:656:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:658:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:659:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:660:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:661:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:662:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:663:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:664:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:665:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:666:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:667:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:668:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:669:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:670:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:671:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:672:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:673:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:674:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:675:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:676:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:677:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:678:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:679:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:680:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:681:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:682:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:683:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:684:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:685:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:686:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:687:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:688:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:689:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:691:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:692:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:693:9: sparse: sparse: obsolete array initializer, use C99 syntax
   drivers/pinctrl/nuvoton/pinctrl-wpcm450.c:694:9: sparse: sparse: too many warnings

vim +592 drivers/pinctrl/nuvoton/pinctrl-wpcm450.c

c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  589  
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  590  static const struct wpcm450_pincfg pincfg[] = {
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  591  	/*		PIN	  FUNCTION 1		   FUNCTION 2 */
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07 @592  	WPCM450_PINCFG(0,	 none, NONE, 0,		  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  593  	WPCM450_PINCFG(1,	 none, NONE, 0,		  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  594  	WPCM450_PINCFG(2,	 none, NONE, 0,		  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  595  	WPCM450_PINCFG(3,	 none, NONE, 0,		  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  596  	WPCM450_PINCFG(4,	 none, NONE, 0,		  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  597  	WPCM450_PINCFG(5,	 none, NONE, 0,		  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  598  	WPCM450_PINCFG(6,	 none, NONE, 0,		  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  599  	WPCM450_PINCFG(7,	 none, NONE, 0,		  sdio, MFSEL1, 30),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  600  	WPCM450_PINCFG(8,	 none, NONE, 0,		  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  601  	WPCM450_PINCFG(9,	 none, NONE, 0,		  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  602  	WPCM450_PINCFG(10,	 none, NONE, 0,		  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  603  	WPCM450_PINCFG(11,	 none, NONE, 0,		  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  604  	WPCM450_PINCFG(12,	 gspi, MFSEL1, 24,	  sspi, MFSEL1, 31),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  605  	WPCM450_PINCFG(13,	 gspi, MFSEL1, 24,	  sspi, MFSEL1, 31),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  606  	WPCM450_PINCFG(14,	 gspi, MFSEL1, 24,	  sspi, MFSEL1, 31),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  607  	WPCM450_PINCFG(15,	 gspi, MFSEL1, 24,	  sspi, MFSEL1, 31),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  608  	WPCM450_PINCFG(16,	 none, NONE, 0,		  pwm6, MFSEL2, 22),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  609  	WPCM450_PINCFG(17,	 none, NONE, 0,		  pwm7, MFSEL2, 23),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  610  	WPCM450_PINCFG(18,	 none, NONE, 0,		  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  611  	WPCM450_PINCFG(19,	 uinc, MFSEL1, 23,	  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  612  	WPCM450_PINCFG(20,	  hg0, MFSEL2, 24,	  pwm4, MFSEL2, 20),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  613  	WPCM450_PINCFG(21,	  hg1, MFSEL2, 25,	  pwm5, MFSEL2, 21),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  614  	WPCM450_PINCFG(22,	  hg2, MFSEL2, 26,	  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  615  	WPCM450_PINCFG(23,	  hg3, MFSEL2, 27,	  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  616  	WPCM450_PINCFG(24,	  hg4, MFSEL2, 28,	  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  617  	WPCM450_PINCFG(25,	  hg5, MFSEL2, 29,	  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  618  	WPCM450_PINCFG(26,	 smb5, MFSEL1, 2,	  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  619  	WPCM450_PINCFG(27,	 smb5, MFSEL1, 2,	  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  620  	WPCM450_PINCFG(28,	 smb4, MFSEL1, 1,	  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  621  	WPCM450_PINCFG(29,	 smb4, MFSEL1, 1,	  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  622  	WPCM450_PINCFG(30,	 smb3, MFSEL1, 0,	  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  623  	WPCM450_PINCFG(31,	 smb3, MFSEL1, 0,	  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  624  
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  625  	WPCM450_PINCFG(32,	 scs1, MFSEL1, 3,	  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  626  	WPCM450_PINCFG(33,	 scs2, MFSEL1, 4,	  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  627  	WPCM450_PINCFG(34,	 scs3, MFSEL1, 5,	  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  628  	WPCM450_PINCFG(35,	 xcs1, MFSEL1, 29,	  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  629  	WPCM450_PINCFG(36,	 xcs2, MFSEL1, 28,	  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  630  	WPCM450_PINCFG(37,	 none, NONE, 0,		  none, NONE, 0), /* DVO */
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  631  	WPCM450_PINCFG(38,	 none, NONE, 0,		  none, NONE, 0), /* DVO */
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  632  	WPCM450_PINCFG(39,	 none, NONE, 0,		  none, NONE, 0), /* DVO */
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  633  	WPCM450_PINCFG(40,	 none, NONE, 0,		  none, NONE, 0), /* DVO */
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  634  	WPCM450_PINCFG(41,	  bsp, MFSEL1, 9,	  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  635  	WPCM450_PINCFG(42,	  bsp, MFSEL1, 9,	  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  636  	WPCM450_PINCFG(43,	 hsp1, MFSEL1, 10,	  sdio, MFSEL1, 30),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  637  	WPCM450_PINCFG(44,	 hsp1, MFSEL1, 10,	  sdio, MFSEL1, 30),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  638  	WPCM450_PINCFG(45,	 hsp1, MFSEL1, 10,	  sdio, MFSEL1, 30),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  639  	WPCM450_PINCFG(46,	 hsp1, MFSEL1, 10,	  sdio, MFSEL1, 30),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  640  	WPCM450_PINCFG(47,	 hsp1, MFSEL1, 10,	  sdio, MFSEL1, 30),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  641  	WPCM450_PINCFG(48,	 hsp2, MFSEL1, 11,	  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  642  	WPCM450_PINCFG(49,	 hsp2, MFSEL1, 11,	  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  643  	WPCM450_PINCFG(50,	 hsp2, MFSEL1, 11,	  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  644  	WPCM450_PINCFG(51,	 hsp2, MFSEL1, 11,	  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  645  	WPCM450_PINCFG(52,	 hsp2, MFSEL1, 11,	  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  646  	WPCM450_PINCFG(53,	 hsp2, MFSEL1, 11,	  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  647  	WPCM450_PINCFG(54,	 hsp2, MFSEL1, 11,	  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  648  	WPCM450_PINCFG(55,	 hsp2, MFSEL1, 11,	  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  649  	WPCM450_PINCFG(56,	r1err, MFSEL1, 12,	  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  650  	WPCM450_PINCFG(57,	 r1md, MFSEL1, 13,	  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  651  	WPCM450_PINCFG(58,	 r1md, MFSEL1, 13,	  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  652  	WPCM450_PINCFG(59,	  hg6, MFSEL2, 30,	  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  653  	WPCM450_PINCFG(60,	  hg7, MFSEL2, 31,	  sdio, MFSEL1, 30),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  654  	WPCM450_PINCFG(61,	 hsp1, MFSEL1, 10,	  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  655  	WPCM450_PINCFG(62,	 hsp1, MFSEL1, 10,	  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  656  	WPCM450_PINCFG(63,	 hsp1, MFSEL1, 10,	  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  657  
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  658  	WPCM450_PINCFG(64,	  fi0, MFSEL2, 0,	  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  659  	WPCM450_PINCFG(65,	  fi1, MFSEL2, 1,	  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  660  	WPCM450_PINCFG(66,	  fi2, MFSEL2, 2,	  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  661  	WPCM450_PINCFG(67,	  fi3, MFSEL2, 3,	  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  662  	WPCM450_PINCFG(68,	  fi4, MFSEL2, 4,	  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  663  	WPCM450_PINCFG(69,	  fi5, MFSEL2, 5,	  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  664  	WPCM450_PINCFG(70,	  fi6, MFSEL2, 6,	  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  665  	WPCM450_PINCFG(71,	  fi7, MFSEL2, 7,	  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  666  	WPCM450_PINCFG(72,	  fi8, MFSEL2, 8,	  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  667  	WPCM450_PINCFG(73,	  fi9, MFSEL2, 9,	  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  668  	WPCM450_PINCFG(74,	 fi10, MFSEL2, 10,	  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  669  	WPCM450_PINCFG(75,	 fi11, MFSEL2, 11,	  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  670  	WPCM450_PINCFG(76,	 fi12, MFSEL2, 12,	  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  671  	WPCM450_PINCFG(77,	 fi13, MFSEL2, 13,	  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  672  	WPCM450_PINCFG(78,	 fi14, MFSEL2, 14,	  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  673  	WPCM450_PINCFG(79,	 fi15, MFSEL2, 15,	  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  674  	WPCM450_PINCFG(80,	 pwm0, MFSEL2, 16,	  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  675  	WPCM450_PINCFG(81,	 pwm1, MFSEL2, 17,	  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  676  	WPCM450_PINCFG(82,	 pwm2, MFSEL2, 18,	  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  677  	WPCM450_PINCFG(83,	 pwm3, MFSEL2, 19,	  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  678  	WPCM450_PINCFG(84,	rmii2, MFSEL1, 14,	  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  679  	WPCM450_PINCFG(85,	rmii2, MFSEL1, 14,	  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  680  	WPCM450_PINCFG(86,	rmii2, MFSEL1, 14,	  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  681  	WPCM450_PINCFG(87,	rmii2, MFSEL1, 14,	  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  682  	WPCM450_PINCFG(88,	rmii2, MFSEL1, 14,	  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  683  	WPCM450_PINCFG(89,	rmii2, MFSEL1, 14,	  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  684  	WPCM450_PINCFG(90,	r2err, MFSEL1, 15,	  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  685  	WPCM450_PINCFG(91,	 r2md, MFSEL1, 16,	  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  686  	WPCM450_PINCFG(92,	 r2md, MFSEL1, 16,	  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  687  	WPCM450_PINCFG(93,	 kbcc, MFSEL1, 17,	  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  688  	WPCM450_PINCFG(94,	 kbcc, MFSEL1, 17,	  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  689  	WPCM450_PINCFG(95,	 none, NONE, 0,		  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  690  
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  691  	WPCM450_PINCFG(96,	 none, NONE, 0,		  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  692  	WPCM450_PINCFG(97,	 none, NONE, 0,		  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  693  	WPCM450_PINCFG(98,	 none, NONE, 0,		  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  694  	WPCM450_PINCFG(99,	 none, NONE, 0,		  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  695  	WPCM450_PINCFG(100,	 none, NONE, 0,		  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  696  	WPCM450_PINCFG(101,	 none, NONE, 0,		  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  697  	WPCM450_PINCFG(102,	 none, NONE, 0,		  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  698  	WPCM450_PINCFG(103,	 none, NONE, 0,		  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  699  	WPCM450_PINCFG(104,	 none, NONE, 0,		  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  700  	WPCM450_PINCFG(105,	 none, NONE, 0,		  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  701  	WPCM450_PINCFG(106,	 none, NONE, 0,		  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  702  	WPCM450_PINCFG(107,	 none, NONE, 0,		  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  703  	WPCM450_PINCFG(108,	 none, NONE, 0,		  none, NONE, 0), /* DVO */
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  704  	WPCM450_PINCFG(109,	 none, NONE, 0,		  none, NONE, 0), /* DVO */
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  705  	WPCM450_PINCFG(110,	 none, NONE, 0,		  none, NONE, 0), /* DVO */
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  706  	WPCM450_PINCFG(111,	 none, NONE, 0,		  none, NONE, 0), /* DVO */
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  707  	WPCM450_PINCFG(112,	 none, NONE, 0,		  none, NONE, 0), /* DVO */
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  708  	WPCM450_PINCFG(113,	 none, NONE, 0,		  none, NONE, 0), /* DVO */
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  709  	WPCM450_PINCFG(114,	 smb0, MFSEL1, 6,	  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  710  	WPCM450_PINCFG(115,	 smb0, MFSEL1, 6,	  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  711  	WPCM450_PINCFG(116,	 smb1, MFSEL1, 7,	  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  712  	WPCM450_PINCFG(117,	 smb1, MFSEL1, 7,	  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  713  	WPCM450_PINCFG(118,	 smb2, MFSEL1, 8,	  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  714  	WPCM450_PINCFG(119,	 smb2, MFSEL1, 8,	  none, NONE, 0),
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  715  	WPCM450_PINCFG(120,	 none, NONE, 0,		  none, NONE, 0), /* DVO */
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  716  	WPCM450_PINCFG(121,	 none, NONE, 0,		  none, NONE, 0), /* DVO */
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  717  	WPCM450_PINCFG(122,	 none, NONE, 0,		  none, NONE, 0), /* DVO */
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  718  	WPCM450_PINCFG(123,	 none, NONE, 0,		  none, NONE, 0), /* DVO */
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  719  	WPCM450_PINCFG(124,	 none, NONE, 0,		  none, NONE, 0), /* DVO */
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  720  	WPCM450_PINCFG(125,	 none, NONE, 0,		  none, NONE, 0), /* DVO */
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  721  	WPCM450_PINCFG(126,	 none, NONE, 0,		  none, NONE, 0), /* DVO */
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  722  	WPCM450_PINCFG(127,	 none, NONE, 0,		  none, NONE, 0), /* DVO */
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  723  };
c08fb0aafb60234 Jonathan Neuschäfer 2021-12-07  724  

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org

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

end of thread, other threads:[~2021-12-19  1:24 UTC | newest]

Thread overview: 53+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-12-07 21:08 [PATCH v2 0/8] Nuvoton WPCM450 pinctrl and GPIO driver Jonathan Neuschäfer
2021-12-07 21:08 ` Jonathan Neuschäfer
2021-12-07 21:08 ` [PATCH v2 1/8] dt-bindings: arm/npcm: Add binding for global control registers (GCR) Jonathan Neuschäfer
2021-12-07 21:08   ` Jonathan Neuschäfer
2021-12-08 13:44   ` Rob Herring
2021-12-08 13:44     ` Rob Herring
2021-12-10 14:54   ` Rob Herring
2021-12-10 14:54     ` Rob Herring
2021-12-12 23:12     ` Jonathan Neuschäfer
2021-12-12 23:12       ` Jonathan Neuschäfer
2021-12-07 21:08 ` [PATCH v2 2/8] MAINTAINERS: Match all of bindings/arm/npcm/ as part of NPCM architecture Jonathan Neuschäfer
2021-12-07 21:08   ` Jonathan Neuschäfer
2021-12-07 21:08 ` [PATCH v2 3/8] ARM: dts: wpcm450: Add global control registers (GCR) node Jonathan Neuschäfer
2021-12-07 21:08   ` Jonathan Neuschäfer
2021-12-07 21:08 ` [PATCH v2 4/8] dt-bindings: pinctrl: Add Nuvoton WPCM450 Jonathan Neuschäfer
2021-12-07 21:08   ` Jonathan Neuschäfer
2021-12-08 13:44   ` Rob Herring
2021-12-08 13:44     ` Rob Herring
2021-12-10 15:18   ` Rob Herring
2021-12-10 15:18     ` Rob Herring
2021-12-12 23:38     ` Jonathan Neuschäfer
2021-12-12 23:38       ` Jonathan Neuschäfer
2021-12-07 21:08 ` [PATCH v2 5/8] pinctrl: nuvoton: Add driver for WPCM450 Jonathan Neuschäfer
2021-12-07 21:08   ` Jonathan Neuschäfer
2021-12-08  0:51   ` kernel test robot
2021-12-08  0:51     ` kernel test robot
2021-12-08  0:51     ` kernel test robot
2021-12-08  2:34   ` kernel test robot
2021-12-08  2:34     ` kernel test robot
2021-12-08  2:34     ` kernel test robot
2021-12-08 11:24   ` Andy Shevchenko
2021-12-08 13:58     ` Jonathan Neuschäfer
2021-12-08 13:58       ` Jonathan Neuschäfer
2021-12-08 14:14       ` Andy Shevchenko
2021-12-08 14:14         ` Andy Shevchenko
2021-12-12 23:02         ` Jonathan Neuschäfer
2021-12-12 23:02           ` Jonathan Neuschäfer
2021-12-09  8:26       ` Zev Weiss
2021-12-09  8:26         ` Zev Weiss
2021-12-10  1:41         ` Linus Walleij
2021-12-10  1:41           ` Linus Walleij
2021-12-12 23:03           ` Jonathan Neuschäfer
2021-12-12 23:03             ` Jonathan Neuschäfer
2021-12-07 21:08 ` [PATCH v2 6/8] ARM: dts: wpcm450: Add pinctrl and GPIO nodes Jonathan Neuschäfer
2021-12-07 21:08   ` Jonathan Neuschäfer
2021-12-10  1:42   ` Linus Walleij
2021-12-10  1:42     ` Linus Walleij
2021-12-07 21:08 ` [PATCH v2 7/8] ARM: dts: wpcm450: Add pin functions Jonathan Neuschäfer
2021-12-07 21:08   ` Jonathan Neuschäfer
2021-12-07 21:08 ` [PATCH v2 8/8] ARM: dts: wpcm450-supermicro-x9sci-ln4f: Add GPIO LEDs and buttons Jonathan Neuschäfer
2021-12-07 21:08   ` Jonathan Neuschäfer
2021-12-09 18:40 [PATCH v2 5/8] pinctrl: nuvoton: Add driver for WPCM450 kernel test robot
2021-12-19  1:24 kernel test robot

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.