All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/6] pinctrl: sunxi: Allwinner D1/D1s support
@ 2022-06-26  2:11 ` Samuel Holland
  0 siblings, 0 replies; 56+ messages in thread
From: Samuel Holland @ 2022-06-26  2:11 UTC (permalink / raw)
  To: Chen-Yu Tsai, Jernej Skrabec, Linus Walleij
  Cc: Samuel Holland, Krzysztof Kozlowski, Maxime Ripard,
	Ondrej Jirman, Rob Herring, devicetree, linux-arm-kernel,
	linux-gpio, linux-kernel, linux-sunxi

This series adds pinctrl support for the Allwinner D1/D1s SoCs. First,
it updates the I/O bias code to support the new mode found on the D1/D1s
(as well as some existing SoCs). Then it refactors the driver to support
the new register layout found on the D1/D1s. Finally, it adds the new
driver.

The code size impact of the dynamic register layout ends up being just
over 100 bytes:

   text    data     bss     dec     hex filename
  11293     564       0   11857    2e51 pinctrl-sunxi.o (patch 3)
  11405     564       0   11969    2ec1 pinctrl-sunxi.o (patch 6)

This series was tested on A64, H6, and D1.


Samuel Holland (6):
  dt-bindings: pinctrl: Add compatibles for Allwinner D1/D1s
  pinctrl: sunxi: Add I/O bias setting for H6 R-PIO
  pinctrl: sunxi: Support the 2.5V I/O bias mode
  pinctrl: sunxi: Refactor register/offset calculation
  pinctrl: sunxi: Make some layout parameters dynamic
  pinctrl: sunxi: Add driver for Allwinner D1/D1s

 .../pinctrl/allwinner,sun4i-a10-pinctrl.yaml  |  15 +
 drivers/pinctrl/sunxi/Kconfig                 |   5 +
 drivers/pinctrl/sunxi/Makefile                |   1 +
 drivers/pinctrl/sunxi/pinctrl-sun20i-d1.c     | 860 ++++++++++++++++++
 drivers/pinctrl/sunxi/pinctrl-sun50i-a100-r.c |   1 +
 drivers/pinctrl/sunxi/pinctrl-sun50i-a100.c   |   2 +-
 drivers/pinctrl/sunxi/pinctrl-sun50i-h6-r.c   |   1 +
 drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c   |   2 +-
 drivers/pinctrl/sunxi/pinctrl-sunxi.c         | 156 +++-
 drivers/pinctrl/sunxi/pinctrl-sunxi.h         | 110 +--
 10 files changed, 1022 insertions(+), 131 deletions(-)
 create mode 100644 drivers/pinctrl/sunxi/pinctrl-sun20i-d1.c

-- 
2.35.1


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

* [PATCH 0/6] pinctrl: sunxi: Allwinner D1/D1s support
@ 2022-06-26  2:11 ` Samuel Holland
  0 siblings, 0 replies; 56+ messages in thread
From: Samuel Holland @ 2022-06-26  2:11 UTC (permalink / raw)
  To: Chen-Yu Tsai, Jernej Skrabec, Linus Walleij
  Cc: Samuel Holland, Krzysztof Kozlowski, Maxime Ripard,
	Ondrej Jirman, Rob Herring, devicetree, linux-arm-kernel,
	linux-gpio, linux-kernel, linux-sunxi

This series adds pinctrl support for the Allwinner D1/D1s SoCs. First,
it updates the I/O bias code to support the new mode found on the D1/D1s
(as well as some existing SoCs). Then it refactors the driver to support
the new register layout found on the D1/D1s. Finally, it adds the new
driver.

The code size impact of the dynamic register layout ends up being just
over 100 bytes:

   text    data     bss     dec     hex filename
  11293     564       0   11857    2e51 pinctrl-sunxi.o (patch 3)
  11405     564       0   11969    2ec1 pinctrl-sunxi.o (patch 6)

This series was tested on A64, H6, and D1.


Samuel Holland (6):
  dt-bindings: pinctrl: Add compatibles for Allwinner D1/D1s
  pinctrl: sunxi: Add I/O bias setting for H6 R-PIO
  pinctrl: sunxi: Support the 2.5V I/O bias mode
  pinctrl: sunxi: Refactor register/offset calculation
  pinctrl: sunxi: Make some layout parameters dynamic
  pinctrl: sunxi: Add driver for Allwinner D1/D1s

 .../pinctrl/allwinner,sun4i-a10-pinctrl.yaml  |  15 +
 drivers/pinctrl/sunxi/Kconfig                 |   5 +
 drivers/pinctrl/sunxi/Makefile                |   1 +
 drivers/pinctrl/sunxi/pinctrl-sun20i-d1.c     | 860 ++++++++++++++++++
 drivers/pinctrl/sunxi/pinctrl-sun50i-a100-r.c |   1 +
 drivers/pinctrl/sunxi/pinctrl-sun50i-a100.c   |   2 +-
 drivers/pinctrl/sunxi/pinctrl-sun50i-h6-r.c   |   1 +
 drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c   |   2 +-
 drivers/pinctrl/sunxi/pinctrl-sunxi.c         | 156 +++-
 drivers/pinctrl/sunxi/pinctrl-sunxi.h         | 110 +--
 10 files changed, 1022 insertions(+), 131 deletions(-)
 create mode 100644 drivers/pinctrl/sunxi/pinctrl-sun20i-d1.c

-- 
2.35.1


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

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

* [PATCH 1/6] dt-bindings: pinctrl: Add compatibles for Allwinner D1/D1s
  2022-06-26  2:11 ` Samuel Holland
@ 2022-06-26  2:11   ` Samuel Holland
  -1 siblings, 0 replies; 56+ messages in thread
From: Samuel Holland @ 2022-06-26  2:11 UTC (permalink / raw)
  To: Chen-Yu Tsai, Jernej Skrabec, Linus Walleij
  Cc: Samuel Holland, Krzysztof Kozlowski, Maxime Ripard,
	Ondrej Jirman, Rob Herring, devicetree, linux-arm-kernel,
	linux-gpio, linux-kernel, linux-sunxi

D1 contains a pin controller similar to previous SoCs, but with some
register layout changes. It includes 6 interrupt-capable pin banks.

D1s is a low pin count version of the D1 SoC, with some pins omitted.
The remaining pins have the same function assignments as D1.

Signed-off-by: Samuel Holland <samuel@sholland.org>
---

 .../pinctrl/allwinner,sun4i-a10-pinctrl.yaml      | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/Documentation/devicetree/bindings/pinctrl/allwinner,sun4i-a10-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/allwinner,sun4i-a10-pinctrl.yaml
index bfce850c2035..3da52814f151 100644
--- a/Documentation/devicetree/bindings/pinctrl/allwinner,sun4i-a10-pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/allwinner,sun4i-a10-pinctrl.yaml
@@ -46,6 +46,8 @@ properties:
       - allwinner,sun8i-v3s-pinctrl
       - allwinner,sun9i-a80-pinctrl
       - allwinner,sun9i-a80-r-pinctrl
+      - allwinner,sun20i-d1-pinctrl
+      - allwinner,sun20i-d1s-pinctrl
       - allwinner,sun50i-a64-pinctrl
       - allwinner,sun50i-a64-r-pinctrl
       - allwinner,sun50i-a100-pinctrl
@@ -171,6 +173,19 @@ allOf:
           minItems: 7
           maxItems: 7
 
+  - if:
+      properties:
+        compatible:
+          enum:
+            - allwinner,sun20i-d1-pinctrl
+            - allwinner,sun20i-d1s-pinctrl
+
+    then:
+      properties:
+        interrupts:
+          minItems: 6
+          maxItems: 6
+
   - if:
       properties:
         compatible:
-- 
2.35.1


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

* [PATCH 1/6] dt-bindings: pinctrl: Add compatibles for Allwinner D1/D1s
@ 2022-06-26  2:11   ` Samuel Holland
  0 siblings, 0 replies; 56+ messages in thread
From: Samuel Holland @ 2022-06-26  2:11 UTC (permalink / raw)
  To: Chen-Yu Tsai, Jernej Skrabec, Linus Walleij
  Cc: Samuel Holland, Krzysztof Kozlowski, Maxime Ripard,
	Ondrej Jirman, Rob Herring, devicetree, linux-arm-kernel,
	linux-gpio, linux-kernel, linux-sunxi

D1 contains a pin controller similar to previous SoCs, but with some
register layout changes. It includes 6 interrupt-capable pin banks.

D1s is a low pin count version of the D1 SoC, with some pins omitted.
The remaining pins have the same function assignments as D1.

Signed-off-by: Samuel Holland <samuel@sholland.org>
---

 .../pinctrl/allwinner,sun4i-a10-pinctrl.yaml      | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/Documentation/devicetree/bindings/pinctrl/allwinner,sun4i-a10-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/allwinner,sun4i-a10-pinctrl.yaml
index bfce850c2035..3da52814f151 100644
--- a/Documentation/devicetree/bindings/pinctrl/allwinner,sun4i-a10-pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/allwinner,sun4i-a10-pinctrl.yaml
@@ -46,6 +46,8 @@ properties:
       - allwinner,sun8i-v3s-pinctrl
       - allwinner,sun9i-a80-pinctrl
       - allwinner,sun9i-a80-r-pinctrl
+      - allwinner,sun20i-d1-pinctrl
+      - allwinner,sun20i-d1s-pinctrl
       - allwinner,sun50i-a64-pinctrl
       - allwinner,sun50i-a64-r-pinctrl
       - allwinner,sun50i-a100-pinctrl
@@ -171,6 +173,19 @@ allOf:
           minItems: 7
           maxItems: 7
 
+  - if:
+      properties:
+        compatible:
+          enum:
+            - allwinner,sun20i-d1-pinctrl
+            - allwinner,sun20i-d1s-pinctrl
+
+    then:
+      properties:
+        interrupts:
+          minItems: 6
+          maxItems: 6
+
   - if:
       properties:
         compatible:
-- 
2.35.1


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

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

* [PATCH 2/6] pinctrl: sunxi: Add I/O bias setting for H6 R-PIO
  2022-06-26  2:11 ` Samuel Holland
@ 2022-06-26  2:11   ` Samuel Holland
  -1 siblings, 0 replies; 56+ messages in thread
From: Samuel Holland @ 2022-06-26  2:11 UTC (permalink / raw)
  To: Chen-Yu Tsai, Jernej Skrabec, Linus Walleij
  Cc: Samuel Holland, Krzysztof Kozlowski, Maxime Ripard,
	Ondrej Jirman, Rob Herring, devicetree, linux-arm-kernel,
	linux-gpio, linux-kernel, linux-sunxi

H6 requires I/O bias configuration on both of its PIO devices.
Previously it was only done for the main PIO.

The setting for Port L is at bit 0, so the bank calculation needs to
account for the pin base. Otherwise the wrong bit is used.

Fixes: cc62383fcebe ("pinctrl: sunxi: Support I/O bias voltage setting on H6")
Signed-off-by: Samuel Holland <samuel@sholland.org>
---

 drivers/pinctrl/sunxi/pinctrl-sun50i-h6-r.c | 1 +
 drivers/pinctrl/sunxi/pinctrl-sunxi.c       | 7 ++++---
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/pinctrl/sunxi/pinctrl-sun50i-h6-r.c b/drivers/pinctrl/sunxi/pinctrl-sun50i-h6-r.c
index c7d90c44e87a..7b4b9f3d4555 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sun50i-h6-r.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sun50i-h6-r.c
@@ -107,6 +107,7 @@ static const struct sunxi_pinctrl_desc sun50i_h6_r_pinctrl_data = {
 	.npins = ARRAY_SIZE(sun50i_h6_r_pins),
 	.pin_base = PL_BASE,
 	.irq_banks = 2,
+	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_SEL,
 };
 
 static int sun50i_h6_r_pinctrl_probe(struct platform_device *pdev)
diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
index d9327d7d56ee..3c5e71359ca8 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
@@ -622,7 +622,7 @@ static int sunxi_pinctrl_set_io_bias_cfg(struct sunxi_pinctrl *pctl,
 					 unsigned pin,
 					 struct regulator *supply)
 {
-	unsigned short bank = pin / PINS_PER_BANK;
+	unsigned short bank;
 	unsigned long flags;
 	u32 val, reg;
 	int uV;
@@ -638,6 +638,9 @@ static int sunxi_pinctrl_set_io_bias_cfg(struct sunxi_pinctrl *pctl,
 	if (uV == 0)
 		return 0;
 
+	pin -= pctl->desc->pin_base;
+	bank = pin / PINS_PER_BANK;
+
 	switch (pctl->desc->io_bias_cfg_variant) {
 	case BIAS_VOLTAGE_GRP_CONFIG:
 		/*
@@ -655,8 +658,6 @@ static int sunxi_pinctrl_set_io_bias_cfg(struct sunxi_pinctrl *pctl,
 		else
 			val = 0xD; /* 3.3V */
 
-		pin -= pctl->desc->pin_base;
-
 		reg = readl(pctl->membase + sunxi_grp_config_reg(pin));
 		reg &= ~IO_BIAS_MASK;
 		writel(reg | val, pctl->membase + sunxi_grp_config_reg(pin));
-- 
2.35.1


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

* [PATCH 2/6] pinctrl: sunxi: Add I/O bias setting for H6 R-PIO
@ 2022-06-26  2:11   ` Samuel Holland
  0 siblings, 0 replies; 56+ messages in thread
From: Samuel Holland @ 2022-06-26  2:11 UTC (permalink / raw)
  To: Chen-Yu Tsai, Jernej Skrabec, Linus Walleij
  Cc: Samuel Holland, Krzysztof Kozlowski, Maxime Ripard,
	Ondrej Jirman, Rob Herring, devicetree, linux-arm-kernel,
	linux-gpio, linux-kernel, linux-sunxi

H6 requires I/O bias configuration on both of its PIO devices.
Previously it was only done for the main PIO.

The setting for Port L is at bit 0, so the bank calculation needs to
account for the pin base. Otherwise the wrong bit is used.

Fixes: cc62383fcebe ("pinctrl: sunxi: Support I/O bias voltage setting on H6")
Signed-off-by: Samuel Holland <samuel@sholland.org>
---

 drivers/pinctrl/sunxi/pinctrl-sun50i-h6-r.c | 1 +
 drivers/pinctrl/sunxi/pinctrl-sunxi.c       | 7 ++++---
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/pinctrl/sunxi/pinctrl-sun50i-h6-r.c b/drivers/pinctrl/sunxi/pinctrl-sun50i-h6-r.c
index c7d90c44e87a..7b4b9f3d4555 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sun50i-h6-r.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sun50i-h6-r.c
@@ -107,6 +107,7 @@ static const struct sunxi_pinctrl_desc sun50i_h6_r_pinctrl_data = {
 	.npins = ARRAY_SIZE(sun50i_h6_r_pins),
 	.pin_base = PL_BASE,
 	.irq_banks = 2,
+	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_SEL,
 };
 
 static int sun50i_h6_r_pinctrl_probe(struct platform_device *pdev)
diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
index d9327d7d56ee..3c5e71359ca8 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
@@ -622,7 +622,7 @@ static int sunxi_pinctrl_set_io_bias_cfg(struct sunxi_pinctrl *pctl,
 					 unsigned pin,
 					 struct regulator *supply)
 {
-	unsigned short bank = pin / PINS_PER_BANK;
+	unsigned short bank;
 	unsigned long flags;
 	u32 val, reg;
 	int uV;
@@ -638,6 +638,9 @@ static int sunxi_pinctrl_set_io_bias_cfg(struct sunxi_pinctrl *pctl,
 	if (uV == 0)
 		return 0;
 
+	pin -= pctl->desc->pin_base;
+	bank = pin / PINS_PER_BANK;
+
 	switch (pctl->desc->io_bias_cfg_variant) {
 	case BIAS_VOLTAGE_GRP_CONFIG:
 		/*
@@ -655,8 +658,6 @@ static int sunxi_pinctrl_set_io_bias_cfg(struct sunxi_pinctrl *pctl,
 		else
 			val = 0xD; /* 3.3V */
 
-		pin -= pctl->desc->pin_base;
-
 		reg = readl(pctl->membase + sunxi_grp_config_reg(pin));
 		reg &= ~IO_BIAS_MASK;
 		writel(reg | val, pctl->membase + sunxi_grp_config_reg(pin));
-- 
2.35.1


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

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

* [PATCH 3/6] pinctrl: sunxi: Support the 2.5V I/O bias mode
  2022-06-26  2:11 ` Samuel Holland
@ 2022-06-26  2:11   ` Samuel Holland
  -1 siblings, 0 replies; 56+ messages in thread
From: Samuel Holland @ 2022-06-26  2:11 UTC (permalink / raw)
  To: Chen-Yu Tsai, Jernej Skrabec, Linus Walleij
  Cc: Samuel Holland, Krzysztof Kozlowski, Maxime Ripard,
	Ondrej Jirman, Rob Herring, devicetree, linux-arm-kernel,
	linux-gpio, linux-kernel, linux-sunxi

H616 and newer SoCs feature a 2.5V I/O bias mode in addition to the
1.8V and 3.3V modes. This mode is entered by selecting the 3.3V level
and disabling the "withstand function".

H616 supports this capability on its main PIO only. A100 supports this
capability on both its PIO and R-PIO.

Signed-off-by: Samuel Holland <samuel@sholland.org>
---

 drivers/pinctrl/sunxi/pinctrl-sun50i-a100-r.c |  1 +
 drivers/pinctrl/sunxi/pinctrl-sun50i-a100.c   |  2 +-
 drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c   |  2 +-
 drivers/pinctrl/sunxi/pinctrl-sunxi.c         | 10 ++++++++++
 drivers/pinctrl/sunxi/pinctrl-sunxi.h         |  7 +++++++
 5 files changed, 20 insertions(+), 2 deletions(-)

diff --git a/drivers/pinctrl/sunxi/pinctrl-sun50i-a100-r.c b/drivers/pinctrl/sunxi/pinctrl-sun50i-a100-r.c
index 21054fcacd34..afc1f5df7545 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sun50i-a100-r.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sun50i-a100-r.c
@@ -82,6 +82,7 @@ static const struct sunxi_pinctrl_desc a100_r_pinctrl_data = {
 	.npins = ARRAY_SIZE(a100_r_pins),
 	.pin_base = PL_BASE,
 	.irq_banks = 1,
+	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_CTL,
 };
 
 static int a100_r_pinctrl_probe(struct platform_device *pdev)
diff --git a/drivers/pinctrl/sunxi/pinctrl-sun50i-a100.c b/drivers/pinctrl/sunxi/pinctrl-sun50i-a100.c
index e69f6da40dc0..f682e0e4244d 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sun50i-a100.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sun50i-a100.c
@@ -684,7 +684,7 @@ static const struct sunxi_pinctrl_desc a100_pinctrl_data = {
 	.npins = ARRAY_SIZE(a100_pins),
 	.irq_banks = 7,
 	.irq_bank_map = a100_irq_bank_map,
-	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_SEL,
+	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_CTL,
 };
 
 static int a100_pinctrl_probe(struct platform_device *pdev)
diff --git a/drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c b/drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c
index 152b71226a80..d6ca720ee8d8 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c
@@ -525,7 +525,7 @@ static const struct sunxi_pinctrl_desc h616_pinctrl_data = {
 	.irq_banks = ARRAY_SIZE(h616_irq_bank_map),
 	.irq_bank_map = h616_irq_bank_map,
 	.irq_read_needs_mux = true,
-	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_SEL,
+	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_CTL,
 };
 
 static int h616_pinctrl_probe(struct platform_device *pdev)
diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
index 3c5e71359ca8..eb3d595f816a 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
@@ -662,6 +662,16 @@ static int sunxi_pinctrl_set_io_bias_cfg(struct sunxi_pinctrl *pctl,
 		reg &= ~IO_BIAS_MASK;
 		writel(reg | val, pctl->membase + sunxi_grp_config_reg(pin));
 		return 0;
+	case BIAS_VOLTAGE_PIO_POW_MODE_CTL:
+		val = uV > 1800000 && uV <= 2500000 ? BIT(bank) : 0;
+
+		raw_spin_lock_irqsave(&pctl->lock, flags);
+		reg = readl(pctl->membase + PIO_POW_MOD_CTL_REG);
+		reg &= ~BIT(bank);
+		writel(reg | val, pctl->membase + PIO_POW_MOD_CTL_REG);
+		raw_spin_unlock_irqrestore(&pctl->lock, flags);
+
+		fallthrough;
 	case BIAS_VOLTAGE_PIO_POW_MODE_SEL:
 		val = uV <= 1800000 ? 1 : 0;
 
diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.h b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
index a32bb5bcb754..0f1aab58650c 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.h
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
@@ -98,6 +98,7 @@
 #define PINCTRL_SUN8I_V3S	BIT(10)
 
 #define PIO_POW_MOD_SEL_REG	0x340
+#define PIO_POW_MOD_CTL_REG	0x344
 
 enum sunxi_desc_bias_voltage {
 	BIAS_VOLTAGE_NONE,
@@ -111,6 +112,12 @@ enum sunxi_desc_bias_voltage {
 	 * register, as seen on H6 SoC, for example.
 	 */
 	BIAS_VOLTAGE_PIO_POW_MODE_SEL,
+	/*
+	 * Bias voltage is set through PIO_POW_MOD_SEL_REG
+	 * and PIO_POW_MOD_CTL_REG register, as seen on
+	 * A100 and D1 SoC, for example.
+	 */
+	BIAS_VOLTAGE_PIO_POW_MODE_CTL,
 };
 
 struct sunxi_desc_function {
-- 
2.35.1


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

* [PATCH 3/6] pinctrl: sunxi: Support the 2.5V I/O bias mode
@ 2022-06-26  2:11   ` Samuel Holland
  0 siblings, 0 replies; 56+ messages in thread
From: Samuel Holland @ 2022-06-26  2:11 UTC (permalink / raw)
  To: Chen-Yu Tsai, Jernej Skrabec, Linus Walleij
  Cc: Samuel Holland, Krzysztof Kozlowski, Maxime Ripard,
	Ondrej Jirman, Rob Herring, devicetree, linux-arm-kernel,
	linux-gpio, linux-kernel, linux-sunxi

H616 and newer SoCs feature a 2.5V I/O bias mode in addition to the
1.8V and 3.3V modes. This mode is entered by selecting the 3.3V level
and disabling the "withstand function".

H616 supports this capability on its main PIO only. A100 supports this
capability on both its PIO and R-PIO.

Signed-off-by: Samuel Holland <samuel@sholland.org>
---

 drivers/pinctrl/sunxi/pinctrl-sun50i-a100-r.c |  1 +
 drivers/pinctrl/sunxi/pinctrl-sun50i-a100.c   |  2 +-
 drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c   |  2 +-
 drivers/pinctrl/sunxi/pinctrl-sunxi.c         | 10 ++++++++++
 drivers/pinctrl/sunxi/pinctrl-sunxi.h         |  7 +++++++
 5 files changed, 20 insertions(+), 2 deletions(-)

diff --git a/drivers/pinctrl/sunxi/pinctrl-sun50i-a100-r.c b/drivers/pinctrl/sunxi/pinctrl-sun50i-a100-r.c
index 21054fcacd34..afc1f5df7545 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sun50i-a100-r.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sun50i-a100-r.c
@@ -82,6 +82,7 @@ static const struct sunxi_pinctrl_desc a100_r_pinctrl_data = {
 	.npins = ARRAY_SIZE(a100_r_pins),
 	.pin_base = PL_BASE,
 	.irq_banks = 1,
+	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_CTL,
 };
 
 static int a100_r_pinctrl_probe(struct platform_device *pdev)
diff --git a/drivers/pinctrl/sunxi/pinctrl-sun50i-a100.c b/drivers/pinctrl/sunxi/pinctrl-sun50i-a100.c
index e69f6da40dc0..f682e0e4244d 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sun50i-a100.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sun50i-a100.c
@@ -684,7 +684,7 @@ static const struct sunxi_pinctrl_desc a100_pinctrl_data = {
 	.npins = ARRAY_SIZE(a100_pins),
 	.irq_banks = 7,
 	.irq_bank_map = a100_irq_bank_map,
-	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_SEL,
+	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_CTL,
 };
 
 static int a100_pinctrl_probe(struct platform_device *pdev)
diff --git a/drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c b/drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c
index 152b71226a80..d6ca720ee8d8 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c
@@ -525,7 +525,7 @@ static const struct sunxi_pinctrl_desc h616_pinctrl_data = {
 	.irq_banks = ARRAY_SIZE(h616_irq_bank_map),
 	.irq_bank_map = h616_irq_bank_map,
 	.irq_read_needs_mux = true,
-	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_SEL,
+	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_CTL,
 };
 
 static int h616_pinctrl_probe(struct platform_device *pdev)
diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
index 3c5e71359ca8..eb3d595f816a 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
@@ -662,6 +662,16 @@ static int sunxi_pinctrl_set_io_bias_cfg(struct sunxi_pinctrl *pctl,
 		reg &= ~IO_BIAS_MASK;
 		writel(reg | val, pctl->membase + sunxi_grp_config_reg(pin));
 		return 0;
+	case BIAS_VOLTAGE_PIO_POW_MODE_CTL:
+		val = uV > 1800000 && uV <= 2500000 ? BIT(bank) : 0;
+
+		raw_spin_lock_irqsave(&pctl->lock, flags);
+		reg = readl(pctl->membase + PIO_POW_MOD_CTL_REG);
+		reg &= ~BIT(bank);
+		writel(reg | val, pctl->membase + PIO_POW_MOD_CTL_REG);
+		raw_spin_unlock_irqrestore(&pctl->lock, flags);
+
+		fallthrough;
 	case BIAS_VOLTAGE_PIO_POW_MODE_SEL:
 		val = uV <= 1800000 ? 1 : 0;
 
diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.h b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
index a32bb5bcb754..0f1aab58650c 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.h
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
@@ -98,6 +98,7 @@
 #define PINCTRL_SUN8I_V3S	BIT(10)
 
 #define PIO_POW_MOD_SEL_REG	0x340
+#define PIO_POW_MOD_CTL_REG	0x344
 
 enum sunxi_desc_bias_voltage {
 	BIAS_VOLTAGE_NONE,
@@ -111,6 +112,12 @@ enum sunxi_desc_bias_voltage {
 	 * register, as seen on H6 SoC, for example.
 	 */
 	BIAS_VOLTAGE_PIO_POW_MODE_SEL,
+	/*
+	 * Bias voltage is set through PIO_POW_MOD_SEL_REG
+	 * and PIO_POW_MOD_CTL_REG register, as seen on
+	 * A100 and D1 SoC, for example.
+	 */
+	BIAS_VOLTAGE_PIO_POW_MODE_CTL,
 };
 
 struct sunxi_desc_function {
-- 
2.35.1


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

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

* [PATCH 4/6] pinctrl: sunxi: Refactor register/offset calculation
  2022-06-26  2:11 ` Samuel Holland
@ 2022-06-26  2:11   ` Samuel Holland
  -1 siblings, 0 replies; 56+ messages in thread
From: Samuel Holland @ 2022-06-26  2:11 UTC (permalink / raw)
  To: Chen-Yu Tsai, Jernej Skrabec, Linus Walleij
  Cc: Samuel Holland, Krzysztof Kozlowski, Maxime Ripard,
	Ondrej Jirman, Rob Herring, devicetree, linux-arm-kernel,
	linux-gpio, linux-kernel, linux-sunxi

Starting with the D1/D1s/T113 SoC, Allwinner changed the layout of the
pinctrl registers. This new layout widens the drive level field, which
affects the pull register offset and the overall bank size.

As a first step to support this, combine the register and offset
calculation functions, and refactor the math to depend on one constant
for field widths instead of three. This minimizes the code size impact
of making some of the factors dynamic.

While rewriting these functions, move them to the implementation file,
since that is the only file where they are used. And make the comment
more generic, without mentioning specific offsets/sizes.

The callers are updated to expect a shifted mask, and to use consistent
terminology (reg/shift/mask/val).

Signed-off-by: Samuel Holland <samuel@sholland.org>
---

 drivers/pinctrl/sunxi/pinctrl-sunxi.c | 119 ++++++++++++++++++--------
 drivers/pinctrl/sunxi/pinctrl-sunxi.h |  93 +-------------------
 2 files changed, 89 insertions(+), 123 deletions(-)

diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
index eb3d595f816a..78b7ab69d7a5 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
@@ -46,6 +46,63 @@ static struct lock_class_key sunxi_pinctrl_irq_request_class;
 static struct irq_chip sunxi_pinctrl_edge_irq_chip;
 static struct irq_chip sunxi_pinctrl_level_irq_chip;
 
+/*
+ * The sunXi PIO registers are organized as a series of banks, with registers
+ * for each bank in the following order:
+ *  - Mux config
+ *  - Data value
+ *  - Drive level
+ *  - Pull direction
+ *
+ * Multiple consecutive registers are used for fields wider than one bit.
+ *
+ * The following functions calculate the register and the bit offset to access.
+ * They take a pin number which is relative to the start of the current device.
+ */
+static void sunxi_mux_reg(u32 pin, u32 *reg, u32 *shift, u32 *mask)
+{
+	u32 bank   = pin / PINS_PER_BANK;
+	u32 offset = pin % PINS_PER_BANK * MUX_FIELD_WIDTH;
+
+	*reg   = bank * BANK_MEM_SIZE + MUX_REGS_OFFSET +
+		 offset / BITS_PER_TYPE(u32) * sizeof(u32);
+	*shift = offset % BITS_PER_TYPE(u32);
+	*mask  = (BIT(MUX_FIELD_WIDTH) - 1) << *shift;
+}
+
+static void sunxi_data_reg(u32 pin, u32 *reg, u32 *shift, u32 *mask)
+{
+	u32 bank   = pin / PINS_PER_BANK;
+	u32 offset = pin % PINS_PER_BANK * DATA_FIELD_WIDTH;
+
+	*reg   = bank * BANK_MEM_SIZE + DATA_REGS_OFFSET +
+		 offset / BITS_PER_TYPE(u32) * sizeof(u32);
+	*shift = offset % BITS_PER_TYPE(u32);
+	*mask  = (BIT(DATA_FIELD_WIDTH) - 1) << *shift;
+}
+
+static void sunxi_dlevel_reg(u32 pin, u32 *reg, u32 *shift, u32 *mask)
+{
+	u32 bank   = pin / PINS_PER_BANK;
+	u32 offset = pin % PINS_PER_BANK * DLEVEL_FIELD_WIDTH;
+
+	*reg   = bank * BANK_MEM_SIZE + DLEVEL_REGS_OFFSET +
+		 offset / BITS_PER_TYPE(u32) * sizeof(u32);
+	*shift = offset % BITS_PER_TYPE(u32);
+	*mask  = (BIT(DLEVEL_FIELD_WIDTH) - 1) << *shift;
+}
+
+static void sunxi_pull_reg(u32 pin, u32 *reg, u32 *shift, u32 *mask)
+{
+	u32 bank   = pin / PINS_PER_BANK;
+	u32 offset = pin % PINS_PER_BANK * PULL_FIELD_WIDTH;
+
+	*reg   = bank * BANK_MEM_SIZE + PULL_REGS_OFFSET +
+		 offset / BITS_PER_TYPE(u32) * sizeof(u32);
+	*shift = offset % BITS_PER_TYPE(u32);
+	*mask  = (BIT(PULL_FIELD_WIDTH) - 1) << *shift;
+}
+
 static struct sunxi_pinctrl_group *
 sunxi_pinctrl_find_group_by_name(struct sunxi_pinctrl *pctl, const char *group)
 {
@@ -452,21 +509,17 @@ static const struct pinctrl_ops sunxi_pctrl_ops = {
 };
 
 static int sunxi_pconf_reg(unsigned pin, enum pin_config_param param,
-			   u32 *offset, u32 *shift, u32 *mask)
+			   u32 *reg, u32 *shift, u32 *mask)
 {
 	switch (param) {
 	case PIN_CONFIG_DRIVE_STRENGTH:
-		*offset = sunxi_dlevel_reg(pin);
-		*shift = sunxi_dlevel_offset(pin);
-		*mask = DLEVEL_PINS_MASK;
+		sunxi_dlevel_reg(pin, reg, shift, mask);
 		break;
 
 	case PIN_CONFIG_BIAS_PULL_UP:
 	case PIN_CONFIG_BIAS_PULL_DOWN:
 	case PIN_CONFIG_BIAS_DISABLE:
-		*offset = sunxi_pull_reg(pin);
-		*shift = sunxi_pull_offset(pin);
-		*mask = PULL_PINS_MASK;
+		sunxi_pull_reg(pin, reg, shift, mask);
 		break;
 
 	default:
@@ -481,17 +534,17 @@ static int sunxi_pconf_get(struct pinctrl_dev *pctldev, unsigned pin,
 {
 	struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
 	enum pin_config_param param = pinconf_to_config_param(*config);
-	u32 offset, shift, mask, val;
+	u32 reg, shift, mask, val;
 	u16 arg;
 	int ret;
 
 	pin -= pctl->desc->pin_base;
 
-	ret = sunxi_pconf_reg(pin, param, &offset, &shift, &mask);
+	ret = sunxi_pconf_reg(pin, param, &reg, &shift, &mask);
 	if (ret < 0)
 		return ret;
 
-	val = (readl(pctl->membase + offset) >> shift) & mask;
+	val = (readl(pctl->membase + reg) & mask) >> shift;
 
 	switch (pinconf_to_config_param(*config)) {
 	case PIN_CONFIG_DRIVE_STRENGTH:
@@ -545,16 +598,15 @@ static int sunxi_pconf_set(struct pinctrl_dev *pctldev, unsigned pin,
 	int i;
 
 	for (i = 0; i < num_configs; i++) {
+		u32 arg, reg, shift, mask, val;
 		enum pin_config_param param;
 		unsigned long flags;
-		u32 offset, shift, mask, reg;
-		u32 arg, val;
 		int ret;
 
 		param = pinconf_to_config_param(configs[i]);
 		arg = pinconf_to_config_argument(configs[i]);
 
-		ret = sunxi_pconf_reg(pin, param, &offset, &shift, &mask);
+		ret = sunxi_pconf_reg(pin, param, &reg, &shift, &mask);
 		if (ret < 0)
 			return ret;
 
@@ -591,9 +643,8 @@ static int sunxi_pconf_set(struct pinctrl_dev *pctldev, unsigned pin,
 		}
 
 		raw_spin_lock_irqsave(&pctl->lock, flags);
-		reg = readl(pctl->membase + offset);
-		reg &= ~(mask << shift);
-		writel(reg | val << shift, pctl->membase + offset);
+		writel((readl(pctl->membase + reg) & ~mask) | val << shift,
+		       pctl->membase + reg);
 		raw_spin_unlock_irqrestore(&pctl->lock, flags);
 	} /* for each config */
 
@@ -719,16 +770,16 @@ static void sunxi_pmx_set(struct pinctrl_dev *pctldev,
 				 u8 config)
 {
 	struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+	u32 reg, shift, mask;
 	unsigned long flags;
-	u32 val, mask;
+
+	pin -= pctl->desc->pin_base;
+	sunxi_mux_reg(pin, &reg, &shift, &mask);
 
 	raw_spin_lock_irqsave(&pctl->lock, flags);
 
-	pin -= pctl->desc->pin_base;
-	val = readl(pctl->membase + sunxi_mux_reg(pin));
-	mask = MUX_PINS_MASK << sunxi_mux_offset(pin);
-	writel((val & ~mask) | config << sunxi_mux_offset(pin),
-		pctl->membase + sunxi_mux_reg(pin));
+	writel((readl(pctl->membase + reg) & ~mask) | config << shift,
+	       pctl->membase + reg);
 
 	raw_spin_unlock_irqrestore(&pctl->lock, flags);
 }
@@ -861,43 +912,43 @@ static int sunxi_pinctrl_gpio_direction_input(struct gpio_chip *chip,
 static int sunxi_pinctrl_gpio_get(struct gpio_chip *chip, unsigned offset)
 {
 	struct sunxi_pinctrl *pctl = gpiochip_get_data(chip);
-	u32 reg = sunxi_data_reg(offset);
-	u8 index = sunxi_data_offset(offset);
 	bool set_mux = pctl->desc->irq_read_needs_mux &&
 		gpiochip_line_is_irq(chip, offset);
 	u32 pin = offset + chip->base;
-	u32 val;
+	u32 reg, shift, mask, val;
+
+	sunxi_data_reg(offset, &reg, &shift, &mask);
 
 	if (set_mux)
 		sunxi_pmx_set(pctl->pctl_dev, pin, SUN4I_FUNC_INPUT);
 
-	val = (readl(pctl->membase + reg) >> index) & DATA_PINS_MASK;
+	val = (readl(pctl->membase + reg) & mask) >> shift;
 
 	if (set_mux)
 		sunxi_pmx_set(pctl->pctl_dev, pin, SUN4I_FUNC_IRQ);
 
-	return !!val;
+	return val;
 }
 
 static void sunxi_pinctrl_gpio_set(struct gpio_chip *chip,
 				unsigned offset, int value)
 {
 	struct sunxi_pinctrl *pctl = gpiochip_get_data(chip);
-	u32 reg = sunxi_data_reg(offset);
-	u8 index = sunxi_data_offset(offset);
+	u32 reg, shift, mask, val;
 	unsigned long flags;
-	u32 regval;
+
+	sunxi_data_reg(offset, &reg, &shift, &mask);
 
 	raw_spin_lock_irqsave(&pctl->lock, flags);
 
-	regval = readl(pctl->membase + reg);
+	val = readl(pctl->membase + reg);
 
 	if (value)
-		regval |= BIT(index);
+		val |= mask;
 	else
-		regval &= ~(BIT(index));
+		val &= ~mask;
 
-	writel(regval, pctl->membase + reg);
+	writel(val, pctl->membase + reg);
 
 	raw_spin_unlock_irqrestore(&pctl->lock, flags);
 }
diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.h b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
index 0f1aab58650c..efaa97457e08 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.h
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
@@ -36,23 +36,15 @@
 
 #define BANK_MEM_SIZE		0x24
 #define MUX_REGS_OFFSET		0x0
+#define MUX_FIELD_WIDTH		4
 #define DATA_REGS_OFFSET	0x10
+#define DATA_FIELD_WIDTH	1
 #define DLEVEL_REGS_OFFSET	0x14
+#define DLEVEL_FIELD_WIDTH	2
 #define PULL_REGS_OFFSET	0x1c
+#define PULL_FIELD_WIDTH	2
 
 #define PINS_PER_BANK		32
-#define MUX_PINS_PER_REG	8
-#define MUX_PINS_BITS		4
-#define MUX_PINS_MASK		0x0f
-#define DATA_PINS_PER_REG	32
-#define DATA_PINS_BITS		1
-#define DATA_PINS_MASK		0x01
-#define DLEVEL_PINS_PER_REG	16
-#define DLEVEL_PINS_BITS	2
-#define DLEVEL_PINS_MASK	0x03
-#define PULL_PINS_PER_REG	16
-#define PULL_PINS_BITS		2
-#define PULL_PINS_MASK		0x03
 
 #define IRQ_PER_BANK		32
 
@@ -222,83 +214,6 @@ struct sunxi_pinctrl {
 		.irqnum = _irq,					\
 	}
 
-/*
- * The sunXi PIO registers are organized as is:
- * 0x00 - 0x0c	Muxing values.
- *		8 pins per register, each pin having a 4bits value
- * 0x10		Pin values
- *		32 bits per register, each pin corresponding to one bit
- * 0x14 - 0x18	Drive level
- *		16 pins per register, each pin having a 2bits value
- * 0x1c - 0x20	Pull-Up values
- *		16 pins per register, each pin having a 2bits value
- *
- * This is for the first bank. Each bank will have the same layout,
- * with an offset being a multiple of 0x24.
- *
- * The following functions calculate from the pin number the register
- * and the bit offset that we should access.
- */
-static inline u32 sunxi_mux_reg(u16 pin)
-{
-	u8 bank = pin / PINS_PER_BANK;
-	u32 offset = bank * BANK_MEM_SIZE;
-	offset += MUX_REGS_OFFSET;
-	offset += pin % PINS_PER_BANK / MUX_PINS_PER_REG * 0x04;
-	return round_down(offset, 4);
-}
-
-static inline u32 sunxi_mux_offset(u16 pin)
-{
-	u32 pin_num = pin % MUX_PINS_PER_REG;
-	return pin_num * MUX_PINS_BITS;
-}
-
-static inline u32 sunxi_data_reg(u16 pin)
-{
-	u8 bank = pin / PINS_PER_BANK;
-	u32 offset = bank * BANK_MEM_SIZE;
-	offset += DATA_REGS_OFFSET;
-	offset += pin % PINS_PER_BANK / DATA_PINS_PER_REG * 0x04;
-	return round_down(offset, 4);
-}
-
-static inline u32 sunxi_data_offset(u16 pin)
-{
-	u32 pin_num = pin % DATA_PINS_PER_REG;
-	return pin_num * DATA_PINS_BITS;
-}
-
-static inline u32 sunxi_dlevel_reg(u16 pin)
-{
-	u8 bank = pin / PINS_PER_BANK;
-	u32 offset = bank * BANK_MEM_SIZE;
-	offset += DLEVEL_REGS_OFFSET;
-	offset += pin % PINS_PER_BANK / DLEVEL_PINS_PER_REG * 0x04;
-	return round_down(offset, 4);
-}
-
-static inline u32 sunxi_dlevel_offset(u16 pin)
-{
-	u32 pin_num = pin % DLEVEL_PINS_PER_REG;
-	return pin_num * DLEVEL_PINS_BITS;
-}
-
-static inline u32 sunxi_pull_reg(u16 pin)
-{
-	u8 bank = pin / PINS_PER_BANK;
-	u32 offset = bank * BANK_MEM_SIZE;
-	offset += PULL_REGS_OFFSET;
-	offset += pin % PINS_PER_BANK / PULL_PINS_PER_REG * 0x04;
-	return round_down(offset, 4);
-}
-
-static inline u32 sunxi_pull_offset(u16 pin)
-{
-	u32 pin_num = pin % PULL_PINS_PER_REG;
-	return pin_num * PULL_PINS_BITS;
-}
-
 static inline u32 sunxi_irq_hw_bank_num(const struct sunxi_pinctrl_desc *desc, u8 bank)
 {
 	if (!desc->irq_bank_map)
-- 
2.35.1


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

* [PATCH 4/6] pinctrl: sunxi: Refactor register/offset calculation
@ 2022-06-26  2:11   ` Samuel Holland
  0 siblings, 0 replies; 56+ messages in thread
From: Samuel Holland @ 2022-06-26  2:11 UTC (permalink / raw)
  To: Chen-Yu Tsai, Jernej Skrabec, Linus Walleij
  Cc: Samuel Holland, Krzysztof Kozlowski, Maxime Ripard,
	Ondrej Jirman, Rob Herring, devicetree, linux-arm-kernel,
	linux-gpio, linux-kernel, linux-sunxi

Starting with the D1/D1s/T113 SoC, Allwinner changed the layout of the
pinctrl registers. This new layout widens the drive level field, which
affects the pull register offset and the overall bank size.

As a first step to support this, combine the register and offset
calculation functions, and refactor the math to depend on one constant
for field widths instead of three. This minimizes the code size impact
of making some of the factors dynamic.

While rewriting these functions, move them to the implementation file,
since that is the only file where they are used. And make the comment
more generic, without mentioning specific offsets/sizes.

The callers are updated to expect a shifted mask, and to use consistent
terminology (reg/shift/mask/val).

Signed-off-by: Samuel Holland <samuel@sholland.org>
---

 drivers/pinctrl/sunxi/pinctrl-sunxi.c | 119 ++++++++++++++++++--------
 drivers/pinctrl/sunxi/pinctrl-sunxi.h |  93 +-------------------
 2 files changed, 89 insertions(+), 123 deletions(-)

diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
index eb3d595f816a..78b7ab69d7a5 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
@@ -46,6 +46,63 @@ static struct lock_class_key sunxi_pinctrl_irq_request_class;
 static struct irq_chip sunxi_pinctrl_edge_irq_chip;
 static struct irq_chip sunxi_pinctrl_level_irq_chip;
 
+/*
+ * The sunXi PIO registers are organized as a series of banks, with registers
+ * for each bank in the following order:
+ *  - Mux config
+ *  - Data value
+ *  - Drive level
+ *  - Pull direction
+ *
+ * Multiple consecutive registers are used for fields wider than one bit.
+ *
+ * The following functions calculate the register and the bit offset to access.
+ * They take a pin number which is relative to the start of the current device.
+ */
+static void sunxi_mux_reg(u32 pin, u32 *reg, u32 *shift, u32 *mask)
+{
+	u32 bank   = pin / PINS_PER_BANK;
+	u32 offset = pin % PINS_PER_BANK * MUX_FIELD_WIDTH;
+
+	*reg   = bank * BANK_MEM_SIZE + MUX_REGS_OFFSET +
+		 offset / BITS_PER_TYPE(u32) * sizeof(u32);
+	*shift = offset % BITS_PER_TYPE(u32);
+	*mask  = (BIT(MUX_FIELD_WIDTH) - 1) << *shift;
+}
+
+static void sunxi_data_reg(u32 pin, u32 *reg, u32 *shift, u32 *mask)
+{
+	u32 bank   = pin / PINS_PER_BANK;
+	u32 offset = pin % PINS_PER_BANK * DATA_FIELD_WIDTH;
+
+	*reg   = bank * BANK_MEM_SIZE + DATA_REGS_OFFSET +
+		 offset / BITS_PER_TYPE(u32) * sizeof(u32);
+	*shift = offset % BITS_PER_TYPE(u32);
+	*mask  = (BIT(DATA_FIELD_WIDTH) - 1) << *shift;
+}
+
+static void sunxi_dlevel_reg(u32 pin, u32 *reg, u32 *shift, u32 *mask)
+{
+	u32 bank   = pin / PINS_PER_BANK;
+	u32 offset = pin % PINS_PER_BANK * DLEVEL_FIELD_WIDTH;
+
+	*reg   = bank * BANK_MEM_SIZE + DLEVEL_REGS_OFFSET +
+		 offset / BITS_PER_TYPE(u32) * sizeof(u32);
+	*shift = offset % BITS_PER_TYPE(u32);
+	*mask  = (BIT(DLEVEL_FIELD_WIDTH) - 1) << *shift;
+}
+
+static void sunxi_pull_reg(u32 pin, u32 *reg, u32 *shift, u32 *mask)
+{
+	u32 bank   = pin / PINS_PER_BANK;
+	u32 offset = pin % PINS_PER_BANK * PULL_FIELD_WIDTH;
+
+	*reg   = bank * BANK_MEM_SIZE + PULL_REGS_OFFSET +
+		 offset / BITS_PER_TYPE(u32) * sizeof(u32);
+	*shift = offset % BITS_PER_TYPE(u32);
+	*mask  = (BIT(PULL_FIELD_WIDTH) - 1) << *shift;
+}
+
 static struct sunxi_pinctrl_group *
 sunxi_pinctrl_find_group_by_name(struct sunxi_pinctrl *pctl, const char *group)
 {
@@ -452,21 +509,17 @@ static const struct pinctrl_ops sunxi_pctrl_ops = {
 };
 
 static int sunxi_pconf_reg(unsigned pin, enum pin_config_param param,
-			   u32 *offset, u32 *shift, u32 *mask)
+			   u32 *reg, u32 *shift, u32 *mask)
 {
 	switch (param) {
 	case PIN_CONFIG_DRIVE_STRENGTH:
-		*offset = sunxi_dlevel_reg(pin);
-		*shift = sunxi_dlevel_offset(pin);
-		*mask = DLEVEL_PINS_MASK;
+		sunxi_dlevel_reg(pin, reg, shift, mask);
 		break;
 
 	case PIN_CONFIG_BIAS_PULL_UP:
 	case PIN_CONFIG_BIAS_PULL_DOWN:
 	case PIN_CONFIG_BIAS_DISABLE:
-		*offset = sunxi_pull_reg(pin);
-		*shift = sunxi_pull_offset(pin);
-		*mask = PULL_PINS_MASK;
+		sunxi_pull_reg(pin, reg, shift, mask);
 		break;
 
 	default:
@@ -481,17 +534,17 @@ static int sunxi_pconf_get(struct pinctrl_dev *pctldev, unsigned pin,
 {
 	struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
 	enum pin_config_param param = pinconf_to_config_param(*config);
-	u32 offset, shift, mask, val;
+	u32 reg, shift, mask, val;
 	u16 arg;
 	int ret;
 
 	pin -= pctl->desc->pin_base;
 
-	ret = sunxi_pconf_reg(pin, param, &offset, &shift, &mask);
+	ret = sunxi_pconf_reg(pin, param, &reg, &shift, &mask);
 	if (ret < 0)
 		return ret;
 
-	val = (readl(pctl->membase + offset) >> shift) & mask;
+	val = (readl(pctl->membase + reg) & mask) >> shift;
 
 	switch (pinconf_to_config_param(*config)) {
 	case PIN_CONFIG_DRIVE_STRENGTH:
@@ -545,16 +598,15 @@ static int sunxi_pconf_set(struct pinctrl_dev *pctldev, unsigned pin,
 	int i;
 
 	for (i = 0; i < num_configs; i++) {
+		u32 arg, reg, shift, mask, val;
 		enum pin_config_param param;
 		unsigned long flags;
-		u32 offset, shift, mask, reg;
-		u32 arg, val;
 		int ret;
 
 		param = pinconf_to_config_param(configs[i]);
 		arg = pinconf_to_config_argument(configs[i]);
 
-		ret = sunxi_pconf_reg(pin, param, &offset, &shift, &mask);
+		ret = sunxi_pconf_reg(pin, param, &reg, &shift, &mask);
 		if (ret < 0)
 			return ret;
 
@@ -591,9 +643,8 @@ static int sunxi_pconf_set(struct pinctrl_dev *pctldev, unsigned pin,
 		}
 
 		raw_spin_lock_irqsave(&pctl->lock, flags);
-		reg = readl(pctl->membase + offset);
-		reg &= ~(mask << shift);
-		writel(reg | val << shift, pctl->membase + offset);
+		writel((readl(pctl->membase + reg) & ~mask) | val << shift,
+		       pctl->membase + reg);
 		raw_spin_unlock_irqrestore(&pctl->lock, flags);
 	} /* for each config */
 
@@ -719,16 +770,16 @@ static void sunxi_pmx_set(struct pinctrl_dev *pctldev,
 				 u8 config)
 {
 	struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+	u32 reg, shift, mask;
 	unsigned long flags;
-	u32 val, mask;
+
+	pin -= pctl->desc->pin_base;
+	sunxi_mux_reg(pin, &reg, &shift, &mask);
 
 	raw_spin_lock_irqsave(&pctl->lock, flags);
 
-	pin -= pctl->desc->pin_base;
-	val = readl(pctl->membase + sunxi_mux_reg(pin));
-	mask = MUX_PINS_MASK << sunxi_mux_offset(pin);
-	writel((val & ~mask) | config << sunxi_mux_offset(pin),
-		pctl->membase + sunxi_mux_reg(pin));
+	writel((readl(pctl->membase + reg) & ~mask) | config << shift,
+	       pctl->membase + reg);
 
 	raw_spin_unlock_irqrestore(&pctl->lock, flags);
 }
@@ -861,43 +912,43 @@ static int sunxi_pinctrl_gpio_direction_input(struct gpio_chip *chip,
 static int sunxi_pinctrl_gpio_get(struct gpio_chip *chip, unsigned offset)
 {
 	struct sunxi_pinctrl *pctl = gpiochip_get_data(chip);
-	u32 reg = sunxi_data_reg(offset);
-	u8 index = sunxi_data_offset(offset);
 	bool set_mux = pctl->desc->irq_read_needs_mux &&
 		gpiochip_line_is_irq(chip, offset);
 	u32 pin = offset + chip->base;
-	u32 val;
+	u32 reg, shift, mask, val;
+
+	sunxi_data_reg(offset, &reg, &shift, &mask);
 
 	if (set_mux)
 		sunxi_pmx_set(pctl->pctl_dev, pin, SUN4I_FUNC_INPUT);
 
-	val = (readl(pctl->membase + reg) >> index) & DATA_PINS_MASK;
+	val = (readl(pctl->membase + reg) & mask) >> shift;
 
 	if (set_mux)
 		sunxi_pmx_set(pctl->pctl_dev, pin, SUN4I_FUNC_IRQ);
 
-	return !!val;
+	return val;
 }
 
 static void sunxi_pinctrl_gpio_set(struct gpio_chip *chip,
 				unsigned offset, int value)
 {
 	struct sunxi_pinctrl *pctl = gpiochip_get_data(chip);
-	u32 reg = sunxi_data_reg(offset);
-	u8 index = sunxi_data_offset(offset);
+	u32 reg, shift, mask, val;
 	unsigned long flags;
-	u32 regval;
+
+	sunxi_data_reg(offset, &reg, &shift, &mask);
 
 	raw_spin_lock_irqsave(&pctl->lock, flags);
 
-	regval = readl(pctl->membase + reg);
+	val = readl(pctl->membase + reg);
 
 	if (value)
-		regval |= BIT(index);
+		val |= mask;
 	else
-		regval &= ~(BIT(index));
+		val &= ~mask;
 
-	writel(regval, pctl->membase + reg);
+	writel(val, pctl->membase + reg);
 
 	raw_spin_unlock_irqrestore(&pctl->lock, flags);
 }
diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.h b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
index 0f1aab58650c..efaa97457e08 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.h
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
@@ -36,23 +36,15 @@
 
 #define BANK_MEM_SIZE		0x24
 #define MUX_REGS_OFFSET		0x0
+#define MUX_FIELD_WIDTH		4
 #define DATA_REGS_OFFSET	0x10
+#define DATA_FIELD_WIDTH	1
 #define DLEVEL_REGS_OFFSET	0x14
+#define DLEVEL_FIELD_WIDTH	2
 #define PULL_REGS_OFFSET	0x1c
+#define PULL_FIELD_WIDTH	2
 
 #define PINS_PER_BANK		32
-#define MUX_PINS_PER_REG	8
-#define MUX_PINS_BITS		4
-#define MUX_PINS_MASK		0x0f
-#define DATA_PINS_PER_REG	32
-#define DATA_PINS_BITS		1
-#define DATA_PINS_MASK		0x01
-#define DLEVEL_PINS_PER_REG	16
-#define DLEVEL_PINS_BITS	2
-#define DLEVEL_PINS_MASK	0x03
-#define PULL_PINS_PER_REG	16
-#define PULL_PINS_BITS		2
-#define PULL_PINS_MASK		0x03
 
 #define IRQ_PER_BANK		32
 
@@ -222,83 +214,6 @@ struct sunxi_pinctrl {
 		.irqnum = _irq,					\
 	}
 
-/*
- * The sunXi PIO registers are organized as is:
- * 0x00 - 0x0c	Muxing values.
- *		8 pins per register, each pin having a 4bits value
- * 0x10		Pin values
- *		32 bits per register, each pin corresponding to one bit
- * 0x14 - 0x18	Drive level
- *		16 pins per register, each pin having a 2bits value
- * 0x1c - 0x20	Pull-Up values
- *		16 pins per register, each pin having a 2bits value
- *
- * This is for the first bank. Each bank will have the same layout,
- * with an offset being a multiple of 0x24.
- *
- * The following functions calculate from the pin number the register
- * and the bit offset that we should access.
- */
-static inline u32 sunxi_mux_reg(u16 pin)
-{
-	u8 bank = pin / PINS_PER_BANK;
-	u32 offset = bank * BANK_MEM_SIZE;
-	offset += MUX_REGS_OFFSET;
-	offset += pin % PINS_PER_BANK / MUX_PINS_PER_REG * 0x04;
-	return round_down(offset, 4);
-}
-
-static inline u32 sunxi_mux_offset(u16 pin)
-{
-	u32 pin_num = pin % MUX_PINS_PER_REG;
-	return pin_num * MUX_PINS_BITS;
-}
-
-static inline u32 sunxi_data_reg(u16 pin)
-{
-	u8 bank = pin / PINS_PER_BANK;
-	u32 offset = bank * BANK_MEM_SIZE;
-	offset += DATA_REGS_OFFSET;
-	offset += pin % PINS_PER_BANK / DATA_PINS_PER_REG * 0x04;
-	return round_down(offset, 4);
-}
-
-static inline u32 sunxi_data_offset(u16 pin)
-{
-	u32 pin_num = pin % DATA_PINS_PER_REG;
-	return pin_num * DATA_PINS_BITS;
-}
-
-static inline u32 sunxi_dlevel_reg(u16 pin)
-{
-	u8 bank = pin / PINS_PER_BANK;
-	u32 offset = bank * BANK_MEM_SIZE;
-	offset += DLEVEL_REGS_OFFSET;
-	offset += pin % PINS_PER_BANK / DLEVEL_PINS_PER_REG * 0x04;
-	return round_down(offset, 4);
-}
-
-static inline u32 sunxi_dlevel_offset(u16 pin)
-{
-	u32 pin_num = pin % DLEVEL_PINS_PER_REG;
-	return pin_num * DLEVEL_PINS_BITS;
-}
-
-static inline u32 sunxi_pull_reg(u16 pin)
-{
-	u8 bank = pin / PINS_PER_BANK;
-	u32 offset = bank * BANK_MEM_SIZE;
-	offset += PULL_REGS_OFFSET;
-	offset += pin % PINS_PER_BANK / PULL_PINS_PER_REG * 0x04;
-	return round_down(offset, 4);
-}
-
-static inline u32 sunxi_pull_offset(u16 pin)
-{
-	u32 pin_num = pin % PULL_PINS_PER_REG;
-	return pin_num * PULL_PINS_BITS;
-}
-
 static inline u32 sunxi_irq_hw_bank_num(const struct sunxi_pinctrl_desc *desc, u8 bank)
 {
 	if (!desc->irq_bank_map)
-- 
2.35.1


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

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

* [PATCH 5/6] pinctrl: sunxi: Make some layout parameters dynamic
  2022-06-26  2:11 ` Samuel Holland
@ 2022-06-26  2:11   ` Samuel Holland
  -1 siblings, 0 replies; 56+ messages in thread
From: Samuel Holland @ 2022-06-26  2:11 UTC (permalink / raw)
  To: Chen-Yu Tsai, Jernej Skrabec, Linus Walleij
  Cc: Samuel Holland, Krzysztof Kozlowski, Maxime Ripard,
	Ondrej Jirman, Rob Herring, devicetree, linux-arm-kernel,
	linux-gpio, linux-kernel, linux-sunxi

Starting with the D1/D1s/T113 SoC, Allwinner changed the layout of the
pinctrl registers. This new layout widens the drive level field, which
affects the pull register offset and the overall bank size.

In order to support multiple register layouts, some of the layout
parameters need to be set based on the pinctrl variant. This requires
passing the pinctrl struct pointer to the register/offset calculation
functions.

Signed-off-by: Samuel Holland <samuel@sholland.org>
---

 drivers/pinctrl/sunxi/pinctrl-sunxi.c | 44 ++++++++++++++++-----------
 drivers/pinctrl/sunxi/pinctrl-sunxi.h |  3 ++
 2 files changed, 29 insertions(+), 18 deletions(-)

diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
index 78b7ab69d7a5..ec7daaa5666b 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
@@ -59,45 +59,49 @@ static struct irq_chip sunxi_pinctrl_level_irq_chip;
  * The following functions calculate the register and the bit offset to access.
  * They take a pin number which is relative to the start of the current device.
  */
-static void sunxi_mux_reg(u32 pin, u32 *reg, u32 *shift, u32 *mask)
+static void sunxi_mux_reg(const struct sunxi_pinctrl *pctl,
+			  u32 pin, u32 *reg, u32 *shift, u32 *mask)
 {
 	u32 bank   = pin / PINS_PER_BANK;
 	u32 offset = pin % PINS_PER_BANK * MUX_FIELD_WIDTH;
 
-	*reg   = bank * BANK_MEM_SIZE + MUX_REGS_OFFSET +
+	*reg   = bank * pctl->bank_mem_size + MUX_REGS_OFFSET +
 		 offset / BITS_PER_TYPE(u32) * sizeof(u32);
 	*shift = offset % BITS_PER_TYPE(u32);
 	*mask  = (BIT(MUX_FIELD_WIDTH) - 1) << *shift;
 }
 
-static void sunxi_data_reg(u32 pin, u32 *reg, u32 *shift, u32 *mask)
+static void sunxi_data_reg(const struct sunxi_pinctrl *pctl,
+			   u32 pin, u32 *reg, u32 *shift, u32 *mask)
 {
 	u32 bank   = pin / PINS_PER_BANK;
 	u32 offset = pin % PINS_PER_BANK * DATA_FIELD_WIDTH;
 
-	*reg   = bank * BANK_MEM_SIZE + DATA_REGS_OFFSET +
+	*reg   = bank * pctl->bank_mem_size + DATA_REGS_OFFSET +
 		 offset / BITS_PER_TYPE(u32) * sizeof(u32);
 	*shift = offset % BITS_PER_TYPE(u32);
 	*mask  = (BIT(DATA_FIELD_WIDTH) - 1) << *shift;
 }
 
-static void sunxi_dlevel_reg(u32 pin, u32 *reg, u32 *shift, u32 *mask)
+static void sunxi_dlevel_reg(const struct sunxi_pinctrl *pctl,
+			     u32 pin, u32 *reg, u32 *shift, u32 *mask)
 {
 	u32 bank   = pin / PINS_PER_BANK;
-	u32 offset = pin % PINS_PER_BANK * DLEVEL_FIELD_WIDTH;
+	u32 offset = pin % PINS_PER_BANK * pctl->dlevel_field_width;
 
-	*reg   = bank * BANK_MEM_SIZE + DLEVEL_REGS_OFFSET +
+	*reg   = bank * pctl->bank_mem_size + DLEVEL_REGS_OFFSET +
 		 offset / BITS_PER_TYPE(u32) * sizeof(u32);
 	*shift = offset % BITS_PER_TYPE(u32);
-	*mask  = (BIT(DLEVEL_FIELD_WIDTH) - 1) << *shift;
+	*mask  = (BIT(pctl->dlevel_field_width) - 1) << *shift;
 }
 
-static void sunxi_pull_reg(u32 pin, u32 *reg, u32 *shift, u32 *mask)
+static void sunxi_pull_reg(const struct sunxi_pinctrl *pctl,
+			   u32 pin, u32 *reg, u32 *shift, u32 *mask)
 {
 	u32 bank   = pin / PINS_PER_BANK;
 	u32 offset = pin % PINS_PER_BANK * PULL_FIELD_WIDTH;
 
-	*reg   = bank * BANK_MEM_SIZE + PULL_REGS_OFFSET +
+	*reg   = bank * pctl->bank_mem_size + pctl->pull_regs_offset +
 		 offset / BITS_PER_TYPE(u32) * sizeof(u32);
 	*shift = offset % BITS_PER_TYPE(u32);
 	*mask  = (BIT(PULL_FIELD_WIDTH) - 1) << *shift;
@@ -508,18 +512,19 @@ static const struct pinctrl_ops sunxi_pctrl_ops = {
 	.get_group_pins		= sunxi_pctrl_get_group_pins,
 };
 
-static int sunxi_pconf_reg(unsigned pin, enum pin_config_param param,
+static int sunxi_pconf_reg(const struct sunxi_pinctrl *pctl,
+			   u32 pin, enum pin_config_param param,
 			   u32 *reg, u32 *shift, u32 *mask)
 {
 	switch (param) {
 	case PIN_CONFIG_DRIVE_STRENGTH:
-		sunxi_dlevel_reg(pin, reg, shift, mask);
+		sunxi_dlevel_reg(pctl, pin, reg, shift, mask);
 		break;
 
 	case PIN_CONFIG_BIAS_PULL_UP:
 	case PIN_CONFIG_BIAS_PULL_DOWN:
 	case PIN_CONFIG_BIAS_DISABLE:
-		sunxi_pull_reg(pin, reg, shift, mask);
+		sunxi_pull_reg(pctl, pin, reg, shift, mask);
 		break;
 
 	default:
@@ -540,7 +545,7 @@ static int sunxi_pconf_get(struct pinctrl_dev *pctldev, unsigned pin,
 
 	pin -= pctl->desc->pin_base;
 
-	ret = sunxi_pconf_reg(pin, param, &reg, &shift, &mask);
+	ret = sunxi_pconf_reg(pctl, pin, param, &reg, &shift, &mask);
 	if (ret < 0)
 		return ret;
 
@@ -606,7 +611,7 @@ static int sunxi_pconf_set(struct pinctrl_dev *pctldev, unsigned pin,
 		param = pinconf_to_config_param(configs[i]);
 		arg = pinconf_to_config_argument(configs[i]);
 
-		ret = sunxi_pconf_reg(pin, param, &reg, &shift, &mask);
+		ret = sunxi_pconf_reg(pctl, pin, param, &reg, &shift, &mask);
 		if (ret < 0)
 			return ret;
 
@@ -774,7 +779,7 @@ static void sunxi_pmx_set(struct pinctrl_dev *pctldev,
 	unsigned long flags;
 
 	pin -= pctl->desc->pin_base;
-	sunxi_mux_reg(pin, &reg, &shift, &mask);
+	sunxi_mux_reg(pctl, pin, &reg, &shift, &mask);
 
 	raw_spin_lock_irqsave(&pctl->lock, flags);
 
@@ -917,7 +922,7 @@ static int sunxi_pinctrl_gpio_get(struct gpio_chip *chip, unsigned offset)
 	u32 pin = offset + chip->base;
 	u32 reg, shift, mask, val;
 
-	sunxi_data_reg(offset, &reg, &shift, &mask);
+	sunxi_data_reg(pctl, offset, &reg, &shift, &mask);
 
 	if (set_mux)
 		sunxi_pmx_set(pctl->pctl_dev, pin, SUN4I_FUNC_INPUT);
@@ -937,7 +942,7 @@ static void sunxi_pinctrl_gpio_set(struct gpio_chip *chip,
 	u32 reg, shift, mask, val;
 	unsigned long flags;
 
-	sunxi_data_reg(offset, &reg, &shift, &mask);
+	sunxi_data_reg(pctl, offset, &reg, &shift, &mask);
 
 	raw_spin_lock_irqsave(&pctl->lock, flags);
 
@@ -1489,6 +1494,9 @@ int sunxi_pinctrl_init_with_variant(struct platform_device *pdev,
 	pctl->dev = &pdev->dev;
 	pctl->desc = desc;
 	pctl->variant = variant;
+	pctl->bank_mem_size = BANK_MEM_SIZE;
+	pctl->pull_regs_offset = PULL_REGS_OFFSET;
+	pctl->dlevel_field_width = DLEVEL_FIELD_WIDTH;
 
 	pctl->irq_array = devm_kcalloc(&pdev->dev,
 				       IRQ_PER_BANK * pctl->desc->irq_banks,
diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.h b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
index efaa97457e08..c705828add73 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.h
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
@@ -169,6 +169,9 @@ struct sunxi_pinctrl {
 	raw_spinlock_t			lock;
 	struct pinctrl_dev		*pctl_dev;
 	unsigned long			variant;
+	u32				bank_mem_size;
+	u32				pull_regs_offset;
+	u32				dlevel_field_width;
 };
 
 #define SUNXI_PIN(_pin, ...)					\
-- 
2.35.1


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

* [PATCH 5/6] pinctrl: sunxi: Make some layout parameters dynamic
@ 2022-06-26  2:11   ` Samuel Holland
  0 siblings, 0 replies; 56+ messages in thread
From: Samuel Holland @ 2022-06-26  2:11 UTC (permalink / raw)
  To: Chen-Yu Tsai, Jernej Skrabec, Linus Walleij
  Cc: Samuel Holland, Krzysztof Kozlowski, Maxime Ripard,
	Ondrej Jirman, Rob Herring, devicetree, linux-arm-kernel,
	linux-gpio, linux-kernel, linux-sunxi

Starting with the D1/D1s/T113 SoC, Allwinner changed the layout of the
pinctrl registers. This new layout widens the drive level field, which
affects the pull register offset and the overall bank size.

In order to support multiple register layouts, some of the layout
parameters need to be set based on the pinctrl variant. This requires
passing the pinctrl struct pointer to the register/offset calculation
functions.

Signed-off-by: Samuel Holland <samuel@sholland.org>
---

 drivers/pinctrl/sunxi/pinctrl-sunxi.c | 44 ++++++++++++++++-----------
 drivers/pinctrl/sunxi/pinctrl-sunxi.h |  3 ++
 2 files changed, 29 insertions(+), 18 deletions(-)

diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
index 78b7ab69d7a5..ec7daaa5666b 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
@@ -59,45 +59,49 @@ static struct irq_chip sunxi_pinctrl_level_irq_chip;
  * The following functions calculate the register and the bit offset to access.
  * They take a pin number which is relative to the start of the current device.
  */
-static void sunxi_mux_reg(u32 pin, u32 *reg, u32 *shift, u32 *mask)
+static void sunxi_mux_reg(const struct sunxi_pinctrl *pctl,
+			  u32 pin, u32 *reg, u32 *shift, u32 *mask)
 {
 	u32 bank   = pin / PINS_PER_BANK;
 	u32 offset = pin % PINS_PER_BANK * MUX_FIELD_WIDTH;
 
-	*reg   = bank * BANK_MEM_SIZE + MUX_REGS_OFFSET +
+	*reg   = bank * pctl->bank_mem_size + MUX_REGS_OFFSET +
 		 offset / BITS_PER_TYPE(u32) * sizeof(u32);
 	*shift = offset % BITS_PER_TYPE(u32);
 	*mask  = (BIT(MUX_FIELD_WIDTH) - 1) << *shift;
 }
 
-static void sunxi_data_reg(u32 pin, u32 *reg, u32 *shift, u32 *mask)
+static void sunxi_data_reg(const struct sunxi_pinctrl *pctl,
+			   u32 pin, u32 *reg, u32 *shift, u32 *mask)
 {
 	u32 bank   = pin / PINS_PER_BANK;
 	u32 offset = pin % PINS_PER_BANK * DATA_FIELD_WIDTH;
 
-	*reg   = bank * BANK_MEM_SIZE + DATA_REGS_OFFSET +
+	*reg   = bank * pctl->bank_mem_size + DATA_REGS_OFFSET +
 		 offset / BITS_PER_TYPE(u32) * sizeof(u32);
 	*shift = offset % BITS_PER_TYPE(u32);
 	*mask  = (BIT(DATA_FIELD_WIDTH) - 1) << *shift;
 }
 
-static void sunxi_dlevel_reg(u32 pin, u32 *reg, u32 *shift, u32 *mask)
+static void sunxi_dlevel_reg(const struct sunxi_pinctrl *pctl,
+			     u32 pin, u32 *reg, u32 *shift, u32 *mask)
 {
 	u32 bank   = pin / PINS_PER_BANK;
-	u32 offset = pin % PINS_PER_BANK * DLEVEL_FIELD_WIDTH;
+	u32 offset = pin % PINS_PER_BANK * pctl->dlevel_field_width;
 
-	*reg   = bank * BANK_MEM_SIZE + DLEVEL_REGS_OFFSET +
+	*reg   = bank * pctl->bank_mem_size + DLEVEL_REGS_OFFSET +
 		 offset / BITS_PER_TYPE(u32) * sizeof(u32);
 	*shift = offset % BITS_PER_TYPE(u32);
-	*mask  = (BIT(DLEVEL_FIELD_WIDTH) - 1) << *shift;
+	*mask  = (BIT(pctl->dlevel_field_width) - 1) << *shift;
 }
 
-static void sunxi_pull_reg(u32 pin, u32 *reg, u32 *shift, u32 *mask)
+static void sunxi_pull_reg(const struct sunxi_pinctrl *pctl,
+			   u32 pin, u32 *reg, u32 *shift, u32 *mask)
 {
 	u32 bank   = pin / PINS_PER_BANK;
 	u32 offset = pin % PINS_PER_BANK * PULL_FIELD_WIDTH;
 
-	*reg   = bank * BANK_MEM_SIZE + PULL_REGS_OFFSET +
+	*reg   = bank * pctl->bank_mem_size + pctl->pull_regs_offset +
 		 offset / BITS_PER_TYPE(u32) * sizeof(u32);
 	*shift = offset % BITS_PER_TYPE(u32);
 	*mask  = (BIT(PULL_FIELD_WIDTH) - 1) << *shift;
@@ -508,18 +512,19 @@ static const struct pinctrl_ops sunxi_pctrl_ops = {
 	.get_group_pins		= sunxi_pctrl_get_group_pins,
 };
 
-static int sunxi_pconf_reg(unsigned pin, enum pin_config_param param,
+static int sunxi_pconf_reg(const struct sunxi_pinctrl *pctl,
+			   u32 pin, enum pin_config_param param,
 			   u32 *reg, u32 *shift, u32 *mask)
 {
 	switch (param) {
 	case PIN_CONFIG_DRIVE_STRENGTH:
-		sunxi_dlevel_reg(pin, reg, shift, mask);
+		sunxi_dlevel_reg(pctl, pin, reg, shift, mask);
 		break;
 
 	case PIN_CONFIG_BIAS_PULL_UP:
 	case PIN_CONFIG_BIAS_PULL_DOWN:
 	case PIN_CONFIG_BIAS_DISABLE:
-		sunxi_pull_reg(pin, reg, shift, mask);
+		sunxi_pull_reg(pctl, pin, reg, shift, mask);
 		break;
 
 	default:
@@ -540,7 +545,7 @@ static int sunxi_pconf_get(struct pinctrl_dev *pctldev, unsigned pin,
 
 	pin -= pctl->desc->pin_base;
 
-	ret = sunxi_pconf_reg(pin, param, &reg, &shift, &mask);
+	ret = sunxi_pconf_reg(pctl, pin, param, &reg, &shift, &mask);
 	if (ret < 0)
 		return ret;
 
@@ -606,7 +611,7 @@ static int sunxi_pconf_set(struct pinctrl_dev *pctldev, unsigned pin,
 		param = pinconf_to_config_param(configs[i]);
 		arg = pinconf_to_config_argument(configs[i]);
 
-		ret = sunxi_pconf_reg(pin, param, &reg, &shift, &mask);
+		ret = sunxi_pconf_reg(pctl, pin, param, &reg, &shift, &mask);
 		if (ret < 0)
 			return ret;
 
@@ -774,7 +779,7 @@ static void sunxi_pmx_set(struct pinctrl_dev *pctldev,
 	unsigned long flags;
 
 	pin -= pctl->desc->pin_base;
-	sunxi_mux_reg(pin, &reg, &shift, &mask);
+	sunxi_mux_reg(pctl, pin, &reg, &shift, &mask);
 
 	raw_spin_lock_irqsave(&pctl->lock, flags);
 
@@ -917,7 +922,7 @@ static int sunxi_pinctrl_gpio_get(struct gpio_chip *chip, unsigned offset)
 	u32 pin = offset + chip->base;
 	u32 reg, shift, mask, val;
 
-	sunxi_data_reg(offset, &reg, &shift, &mask);
+	sunxi_data_reg(pctl, offset, &reg, &shift, &mask);
 
 	if (set_mux)
 		sunxi_pmx_set(pctl->pctl_dev, pin, SUN4I_FUNC_INPUT);
@@ -937,7 +942,7 @@ static void sunxi_pinctrl_gpio_set(struct gpio_chip *chip,
 	u32 reg, shift, mask, val;
 	unsigned long flags;
 
-	sunxi_data_reg(offset, &reg, &shift, &mask);
+	sunxi_data_reg(pctl, offset, &reg, &shift, &mask);
 
 	raw_spin_lock_irqsave(&pctl->lock, flags);
 
@@ -1489,6 +1494,9 @@ int sunxi_pinctrl_init_with_variant(struct platform_device *pdev,
 	pctl->dev = &pdev->dev;
 	pctl->desc = desc;
 	pctl->variant = variant;
+	pctl->bank_mem_size = BANK_MEM_SIZE;
+	pctl->pull_regs_offset = PULL_REGS_OFFSET;
+	pctl->dlevel_field_width = DLEVEL_FIELD_WIDTH;
 
 	pctl->irq_array = devm_kcalloc(&pdev->dev,
 				       IRQ_PER_BANK * pctl->desc->irq_banks,
diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.h b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
index efaa97457e08..c705828add73 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.h
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
@@ -169,6 +169,9 @@ struct sunxi_pinctrl {
 	raw_spinlock_t			lock;
 	struct pinctrl_dev		*pctl_dev;
 	unsigned long			variant;
+	u32				bank_mem_size;
+	u32				pull_regs_offset;
+	u32				dlevel_field_width;
 };
 
 #define SUNXI_PIN(_pin, ...)					\
-- 
2.35.1


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

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

* [PATCH 6/6] pinctrl: sunxi: Add driver for Allwinner D1/D1s
  2022-06-26  2:11 ` Samuel Holland
@ 2022-06-26  2:11   ` Samuel Holland
  -1 siblings, 0 replies; 56+ messages in thread
From: Samuel Holland @ 2022-06-26  2:11 UTC (permalink / raw)
  To: Chen-Yu Tsai, Jernej Skrabec, Linus Walleij
  Cc: Samuel Holland, Krzysztof Kozlowski, Maxime Ripard,
	Ondrej Jirman, Rob Herring, devicetree, linux-arm-kernel,
	linux-gpio, linux-kernel, linux-sunxi

These SoCs contain a pinctrl with a new register layout. Use the variant
parameter to set the right register offsets. This pinctrl also increases
the number of functions per pin from 8 to 16, taking advantage of all 4
bits in the mux config field (so far, only functions 0-8 and 14-15 are
used). This increases the maximum possible number of functions.

D1s is a low pin count version of the D1 SoC, with some pins omitted.
The remaining pins have the same function assignments as D1.

Signed-off-by: Samuel Holland <samuel@sholland.org>
---

 drivers/pinctrl/sunxi/Kconfig             |   5 +
 drivers/pinctrl/sunxi/Makefile            |   1 +
 drivers/pinctrl/sunxi/pinctrl-sun20i-d1.c | 860 ++++++++++++++++++++++
 drivers/pinctrl/sunxi/pinctrl-sunxi.c     |  16 +-
 drivers/pinctrl/sunxi/pinctrl-sunxi.h     |   7 +
 5 files changed, 884 insertions(+), 5 deletions(-)
 create mode 100644 drivers/pinctrl/sunxi/pinctrl-sun20i-d1.c

diff --git a/drivers/pinctrl/sunxi/Kconfig b/drivers/pinctrl/sunxi/Kconfig
index 33751a6a0757..a6ac1c1f2585 100644
--- a/drivers/pinctrl/sunxi/Kconfig
+++ b/drivers/pinctrl/sunxi/Kconfig
@@ -84,6 +84,11 @@ config PINCTRL_SUN9I_A80_R
 	depends on RESET_CONTROLLER
 	select PINCTRL_SUNXI
 
+config PINCTRL_SUN20I_D1
+	bool "Support for the Allwinner D1 PIO"
+	default RISCV && ARCH_SUNXI
+	select PINCTRL_SUNXI
+
 config PINCTRL_SUN50I_A64
 	bool "Support for the Allwinner A64 PIO"
 	default ARM64 && ARCH_SUNXI
diff --git a/drivers/pinctrl/sunxi/Makefile b/drivers/pinctrl/sunxi/Makefile
index d3440c42b9d6..2ff5a55927ad 100644
--- a/drivers/pinctrl/sunxi/Makefile
+++ b/drivers/pinctrl/sunxi/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_PINCTRL_SUN8I_A83T_R)	+= pinctrl-sun8i-a83t-r.o
 obj-$(CONFIG_PINCTRL_SUN8I_H3)		+= pinctrl-sun8i-h3.o
 obj-$(CONFIG_PINCTRL_SUN8I_H3_R)	+= pinctrl-sun8i-h3-r.o
 obj-$(CONFIG_PINCTRL_SUN8I_V3S)		+= pinctrl-sun8i-v3s.o
+obj-$(CONFIG_PINCTRL_SUN20I_D1)		+= pinctrl-sun20i-d1.o
 obj-$(CONFIG_PINCTRL_SUN50I_H5)		+= pinctrl-sun50i-h5.o
 obj-$(CONFIG_PINCTRL_SUN50I_H6)		+= pinctrl-sun50i-h6.o
 obj-$(CONFIG_PINCTRL_SUN50I_H6_R)	+= pinctrl-sun50i-h6-r.o
diff --git a/drivers/pinctrl/sunxi/pinctrl-sun20i-d1.c b/drivers/pinctrl/sunxi/pinctrl-sun20i-d1.c
new file mode 100644
index 000000000000..7247c1f1d92c
--- /dev/null
+++ b/drivers/pinctrl/sunxi/pinctrl-sun20i-d1.c
@@ -0,0 +1,860 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Allwinner D1 SoC pinctrl driver.
+ *
+ * Copyright (c) 2020 wuyan@allwinnertech.com
+ * Copyright (c) 2021-2022 Samuel Holland <samuel@sholland.org>
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/pinctrl.h>
+
+#include "pinctrl-sunxi.h"
+
+static const struct sunxi_desc_pin d1_pins[] = {
+	/* PB */
+	SUNXI_PIN_VARIANT(SUNXI_PINCTRL_PIN(B, 0),
+		PINCTRL_SUN20I_D1,
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "pwm"),
+		SUNXI_FUNCTION(0x3, "ir"),		/* TX */
+		SUNXI_FUNCTION(0x4, "i2c2"),		/* SCK */
+		SUNXI_FUNCTION(0x5, "spi1"),		/* WP */
+		SUNXI_FUNCTION(0x6, "uart0"),		/* TX */
+		SUNXI_FUNCTION(0x7, "uart2"),		/* TX */
+		SUNXI_FUNCTION(0x8, "spdif"),		/* OUT */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 0)),
+	SUNXI_PIN_VARIANT(SUNXI_PINCTRL_PIN(B, 1),
+		PINCTRL_SUN20I_D1,
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "pwm"),
+		SUNXI_FUNCTION(0x3, "i2s2_dout"),	/* DOUT3 */
+		SUNXI_FUNCTION(0x4, "i2c2"),		/* SDA */
+		SUNXI_FUNCTION(0x5, "i2s2_din"),	/* DIN3 */
+		SUNXI_FUNCTION(0x6, "uart0"),		/* RX */
+		SUNXI_FUNCTION(0x7, "uart2"),		/* RX */
+		SUNXI_FUNCTION(0x8, "ir"),		/* RX */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 1)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 2),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* D0 */
+		SUNXI_FUNCTION(0x3, "i2s2_dout"),	/* DOUT2 */
+		SUNXI_FUNCTION(0x4, "i2c0"),		/* SDA */
+		SUNXI_FUNCTION(0x5, "i2s2_din"),	/* DIN2 */
+		SUNXI_FUNCTION(0x6, "lcd0"),		/* D18 */
+		SUNXI_FUNCTION(0x7, "uart4"),		/* TX */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 2)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 3),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* D1 */
+		SUNXI_FUNCTION(0x3, "i2s2_dout"),	/* DOUT1 */
+		SUNXI_FUNCTION(0x4, "i2c0"),		/* SCK */
+		SUNXI_FUNCTION(0x5, "i2s2_din"),	/* DIN0 */
+		SUNXI_FUNCTION(0x6, "lcd0"),		/* D19 */
+		SUNXI_FUNCTION(0x7, "uart4"),		/* RX */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 3)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 4),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* D8 */
+		SUNXI_FUNCTION(0x3, "i2s2_dout"),	/* DOUT0 */
+		SUNXI_FUNCTION(0x4, "i2c1"),		/* SCK */
+		SUNXI_FUNCTION(0x5, "i2s2_din"),	/* DIN1 */
+		SUNXI_FUNCTION(0x6, "lcd0"),		/* D20 */
+		SUNXI_FUNCTION(0x7, "uart5"),		/* TX */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 4)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 5),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* D9 */
+		SUNXI_FUNCTION(0x3, "i2s2"),		/* BCLK */
+		SUNXI_FUNCTION(0x4, "i2c1"),		/* SDA */
+		SUNXI_FUNCTION(0x5, "pwm"),
+		SUNXI_FUNCTION(0x6, "lcd0"),		/* D21 */
+		SUNXI_FUNCTION(0x7, "uart5"),		/* RX */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 5)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 6),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* D16 */
+		SUNXI_FUNCTION(0x3, "i2s2"),		/* LRCK */
+		SUNXI_FUNCTION(0x4, "i2c3"),		/* SCK */
+		SUNXI_FUNCTION(0x5, "pwm"),
+		SUNXI_FUNCTION(0x6, "lcd0"),		/* D22 */
+		SUNXI_FUNCTION(0x7, "uart3"),		/* TX */
+		SUNXI_FUNCTION(0x8, "bist0"),		/* BIST_RESULT0 */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 6)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 7),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* D17 */
+		SUNXI_FUNCTION(0x3, "i2s2"),		/* MCLK */
+		SUNXI_FUNCTION(0x4, "i2c3"),		/* SDA */
+		SUNXI_FUNCTION(0x5, "ir"),		/* RX */
+		SUNXI_FUNCTION(0x6, "lcd0"),		/* D23 */
+		SUNXI_FUNCTION(0x7, "uart3"),		/* RX */
+		SUNXI_FUNCTION(0x8, "bist1"),		/* BIST_RESULT1 */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 7)),
+	SUNXI_PIN_VARIANT(SUNXI_PINCTRL_PIN(B, 8),
+		PINCTRL_SUN20I_D1,
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "dmic"),		/* DATA3 */
+		SUNXI_FUNCTION(0x3, "pwm"),
+		SUNXI_FUNCTION(0x4, "i2c2"),		/* SCK */
+		SUNXI_FUNCTION(0x5, "spi1"),		/* HOLD */
+		SUNXI_FUNCTION(0x6, "uart0"),		/* TX */
+		SUNXI_FUNCTION(0x7, "uart1"),		/* TX */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 8)),
+	SUNXI_PIN_VARIANT(SUNXI_PINCTRL_PIN(B, 9),
+		PINCTRL_SUN20I_D1,
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "dmic"),		/* DATA2 */
+		SUNXI_FUNCTION(0x3, "pwm"),
+		SUNXI_FUNCTION(0x4, "i2c2"),		/* SDA */
+		SUNXI_FUNCTION(0x5, "spi1"),		/* MISO */
+		SUNXI_FUNCTION(0x6, "uart0"),		/* RX */
+		SUNXI_FUNCTION(0x7, "uart1"),		/* RX */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 9)),
+	SUNXI_PIN_VARIANT(SUNXI_PINCTRL_PIN(B, 10),
+		PINCTRL_SUN20I_D1,
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "dmic"),		/* DATA1 */
+		SUNXI_FUNCTION(0x3, "pwm"),
+		SUNXI_FUNCTION(0x4, "i2c0"),		/* SCK */
+		SUNXI_FUNCTION(0x5, "spi1"),		/* MOSI */
+		SUNXI_FUNCTION(0x6, "clk"),		/* FANOUT0 */
+		SUNXI_FUNCTION(0x7, "uart1"),		/* RTS */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 10)),
+	SUNXI_PIN_VARIANT(SUNXI_PINCTRL_PIN(B, 11),
+		PINCTRL_SUN20I_D1,
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "dmic"),		/* DATA0 */
+		SUNXI_FUNCTION(0x3, "pwm"),
+		SUNXI_FUNCTION(0x4, "i2c0"),		/* SDA */
+		SUNXI_FUNCTION(0x5, "spi1"),		/* CLK */
+		SUNXI_FUNCTION(0x6, "clk"),		/* FANOUT1 */
+		SUNXI_FUNCTION(0x7, "uart1"),		/* CTS */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 11)),
+	SUNXI_PIN_VARIANT(SUNXI_PINCTRL_PIN(B, 12),
+		PINCTRL_SUN20I_D1,
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "dmic"),		/* CLK */
+		SUNXI_FUNCTION(0x3, "pwm"),
+		SUNXI_FUNCTION(0x4, "spdif"),		/* IN */
+		SUNXI_FUNCTION(0x5, "spi1"),		/* CS0 */
+		SUNXI_FUNCTION(0x6, "clk"),		/* FANOUT2 */
+		SUNXI_FUNCTION(0x7, "ir"),		/* RX */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 12)),
+	/* PC */
+	SUNXI_PIN_VARIANT(SUNXI_PINCTRL_PIN(C, 0),
+		PINCTRL_SUN20I_D1,
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "uart2"),		/* TX */
+		SUNXI_FUNCTION(0x3, "i2c2"),		/* SCK */
+		SUNXI_FUNCTION(0x4, "ledc"),
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 0)),
+	SUNXI_PIN_VARIANT(SUNXI_PINCTRL_PIN(C, 1),
+		PINCTRL_SUN20I_D1,
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "uart2"),		/* RX */
+		SUNXI_FUNCTION(0x3, "i2c2"),		/* SDA */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 1)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 2),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "spi0"),		/* CLK */
+		SUNXI_FUNCTION(0x3, "mmc2"),		/* CLK */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 2)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 3),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "spi0"),		/* CS0 */
+		SUNXI_FUNCTION(0x3, "mmc2"),		/* CMD */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 3)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 4),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "spi0"),		/* MOSI */
+		SUNXI_FUNCTION(0x3, "mmc2"),		/* D2 */
+		SUNXI_FUNCTION(0x4, "boot"),		/* SEL0 */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 4)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 5),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "spi0"),		/* MISO */
+		SUNXI_FUNCTION(0x3, "mmc2"),		/* D1 */
+		SUNXI_FUNCTION(0x4, "boot"),		/* SEL1 */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 5)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 6),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "spi0"),		/* WP */
+		SUNXI_FUNCTION(0x3, "mmc2"),		/* D0 */
+		SUNXI_FUNCTION(0x4, "uart3"),		/* TX */
+		SUNXI_FUNCTION(0x5, "i2c3"),		/* SCK */
+		SUNXI_FUNCTION(0x6, "pll"),		/* DBG-CLK */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 6)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 7),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "spi0"),		/* HOLD */
+		SUNXI_FUNCTION(0x3, "mmc2"),		/* D3 */
+		SUNXI_FUNCTION(0x4, "uart3"),		/* RX */
+		SUNXI_FUNCTION(0x5, "i2c3"),		/* SDA */
+		SUNXI_FUNCTION(0x6, "tcon"),		/* TRIG0 */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 7)),
+	/* PD */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 0),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* D2 */
+		SUNXI_FUNCTION(0x3, "lvds0"),		/* V0P */
+		SUNXI_FUNCTION(0x4, "dsi"),		/* D0P */
+		SUNXI_FUNCTION(0x5, "i2c0"),		/* SCK */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 0)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 1),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* D3 */
+		SUNXI_FUNCTION(0x3, "lvds0"),		/* V0N */
+		SUNXI_FUNCTION(0x4, "dsi"),		/* D0N */
+		SUNXI_FUNCTION(0x5, "uart2"),		/* TX */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 1)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 2),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* D4 */
+		SUNXI_FUNCTION(0x3, "lvds0"),		/* V1P */
+		SUNXI_FUNCTION(0x4, "dsi"),		/* D1P */
+		SUNXI_FUNCTION(0x5, "uart2"),		/* RX */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 2)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 3),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* D5 */
+		SUNXI_FUNCTION(0x3, "lvds0"),		/* V1N */
+		SUNXI_FUNCTION(0x4, "dsi"),		/* D1N */
+		SUNXI_FUNCTION(0x5, "uart2"),		/* RTS */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 3)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 4),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* D6 */
+		SUNXI_FUNCTION(0x3, "lvds0"),		/* V2P */
+		SUNXI_FUNCTION(0x4, "dsi"),		/* CKP */
+		SUNXI_FUNCTION(0x5, "uart2"),		/* CTS */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 4)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 5),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* D7 */
+		SUNXI_FUNCTION(0x3, "lvds0"),		/* V2N */
+		SUNXI_FUNCTION(0x4, "dsi"),		/* CKN */
+		SUNXI_FUNCTION(0x5, "uart5"),		/* TX */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 5)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 6),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* D10 */
+		SUNXI_FUNCTION(0x3, "lvds0"),		/* CKP */
+		SUNXI_FUNCTION(0x4, "dsi"),		/* D2P */
+		SUNXI_FUNCTION(0x5, "uart5"),		/* RX */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 6)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 7),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* D11 */
+		SUNXI_FUNCTION(0x3, "lvds0"),		/* CKN */
+		SUNXI_FUNCTION(0x4, "dsi"),		/* D2N */
+		SUNXI_FUNCTION(0x5, "uart4"),		/* TX */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 7)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 8),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* D12 */
+		SUNXI_FUNCTION(0x3, "lvds0"),		/* V3P */
+		SUNXI_FUNCTION(0x4, "dsi"),		/* D3P */
+		SUNXI_FUNCTION(0x5, "uart4"),		/* RX */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 8)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 9),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* D13 */
+		SUNXI_FUNCTION(0x3, "lvds0"),		/* V3N */
+		SUNXI_FUNCTION(0x4, "dsi"),		/* D3N */
+		SUNXI_FUNCTION(0x5, "pwm"),
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 9)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 10),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* D14 */
+		SUNXI_FUNCTION(0x3, "lvds1"),		/* V0P */
+		SUNXI_FUNCTION(0x4, "spi1"),		/* CS0 */
+		SUNXI_FUNCTION(0x5, "uart3"),		/* TX */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 10)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 11),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* D15 */
+		SUNXI_FUNCTION(0x3, "lvds1"),		/* V0N */
+		SUNXI_FUNCTION(0x4, "spi1"),		/* CLK */
+		SUNXI_FUNCTION(0x5, "uart3"),		/* RX */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 11)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 12),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* D18 */
+		SUNXI_FUNCTION(0x3, "lvds1"),		/* V1P */
+		SUNXI_FUNCTION(0x4, "spi1"),		/* MOSI */
+		SUNXI_FUNCTION(0x5, "i2c0"),		/* SDA */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 12)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 13),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* D19 */
+		SUNXI_FUNCTION(0x3, "lvds1"),		/* V1N */
+		SUNXI_FUNCTION(0x4, "spi1"),		/* MISO */
+		SUNXI_FUNCTION(0x5, "uart3"),		/* RTS */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 13)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 14),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* D20 */
+		SUNXI_FUNCTION(0x3, "lvds1"),		/* V2P */
+		SUNXI_FUNCTION(0x4, "spi1"),		/* HOLD */
+		SUNXI_FUNCTION(0x5, "uart3"),		/* CTS */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 14)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 15),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* D21 */
+		SUNXI_FUNCTION(0x3, "lvds1"),		/* V2N */
+		SUNXI_FUNCTION(0x4, "spi1"),		/* WP */
+		SUNXI_FUNCTION(0x5, "ir"),		/* RX */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 15)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 16),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* D22 */
+		SUNXI_FUNCTION(0x3, "lvds1"),		/* CKP */
+		SUNXI_FUNCTION(0x4, "dmic"),		/* DATA3 */
+		SUNXI_FUNCTION(0x5, "pwm"),
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 16)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 17),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* D23 */
+		SUNXI_FUNCTION(0x3, "lvds1"),		/* CKN */
+		SUNXI_FUNCTION(0x4, "dmic"),		/* DATA2 */
+		SUNXI_FUNCTION(0x5, "pwm"),
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 17)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 18),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* CLK */
+		SUNXI_FUNCTION(0x3, "lvds1"),		/* V3P */
+		SUNXI_FUNCTION(0x4, "dmic"),		/* DATA1 */
+		SUNXI_FUNCTION(0x5, "pwm"),
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 18)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 19),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* DE */
+		SUNXI_FUNCTION(0x3, "lvds1"),		/* V3N */
+		SUNXI_FUNCTION(0x4, "dmic"),		/* DATA0 */
+		SUNXI_FUNCTION(0x5, "pwm"),
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 19)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 20),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* HSYNC */
+		SUNXI_FUNCTION(0x3, "i2c2"),		/* SCK */
+		SUNXI_FUNCTION(0x4, "dmic"),		/* CLK */
+		SUNXI_FUNCTION(0x5, "pwm"),
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 20)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 21),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* VSYNC */
+		SUNXI_FUNCTION(0x3, "i2c2"),		/* SDA */
+		SUNXI_FUNCTION(0x4, "uart1"),		/* TX */
+		SUNXI_FUNCTION(0x5, "pwm"),
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 21)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 22),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "spdif"),		/* OUT */
+		SUNXI_FUNCTION(0x3, "ir"),		/* RX */
+		SUNXI_FUNCTION(0x4, "uart1"),		/* RX */
+		SUNXI_FUNCTION(0x5, "pwm"),
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 22)),
+	/* PE */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 0),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "ncsi0"),		/* HSYNC */
+		SUNXI_FUNCTION(0x3, "uart2"),		/* RTS */
+		SUNXI_FUNCTION(0x4, "i2c1"),		/* SCK */
+		SUNXI_FUNCTION(0x5, "lcd0"),		/* HSYNC */
+		SUNXI_FUNCTION(0x8, "emac"),		/* RXCTL/CRS_DV */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 0)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 1),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "ncsi0"),		/* VSYNC */
+		SUNXI_FUNCTION(0x3, "uart2"),		/* CTS */
+		SUNXI_FUNCTION(0x4, "i2c1"),		/* SDA */
+		SUNXI_FUNCTION(0x5, "lcd0"),		/* VSYNC */
+		SUNXI_FUNCTION(0x8, "emac"),		/* RXD0 */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 1)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 2),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "ncsi0"),		/* PCLK */
+		SUNXI_FUNCTION(0x3, "uart2"),		/* TX */
+		SUNXI_FUNCTION(0x4, "i2c0"),		/* SCK */
+		SUNXI_FUNCTION(0x5, "clk"),		/* FANOUT0 */
+		SUNXI_FUNCTION(0x6, "uart0"),		/* TX */
+		SUNXI_FUNCTION(0x8, "emac"),		/* RXD1 */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 2)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 3),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "csi0"),		/* MCLK */
+		SUNXI_FUNCTION(0x3, "uart2"),		/* RX */
+		SUNXI_FUNCTION(0x4, "i2c0"),		/* SDA */
+		SUNXI_FUNCTION(0x5, "clk"),		/* FANOUT1 */
+		SUNXI_FUNCTION(0x6, "uart0"),		/* RX */
+		SUNXI_FUNCTION(0x8, "emac"),		/* TXCK */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 3)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 4),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "ncsi0"),		/* D0 */
+		SUNXI_FUNCTION(0x3, "uart4"),		/* TX */
+		SUNXI_FUNCTION(0x4, "i2c2"),		/* SCK */
+		SUNXI_FUNCTION(0x5, "clk"),		/* FANOUT2 */
+		SUNXI_FUNCTION(0x6, "d_jtag"),		/* MS */
+		SUNXI_FUNCTION(0x7, "r_jtag"),		/* MS */
+		SUNXI_FUNCTION(0x8, "emac"),		/* TXD0 */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 4)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 5),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "ncsi0"),		/* D1 */
+		SUNXI_FUNCTION(0x3, "uart4"),		/* RX */
+		SUNXI_FUNCTION(0x4, "i2c2"),		/* SDA */
+		SUNXI_FUNCTION(0x5, "ledc"),
+		SUNXI_FUNCTION(0x6, "d_jtag"),		/* D1 */
+		SUNXI_FUNCTION(0x7, "r_jtag"),		/* D1 */
+		SUNXI_FUNCTION(0x8, "emac"),		/* TXD1 */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 5)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 6),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "ncsi0"),		/* D2 */
+		SUNXI_FUNCTION(0x3, "uart5"),		/* TX */
+		SUNXI_FUNCTION(0x4, "i2c3"),		/* SCK */
+		SUNXI_FUNCTION(0x5, "spdif"),		/* IN */
+		SUNXI_FUNCTION(0x6, "d_jtag"),		/* D0 */
+		SUNXI_FUNCTION(0x7, "r_jtag"),		/* D0 */
+		SUNXI_FUNCTION(0x8, "emac"),		/* TXCTL/TXEN */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 6)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 7),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "ncsi0"),		/* D3 */
+		SUNXI_FUNCTION(0x3, "uart5"),		/* RX */
+		SUNXI_FUNCTION(0x4, "i2c3"),		/* SDA */
+		SUNXI_FUNCTION(0x5, "spdif"),		/* OUT */
+		SUNXI_FUNCTION(0x6, "d_jtag"),		/* CK */
+		SUNXI_FUNCTION(0x7, "r_jtag"),		/* CK */
+		SUNXI_FUNCTION(0x8, "emac"),		/* CK */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 7)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 8),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "ncsi0"),		/* D4 */
+		SUNXI_FUNCTION(0x3, "uart1"),		/* RTS */
+		SUNXI_FUNCTION(0x4, "pwm"),
+		SUNXI_FUNCTION(0x5, "uart3"),		/* TX */
+		SUNXI_FUNCTION(0x6, "jtag"),		/* MS */
+		SUNXI_FUNCTION(0x8, "emac"),		/* MDC */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 8)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 9),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "ncsi0"),		/* D5 */
+		SUNXI_FUNCTION(0x3, "uart1"),		/* CTS */
+		SUNXI_FUNCTION(0x4, "pwm"),
+		SUNXI_FUNCTION(0x5, "uart3"),		/* RX */
+		SUNXI_FUNCTION(0x6, "jtag"),		/* D1 */
+		SUNXI_FUNCTION(0x8, "emac"),		/* MDIO */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 9)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 10),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "ncsi0"),		/* D6 */
+		SUNXI_FUNCTION(0x3, "uart1"),		/* TX */
+		SUNXI_FUNCTION(0x4, "pwm"),
+		SUNXI_FUNCTION(0x5, "ir"),		/* RX */
+		SUNXI_FUNCTION(0x6, "jtag"),		/* D0 */
+		SUNXI_FUNCTION(0x8, "emac"),		/* EPHY-25M */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 10)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 11),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "ncsi0"),		/* D7 */
+		SUNXI_FUNCTION(0x3, "uart1"),		/* RX */
+		SUNXI_FUNCTION(0x4, "i2s0_dout"),	/* DOUT3 */
+		SUNXI_FUNCTION(0x5, "i2s0_din"),	/* DIN3 */
+		SUNXI_FUNCTION(0x6, "jtag"),		/* CK */
+		SUNXI_FUNCTION(0x8, "emac"),		/* TXD2 */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 11)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 12),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "i2c2"),		/* SCK */
+		SUNXI_FUNCTION(0x3, "ncsi0"),		/* FIELD */
+		SUNXI_FUNCTION(0x4, "i2s0_dout"),	/* DOUT2 */
+		SUNXI_FUNCTION(0x5, "i2s0_din"),	/* DIN2 */
+		SUNXI_FUNCTION(0x8, "emac"),		/* TXD3 */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 12)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 13),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "i2c2"),		/* SDA */
+		SUNXI_FUNCTION(0x3, "pwm"),
+		SUNXI_FUNCTION(0x4, "i2s0_dout"),	/* DOUT0 */
+		SUNXI_FUNCTION(0x5, "i2s0_din"),	/* DIN1 */
+		SUNXI_FUNCTION(0x6, "dmic"),		/* DATA3 */
+		SUNXI_FUNCTION(0x8, "emac"),		/* RXD2 */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 13)),
+	SUNXI_PIN_VARIANT(SUNXI_PINCTRL_PIN(E, 14),
+		PINCTRL_SUN20I_D1,
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "i2c1"),		/* SCK */
+		SUNXI_FUNCTION(0x3, "d_jtag"),		/* MS */
+		SUNXI_FUNCTION(0x4, "i2s0_dout"),	/* DOUT1 */
+		SUNXI_FUNCTION(0x5, "i2s0_din"),	/* DIN0 */
+		SUNXI_FUNCTION(0x6, "dmic"),		/* DATA2 */
+		SUNXI_FUNCTION(0x8, "emac"),		/* RXD3 */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 14)),
+	SUNXI_PIN_VARIANT(SUNXI_PINCTRL_PIN(E, 15),
+		PINCTRL_SUN20I_D1,
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "i2c1"),		/* SDA */
+		SUNXI_FUNCTION(0x3, "d_jtag"),		/* D1 */
+		SUNXI_FUNCTION(0x4, "pwm"),
+		SUNXI_FUNCTION(0x5, "i2s0"),		/* LRCK */
+		SUNXI_FUNCTION(0x6, "dmic"),		/* DATA1 */
+		SUNXI_FUNCTION(0x8, "emac"),		/* RXCK */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 15)),
+	SUNXI_PIN_VARIANT(SUNXI_PINCTRL_PIN(E, 16),
+		PINCTRL_SUN20I_D1,
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "i2c3"),		/* SCK */
+		SUNXI_FUNCTION(0x3, "d_jtag"),		/* D0 */
+		SUNXI_FUNCTION(0x4, "pwm"),
+		SUNXI_FUNCTION(0x5, "i2s0"),		/* BCLK */
+		SUNXI_FUNCTION(0x6, "dmic"),		/* DATA0 */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 16)),
+	SUNXI_PIN_VARIANT(SUNXI_PINCTRL_PIN(E, 17),
+		PINCTRL_SUN20I_D1,
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "i2c3"),		/* SDA */
+		SUNXI_FUNCTION(0x3, "d_jtag"),		/* CK */
+		SUNXI_FUNCTION(0x4, "ir"),		/* TX */
+		SUNXI_FUNCTION(0x5, "i2s0"),		/* MCLK */
+		SUNXI_FUNCTION(0x6, "dmic"),		/* CLK */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 17)),
+	/* PF */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 0),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "mmc0"),		/* D1 */
+		SUNXI_FUNCTION(0x3, "jtag"),		/* MS */
+		SUNXI_FUNCTION(0x4, "r_jtag"),		/* MS */
+		SUNXI_FUNCTION(0x5, "i2s2_dout"),	/* DOUT1 */
+		SUNXI_FUNCTION(0x6, "i2s2_din"),	/* DIN0 */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 0)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 1),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "mmc0"),		/* D0 */
+		SUNXI_FUNCTION(0x3, "jtag"),		/* DI */
+		SUNXI_FUNCTION(0x4, "r_jtag"),		/* DI */
+		SUNXI_FUNCTION(0x5, "i2s2_dout"),	/* DOUT0 */
+		SUNXI_FUNCTION(0x6, "i2s2_din"),	/* DIN1 */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 1)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 2),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "mmc0"),		/* CLK */
+		SUNXI_FUNCTION(0x3, "uart0"),		/* TX */
+		SUNXI_FUNCTION(0x4, "i2c0"),		/* SCK */
+		SUNXI_FUNCTION(0x5, "ledc"),
+		SUNXI_FUNCTION(0x6, "spdif"),		/* IN */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 2)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 3),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "mmc0"),		/* CMD */
+		SUNXI_FUNCTION(0x3, "jtag"),		/* DO */
+		SUNXI_FUNCTION(0x4, "r_jtag"),		/* DO */
+		SUNXI_FUNCTION(0x5, "i2s2"),		/* BCLK */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 3)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 4),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "mmc0"),		/* D3 */
+		SUNXI_FUNCTION(0x3, "uart0"),		/* RX */
+		SUNXI_FUNCTION(0x4, "i2c0"),		/* SDA */
+		SUNXI_FUNCTION(0x5, "pwm"),
+		SUNXI_FUNCTION(0x6, "ir"),		/* TX */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 4)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 5),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "mmc0"),		/* D2 */
+		SUNXI_FUNCTION(0x3, "jtag"),		/* CK */
+		SUNXI_FUNCTION(0x4, "r_jtag"),		/* CK */
+		SUNXI_FUNCTION(0x5, "i2s2"),		/* LRCK */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 5)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 6),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x3, "spdif"),		/* OUT */
+		SUNXI_FUNCTION(0x4, "ir"),		/* RX */
+		SUNXI_FUNCTION(0x5, "i2s2"),		/* MCLK */
+		SUNXI_FUNCTION(0x6, "pwm"),
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 6)),
+	/* PG */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 0),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "mmc1"),		/* CLK */
+		SUNXI_FUNCTION(0x3, "uart3"),		/* TX */
+		SUNXI_FUNCTION(0x4, "emac"),		/* RXCTRL/CRS_DV */
+		SUNXI_FUNCTION(0x5, "pwm"),
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 0)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 1),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "mmc1"),		/* CMD */
+		SUNXI_FUNCTION(0x3, "uart3"),		/* RX */
+		SUNXI_FUNCTION(0x4, "emac"),		/* RXD0 */
+		SUNXI_FUNCTION(0x5, "pwm"),
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 1)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 2),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "mmc1"),		/* D0 */
+		SUNXI_FUNCTION(0x3, "uart3"),		/* RTS */
+		SUNXI_FUNCTION(0x4, "emac"),		/* RXD1 */
+		SUNXI_FUNCTION(0x5, "uart4"),		/* TX */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 2)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 3),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "mmc1"),		/* D1 */
+		SUNXI_FUNCTION(0x3, "uart3"),		/* CTS */
+		SUNXI_FUNCTION(0x4, "emac"),		/* TXCK */
+		SUNXI_FUNCTION(0x5, "uart4"),		/* RX */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 3)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 4),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "mmc1"),		/* D2 */
+		SUNXI_FUNCTION(0x3, "uart5"),		/* TX */
+		SUNXI_FUNCTION(0x4, "emac"),		/* TXD0 */
+		SUNXI_FUNCTION(0x5, "pwm"),
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 4)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 5),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "mmc1"),		/* D3 */
+		SUNXI_FUNCTION(0x3, "uart5"),		/* RX */
+		SUNXI_FUNCTION(0x4, "emac"),		/* TXD1 */
+		SUNXI_FUNCTION(0x5, "pwm"),
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 5)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 6),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "uart1"),		/* TX */
+		SUNXI_FUNCTION(0x3, "i2c2"),		/* SCK */
+		SUNXI_FUNCTION(0x4, "emac"),		/* TXD2 */
+		SUNXI_FUNCTION(0x5, "pwm"),
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 6)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 7),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "uart1"),		/* RX */
+		SUNXI_FUNCTION(0x3, "i2c2"),		/* SDA */
+		SUNXI_FUNCTION(0x4, "emac"),		/* TXD3 */
+		SUNXI_FUNCTION(0x5, "spdif"),		/* IN */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 7)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 8),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "uart1"),		/* RTS */
+		SUNXI_FUNCTION(0x3, "i2c1"),		/* SCK */
+		SUNXI_FUNCTION(0x4, "emac"),		/* RXD2 */
+		SUNXI_FUNCTION(0x5, "uart3"),		/* TX */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 8)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 9),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "uart1"),		/* CTS */
+		SUNXI_FUNCTION(0x3, "i2c1"),		/* SDA */
+		SUNXI_FUNCTION(0x4, "emac"),		/* RXD3 */
+		SUNXI_FUNCTION(0x5, "uart3"),		/* RX */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 9)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 10),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "pwm"),
+		SUNXI_FUNCTION(0x3, "i2c3"),		/* SCK */
+		SUNXI_FUNCTION(0x4, "emac"),		/* RXCK */
+		SUNXI_FUNCTION(0x5, "clk"),		/* FANOUT0 */
+		SUNXI_FUNCTION(0x6, "ir"),		/* RX */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 10)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 11),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "i2s1"),		/* MCLK */
+		SUNXI_FUNCTION(0x3, "i2c3"),		/* SDA */
+		SUNXI_FUNCTION(0x4, "emac"),		/* EPHY-25M */
+		SUNXI_FUNCTION(0x5, "clk"),		/* FANOUT1 */
+		SUNXI_FUNCTION(0x6, "tcon"),		/* TRIG0 */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 11)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 12),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "i2s1"),		/* LRCK */
+		SUNXI_FUNCTION(0x3, "i2c0"),		/* SCK */
+		SUNXI_FUNCTION(0x4, "emac"),		/* TXCTL/TXEN */
+		SUNXI_FUNCTION(0x5, "clk"),		/* FANOUT2 */
+		SUNXI_FUNCTION(0x6, "pwm"),
+		SUNXI_FUNCTION(0x7, "uart1"),		/* TX */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 12)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 13),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "i2s1"),		/* BCLK */
+		SUNXI_FUNCTION(0x3, "i2c0"),		/* SDA */
+		SUNXI_FUNCTION(0x4, "emac"),		/* CLKIN/RXER */
+		SUNXI_FUNCTION(0x5, "pwm"),
+		SUNXI_FUNCTION(0x6, "ledc"),
+		SUNXI_FUNCTION(0x7, "uart1"),		/* RX */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 13)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 14),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "i2s1_din"),	/* DIN0 */
+		SUNXI_FUNCTION(0x3, "i2c2"),		/* SCK */
+		SUNXI_FUNCTION(0x4, "emac"),		/* MDC */
+		SUNXI_FUNCTION(0x5, "i2s1_dout"),	/* DOUT1 */
+		SUNXI_FUNCTION(0x6, "spi0"),		/* WP */
+		SUNXI_FUNCTION(0x7, "uart1"),		/* RTS */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 14)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 15),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "i2s1_dout"),	/* DOUT0 */
+		SUNXI_FUNCTION(0x3, "i2c2"),		/* SDA */
+		SUNXI_FUNCTION(0x4, "emac"),		/* MDIO */
+		SUNXI_FUNCTION(0x5, "i2s1_din"),	/* DIN1 */
+		SUNXI_FUNCTION(0x6, "spi0"),		/* HOLD */
+		SUNXI_FUNCTION(0x7, "uart1"),		/* CTS */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 15)),
+	SUNXI_PIN_VARIANT(SUNXI_PINCTRL_PIN(G, 16),
+		PINCTRL_SUN20I_D1,
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "ir"),		/* RX */
+		SUNXI_FUNCTION(0x3, "tcon"),		/* TRIG0 */
+		SUNXI_FUNCTION(0x4, "pwm"),
+		SUNXI_FUNCTION(0x5, "clk"),		/* FANOUT2 */
+		SUNXI_FUNCTION(0x6, "spdif"),		/* IN */
+		SUNXI_FUNCTION(0x7, "ledc"),
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 16)),
+	SUNXI_PIN_VARIANT(SUNXI_PINCTRL_PIN(G, 17),
+		PINCTRL_SUN20I_D1,
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "uart2"),		/* TX */
+		SUNXI_FUNCTION(0x3, "i2c3"),		/* SCK */
+		SUNXI_FUNCTION(0x4, "pwm"),
+		SUNXI_FUNCTION(0x5, "clk"),		/* FANOUT0 */
+		SUNXI_FUNCTION(0x6, "ir"),		/* TX */
+		SUNXI_FUNCTION(0x7, "uart0"),		/* TX */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 17)),
+	SUNXI_PIN_VARIANT(SUNXI_PINCTRL_PIN(G, 18),
+		PINCTRL_SUN20I_D1,
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "uart2"),		/* RX */
+		SUNXI_FUNCTION(0x3, "i2c3"),		/* SDA */
+		SUNXI_FUNCTION(0x4, "pwm"),
+		SUNXI_FUNCTION(0x5, "clk"),		/* FANOUT1 */
+		SUNXI_FUNCTION(0x6, "spdif"),		/* OUT */
+		SUNXI_FUNCTION(0x7, "uart0"),		/* RX */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 18)),
+};
+
+static const unsigned int d1_irq_bank_map[] = { 1, 2, 3, 4, 5, 6 };
+
+static const struct sunxi_pinctrl_desc d1_pinctrl_data = {
+	.pins			= d1_pins,
+	.npins			= ARRAY_SIZE(d1_pins),
+	.irq_banks		= ARRAY_SIZE(d1_irq_bank_map),
+	.irq_bank_map		= d1_irq_bank_map,
+	.io_bias_cfg_variant	= BIAS_VOLTAGE_PIO_POW_MODE_CTL,
+};
+
+static int d1_pinctrl_probe(struct platform_device *pdev)
+{
+	unsigned long variant = (unsigned long)of_device_get_match_data(&pdev->dev);
+
+	return sunxi_pinctrl_init_with_variant(pdev, &d1_pinctrl_data, variant);
+}
+
+static const struct of_device_id d1_pinctrl_match[] = {
+	{
+		.compatible = "allwinner,sun20i-d1-pinctrl",
+		.data = (void *)PINCTRL_SUN20I_D1
+	},
+	{
+		.compatible = "allwinner,sun20i-d1s-pinctrl",
+		.data = (void *)PINCTRL_SUN20I_D1S
+	},
+	{}
+};
+
+static struct platform_driver d1_pinctrl_driver = {
+	.probe	= d1_pinctrl_probe,
+	.driver	= {
+		.name		= "sun20i-d1-pinctrl",
+		.of_match_table	= d1_pinctrl_match,
+	},
+};
+builtin_platform_driver(d1_pinctrl_driver);
diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
index ec7daaa5666b..350044d4c1b5 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
@@ -1297,11 +1297,11 @@ static int sunxi_pinctrl_build_state(struct platform_device *pdev)
 
 	/*
 	 * Find an upper bound for the maximum number of functions: in
-	 * the worst case we have gpio_in, gpio_out, irq and up to four
+	 * the worst case we have gpio_in, gpio_out, irq and up to seven
 	 * special functions per pin, plus one entry for the sentinel.
 	 * We'll reallocate that later anyway.
 	 */
-	pctl->functions = kcalloc(4 * pctl->ngroups + 4,
+	pctl->functions = kcalloc(7 * pctl->ngroups + 4,
 				  sizeof(*pctl->functions),
 				  GFP_KERNEL);
 	if (!pctl->functions)
@@ -1494,9 +1494,15 @@ int sunxi_pinctrl_init_with_variant(struct platform_device *pdev,
 	pctl->dev = &pdev->dev;
 	pctl->desc = desc;
 	pctl->variant = variant;
-	pctl->bank_mem_size = BANK_MEM_SIZE;
-	pctl->pull_regs_offset = PULL_REGS_OFFSET;
-	pctl->dlevel_field_width = DLEVEL_FIELD_WIDTH;
+	if (pctl->variant >= PINCTRL_SUN20I_D1) {
+		pctl->bank_mem_size = D1_BANK_MEM_SIZE;
+		pctl->pull_regs_offset = D1_PULL_REGS_OFFSET;
+		pctl->dlevel_field_width = D1_DLEVEL_FIELD_WIDTH;
+	} else {
+		pctl->bank_mem_size = BANK_MEM_SIZE;
+		pctl->pull_regs_offset = PULL_REGS_OFFSET;
+		pctl->dlevel_field_width = DLEVEL_FIELD_WIDTH;
+	}
 
 	pctl->irq_array = devm_kcalloc(&pdev->dev,
 				       IRQ_PER_BANK * pctl->desc->irq_banks,
diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.h b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
index c705828add73..f0f48941bc30 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.h
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
@@ -44,6 +44,10 @@
 #define PULL_REGS_OFFSET	0x1c
 #define PULL_FIELD_WIDTH	2
 
+#define D1_BANK_MEM_SIZE	0x30
+#define D1_DLEVEL_FIELD_WIDTH	4
+#define D1_PULL_REGS_OFFSET	0x24
+
 #define PINS_PER_BANK		32
 
 #define IRQ_PER_BANK		32
@@ -88,6 +92,9 @@
 #define PINCTRL_SUN8I_R40	BIT(8)
 #define PINCTRL_SUN8I_V3	BIT(9)
 #define PINCTRL_SUN8I_V3S	BIT(10)
+/* Variants below here have an updated register layout. */
+#define PINCTRL_SUN20I_D1	BIT(11)
+#define PINCTRL_SUN20I_D1S	BIT(12)
 
 #define PIO_POW_MOD_SEL_REG	0x340
 #define PIO_POW_MOD_CTL_REG	0x344
-- 
2.35.1


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

* [PATCH 6/6] pinctrl: sunxi: Add driver for Allwinner D1/D1s
@ 2022-06-26  2:11   ` Samuel Holland
  0 siblings, 0 replies; 56+ messages in thread
From: Samuel Holland @ 2022-06-26  2:11 UTC (permalink / raw)
  To: Chen-Yu Tsai, Jernej Skrabec, Linus Walleij
  Cc: Samuel Holland, Krzysztof Kozlowski, Maxime Ripard,
	Ondrej Jirman, Rob Herring, devicetree, linux-arm-kernel,
	linux-gpio, linux-kernel, linux-sunxi

These SoCs contain a pinctrl with a new register layout. Use the variant
parameter to set the right register offsets. This pinctrl also increases
the number of functions per pin from 8 to 16, taking advantage of all 4
bits in the mux config field (so far, only functions 0-8 and 14-15 are
used). This increases the maximum possible number of functions.

D1s is a low pin count version of the D1 SoC, with some pins omitted.
The remaining pins have the same function assignments as D1.

Signed-off-by: Samuel Holland <samuel@sholland.org>
---

 drivers/pinctrl/sunxi/Kconfig             |   5 +
 drivers/pinctrl/sunxi/Makefile            |   1 +
 drivers/pinctrl/sunxi/pinctrl-sun20i-d1.c | 860 ++++++++++++++++++++++
 drivers/pinctrl/sunxi/pinctrl-sunxi.c     |  16 +-
 drivers/pinctrl/sunxi/pinctrl-sunxi.h     |   7 +
 5 files changed, 884 insertions(+), 5 deletions(-)
 create mode 100644 drivers/pinctrl/sunxi/pinctrl-sun20i-d1.c

diff --git a/drivers/pinctrl/sunxi/Kconfig b/drivers/pinctrl/sunxi/Kconfig
index 33751a6a0757..a6ac1c1f2585 100644
--- a/drivers/pinctrl/sunxi/Kconfig
+++ b/drivers/pinctrl/sunxi/Kconfig
@@ -84,6 +84,11 @@ config PINCTRL_SUN9I_A80_R
 	depends on RESET_CONTROLLER
 	select PINCTRL_SUNXI
 
+config PINCTRL_SUN20I_D1
+	bool "Support for the Allwinner D1 PIO"
+	default RISCV && ARCH_SUNXI
+	select PINCTRL_SUNXI
+
 config PINCTRL_SUN50I_A64
 	bool "Support for the Allwinner A64 PIO"
 	default ARM64 && ARCH_SUNXI
diff --git a/drivers/pinctrl/sunxi/Makefile b/drivers/pinctrl/sunxi/Makefile
index d3440c42b9d6..2ff5a55927ad 100644
--- a/drivers/pinctrl/sunxi/Makefile
+++ b/drivers/pinctrl/sunxi/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_PINCTRL_SUN8I_A83T_R)	+= pinctrl-sun8i-a83t-r.o
 obj-$(CONFIG_PINCTRL_SUN8I_H3)		+= pinctrl-sun8i-h3.o
 obj-$(CONFIG_PINCTRL_SUN8I_H3_R)	+= pinctrl-sun8i-h3-r.o
 obj-$(CONFIG_PINCTRL_SUN8I_V3S)		+= pinctrl-sun8i-v3s.o
+obj-$(CONFIG_PINCTRL_SUN20I_D1)		+= pinctrl-sun20i-d1.o
 obj-$(CONFIG_PINCTRL_SUN50I_H5)		+= pinctrl-sun50i-h5.o
 obj-$(CONFIG_PINCTRL_SUN50I_H6)		+= pinctrl-sun50i-h6.o
 obj-$(CONFIG_PINCTRL_SUN50I_H6_R)	+= pinctrl-sun50i-h6-r.o
diff --git a/drivers/pinctrl/sunxi/pinctrl-sun20i-d1.c b/drivers/pinctrl/sunxi/pinctrl-sun20i-d1.c
new file mode 100644
index 000000000000..7247c1f1d92c
--- /dev/null
+++ b/drivers/pinctrl/sunxi/pinctrl-sun20i-d1.c
@@ -0,0 +1,860 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Allwinner D1 SoC pinctrl driver.
+ *
+ * Copyright (c) 2020 wuyan@allwinnertech.com
+ * Copyright (c) 2021-2022 Samuel Holland <samuel@sholland.org>
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/pinctrl.h>
+
+#include "pinctrl-sunxi.h"
+
+static const struct sunxi_desc_pin d1_pins[] = {
+	/* PB */
+	SUNXI_PIN_VARIANT(SUNXI_PINCTRL_PIN(B, 0),
+		PINCTRL_SUN20I_D1,
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "pwm"),
+		SUNXI_FUNCTION(0x3, "ir"),		/* TX */
+		SUNXI_FUNCTION(0x4, "i2c2"),		/* SCK */
+		SUNXI_FUNCTION(0x5, "spi1"),		/* WP */
+		SUNXI_FUNCTION(0x6, "uart0"),		/* TX */
+		SUNXI_FUNCTION(0x7, "uart2"),		/* TX */
+		SUNXI_FUNCTION(0x8, "spdif"),		/* OUT */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 0)),
+	SUNXI_PIN_VARIANT(SUNXI_PINCTRL_PIN(B, 1),
+		PINCTRL_SUN20I_D1,
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "pwm"),
+		SUNXI_FUNCTION(0x3, "i2s2_dout"),	/* DOUT3 */
+		SUNXI_FUNCTION(0x4, "i2c2"),		/* SDA */
+		SUNXI_FUNCTION(0x5, "i2s2_din"),	/* DIN3 */
+		SUNXI_FUNCTION(0x6, "uart0"),		/* RX */
+		SUNXI_FUNCTION(0x7, "uart2"),		/* RX */
+		SUNXI_FUNCTION(0x8, "ir"),		/* RX */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 1)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 2),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* D0 */
+		SUNXI_FUNCTION(0x3, "i2s2_dout"),	/* DOUT2 */
+		SUNXI_FUNCTION(0x4, "i2c0"),		/* SDA */
+		SUNXI_FUNCTION(0x5, "i2s2_din"),	/* DIN2 */
+		SUNXI_FUNCTION(0x6, "lcd0"),		/* D18 */
+		SUNXI_FUNCTION(0x7, "uart4"),		/* TX */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 2)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 3),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* D1 */
+		SUNXI_FUNCTION(0x3, "i2s2_dout"),	/* DOUT1 */
+		SUNXI_FUNCTION(0x4, "i2c0"),		/* SCK */
+		SUNXI_FUNCTION(0x5, "i2s2_din"),	/* DIN0 */
+		SUNXI_FUNCTION(0x6, "lcd0"),		/* D19 */
+		SUNXI_FUNCTION(0x7, "uart4"),		/* RX */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 3)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 4),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* D8 */
+		SUNXI_FUNCTION(0x3, "i2s2_dout"),	/* DOUT0 */
+		SUNXI_FUNCTION(0x4, "i2c1"),		/* SCK */
+		SUNXI_FUNCTION(0x5, "i2s2_din"),	/* DIN1 */
+		SUNXI_FUNCTION(0x6, "lcd0"),		/* D20 */
+		SUNXI_FUNCTION(0x7, "uart5"),		/* TX */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 4)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 5),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* D9 */
+		SUNXI_FUNCTION(0x3, "i2s2"),		/* BCLK */
+		SUNXI_FUNCTION(0x4, "i2c1"),		/* SDA */
+		SUNXI_FUNCTION(0x5, "pwm"),
+		SUNXI_FUNCTION(0x6, "lcd0"),		/* D21 */
+		SUNXI_FUNCTION(0x7, "uart5"),		/* RX */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 5)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 6),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* D16 */
+		SUNXI_FUNCTION(0x3, "i2s2"),		/* LRCK */
+		SUNXI_FUNCTION(0x4, "i2c3"),		/* SCK */
+		SUNXI_FUNCTION(0x5, "pwm"),
+		SUNXI_FUNCTION(0x6, "lcd0"),		/* D22 */
+		SUNXI_FUNCTION(0x7, "uart3"),		/* TX */
+		SUNXI_FUNCTION(0x8, "bist0"),		/* BIST_RESULT0 */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 6)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 7),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* D17 */
+		SUNXI_FUNCTION(0x3, "i2s2"),		/* MCLK */
+		SUNXI_FUNCTION(0x4, "i2c3"),		/* SDA */
+		SUNXI_FUNCTION(0x5, "ir"),		/* RX */
+		SUNXI_FUNCTION(0x6, "lcd0"),		/* D23 */
+		SUNXI_FUNCTION(0x7, "uart3"),		/* RX */
+		SUNXI_FUNCTION(0x8, "bist1"),		/* BIST_RESULT1 */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 7)),
+	SUNXI_PIN_VARIANT(SUNXI_PINCTRL_PIN(B, 8),
+		PINCTRL_SUN20I_D1,
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "dmic"),		/* DATA3 */
+		SUNXI_FUNCTION(0x3, "pwm"),
+		SUNXI_FUNCTION(0x4, "i2c2"),		/* SCK */
+		SUNXI_FUNCTION(0x5, "spi1"),		/* HOLD */
+		SUNXI_FUNCTION(0x6, "uart0"),		/* TX */
+		SUNXI_FUNCTION(0x7, "uart1"),		/* TX */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 8)),
+	SUNXI_PIN_VARIANT(SUNXI_PINCTRL_PIN(B, 9),
+		PINCTRL_SUN20I_D1,
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "dmic"),		/* DATA2 */
+		SUNXI_FUNCTION(0x3, "pwm"),
+		SUNXI_FUNCTION(0x4, "i2c2"),		/* SDA */
+		SUNXI_FUNCTION(0x5, "spi1"),		/* MISO */
+		SUNXI_FUNCTION(0x6, "uart0"),		/* RX */
+		SUNXI_FUNCTION(0x7, "uart1"),		/* RX */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 9)),
+	SUNXI_PIN_VARIANT(SUNXI_PINCTRL_PIN(B, 10),
+		PINCTRL_SUN20I_D1,
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "dmic"),		/* DATA1 */
+		SUNXI_FUNCTION(0x3, "pwm"),
+		SUNXI_FUNCTION(0x4, "i2c0"),		/* SCK */
+		SUNXI_FUNCTION(0x5, "spi1"),		/* MOSI */
+		SUNXI_FUNCTION(0x6, "clk"),		/* FANOUT0 */
+		SUNXI_FUNCTION(0x7, "uart1"),		/* RTS */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 10)),
+	SUNXI_PIN_VARIANT(SUNXI_PINCTRL_PIN(B, 11),
+		PINCTRL_SUN20I_D1,
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "dmic"),		/* DATA0 */
+		SUNXI_FUNCTION(0x3, "pwm"),
+		SUNXI_FUNCTION(0x4, "i2c0"),		/* SDA */
+		SUNXI_FUNCTION(0x5, "spi1"),		/* CLK */
+		SUNXI_FUNCTION(0x6, "clk"),		/* FANOUT1 */
+		SUNXI_FUNCTION(0x7, "uart1"),		/* CTS */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 11)),
+	SUNXI_PIN_VARIANT(SUNXI_PINCTRL_PIN(B, 12),
+		PINCTRL_SUN20I_D1,
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "dmic"),		/* CLK */
+		SUNXI_FUNCTION(0x3, "pwm"),
+		SUNXI_FUNCTION(0x4, "spdif"),		/* IN */
+		SUNXI_FUNCTION(0x5, "spi1"),		/* CS0 */
+		SUNXI_FUNCTION(0x6, "clk"),		/* FANOUT2 */
+		SUNXI_FUNCTION(0x7, "ir"),		/* RX */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 12)),
+	/* PC */
+	SUNXI_PIN_VARIANT(SUNXI_PINCTRL_PIN(C, 0),
+		PINCTRL_SUN20I_D1,
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "uart2"),		/* TX */
+		SUNXI_FUNCTION(0x3, "i2c2"),		/* SCK */
+		SUNXI_FUNCTION(0x4, "ledc"),
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 0)),
+	SUNXI_PIN_VARIANT(SUNXI_PINCTRL_PIN(C, 1),
+		PINCTRL_SUN20I_D1,
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "uart2"),		/* RX */
+		SUNXI_FUNCTION(0x3, "i2c2"),		/* SDA */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 1)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 2),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "spi0"),		/* CLK */
+		SUNXI_FUNCTION(0x3, "mmc2"),		/* CLK */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 2)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 3),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "spi0"),		/* CS0 */
+		SUNXI_FUNCTION(0x3, "mmc2"),		/* CMD */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 3)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 4),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "spi0"),		/* MOSI */
+		SUNXI_FUNCTION(0x3, "mmc2"),		/* D2 */
+		SUNXI_FUNCTION(0x4, "boot"),		/* SEL0 */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 4)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 5),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "spi0"),		/* MISO */
+		SUNXI_FUNCTION(0x3, "mmc2"),		/* D1 */
+		SUNXI_FUNCTION(0x4, "boot"),		/* SEL1 */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 5)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 6),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "spi0"),		/* WP */
+		SUNXI_FUNCTION(0x3, "mmc2"),		/* D0 */
+		SUNXI_FUNCTION(0x4, "uart3"),		/* TX */
+		SUNXI_FUNCTION(0x5, "i2c3"),		/* SCK */
+		SUNXI_FUNCTION(0x6, "pll"),		/* DBG-CLK */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 6)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 7),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "spi0"),		/* HOLD */
+		SUNXI_FUNCTION(0x3, "mmc2"),		/* D3 */
+		SUNXI_FUNCTION(0x4, "uart3"),		/* RX */
+		SUNXI_FUNCTION(0x5, "i2c3"),		/* SDA */
+		SUNXI_FUNCTION(0x6, "tcon"),		/* TRIG0 */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 7)),
+	/* PD */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 0),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* D2 */
+		SUNXI_FUNCTION(0x3, "lvds0"),		/* V0P */
+		SUNXI_FUNCTION(0x4, "dsi"),		/* D0P */
+		SUNXI_FUNCTION(0x5, "i2c0"),		/* SCK */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 0)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 1),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* D3 */
+		SUNXI_FUNCTION(0x3, "lvds0"),		/* V0N */
+		SUNXI_FUNCTION(0x4, "dsi"),		/* D0N */
+		SUNXI_FUNCTION(0x5, "uart2"),		/* TX */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 1)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 2),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* D4 */
+		SUNXI_FUNCTION(0x3, "lvds0"),		/* V1P */
+		SUNXI_FUNCTION(0x4, "dsi"),		/* D1P */
+		SUNXI_FUNCTION(0x5, "uart2"),		/* RX */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 2)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 3),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* D5 */
+		SUNXI_FUNCTION(0x3, "lvds0"),		/* V1N */
+		SUNXI_FUNCTION(0x4, "dsi"),		/* D1N */
+		SUNXI_FUNCTION(0x5, "uart2"),		/* RTS */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 3)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 4),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* D6 */
+		SUNXI_FUNCTION(0x3, "lvds0"),		/* V2P */
+		SUNXI_FUNCTION(0x4, "dsi"),		/* CKP */
+		SUNXI_FUNCTION(0x5, "uart2"),		/* CTS */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 4)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 5),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* D7 */
+		SUNXI_FUNCTION(0x3, "lvds0"),		/* V2N */
+		SUNXI_FUNCTION(0x4, "dsi"),		/* CKN */
+		SUNXI_FUNCTION(0x5, "uart5"),		/* TX */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 5)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 6),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* D10 */
+		SUNXI_FUNCTION(0x3, "lvds0"),		/* CKP */
+		SUNXI_FUNCTION(0x4, "dsi"),		/* D2P */
+		SUNXI_FUNCTION(0x5, "uart5"),		/* RX */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 6)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 7),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* D11 */
+		SUNXI_FUNCTION(0x3, "lvds0"),		/* CKN */
+		SUNXI_FUNCTION(0x4, "dsi"),		/* D2N */
+		SUNXI_FUNCTION(0x5, "uart4"),		/* TX */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 7)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 8),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* D12 */
+		SUNXI_FUNCTION(0x3, "lvds0"),		/* V3P */
+		SUNXI_FUNCTION(0x4, "dsi"),		/* D3P */
+		SUNXI_FUNCTION(0x5, "uart4"),		/* RX */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 8)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 9),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* D13 */
+		SUNXI_FUNCTION(0x3, "lvds0"),		/* V3N */
+		SUNXI_FUNCTION(0x4, "dsi"),		/* D3N */
+		SUNXI_FUNCTION(0x5, "pwm"),
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 9)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 10),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* D14 */
+		SUNXI_FUNCTION(0x3, "lvds1"),		/* V0P */
+		SUNXI_FUNCTION(0x4, "spi1"),		/* CS0 */
+		SUNXI_FUNCTION(0x5, "uart3"),		/* TX */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 10)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 11),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* D15 */
+		SUNXI_FUNCTION(0x3, "lvds1"),		/* V0N */
+		SUNXI_FUNCTION(0x4, "spi1"),		/* CLK */
+		SUNXI_FUNCTION(0x5, "uart3"),		/* RX */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 11)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 12),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* D18 */
+		SUNXI_FUNCTION(0x3, "lvds1"),		/* V1P */
+		SUNXI_FUNCTION(0x4, "spi1"),		/* MOSI */
+		SUNXI_FUNCTION(0x5, "i2c0"),		/* SDA */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 12)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 13),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* D19 */
+		SUNXI_FUNCTION(0x3, "lvds1"),		/* V1N */
+		SUNXI_FUNCTION(0x4, "spi1"),		/* MISO */
+		SUNXI_FUNCTION(0x5, "uart3"),		/* RTS */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 13)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 14),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* D20 */
+		SUNXI_FUNCTION(0x3, "lvds1"),		/* V2P */
+		SUNXI_FUNCTION(0x4, "spi1"),		/* HOLD */
+		SUNXI_FUNCTION(0x5, "uart3"),		/* CTS */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 14)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 15),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* D21 */
+		SUNXI_FUNCTION(0x3, "lvds1"),		/* V2N */
+		SUNXI_FUNCTION(0x4, "spi1"),		/* WP */
+		SUNXI_FUNCTION(0x5, "ir"),		/* RX */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 15)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 16),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* D22 */
+		SUNXI_FUNCTION(0x3, "lvds1"),		/* CKP */
+		SUNXI_FUNCTION(0x4, "dmic"),		/* DATA3 */
+		SUNXI_FUNCTION(0x5, "pwm"),
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 16)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 17),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* D23 */
+		SUNXI_FUNCTION(0x3, "lvds1"),		/* CKN */
+		SUNXI_FUNCTION(0x4, "dmic"),		/* DATA2 */
+		SUNXI_FUNCTION(0x5, "pwm"),
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 17)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 18),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* CLK */
+		SUNXI_FUNCTION(0x3, "lvds1"),		/* V3P */
+		SUNXI_FUNCTION(0x4, "dmic"),		/* DATA1 */
+		SUNXI_FUNCTION(0x5, "pwm"),
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 18)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 19),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* DE */
+		SUNXI_FUNCTION(0x3, "lvds1"),		/* V3N */
+		SUNXI_FUNCTION(0x4, "dmic"),		/* DATA0 */
+		SUNXI_FUNCTION(0x5, "pwm"),
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 19)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 20),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* HSYNC */
+		SUNXI_FUNCTION(0x3, "i2c2"),		/* SCK */
+		SUNXI_FUNCTION(0x4, "dmic"),		/* CLK */
+		SUNXI_FUNCTION(0x5, "pwm"),
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 20)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 21),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd0"),		/* VSYNC */
+		SUNXI_FUNCTION(0x3, "i2c2"),		/* SDA */
+		SUNXI_FUNCTION(0x4, "uart1"),		/* TX */
+		SUNXI_FUNCTION(0x5, "pwm"),
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 21)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 22),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "spdif"),		/* OUT */
+		SUNXI_FUNCTION(0x3, "ir"),		/* RX */
+		SUNXI_FUNCTION(0x4, "uart1"),		/* RX */
+		SUNXI_FUNCTION(0x5, "pwm"),
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 22)),
+	/* PE */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 0),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "ncsi0"),		/* HSYNC */
+		SUNXI_FUNCTION(0x3, "uart2"),		/* RTS */
+		SUNXI_FUNCTION(0x4, "i2c1"),		/* SCK */
+		SUNXI_FUNCTION(0x5, "lcd0"),		/* HSYNC */
+		SUNXI_FUNCTION(0x8, "emac"),		/* RXCTL/CRS_DV */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 0)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 1),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "ncsi0"),		/* VSYNC */
+		SUNXI_FUNCTION(0x3, "uart2"),		/* CTS */
+		SUNXI_FUNCTION(0x4, "i2c1"),		/* SDA */
+		SUNXI_FUNCTION(0x5, "lcd0"),		/* VSYNC */
+		SUNXI_FUNCTION(0x8, "emac"),		/* RXD0 */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 1)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 2),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "ncsi0"),		/* PCLK */
+		SUNXI_FUNCTION(0x3, "uart2"),		/* TX */
+		SUNXI_FUNCTION(0x4, "i2c0"),		/* SCK */
+		SUNXI_FUNCTION(0x5, "clk"),		/* FANOUT0 */
+		SUNXI_FUNCTION(0x6, "uart0"),		/* TX */
+		SUNXI_FUNCTION(0x8, "emac"),		/* RXD1 */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 2)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 3),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "csi0"),		/* MCLK */
+		SUNXI_FUNCTION(0x3, "uart2"),		/* RX */
+		SUNXI_FUNCTION(0x4, "i2c0"),		/* SDA */
+		SUNXI_FUNCTION(0x5, "clk"),		/* FANOUT1 */
+		SUNXI_FUNCTION(0x6, "uart0"),		/* RX */
+		SUNXI_FUNCTION(0x8, "emac"),		/* TXCK */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 3)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 4),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "ncsi0"),		/* D0 */
+		SUNXI_FUNCTION(0x3, "uart4"),		/* TX */
+		SUNXI_FUNCTION(0x4, "i2c2"),		/* SCK */
+		SUNXI_FUNCTION(0x5, "clk"),		/* FANOUT2 */
+		SUNXI_FUNCTION(0x6, "d_jtag"),		/* MS */
+		SUNXI_FUNCTION(0x7, "r_jtag"),		/* MS */
+		SUNXI_FUNCTION(0x8, "emac"),		/* TXD0 */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 4)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 5),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "ncsi0"),		/* D1 */
+		SUNXI_FUNCTION(0x3, "uart4"),		/* RX */
+		SUNXI_FUNCTION(0x4, "i2c2"),		/* SDA */
+		SUNXI_FUNCTION(0x5, "ledc"),
+		SUNXI_FUNCTION(0x6, "d_jtag"),		/* D1 */
+		SUNXI_FUNCTION(0x7, "r_jtag"),		/* D1 */
+		SUNXI_FUNCTION(0x8, "emac"),		/* TXD1 */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 5)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 6),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "ncsi0"),		/* D2 */
+		SUNXI_FUNCTION(0x3, "uart5"),		/* TX */
+		SUNXI_FUNCTION(0x4, "i2c3"),		/* SCK */
+		SUNXI_FUNCTION(0x5, "spdif"),		/* IN */
+		SUNXI_FUNCTION(0x6, "d_jtag"),		/* D0 */
+		SUNXI_FUNCTION(0x7, "r_jtag"),		/* D0 */
+		SUNXI_FUNCTION(0x8, "emac"),		/* TXCTL/TXEN */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 6)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 7),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "ncsi0"),		/* D3 */
+		SUNXI_FUNCTION(0x3, "uart5"),		/* RX */
+		SUNXI_FUNCTION(0x4, "i2c3"),		/* SDA */
+		SUNXI_FUNCTION(0x5, "spdif"),		/* OUT */
+		SUNXI_FUNCTION(0x6, "d_jtag"),		/* CK */
+		SUNXI_FUNCTION(0x7, "r_jtag"),		/* CK */
+		SUNXI_FUNCTION(0x8, "emac"),		/* CK */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 7)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 8),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "ncsi0"),		/* D4 */
+		SUNXI_FUNCTION(0x3, "uart1"),		/* RTS */
+		SUNXI_FUNCTION(0x4, "pwm"),
+		SUNXI_FUNCTION(0x5, "uart3"),		/* TX */
+		SUNXI_FUNCTION(0x6, "jtag"),		/* MS */
+		SUNXI_FUNCTION(0x8, "emac"),		/* MDC */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 8)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 9),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "ncsi0"),		/* D5 */
+		SUNXI_FUNCTION(0x3, "uart1"),		/* CTS */
+		SUNXI_FUNCTION(0x4, "pwm"),
+		SUNXI_FUNCTION(0x5, "uart3"),		/* RX */
+		SUNXI_FUNCTION(0x6, "jtag"),		/* D1 */
+		SUNXI_FUNCTION(0x8, "emac"),		/* MDIO */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 9)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 10),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "ncsi0"),		/* D6 */
+		SUNXI_FUNCTION(0x3, "uart1"),		/* TX */
+		SUNXI_FUNCTION(0x4, "pwm"),
+		SUNXI_FUNCTION(0x5, "ir"),		/* RX */
+		SUNXI_FUNCTION(0x6, "jtag"),		/* D0 */
+		SUNXI_FUNCTION(0x8, "emac"),		/* EPHY-25M */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 10)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 11),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "ncsi0"),		/* D7 */
+		SUNXI_FUNCTION(0x3, "uart1"),		/* RX */
+		SUNXI_FUNCTION(0x4, "i2s0_dout"),	/* DOUT3 */
+		SUNXI_FUNCTION(0x5, "i2s0_din"),	/* DIN3 */
+		SUNXI_FUNCTION(0x6, "jtag"),		/* CK */
+		SUNXI_FUNCTION(0x8, "emac"),		/* TXD2 */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 11)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 12),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "i2c2"),		/* SCK */
+		SUNXI_FUNCTION(0x3, "ncsi0"),		/* FIELD */
+		SUNXI_FUNCTION(0x4, "i2s0_dout"),	/* DOUT2 */
+		SUNXI_FUNCTION(0x5, "i2s0_din"),	/* DIN2 */
+		SUNXI_FUNCTION(0x8, "emac"),		/* TXD3 */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 12)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 13),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "i2c2"),		/* SDA */
+		SUNXI_FUNCTION(0x3, "pwm"),
+		SUNXI_FUNCTION(0x4, "i2s0_dout"),	/* DOUT0 */
+		SUNXI_FUNCTION(0x5, "i2s0_din"),	/* DIN1 */
+		SUNXI_FUNCTION(0x6, "dmic"),		/* DATA3 */
+		SUNXI_FUNCTION(0x8, "emac"),		/* RXD2 */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 13)),
+	SUNXI_PIN_VARIANT(SUNXI_PINCTRL_PIN(E, 14),
+		PINCTRL_SUN20I_D1,
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "i2c1"),		/* SCK */
+		SUNXI_FUNCTION(0x3, "d_jtag"),		/* MS */
+		SUNXI_FUNCTION(0x4, "i2s0_dout"),	/* DOUT1 */
+		SUNXI_FUNCTION(0x5, "i2s0_din"),	/* DIN0 */
+		SUNXI_FUNCTION(0x6, "dmic"),		/* DATA2 */
+		SUNXI_FUNCTION(0x8, "emac"),		/* RXD3 */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 14)),
+	SUNXI_PIN_VARIANT(SUNXI_PINCTRL_PIN(E, 15),
+		PINCTRL_SUN20I_D1,
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "i2c1"),		/* SDA */
+		SUNXI_FUNCTION(0x3, "d_jtag"),		/* D1 */
+		SUNXI_FUNCTION(0x4, "pwm"),
+		SUNXI_FUNCTION(0x5, "i2s0"),		/* LRCK */
+		SUNXI_FUNCTION(0x6, "dmic"),		/* DATA1 */
+		SUNXI_FUNCTION(0x8, "emac"),		/* RXCK */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 15)),
+	SUNXI_PIN_VARIANT(SUNXI_PINCTRL_PIN(E, 16),
+		PINCTRL_SUN20I_D1,
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "i2c3"),		/* SCK */
+		SUNXI_FUNCTION(0x3, "d_jtag"),		/* D0 */
+		SUNXI_FUNCTION(0x4, "pwm"),
+		SUNXI_FUNCTION(0x5, "i2s0"),		/* BCLK */
+		SUNXI_FUNCTION(0x6, "dmic"),		/* DATA0 */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 16)),
+	SUNXI_PIN_VARIANT(SUNXI_PINCTRL_PIN(E, 17),
+		PINCTRL_SUN20I_D1,
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "i2c3"),		/* SDA */
+		SUNXI_FUNCTION(0x3, "d_jtag"),		/* CK */
+		SUNXI_FUNCTION(0x4, "ir"),		/* TX */
+		SUNXI_FUNCTION(0x5, "i2s0"),		/* MCLK */
+		SUNXI_FUNCTION(0x6, "dmic"),		/* CLK */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 17)),
+	/* PF */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 0),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "mmc0"),		/* D1 */
+		SUNXI_FUNCTION(0x3, "jtag"),		/* MS */
+		SUNXI_FUNCTION(0x4, "r_jtag"),		/* MS */
+		SUNXI_FUNCTION(0x5, "i2s2_dout"),	/* DOUT1 */
+		SUNXI_FUNCTION(0x6, "i2s2_din"),	/* DIN0 */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 0)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 1),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "mmc0"),		/* D0 */
+		SUNXI_FUNCTION(0x3, "jtag"),		/* DI */
+		SUNXI_FUNCTION(0x4, "r_jtag"),		/* DI */
+		SUNXI_FUNCTION(0x5, "i2s2_dout"),	/* DOUT0 */
+		SUNXI_FUNCTION(0x6, "i2s2_din"),	/* DIN1 */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 1)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 2),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "mmc0"),		/* CLK */
+		SUNXI_FUNCTION(0x3, "uart0"),		/* TX */
+		SUNXI_FUNCTION(0x4, "i2c0"),		/* SCK */
+		SUNXI_FUNCTION(0x5, "ledc"),
+		SUNXI_FUNCTION(0x6, "spdif"),		/* IN */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 2)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 3),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "mmc0"),		/* CMD */
+		SUNXI_FUNCTION(0x3, "jtag"),		/* DO */
+		SUNXI_FUNCTION(0x4, "r_jtag"),		/* DO */
+		SUNXI_FUNCTION(0x5, "i2s2"),		/* BCLK */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 3)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 4),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "mmc0"),		/* D3 */
+		SUNXI_FUNCTION(0x3, "uart0"),		/* RX */
+		SUNXI_FUNCTION(0x4, "i2c0"),		/* SDA */
+		SUNXI_FUNCTION(0x5, "pwm"),
+		SUNXI_FUNCTION(0x6, "ir"),		/* TX */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 4)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 5),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "mmc0"),		/* D2 */
+		SUNXI_FUNCTION(0x3, "jtag"),		/* CK */
+		SUNXI_FUNCTION(0x4, "r_jtag"),		/* CK */
+		SUNXI_FUNCTION(0x5, "i2s2"),		/* LRCK */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 5)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 6),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x3, "spdif"),		/* OUT */
+		SUNXI_FUNCTION(0x4, "ir"),		/* RX */
+		SUNXI_FUNCTION(0x5, "i2s2"),		/* MCLK */
+		SUNXI_FUNCTION(0x6, "pwm"),
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 6)),
+	/* PG */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 0),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "mmc1"),		/* CLK */
+		SUNXI_FUNCTION(0x3, "uart3"),		/* TX */
+		SUNXI_FUNCTION(0x4, "emac"),		/* RXCTRL/CRS_DV */
+		SUNXI_FUNCTION(0x5, "pwm"),
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 0)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 1),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "mmc1"),		/* CMD */
+		SUNXI_FUNCTION(0x3, "uart3"),		/* RX */
+		SUNXI_FUNCTION(0x4, "emac"),		/* RXD0 */
+		SUNXI_FUNCTION(0x5, "pwm"),
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 1)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 2),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "mmc1"),		/* D0 */
+		SUNXI_FUNCTION(0x3, "uart3"),		/* RTS */
+		SUNXI_FUNCTION(0x4, "emac"),		/* RXD1 */
+		SUNXI_FUNCTION(0x5, "uart4"),		/* TX */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 2)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 3),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "mmc1"),		/* D1 */
+		SUNXI_FUNCTION(0x3, "uart3"),		/* CTS */
+		SUNXI_FUNCTION(0x4, "emac"),		/* TXCK */
+		SUNXI_FUNCTION(0x5, "uart4"),		/* RX */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 3)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 4),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "mmc1"),		/* D2 */
+		SUNXI_FUNCTION(0x3, "uart5"),		/* TX */
+		SUNXI_FUNCTION(0x4, "emac"),		/* TXD0 */
+		SUNXI_FUNCTION(0x5, "pwm"),
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 4)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 5),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "mmc1"),		/* D3 */
+		SUNXI_FUNCTION(0x3, "uart5"),		/* RX */
+		SUNXI_FUNCTION(0x4, "emac"),		/* TXD1 */
+		SUNXI_FUNCTION(0x5, "pwm"),
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 5)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 6),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "uart1"),		/* TX */
+		SUNXI_FUNCTION(0x3, "i2c2"),		/* SCK */
+		SUNXI_FUNCTION(0x4, "emac"),		/* TXD2 */
+		SUNXI_FUNCTION(0x5, "pwm"),
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 6)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 7),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "uart1"),		/* RX */
+		SUNXI_FUNCTION(0x3, "i2c2"),		/* SDA */
+		SUNXI_FUNCTION(0x4, "emac"),		/* TXD3 */
+		SUNXI_FUNCTION(0x5, "spdif"),		/* IN */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 7)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 8),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "uart1"),		/* RTS */
+		SUNXI_FUNCTION(0x3, "i2c1"),		/* SCK */
+		SUNXI_FUNCTION(0x4, "emac"),		/* RXD2 */
+		SUNXI_FUNCTION(0x5, "uart3"),		/* TX */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 8)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 9),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "uart1"),		/* CTS */
+		SUNXI_FUNCTION(0x3, "i2c1"),		/* SDA */
+		SUNXI_FUNCTION(0x4, "emac"),		/* RXD3 */
+		SUNXI_FUNCTION(0x5, "uart3"),		/* RX */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 9)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 10),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "pwm"),
+		SUNXI_FUNCTION(0x3, "i2c3"),		/* SCK */
+		SUNXI_FUNCTION(0x4, "emac"),		/* RXCK */
+		SUNXI_FUNCTION(0x5, "clk"),		/* FANOUT0 */
+		SUNXI_FUNCTION(0x6, "ir"),		/* RX */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 10)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 11),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "i2s1"),		/* MCLK */
+		SUNXI_FUNCTION(0x3, "i2c3"),		/* SDA */
+		SUNXI_FUNCTION(0x4, "emac"),		/* EPHY-25M */
+		SUNXI_FUNCTION(0x5, "clk"),		/* FANOUT1 */
+		SUNXI_FUNCTION(0x6, "tcon"),		/* TRIG0 */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 11)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 12),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "i2s1"),		/* LRCK */
+		SUNXI_FUNCTION(0x3, "i2c0"),		/* SCK */
+		SUNXI_FUNCTION(0x4, "emac"),		/* TXCTL/TXEN */
+		SUNXI_FUNCTION(0x5, "clk"),		/* FANOUT2 */
+		SUNXI_FUNCTION(0x6, "pwm"),
+		SUNXI_FUNCTION(0x7, "uart1"),		/* TX */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 12)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 13),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "i2s1"),		/* BCLK */
+		SUNXI_FUNCTION(0x3, "i2c0"),		/* SDA */
+		SUNXI_FUNCTION(0x4, "emac"),		/* CLKIN/RXER */
+		SUNXI_FUNCTION(0x5, "pwm"),
+		SUNXI_FUNCTION(0x6, "ledc"),
+		SUNXI_FUNCTION(0x7, "uart1"),		/* RX */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 13)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 14),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "i2s1_din"),	/* DIN0 */
+		SUNXI_FUNCTION(0x3, "i2c2"),		/* SCK */
+		SUNXI_FUNCTION(0x4, "emac"),		/* MDC */
+		SUNXI_FUNCTION(0x5, "i2s1_dout"),	/* DOUT1 */
+		SUNXI_FUNCTION(0x6, "spi0"),		/* WP */
+		SUNXI_FUNCTION(0x7, "uart1"),		/* RTS */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 14)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 15),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "i2s1_dout"),	/* DOUT0 */
+		SUNXI_FUNCTION(0x3, "i2c2"),		/* SDA */
+		SUNXI_FUNCTION(0x4, "emac"),		/* MDIO */
+		SUNXI_FUNCTION(0x5, "i2s1_din"),	/* DIN1 */
+		SUNXI_FUNCTION(0x6, "spi0"),		/* HOLD */
+		SUNXI_FUNCTION(0x7, "uart1"),		/* CTS */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 15)),
+	SUNXI_PIN_VARIANT(SUNXI_PINCTRL_PIN(G, 16),
+		PINCTRL_SUN20I_D1,
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "ir"),		/* RX */
+		SUNXI_FUNCTION(0x3, "tcon"),		/* TRIG0 */
+		SUNXI_FUNCTION(0x4, "pwm"),
+		SUNXI_FUNCTION(0x5, "clk"),		/* FANOUT2 */
+		SUNXI_FUNCTION(0x6, "spdif"),		/* IN */
+		SUNXI_FUNCTION(0x7, "ledc"),
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 16)),
+	SUNXI_PIN_VARIANT(SUNXI_PINCTRL_PIN(G, 17),
+		PINCTRL_SUN20I_D1,
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "uart2"),		/* TX */
+		SUNXI_FUNCTION(0x3, "i2c3"),		/* SCK */
+		SUNXI_FUNCTION(0x4, "pwm"),
+		SUNXI_FUNCTION(0x5, "clk"),		/* FANOUT0 */
+		SUNXI_FUNCTION(0x6, "ir"),		/* TX */
+		SUNXI_FUNCTION(0x7, "uart0"),		/* TX */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 17)),
+	SUNXI_PIN_VARIANT(SUNXI_PINCTRL_PIN(G, 18),
+		PINCTRL_SUN20I_D1,
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "uart2"),		/* RX */
+		SUNXI_FUNCTION(0x3, "i2c3"),		/* SDA */
+		SUNXI_FUNCTION(0x4, "pwm"),
+		SUNXI_FUNCTION(0x5, "clk"),		/* FANOUT1 */
+		SUNXI_FUNCTION(0x6, "spdif"),		/* OUT */
+		SUNXI_FUNCTION(0x7, "uart0"),		/* RX */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 18)),
+};
+
+static const unsigned int d1_irq_bank_map[] = { 1, 2, 3, 4, 5, 6 };
+
+static const struct sunxi_pinctrl_desc d1_pinctrl_data = {
+	.pins			= d1_pins,
+	.npins			= ARRAY_SIZE(d1_pins),
+	.irq_banks		= ARRAY_SIZE(d1_irq_bank_map),
+	.irq_bank_map		= d1_irq_bank_map,
+	.io_bias_cfg_variant	= BIAS_VOLTAGE_PIO_POW_MODE_CTL,
+};
+
+static int d1_pinctrl_probe(struct platform_device *pdev)
+{
+	unsigned long variant = (unsigned long)of_device_get_match_data(&pdev->dev);
+
+	return sunxi_pinctrl_init_with_variant(pdev, &d1_pinctrl_data, variant);
+}
+
+static const struct of_device_id d1_pinctrl_match[] = {
+	{
+		.compatible = "allwinner,sun20i-d1-pinctrl",
+		.data = (void *)PINCTRL_SUN20I_D1
+	},
+	{
+		.compatible = "allwinner,sun20i-d1s-pinctrl",
+		.data = (void *)PINCTRL_SUN20I_D1S
+	},
+	{}
+};
+
+static struct platform_driver d1_pinctrl_driver = {
+	.probe	= d1_pinctrl_probe,
+	.driver	= {
+		.name		= "sun20i-d1-pinctrl",
+		.of_match_table	= d1_pinctrl_match,
+	},
+};
+builtin_platform_driver(d1_pinctrl_driver);
diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
index ec7daaa5666b..350044d4c1b5 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
@@ -1297,11 +1297,11 @@ static int sunxi_pinctrl_build_state(struct platform_device *pdev)
 
 	/*
 	 * Find an upper bound for the maximum number of functions: in
-	 * the worst case we have gpio_in, gpio_out, irq and up to four
+	 * the worst case we have gpio_in, gpio_out, irq and up to seven
 	 * special functions per pin, plus one entry for the sentinel.
 	 * We'll reallocate that later anyway.
 	 */
-	pctl->functions = kcalloc(4 * pctl->ngroups + 4,
+	pctl->functions = kcalloc(7 * pctl->ngroups + 4,
 				  sizeof(*pctl->functions),
 				  GFP_KERNEL);
 	if (!pctl->functions)
@@ -1494,9 +1494,15 @@ int sunxi_pinctrl_init_with_variant(struct platform_device *pdev,
 	pctl->dev = &pdev->dev;
 	pctl->desc = desc;
 	pctl->variant = variant;
-	pctl->bank_mem_size = BANK_MEM_SIZE;
-	pctl->pull_regs_offset = PULL_REGS_OFFSET;
-	pctl->dlevel_field_width = DLEVEL_FIELD_WIDTH;
+	if (pctl->variant >= PINCTRL_SUN20I_D1) {
+		pctl->bank_mem_size = D1_BANK_MEM_SIZE;
+		pctl->pull_regs_offset = D1_PULL_REGS_OFFSET;
+		pctl->dlevel_field_width = D1_DLEVEL_FIELD_WIDTH;
+	} else {
+		pctl->bank_mem_size = BANK_MEM_SIZE;
+		pctl->pull_regs_offset = PULL_REGS_OFFSET;
+		pctl->dlevel_field_width = DLEVEL_FIELD_WIDTH;
+	}
 
 	pctl->irq_array = devm_kcalloc(&pdev->dev,
 				       IRQ_PER_BANK * pctl->desc->irq_banks,
diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.h b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
index c705828add73..f0f48941bc30 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.h
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
@@ -44,6 +44,10 @@
 #define PULL_REGS_OFFSET	0x1c
 #define PULL_FIELD_WIDTH	2
 
+#define D1_BANK_MEM_SIZE	0x30
+#define D1_DLEVEL_FIELD_WIDTH	4
+#define D1_PULL_REGS_OFFSET	0x24
+
 #define PINS_PER_BANK		32
 
 #define IRQ_PER_BANK		32
@@ -88,6 +92,9 @@
 #define PINCTRL_SUN8I_R40	BIT(8)
 #define PINCTRL_SUN8I_V3	BIT(9)
 #define PINCTRL_SUN8I_V3S	BIT(10)
+/* Variants below here have an updated register layout. */
+#define PINCTRL_SUN20I_D1	BIT(11)
+#define PINCTRL_SUN20I_D1S	BIT(12)
 
 #define PIO_POW_MOD_SEL_REG	0x340
 #define PIO_POW_MOD_CTL_REG	0x344
-- 
2.35.1


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

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

* Re: [PATCH 1/6] dt-bindings: pinctrl: Add compatibles for Allwinner D1/D1s
  2022-06-26  2:11   ` Samuel Holland
@ 2022-06-26 10:37     ` Krzysztof Kozlowski
  -1 siblings, 0 replies; 56+ messages in thread
From: Krzysztof Kozlowski @ 2022-06-26 10:37 UTC (permalink / raw)
  To: Samuel Holland, Chen-Yu Tsai, Jernej Skrabec, Linus Walleij
  Cc: Krzysztof Kozlowski, Maxime Ripard, Ondrej Jirman, Rob Herring,
	devicetree, linux-arm-kernel, linux-gpio, linux-kernel,
	linux-sunxi

On 26/06/2022 04:11, Samuel Holland wrote:
> D1 contains a pin controller similar to previous SoCs, but with some
> register layout changes. It includes 6 interrupt-capable pin banks.
> 
> D1s is a low pin count version of the D1 SoC, with some pins omitted.
> The remaining pins have the same function assignments as D1.
> 
> Signed-off-by: Samuel Holland <samuel@sholland.org>


Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>


Best regards,
Krzysztof

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

* Re: [PATCH 1/6] dt-bindings: pinctrl: Add compatibles for Allwinner D1/D1s
@ 2022-06-26 10:37     ` Krzysztof Kozlowski
  0 siblings, 0 replies; 56+ messages in thread
From: Krzysztof Kozlowski @ 2022-06-26 10:37 UTC (permalink / raw)
  To: Samuel Holland, Chen-Yu Tsai, Jernej Skrabec, Linus Walleij
  Cc: Krzysztof Kozlowski, Maxime Ripard, Ondrej Jirman, Rob Herring,
	devicetree, linux-arm-kernel, linux-gpio, linux-kernel,
	linux-sunxi

On 26/06/2022 04:11, Samuel Holland wrote:
> D1 contains a pin controller similar to previous SoCs, but with some
> register layout changes. It includes 6 interrupt-capable pin banks.
> 
> D1s is a low pin count version of the D1 SoC, with some pins omitted.
> The remaining pins have the same function assignments as D1.
> 
> Signed-off-by: Samuel Holland <samuel@sholland.org>


Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>


Best regards,
Krzysztof

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

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

* Re: [PATCH 2/6] pinctrl: sunxi: Add I/O bias setting for H6 R-PIO
  2022-06-26  2:11   ` Samuel Holland
@ 2022-06-27 20:34     ` Jernej Škrabec
  -1 siblings, 0 replies; 56+ messages in thread
From: Jernej Škrabec @ 2022-06-27 20:34 UTC (permalink / raw)
  To: Chen-Yu Tsai, Linus Walleij, Samuel Holland
  Cc: Samuel Holland, Krzysztof Kozlowski, Maxime Ripard,
	Ondrej Jirman, Rob Herring, devicetree, linux-arm-kernel,
	linux-gpio, linux-kernel, linux-sunxi

Dne nedelja, 26. junij 2022 ob 04:11:43 CEST je Samuel Holland napisal(a):
> H6 requires I/O bias configuration on both of its PIO devices.
> Previously it was only done for the main PIO.
> 
> The setting for Port L is at bit 0, so the bank calculation needs to
> account for the pin base. Otherwise the wrong bit is used.
> 
> Fixes: cc62383fcebe ("pinctrl: sunxi: Support I/O bias voltage setting on
> H6") Signed-off-by: Samuel Holland <samuel@sholland.org>

Reviewed-by: Jernej Skrabec <jernej.skrabec@gmail.com>

Did you noticed any improvement with this properly set? In theory, 3.3 V bias 
should always work, right?

Best regards,
Jernej



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

* Re: [PATCH 2/6] pinctrl: sunxi: Add I/O bias setting for H6 R-PIO
@ 2022-06-27 20:34     ` Jernej Škrabec
  0 siblings, 0 replies; 56+ messages in thread
From: Jernej Škrabec @ 2022-06-27 20:34 UTC (permalink / raw)
  To: Chen-Yu Tsai, Linus Walleij, Samuel Holland
  Cc: Samuel Holland, Krzysztof Kozlowski, Maxime Ripard,
	Ondrej Jirman, Rob Herring, devicetree, linux-arm-kernel,
	linux-gpio, linux-kernel, linux-sunxi

Dne nedelja, 26. junij 2022 ob 04:11:43 CEST je Samuel Holland napisal(a):
> H6 requires I/O bias configuration on both of its PIO devices.
> Previously it was only done for the main PIO.
> 
> The setting for Port L is at bit 0, so the bank calculation needs to
> account for the pin base. Otherwise the wrong bit is used.
> 
> Fixes: cc62383fcebe ("pinctrl: sunxi: Support I/O bias voltage setting on
> H6") Signed-off-by: Samuel Holland <samuel@sholland.org>

Reviewed-by: Jernej Skrabec <jernej.skrabec@gmail.com>

Did you noticed any improvement with this properly set? In theory, 3.3 V bias 
should always work, right?

Best regards,
Jernej



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

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

* Re: [PATCH 3/6] pinctrl: sunxi: Support the 2.5V I/O bias mode
  2022-06-26  2:11   ` Samuel Holland
@ 2022-06-27 20:43     ` Jernej Škrabec
  -1 siblings, 0 replies; 56+ messages in thread
From: Jernej Škrabec @ 2022-06-27 20:43 UTC (permalink / raw)
  To: Chen-Yu Tsai, Linus Walleij, Samuel Holland
  Cc: Samuel Holland, Krzysztof Kozlowski, Maxime Ripard,
	Ondrej Jirman, Rob Herring, devicetree, linux-arm-kernel,
	linux-gpio, linux-kernel, linux-sunxi

Dne nedelja, 26. junij 2022 ob 04:11:44 CEST je Samuel Holland napisal(a):
> H616 and newer SoCs feature a 2.5V I/O bias mode in addition to the
> 1.8V and 3.3V modes. This mode is entered by selecting the 3.3V level
> and disabling the "withstand function".
> 
> H616 supports this capability on its main PIO only. A100 supports this
> capability on both its PIO and R-PIO.
> 
> Signed-off-by: Samuel Holland <samuel@sholland.org>
> ---
> 
>  drivers/pinctrl/sunxi/pinctrl-sun50i-a100-r.c |  1 +
>  drivers/pinctrl/sunxi/pinctrl-sun50i-a100.c   |  2 +-
>  drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c   |  2 +-
>  drivers/pinctrl/sunxi/pinctrl-sunxi.c         | 10 ++++++++++
>  drivers/pinctrl/sunxi/pinctrl-sunxi.h         |  7 +++++++
>  5 files changed, 20 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/pinctrl/sunxi/pinctrl-sun50i-a100-r.c
> b/drivers/pinctrl/sunxi/pinctrl-sun50i-a100-r.c index
> 21054fcacd34..afc1f5df7545 100644
> --- a/drivers/pinctrl/sunxi/pinctrl-sun50i-a100-r.c
> +++ b/drivers/pinctrl/sunxi/pinctrl-sun50i-a100-r.c
> @@ -82,6 +82,7 @@ static const struct sunxi_pinctrl_desc a100_r_pinctrl_data
> = { .npins = ARRAY_SIZE(a100_r_pins),
>  	.pin_base = PL_BASE,
>  	.irq_banks = 1,
> +	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_CTL,
>  };
> 
>  static int a100_r_pinctrl_probe(struct platform_device *pdev)
> diff --git a/drivers/pinctrl/sunxi/pinctrl-sun50i-a100.c
> b/drivers/pinctrl/sunxi/pinctrl-sun50i-a100.c index
> e69f6da40dc0..f682e0e4244d 100644
> --- a/drivers/pinctrl/sunxi/pinctrl-sun50i-a100.c
> +++ b/drivers/pinctrl/sunxi/pinctrl-sun50i-a100.c
> @@ -684,7 +684,7 @@ static const struct sunxi_pinctrl_desc a100_pinctrl_data
> = { .npins = ARRAY_SIZE(a100_pins),
>  	.irq_banks = 7,
>  	.irq_bank_map = a100_irq_bank_map,
> -	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_SEL,
> +	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_CTL,
>  };
> 
>  static int a100_pinctrl_probe(struct platform_device *pdev)
> diff --git a/drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c
> b/drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c index
> 152b71226a80..d6ca720ee8d8 100644
> --- a/drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c
> +++ b/drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c
> @@ -525,7 +525,7 @@ static const struct sunxi_pinctrl_desc h616_pinctrl_data
> = { .irq_banks = ARRAY_SIZE(h616_irq_bank_map),
>  	.irq_bank_map = h616_irq_bank_map,
>  	.irq_read_needs_mux = true,
> -	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_SEL,
> +	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_CTL,
>  };
> 
>  static int h616_pinctrl_probe(struct platform_device *pdev)
> diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> b/drivers/pinctrl/sunxi/pinctrl-sunxi.c index 3c5e71359ca8..eb3d595f816a
> 100644
> --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> @@ -662,6 +662,16 @@ static int sunxi_pinctrl_set_io_bias_cfg(struct
> sunxi_pinctrl *pctl, reg &= ~IO_BIAS_MASK;
>  		writel(reg | val, pctl->membase + 
sunxi_grp_config_reg(pin));
>  		return 0;
> +	case BIAS_VOLTAGE_PIO_POW_MODE_CTL:
> +		val = uV > 1800000 && uV <= 2500000 ? BIT(bank) : 0;
> +
> +		raw_spin_lock_irqsave(&pctl->lock, flags);
> +		reg = readl(pctl->membase + PIO_POW_MOD_CTL_REG);
> +		reg &= ~BIT(bank);
> +		writel(reg | val, pctl->membase + PIO_POW_MOD_CTL_REG);
> +		raw_spin_unlock_irqrestore(&pctl->lock, flags);
> +
> +		fallthrough;

Would this set bit 12 as needed? According to documentation, it's a bit 
special case, since it covers VCC-IO, port F and port H, at least according to 
documentation. I guess BIAS_VOLTAGE_PIO_POW_MODE_SEL has same issue.

Best regards,
Jernej

>  	case BIAS_VOLTAGE_PIO_POW_MODE_SEL:
>  		val = uV <= 1800000 ? 1 : 0;
> 
> diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.h
> b/drivers/pinctrl/sunxi/pinctrl-sunxi.h index a32bb5bcb754..0f1aab58650c
> 100644
> --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.h
> +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
> @@ -98,6 +98,7 @@
>  #define PINCTRL_SUN8I_V3S	BIT(10)
> 
>  #define PIO_POW_MOD_SEL_REG	0x340
> +#define PIO_POW_MOD_CTL_REG	0x344
> 
>  enum sunxi_desc_bias_voltage {
>  	BIAS_VOLTAGE_NONE,
> @@ -111,6 +112,12 @@ enum sunxi_desc_bias_voltage {
>  	 * register, as seen on H6 SoC, for example.
>  	 */
>  	BIAS_VOLTAGE_PIO_POW_MODE_SEL,
> +	/*
> +	 * Bias voltage is set through PIO_POW_MOD_SEL_REG
> +	 * and PIO_POW_MOD_CTL_REG register, as seen on
> +	 * A100 and D1 SoC, for example.
> +	 */
> +	BIAS_VOLTAGE_PIO_POW_MODE_CTL,
>  };
> 
>  struct sunxi_desc_function {





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

* Re: [PATCH 3/6] pinctrl: sunxi: Support the 2.5V I/O bias mode
@ 2022-06-27 20:43     ` Jernej Škrabec
  0 siblings, 0 replies; 56+ messages in thread
From: Jernej Škrabec @ 2022-06-27 20:43 UTC (permalink / raw)
  To: Chen-Yu Tsai, Linus Walleij, Samuel Holland
  Cc: Samuel Holland, Krzysztof Kozlowski, Maxime Ripard,
	Ondrej Jirman, Rob Herring, devicetree, linux-arm-kernel,
	linux-gpio, linux-kernel, linux-sunxi

Dne nedelja, 26. junij 2022 ob 04:11:44 CEST je Samuel Holland napisal(a):
> H616 and newer SoCs feature a 2.5V I/O bias mode in addition to the
> 1.8V and 3.3V modes. This mode is entered by selecting the 3.3V level
> and disabling the "withstand function".
> 
> H616 supports this capability on its main PIO only. A100 supports this
> capability on both its PIO and R-PIO.
> 
> Signed-off-by: Samuel Holland <samuel@sholland.org>
> ---
> 
>  drivers/pinctrl/sunxi/pinctrl-sun50i-a100-r.c |  1 +
>  drivers/pinctrl/sunxi/pinctrl-sun50i-a100.c   |  2 +-
>  drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c   |  2 +-
>  drivers/pinctrl/sunxi/pinctrl-sunxi.c         | 10 ++++++++++
>  drivers/pinctrl/sunxi/pinctrl-sunxi.h         |  7 +++++++
>  5 files changed, 20 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/pinctrl/sunxi/pinctrl-sun50i-a100-r.c
> b/drivers/pinctrl/sunxi/pinctrl-sun50i-a100-r.c index
> 21054fcacd34..afc1f5df7545 100644
> --- a/drivers/pinctrl/sunxi/pinctrl-sun50i-a100-r.c
> +++ b/drivers/pinctrl/sunxi/pinctrl-sun50i-a100-r.c
> @@ -82,6 +82,7 @@ static const struct sunxi_pinctrl_desc a100_r_pinctrl_data
> = { .npins = ARRAY_SIZE(a100_r_pins),
>  	.pin_base = PL_BASE,
>  	.irq_banks = 1,
> +	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_CTL,
>  };
> 
>  static int a100_r_pinctrl_probe(struct platform_device *pdev)
> diff --git a/drivers/pinctrl/sunxi/pinctrl-sun50i-a100.c
> b/drivers/pinctrl/sunxi/pinctrl-sun50i-a100.c index
> e69f6da40dc0..f682e0e4244d 100644
> --- a/drivers/pinctrl/sunxi/pinctrl-sun50i-a100.c
> +++ b/drivers/pinctrl/sunxi/pinctrl-sun50i-a100.c
> @@ -684,7 +684,7 @@ static const struct sunxi_pinctrl_desc a100_pinctrl_data
> = { .npins = ARRAY_SIZE(a100_pins),
>  	.irq_banks = 7,
>  	.irq_bank_map = a100_irq_bank_map,
> -	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_SEL,
> +	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_CTL,
>  };
> 
>  static int a100_pinctrl_probe(struct platform_device *pdev)
> diff --git a/drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c
> b/drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c index
> 152b71226a80..d6ca720ee8d8 100644
> --- a/drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c
> +++ b/drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c
> @@ -525,7 +525,7 @@ static const struct sunxi_pinctrl_desc h616_pinctrl_data
> = { .irq_banks = ARRAY_SIZE(h616_irq_bank_map),
>  	.irq_bank_map = h616_irq_bank_map,
>  	.irq_read_needs_mux = true,
> -	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_SEL,
> +	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_CTL,
>  };
> 
>  static int h616_pinctrl_probe(struct platform_device *pdev)
> diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> b/drivers/pinctrl/sunxi/pinctrl-sunxi.c index 3c5e71359ca8..eb3d595f816a
> 100644
> --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> @@ -662,6 +662,16 @@ static int sunxi_pinctrl_set_io_bias_cfg(struct
> sunxi_pinctrl *pctl, reg &= ~IO_BIAS_MASK;
>  		writel(reg | val, pctl->membase + 
sunxi_grp_config_reg(pin));
>  		return 0;
> +	case BIAS_VOLTAGE_PIO_POW_MODE_CTL:
> +		val = uV > 1800000 && uV <= 2500000 ? BIT(bank) : 0;
> +
> +		raw_spin_lock_irqsave(&pctl->lock, flags);
> +		reg = readl(pctl->membase + PIO_POW_MOD_CTL_REG);
> +		reg &= ~BIT(bank);
> +		writel(reg | val, pctl->membase + PIO_POW_MOD_CTL_REG);
> +		raw_spin_unlock_irqrestore(&pctl->lock, flags);
> +
> +		fallthrough;

Would this set bit 12 as needed? According to documentation, it's a bit 
special case, since it covers VCC-IO, port F and port H, at least according to 
documentation. I guess BIAS_VOLTAGE_PIO_POW_MODE_SEL has same issue.

Best regards,
Jernej

>  	case BIAS_VOLTAGE_PIO_POW_MODE_SEL:
>  		val = uV <= 1800000 ? 1 : 0;
> 
> diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.h
> b/drivers/pinctrl/sunxi/pinctrl-sunxi.h index a32bb5bcb754..0f1aab58650c
> 100644
> --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.h
> +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
> @@ -98,6 +98,7 @@
>  #define PINCTRL_SUN8I_V3S	BIT(10)
> 
>  #define PIO_POW_MOD_SEL_REG	0x340
> +#define PIO_POW_MOD_CTL_REG	0x344
> 
>  enum sunxi_desc_bias_voltage {
>  	BIAS_VOLTAGE_NONE,
> @@ -111,6 +112,12 @@ enum sunxi_desc_bias_voltage {
>  	 * register, as seen on H6 SoC, for example.
>  	 */
>  	BIAS_VOLTAGE_PIO_POW_MODE_SEL,
> +	/*
> +	 * Bias voltage is set through PIO_POW_MOD_SEL_REG
> +	 * and PIO_POW_MOD_CTL_REG register, as seen on
> +	 * A100 and D1 SoC, for example.
> +	 */
> +	BIAS_VOLTAGE_PIO_POW_MODE_CTL,
>  };
> 
>  struct sunxi_desc_function {





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

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

* Re: [PATCH 2/6] pinctrl: sunxi: Add I/O bias setting for H6 R-PIO
  2022-06-27 20:34     ` Jernej Škrabec
@ 2022-06-28  3:18       ` Samuel Holland
  -1 siblings, 0 replies; 56+ messages in thread
From: Samuel Holland @ 2022-06-28  3:18 UTC (permalink / raw)
  To: Jernej Škrabec, Chen-Yu Tsai, Linus Walleij
  Cc: Krzysztof Kozlowski, Maxime Ripard, Ondrej Jirman, Rob Herring,
	devicetree, linux-arm-kernel, linux-gpio, linux-kernel,
	linux-sunxi

On 6/27/22 3:34 PM, Jernej Škrabec wrote:
> Dne nedelja, 26. junij 2022 ob 04:11:43 CEST je Samuel Holland napisal(a):
>> H6 requires I/O bias configuration on both of its PIO devices.
>> Previously it was only done for the main PIO.
>>
>> The setting for Port L is at bit 0, so the bank calculation needs to
>> account for the pin base. Otherwise the wrong bit is used.
>>
>> Fixes: cc62383fcebe ("pinctrl: sunxi: Support I/O bias voltage setting on
>> H6") Signed-off-by: Samuel Holland <samuel@sholland.org>
> 
> Reviewed-by: Jernej Skrabec <jernej.skrabec@gmail.com>
> 
> Did you noticed any improvement with this properly set? In theory, 3.3 V bias 
> should always work, right?

I think it matters for inputs, which may not detect a high level state if the
bias (comparator reference) voltage is too high.

It looks like Orange Pi 3 has a 1.8 V supply for port M. I am not currently set
up to test the behavior with different bias settings, but I may do that if I get
the chance.

Regards,
Samuel

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

* Re: [PATCH 2/6] pinctrl: sunxi: Add I/O bias setting for H6 R-PIO
@ 2022-06-28  3:18       ` Samuel Holland
  0 siblings, 0 replies; 56+ messages in thread
From: Samuel Holland @ 2022-06-28  3:18 UTC (permalink / raw)
  To: Jernej Škrabec, Chen-Yu Tsai, Linus Walleij
  Cc: Krzysztof Kozlowski, Maxime Ripard, Ondrej Jirman, Rob Herring,
	devicetree, linux-arm-kernel, linux-gpio, linux-kernel,
	linux-sunxi

On 6/27/22 3:34 PM, Jernej Škrabec wrote:
> Dne nedelja, 26. junij 2022 ob 04:11:43 CEST je Samuel Holland napisal(a):
>> H6 requires I/O bias configuration on both of its PIO devices.
>> Previously it was only done for the main PIO.
>>
>> The setting for Port L is at bit 0, so the bank calculation needs to
>> account for the pin base. Otherwise the wrong bit is used.
>>
>> Fixes: cc62383fcebe ("pinctrl: sunxi: Support I/O bias voltage setting on
>> H6") Signed-off-by: Samuel Holland <samuel@sholland.org>
> 
> Reviewed-by: Jernej Skrabec <jernej.skrabec@gmail.com>
> 
> Did you noticed any improvement with this properly set? In theory, 3.3 V bias 
> should always work, right?

I think it matters for inputs, which may not detect a high level state if the
bias (comparator reference) voltage is too high.

It looks like Orange Pi 3 has a 1.8 V supply for port M. I am not currently set
up to test the behavior with different bias settings, but I may do that if I get
the chance.

Regards,
Samuel

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

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

* Re: [PATCH 3/6] pinctrl: sunxi: Support the 2.5V I/O bias mode
  2022-06-27 20:43     ` Jernej Škrabec
@ 2022-06-28  3:29       ` Samuel Holland
  -1 siblings, 0 replies; 56+ messages in thread
From: Samuel Holland @ 2022-06-28  3:29 UTC (permalink / raw)
  To: Jernej Škrabec, Chen-Yu Tsai, Linus Walleij
  Cc: Krzysztof Kozlowski, Maxime Ripard, Ondrej Jirman, Rob Herring,
	devicetree, linux-arm-kernel, linux-gpio, linux-kernel,
	linux-sunxi

On 6/27/22 3:43 PM, Jernej Škrabec wrote:
> Dne nedelja, 26. junij 2022 ob 04:11:44 CEST je Samuel Holland napisal(a):
>> H616 and newer SoCs feature a 2.5V I/O bias mode in addition to the
>> 1.8V and 3.3V modes. This mode is entered by selecting the 3.3V level
>> and disabling the "withstand function".
>>
>> H616 supports this capability on its main PIO only. A100 supports this
>> capability on both its PIO and R-PIO.
>>
>> Signed-off-by: Samuel Holland <samuel@sholland.org>
>> ---
>>
>>  drivers/pinctrl/sunxi/pinctrl-sun50i-a100-r.c |  1 +
>>  drivers/pinctrl/sunxi/pinctrl-sun50i-a100.c   |  2 +-
>>  drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c   |  2 +-
>>  drivers/pinctrl/sunxi/pinctrl-sunxi.c         | 10 ++++++++++
>>  drivers/pinctrl/sunxi/pinctrl-sunxi.h         |  7 +++++++
>>  5 files changed, 20 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/pinctrl/sunxi/pinctrl-sun50i-a100-r.c
>> b/drivers/pinctrl/sunxi/pinctrl-sun50i-a100-r.c index
>> 21054fcacd34..afc1f5df7545 100644
>> --- a/drivers/pinctrl/sunxi/pinctrl-sun50i-a100-r.c
>> +++ b/drivers/pinctrl/sunxi/pinctrl-sun50i-a100-r.c
>> @@ -82,6 +82,7 @@ static const struct sunxi_pinctrl_desc a100_r_pinctrl_data
>> = { .npins = ARRAY_SIZE(a100_r_pins),
>>  	.pin_base = PL_BASE,
>>  	.irq_banks = 1,
>> +	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_CTL,
>>  };
>>
>>  static int a100_r_pinctrl_probe(struct platform_device *pdev)
>> diff --git a/drivers/pinctrl/sunxi/pinctrl-sun50i-a100.c
>> b/drivers/pinctrl/sunxi/pinctrl-sun50i-a100.c index
>> e69f6da40dc0..f682e0e4244d 100644
>> --- a/drivers/pinctrl/sunxi/pinctrl-sun50i-a100.c
>> +++ b/drivers/pinctrl/sunxi/pinctrl-sun50i-a100.c
>> @@ -684,7 +684,7 @@ static const struct sunxi_pinctrl_desc a100_pinctrl_data
>> = { .npins = ARRAY_SIZE(a100_pins),
>>  	.irq_banks = 7,
>>  	.irq_bank_map = a100_irq_bank_map,
>> -	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_SEL,
>> +	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_CTL,
>>  };
>>
>>  static int a100_pinctrl_probe(struct platform_device *pdev)
>> diff --git a/drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c
>> b/drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c index
>> 152b71226a80..d6ca720ee8d8 100644
>> --- a/drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c
>> +++ b/drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c
>> @@ -525,7 +525,7 @@ static const struct sunxi_pinctrl_desc h616_pinctrl_data
>> = { .irq_banks = ARRAY_SIZE(h616_irq_bank_map),
>>  	.irq_bank_map = h616_irq_bank_map,
>>  	.irq_read_needs_mux = true,
>> -	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_SEL,
>> +	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_CTL,
>>  };
>>
>>  static int h616_pinctrl_probe(struct platform_device *pdev)
>> diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
>> b/drivers/pinctrl/sunxi/pinctrl-sunxi.c index 3c5e71359ca8..eb3d595f816a
>> 100644
>> --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
>> +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
>> @@ -662,6 +662,16 @@ static int sunxi_pinctrl_set_io_bias_cfg(struct
>> sunxi_pinctrl *pctl, reg &= ~IO_BIAS_MASK;
>>  		writel(reg | val, pctl->membase + 
> sunxi_grp_config_reg(pin));
>>  		return 0;
>> +	case BIAS_VOLTAGE_PIO_POW_MODE_CTL:
>> +		val = uV > 1800000 && uV <= 2500000 ? BIT(bank) : 0;
>> +
>> +		raw_spin_lock_irqsave(&pctl->lock, flags);
>> +		reg = readl(pctl->membase + PIO_POW_MOD_CTL_REG);
>> +		reg &= ~BIT(bank);
>> +		writel(reg | val, pctl->membase + PIO_POW_MOD_CTL_REG);
>> +		raw_spin_unlock_irqrestore(&pctl->lock, flags);
>> +
>> +		fallthrough;
> 
> Would this set bit 12 as needed? According to documentation, it's a bit 
> special case, since it covers VCC-IO, port F and port H, at least according to 
> documentation. I guess BIAS_VOLTAGE_PIO_POW_MODE_SEL has same issue.

Right, it seems we would need some mask to tell us which ports are affected by
bit 12, and which have their own setting. The current code is unlikely to cause
any issue, though, because in practice VCC-IO is always 3.3 V.

Regards,
Samuel

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

* Re: [PATCH 3/6] pinctrl: sunxi: Support the 2.5V I/O bias mode
@ 2022-06-28  3:29       ` Samuel Holland
  0 siblings, 0 replies; 56+ messages in thread
From: Samuel Holland @ 2022-06-28  3:29 UTC (permalink / raw)
  To: Jernej Škrabec, Chen-Yu Tsai, Linus Walleij
  Cc: Krzysztof Kozlowski, Maxime Ripard, Ondrej Jirman, Rob Herring,
	devicetree, linux-arm-kernel, linux-gpio, linux-kernel,
	linux-sunxi

On 6/27/22 3:43 PM, Jernej Škrabec wrote:
> Dne nedelja, 26. junij 2022 ob 04:11:44 CEST je Samuel Holland napisal(a):
>> H616 and newer SoCs feature a 2.5V I/O bias mode in addition to the
>> 1.8V and 3.3V modes. This mode is entered by selecting the 3.3V level
>> and disabling the "withstand function".
>>
>> H616 supports this capability on its main PIO only. A100 supports this
>> capability on both its PIO and R-PIO.
>>
>> Signed-off-by: Samuel Holland <samuel@sholland.org>
>> ---
>>
>>  drivers/pinctrl/sunxi/pinctrl-sun50i-a100-r.c |  1 +
>>  drivers/pinctrl/sunxi/pinctrl-sun50i-a100.c   |  2 +-
>>  drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c   |  2 +-
>>  drivers/pinctrl/sunxi/pinctrl-sunxi.c         | 10 ++++++++++
>>  drivers/pinctrl/sunxi/pinctrl-sunxi.h         |  7 +++++++
>>  5 files changed, 20 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/pinctrl/sunxi/pinctrl-sun50i-a100-r.c
>> b/drivers/pinctrl/sunxi/pinctrl-sun50i-a100-r.c index
>> 21054fcacd34..afc1f5df7545 100644
>> --- a/drivers/pinctrl/sunxi/pinctrl-sun50i-a100-r.c
>> +++ b/drivers/pinctrl/sunxi/pinctrl-sun50i-a100-r.c
>> @@ -82,6 +82,7 @@ static const struct sunxi_pinctrl_desc a100_r_pinctrl_data
>> = { .npins = ARRAY_SIZE(a100_r_pins),
>>  	.pin_base = PL_BASE,
>>  	.irq_banks = 1,
>> +	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_CTL,
>>  };
>>
>>  static int a100_r_pinctrl_probe(struct platform_device *pdev)
>> diff --git a/drivers/pinctrl/sunxi/pinctrl-sun50i-a100.c
>> b/drivers/pinctrl/sunxi/pinctrl-sun50i-a100.c index
>> e69f6da40dc0..f682e0e4244d 100644
>> --- a/drivers/pinctrl/sunxi/pinctrl-sun50i-a100.c
>> +++ b/drivers/pinctrl/sunxi/pinctrl-sun50i-a100.c
>> @@ -684,7 +684,7 @@ static const struct sunxi_pinctrl_desc a100_pinctrl_data
>> = { .npins = ARRAY_SIZE(a100_pins),
>>  	.irq_banks = 7,
>>  	.irq_bank_map = a100_irq_bank_map,
>> -	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_SEL,
>> +	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_CTL,
>>  };
>>
>>  static int a100_pinctrl_probe(struct platform_device *pdev)
>> diff --git a/drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c
>> b/drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c index
>> 152b71226a80..d6ca720ee8d8 100644
>> --- a/drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c
>> +++ b/drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c
>> @@ -525,7 +525,7 @@ static const struct sunxi_pinctrl_desc h616_pinctrl_data
>> = { .irq_banks = ARRAY_SIZE(h616_irq_bank_map),
>>  	.irq_bank_map = h616_irq_bank_map,
>>  	.irq_read_needs_mux = true,
>> -	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_SEL,
>> +	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_CTL,
>>  };
>>
>>  static int h616_pinctrl_probe(struct platform_device *pdev)
>> diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
>> b/drivers/pinctrl/sunxi/pinctrl-sunxi.c index 3c5e71359ca8..eb3d595f816a
>> 100644
>> --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
>> +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
>> @@ -662,6 +662,16 @@ static int sunxi_pinctrl_set_io_bias_cfg(struct
>> sunxi_pinctrl *pctl, reg &= ~IO_BIAS_MASK;
>>  		writel(reg | val, pctl->membase + 
> sunxi_grp_config_reg(pin));
>>  		return 0;
>> +	case BIAS_VOLTAGE_PIO_POW_MODE_CTL:
>> +		val = uV > 1800000 && uV <= 2500000 ? BIT(bank) : 0;
>> +
>> +		raw_spin_lock_irqsave(&pctl->lock, flags);
>> +		reg = readl(pctl->membase + PIO_POW_MOD_CTL_REG);
>> +		reg &= ~BIT(bank);
>> +		writel(reg | val, pctl->membase + PIO_POW_MOD_CTL_REG);
>> +		raw_spin_unlock_irqrestore(&pctl->lock, flags);
>> +
>> +		fallthrough;
> 
> Would this set bit 12 as needed? According to documentation, it's a bit 
> special case, since it covers VCC-IO, port F and port H, at least according to 
> documentation. I guess BIAS_VOLTAGE_PIO_POW_MODE_SEL has same issue.

Right, it seems we would need some mask to tell us which ports are affected by
bit 12, and which have their own setting. The current code is unlikely to cause
any issue, though, because in practice VCC-IO is always 3.3 V.

Regards,
Samuel

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

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

* Re: [PATCH 1/6] dt-bindings: pinctrl: Add compatibles for Allwinner D1/D1s
  2022-06-26  2:11   ` Samuel Holland
@ 2022-07-01 13:02     ` Heiko Stuebner
  -1 siblings, 0 replies; 56+ messages in thread
From: Heiko Stuebner @ 2022-07-01 13:02 UTC (permalink / raw)
  To: Chen-Yu Tsai, Jernej Skrabec, Linus Walleij, linux-arm-kernel
  Cc: Samuel Holland, Krzysztof Kozlowski, Maxime Ripard,
	Ondrej Jirman, Rob Herring, devicetree, linux-arm-kernel,
	linux-gpio, linux-kernel, linux-sunxi, Samuel Holland

Am Sonntag, 26. Juni 2022, 04:11:42 CEST schrieb Samuel Holland:
> D1 contains a pin controller similar to previous SoCs, but with some
> register layout changes. It includes 6 interrupt-capable pin banks.
> 
> D1s is a low pin count version of the D1 SoC, with some pins omitted.
> The remaining pins have the same function assignments as D1.
> 
> Signed-off-by: Samuel Holland <samuel@sholland.org>

On a D1-Nezha
Tested-by: Heiko Stuebner <heiko@sntech.de>




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

* Re: [PATCH 1/6] dt-bindings: pinctrl: Add compatibles for Allwinner D1/D1s
@ 2022-07-01 13:02     ` Heiko Stuebner
  0 siblings, 0 replies; 56+ messages in thread
From: Heiko Stuebner @ 2022-07-01 13:02 UTC (permalink / raw)
  To: Chen-Yu Tsai, Jernej Skrabec, Linus Walleij, linux-arm-kernel
  Cc: Samuel Holland, Krzysztof Kozlowski, Maxime Ripard,
	Ondrej Jirman, Rob Herring, devicetree, linux-arm-kernel,
	linux-gpio, linux-kernel, linux-sunxi, Samuel Holland

Am Sonntag, 26. Juni 2022, 04:11:42 CEST schrieb Samuel Holland:
> D1 contains a pin controller similar to previous SoCs, but with some
> register layout changes. It includes 6 interrupt-capable pin banks.
> 
> D1s is a low pin count version of the D1 SoC, with some pins omitted.
> The remaining pins have the same function assignments as D1.
> 
> Signed-off-by: Samuel Holland <samuel@sholland.org>

On a D1-Nezha
Tested-by: Heiko Stuebner <heiko@sntech.de>




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

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

* Re: [PATCH 2/6] pinctrl: sunxi: Add I/O bias setting for H6 R-PIO
  2022-06-26  2:11   ` Samuel Holland
@ 2022-07-01 13:03     ` Heiko Stuebner
  -1 siblings, 0 replies; 56+ messages in thread
From: Heiko Stuebner @ 2022-07-01 13:03 UTC (permalink / raw)
  To: Chen-Yu Tsai, Jernej Skrabec, Linus Walleij, linux-arm-kernel
  Cc: Samuel Holland, Krzysztof Kozlowski, Maxime Ripard,
	Ondrej Jirman, Rob Herring, devicetree, linux-arm-kernel,
	linux-gpio, linux-kernel, linux-sunxi, Samuel Holland

Am Sonntag, 26. Juni 2022, 04:11:43 CEST schrieb Samuel Holland:
> H6 requires I/O bias configuration on both of its PIO devices.
> Previously it was only done for the main PIO.
> 
> The setting for Port L is at bit 0, so the bank calculation needs to
> account for the pin base. Otherwise the wrong bit is used.
> 
> Fixes: cc62383fcebe ("pinctrl: sunxi: Support I/O bias voltage setting on H6")
> Signed-off-by: Samuel Holland <samuel@sholland.org>

On a D1-Nezha
Tested-by: Heiko Stuebner <heiko@sntech.de>





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

* Re: [PATCH 2/6] pinctrl: sunxi: Add I/O bias setting for H6 R-PIO
@ 2022-07-01 13:03     ` Heiko Stuebner
  0 siblings, 0 replies; 56+ messages in thread
From: Heiko Stuebner @ 2022-07-01 13:03 UTC (permalink / raw)
  To: Chen-Yu Tsai, Jernej Skrabec, Linus Walleij, linux-arm-kernel
  Cc: Samuel Holland, Krzysztof Kozlowski, Maxime Ripard,
	Ondrej Jirman, Rob Herring, devicetree, linux-arm-kernel,
	linux-gpio, linux-kernel, linux-sunxi, Samuel Holland

Am Sonntag, 26. Juni 2022, 04:11:43 CEST schrieb Samuel Holland:
> H6 requires I/O bias configuration on both of its PIO devices.
> Previously it was only done for the main PIO.
> 
> The setting for Port L is at bit 0, so the bank calculation needs to
> account for the pin base. Otherwise the wrong bit is used.
> 
> Fixes: cc62383fcebe ("pinctrl: sunxi: Support I/O bias voltage setting on H6")
> Signed-off-by: Samuel Holland <samuel@sholland.org>

On a D1-Nezha
Tested-by: Heiko Stuebner <heiko@sntech.de>





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

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

* Re: [PATCH 3/6] pinctrl: sunxi: Support the 2.5V I/O bias mode
  2022-06-26  2:11   ` Samuel Holland
@ 2022-07-01 13:04     ` Heiko Stuebner
  -1 siblings, 0 replies; 56+ messages in thread
From: Heiko Stuebner @ 2022-07-01 13:04 UTC (permalink / raw)
  To: Chen-Yu Tsai, Jernej Skrabec, Linus Walleij, linux-arm-kernel
  Cc: Samuel Holland, Krzysztof Kozlowski, Maxime Ripard,
	Ondrej Jirman, Rob Herring, devicetree, linux-arm-kernel,
	linux-gpio, linux-kernel, linux-sunxi, Samuel Holland

Am Sonntag, 26. Juni 2022, 04:11:44 CEST schrieb Samuel Holland:
> H616 and newer SoCs feature a 2.5V I/O bias mode in addition to the
> 1.8V and 3.3V modes. This mode is entered by selecting the 3.3V level
> and disabling the "withstand function".
> 
> H616 supports this capability on its main PIO only. A100 supports this
> capability on both its PIO and R-PIO.
> 
> Signed-off-by: Samuel Holland <samuel@sholland.org>

On a D1-Nezha
Tested-by: Heiko Stuebner <heiko@sntech.de>




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

* Re: [PATCH 3/6] pinctrl: sunxi: Support the 2.5V I/O bias mode
@ 2022-07-01 13:04     ` Heiko Stuebner
  0 siblings, 0 replies; 56+ messages in thread
From: Heiko Stuebner @ 2022-07-01 13:04 UTC (permalink / raw)
  To: Chen-Yu Tsai, Jernej Skrabec, Linus Walleij, linux-arm-kernel
  Cc: Samuel Holland, Krzysztof Kozlowski, Maxime Ripard,
	Ondrej Jirman, Rob Herring, devicetree, linux-arm-kernel,
	linux-gpio, linux-kernel, linux-sunxi, Samuel Holland

Am Sonntag, 26. Juni 2022, 04:11:44 CEST schrieb Samuel Holland:
> H616 and newer SoCs feature a 2.5V I/O bias mode in addition to the
> 1.8V and 3.3V modes. This mode is entered by selecting the 3.3V level
> and disabling the "withstand function".
> 
> H616 supports this capability on its main PIO only. A100 supports this
> capability on both its PIO and R-PIO.
> 
> Signed-off-by: Samuel Holland <samuel@sholland.org>

On a D1-Nezha
Tested-by: Heiko Stuebner <heiko@sntech.de>




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

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

* Re: [PATCH 4/6] pinctrl: sunxi: Refactor register/offset calculation
  2022-06-26  2:11   ` Samuel Holland
@ 2022-07-01 13:07     ` Heiko Stuebner
  -1 siblings, 0 replies; 56+ messages in thread
From: Heiko Stuebner @ 2022-07-01 13:07 UTC (permalink / raw)
  To: Chen-Yu Tsai, Jernej Skrabec, Linus Walleij, linux-arm-kernel
  Cc: Samuel Holland, Krzysztof Kozlowski, Maxime Ripard,
	Ondrej Jirman, Rob Herring, devicetree, linux-arm-kernel,
	linux-gpio, linux-kernel, linux-sunxi, Samuel Holland

Am Sonntag, 26. Juni 2022, 04:11:45 CEST schrieb Samuel Holland:
> Starting with the D1/D1s/T113 SoC, Allwinner changed the layout of the
> pinctrl registers. This new layout widens the drive level field, which
> affects the pull register offset and the overall bank size.
> 
> As a first step to support this, combine the register and offset
> calculation functions, and refactor the math to depend on one constant
> for field widths instead of three. This minimizes the code size impact
> of making some of the factors dynamic.
> 
> While rewriting these functions, move them to the implementation file,
> since that is the only file where they are used. And make the comment
> more generic, without mentioning specific offsets/sizes.
> 
> The callers are updated to expect a shifted mask, and to use consistent
> terminology (reg/shift/mask/val).
> 
> Signed-off-by: Samuel Holland <samuel@sholland.org>

On a D1-Nezha
Tested-by: Heiko Stuebner <heiko@sntech.de>

Change also looks good
Reviewed-by: Heiko Stuebner <heiko@sntech.de>



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

* Re: [PATCH 4/6] pinctrl: sunxi: Refactor register/offset calculation
@ 2022-07-01 13:07     ` Heiko Stuebner
  0 siblings, 0 replies; 56+ messages in thread
From: Heiko Stuebner @ 2022-07-01 13:07 UTC (permalink / raw)
  To: Chen-Yu Tsai, Jernej Skrabec, Linus Walleij, linux-arm-kernel
  Cc: Samuel Holland, Krzysztof Kozlowski, Maxime Ripard,
	Ondrej Jirman, Rob Herring, devicetree, linux-arm-kernel,
	linux-gpio, linux-kernel, linux-sunxi, Samuel Holland

Am Sonntag, 26. Juni 2022, 04:11:45 CEST schrieb Samuel Holland:
> Starting with the D1/D1s/T113 SoC, Allwinner changed the layout of the
> pinctrl registers. This new layout widens the drive level field, which
> affects the pull register offset and the overall bank size.
> 
> As a first step to support this, combine the register and offset
> calculation functions, and refactor the math to depend on one constant
> for field widths instead of three. This minimizes the code size impact
> of making some of the factors dynamic.
> 
> While rewriting these functions, move them to the implementation file,
> since that is the only file where they are used. And make the comment
> more generic, without mentioning specific offsets/sizes.
> 
> The callers are updated to expect a shifted mask, and to use consistent
> terminology (reg/shift/mask/val).
> 
> Signed-off-by: Samuel Holland <samuel@sholland.org>

On a D1-Nezha
Tested-by: Heiko Stuebner <heiko@sntech.de>

Change also looks good
Reviewed-by: Heiko Stuebner <heiko@sntech.de>



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

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

* Re: [PATCH 5/6] pinctrl: sunxi: Make some layout parameters dynamic
  2022-06-26  2:11   ` Samuel Holland
@ 2022-07-01 13:09     ` Heiko Stuebner
  -1 siblings, 0 replies; 56+ messages in thread
From: Heiko Stuebner @ 2022-07-01 13:09 UTC (permalink / raw)
  To: Chen-Yu Tsai, Jernej Skrabec, Linus Walleij, linux-arm-kernel
  Cc: Samuel Holland, Krzysztof Kozlowski, Maxime Ripard,
	Ondrej Jirman, Rob Herring, devicetree, linux-arm-kernel,
	linux-gpio, linux-kernel, linux-sunxi, Samuel Holland

Am Sonntag, 26. Juni 2022, 04:11:46 CEST schrieb Samuel Holland:
> Starting with the D1/D1s/T113 SoC, Allwinner changed the layout of the
> pinctrl registers. This new layout widens the drive level field, which
> affects the pull register offset and the overall bank size.
> 
> In order to support multiple register layouts, some of the layout
> parameters need to be set based on the pinctrl variant. This requires
> passing the pinctrl struct pointer to the register/offset calculation
> functions.
> 
> Signed-off-by: Samuel Holland <samuel@sholland.org>

On a D1-Nezha
Tested-by: Heiko Stuebner <heiko@sntech.de>

Reviewed-by: Heiko Stuebner <heiko@sntech.de>



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

* Re: [PATCH 5/6] pinctrl: sunxi: Make some layout parameters dynamic
@ 2022-07-01 13:09     ` Heiko Stuebner
  0 siblings, 0 replies; 56+ messages in thread
From: Heiko Stuebner @ 2022-07-01 13:09 UTC (permalink / raw)
  To: Chen-Yu Tsai, Jernej Skrabec, Linus Walleij, linux-arm-kernel
  Cc: Samuel Holland, Krzysztof Kozlowski, Maxime Ripard,
	Ondrej Jirman, Rob Herring, devicetree, linux-arm-kernel,
	linux-gpio, linux-kernel, linux-sunxi, Samuel Holland

Am Sonntag, 26. Juni 2022, 04:11:46 CEST schrieb Samuel Holland:
> Starting with the D1/D1s/T113 SoC, Allwinner changed the layout of the
> pinctrl registers. This new layout widens the drive level field, which
> affects the pull register offset and the overall bank size.
> 
> In order to support multiple register layouts, some of the layout
> parameters need to be set based on the pinctrl variant. This requires
> passing the pinctrl struct pointer to the register/offset calculation
> functions.
> 
> Signed-off-by: Samuel Holland <samuel@sholland.org>

On a D1-Nezha
Tested-by: Heiko Stuebner <heiko@sntech.de>

Reviewed-by: Heiko Stuebner <heiko@sntech.de>



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

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

* Re: [PATCH 6/6] pinctrl: sunxi: Add driver for Allwinner D1/D1s
  2022-06-26  2:11   ` Samuel Holland
@ 2022-07-01 13:13     ` Heiko Stuebner
  -1 siblings, 0 replies; 56+ messages in thread
From: Heiko Stuebner @ 2022-07-01 13:13 UTC (permalink / raw)
  To: Chen-Yu Tsai, Jernej Skrabec, Linus Walleij, linux-arm-kernel
  Cc: Samuel Holland, Krzysztof Kozlowski, Maxime Ripard,
	Ondrej Jirman, Rob Herring, devicetree, linux-arm-kernel,
	linux-gpio, linux-kernel, linux-sunxi, Samuel Holland

Am Sonntag, 26. Juni 2022, 04:11:47 CEST schrieb Samuel Holland:
> These SoCs contain a pinctrl with a new register layout. Use the variant
> parameter to set the right register offsets. This pinctrl also increases
> the number of functions per pin from 8 to 16, taking advantage of all 4
> bits in the mux config field (so far, only functions 0-8 and 14-15 are
> used). This increases the maximum possible number of functions.
> 
> D1s is a low pin count version of the D1 SoC, with some pins omitted.
> The remaining pins have the same function assignments as D1.
> 
> Signed-off-by: Samuel Holland <samuel@sholland.org>

On a D1-Nezha
Tested-by: Heiko Stuebner <heiko@sntech.de>

Reviewed-by: Heiko Stuebner <heiko@sntech.de>

with one remark below

> diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> index ec7daaa5666b..350044d4c1b5 100644
> --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> @@ -1297,11 +1297,11 @@ static int sunxi_pinctrl_build_state(struct platform_device *pdev)
>  
>  	/*
>  	 * Find an upper bound for the maximum number of functions: in
> -	 * the worst case we have gpio_in, gpio_out, irq and up to four
> +	 * the worst case we have gpio_in, gpio_out, irq and up to seven
>  	 * special functions per pin, plus one entry for the sentinel.
>  	 * We'll reallocate that later anyway.
>  	 */
> -	pctl->functions = kcalloc(4 * pctl->ngroups + 4,
> +	pctl->functions = kcalloc(7 * pctl->ngroups + 4,
>  				  sizeof(*pctl->functions),
>  				  GFP_KERNEL);
>  	if (!pctl->functions)
> @@ -1494,9 +1494,15 @@ int sunxi_pinctrl_init_with_variant(struct platform_device *pdev,
>  	pctl->dev = &pdev->dev;
>  	pctl->desc = desc;
>  	pctl->variant = variant;
> -	pctl->bank_mem_size = BANK_MEM_SIZE;
> -	pctl->pull_regs_offset = PULL_REGS_OFFSET;
> -	pctl->dlevel_field_width = DLEVEL_FIELD_WIDTH;
> +	if (pctl->variant >= PINCTRL_SUN20I_D1) {
> +		pctl->bank_mem_size = D1_BANK_MEM_SIZE;
> +		pctl->pull_regs_offset = D1_PULL_REGS_OFFSET;
> +		pctl->dlevel_field_width = D1_DLEVEL_FIELD_WIDTH;
> +	} else {
> +		pctl->bank_mem_size = BANK_MEM_SIZE;
> +		pctl->pull_regs_offset = PULL_REGS_OFFSET;
> +		pctl->dlevel_field_width = DLEVEL_FIELD_WIDTH;
> +	}

this is likely ok for _one_ variant (so for now this should be ok) but
will get ugly when there are more of them.

So in the long term it might make sense to pass these values in from
the soc-specific driver maybe?


Heiko



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

* Re: [PATCH 6/6] pinctrl: sunxi: Add driver for Allwinner D1/D1s
@ 2022-07-01 13:13     ` Heiko Stuebner
  0 siblings, 0 replies; 56+ messages in thread
From: Heiko Stuebner @ 2022-07-01 13:13 UTC (permalink / raw)
  To: Chen-Yu Tsai, Jernej Skrabec, Linus Walleij, linux-arm-kernel
  Cc: Samuel Holland, Krzysztof Kozlowski, Maxime Ripard,
	Ondrej Jirman, Rob Herring, devicetree, linux-arm-kernel,
	linux-gpio, linux-kernel, linux-sunxi, Samuel Holland

Am Sonntag, 26. Juni 2022, 04:11:47 CEST schrieb Samuel Holland:
> These SoCs contain a pinctrl with a new register layout. Use the variant
> parameter to set the right register offsets. This pinctrl also increases
> the number of functions per pin from 8 to 16, taking advantage of all 4
> bits in the mux config field (so far, only functions 0-8 and 14-15 are
> used). This increases the maximum possible number of functions.
> 
> D1s is a low pin count version of the D1 SoC, with some pins omitted.
> The remaining pins have the same function assignments as D1.
> 
> Signed-off-by: Samuel Holland <samuel@sholland.org>

On a D1-Nezha
Tested-by: Heiko Stuebner <heiko@sntech.de>

Reviewed-by: Heiko Stuebner <heiko@sntech.de>

with one remark below

> diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> index ec7daaa5666b..350044d4c1b5 100644
> --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> @@ -1297,11 +1297,11 @@ static int sunxi_pinctrl_build_state(struct platform_device *pdev)
>  
>  	/*
>  	 * Find an upper bound for the maximum number of functions: in
> -	 * the worst case we have gpio_in, gpio_out, irq and up to four
> +	 * the worst case we have gpio_in, gpio_out, irq and up to seven
>  	 * special functions per pin, plus one entry for the sentinel.
>  	 * We'll reallocate that later anyway.
>  	 */
> -	pctl->functions = kcalloc(4 * pctl->ngroups + 4,
> +	pctl->functions = kcalloc(7 * pctl->ngroups + 4,
>  				  sizeof(*pctl->functions),
>  				  GFP_KERNEL);
>  	if (!pctl->functions)
> @@ -1494,9 +1494,15 @@ int sunxi_pinctrl_init_with_variant(struct platform_device *pdev,
>  	pctl->dev = &pdev->dev;
>  	pctl->desc = desc;
>  	pctl->variant = variant;
> -	pctl->bank_mem_size = BANK_MEM_SIZE;
> -	pctl->pull_regs_offset = PULL_REGS_OFFSET;
> -	pctl->dlevel_field_width = DLEVEL_FIELD_WIDTH;
> +	if (pctl->variant >= PINCTRL_SUN20I_D1) {
> +		pctl->bank_mem_size = D1_BANK_MEM_SIZE;
> +		pctl->pull_regs_offset = D1_PULL_REGS_OFFSET;
> +		pctl->dlevel_field_width = D1_DLEVEL_FIELD_WIDTH;
> +	} else {
> +		pctl->bank_mem_size = BANK_MEM_SIZE;
> +		pctl->pull_regs_offset = PULL_REGS_OFFSET;
> +		pctl->dlevel_field_width = DLEVEL_FIELD_WIDTH;
> +	}

this is likely ok for _one_ variant (so for now this should be ok) but
will get ugly when there are more of them.

So in the long term it might make sense to pass these values in from
the soc-specific driver maybe?


Heiko



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

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

* Re: [PATCH 6/6] pinctrl: sunxi: Add driver for Allwinner D1/D1s
  2022-07-01 13:13     ` Heiko Stuebner
@ 2022-07-01 15:16       ` Samuel Holland
  -1 siblings, 0 replies; 56+ messages in thread
From: Samuel Holland @ 2022-07-01 15:16 UTC (permalink / raw)
  To: Heiko Stuebner, Chen-Yu Tsai, Jernej Skrabec, Linus Walleij,
	linux-arm-kernel
  Cc: Krzysztof Kozlowski, Maxime Ripard, Ondrej Jirman, Rob Herring,
	devicetree, linux-gpio, linux-kernel, linux-sunxi

Hi Heiko,

On 7/1/22 8:13 AM, Heiko Stuebner wrote:
> Am Sonntag, 26. Juni 2022, 04:11:47 CEST schrieb Samuel Holland:
>> These SoCs contain a pinctrl with a new register layout. Use the variant
>> parameter to set the right register offsets. This pinctrl also increases
>> the number of functions per pin from 8 to 16, taking advantage of all 4
>> bits in the mux config field (so far, only functions 0-8 and 14-15 are
>> used). This increases the maximum possible number of functions.
>>
>> D1s is a low pin count version of the D1 SoC, with some pins omitted.
>> The remaining pins have the same function assignments as D1.
>>
>> Signed-off-by: Samuel Holland <samuel@sholland.org>
> 
> On a D1-Nezha
> Tested-by: Heiko Stuebner <heiko@sntech.de>
> 
> Reviewed-by: Heiko Stuebner <heiko@sntech.de>
> 
> with one remark below

Thanks for reviewing the series.

>> diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
>> index ec7daaa5666b..350044d4c1b5 100644
>> --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
>> +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
>> @@ -1297,11 +1297,11 @@ static int sunxi_pinctrl_build_state(struct platform_device *pdev)
>>  
>>  	/*
>>  	 * Find an upper bound for the maximum number of functions: in
>> -	 * the worst case we have gpio_in, gpio_out, irq and up to four
>> +	 * the worst case we have gpio_in, gpio_out, irq and up to seven
>>  	 * special functions per pin, plus one entry for the sentinel.
>>  	 * We'll reallocate that later anyway.
>>  	 */
>> -	pctl->functions = kcalloc(4 * pctl->ngroups + 4,
>> +	pctl->functions = kcalloc(7 * pctl->ngroups + 4,
>>  				  sizeof(*pctl->functions),
>>  				  GFP_KERNEL);
>>  	if (!pctl->functions)
>> @@ -1494,9 +1494,15 @@ int sunxi_pinctrl_init_with_variant(struct platform_device *pdev,
>>  	pctl->dev = &pdev->dev;
>>  	pctl->desc = desc;
>>  	pctl->variant = variant;
>> -	pctl->bank_mem_size = BANK_MEM_SIZE;
>> -	pctl->pull_regs_offset = PULL_REGS_OFFSET;
>> -	pctl->dlevel_field_width = DLEVEL_FIELD_WIDTH;
>> +	if (pctl->variant >= PINCTRL_SUN20I_D1) {
>> +		pctl->bank_mem_size = D1_BANK_MEM_SIZE;
>> +		pctl->pull_regs_offset = D1_PULL_REGS_OFFSET;
>> +		pctl->dlevel_field_width = D1_DLEVEL_FIELD_WIDTH;
>> +	} else {
>> +		pctl->bank_mem_size = BANK_MEM_SIZE;
>> +		pctl->pull_regs_offset = PULL_REGS_OFFSET;
>> +		pctl->dlevel_field_width = DLEVEL_FIELD_WIDTH;
>> +	}
> 
> this is likely ok for _one_ variant (so for now this should be ok) but
> will get ugly when there are more of them.
> 
> So in the long term it might make sense to pass these values in from
> the soc-specific driver maybe?

Yes, in the long term. It took 10 years before the first layout change, so I do
not expect another layout change any time soon.

For now, I did not want to deal with the overhead of passing in the offsets
individually, nor coming up with a name for each layout to look up the offsets
from a table. (The BSP calls the variants "SUNXI_PCTL_HW_TYPE_0" and
"SUNXI_PCTL_HW_TYPE_1", which is... not descriptive.)

Regards,
Samuel

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

* Re: [PATCH 6/6] pinctrl: sunxi: Add driver for Allwinner D1/D1s
@ 2022-07-01 15:16       ` Samuel Holland
  0 siblings, 0 replies; 56+ messages in thread
From: Samuel Holland @ 2022-07-01 15:16 UTC (permalink / raw)
  To: Heiko Stuebner, Chen-Yu Tsai, Jernej Skrabec, Linus Walleij,
	linux-arm-kernel
  Cc: Krzysztof Kozlowski, Maxime Ripard, Ondrej Jirman, Rob Herring,
	devicetree, linux-gpio, linux-kernel, linux-sunxi

Hi Heiko,

On 7/1/22 8:13 AM, Heiko Stuebner wrote:
> Am Sonntag, 26. Juni 2022, 04:11:47 CEST schrieb Samuel Holland:
>> These SoCs contain a pinctrl with a new register layout. Use the variant
>> parameter to set the right register offsets. This pinctrl also increases
>> the number of functions per pin from 8 to 16, taking advantage of all 4
>> bits in the mux config field (so far, only functions 0-8 and 14-15 are
>> used). This increases the maximum possible number of functions.
>>
>> D1s is a low pin count version of the D1 SoC, with some pins omitted.
>> The remaining pins have the same function assignments as D1.
>>
>> Signed-off-by: Samuel Holland <samuel@sholland.org>
> 
> On a D1-Nezha
> Tested-by: Heiko Stuebner <heiko@sntech.de>
> 
> Reviewed-by: Heiko Stuebner <heiko@sntech.de>
> 
> with one remark below

Thanks for reviewing the series.

>> diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
>> index ec7daaa5666b..350044d4c1b5 100644
>> --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
>> +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
>> @@ -1297,11 +1297,11 @@ static int sunxi_pinctrl_build_state(struct platform_device *pdev)
>>  
>>  	/*
>>  	 * Find an upper bound for the maximum number of functions: in
>> -	 * the worst case we have gpio_in, gpio_out, irq and up to four
>> +	 * the worst case we have gpio_in, gpio_out, irq and up to seven
>>  	 * special functions per pin, plus one entry for the sentinel.
>>  	 * We'll reallocate that later anyway.
>>  	 */
>> -	pctl->functions = kcalloc(4 * pctl->ngroups + 4,
>> +	pctl->functions = kcalloc(7 * pctl->ngroups + 4,
>>  				  sizeof(*pctl->functions),
>>  				  GFP_KERNEL);
>>  	if (!pctl->functions)
>> @@ -1494,9 +1494,15 @@ int sunxi_pinctrl_init_with_variant(struct platform_device *pdev,
>>  	pctl->dev = &pdev->dev;
>>  	pctl->desc = desc;
>>  	pctl->variant = variant;
>> -	pctl->bank_mem_size = BANK_MEM_SIZE;
>> -	pctl->pull_regs_offset = PULL_REGS_OFFSET;
>> -	pctl->dlevel_field_width = DLEVEL_FIELD_WIDTH;
>> +	if (pctl->variant >= PINCTRL_SUN20I_D1) {
>> +		pctl->bank_mem_size = D1_BANK_MEM_SIZE;
>> +		pctl->pull_regs_offset = D1_PULL_REGS_OFFSET;
>> +		pctl->dlevel_field_width = D1_DLEVEL_FIELD_WIDTH;
>> +	} else {
>> +		pctl->bank_mem_size = BANK_MEM_SIZE;
>> +		pctl->pull_regs_offset = PULL_REGS_OFFSET;
>> +		pctl->dlevel_field_width = DLEVEL_FIELD_WIDTH;
>> +	}
> 
> this is likely ok for _one_ variant (so for now this should be ok) but
> will get ugly when there are more of them.
> 
> So in the long term it might make sense to pass these values in from
> the soc-specific driver maybe?

Yes, in the long term. It took 10 years before the first layout change, so I do
not expect another layout change any time soon.

For now, I did not want to deal with the overhead of passing in the offsets
individually, nor coming up with a name for each layout to look up the offsets
from a table. (The BSP calls the variants "SUNXI_PCTL_HW_TYPE_0" and
"SUNXI_PCTL_HW_TYPE_1", which is... not descriptive.)

Regards,
Samuel

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

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

* Re: [PATCH 6/6] pinctrl: sunxi: Add driver for Allwinner D1/D1s
  2022-06-26  2:11   ` Samuel Holland
@ 2022-07-02 14:47     ` Andre Przywara
  -1 siblings, 0 replies; 56+ messages in thread
From: Andre Przywara @ 2022-07-02 14:47 UTC (permalink / raw)
  To: Samuel Holland
  Cc: Chen-Yu Tsai, Jernej Skrabec, Linus Walleij, Krzysztof Kozlowski,
	Maxime Ripard, Ondrej Jirman, Rob Herring, devicetree,
	linux-arm-kernel, linux-gpio, linux-kernel, linux-sunxi,
	Heiko Stuebner

On Sat, 25 Jun 2022 21:11:47 -0500
Samuel Holland <samuel@sholland.org> wrote:

Hi Samuel,

> These SoCs contain a pinctrl with a new register layout. Use the variant
> parameter to set the right register offsets. This pinctrl also increases
> the number of functions per pin from 8 to 16, taking advantage of all 4
> bits in the mux config field (so far, only functions 0-8 and 14-15 are
> used). This increases the maximum possible number of functions.
> 
> D1s is a low pin count version of the D1 SoC, with some pins omitted.
> The remaining pins have the same function assignments as D1.

So do we actually need this extra variant, if there are no conflicts?
The D1s seems to be a simple subset of the D1. I think we followed the
same approach for the H616 already, where there are more pins in the
pinctrl driver than the manual describes, and which are used in other
package variants, like the T507.
In case of the H616, those pins are there, you can program them (which
is not the case for not implemented pins otherwise), they are just not
connected to the package.
I would expect a DT to never reference them, and even if, it doesn't do
any harm other than just not working.

For the table below: I checked every pin against the D1 manual (yes,
that took an hour), and found only one small issue and some nits in
PortE, see inline.

> Signed-off-by: Samuel Holland <samuel@sholland.org>
> ---
> 
>  drivers/pinctrl/sunxi/Kconfig             |   5 +
>  drivers/pinctrl/sunxi/Makefile            |   1 +
>  drivers/pinctrl/sunxi/pinctrl-sun20i-d1.c | 860 ++++++++++++++++++++++
>  drivers/pinctrl/sunxi/pinctrl-sunxi.c     |  16 +-
>  drivers/pinctrl/sunxi/pinctrl-sunxi.h     |   7 +
>  5 files changed, 884 insertions(+), 5 deletions(-)
>  create mode 100644 drivers/pinctrl/sunxi/pinctrl-sun20i-d1.c
> 
> diff --git a/drivers/pinctrl/sunxi/Kconfig b/drivers/pinctrl/sunxi/Kconfig
> index 33751a6a0757..a6ac1c1f2585 100644
> --- a/drivers/pinctrl/sunxi/Kconfig
> +++ b/drivers/pinctrl/sunxi/Kconfig
> @@ -84,6 +84,11 @@ config PINCTRL_SUN9I_A80_R
>  	depends on RESET_CONTROLLER
>  	select PINCTRL_SUNXI
>  
> +config PINCTRL_SUN20I_D1
> +	bool "Support for the Allwinner D1 PIO"
> +	default RISCV && ARCH_SUNXI
> +	select PINCTRL_SUNXI
> +
>  config PINCTRL_SUN50I_A64
>  	bool "Support for the Allwinner A64 PIO"
>  	default ARM64 && ARCH_SUNXI
> diff --git a/drivers/pinctrl/sunxi/Makefile b/drivers/pinctrl/sunxi/Makefile
> index d3440c42b9d6..2ff5a55927ad 100644
> --- a/drivers/pinctrl/sunxi/Makefile
> +++ b/drivers/pinctrl/sunxi/Makefile
> @@ -20,6 +20,7 @@ obj-$(CONFIG_PINCTRL_SUN8I_A83T_R)	+= pinctrl-sun8i-a83t-r.o
>  obj-$(CONFIG_PINCTRL_SUN8I_H3)		+= pinctrl-sun8i-h3.o
>  obj-$(CONFIG_PINCTRL_SUN8I_H3_R)	+= pinctrl-sun8i-h3-r.o
>  obj-$(CONFIG_PINCTRL_SUN8I_V3S)		+= pinctrl-sun8i-v3s.o
> +obj-$(CONFIG_PINCTRL_SUN20I_D1)		+= pinctrl-sun20i-d1.o
>  obj-$(CONFIG_PINCTRL_SUN50I_H5)		+= pinctrl-sun50i-h5.o
>  obj-$(CONFIG_PINCTRL_SUN50I_H6)		+= pinctrl-sun50i-h6.o
>  obj-$(CONFIG_PINCTRL_SUN50I_H6_R)	+= pinctrl-sun50i-h6-r.o
> diff --git a/drivers/pinctrl/sunxi/pinctrl-sun20i-d1.c b/drivers/pinctrl/sunxi/pinctrl-sun20i-d1.c
> new file mode 100644
> index 000000000000..7247c1f1d92c
> --- /dev/null
> +++ b/drivers/pinctrl/sunxi/pinctrl-sun20i-d1.c
> @@ -0,0 +1,860 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Allwinner D1 SoC pinctrl driver.
> + *
> + * Copyright (c) 2020 wuyan@allwinnertech.com
> + * Copyright (c) 2021-2022 Samuel Holland <samuel@sholland.org>
> + */
> +
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/of.h>
> +#include <linux/of_device.h>
> +#include <linux/pinctrl/pinctrl.h>
> +
> +#include "pinctrl-sunxi.h"
> +
> +static const struct sunxi_desc_pin d1_pins[] = {
> +	/* PB */
> +	SUNXI_PIN_VARIANT(SUNXI_PINCTRL_PIN(B, 0),
> +		PINCTRL_SUN20I_D1,
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "pwm"),

The manual mentions the PWM channel number in the pin name, and it
seems like in other pinctrl drivers we use the number either in the
function name, or at least in the comment.
Shall we do one of them here as well?
And the mux numbers for pwm are all over the place, so lets hope we
never need pwm in U-Boot ;-)

> +		SUNXI_FUNCTION(0x3, "ir"),		/* TX */
> +		SUNXI_FUNCTION(0x4, "i2c2"),		/* SCK */
> +		SUNXI_FUNCTION(0x5, "spi1"),		/* WP */
> +		SUNXI_FUNCTION(0x6, "uart0"),		/* TX */
> +		SUNXI_FUNCTION(0x7, "uart2"),		/* TX */
> +		SUNXI_FUNCTION(0x8, "spdif"),		/* OUT */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 0)),
> +	SUNXI_PIN_VARIANT(SUNXI_PINCTRL_PIN(B, 1),
> +		PINCTRL_SUN20I_D1,
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "pwm"),
> +		SUNXI_FUNCTION(0x3, "i2s2_dout"),	/* DOUT3 */
> +		SUNXI_FUNCTION(0x4, "i2c2"),		/* SDA */
> +		SUNXI_FUNCTION(0x5, "i2s2_din"),	/* DIN3 */
> +		SUNXI_FUNCTION(0x6, "uart0"),		/* RX */
> +		SUNXI_FUNCTION(0x7, "uart2"),		/* RX */
> +		SUNXI_FUNCTION(0x8, "ir"),		/* RX */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 1)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 2),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd0"),		/* D0 */
> +		SUNXI_FUNCTION(0x3, "i2s2_dout"),	/* DOUT2 */
> +		SUNXI_FUNCTION(0x4, "i2c0"),		/* SDA */
> +		SUNXI_FUNCTION(0x5, "i2s2_din"),	/* DIN2 */
> +		SUNXI_FUNCTION(0x6, "lcd0"),		/* D18 */
> +		SUNXI_FUNCTION(0x7, "uart4"),		/* TX */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 2)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 3),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd0"),		/* D1 */
> +		SUNXI_FUNCTION(0x3, "i2s2_dout"),	/* DOUT1 */
> +		SUNXI_FUNCTION(0x4, "i2c0"),		/* SCK */
> +		SUNXI_FUNCTION(0x5, "i2s2_din"),	/* DIN0 */
> +		SUNXI_FUNCTION(0x6, "lcd0"),		/* D19 */
> +		SUNXI_FUNCTION(0x7, "uart4"),		/* RX */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 3)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 4),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd0"),		/* D8 */
> +		SUNXI_FUNCTION(0x3, "i2s2_dout"),	/* DOUT0 */
> +		SUNXI_FUNCTION(0x4, "i2c1"),		/* SCK */
> +		SUNXI_FUNCTION(0x5, "i2s2_din"),	/* DIN1 */
> +		SUNXI_FUNCTION(0x6, "lcd0"),		/* D20 */
> +		SUNXI_FUNCTION(0x7, "uart5"),		/* TX */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 4)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 5),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd0"),		/* D9 */
> +		SUNXI_FUNCTION(0x3, "i2s2"),		/* BCLK */
> +		SUNXI_FUNCTION(0x4, "i2c1"),		/* SDA */
> +		SUNXI_FUNCTION(0x5, "pwm"),
> +		SUNXI_FUNCTION(0x6, "lcd0"),		/* D21 */
> +		SUNXI_FUNCTION(0x7, "uart5"),		/* RX */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 5)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 6),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd0"),		/* D16 */
> +		SUNXI_FUNCTION(0x3, "i2s2"),		/* LRCK */
> +		SUNXI_FUNCTION(0x4, "i2c3"),		/* SCK */
> +		SUNXI_FUNCTION(0x5, "pwm"),
> +		SUNXI_FUNCTION(0x6, "lcd0"),		/* D22 */
> +		SUNXI_FUNCTION(0x7, "uart3"),		/* TX */
> +		SUNXI_FUNCTION(0x8, "bist0"),		/* BIST_RESULT0 */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 6)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 7),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd0"),		/* D17 */
> +		SUNXI_FUNCTION(0x3, "i2s2"),		/* MCLK */
> +		SUNXI_FUNCTION(0x4, "i2c3"),		/* SDA */
> +		SUNXI_FUNCTION(0x5, "ir"),		/* RX */
> +		SUNXI_FUNCTION(0x6, "lcd0"),		/* D23 */
> +		SUNXI_FUNCTION(0x7, "uart3"),		/* RX */
> +		SUNXI_FUNCTION(0x8, "bist1"),		/* BIST_RESULT1 */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 7)),
> +	SUNXI_PIN_VARIANT(SUNXI_PINCTRL_PIN(B, 8),
> +		PINCTRL_SUN20I_D1,
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "dmic"),		/* DATA3 */
> +		SUNXI_FUNCTION(0x3, "pwm"),
> +		SUNXI_FUNCTION(0x4, "i2c2"),		/* SCK */
> +		SUNXI_FUNCTION(0x5, "spi1"),		/* HOLD */
> +		SUNXI_FUNCTION(0x6, "uart0"),		/* TX */
> +		SUNXI_FUNCTION(0x7, "uart1"),		/* TX */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 8)),
> +	SUNXI_PIN_VARIANT(SUNXI_PINCTRL_PIN(B, 9),
> +		PINCTRL_SUN20I_D1,
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "dmic"),		/* DATA2 */
> +		SUNXI_FUNCTION(0x3, "pwm"),
> +		SUNXI_FUNCTION(0x4, "i2c2"),		/* SDA */
> +		SUNXI_FUNCTION(0x5, "spi1"),		/* MISO */
> +		SUNXI_FUNCTION(0x6, "uart0"),		/* RX */
> +		SUNXI_FUNCTION(0x7, "uart1"),		/* RX */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 9)),
> +	SUNXI_PIN_VARIANT(SUNXI_PINCTRL_PIN(B, 10),
> +		PINCTRL_SUN20I_D1,
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "dmic"),		/* DATA1 */
> +		SUNXI_FUNCTION(0x3, "pwm"),
> +		SUNXI_FUNCTION(0x4, "i2c0"),		/* SCK */
> +		SUNXI_FUNCTION(0x5, "spi1"),		/* MOSI */
> +		SUNXI_FUNCTION(0x6, "clk"),		/* FANOUT0 */
> +		SUNXI_FUNCTION(0x7, "uart1"),		/* RTS */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 10)),
> +	SUNXI_PIN_VARIANT(SUNXI_PINCTRL_PIN(B, 11),
> +		PINCTRL_SUN20I_D1,
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "dmic"),		/* DATA0 */
> +		SUNXI_FUNCTION(0x3, "pwm"),
> +		SUNXI_FUNCTION(0x4, "i2c0"),		/* SDA */
> +		SUNXI_FUNCTION(0x5, "spi1"),		/* CLK */
> +		SUNXI_FUNCTION(0x6, "clk"),		/* FANOUT1 */
> +		SUNXI_FUNCTION(0x7, "uart1"),		/* CTS */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 11)),
> +	SUNXI_PIN_VARIANT(SUNXI_PINCTRL_PIN(B, 12),
> +		PINCTRL_SUN20I_D1,
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "dmic"),		/* CLK */
> +		SUNXI_FUNCTION(0x3, "pwm"),
> +		SUNXI_FUNCTION(0x4, "spdif"),		/* IN */
> +		SUNXI_FUNCTION(0x5, "spi1"),		/* CS0 */
> +		SUNXI_FUNCTION(0x6, "clk"),		/* FANOUT2 */
> +		SUNXI_FUNCTION(0x7, "ir"),		/* RX */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 12)),
> +	/* PC */
> +	SUNXI_PIN_VARIANT(SUNXI_PINCTRL_PIN(C, 0),
> +		PINCTRL_SUN20I_D1,
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "uart2"),		/* TX */
> +		SUNXI_FUNCTION(0x3, "i2c2"),		/* SCK */
> +		SUNXI_FUNCTION(0x4, "ledc"),
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 0)),
> +	SUNXI_PIN_VARIANT(SUNXI_PINCTRL_PIN(C, 1),
> +		PINCTRL_SUN20I_D1,
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "uart2"),		/* RX */
> +		SUNXI_FUNCTION(0x3, "i2c2"),		/* SDA */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 1)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 2),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "spi0"),		/* CLK */
> +		SUNXI_FUNCTION(0x3, "mmc2"),		/* CLK */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 2)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 3),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "spi0"),		/* CS0 */
> +		SUNXI_FUNCTION(0x3, "mmc2"),		/* CMD */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 3)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 4),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "spi0"),		/* MOSI */
> +		SUNXI_FUNCTION(0x3, "mmc2"),		/* D2 */
> +		SUNXI_FUNCTION(0x4, "boot"),		/* SEL0 */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 4)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 5),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "spi0"),		/* MISO */
> +		SUNXI_FUNCTION(0x3, "mmc2"),		/* D1 */
> +		SUNXI_FUNCTION(0x4, "boot"),		/* SEL1 */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 5)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 6),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "spi0"),		/* WP */
> +		SUNXI_FUNCTION(0x3, "mmc2"),		/* D0 */
> +		SUNXI_FUNCTION(0x4, "uart3"),		/* TX */
> +		SUNXI_FUNCTION(0x5, "i2c3"),		/* SCK */
> +		SUNXI_FUNCTION(0x6, "pll"),		/* DBG-CLK */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 6)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 7),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "spi0"),		/* HOLD */
> +		SUNXI_FUNCTION(0x3, "mmc2"),		/* D3 */
> +		SUNXI_FUNCTION(0x4, "uart3"),		/* RX */
> +		SUNXI_FUNCTION(0x5, "i2c3"),		/* SDA */
> +		SUNXI_FUNCTION(0x6, "tcon"),		/* TRIG0 */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 7)),
> +	/* PD */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 0),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd0"),		/* D2 */
> +		SUNXI_FUNCTION(0x3, "lvds0"),		/* V0P */
> +		SUNXI_FUNCTION(0x4, "dsi"),		/* D0P */
> +		SUNXI_FUNCTION(0x5, "i2c0"),		/* SCK */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 0)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 1),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd0"),		/* D3 */
> +		SUNXI_FUNCTION(0x3, "lvds0"),		/* V0N */
> +		SUNXI_FUNCTION(0x4, "dsi"),		/* D0N */
> +		SUNXI_FUNCTION(0x5, "uart2"),		/* TX */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 1)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 2),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd0"),		/* D4 */
> +		SUNXI_FUNCTION(0x3, "lvds0"),		/* V1P */
> +		SUNXI_FUNCTION(0x4, "dsi"),		/* D1P */
> +		SUNXI_FUNCTION(0x5, "uart2"),		/* RX */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 2)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 3),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd0"),		/* D5 */
> +		SUNXI_FUNCTION(0x3, "lvds0"),		/* V1N */
> +		SUNXI_FUNCTION(0x4, "dsi"),		/* D1N */
> +		SUNXI_FUNCTION(0x5, "uart2"),		/* RTS */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 3)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 4),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd0"),		/* D6 */
> +		SUNXI_FUNCTION(0x3, "lvds0"),		/* V2P */
> +		SUNXI_FUNCTION(0x4, "dsi"),		/* CKP */
> +		SUNXI_FUNCTION(0x5, "uart2"),		/* CTS */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 4)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 5),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd0"),		/* D7 */
> +		SUNXI_FUNCTION(0x3, "lvds0"),		/* V2N */
> +		SUNXI_FUNCTION(0x4, "dsi"),		/* CKN */
> +		SUNXI_FUNCTION(0x5, "uart5"),		/* TX */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 5)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 6),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd0"),		/* D10 */
> +		SUNXI_FUNCTION(0x3, "lvds0"),		/* CKP */
> +		SUNXI_FUNCTION(0x4, "dsi"),		/* D2P */
> +		SUNXI_FUNCTION(0x5, "uart5"),		/* RX */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 6)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 7),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd0"),		/* D11 */
> +		SUNXI_FUNCTION(0x3, "lvds0"),		/* CKN */
> +		SUNXI_FUNCTION(0x4, "dsi"),		/* D2N */
> +		SUNXI_FUNCTION(0x5, "uart4"),		/* TX */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 7)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 8),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd0"),		/* D12 */
> +		SUNXI_FUNCTION(0x3, "lvds0"),		/* V3P */
> +		SUNXI_FUNCTION(0x4, "dsi"),		/* D3P */
> +		SUNXI_FUNCTION(0x5, "uart4"),		/* RX */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 8)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 9),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd0"),		/* D13 */
> +		SUNXI_FUNCTION(0x3, "lvds0"),		/* V3N */
> +		SUNXI_FUNCTION(0x4, "dsi"),		/* D3N */
> +		SUNXI_FUNCTION(0x5, "pwm"),
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 9)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 10),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd0"),		/* D14 */
> +		SUNXI_FUNCTION(0x3, "lvds1"),		/* V0P */
> +		SUNXI_FUNCTION(0x4, "spi1"),		/* CS0 */
> +		SUNXI_FUNCTION(0x5, "uart3"),		/* TX */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 10)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 11),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd0"),		/* D15 */
> +		SUNXI_FUNCTION(0x3, "lvds1"),		/* V0N */
> +		SUNXI_FUNCTION(0x4, "spi1"),		/* CLK */
> +		SUNXI_FUNCTION(0x5, "uart3"),		/* RX */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 11)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 12),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd0"),		/* D18 */
> +		SUNXI_FUNCTION(0x3, "lvds1"),		/* V1P */
> +		SUNXI_FUNCTION(0x4, "spi1"),		/* MOSI */
> +		SUNXI_FUNCTION(0x5, "i2c0"),		/* SDA */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 12)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 13),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd0"),		/* D19 */
> +		SUNXI_FUNCTION(0x3, "lvds1"),		/* V1N */
> +		SUNXI_FUNCTION(0x4, "spi1"),		/* MISO */
> +		SUNXI_FUNCTION(0x5, "uart3"),		/* RTS */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 13)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 14),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd0"),		/* D20 */
> +		SUNXI_FUNCTION(0x3, "lvds1"),		/* V2P */
> +		SUNXI_FUNCTION(0x4, "spi1"),		/* HOLD */
> +		SUNXI_FUNCTION(0x5, "uart3"),		/* CTS */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 14)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 15),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd0"),		/* D21 */
> +		SUNXI_FUNCTION(0x3, "lvds1"),		/* V2N */
> +		SUNXI_FUNCTION(0x4, "spi1"),		/* WP */
> +		SUNXI_FUNCTION(0x5, "ir"),		/* RX */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 15)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 16),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd0"),		/* D22 */
> +		SUNXI_FUNCTION(0x3, "lvds1"),		/* CKP */
> +		SUNXI_FUNCTION(0x4, "dmic"),		/* DATA3 */
> +		SUNXI_FUNCTION(0x5, "pwm"),
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 16)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 17),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd0"),		/* D23 */
> +		SUNXI_FUNCTION(0x3, "lvds1"),		/* CKN */
> +		SUNXI_FUNCTION(0x4, "dmic"),		/* DATA2 */
> +		SUNXI_FUNCTION(0x5, "pwm"),
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 17)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 18),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd0"),		/* CLK */
> +		SUNXI_FUNCTION(0x3, "lvds1"),		/* V3P */
> +		SUNXI_FUNCTION(0x4, "dmic"),		/* DATA1 */
> +		SUNXI_FUNCTION(0x5, "pwm"),
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 18)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 19),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd0"),		/* DE */
> +		SUNXI_FUNCTION(0x3, "lvds1"),		/* V3N */
> +		SUNXI_FUNCTION(0x4, "dmic"),		/* DATA0 */
> +		SUNXI_FUNCTION(0x5, "pwm"),
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 19)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 20),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd0"),		/* HSYNC */
> +		SUNXI_FUNCTION(0x3, "i2c2"),		/* SCK */
> +		SUNXI_FUNCTION(0x4, "dmic"),		/* CLK */
> +		SUNXI_FUNCTION(0x5, "pwm"),
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 20)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 21),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd0"),		/* VSYNC */
> +		SUNXI_FUNCTION(0x3, "i2c2"),		/* SDA */
> +		SUNXI_FUNCTION(0x4, "uart1"),		/* TX */
> +		SUNXI_FUNCTION(0x5, "pwm"),
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 21)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 22),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "spdif"),		/* OUT */
> +		SUNXI_FUNCTION(0x3, "ir"),		/* RX */
> +		SUNXI_FUNCTION(0x4, "uart1"),		/* RX */
> +		SUNXI_FUNCTION(0x5, "pwm"),
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 22)),
> +	/* PE */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 0),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "ncsi0"),		/* HSYNC */
> +		SUNXI_FUNCTION(0x3, "uart2"),		/* RTS */
> +		SUNXI_FUNCTION(0x4, "i2c1"),		/* SCK */
> +		SUNXI_FUNCTION(0x5, "lcd0"),		/* HSYNC */
> +		SUNXI_FUNCTION(0x8, "emac"),		/* RXCTL/CRS_DV */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 0)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 1),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "ncsi0"),		/* VSYNC */
> +		SUNXI_FUNCTION(0x3, "uart2"),		/* CTS */
> +		SUNXI_FUNCTION(0x4, "i2c1"),		/* SDA */
> +		SUNXI_FUNCTION(0x5, "lcd0"),		/* VSYNC */
> +		SUNXI_FUNCTION(0x8, "emac"),		/* RXD0 */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 1)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 2),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "ncsi0"),		/* PCLK */
> +		SUNXI_FUNCTION(0x3, "uart2"),		/* TX */
> +		SUNXI_FUNCTION(0x4, "i2c0"),		/* SCK */
> +		SUNXI_FUNCTION(0x5, "clk"),		/* FANOUT0 */
> +		SUNXI_FUNCTION(0x6, "uart0"),		/* TX */
> +		SUNXI_FUNCTION(0x8, "emac"),		/* RXD1 */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 2)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 3),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "csi0"),		/* MCLK */

That function name should be "ncsi0".

> +		SUNXI_FUNCTION(0x3, "uart2"),		/* RX */
> +		SUNXI_FUNCTION(0x4, "i2c0"),		/* SDA */
> +		SUNXI_FUNCTION(0x5, "clk"),		/* FANOUT1 */
> +		SUNXI_FUNCTION(0x6, "uart0"),		/* RX */
> +		SUNXI_FUNCTION(0x8, "emac"),		/* TXCK */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 3)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 4),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "ncsi0"),		/* D0 */
> +		SUNXI_FUNCTION(0x3, "uart4"),		/* TX */
> +		SUNXI_FUNCTION(0x4, "i2c2"),		/* SCK */
> +		SUNXI_FUNCTION(0x5, "clk"),		/* FANOUT2 */
> +		SUNXI_FUNCTION(0x6, "d_jtag"),		/* MS */
> +		SUNXI_FUNCTION(0x7, "r_jtag"),		/* MS */
> +		SUNXI_FUNCTION(0x8, "emac"),		/* TXD0 */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 4)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 5),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "ncsi0"),		/* D1 */
> +		SUNXI_FUNCTION(0x3, "uart4"),		/* RX */
> +		SUNXI_FUNCTION(0x4, "i2c2"),		/* SDA */
> +		SUNXI_FUNCTION(0x5, "ledc"),
> +		SUNXI_FUNCTION(0x6, "d_jtag"),		/* D1 */
> +		SUNXI_FUNCTION(0x7, "r_jtag"),		/* D1 */

Those two pins should read "DI" in the comment (as in data in), I think.

> +		SUNXI_FUNCTION(0x8, "emac"),		/* TXD1 */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 5)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 6),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "ncsi0"),		/* D2 */
> +		SUNXI_FUNCTION(0x3, "uart5"),		/* TX */
> +		SUNXI_FUNCTION(0x4, "i2c3"),		/* SCK */
> +		SUNXI_FUNCTION(0x5, "spdif"),		/* IN */
> +		SUNXI_FUNCTION(0x6, "d_jtag"),		/* D0 */
> +		SUNXI_FUNCTION(0x7, "r_jtag"),		/* D0 */

And those two pins should be "DO" (as in data out).
Same for the other PortE JTAG signals below (but PortF is correct).


The rest looks correct to me. Very impressive!

Cheers,
Andre

> +		SUNXI_FUNCTION(0x8, "emac"),		/* TXCTL/TXEN */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 6)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 7),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "ncsi0"),		/* D3 */
> +		SUNXI_FUNCTION(0x3, "uart5"),		/* RX */
> +		SUNXI_FUNCTION(0x4, "i2c3"),		/* SDA */
> +		SUNXI_FUNCTION(0x5, "spdif"),		/* OUT */
> +		SUNXI_FUNCTION(0x6, "d_jtag"),		/* CK */
> +		SUNXI_FUNCTION(0x7, "r_jtag"),		/* CK */
> +		SUNXI_FUNCTION(0x8, "emac"),		/* CK */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 7)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 8),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "ncsi0"),		/* D4 */
> +		SUNXI_FUNCTION(0x3, "uart1"),		/* RTS */
> +		SUNXI_FUNCTION(0x4, "pwm"),
> +		SUNXI_FUNCTION(0x5, "uart3"),		/* TX */
> +		SUNXI_FUNCTION(0x6, "jtag"),		/* MS */
> +		SUNXI_FUNCTION(0x8, "emac"),		/* MDC */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 8)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 9),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "ncsi0"),		/* D5 */
> +		SUNXI_FUNCTION(0x3, "uart1"),		/* CTS */
> +		SUNXI_FUNCTION(0x4, "pwm"),
> +		SUNXI_FUNCTION(0x5, "uart3"),		/* RX */
> +		SUNXI_FUNCTION(0x6, "jtag"),		/* D1 */
> +		SUNXI_FUNCTION(0x8, "emac"),		/* MDIO */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 9)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 10),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "ncsi0"),		/* D6 */
> +		SUNXI_FUNCTION(0x3, "uart1"),		/* TX */
> +		SUNXI_FUNCTION(0x4, "pwm"),
> +		SUNXI_FUNCTION(0x5, "ir"),		/* RX */
> +		SUNXI_FUNCTION(0x6, "jtag"),		/* D0 */
> +		SUNXI_FUNCTION(0x8, "emac"),		/* EPHY-25M */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 10)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 11),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "ncsi0"),		/* D7 */
> +		SUNXI_FUNCTION(0x3, "uart1"),		/* RX */
> +		SUNXI_FUNCTION(0x4, "i2s0_dout"),	/* DOUT3 */
> +		SUNXI_FUNCTION(0x5, "i2s0_din"),	/* DIN3 */
> +		SUNXI_FUNCTION(0x6, "jtag"),		/* CK */
> +		SUNXI_FUNCTION(0x8, "emac"),		/* TXD2 */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 11)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 12),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "i2c2"),		/* SCK */
> +		SUNXI_FUNCTION(0x3, "ncsi0"),		/* FIELD */
> +		SUNXI_FUNCTION(0x4, "i2s0_dout"),	/* DOUT2 */
> +		SUNXI_FUNCTION(0x5, "i2s0_din"),	/* DIN2 */
> +		SUNXI_FUNCTION(0x8, "emac"),		/* TXD3 */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 12)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 13),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "i2c2"),		/* SDA */
> +		SUNXI_FUNCTION(0x3, "pwm"),
> +		SUNXI_FUNCTION(0x4, "i2s0_dout"),	/* DOUT0 */
> +		SUNXI_FUNCTION(0x5, "i2s0_din"),	/* DIN1 */
> +		SUNXI_FUNCTION(0x6, "dmic"),		/* DATA3 */
> +		SUNXI_FUNCTION(0x8, "emac"),		/* RXD2 */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 13)),
> +	SUNXI_PIN_VARIANT(SUNXI_PINCTRL_PIN(E, 14),
> +		PINCTRL_SUN20I_D1,
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "i2c1"),		/* SCK */
> +		SUNXI_FUNCTION(0x3, "d_jtag"),		/* MS */
> +		SUNXI_FUNCTION(0x4, "i2s0_dout"),	/* DOUT1 */
> +		SUNXI_FUNCTION(0x5, "i2s0_din"),	/* DIN0 */
> +		SUNXI_FUNCTION(0x6, "dmic"),		/* DATA2 */
> +		SUNXI_FUNCTION(0x8, "emac"),		/* RXD3 */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 14)),
> +	SUNXI_PIN_VARIANT(SUNXI_PINCTRL_PIN(E, 15),
> +		PINCTRL_SUN20I_D1,
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "i2c1"),		/* SDA */
> +		SUNXI_FUNCTION(0x3, "d_jtag"),		/* D1 */
> +		SUNXI_FUNCTION(0x4, "pwm"),
> +		SUNXI_FUNCTION(0x5, "i2s0"),		/* LRCK */
> +		SUNXI_FUNCTION(0x6, "dmic"),		/* DATA1 */
> +		SUNXI_FUNCTION(0x8, "emac"),		/* RXCK */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 15)),
> +	SUNXI_PIN_VARIANT(SUNXI_PINCTRL_PIN(E, 16),
> +		PINCTRL_SUN20I_D1,
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "i2c3"),		/* SCK */
> +		SUNXI_FUNCTION(0x3, "d_jtag"),		/* D0 */
> +		SUNXI_FUNCTION(0x4, "pwm"),
> +		SUNXI_FUNCTION(0x5, "i2s0"),		/* BCLK */
> +		SUNXI_FUNCTION(0x6, "dmic"),		/* DATA0 */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 16)),
> +	SUNXI_PIN_VARIANT(SUNXI_PINCTRL_PIN(E, 17),
> +		PINCTRL_SUN20I_D1,
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "i2c3"),		/* SDA */
> +		SUNXI_FUNCTION(0x3, "d_jtag"),		/* CK */
> +		SUNXI_FUNCTION(0x4, "ir"),		/* TX */
> +		SUNXI_FUNCTION(0x5, "i2s0"),		/* MCLK */
> +		SUNXI_FUNCTION(0x6, "dmic"),		/* CLK */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 17)),
> +	/* PF */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 0),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "mmc0"),		/* D1 */
> +		SUNXI_FUNCTION(0x3, "jtag"),		/* MS */
> +		SUNXI_FUNCTION(0x4, "r_jtag"),		/* MS */
> +		SUNXI_FUNCTION(0x5, "i2s2_dout"),	/* DOUT1 */
> +		SUNXI_FUNCTION(0x6, "i2s2_din"),	/* DIN0 */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 0)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 1),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "mmc0"),		/* D0 */
> +		SUNXI_FUNCTION(0x3, "jtag"),		/* DI */
> +		SUNXI_FUNCTION(0x4, "r_jtag"),		/* DI */
> +		SUNXI_FUNCTION(0x5, "i2s2_dout"),	/* DOUT0 */
> +		SUNXI_FUNCTION(0x6, "i2s2_din"),	/* DIN1 */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 1)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 2),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "mmc0"),		/* CLK */
> +		SUNXI_FUNCTION(0x3, "uart0"),		/* TX */
> +		SUNXI_FUNCTION(0x4, "i2c0"),		/* SCK */
> +		SUNXI_FUNCTION(0x5, "ledc"),
> +		SUNXI_FUNCTION(0x6, "spdif"),		/* IN */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 2)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 3),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "mmc0"),		/* CMD */
> +		SUNXI_FUNCTION(0x3, "jtag"),		/* DO */
> +		SUNXI_FUNCTION(0x4, "r_jtag"),		/* DO */
> +		SUNXI_FUNCTION(0x5, "i2s2"),		/* BCLK */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 3)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 4),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "mmc0"),		/* D3 */
> +		SUNXI_FUNCTION(0x3, "uart0"),		/* RX */
> +		SUNXI_FUNCTION(0x4, "i2c0"),		/* SDA */
> +		SUNXI_FUNCTION(0x5, "pwm"),
> +		SUNXI_FUNCTION(0x6, "ir"),		/* TX */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 4)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 5),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "mmc0"),		/* D2 */
> +		SUNXI_FUNCTION(0x3, "jtag"),		/* CK */
> +		SUNXI_FUNCTION(0x4, "r_jtag"),		/* CK */
> +		SUNXI_FUNCTION(0x5, "i2s2"),		/* LRCK */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 5)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 6),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x3, "spdif"),		/* OUT */
> +		SUNXI_FUNCTION(0x4, "ir"),		/* RX */
> +		SUNXI_FUNCTION(0x5, "i2s2"),		/* MCLK */
> +		SUNXI_FUNCTION(0x6, "pwm"),
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 6)),
> +	/* PG */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 0),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "mmc1"),		/* CLK */
> +		SUNXI_FUNCTION(0x3, "uart3"),		/* TX */
> +		SUNXI_FUNCTION(0x4, "emac"),		/* RXCTRL/CRS_DV */
> +		SUNXI_FUNCTION(0x5, "pwm"),
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 0)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 1),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "mmc1"),		/* CMD */
> +		SUNXI_FUNCTION(0x3, "uart3"),		/* RX */
> +		SUNXI_FUNCTION(0x4, "emac"),		/* RXD0 */
> +		SUNXI_FUNCTION(0x5, "pwm"),
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 1)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 2),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "mmc1"),		/* D0 */
> +		SUNXI_FUNCTION(0x3, "uart3"),		/* RTS */
> +		SUNXI_FUNCTION(0x4, "emac"),		/* RXD1 */
> +		SUNXI_FUNCTION(0x5, "uart4"),		/* TX */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 2)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 3),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "mmc1"),		/* D1 */
> +		SUNXI_FUNCTION(0x3, "uart3"),		/* CTS */
> +		SUNXI_FUNCTION(0x4, "emac"),		/* TXCK */
> +		SUNXI_FUNCTION(0x5, "uart4"),		/* RX */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 3)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 4),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "mmc1"),		/* D2 */
> +		SUNXI_FUNCTION(0x3, "uart5"),		/* TX */
> +		SUNXI_FUNCTION(0x4, "emac"),		/* TXD0 */
> +		SUNXI_FUNCTION(0x5, "pwm"),
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 4)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 5),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "mmc1"),		/* D3 */
> +		SUNXI_FUNCTION(0x3, "uart5"),		/* RX */
> +		SUNXI_FUNCTION(0x4, "emac"),		/* TXD1 */
> +		SUNXI_FUNCTION(0x5, "pwm"),
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 5)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 6),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "uart1"),		/* TX */
> +		SUNXI_FUNCTION(0x3, "i2c2"),		/* SCK */
> +		SUNXI_FUNCTION(0x4, "emac"),		/* TXD2 */
> +		SUNXI_FUNCTION(0x5, "pwm"),
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 6)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 7),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "uart1"),		/* RX */
> +		SUNXI_FUNCTION(0x3, "i2c2"),		/* SDA */
> +		SUNXI_FUNCTION(0x4, "emac"),		/* TXD3 */
> +		SUNXI_FUNCTION(0x5, "spdif"),		/* IN */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 7)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 8),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "uart1"),		/* RTS */
> +		SUNXI_FUNCTION(0x3, "i2c1"),		/* SCK */
> +		SUNXI_FUNCTION(0x4, "emac"),		/* RXD2 */
> +		SUNXI_FUNCTION(0x5, "uart3"),		/* TX */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 8)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 9),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "uart1"),		/* CTS */
> +		SUNXI_FUNCTION(0x3, "i2c1"),		/* SDA */
> +		SUNXI_FUNCTION(0x4, "emac"),		/* RXD3 */
> +		SUNXI_FUNCTION(0x5, "uart3"),		/* RX */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 9)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 10),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "pwm"),
> +		SUNXI_FUNCTION(0x3, "i2c3"),		/* SCK */
> +		SUNXI_FUNCTION(0x4, "emac"),		/* RXCK */
> +		SUNXI_FUNCTION(0x5, "clk"),		/* FANOUT0 */
> +		SUNXI_FUNCTION(0x6, "ir"),		/* RX */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 10)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 11),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "i2s1"),		/* MCLK */
> +		SUNXI_FUNCTION(0x3, "i2c3"),		/* SDA */
> +		SUNXI_FUNCTION(0x4, "emac"),		/* EPHY-25M */
> +		SUNXI_FUNCTION(0x5, "clk"),		/* FANOUT1 */
> +		SUNXI_FUNCTION(0x6, "tcon"),		/* TRIG0 */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 11)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 12),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "i2s1"),		/* LRCK */
> +		SUNXI_FUNCTION(0x3, "i2c0"),		/* SCK */
> +		SUNXI_FUNCTION(0x4, "emac"),		/* TXCTL/TXEN */
> +		SUNXI_FUNCTION(0x5, "clk"),		/* FANOUT2 */
> +		SUNXI_FUNCTION(0x6, "pwm"),
> +		SUNXI_FUNCTION(0x7, "uart1"),		/* TX */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 12)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 13),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "i2s1"),		/* BCLK */
> +		SUNXI_FUNCTION(0x3, "i2c0"),		/* SDA */
> +		SUNXI_FUNCTION(0x4, "emac"),		/* CLKIN/RXER */
> +		SUNXI_FUNCTION(0x5, "pwm"),
> +		SUNXI_FUNCTION(0x6, "ledc"),
> +		SUNXI_FUNCTION(0x7, "uart1"),		/* RX */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 13)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 14),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "i2s1_din"),	/* DIN0 */
> +		SUNXI_FUNCTION(0x3, "i2c2"),		/* SCK */
> +		SUNXI_FUNCTION(0x4, "emac"),		/* MDC */
> +		SUNXI_FUNCTION(0x5, "i2s1_dout"),	/* DOUT1 */
> +		SUNXI_FUNCTION(0x6, "spi0"),		/* WP */
> +		SUNXI_FUNCTION(0x7, "uart1"),		/* RTS */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 14)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 15),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "i2s1_dout"),	/* DOUT0 */
> +		SUNXI_FUNCTION(0x3, "i2c2"),		/* SDA */
> +		SUNXI_FUNCTION(0x4, "emac"),		/* MDIO */
> +		SUNXI_FUNCTION(0x5, "i2s1_din"),	/* DIN1 */
> +		SUNXI_FUNCTION(0x6, "spi0"),		/* HOLD */
> +		SUNXI_FUNCTION(0x7, "uart1"),		/* CTS */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 15)),
> +	SUNXI_PIN_VARIANT(SUNXI_PINCTRL_PIN(G, 16),
> +		PINCTRL_SUN20I_D1,
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "ir"),		/* RX */
> +		SUNXI_FUNCTION(0x3, "tcon"),		/* TRIG0 */
> +		SUNXI_FUNCTION(0x4, "pwm"),
> +		SUNXI_FUNCTION(0x5, "clk"),		/* FANOUT2 */
> +		SUNXI_FUNCTION(0x6, "spdif"),		/* IN */
> +		SUNXI_FUNCTION(0x7, "ledc"),
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 16)),
> +	SUNXI_PIN_VARIANT(SUNXI_PINCTRL_PIN(G, 17),
> +		PINCTRL_SUN20I_D1,
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "uart2"),		/* TX */
> +		SUNXI_FUNCTION(0x3, "i2c3"),		/* SCK */
> +		SUNXI_FUNCTION(0x4, "pwm"),
> +		SUNXI_FUNCTION(0x5, "clk"),		/* FANOUT0 */
> +		SUNXI_FUNCTION(0x6, "ir"),		/* TX */
> +		SUNXI_FUNCTION(0x7, "uart0"),		/* TX */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 17)),
> +	SUNXI_PIN_VARIANT(SUNXI_PINCTRL_PIN(G, 18),
> +		PINCTRL_SUN20I_D1,
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "uart2"),		/* RX */
> +		SUNXI_FUNCTION(0x3, "i2c3"),		/* SDA */
> +		SUNXI_FUNCTION(0x4, "pwm"),
> +		SUNXI_FUNCTION(0x5, "clk"),		/* FANOUT1 */
> +		SUNXI_FUNCTION(0x6, "spdif"),		/* OUT */
> +		SUNXI_FUNCTION(0x7, "uart0"),		/* RX */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 18)),
> +};
> +
> +static const unsigned int d1_irq_bank_map[] = { 1, 2, 3, 4, 5, 6 };
> +
> +static const struct sunxi_pinctrl_desc d1_pinctrl_data = {
> +	.pins			= d1_pins,
> +	.npins			= ARRAY_SIZE(d1_pins),
> +	.irq_banks		= ARRAY_SIZE(d1_irq_bank_map),
> +	.irq_bank_map		= d1_irq_bank_map,
> +	.io_bias_cfg_variant	= BIAS_VOLTAGE_PIO_POW_MODE_CTL,
> +};
> +
> +static int d1_pinctrl_probe(struct platform_device *pdev)
> +{
> +	unsigned long variant = (unsigned long)of_device_get_match_data(&pdev->dev);
> +
> +	return sunxi_pinctrl_init_with_variant(pdev, &d1_pinctrl_data, variant);
> +}
> +
> +static const struct of_device_id d1_pinctrl_match[] = {
> +	{
> +		.compatible = "allwinner,sun20i-d1-pinctrl",
> +		.data = (void *)PINCTRL_SUN20I_D1
> +	},
> +	{
> +		.compatible = "allwinner,sun20i-d1s-pinctrl",
> +		.data = (void *)PINCTRL_SUN20I_D1S
> +	},
> +	{}
> +};
> +
> +static struct platform_driver d1_pinctrl_driver = {
> +	.probe	= d1_pinctrl_probe,
> +	.driver	= {
> +		.name		= "sun20i-d1-pinctrl",
> +		.of_match_table	= d1_pinctrl_match,
> +	},
> +};
> +builtin_platform_driver(d1_pinctrl_driver);
> diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> index ec7daaa5666b..350044d4c1b5 100644
> --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> @@ -1297,11 +1297,11 @@ static int sunxi_pinctrl_build_state(struct platform_device *pdev)
>  
>  	/*
>  	 * Find an upper bound for the maximum number of functions: in
> -	 * the worst case we have gpio_in, gpio_out, irq and up to four
> +	 * the worst case we have gpio_in, gpio_out, irq and up to seven
>  	 * special functions per pin, plus one entry for the sentinel.
>  	 * We'll reallocate that later anyway.
>  	 */
> -	pctl->functions = kcalloc(4 * pctl->ngroups + 4,
> +	pctl->functions = kcalloc(7 * pctl->ngroups + 4,
>  				  sizeof(*pctl->functions),
>  				  GFP_KERNEL);
>  	if (!pctl->functions)
> @@ -1494,9 +1494,15 @@ int sunxi_pinctrl_init_with_variant(struct platform_device *pdev,
>  	pctl->dev = &pdev->dev;
>  	pctl->desc = desc;
>  	pctl->variant = variant;
> -	pctl->bank_mem_size = BANK_MEM_SIZE;
> -	pctl->pull_regs_offset = PULL_REGS_OFFSET;
> -	pctl->dlevel_field_width = DLEVEL_FIELD_WIDTH;
> +	if (pctl->variant >= PINCTRL_SUN20I_D1) {
> +		pctl->bank_mem_size = D1_BANK_MEM_SIZE;
> +		pctl->pull_regs_offset = D1_PULL_REGS_OFFSET;
> +		pctl->dlevel_field_width = D1_DLEVEL_FIELD_WIDTH;
> +	} else {
> +		pctl->bank_mem_size = BANK_MEM_SIZE;
> +		pctl->pull_regs_offset = PULL_REGS_OFFSET;
> +		pctl->dlevel_field_width = DLEVEL_FIELD_WIDTH;
> +	}
>  
>  	pctl->irq_array = devm_kcalloc(&pdev->dev,
>  				       IRQ_PER_BANK * pctl->desc->irq_banks,
> diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.h b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
> index c705828add73..f0f48941bc30 100644
> --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.h
> +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
> @@ -44,6 +44,10 @@
>  #define PULL_REGS_OFFSET	0x1c
>  #define PULL_FIELD_WIDTH	2
>  
> +#define D1_BANK_MEM_SIZE	0x30
> +#define D1_DLEVEL_FIELD_WIDTH	4
> +#define D1_PULL_REGS_OFFSET	0x24
> +
>  #define PINS_PER_BANK		32
>  
>  #define IRQ_PER_BANK		32
> @@ -88,6 +92,9 @@
>  #define PINCTRL_SUN8I_R40	BIT(8)
>  #define PINCTRL_SUN8I_V3	BIT(9)
>  #define PINCTRL_SUN8I_V3S	BIT(10)
> +/* Variants below here have an updated register layout. */
> +#define PINCTRL_SUN20I_D1	BIT(11)
> +#define PINCTRL_SUN20I_D1S	BIT(12)
>  
>  #define PIO_POW_MOD_SEL_REG	0x340
>  #define PIO_POW_MOD_CTL_REG	0x344


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

* Re: [PATCH 6/6] pinctrl: sunxi: Add driver for Allwinner D1/D1s
@ 2022-07-02 14:47     ` Andre Przywara
  0 siblings, 0 replies; 56+ messages in thread
From: Andre Przywara @ 2022-07-02 14:47 UTC (permalink / raw)
  To: Samuel Holland
  Cc: Chen-Yu Tsai, Jernej Skrabec, Linus Walleij, Krzysztof Kozlowski,
	Maxime Ripard, Ondrej Jirman, Rob Herring, devicetree,
	linux-arm-kernel, linux-gpio, linux-kernel, linux-sunxi,
	Heiko Stuebner

On Sat, 25 Jun 2022 21:11:47 -0500
Samuel Holland <samuel@sholland.org> wrote:

Hi Samuel,

> These SoCs contain a pinctrl with a new register layout. Use the variant
> parameter to set the right register offsets. This pinctrl also increases
> the number of functions per pin from 8 to 16, taking advantage of all 4
> bits in the mux config field (so far, only functions 0-8 and 14-15 are
> used). This increases the maximum possible number of functions.
> 
> D1s is a low pin count version of the D1 SoC, with some pins omitted.
> The remaining pins have the same function assignments as D1.

So do we actually need this extra variant, if there are no conflicts?
The D1s seems to be a simple subset of the D1. I think we followed the
same approach for the H616 already, where there are more pins in the
pinctrl driver than the manual describes, and which are used in other
package variants, like the T507.
In case of the H616, those pins are there, you can program them (which
is not the case for not implemented pins otherwise), they are just not
connected to the package.
I would expect a DT to never reference them, and even if, it doesn't do
any harm other than just not working.

For the table below: I checked every pin against the D1 manual (yes,
that took an hour), and found only one small issue and some nits in
PortE, see inline.

> Signed-off-by: Samuel Holland <samuel@sholland.org>
> ---
> 
>  drivers/pinctrl/sunxi/Kconfig             |   5 +
>  drivers/pinctrl/sunxi/Makefile            |   1 +
>  drivers/pinctrl/sunxi/pinctrl-sun20i-d1.c | 860 ++++++++++++++++++++++
>  drivers/pinctrl/sunxi/pinctrl-sunxi.c     |  16 +-
>  drivers/pinctrl/sunxi/pinctrl-sunxi.h     |   7 +
>  5 files changed, 884 insertions(+), 5 deletions(-)
>  create mode 100644 drivers/pinctrl/sunxi/pinctrl-sun20i-d1.c
> 
> diff --git a/drivers/pinctrl/sunxi/Kconfig b/drivers/pinctrl/sunxi/Kconfig
> index 33751a6a0757..a6ac1c1f2585 100644
> --- a/drivers/pinctrl/sunxi/Kconfig
> +++ b/drivers/pinctrl/sunxi/Kconfig
> @@ -84,6 +84,11 @@ config PINCTRL_SUN9I_A80_R
>  	depends on RESET_CONTROLLER
>  	select PINCTRL_SUNXI
>  
> +config PINCTRL_SUN20I_D1
> +	bool "Support for the Allwinner D1 PIO"
> +	default RISCV && ARCH_SUNXI
> +	select PINCTRL_SUNXI
> +
>  config PINCTRL_SUN50I_A64
>  	bool "Support for the Allwinner A64 PIO"
>  	default ARM64 && ARCH_SUNXI
> diff --git a/drivers/pinctrl/sunxi/Makefile b/drivers/pinctrl/sunxi/Makefile
> index d3440c42b9d6..2ff5a55927ad 100644
> --- a/drivers/pinctrl/sunxi/Makefile
> +++ b/drivers/pinctrl/sunxi/Makefile
> @@ -20,6 +20,7 @@ obj-$(CONFIG_PINCTRL_SUN8I_A83T_R)	+= pinctrl-sun8i-a83t-r.o
>  obj-$(CONFIG_PINCTRL_SUN8I_H3)		+= pinctrl-sun8i-h3.o
>  obj-$(CONFIG_PINCTRL_SUN8I_H3_R)	+= pinctrl-sun8i-h3-r.o
>  obj-$(CONFIG_PINCTRL_SUN8I_V3S)		+= pinctrl-sun8i-v3s.o
> +obj-$(CONFIG_PINCTRL_SUN20I_D1)		+= pinctrl-sun20i-d1.o
>  obj-$(CONFIG_PINCTRL_SUN50I_H5)		+= pinctrl-sun50i-h5.o
>  obj-$(CONFIG_PINCTRL_SUN50I_H6)		+= pinctrl-sun50i-h6.o
>  obj-$(CONFIG_PINCTRL_SUN50I_H6_R)	+= pinctrl-sun50i-h6-r.o
> diff --git a/drivers/pinctrl/sunxi/pinctrl-sun20i-d1.c b/drivers/pinctrl/sunxi/pinctrl-sun20i-d1.c
> new file mode 100644
> index 000000000000..7247c1f1d92c
> --- /dev/null
> +++ b/drivers/pinctrl/sunxi/pinctrl-sun20i-d1.c
> @@ -0,0 +1,860 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Allwinner D1 SoC pinctrl driver.
> + *
> + * Copyright (c) 2020 wuyan@allwinnertech.com
> + * Copyright (c) 2021-2022 Samuel Holland <samuel@sholland.org>
> + */
> +
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/of.h>
> +#include <linux/of_device.h>
> +#include <linux/pinctrl/pinctrl.h>
> +
> +#include "pinctrl-sunxi.h"
> +
> +static const struct sunxi_desc_pin d1_pins[] = {
> +	/* PB */
> +	SUNXI_PIN_VARIANT(SUNXI_PINCTRL_PIN(B, 0),
> +		PINCTRL_SUN20I_D1,
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "pwm"),

The manual mentions the PWM channel number in the pin name, and it
seems like in other pinctrl drivers we use the number either in the
function name, or at least in the comment.
Shall we do one of them here as well?
And the mux numbers for pwm are all over the place, so lets hope we
never need pwm in U-Boot ;-)

> +		SUNXI_FUNCTION(0x3, "ir"),		/* TX */
> +		SUNXI_FUNCTION(0x4, "i2c2"),		/* SCK */
> +		SUNXI_FUNCTION(0x5, "spi1"),		/* WP */
> +		SUNXI_FUNCTION(0x6, "uart0"),		/* TX */
> +		SUNXI_FUNCTION(0x7, "uart2"),		/* TX */
> +		SUNXI_FUNCTION(0x8, "spdif"),		/* OUT */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 0)),
> +	SUNXI_PIN_VARIANT(SUNXI_PINCTRL_PIN(B, 1),
> +		PINCTRL_SUN20I_D1,
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "pwm"),
> +		SUNXI_FUNCTION(0x3, "i2s2_dout"),	/* DOUT3 */
> +		SUNXI_FUNCTION(0x4, "i2c2"),		/* SDA */
> +		SUNXI_FUNCTION(0x5, "i2s2_din"),	/* DIN3 */
> +		SUNXI_FUNCTION(0x6, "uart0"),		/* RX */
> +		SUNXI_FUNCTION(0x7, "uart2"),		/* RX */
> +		SUNXI_FUNCTION(0x8, "ir"),		/* RX */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 1)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 2),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd0"),		/* D0 */
> +		SUNXI_FUNCTION(0x3, "i2s2_dout"),	/* DOUT2 */
> +		SUNXI_FUNCTION(0x4, "i2c0"),		/* SDA */
> +		SUNXI_FUNCTION(0x5, "i2s2_din"),	/* DIN2 */
> +		SUNXI_FUNCTION(0x6, "lcd0"),		/* D18 */
> +		SUNXI_FUNCTION(0x7, "uart4"),		/* TX */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 2)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 3),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd0"),		/* D1 */
> +		SUNXI_FUNCTION(0x3, "i2s2_dout"),	/* DOUT1 */
> +		SUNXI_FUNCTION(0x4, "i2c0"),		/* SCK */
> +		SUNXI_FUNCTION(0x5, "i2s2_din"),	/* DIN0 */
> +		SUNXI_FUNCTION(0x6, "lcd0"),		/* D19 */
> +		SUNXI_FUNCTION(0x7, "uart4"),		/* RX */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 3)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 4),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd0"),		/* D8 */
> +		SUNXI_FUNCTION(0x3, "i2s2_dout"),	/* DOUT0 */
> +		SUNXI_FUNCTION(0x4, "i2c1"),		/* SCK */
> +		SUNXI_FUNCTION(0x5, "i2s2_din"),	/* DIN1 */
> +		SUNXI_FUNCTION(0x6, "lcd0"),		/* D20 */
> +		SUNXI_FUNCTION(0x7, "uart5"),		/* TX */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 4)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 5),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd0"),		/* D9 */
> +		SUNXI_FUNCTION(0x3, "i2s2"),		/* BCLK */
> +		SUNXI_FUNCTION(0x4, "i2c1"),		/* SDA */
> +		SUNXI_FUNCTION(0x5, "pwm"),
> +		SUNXI_FUNCTION(0x6, "lcd0"),		/* D21 */
> +		SUNXI_FUNCTION(0x7, "uart5"),		/* RX */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 5)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 6),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd0"),		/* D16 */
> +		SUNXI_FUNCTION(0x3, "i2s2"),		/* LRCK */
> +		SUNXI_FUNCTION(0x4, "i2c3"),		/* SCK */
> +		SUNXI_FUNCTION(0x5, "pwm"),
> +		SUNXI_FUNCTION(0x6, "lcd0"),		/* D22 */
> +		SUNXI_FUNCTION(0x7, "uart3"),		/* TX */
> +		SUNXI_FUNCTION(0x8, "bist0"),		/* BIST_RESULT0 */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 6)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 7),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd0"),		/* D17 */
> +		SUNXI_FUNCTION(0x3, "i2s2"),		/* MCLK */
> +		SUNXI_FUNCTION(0x4, "i2c3"),		/* SDA */
> +		SUNXI_FUNCTION(0x5, "ir"),		/* RX */
> +		SUNXI_FUNCTION(0x6, "lcd0"),		/* D23 */
> +		SUNXI_FUNCTION(0x7, "uart3"),		/* RX */
> +		SUNXI_FUNCTION(0x8, "bist1"),		/* BIST_RESULT1 */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 7)),
> +	SUNXI_PIN_VARIANT(SUNXI_PINCTRL_PIN(B, 8),
> +		PINCTRL_SUN20I_D1,
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "dmic"),		/* DATA3 */
> +		SUNXI_FUNCTION(0x3, "pwm"),
> +		SUNXI_FUNCTION(0x4, "i2c2"),		/* SCK */
> +		SUNXI_FUNCTION(0x5, "spi1"),		/* HOLD */
> +		SUNXI_FUNCTION(0x6, "uart0"),		/* TX */
> +		SUNXI_FUNCTION(0x7, "uart1"),		/* TX */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 8)),
> +	SUNXI_PIN_VARIANT(SUNXI_PINCTRL_PIN(B, 9),
> +		PINCTRL_SUN20I_D1,
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "dmic"),		/* DATA2 */
> +		SUNXI_FUNCTION(0x3, "pwm"),
> +		SUNXI_FUNCTION(0x4, "i2c2"),		/* SDA */
> +		SUNXI_FUNCTION(0x5, "spi1"),		/* MISO */
> +		SUNXI_FUNCTION(0x6, "uart0"),		/* RX */
> +		SUNXI_FUNCTION(0x7, "uart1"),		/* RX */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 9)),
> +	SUNXI_PIN_VARIANT(SUNXI_PINCTRL_PIN(B, 10),
> +		PINCTRL_SUN20I_D1,
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "dmic"),		/* DATA1 */
> +		SUNXI_FUNCTION(0x3, "pwm"),
> +		SUNXI_FUNCTION(0x4, "i2c0"),		/* SCK */
> +		SUNXI_FUNCTION(0x5, "spi1"),		/* MOSI */
> +		SUNXI_FUNCTION(0x6, "clk"),		/* FANOUT0 */
> +		SUNXI_FUNCTION(0x7, "uart1"),		/* RTS */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 10)),
> +	SUNXI_PIN_VARIANT(SUNXI_PINCTRL_PIN(B, 11),
> +		PINCTRL_SUN20I_D1,
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "dmic"),		/* DATA0 */
> +		SUNXI_FUNCTION(0x3, "pwm"),
> +		SUNXI_FUNCTION(0x4, "i2c0"),		/* SDA */
> +		SUNXI_FUNCTION(0x5, "spi1"),		/* CLK */
> +		SUNXI_FUNCTION(0x6, "clk"),		/* FANOUT1 */
> +		SUNXI_FUNCTION(0x7, "uart1"),		/* CTS */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 11)),
> +	SUNXI_PIN_VARIANT(SUNXI_PINCTRL_PIN(B, 12),
> +		PINCTRL_SUN20I_D1,
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "dmic"),		/* CLK */
> +		SUNXI_FUNCTION(0x3, "pwm"),
> +		SUNXI_FUNCTION(0x4, "spdif"),		/* IN */
> +		SUNXI_FUNCTION(0x5, "spi1"),		/* CS0 */
> +		SUNXI_FUNCTION(0x6, "clk"),		/* FANOUT2 */
> +		SUNXI_FUNCTION(0x7, "ir"),		/* RX */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 12)),
> +	/* PC */
> +	SUNXI_PIN_VARIANT(SUNXI_PINCTRL_PIN(C, 0),
> +		PINCTRL_SUN20I_D1,
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "uart2"),		/* TX */
> +		SUNXI_FUNCTION(0x3, "i2c2"),		/* SCK */
> +		SUNXI_FUNCTION(0x4, "ledc"),
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 0)),
> +	SUNXI_PIN_VARIANT(SUNXI_PINCTRL_PIN(C, 1),
> +		PINCTRL_SUN20I_D1,
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "uart2"),		/* RX */
> +		SUNXI_FUNCTION(0x3, "i2c2"),		/* SDA */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 1)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 2),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "spi0"),		/* CLK */
> +		SUNXI_FUNCTION(0x3, "mmc2"),		/* CLK */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 2)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 3),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "spi0"),		/* CS0 */
> +		SUNXI_FUNCTION(0x3, "mmc2"),		/* CMD */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 3)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 4),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "spi0"),		/* MOSI */
> +		SUNXI_FUNCTION(0x3, "mmc2"),		/* D2 */
> +		SUNXI_FUNCTION(0x4, "boot"),		/* SEL0 */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 4)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 5),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "spi0"),		/* MISO */
> +		SUNXI_FUNCTION(0x3, "mmc2"),		/* D1 */
> +		SUNXI_FUNCTION(0x4, "boot"),		/* SEL1 */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 5)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 6),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "spi0"),		/* WP */
> +		SUNXI_FUNCTION(0x3, "mmc2"),		/* D0 */
> +		SUNXI_FUNCTION(0x4, "uart3"),		/* TX */
> +		SUNXI_FUNCTION(0x5, "i2c3"),		/* SCK */
> +		SUNXI_FUNCTION(0x6, "pll"),		/* DBG-CLK */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 6)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 7),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "spi0"),		/* HOLD */
> +		SUNXI_FUNCTION(0x3, "mmc2"),		/* D3 */
> +		SUNXI_FUNCTION(0x4, "uart3"),		/* RX */
> +		SUNXI_FUNCTION(0x5, "i2c3"),		/* SDA */
> +		SUNXI_FUNCTION(0x6, "tcon"),		/* TRIG0 */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 7)),
> +	/* PD */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 0),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd0"),		/* D2 */
> +		SUNXI_FUNCTION(0x3, "lvds0"),		/* V0P */
> +		SUNXI_FUNCTION(0x4, "dsi"),		/* D0P */
> +		SUNXI_FUNCTION(0x5, "i2c0"),		/* SCK */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 0)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 1),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd0"),		/* D3 */
> +		SUNXI_FUNCTION(0x3, "lvds0"),		/* V0N */
> +		SUNXI_FUNCTION(0x4, "dsi"),		/* D0N */
> +		SUNXI_FUNCTION(0x5, "uart2"),		/* TX */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 1)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 2),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd0"),		/* D4 */
> +		SUNXI_FUNCTION(0x3, "lvds0"),		/* V1P */
> +		SUNXI_FUNCTION(0x4, "dsi"),		/* D1P */
> +		SUNXI_FUNCTION(0x5, "uart2"),		/* RX */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 2)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 3),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd0"),		/* D5 */
> +		SUNXI_FUNCTION(0x3, "lvds0"),		/* V1N */
> +		SUNXI_FUNCTION(0x4, "dsi"),		/* D1N */
> +		SUNXI_FUNCTION(0x5, "uart2"),		/* RTS */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 3)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 4),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd0"),		/* D6 */
> +		SUNXI_FUNCTION(0x3, "lvds0"),		/* V2P */
> +		SUNXI_FUNCTION(0x4, "dsi"),		/* CKP */
> +		SUNXI_FUNCTION(0x5, "uart2"),		/* CTS */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 4)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 5),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd0"),		/* D7 */
> +		SUNXI_FUNCTION(0x3, "lvds0"),		/* V2N */
> +		SUNXI_FUNCTION(0x4, "dsi"),		/* CKN */
> +		SUNXI_FUNCTION(0x5, "uart5"),		/* TX */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 5)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 6),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd0"),		/* D10 */
> +		SUNXI_FUNCTION(0x3, "lvds0"),		/* CKP */
> +		SUNXI_FUNCTION(0x4, "dsi"),		/* D2P */
> +		SUNXI_FUNCTION(0x5, "uart5"),		/* RX */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 6)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 7),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd0"),		/* D11 */
> +		SUNXI_FUNCTION(0x3, "lvds0"),		/* CKN */
> +		SUNXI_FUNCTION(0x4, "dsi"),		/* D2N */
> +		SUNXI_FUNCTION(0x5, "uart4"),		/* TX */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 7)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 8),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd0"),		/* D12 */
> +		SUNXI_FUNCTION(0x3, "lvds0"),		/* V3P */
> +		SUNXI_FUNCTION(0x4, "dsi"),		/* D3P */
> +		SUNXI_FUNCTION(0x5, "uart4"),		/* RX */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 8)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 9),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd0"),		/* D13 */
> +		SUNXI_FUNCTION(0x3, "lvds0"),		/* V3N */
> +		SUNXI_FUNCTION(0x4, "dsi"),		/* D3N */
> +		SUNXI_FUNCTION(0x5, "pwm"),
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 9)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 10),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd0"),		/* D14 */
> +		SUNXI_FUNCTION(0x3, "lvds1"),		/* V0P */
> +		SUNXI_FUNCTION(0x4, "spi1"),		/* CS0 */
> +		SUNXI_FUNCTION(0x5, "uart3"),		/* TX */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 10)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 11),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd0"),		/* D15 */
> +		SUNXI_FUNCTION(0x3, "lvds1"),		/* V0N */
> +		SUNXI_FUNCTION(0x4, "spi1"),		/* CLK */
> +		SUNXI_FUNCTION(0x5, "uart3"),		/* RX */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 11)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 12),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd0"),		/* D18 */
> +		SUNXI_FUNCTION(0x3, "lvds1"),		/* V1P */
> +		SUNXI_FUNCTION(0x4, "spi1"),		/* MOSI */
> +		SUNXI_FUNCTION(0x5, "i2c0"),		/* SDA */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 12)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 13),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd0"),		/* D19 */
> +		SUNXI_FUNCTION(0x3, "lvds1"),		/* V1N */
> +		SUNXI_FUNCTION(0x4, "spi1"),		/* MISO */
> +		SUNXI_FUNCTION(0x5, "uart3"),		/* RTS */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 13)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 14),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd0"),		/* D20 */
> +		SUNXI_FUNCTION(0x3, "lvds1"),		/* V2P */
> +		SUNXI_FUNCTION(0x4, "spi1"),		/* HOLD */
> +		SUNXI_FUNCTION(0x5, "uart3"),		/* CTS */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 14)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 15),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd0"),		/* D21 */
> +		SUNXI_FUNCTION(0x3, "lvds1"),		/* V2N */
> +		SUNXI_FUNCTION(0x4, "spi1"),		/* WP */
> +		SUNXI_FUNCTION(0x5, "ir"),		/* RX */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 15)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 16),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd0"),		/* D22 */
> +		SUNXI_FUNCTION(0x3, "lvds1"),		/* CKP */
> +		SUNXI_FUNCTION(0x4, "dmic"),		/* DATA3 */
> +		SUNXI_FUNCTION(0x5, "pwm"),
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 16)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 17),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd0"),		/* D23 */
> +		SUNXI_FUNCTION(0x3, "lvds1"),		/* CKN */
> +		SUNXI_FUNCTION(0x4, "dmic"),		/* DATA2 */
> +		SUNXI_FUNCTION(0x5, "pwm"),
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 17)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 18),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd0"),		/* CLK */
> +		SUNXI_FUNCTION(0x3, "lvds1"),		/* V3P */
> +		SUNXI_FUNCTION(0x4, "dmic"),		/* DATA1 */
> +		SUNXI_FUNCTION(0x5, "pwm"),
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 18)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 19),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd0"),		/* DE */
> +		SUNXI_FUNCTION(0x3, "lvds1"),		/* V3N */
> +		SUNXI_FUNCTION(0x4, "dmic"),		/* DATA0 */
> +		SUNXI_FUNCTION(0x5, "pwm"),
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 19)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 20),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd0"),		/* HSYNC */
> +		SUNXI_FUNCTION(0x3, "i2c2"),		/* SCK */
> +		SUNXI_FUNCTION(0x4, "dmic"),		/* CLK */
> +		SUNXI_FUNCTION(0x5, "pwm"),
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 20)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 21),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd0"),		/* VSYNC */
> +		SUNXI_FUNCTION(0x3, "i2c2"),		/* SDA */
> +		SUNXI_FUNCTION(0x4, "uart1"),		/* TX */
> +		SUNXI_FUNCTION(0x5, "pwm"),
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 21)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 22),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "spdif"),		/* OUT */
> +		SUNXI_FUNCTION(0x3, "ir"),		/* RX */
> +		SUNXI_FUNCTION(0x4, "uart1"),		/* RX */
> +		SUNXI_FUNCTION(0x5, "pwm"),
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 22)),
> +	/* PE */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 0),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "ncsi0"),		/* HSYNC */
> +		SUNXI_FUNCTION(0x3, "uart2"),		/* RTS */
> +		SUNXI_FUNCTION(0x4, "i2c1"),		/* SCK */
> +		SUNXI_FUNCTION(0x5, "lcd0"),		/* HSYNC */
> +		SUNXI_FUNCTION(0x8, "emac"),		/* RXCTL/CRS_DV */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 0)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 1),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "ncsi0"),		/* VSYNC */
> +		SUNXI_FUNCTION(0x3, "uart2"),		/* CTS */
> +		SUNXI_FUNCTION(0x4, "i2c1"),		/* SDA */
> +		SUNXI_FUNCTION(0x5, "lcd0"),		/* VSYNC */
> +		SUNXI_FUNCTION(0x8, "emac"),		/* RXD0 */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 1)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 2),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "ncsi0"),		/* PCLK */
> +		SUNXI_FUNCTION(0x3, "uart2"),		/* TX */
> +		SUNXI_FUNCTION(0x4, "i2c0"),		/* SCK */
> +		SUNXI_FUNCTION(0x5, "clk"),		/* FANOUT0 */
> +		SUNXI_FUNCTION(0x6, "uart0"),		/* TX */
> +		SUNXI_FUNCTION(0x8, "emac"),		/* RXD1 */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 2)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 3),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "csi0"),		/* MCLK */

That function name should be "ncsi0".

> +		SUNXI_FUNCTION(0x3, "uart2"),		/* RX */
> +		SUNXI_FUNCTION(0x4, "i2c0"),		/* SDA */
> +		SUNXI_FUNCTION(0x5, "clk"),		/* FANOUT1 */
> +		SUNXI_FUNCTION(0x6, "uart0"),		/* RX */
> +		SUNXI_FUNCTION(0x8, "emac"),		/* TXCK */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 3)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 4),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "ncsi0"),		/* D0 */
> +		SUNXI_FUNCTION(0x3, "uart4"),		/* TX */
> +		SUNXI_FUNCTION(0x4, "i2c2"),		/* SCK */
> +		SUNXI_FUNCTION(0x5, "clk"),		/* FANOUT2 */
> +		SUNXI_FUNCTION(0x6, "d_jtag"),		/* MS */
> +		SUNXI_FUNCTION(0x7, "r_jtag"),		/* MS */
> +		SUNXI_FUNCTION(0x8, "emac"),		/* TXD0 */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 4)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 5),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "ncsi0"),		/* D1 */
> +		SUNXI_FUNCTION(0x3, "uart4"),		/* RX */
> +		SUNXI_FUNCTION(0x4, "i2c2"),		/* SDA */
> +		SUNXI_FUNCTION(0x5, "ledc"),
> +		SUNXI_FUNCTION(0x6, "d_jtag"),		/* D1 */
> +		SUNXI_FUNCTION(0x7, "r_jtag"),		/* D1 */

Those two pins should read "DI" in the comment (as in data in), I think.

> +		SUNXI_FUNCTION(0x8, "emac"),		/* TXD1 */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 5)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 6),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "ncsi0"),		/* D2 */
> +		SUNXI_FUNCTION(0x3, "uart5"),		/* TX */
> +		SUNXI_FUNCTION(0x4, "i2c3"),		/* SCK */
> +		SUNXI_FUNCTION(0x5, "spdif"),		/* IN */
> +		SUNXI_FUNCTION(0x6, "d_jtag"),		/* D0 */
> +		SUNXI_FUNCTION(0x7, "r_jtag"),		/* D0 */

And those two pins should be "DO" (as in data out).
Same for the other PortE JTAG signals below (but PortF is correct).


The rest looks correct to me. Very impressive!

Cheers,
Andre

> +		SUNXI_FUNCTION(0x8, "emac"),		/* TXCTL/TXEN */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 6)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 7),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "ncsi0"),		/* D3 */
> +		SUNXI_FUNCTION(0x3, "uart5"),		/* RX */
> +		SUNXI_FUNCTION(0x4, "i2c3"),		/* SDA */
> +		SUNXI_FUNCTION(0x5, "spdif"),		/* OUT */
> +		SUNXI_FUNCTION(0x6, "d_jtag"),		/* CK */
> +		SUNXI_FUNCTION(0x7, "r_jtag"),		/* CK */
> +		SUNXI_FUNCTION(0x8, "emac"),		/* CK */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 7)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 8),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "ncsi0"),		/* D4 */
> +		SUNXI_FUNCTION(0x3, "uart1"),		/* RTS */
> +		SUNXI_FUNCTION(0x4, "pwm"),
> +		SUNXI_FUNCTION(0x5, "uart3"),		/* TX */
> +		SUNXI_FUNCTION(0x6, "jtag"),		/* MS */
> +		SUNXI_FUNCTION(0x8, "emac"),		/* MDC */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 8)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 9),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "ncsi0"),		/* D5 */
> +		SUNXI_FUNCTION(0x3, "uart1"),		/* CTS */
> +		SUNXI_FUNCTION(0x4, "pwm"),
> +		SUNXI_FUNCTION(0x5, "uart3"),		/* RX */
> +		SUNXI_FUNCTION(0x6, "jtag"),		/* D1 */
> +		SUNXI_FUNCTION(0x8, "emac"),		/* MDIO */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 9)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 10),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "ncsi0"),		/* D6 */
> +		SUNXI_FUNCTION(0x3, "uart1"),		/* TX */
> +		SUNXI_FUNCTION(0x4, "pwm"),
> +		SUNXI_FUNCTION(0x5, "ir"),		/* RX */
> +		SUNXI_FUNCTION(0x6, "jtag"),		/* D0 */
> +		SUNXI_FUNCTION(0x8, "emac"),		/* EPHY-25M */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 10)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 11),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "ncsi0"),		/* D7 */
> +		SUNXI_FUNCTION(0x3, "uart1"),		/* RX */
> +		SUNXI_FUNCTION(0x4, "i2s0_dout"),	/* DOUT3 */
> +		SUNXI_FUNCTION(0x5, "i2s0_din"),	/* DIN3 */
> +		SUNXI_FUNCTION(0x6, "jtag"),		/* CK */
> +		SUNXI_FUNCTION(0x8, "emac"),		/* TXD2 */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 11)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 12),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "i2c2"),		/* SCK */
> +		SUNXI_FUNCTION(0x3, "ncsi0"),		/* FIELD */
> +		SUNXI_FUNCTION(0x4, "i2s0_dout"),	/* DOUT2 */
> +		SUNXI_FUNCTION(0x5, "i2s0_din"),	/* DIN2 */
> +		SUNXI_FUNCTION(0x8, "emac"),		/* TXD3 */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 12)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 13),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "i2c2"),		/* SDA */
> +		SUNXI_FUNCTION(0x3, "pwm"),
> +		SUNXI_FUNCTION(0x4, "i2s0_dout"),	/* DOUT0 */
> +		SUNXI_FUNCTION(0x5, "i2s0_din"),	/* DIN1 */
> +		SUNXI_FUNCTION(0x6, "dmic"),		/* DATA3 */
> +		SUNXI_FUNCTION(0x8, "emac"),		/* RXD2 */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 13)),
> +	SUNXI_PIN_VARIANT(SUNXI_PINCTRL_PIN(E, 14),
> +		PINCTRL_SUN20I_D1,
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "i2c1"),		/* SCK */
> +		SUNXI_FUNCTION(0x3, "d_jtag"),		/* MS */
> +		SUNXI_FUNCTION(0x4, "i2s0_dout"),	/* DOUT1 */
> +		SUNXI_FUNCTION(0x5, "i2s0_din"),	/* DIN0 */
> +		SUNXI_FUNCTION(0x6, "dmic"),		/* DATA2 */
> +		SUNXI_FUNCTION(0x8, "emac"),		/* RXD3 */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 14)),
> +	SUNXI_PIN_VARIANT(SUNXI_PINCTRL_PIN(E, 15),
> +		PINCTRL_SUN20I_D1,
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "i2c1"),		/* SDA */
> +		SUNXI_FUNCTION(0x3, "d_jtag"),		/* D1 */
> +		SUNXI_FUNCTION(0x4, "pwm"),
> +		SUNXI_FUNCTION(0x5, "i2s0"),		/* LRCK */
> +		SUNXI_FUNCTION(0x6, "dmic"),		/* DATA1 */
> +		SUNXI_FUNCTION(0x8, "emac"),		/* RXCK */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 15)),
> +	SUNXI_PIN_VARIANT(SUNXI_PINCTRL_PIN(E, 16),
> +		PINCTRL_SUN20I_D1,
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "i2c3"),		/* SCK */
> +		SUNXI_FUNCTION(0x3, "d_jtag"),		/* D0 */
> +		SUNXI_FUNCTION(0x4, "pwm"),
> +		SUNXI_FUNCTION(0x5, "i2s0"),		/* BCLK */
> +		SUNXI_FUNCTION(0x6, "dmic"),		/* DATA0 */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 16)),
> +	SUNXI_PIN_VARIANT(SUNXI_PINCTRL_PIN(E, 17),
> +		PINCTRL_SUN20I_D1,
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "i2c3"),		/* SDA */
> +		SUNXI_FUNCTION(0x3, "d_jtag"),		/* CK */
> +		SUNXI_FUNCTION(0x4, "ir"),		/* TX */
> +		SUNXI_FUNCTION(0x5, "i2s0"),		/* MCLK */
> +		SUNXI_FUNCTION(0x6, "dmic"),		/* CLK */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 17)),
> +	/* PF */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 0),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "mmc0"),		/* D1 */
> +		SUNXI_FUNCTION(0x3, "jtag"),		/* MS */
> +		SUNXI_FUNCTION(0x4, "r_jtag"),		/* MS */
> +		SUNXI_FUNCTION(0x5, "i2s2_dout"),	/* DOUT1 */
> +		SUNXI_FUNCTION(0x6, "i2s2_din"),	/* DIN0 */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 0)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 1),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "mmc0"),		/* D0 */
> +		SUNXI_FUNCTION(0x3, "jtag"),		/* DI */
> +		SUNXI_FUNCTION(0x4, "r_jtag"),		/* DI */
> +		SUNXI_FUNCTION(0x5, "i2s2_dout"),	/* DOUT0 */
> +		SUNXI_FUNCTION(0x6, "i2s2_din"),	/* DIN1 */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 1)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 2),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "mmc0"),		/* CLK */
> +		SUNXI_FUNCTION(0x3, "uart0"),		/* TX */
> +		SUNXI_FUNCTION(0x4, "i2c0"),		/* SCK */
> +		SUNXI_FUNCTION(0x5, "ledc"),
> +		SUNXI_FUNCTION(0x6, "spdif"),		/* IN */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 2)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 3),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "mmc0"),		/* CMD */
> +		SUNXI_FUNCTION(0x3, "jtag"),		/* DO */
> +		SUNXI_FUNCTION(0x4, "r_jtag"),		/* DO */
> +		SUNXI_FUNCTION(0x5, "i2s2"),		/* BCLK */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 3)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 4),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "mmc0"),		/* D3 */
> +		SUNXI_FUNCTION(0x3, "uart0"),		/* RX */
> +		SUNXI_FUNCTION(0x4, "i2c0"),		/* SDA */
> +		SUNXI_FUNCTION(0x5, "pwm"),
> +		SUNXI_FUNCTION(0x6, "ir"),		/* TX */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 4)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 5),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "mmc0"),		/* D2 */
> +		SUNXI_FUNCTION(0x3, "jtag"),		/* CK */
> +		SUNXI_FUNCTION(0x4, "r_jtag"),		/* CK */
> +		SUNXI_FUNCTION(0x5, "i2s2"),		/* LRCK */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 5)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 6),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x3, "spdif"),		/* OUT */
> +		SUNXI_FUNCTION(0x4, "ir"),		/* RX */
> +		SUNXI_FUNCTION(0x5, "i2s2"),		/* MCLK */
> +		SUNXI_FUNCTION(0x6, "pwm"),
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 6)),
> +	/* PG */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 0),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "mmc1"),		/* CLK */
> +		SUNXI_FUNCTION(0x3, "uart3"),		/* TX */
> +		SUNXI_FUNCTION(0x4, "emac"),		/* RXCTRL/CRS_DV */
> +		SUNXI_FUNCTION(0x5, "pwm"),
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 0)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 1),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "mmc1"),		/* CMD */
> +		SUNXI_FUNCTION(0x3, "uart3"),		/* RX */
> +		SUNXI_FUNCTION(0x4, "emac"),		/* RXD0 */
> +		SUNXI_FUNCTION(0x5, "pwm"),
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 1)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 2),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "mmc1"),		/* D0 */
> +		SUNXI_FUNCTION(0x3, "uart3"),		/* RTS */
> +		SUNXI_FUNCTION(0x4, "emac"),		/* RXD1 */
> +		SUNXI_FUNCTION(0x5, "uart4"),		/* TX */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 2)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 3),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "mmc1"),		/* D1 */
> +		SUNXI_FUNCTION(0x3, "uart3"),		/* CTS */
> +		SUNXI_FUNCTION(0x4, "emac"),		/* TXCK */
> +		SUNXI_FUNCTION(0x5, "uart4"),		/* RX */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 3)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 4),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "mmc1"),		/* D2 */
> +		SUNXI_FUNCTION(0x3, "uart5"),		/* TX */
> +		SUNXI_FUNCTION(0x4, "emac"),		/* TXD0 */
> +		SUNXI_FUNCTION(0x5, "pwm"),
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 4)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 5),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "mmc1"),		/* D3 */
> +		SUNXI_FUNCTION(0x3, "uart5"),		/* RX */
> +		SUNXI_FUNCTION(0x4, "emac"),		/* TXD1 */
> +		SUNXI_FUNCTION(0x5, "pwm"),
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 5)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 6),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "uart1"),		/* TX */
> +		SUNXI_FUNCTION(0x3, "i2c2"),		/* SCK */
> +		SUNXI_FUNCTION(0x4, "emac"),		/* TXD2 */
> +		SUNXI_FUNCTION(0x5, "pwm"),
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 6)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 7),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "uart1"),		/* RX */
> +		SUNXI_FUNCTION(0x3, "i2c2"),		/* SDA */
> +		SUNXI_FUNCTION(0x4, "emac"),		/* TXD3 */
> +		SUNXI_FUNCTION(0x5, "spdif"),		/* IN */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 7)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 8),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "uart1"),		/* RTS */
> +		SUNXI_FUNCTION(0x3, "i2c1"),		/* SCK */
> +		SUNXI_FUNCTION(0x4, "emac"),		/* RXD2 */
> +		SUNXI_FUNCTION(0x5, "uart3"),		/* TX */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 8)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 9),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "uart1"),		/* CTS */
> +		SUNXI_FUNCTION(0x3, "i2c1"),		/* SDA */
> +		SUNXI_FUNCTION(0x4, "emac"),		/* RXD3 */
> +		SUNXI_FUNCTION(0x5, "uart3"),		/* RX */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 9)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 10),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "pwm"),
> +		SUNXI_FUNCTION(0x3, "i2c3"),		/* SCK */
> +		SUNXI_FUNCTION(0x4, "emac"),		/* RXCK */
> +		SUNXI_FUNCTION(0x5, "clk"),		/* FANOUT0 */
> +		SUNXI_FUNCTION(0x6, "ir"),		/* RX */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 10)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 11),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "i2s1"),		/* MCLK */
> +		SUNXI_FUNCTION(0x3, "i2c3"),		/* SDA */
> +		SUNXI_FUNCTION(0x4, "emac"),		/* EPHY-25M */
> +		SUNXI_FUNCTION(0x5, "clk"),		/* FANOUT1 */
> +		SUNXI_FUNCTION(0x6, "tcon"),		/* TRIG0 */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 11)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 12),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "i2s1"),		/* LRCK */
> +		SUNXI_FUNCTION(0x3, "i2c0"),		/* SCK */
> +		SUNXI_FUNCTION(0x4, "emac"),		/* TXCTL/TXEN */
> +		SUNXI_FUNCTION(0x5, "clk"),		/* FANOUT2 */
> +		SUNXI_FUNCTION(0x6, "pwm"),
> +		SUNXI_FUNCTION(0x7, "uart1"),		/* TX */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 12)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 13),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "i2s1"),		/* BCLK */
> +		SUNXI_FUNCTION(0x3, "i2c0"),		/* SDA */
> +		SUNXI_FUNCTION(0x4, "emac"),		/* CLKIN/RXER */
> +		SUNXI_FUNCTION(0x5, "pwm"),
> +		SUNXI_FUNCTION(0x6, "ledc"),
> +		SUNXI_FUNCTION(0x7, "uart1"),		/* RX */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 13)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 14),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "i2s1_din"),	/* DIN0 */
> +		SUNXI_FUNCTION(0x3, "i2c2"),		/* SCK */
> +		SUNXI_FUNCTION(0x4, "emac"),		/* MDC */
> +		SUNXI_FUNCTION(0x5, "i2s1_dout"),	/* DOUT1 */
> +		SUNXI_FUNCTION(0x6, "spi0"),		/* WP */
> +		SUNXI_FUNCTION(0x7, "uart1"),		/* RTS */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 14)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 15),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "i2s1_dout"),	/* DOUT0 */
> +		SUNXI_FUNCTION(0x3, "i2c2"),		/* SDA */
> +		SUNXI_FUNCTION(0x4, "emac"),		/* MDIO */
> +		SUNXI_FUNCTION(0x5, "i2s1_din"),	/* DIN1 */
> +		SUNXI_FUNCTION(0x6, "spi0"),		/* HOLD */
> +		SUNXI_FUNCTION(0x7, "uart1"),		/* CTS */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 15)),
> +	SUNXI_PIN_VARIANT(SUNXI_PINCTRL_PIN(G, 16),
> +		PINCTRL_SUN20I_D1,
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "ir"),		/* RX */
> +		SUNXI_FUNCTION(0x3, "tcon"),		/* TRIG0 */
> +		SUNXI_FUNCTION(0x4, "pwm"),
> +		SUNXI_FUNCTION(0x5, "clk"),		/* FANOUT2 */
> +		SUNXI_FUNCTION(0x6, "spdif"),		/* IN */
> +		SUNXI_FUNCTION(0x7, "ledc"),
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 16)),
> +	SUNXI_PIN_VARIANT(SUNXI_PINCTRL_PIN(G, 17),
> +		PINCTRL_SUN20I_D1,
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "uart2"),		/* TX */
> +		SUNXI_FUNCTION(0x3, "i2c3"),		/* SCK */
> +		SUNXI_FUNCTION(0x4, "pwm"),
> +		SUNXI_FUNCTION(0x5, "clk"),		/* FANOUT0 */
> +		SUNXI_FUNCTION(0x6, "ir"),		/* TX */
> +		SUNXI_FUNCTION(0x7, "uart0"),		/* TX */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 17)),
> +	SUNXI_PIN_VARIANT(SUNXI_PINCTRL_PIN(G, 18),
> +		PINCTRL_SUN20I_D1,
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "uart2"),		/* RX */
> +		SUNXI_FUNCTION(0x3, "i2c3"),		/* SDA */
> +		SUNXI_FUNCTION(0x4, "pwm"),
> +		SUNXI_FUNCTION(0x5, "clk"),		/* FANOUT1 */
> +		SUNXI_FUNCTION(0x6, "spdif"),		/* OUT */
> +		SUNXI_FUNCTION(0x7, "uart0"),		/* RX */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 18)),
> +};
> +
> +static const unsigned int d1_irq_bank_map[] = { 1, 2, 3, 4, 5, 6 };
> +
> +static const struct sunxi_pinctrl_desc d1_pinctrl_data = {
> +	.pins			= d1_pins,
> +	.npins			= ARRAY_SIZE(d1_pins),
> +	.irq_banks		= ARRAY_SIZE(d1_irq_bank_map),
> +	.irq_bank_map		= d1_irq_bank_map,
> +	.io_bias_cfg_variant	= BIAS_VOLTAGE_PIO_POW_MODE_CTL,
> +};
> +
> +static int d1_pinctrl_probe(struct platform_device *pdev)
> +{
> +	unsigned long variant = (unsigned long)of_device_get_match_data(&pdev->dev);
> +
> +	return sunxi_pinctrl_init_with_variant(pdev, &d1_pinctrl_data, variant);
> +}
> +
> +static const struct of_device_id d1_pinctrl_match[] = {
> +	{
> +		.compatible = "allwinner,sun20i-d1-pinctrl",
> +		.data = (void *)PINCTRL_SUN20I_D1
> +	},
> +	{
> +		.compatible = "allwinner,sun20i-d1s-pinctrl",
> +		.data = (void *)PINCTRL_SUN20I_D1S
> +	},
> +	{}
> +};
> +
> +static struct platform_driver d1_pinctrl_driver = {
> +	.probe	= d1_pinctrl_probe,
> +	.driver	= {
> +		.name		= "sun20i-d1-pinctrl",
> +		.of_match_table	= d1_pinctrl_match,
> +	},
> +};
> +builtin_platform_driver(d1_pinctrl_driver);
> diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> index ec7daaa5666b..350044d4c1b5 100644
> --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> @@ -1297,11 +1297,11 @@ static int sunxi_pinctrl_build_state(struct platform_device *pdev)
>  
>  	/*
>  	 * Find an upper bound for the maximum number of functions: in
> -	 * the worst case we have gpio_in, gpio_out, irq and up to four
> +	 * the worst case we have gpio_in, gpio_out, irq and up to seven
>  	 * special functions per pin, plus one entry for the sentinel.
>  	 * We'll reallocate that later anyway.
>  	 */
> -	pctl->functions = kcalloc(4 * pctl->ngroups + 4,
> +	pctl->functions = kcalloc(7 * pctl->ngroups + 4,
>  				  sizeof(*pctl->functions),
>  				  GFP_KERNEL);
>  	if (!pctl->functions)
> @@ -1494,9 +1494,15 @@ int sunxi_pinctrl_init_with_variant(struct platform_device *pdev,
>  	pctl->dev = &pdev->dev;
>  	pctl->desc = desc;
>  	pctl->variant = variant;
> -	pctl->bank_mem_size = BANK_MEM_SIZE;
> -	pctl->pull_regs_offset = PULL_REGS_OFFSET;
> -	pctl->dlevel_field_width = DLEVEL_FIELD_WIDTH;
> +	if (pctl->variant >= PINCTRL_SUN20I_D1) {
> +		pctl->bank_mem_size = D1_BANK_MEM_SIZE;
> +		pctl->pull_regs_offset = D1_PULL_REGS_OFFSET;
> +		pctl->dlevel_field_width = D1_DLEVEL_FIELD_WIDTH;
> +	} else {
> +		pctl->bank_mem_size = BANK_MEM_SIZE;
> +		pctl->pull_regs_offset = PULL_REGS_OFFSET;
> +		pctl->dlevel_field_width = DLEVEL_FIELD_WIDTH;
> +	}
>  
>  	pctl->irq_array = devm_kcalloc(&pdev->dev,
>  				       IRQ_PER_BANK * pctl->desc->irq_banks,
> diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.h b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
> index c705828add73..f0f48941bc30 100644
> --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.h
> +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
> @@ -44,6 +44,10 @@
>  #define PULL_REGS_OFFSET	0x1c
>  #define PULL_FIELD_WIDTH	2
>  
> +#define D1_BANK_MEM_SIZE	0x30
> +#define D1_DLEVEL_FIELD_WIDTH	4
> +#define D1_PULL_REGS_OFFSET	0x24
> +
>  #define PINS_PER_BANK		32
>  
>  #define IRQ_PER_BANK		32
> @@ -88,6 +92,9 @@
>  #define PINCTRL_SUN8I_R40	BIT(8)
>  #define PINCTRL_SUN8I_V3	BIT(9)
>  #define PINCTRL_SUN8I_V3S	BIT(10)
> +/* Variants below here have an updated register layout. */
> +#define PINCTRL_SUN20I_D1	BIT(11)
> +#define PINCTRL_SUN20I_D1S	BIT(12)
>  
>  #define PIO_POW_MOD_SEL_REG	0x340
>  #define PIO_POW_MOD_CTL_REG	0x344


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

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

* Re: [PATCH 6/6] pinctrl: sunxi: Add driver for Allwinner D1/D1s
  2022-07-02 14:47     ` Andre Przywara
@ 2022-07-02 15:43       ` Samuel Holland
  -1 siblings, 0 replies; 56+ messages in thread
From: Samuel Holland @ 2022-07-02 15:43 UTC (permalink / raw)
  To: Andre Przywara
  Cc: Chen-Yu Tsai, Jernej Skrabec, Linus Walleij, Krzysztof Kozlowski,
	Maxime Ripard, Ondrej Jirman, Rob Herring, devicetree,
	linux-arm-kernel, linux-gpio, linux-kernel, linux-sunxi,
	Heiko Stuebner

On 7/2/22 9:47 AM, Andre Przywara wrote:
> On Sat, 25 Jun 2022 21:11:47 -0500
> Samuel Holland <samuel@sholland.org> wrote:
> 
> Hi Samuel,
> 
>> These SoCs contain a pinctrl with a new register layout. Use the variant
>> parameter to set the right register offsets. This pinctrl also increases
>> the number of functions per pin from 8 to 16, taking advantage of all 4
>> bits in the mux config field (so far, only functions 0-8 and 14-15 are
>> used). This increases the maximum possible number of functions.
>>
>> D1s is a low pin count version of the D1 SoC, with some pins omitted.
>> The remaining pins have the same function assignments as D1.
> 
> So do we actually need this extra variant, if there are no conflicts?
> The D1s seems to be a simple subset of the D1. I think we followed the
> same approach for the H616 already, where there are more pins in the
> pinctrl driver than the manual describes, and which are used in other
> package variants, like the T507.
> In case of the H616, those pins are there, you can program them (which
> is not the case for not implemented pins otherwise), they are just not
> connected to the package.
> I would expect a DT to never reference them, and even if, it doesn't do
> any harm other than just not working.

I am following the example of V3/V3s here, so it seems we are inconsistent on
this point. I needed to supply one variant for the register layout anyway, so I
though I might as well be "accurate".

But with Allwinner releasing lots of packages per die, it is probably overkill
to have a separate compatible per packge. As you note, there is no harm in
configuring pins that do not map to any pad.

Some notes for completeness:
 - D1 documents all three JTAG functions (ARM, RISC-V, and DSP), although the
ARM JTAG does not work.
 - D1s/F133 only documents the RISC-V JTAG function.
 - T113 only documents the ARM and DSP JTAG functions.
 - T113 adds a CAN function on mux 8 of PB2-PB5. The CAN controller accidentally
made it in to one version of the D1 datasheet, so it may unofficially exist there.

None of these variations are conflicting.

> For the table below: I checked every pin against the D1 manual (yes,
> that took an hour), and found only one small issue and some nits in
> PortE, see inline.
> 
>> Signed-off-by: Samuel Holland <samuel@sholland.org>
>> ---
>>
>>  drivers/pinctrl/sunxi/Kconfig             |   5 +
>>  drivers/pinctrl/sunxi/Makefile            |   1 +
>>  drivers/pinctrl/sunxi/pinctrl-sun20i-d1.c | 860 ++++++++++++++++++++++
>>  drivers/pinctrl/sunxi/pinctrl-sunxi.c     |  16 +-
>>  drivers/pinctrl/sunxi/pinctrl-sunxi.h     |   7 +
>>  5 files changed, 884 insertions(+), 5 deletions(-)
>>  create mode 100644 drivers/pinctrl/sunxi/pinctrl-sun20i-d1.c
>>
>> diff --git a/drivers/pinctrl/sunxi/Kconfig b/drivers/pinctrl/sunxi/Kconfig
>> index 33751a6a0757..a6ac1c1f2585 100644
>> --- a/drivers/pinctrl/sunxi/Kconfig
>> +++ b/drivers/pinctrl/sunxi/Kconfig
>> @@ -84,6 +84,11 @@ config PINCTRL_SUN9I_A80_R
>>  	depends on RESET_CONTROLLER
>>  	select PINCTRL_SUNXI
>>  
>> +config PINCTRL_SUN20I_D1
>> +	bool "Support for the Allwinner D1 PIO"
>> +	default RISCV && ARCH_SUNXI
>> +	select PINCTRL_SUNXI
>> +
>>  config PINCTRL_SUN50I_A64
>>  	bool "Support for the Allwinner A64 PIO"
>>  	default ARM64 && ARCH_SUNXI
>> diff --git a/drivers/pinctrl/sunxi/Makefile b/drivers/pinctrl/sunxi/Makefile
>> index d3440c42b9d6..2ff5a55927ad 100644
>> --- a/drivers/pinctrl/sunxi/Makefile
>> +++ b/drivers/pinctrl/sunxi/Makefile
>> @@ -20,6 +20,7 @@ obj-$(CONFIG_PINCTRL_SUN8I_A83T_R)	+= pinctrl-sun8i-a83t-r.o
>>  obj-$(CONFIG_PINCTRL_SUN8I_H3)		+= pinctrl-sun8i-h3.o
>>  obj-$(CONFIG_PINCTRL_SUN8I_H3_R)	+= pinctrl-sun8i-h3-r.o
>>  obj-$(CONFIG_PINCTRL_SUN8I_V3S)		+= pinctrl-sun8i-v3s.o
>> +obj-$(CONFIG_PINCTRL_SUN20I_D1)		+= pinctrl-sun20i-d1.o
>>  obj-$(CONFIG_PINCTRL_SUN50I_H5)		+= pinctrl-sun50i-h5.o
>>  obj-$(CONFIG_PINCTRL_SUN50I_H6)		+= pinctrl-sun50i-h6.o
>>  obj-$(CONFIG_PINCTRL_SUN50I_H6_R)	+= pinctrl-sun50i-h6-r.o
>> diff --git a/drivers/pinctrl/sunxi/pinctrl-sun20i-d1.c b/drivers/pinctrl/sunxi/pinctrl-sun20i-d1.c
>> new file mode 100644
>> index 000000000000..7247c1f1d92c
>> --- /dev/null
>> +++ b/drivers/pinctrl/sunxi/pinctrl-sun20i-d1.c
>> @@ -0,0 +1,860 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * Allwinner D1 SoC pinctrl driver.
>> + *
>> + * Copyright (c) 2020 wuyan@allwinnertech.com
>> + * Copyright (c) 2021-2022 Samuel Holland <samuel@sholland.org>
>> + */
>> +
>> +#include <linux/module.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/of.h>
>> +#include <linux/of_device.h>
>> +#include <linux/pinctrl/pinctrl.h>
>> +
>> +#include "pinctrl-sunxi.h"
>> +
>> +static const struct sunxi_desc_pin d1_pins[] = {
>> +	/* PB */
>> +	SUNXI_PIN_VARIANT(SUNXI_PINCTRL_PIN(B, 0),
>> +		PINCTRL_SUN20I_D1,
>> +		SUNXI_FUNCTION(0x0, "gpio_in"),
>> +		SUNXI_FUNCTION(0x1, "gpio_out"),
>> +		SUNXI_FUNCTION(0x2, "pwm"),
> 
> The manual mentions the PWM channel number in the pin name, and it
> seems like in other pinctrl drivers we use the number either in the
> function name, or at least in the comment.
> Shall we do one of them here as well?

I originally had the numbers in the function name, but then I realized that no
pin has multiple PWM muxes, so I removed them. As you mention, other drivers
have them, so I will add them back.

> And the mux numbers for pwm are all over the place, so lets hope we
> never need pwm in U-Boot ;-)

PWM is used for the CPU voltage regulator on at least one board (Nezha), but I
think we can get away without U-Boot support for that. And including the PWM
number in the function name will improve things somewhat.

I will fix the typos you noted below.

Regards,
Samuel

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

* Re: [PATCH 6/6] pinctrl: sunxi: Add driver for Allwinner D1/D1s
@ 2022-07-02 15:43       ` Samuel Holland
  0 siblings, 0 replies; 56+ messages in thread
From: Samuel Holland @ 2022-07-02 15:43 UTC (permalink / raw)
  To: Andre Przywara
  Cc: Chen-Yu Tsai, Jernej Skrabec, Linus Walleij, Krzysztof Kozlowski,
	Maxime Ripard, Ondrej Jirman, Rob Herring, devicetree,
	linux-arm-kernel, linux-gpio, linux-kernel, linux-sunxi,
	Heiko Stuebner

On 7/2/22 9:47 AM, Andre Przywara wrote:
> On Sat, 25 Jun 2022 21:11:47 -0500
> Samuel Holland <samuel@sholland.org> wrote:
> 
> Hi Samuel,
> 
>> These SoCs contain a pinctrl with a new register layout. Use the variant
>> parameter to set the right register offsets. This pinctrl also increases
>> the number of functions per pin from 8 to 16, taking advantage of all 4
>> bits in the mux config field (so far, only functions 0-8 and 14-15 are
>> used). This increases the maximum possible number of functions.
>>
>> D1s is a low pin count version of the D1 SoC, with some pins omitted.
>> The remaining pins have the same function assignments as D1.
> 
> So do we actually need this extra variant, if there are no conflicts?
> The D1s seems to be a simple subset of the D1. I think we followed the
> same approach for the H616 already, where there are more pins in the
> pinctrl driver than the manual describes, and which are used in other
> package variants, like the T507.
> In case of the H616, those pins are there, you can program them (which
> is not the case for not implemented pins otherwise), they are just not
> connected to the package.
> I would expect a DT to never reference them, and even if, it doesn't do
> any harm other than just not working.

I am following the example of V3/V3s here, so it seems we are inconsistent on
this point. I needed to supply one variant for the register layout anyway, so I
though I might as well be "accurate".

But with Allwinner releasing lots of packages per die, it is probably overkill
to have a separate compatible per packge. As you note, there is no harm in
configuring pins that do not map to any pad.

Some notes for completeness:
 - D1 documents all three JTAG functions (ARM, RISC-V, and DSP), although the
ARM JTAG does not work.
 - D1s/F133 only documents the RISC-V JTAG function.
 - T113 only documents the ARM and DSP JTAG functions.
 - T113 adds a CAN function on mux 8 of PB2-PB5. The CAN controller accidentally
made it in to one version of the D1 datasheet, so it may unofficially exist there.

None of these variations are conflicting.

> For the table below: I checked every pin against the D1 manual (yes,
> that took an hour), and found only one small issue and some nits in
> PortE, see inline.
> 
>> Signed-off-by: Samuel Holland <samuel@sholland.org>
>> ---
>>
>>  drivers/pinctrl/sunxi/Kconfig             |   5 +
>>  drivers/pinctrl/sunxi/Makefile            |   1 +
>>  drivers/pinctrl/sunxi/pinctrl-sun20i-d1.c | 860 ++++++++++++++++++++++
>>  drivers/pinctrl/sunxi/pinctrl-sunxi.c     |  16 +-
>>  drivers/pinctrl/sunxi/pinctrl-sunxi.h     |   7 +
>>  5 files changed, 884 insertions(+), 5 deletions(-)
>>  create mode 100644 drivers/pinctrl/sunxi/pinctrl-sun20i-d1.c
>>
>> diff --git a/drivers/pinctrl/sunxi/Kconfig b/drivers/pinctrl/sunxi/Kconfig
>> index 33751a6a0757..a6ac1c1f2585 100644
>> --- a/drivers/pinctrl/sunxi/Kconfig
>> +++ b/drivers/pinctrl/sunxi/Kconfig
>> @@ -84,6 +84,11 @@ config PINCTRL_SUN9I_A80_R
>>  	depends on RESET_CONTROLLER
>>  	select PINCTRL_SUNXI
>>  
>> +config PINCTRL_SUN20I_D1
>> +	bool "Support for the Allwinner D1 PIO"
>> +	default RISCV && ARCH_SUNXI
>> +	select PINCTRL_SUNXI
>> +
>>  config PINCTRL_SUN50I_A64
>>  	bool "Support for the Allwinner A64 PIO"
>>  	default ARM64 && ARCH_SUNXI
>> diff --git a/drivers/pinctrl/sunxi/Makefile b/drivers/pinctrl/sunxi/Makefile
>> index d3440c42b9d6..2ff5a55927ad 100644
>> --- a/drivers/pinctrl/sunxi/Makefile
>> +++ b/drivers/pinctrl/sunxi/Makefile
>> @@ -20,6 +20,7 @@ obj-$(CONFIG_PINCTRL_SUN8I_A83T_R)	+= pinctrl-sun8i-a83t-r.o
>>  obj-$(CONFIG_PINCTRL_SUN8I_H3)		+= pinctrl-sun8i-h3.o
>>  obj-$(CONFIG_PINCTRL_SUN8I_H3_R)	+= pinctrl-sun8i-h3-r.o
>>  obj-$(CONFIG_PINCTRL_SUN8I_V3S)		+= pinctrl-sun8i-v3s.o
>> +obj-$(CONFIG_PINCTRL_SUN20I_D1)		+= pinctrl-sun20i-d1.o
>>  obj-$(CONFIG_PINCTRL_SUN50I_H5)		+= pinctrl-sun50i-h5.o
>>  obj-$(CONFIG_PINCTRL_SUN50I_H6)		+= pinctrl-sun50i-h6.o
>>  obj-$(CONFIG_PINCTRL_SUN50I_H6_R)	+= pinctrl-sun50i-h6-r.o
>> diff --git a/drivers/pinctrl/sunxi/pinctrl-sun20i-d1.c b/drivers/pinctrl/sunxi/pinctrl-sun20i-d1.c
>> new file mode 100644
>> index 000000000000..7247c1f1d92c
>> --- /dev/null
>> +++ b/drivers/pinctrl/sunxi/pinctrl-sun20i-d1.c
>> @@ -0,0 +1,860 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * Allwinner D1 SoC pinctrl driver.
>> + *
>> + * Copyright (c) 2020 wuyan@allwinnertech.com
>> + * Copyright (c) 2021-2022 Samuel Holland <samuel@sholland.org>
>> + */
>> +
>> +#include <linux/module.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/of.h>
>> +#include <linux/of_device.h>
>> +#include <linux/pinctrl/pinctrl.h>
>> +
>> +#include "pinctrl-sunxi.h"
>> +
>> +static const struct sunxi_desc_pin d1_pins[] = {
>> +	/* PB */
>> +	SUNXI_PIN_VARIANT(SUNXI_PINCTRL_PIN(B, 0),
>> +		PINCTRL_SUN20I_D1,
>> +		SUNXI_FUNCTION(0x0, "gpio_in"),
>> +		SUNXI_FUNCTION(0x1, "gpio_out"),
>> +		SUNXI_FUNCTION(0x2, "pwm"),
> 
> The manual mentions the PWM channel number in the pin name, and it
> seems like in other pinctrl drivers we use the number either in the
> function name, or at least in the comment.
> Shall we do one of them here as well?

I originally had the numbers in the function name, but then I realized that no
pin has multiple PWM muxes, so I removed them. As you mention, other drivers
have them, so I will add them back.

> And the mux numbers for pwm are all over the place, so lets hope we
> never need pwm in U-Boot ;-)

PWM is used for the CPU voltage regulator on at least one board (Nezha), but I
think we can get away without U-Boot support for that. And including the PWM
number in the function name will improve things somewhat.

I will fix the typos you noted below.

Regards,
Samuel

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

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

* Re: [PATCH 3/6] pinctrl: sunxi: Support the 2.5V I/O bias mode
  2022-06-28  3:29       ` Samuel Holland
@ 2022-07-02 19:48         ` Jernej Škrabec
  -1 siblings, 0 replies; 56+ messages in thread
From: Jernej Škrabec @ 2022-07-02 19:48 UTC (permalink / raw)
  To: Chen-Yu Tsai, Linus Walleij, Samuel Holland
  Cc: Krzysztof Kozlowski, Maxime Ripard, Ondrej Jirman, Rob Herring,
	devicetree, linux-arm-kernel, linux-gpio, linux-kernel,
	linux-sunxi

Dne torek, 28. junij 2022 ob 05:29:51 CEST je Samuel Holland napisal(a):
> On 6/27/22 3:43 PM, Jernej Škrabec wrote:
> > Dne nedelja, 26. junij 2022 ob 04:11:44 CEST je Samuel Holland napisal(a):
> >> H616 and newer SoCs feature a 2.5V I/O bias mode in addition to the
> >> 1.8V and 3.3V modes. This mode is entered by selecting the 3.3V level
> >> and disabling the "withstand function".
> >> 
> >> H616 supports this capability on its main PIO only. A100 supports this
> >> capability on both its PIO and R-PIO.
> >> 
> >> Signed-off-by: Samuel Holland <samuel@sholland.org>
> >> ---
> >> 
> >>  drivers/pinctrl/sunxi/pinctrl-sun50i-a100-r.c |  1 +
> >>  drivers/pinctrl/sunxi/pinctrl-sun50i-a100.c   |  2 +-
> >>  drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c   |  2 +-
> >>  drivers/pinctrl/sunxi/pinctrl-sunxi.c         | 10 ++++++++++
> >>  drivers/pinctrl/sunxi/pinctrl-sunxi.h         |  7 +++++++
> >>  5 files changed, 20 insertions(+), 2 deletions(-)
> >> 
> >> diff --git a/drivers/pinctrl/sunxi/pinctrl-sun50i-a100-r.c
> >> b/drivers/pinctrl/sunxi/pinctrl-sun50i-a100-r.c index
> >> 21054fcacd34..afc1f5df7545 100644
> >> --- a/drivers/pinctrl/sunxi/pinctrl-sun50i-a100-r.c
> >> +++ b/drivers/pinctrl/sunxi/pinctrl-sun50i-a100-r.c
> >> @@ -82,6 +82,7 @@ static const struct sunxi_pinctrl_desc
> >> a100_r_pinctrl_data = { .npins = ARRAY_SIZE(a100_r_pins),
> >> 
> >>  	.pin_base = PL_BASE,
> >>  	.irq_banks = 1,
> >> 
> >> +	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_CTL,
> >> 
> >>  };
> >>  
> >>  static int a100_r_pinctrl_probe(struct platform_device *pdev)
> >> 
> >> diff --git a/drivers/pinctrl/sunxi/pinctrl-sun50i-a100.c
> >> b/drivers/pinctrl/sunxi/pinctrl-sun50i-a100.c index
> >> e69f6da40dc0..f682e0e4244d 100644
> >> --- a/drivers/pinctrl/sunxi/pinctrl-sun50i-a100.c
> >> +++ b/drivers/pinctrl/sunxi/pinctrl-sun50i-a100.c
> >> @@ -684,7 +684,7 @@ static const struct sunxi_pinctrl_desc
> >> a100_pinctrl_data = { .npins = ARRAY_SIZE(a100_pins),
> >> 
> >>  	.irq_banks = 7,
> >>  	.irq_bank_map = a100_irq_bank_map,
> >> 
> >> -	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_SEL,
> >> +	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_CTL,
> >> 
> >>  };
> >>  
> >>  static int a100_pinctrl_probe(struct platform_device *pdev)
> >> 
> >> diff --git a/drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c
> >> b/drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c index
> >> 152b71226a80..d6ca720ee8d8 100644
> >> --- a/drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c
> >> +++ b/drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c
> >> @@ -525,7 +525,7 @@ static const struct sunxi_pinctrl_desc
> >> h616_pinctrl_data = { .irq_banks = ARRAY_SIZE(h616_irq_bank_map),
> >> 
> >>  	.irq_bank_map = h616_irq_bank_map,
> >>  	.irq_read_needs_mux = true,
> >> 
> >> -	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_SEL,
> >> +	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_CTL,
> >> 
> >>  };
> >>  
> >>  static int h616_pinctrl_probe(struct platform_device *pdev)
> >> 
> >> diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> >> b/drivers/pinctrl/sunxi/pinctrl-sunxi.c index 3c5e71359ca8..eb3d595f816a
> >> 100644
> >> --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> >> +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> >> @@ -662,6 +662,16 @@ static int sunxi_pinctrl_set_io_bias_cfg(struct
> >> sunxi_pinctrl *pctl, reg &= ~IO_BIAS_MASK;
> >> 
> >>  		writel(reg | val, pctl->membase +
> > 
> > sunxi_grp_config_reg(pin));
> > 
> >>  		return 0;
> >> 
> >> +	case BIAS_VOLTAGE_PIO_POW_MODE_CTL:
> >> +		val = uV > 1800000 && uV <= 2500000 ? BIT(bank) : 0;
> >> +
> >> +		raw_spin_lock_irqsave(&pctl->lock, flags);
> >> +		reg = readl(pctl->membase + PIO_POW_MOD_CTL_REG);
> >> +		reg &= ~BIT(bank);
> >> +		writel(reg | val, pctl->membase + PIO_POW_MOD_CTL_REG);
> >> +		raw_spin_unlock_irqrestore(&pctl->lock, flags);
> >> +
> >> +		fallthrough;
> > 
> > Would this set bit 12 as needed? According to documentation, it's a bit
> > special case, since it covers VCC-IO, port F and port H, at least
> > according to documentation. I guess BIAS_VOLTAGE_PIO_POW_MODE_SEL has
> > same issue.
> Right, it seems we would need some mask to tell us which ports are affected
> by bit 12, and which have their own setting. The current code is unlikely
> to cause any issue, though, because in practice VCC-IO is always 3.3 V.

ok, it's good for now.

Reviewed-by: Jernej Skrabec <jernej.skrabec@gmail.com>

Best regards,
Jernej




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

* Re: [PATCH 3/6] pinctrl: sunxi: Support the 2.5V I/O bias mode
@ 2022-07-02 19:48         ` Jernej Škrabec
  0 siblings, 0 replies; 56+ messages in thread
From: Jernej Škrabec @ 2022-07-02 19:48 UTC (permalink / raw)
  To: Chen-Yu Tsai, Linus Walleij, Samuel Holland
  Cc: Krzysztof Kozlowski, Maxime Ripard, Ondrej Jirman, Rob Herring,
	devicetree, linux-arm-kernel, linux-gpio, linux-kernel,
	linux-sunxi

Dne torek, 28. junij 2022 ob 05:29:51 CEST je Samuel Holland napisal(a):
> On 6/27/22 3:43 PM, Jernej Škrabec wrote:
> > Dne nedelja, 26. junij 2022 ob 04:11:44 CEST je Samuel Holland napisal(a):
> >> H616 and newer SoCs feature a 2.5V I/O bias mode in addition to the
> >> 1.8V and 3.3V modes. This mode is entered by selecting the 3.3V level
> >> and disabling the "withstand function".
> >> 
> >> H616 supports this capability on its main PIO only. A100 supports this
> >> capability on both its PIO and R-PIO.
> >> 
> >> Signed-off-by: Samuel Holland <samuel@sholland.org>
> >> ---
> >> 
> >>  drivers/pinctrl/sunxi/pinctrl-sun50i-a100-r.c |  1 +
> >>  drivers/pinctrl/sunxi/pinctrl-sun50i-a100.c   |  2 +-
> >>  drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c   |  2 +-
> >>  drivers/pinctrl/sunxi/pinctrl-sunxi.c         | 10 ++++++++++
> >>  drivers/pinctrl/sunxi/pinctrl-sunxi.h         |  7 +++++++
> >>  5 files changed, 20 insertions(+), 2 deletions(-)
> >> 
> >> diff --git a/drivers/pinctrl/sunxi/pinctrl-sun50i-a100-r.c
> >> b/drivers/pinctrl/sunxi/pinctrl-sun50i-a100-r.c index
> >> 21054fcacd34..afc1f5df7545 100644
> >> --- a/drivers/pinctrl/sunxi/pinctrl-sun50i-a100-r.c
> >> +++ b/drivers/pinctrl/sunxi/pinctrl-sun50i-a100-r.c
> >> @@ -82,6 +82,7 @@ static const struct sunxi_pinctrl_desc
> >> a100_r_pinctrl_data = { .npins = ARRAY_SIZE(a100_r_pins),
> >> 
> >>  	.pin_base = PL_BASE,
> >>  	.irq_banks = 1,
> >> 
> >> +	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_CTL,
> >> 
> >>  };
> >>  
> >>  static int a100_r_pinctrl_probe(struct platform_device *pdev)
> >> 
> >> diff --git a/drivers/pinctrl/sunxi/pinctrl-sun50i-a100.c
> >> b/drivers/pinctrl/sunxi/pinctrl-sun50i-a100.c index
> >> e69f6da40dc0..f682e0e4244d 100644
> >> --- a/drivers/pinctrl/sunxi/pinctrl-sun50i-a100.c
> >> +++ b/drivers/pinctrl/sunxi/pinctrl-sun50i-a100.c
> >> @@ -684,7 +684,7 @@ static const struct sunxi_pinctrl_desc
> >> a100_pinctrl_data = { .npins = ARRAY_SIZE(a100_pins),
> >> 
> >>  	.irq_banks = 7,
> >>  	.irq_bank_map = a100_irq_bank_map,
> >> 
> >> -	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_SEL,
> >> +	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_CTL,
> >> 
> >>  };
> >>  
> >>  static int a100_pinctrl_probe(struct platform_device *pdev)
> >> 
> >> diff --git a/drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c
> >> b/drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c index
> >> 152b71226a80..d6ca720ee8d8 100644
> >> --- a/drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c
> >> +++ b/drivers/pinctrl/sunxi/pinctrl-sun50i-h616.c
> >> @@ -525,7 +525,7 @@ static const struct sunxi_pinctrl_desc
> >> h616_pinctrl_data = { .irq_banks = ARRAY_SIZE(h616_irq_bank_map),
> >> 
> >>  	.irq_bank_map = h616_irq_bank_map,
> >>  	.irq_read_needs_mux = true,
> >> 
> >> -	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_SEL,
> >> +	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_CTL,
> >> 
> >>  };
> >>  
> >>  static int h616_pinctrl_probe(struct platform_device *pdev)
> >> 
> >> diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> >> b/drivers/pinctrl/sunxi/pinctrl-sunxi.c index 3c5e71359ca8..eb3d595f816a
> >> 100644
> >> --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> >> +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> >> @@ -662,6 +662,16 @@ static int sunxi_pinctrl_set_io_bias_cfg(struct
> >> sunxi_pinctrl *pctl, reg &= ~IO_BIAS_MASK;
> >> 
> >>  		writel(reg | val, pctl->membase +
> > 
> > sunxi_grp_config_reg(pin));
> > 
> >>  		return 0;
> >> 
> >> +	case BIAS_VOLTAGE_PIO_POW_MODE_CTL:
> >> +		val = uV > 1800000 && uV <= 2500000 ? BIT(bank) : 0;
> >> +
> >> +		raw_spin_lock_irqsave(&pctl->lock, flags);
> >> +		reg = readl(pctl->membase + PIO_POW_MOD_CTL_REG);
> >> +		reg &= ~BIT(bank);
> >> +		writel(reg | val, pctl->membase + PIO_POW_MOD_CTL_REG);
> >> +		raw_spin_unlock_irqrestore(&pctl->lock, flags);
> >> +
> >> +		fallthrough;
> > 
> > Would this set bit 12 as needed? According to documentation, it's a bit
> > special case, since it covers VCC-IO, port F and port H, at least
> > according to documentation. I guess BIAS_VOLTAGE_PIO_POW_MODE_SEL has
> > same issue.
> Right, it seems we would need some mask to tell us which ports are affected
> by bit 12, and which have their own setting. The current code is unlikely
> to cause any issue, though, because in practice VCC-IO is always 3.3 V.

ok, it's good for now.

Reviewed-by: Jernej Skrabec <jernej.skrabec@gmail.com>

Best regards,
Jernej




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

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

* Re: [PATCH 4/6] pinctrl: sunxi: Refactor register/offset calculation
  2022-06-26  2:11   ` Samuel Holland
@ 2022-07-02 20:29     ` Jernej Škrabec
  -1 siblings, 0 replies; 56+ messages in thread
From: Jernej Škrabec @ 2022-07-02 20:29 UTC (permalink / raw)
  To: Chen-Yu Tsai, Linus Walleij, Samuel Holland
  Cc: Samuel Holland, Krzysztof Kozlowski, Maxime Ripard,
	Ondrej Jirman, Rob Herring, devicetree, linux-arm-kernel,
	linux-gpio, linux-kernel, linux-sunxi

Dne nedelja, 26. junij 2022 ob 04:11:45 CEST je Samuel Holland napisal(a):
> Starting with the D1/D1s/T113 SoC, Allwinner changed the layout of the
> pinctrl registers. This new layout widens the drive level field, which
> affects the pull register offset and the overall bank size.
> 
> As a first step to support this, combine the register and offset
> calculation functions, and refactor the math to depend on one constant
> for field widths instead of three. This minimizes the code size impact
> of making some of the factors dynamic.
> 
> While rewriting these functions, move them to the implementation file,
> since that is the only file where they are used. And make the comment
> more generic, without mentioning specific offsets/sizes.
> 
> The callers are updated to expect a shifted mask, and to use consistent
> terminology (reg/shift/mask/val).
> 
> Signed-off-by: Samuel Holland <samuel@sholland.org>

Nice cleanup.

Reviewed-by: Jernej Skrabec <jernej.skrabec@gmail.com>

Best regards,
Jernej



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

* Re: [PATCH 4/6] pinctrl: sunxi: Refactor register/offset calculation
@ 2022-07-02 20:29     ` Jernej Škrabec
  0 siblings, 0 replies; 56+ messages in thread
From: Jernej Škrabec @ 2022-07-02 20:29 UTC (permalink / raw)
  To: Chen-Yu Tsai, Linus Walleij, Samuel Holland
  Cc: Samuel Holland, Krzysztof Kozlowski, Maxime Ripard,
	Ondrej Jirman, Rob Herring, devicetree, linux-arm-kernel,
	linux-gpio, linux-kernel, linux-sunxi

Dne nedelja, 26. junij 2022 ob 04:11:45 CEST je Samuel Holland napisal(a):
> Starting with the D1/D1s/T113 SoC, Allwinner changed the layout of the
> pinctrl registers. This new layout widens the drive level field, which
> affects the pull register offset and the overall bank size.
> 
> As a first step to support this, combine the register and offset
> calculation functions, and refactor the math to depend on one constant
> for field widths instead of three. This minimizes the code size impact
> of making some of the factors dynamic.
> 
> While rewriting these functions, move them to the implementation file,
> since that is the only file where they are used. And make the comment
> more generic, without mentioning specific offsets/sizes.
> 
> The callers are updated to expect a shifted mask, and to use consistent
> terminology (reg/shift/mask/val).
> 
> Signed-off-by: Samuel Holland <samuel@sholland.org>

Nice cleanup.

Reviewed-by: Jernej Skrabec <jernej.skrabec@gmail.com>

Best regards,
Jernej



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

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

* Re: [PATCH 5/6] pinctrl: sunxi: Make some layout parameters dynamic
  2022-06-26  2:11   ` Samuel Holland
@ 2022-07-02 20:33     ` Jernej Škrabec
  -1 siblings, 0 replies; 56+ messages in thread
From: Jernej Škrabec @ 2022-07-02 20:33 UTC (permalink / raw)
  To: Chen-Yu Tsai, Linus Walleij, Samuel Holland
  Cc: Samuel Holland, Krzysztof Kozlowski, Maxime Ripard,
	Ondrej Jirman, Rob Herring, devicetree, linux-arm-kernel,
	linux-gpio, linux-kernel, linux-sunxi

Dne nedelja, 26. junij 2022 ob 04:11:46 CEST je Samuel Holland napisal(a):
> Starting with the D1/D1s/T113 SoC, Allwinner changed the layout of the
> pinctrl registers. This new layout widens the drive level field, which
> affects the pull register offset and the overall bank size.
> 
> In order to support multiple register layouts, some of the layout
> parameters need to be set based on the pinctrl variant. This requires
> passing the pinctrl struct pointer to the register/offset calculation
> functions.
> 
> Signed-off-by: Samuel Holland <samuel@sholland.org>

Reviewed-by: Jernej Skrabec <jernej.skrabec@gmail.com>

Best regards,
Jernej



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

* Re: [PATCH 5/6] pinctrl: sunxi: Make some layout parameters dynamic
@ 2022-07-02 20:33     ` Jernej Škrabec
  0 siblings, 0 replies; 56+ messages in thread
From: Jernej Škrabec @ 2022-07-02 20:33 UTC (permalink / raw)
  To: Chen-Yu Tsai, Linus Walleij, Samuel Holland
  Cc: Samuel Holland, Krzysztof Kozlowski, Maxime Ripard,
	Ondrej Jirman, Rob Herring, devicetree, linux-arm-kernel,
	linux-gpio, linux-kernel, linux-sunxi

Dne nedelja, 26. junij 2022 ob 04:11:46 CEST je Samuel Holland napisal(a):
> Starting with the D1/D1s/T113 SoC, Allwinner changed the layout of the
> pinctrl registers. This new layout widens the drive level field, which
> affects the pull register offset and the overall bank size.
> 
> In order to support multiple register layouts, some of the layout
> parameters need to be set based on the pinctrl variant. This requires
> passing the pinctrl struct pointer to the register/offset calculation
> functions.
> 
> Signed-off-by: Samuel Holland <samuel@sholland.org>

Reviewed-by: Jernej Skrabec <jernej.skrabec@gmail.com>

Best regards,
Jernej



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

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

* Re: [PATCH 6/6] pinctrl: sunxi: Add driver for Allwinner D1/D1s
  2022-07-02 15:43       ` Samuel Holland
@ 2022-07-04  9:42         ` Andre Przywara
  -1 siblings, 0 replies; 56+ messages in thread
From: Andre Przywara @ 2022-07-04  9:42 UTC (permalink / raw)
  To: Samuel Holland
  Cc: Chen-Yu Tsai, Jernej Skrabec, Linus Walleij, Krzysztof Kozlowski,
	Maxime Ripard, Ondrej Jirman, Rob Herring, devicetree,
	linux-arm-kernel, linux-gpio, linux-kernel, linux-sunxi,
	Heiko Stuebner

On Sat, 2 Jul 2022 10:43:05 -0500
Samuel Holland <samuel@sholland.org> wrote:

Hi Samuel,

> On 7/2/22 9:47 AM, Andre Przywara wrote:
> > On Sat, 25 Jun 2022 21:11:47 -0500
> > Samuel Holland <samuel@sholland.org> wrote:
> > 
> > Hi Samuel,
> >   
> >> These SoCs contain a pinctrl with a new register layout. Use the variant
> >> parameter to set the right register offsets. This pinctrl also increases
> >> the number of functions per pin from 8 to 16, taking advantage of all 4
> >> bits in the mux config field (so far, only functions 0-8 and 14-15 are
> >> used). This increases the maximum possible number of functions.
> >>
> >> D1s is a low pin count version of the D1 SoC, with some pins omitted.
> >> The remaining pins have the same function assignments as D1.  
> > 
> > So do we actually need this extra variant, if there are no conflicts?
> > The D1s seems to be a simple subset of the D1. I think we followed the
> > same approach for the H616 already, where there are more pins in the
> > pinctrl driver than the manual describes, and which are used in other
> > package variants, like the T507.
> > In case of the H616, those pins are there, you can program them (which
> > is not the case for not implemented pins otherwise), they are just not
> > connected to the package.
> > I would expect a DT to never reference them, and even if, it doesn't do
> > any harm other than just not working.  
> 
> I am following the example of V3/V3s here, so it seems we are inconsistent on
> this point. I needed to supply one variant for the register layout anyway, so I
> though I might as well be "accurate".
> 
> But with Allwinner releasing lots of packages per die, it is probably overkill
> to have a separate compatible per packge. As you note, there is no harm in
> configuring pins that do not map to any pad.

Yes, thanks, that current inflation of SoC variants is what I was
concerned about.

> Some notes for completeness:
>  - D1 documents all three JTAG functions (ARM, RISC-V, and DSP), although the
> ARM JTAG does not work.
>  - D1s/F133 only documents the RISC-V JTAG function.
>  - T113 only documents the ARM and DSP JTAG functions.
>  - T113 adds a CAN function on mux 8 of PB2-PB5. The CAN controller accidentally
> made it in to one version of the D1 datasheet, so it may unofficially exist there.

Have you checked whether the CAN peripheral registers are there, on the D1?

One more thing below:

> None of these variations are conflicting.
> 
> > For the table below: I checked every pin against the D1 manual (yes,
> > that took an hour), and found only one small issue and some nits in
> > PortE, see inline.
> >   
> >> Signed-off-by: Samuel Holland <samuel@sholland.org>
> >> ---
> >>
> >>  drivers/pinctrl/sunxi/Kconfig             |   5 +
> >>  drivers/pinctrl/sunxi/Makefile            |   1 +
> >>  drivers/pinctrl/sunxi/pinctrl-sun20i-d1.c | 860 ++++++++++++++++++++++
> >>  drivers/pinctrl/sunxi/pinctrl-sunxi.c     |  16 +-
> >>  drivers/pinctrl/sunxi/pinctrl-sunxi.h     |   7 +
> >>  5 files changed, 884 insertions(+), 5 deletions(-)
> >>  create mode 100644 drivers/pinctrl/sunxi/pinctrl-sun20i-d1.c
> >>
> >> diff --git a/drivers/pinctrl/sunxi/Kconfig b/drivers/pinctrl/sunxi/Kconfig
> >> index 33751a6a0757..a6ac1c1f2585 100644
> >> --- a/drivers/pinctrl/sunxi/Kconfig
> >> +++ b/drivers/pinctrl/sunxi/Kconfig
> >> @@ -84,6 +84,11 @@ config PINCTRL_SUN9I_A80_R
> >>  	depends on RESET_CONTROLLER
> >>  	select PINCTRL_SUNXI
> >>  
> >> +config PINCTRL_SUN20I_D1
> >> +	bool "Support for the Allwinner D1 PIO"
> >> +	default RISCV && ARCH_SUNXI

Is there any chance you can add the "MACH_SUN8I || " already?
Not that it is really surprising, but I explicitly compared the pin mux
overview tables of the R528(ARMv7) and D1(RISC-V) manuals, and they are
identical. So we just use the D1 compatible string as a fallback for the
R528 and T113 parts, in which case the driver should be build for ARM, too.

Cheers,
Andre

> >> +	select PINCTRL_SUNXI
> >> +
> >>  config PINCTRL_SUN50I_A64
> >>  	bool "Support for the Allwinner A64 PIO"
> >>  	default ARM64 && ARCH_SUNXI
> >> diff --git a/drivers/pinctrl/sunxi/Makefile b/drivers/pinctrl/sunxi/Makefile
> >> index d3440c42b9d6..2ff5a55927ad 100644
> >> --- a/drivers/pinctrl/sunxi/Makefile
> >> +++ b/drivers/pinctrl/sunxi/Makefile
> >> @@ -20,6 +20,7 @@ obj-$(CONFIG_PINCTRL_SUN8I_A83T_R)	+= pinctrl-sun8i-a83t-r.o
> >>  obj-$(CONFIG_PINCTRL_SUN8I_H3)		+= pinctrl-sun8i-h3.o
> >>  obj-$(CONFIG_PINCTRL_SUN8I_H3_R)	+= pinctrl-sun8i-h3-r.o
> >>  obj-$(CONFIG_PINCTRL_SUN8I_V3S)		+= pinctrl-sun8i-v3s.o
> >> +obj-$(CONFIG_PINCTRL_SUN20I_D1)		+= pinctrl-sun20i-d1.o
> >>  obj-$(CONFIG_PINCTRL_SUN50I_H5)		+= pinctrl-sun50i-h5.o
> >>  obj-$(CONFIG_PINCTRL_SUN50I_H6)		+= pinctrl-sun50i-h6.o
> >>  obj-$(CONFIG_PINCTRL_SUN50I_H6_R)	+= pinctrl-sun50i-h6-r.o
> >> diff --git a/drivers/pinctrl/sunxi/pinctrl-sun20i-d1.c b/drivers/pinctrl/sunxi/pinctrl-sun20i-d1.c
> >> new file mode 100644
> >> index 000000000000..7247c1f1d92c
> >> --- /dev/null
> >> +++ b/drivers/pinctrl/sunxi/pinctrl-sun20i-d1.c
> >> @@ -0,0 +1,860 @@
> >> +// SPDX-License-Identifier: GPL-2.0
> >> +/*
> >> + * Allwinner D1 SoC pinctrl driver.
> >> + *
> >> + * Copyright (c) 2020 wuyan@allwinnertech.com
> >> + * Copyright (c) 2021-2022 Samuel Holland <samuel@sholland.org>
> >> + */
> >> +
> >> +#include <linux/module.h>
> >> +#include <linux/platform_device.h>
> >> +#include <linux/of.h>
> >> +#include <linux/of_device.h>
> >> +#include <linux/pinctrl/pinctrl.h>
> >> +
> >> +#include "pinctrl-sunxi.h"
> >> +
> >> +static const struct sunxi_desc_pin d1_pins[] = {
> >> +	/* PB */
> >> +	SUNXI_PIN_VARIANT(SUNXI_PINCTRL_PIN(B, 0),
> >> +		PINCTRL_SUN20I_D1,
> >> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> >> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> >> +		SUNXI_FUNCTION(0x2, "pwm"),  
> > 
> > The manual mentions the PWM channel number in the pin name, and it
> > seems like in other pinctrl drivers we use the number either in the
> > function name, or at least in the comment.
> > Shall we do one of them here as well?  
> 
> I originally had the numbers in the function name, but then I realized that no
> pin has multiple PWM muxes, so I removed them. As you mention, other drivers
> have them, so I will add them back.
> 
> > And the mux numbers for pwm are all over the place, so lets hope we
> > never need pwm in U-Boot ;-)  
> 
> PWM is used for the CPU voltage regulator on at least one board (Nezha), but I
> think we can get away without U-Boot support for that. And including the PWM
> number in the function name will improve things somewhat.
> 
> I will fix the typos you noted below.
> 
> Regards,
> Samuel


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

* Re: [PATCH 6/6] pinctrl: sunxi: Add driver for Allwinner D1/D1s
@ 2022-07-04  9:42         ` Andre Przywara
  0 siblings, 0 replies; 56+ messages in thread
From: Andre Przywara @ 2022-07-04  9:42 UTC (permalink / raw)
  To: Samuel Holland
  Cc: Chen-Yu Tsai, Jernej Skrabec, Linus Walleij, Krzysztof Kozlowski,
	Maxime Ripard, Ondrej Jirman, Rob Herring, devicetree,
	linux-arm-kernel, linux-gpio, linux-kernel, linux-sunxi,
	Heiko Stuebner

On Sat, 2 Jul 2022 10:43:05 -0500
Samuel Holland <samuel@sholland.org> wrote:

Hi Samuel,

> On 7/2/22 9:47 AM, Andre Przywara wrote:
> > On Sat, 25 Jun 2022 21:11:47 -0500
> > Samuel Holland <samuel@sholland.org> wrote:
> > 
> > Hi Samuel,
> >   
> >> These SoCs contain a pinctrl with a new register layout. Use the variant
> >> parameter to set the right register offsets. This pinctrl also increases
> >> the number of functions per pin from 8 to 16, taking advantage of all 4
> >> bits in the mux config field (so far, only functions 0-8 and 14-15 are
> >> used). This increases the maximum possible number of functions.
> >>
> >> D1s is a low pin count version of the D1 SoC, with some pins omitted.
> >> The remaining pins have the same function assignments as D1.  
> > 
> > So do we actually need this extra variant, if there are no conflicts?
> > The D1s seems to be a simple subset of the D1. I think we followed the
> > same approach for the H616 already, where there are more pins in the
> > pinctrl driver than the manual describes, and which are used in other
> > package variants, like the T507.
> > In case of the H616, those pins are there, you can program them (which
> > is not the case for not implemented pins otherwise), they are just not
> > connected to the package.
> > I would expect a DT to never reference them, and even if, it doesn't do
> > any harm other than just not working.  
> 
> I am following the example of V3/V3s here, so it seems we are inconsistent on
> this point. I needed to supply one variant for the register layout anyway, so I
> though I might as well be "accurate".
> 
> But with Allwinner releasing lots of packages per die, it is probably overkill
> to have a separate compatible per packge. As you note, there is no harm in
> configuring pins that do not map to any pad.

Yes, thanks, that current inflation of SoC variants is what I was
concerned about.

> Some notes for completeness:
>  - D1 documents all three JTAG functions (ARM, RISC-V, and DSP), although the
> ARM JTAG does not work.
>  - D1s/F133 only documents the RISC-V JTAG function.
>  - T113 only documents the ARM and DSP JTAG functions.
>  - T113 adds a CAN function on mux 8 of PB2-PB5. The CAN controller accidentally
> made it in to one version of the D1 datasheet, so it may unofficially exist there.

Have you checked whether the CAN peripheral registers are there, on the D1?

One more thing below:

> None of these variations are conflicting.
> 
> > For the table below: I checked every pin against the D1 manual (yes,
> > that took an hour), and found only one small issue and some nits in
> > PortE, see inline.
> >   
> >> Signed-off-by: Samuel Holland <samuel@sholland.org>
> >> ---
> >>
> >>  drivers/pinctrl/sunxi/Kconfig             |   5 +
> >>  drivers/pinctrl/sunxi/Makefile            |   1 +
> >>  drivers/pinctrl/sunxi/pinctrl-sun20i-d1.c | 860 ++++++++++++++++++++++
> >>  drivers/pinctrl/sunxi/pinctrl-sunxi.c     |  16 +-
> >>  drivers/pinctrl/sunxi/pinctrl-sunxi.h     |   7 +
> >>  5 files changed, 884 insertions(+), 5 deletions(-)
> >>  create mode 100644 drivers/pinctrl/sunxi/pinctrl-sun20i-d1.c
> >>
> >> diff --git a/drivers/pinctrl/sunxi/Kconfig b/drivers/pinctrl/sunxi/Kconfig
> >> index 33751a6a0757..a6ac1c1f2585 100644
> >> --- a/drivers/pinctrl/sunxi/Kconfig
> >> +++ b/drivers/pinctrl/sunxi/Kconfig
> >> @@ -84,6 +84,11 @@ config PINCTRL_SUN9I_A80_R
> >>  	depends on RESET_CONTROLLER
> >>  	select PINCTRL_SUNXI
> >>  
> >> +config PINCTRL_SUN20I_D1
> >> +	bool "Support for the Allwinner D1 PIO"
> >> +	default RISCV && ARCH_SUNXI

Is there any chance you can add the "MACH_SUN8I || " already?
Not that it is really surprising, but I explicitly compared the pin mux
overview tables of the R528(ARMv7) and D1(RISC-V) manuals, and they are
identical. So we just use the D1 compatible string as a fallback for the
R528 and T113 parts, in which case the driver should be build for ARM, too.

Cheers,
Andre

> >> +	select PINCTRL_SUNXI
> >> +
> >>  config PINCTRL_SUN50I_A64
> >>  	bool "Support for the Allwinner A64 PIO"
> >>  	default ARM64 && ARCH_SUNXI
> >> diff --git a/drivers/pinctrl/sunxi/Makefile b/drivers/pinctrl/sunxi/Makefile
> >> index d3440c42b9d6..2ff5a55927ad 100644
> >> --- a/drivers/pinctrl/sunxi/Makefile
> >> +++ b/drivers/pinctrl/sunxi/Makefile
> >> @@ -20,6 +20,7 @@ obj-$(CONFIG_PINCTRL_SUN8I_A83T_R)	+= pinctrl-sun8i-a83t-r.o
> >>  obj-$(CONFIG_PINCTRL_SUN8I_H3)		+= pinctrl-sun8i-h3.o
> >>  obj-$(CONFIG_PINCTRL_SUN8I_H3_R)	+= pinctrl-sun8i-h3-r.o
> >>  obj-$(CONFIG_PINCTRL_SUN8I_V3S)		+= pinctrl-sun8i-v3s.o
> >> +obj-$(CONFIG_PINCTRL_SUN20I_D1)		+= pinctrl-sun20i-d1.o
> >>  obj-$(CONFIG_PINCTRL_SUN50I_H5)		+= pinctrl-sun50i-h5.o
> >>  obj-$(CONFIG_PINCTRL_SUN50I_H6)		+= pinctrl-sun50i-h6.o
> >>  obj-$(CONFIG_PINCTRL_SUN50I_H6_R)	+= pinctrl-sun50i-h6-r.o
> >> diff --git a/drivers/pinctrl/sunxi/pinctrl-sun20i-d1.c b/drivers/pinctrl/sunxi/pinctrl-sun20i-d1.c
> >> new file mode 100644
> >> index 000000000000..7247c1f1d92c
> >> --- /dev/null
> >> +++ b/drivers/pinctrl/sunxi/pinctrl-sun20i-d1.c
> >> @@ -0,0 +1,860 @@
> >> +// SPDX-License-Identifier: GPL-2.0
> >> +/*
> >> + * Allwinner D1 SoC pinctrl driver.
> >> + *
> >> + * Copyright (c) 2020 wuyan@allwinnertech.com
> >> + * Copyright (c) 2021-2022 Samuel Holland <samuel@sholland.org>
> >> + */
> >> +
> >> +#include <linux/module.h>
> >> +#include <linux/platform_device.h>
> >> +#include <linux/of.h>
> >> +#include <linux/of_device.h>
> >> +#include <linux/pinctrl/pinctrl.h>
> >> +
> >> +#include "pinctrl-sunxi.h"
> >> +
> >> +static const struct sunxi_desc_pin d1_pins[] = {
> >> +	/* PB */
> >> +	SUNXI_PIN_VARIANT(SUNXI_PINCTRL_PIN(B, 0),
> >> +		PINCTRL_SUN20I_D1,
> >> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> >> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> >> +		SUNXI_FUNCTION(0x2, "pwm"),  
> > 
> > The manual mentions the PWM channel number in the pin name, and it
> > seems like in other pinctrl drivers we use the number either in the
> > function name, or at least in the comment.
> > Shall we do one of them here as well?  
> 
> I originally had the numbers in the function name, but then I realized that no
> pin has multiple PWM muxes, so I removed them. As you mention, other drivers
> have them, so I will add them back.
> 
> > And the mux numbers for pwm are all over the place, so lets hope we
> > never need pwm in U-Boot ;-)  
> 
> PWM is used for the CPU voltage regulator on at least one board (Nezha), but I
> think we can get away without U-Boot support for that. And including the PWM
> number in the function name will improve things somewhat.
> 
> I will fix the typos you noted below.
> 
> Regards,
> Samuel


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

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

* Re: [PATCH 1/6] dt-bindings: pinctrl: Add compatibles for Allwinner D1/D1s
  2022-06-26  2:11   ` Samuel Holland
@ 2022-07-11  8:58     ` Linus Walleij
  -1 siblings, 0 replies; 56+ messages in thread
From: Linus Walleij @ 2022-07-11  8:58 UTC (permalink / raw)
  To: Samuel Holland
  Cc: Chen-Yu Tsai, Jernej Skrabec, Krzysztof Kozlowski, Maxime Ripard,
	Ondrej Jirman, Rob Herring, devicetree, linux-arm-kernel,
	linux-gpio, linux-kernel, linux-sunxi

On Sun, Jun 26, 2022 at 4:11 AM Samuel Holland <samuel@sholland.org> wrote:

> D1 contains a pin controller similar to previous SoCs, but with some
> register layout changes. It includes 6 interrupt-capable pin banks.
>
> D1s is a low pin count version of the D1 SoC, with some pins omitted.
> The remaining pins have the same function assignments as D1.
>
> Signed-off-by: Samuel Holland <samuel@sholland.org>

All 6 patches applied to the pinctrl tree, the last patch 6/6
required some fuzzing so please check the result!

Yours,
Linus Walleij

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

* Re: [PATCH 1/6] dt-bindings: pinctrl: Add compatibles for Allwinner D1/D1s
@ 2022-07-11  8:58     ` Linus Walleij
  0 siblings, 0 replies; 56+ messages in thread
From: Linus Walleij @ 2022-07-11  8:58 UTC (permalink / raw)
  To: Samuel Holland
  Cc: Chen-Yu Tsai, Jernej Skrabec, Krzysztof Kozlowski, Maxime Ripard,
	Ondrej Jirman, Rob Herring, devicetree, linux-arm-kernel,
	linux-gpio, linux-kernel, linux-sunxi

On Sun, Jun 26, 2022 at 4:11 AM Samuel Holland <samuel@sholland.org> wrote:

> D1 contains a pin controller similar to previous SoCs, but with some
> register layout changes. It includes 6 interrupt-capable pin banks.
>
> D1s is a low pin count version of the D1 SoC, with some pins omitted.
> The remaining pins have the same function assignments as D1.
>
> Signed-off-by: Samuel Holland <samuel@sholland.org>

All 6 patches applied to the pinctrl tree, the last patch 6/6
required some fuzzing so please check the result!

Yours,
Linus Walleij

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

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

* Re: [PATCH 1/6] dt-bindings: pinctrl: Add compatibles for Allwinner D1/D1s
  2022-07-11  8:58     ` Linus Walleij
@ 2022-07-12 10:14       ` Samuel Holland
  -1 siblings, 0 replies; 56+ messages in thread
From: Samuel Holland @ 2022-07-12 10:14 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Chen-Yu Tsai, Jernej Skrabec, Krzysztof Kozlowski, Maxime Ripard,
	Ondrej Jirman, Rob Herring, devicetree, linux-arm-kernel,
	linux-gpio, linux-kernel, linux-sunxi, Andre Przywara

Hi Linus,

On 7/11/22 3:58 AM, Linus Walleij wrote:
> On Sun, Jun 26, 2022 at 4:11 AM Samuel Holland <samuel@sholland.org> wrote:
> 
>> D1 contains a pin controller similar to previous SoCs, but with some
>> register layout changes. It includes 6 interrupt-capable pin banks.
>>
>> D1s is a low pin count version of the D1 SoC, with some pins omitted.
>> The remaining pins have the same function assignments as D1.
>>
>> Signed-off-by: Samuel Holland <samuel@sholland.org>
> 
> All 6 patches applied to the pinctrl tree, the last patch 6/6
> required some fuzzing so please check the result!

Somehow the version of patch 6 applied to the pinctrl tree did not include the
new driver source file. It only applied changes to existing files (including the
Makefile reference to the new file).

I also needed to make some minor changes to patch 6 to resolve comments from Andre.

Is it okay if I send a v2 of just patch 6? Or do I need to send a follow-up
based on what was already applied?

Regards,
Samuel

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

* Re: [PATCH 1/6] dt-bindings: pinctrl: Add compatibles for Allwinner D1/D1s
@ 2022-07-12 10:14       ` Samuel Holland
  0 siblings, 0 replies; 56+ messages in thread
From: Samuel Holland @ 2022-07-12 10:14 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Chen-Yu Tsai, Jernej Skrabec, Krzysztof Kozlowski, Maxime Ripard,
	Ondrej Jirman, Rob Herring, devicetree, linux-arm-kernel,
	linux-gpio, linux-kernel, linux-sunxi, Andre Przywara

Hi Linus,

On 7/11/22 3:58 AM, Linus Walleij wrote:
> On Sun, Jun 26, 2022 at 4:11 AM Samuel Holland <samuel@sholland.org> wrote:
> 
>> D1 contains a pin controller similar to previous SoCs, but with some
>> register layout changes. It includes 6 interrupt-capable pin banks.
>>
>> D1s is a low pin count version of the D1 SoC, with some pins omitted.
>> The remaining pins have the same function assignments as D1.
>>
>> Signed-off-by: Samuel Holland <samuel@sholland.org>
> 
> All 6 patches applied to the pinctrl tree, the last patch 6/6
> required some fuzzing so please check the result!

Somehow the version of patch 6 applied to the pinctrl tree did not include the
new driver source file. It only applied changes to existing files (including the
Makefile reference to the new file).

I also needed to make some minor changes to patch 6 to resolve comments from Andre.

Is it okay if I send a v2 of just patch 6? Or do I need to send a follow-up
based on what was already applied?

Regards,
Samuel

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

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

* Re: [PATCH 1/6] dt-bindings: pinctrl: Add compatibles for Allwinner D1/D1s
  2022-07-12 10:14       ` Samuel Holland
@ 2022-07-13  2:56         ` Samuel Holland
  -1 siblings, 0 replies; 56+ messages in thread
From: Samuel Holland @ 2022-07-13  2:56 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Chen-Yu Tsai, Jernej Skrabec, Krzysztof Kozlowski, Maxime Ripard,
	Ondrej Jirman, Rob Herring, devicetree, linux-arm-kernel,
	linux-gpio, linux-kernel, linux-sunxi, Andre Przywara

On 7/12/22 5:14 AM, Samuel Holland wrote:
> Hi Linus,
> 
> On 7/11/22 3:58 AM, Linus Walleij wrote:
>> On Sun, Jun 26, 2022 at 4:11 AM Samuel Holland <samuel@sholland.org> wrote:
>>
>>> D1 contains a pin controller similar to previous SoCs, but with some
>>> register layout changes. It includes 6 interrupt-capable pin banks.
>>>
>>> D1s is a low pin count version of the D1 SoC, with some pins omitted.
>>> The remaining pins have the same function assignments as D1.
>>>
>>> Signed-off-by: Samuel Holland <samuel@sholland.org>
>>
>> All 6 patches applied to the pinctrl tree, the last patch 6/6
>> required some fuzzing so please check the result!

I do not see anything in patch 6 that would have required a 3-way merge, so I
don't understand what the issue was here.

> Somehow the version of patch 6 applied to the pinctrl tree did not include the
> new driver source file. It only applied changes to existing files (including the
> Makefile reference to the new file).
> 
> I also needed to make some minor changes to patch 6 to resolve comments from Andre.
> 
> Is it okay if I send a v2 of just patch 6? Or do I need to send a follow-up
> based on what was already applied?

I sent a v2 of the whole series:

https://lore.kernel.org/linux-gpio/20220713025233.27248-1-samuel@sholland.org/

Please let me know if you want something different.

Regards,
Samuel

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

* Re: [PATCH 1/6] dt-bindings: pinctrl: Add compatibles for Allwinner D1/D1s
@ 2022-07-13  2:56         ` Samuel Holland
  0 siblings, 0 replies; 56+ messages in thread
From: Samuel Holland @ 2022-07-13  2:56 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Chen-Yu Tsai, Jernej Skrabec, Krzysztof Kozlowski, Maxime Ripard,
	Ondrej Jirman, Rob Herring, devicetree, linux-arm-kernel,
	linux-gpio, linux-kernel, linux-sunxi, Andre Przywara

On 7/12/22 5:14 AM, Samuel Holland wrote:
> Hi Linus,
> 
> On 7/11/22 3:58 AM, Linus Walleij wrote:
>> On Sun, Jun 26, 2022 at 4:11 AM Samuel Holland <samuel@sholland.org> wrote:
>>
>>> D1 contains a pin controller similar to previous SoCs, but with some
>>> register layout changes. It includes 6 interrupt-capable pin banks.
>>>
>>> D1s is a low pin count version of the D1 SoC, with some pins omitted.
>>> The remaining pins have the same function assignments as D1.
>>>
>>> Signed-off-by: Samuel Holland <samuel@sholland.org>
>>
>> All 6 patches applied to the pinctrl tree, the last patch 6/6
>> required some fuzzing so please check the result!

I do not see anything in patch 6 that would have required a 3-way merge, so I
don't understand what the issue was here.

> Somehow the version of patch 6 applied to the pinctrl tree did not include the
> new driver source file. It only applied changes to existing files (including the
> Makefile reference to the new file).
> 
> I also needed to make some minor changes to patch 6 to resolve comments from Andre.
> 
> Is it okay if I send a v2 of just patch 6? Or do I need to send a follow-up
> based on what was already applied?

I sent a v2 of the whole series:

https://lore.kernel.org/linux-gpio/20220713025233.27248-1-samuel@sholland.org/

Please let me know if you want something different.

Regards,
Samuel

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

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

end of thread, other threads:[~2022-07-13  2:57 UTC | newest]

Thread overview: 56+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-06-26  2:11 [PATCH 0/6] pinctrl: sunxi: Allwinner D1/D1s support Samuel Holland
2022-06-26  2:11 ` Samuel Holland
2022-06-26  2:11 ` [PATCH 1/6] dt-bindings: pinctrl: Add compatibles for Allwinner D1/D1s Samuel Holland
2022-06-26  2:11   ` Samuel Holland
2022-06-26 10:37   ` Krzysztof Kozlowski
2022-06-26 10:37     ` Krzysztof Kozlowski
2022-07-01 13:02   ` Heiko Stuebner
2022-07-01 13:02     ` Heiko Stuebner
2022-07-11  8:58   ` Linus Walleij
2022-07-11  8:58     ` Linus Walleij
2022-07-12 10:14     ` Samuel Holland
2022-07-12 10:14       ` Samuel Holland
2022-07-13  2:56       ` Samuel Holland
2022-07-13  2:56         ` Samuel Holland
2022-06-26  2:11 ` [PATCH 2/6] pinctrl: sunxi: Add I/O bias setting for H6 R-PIO Samuel Holland
2022-06-26  2:11   ` Samuel Holland
2022-06-27 20:34   ` Jernej Škrabec
2022-06-27 20:34     ` Jernej Škrabec
2022-06-28  3:18     ` Samuel Holland
2022-06-28  3:18       ` Samuel Holland
2022-07-01 13:03   ` Heiko Stuebner
2022-07-01 13:03     ` Heiko Stuebner
2022-06-26  2:11 ` [PATCH 3/6] pinctrl: sunxi: Support the 2.5V I/O bias mode Samuel Holland
2022-06-26  2:11   ` Samuel Holland
2022-06-27 20:43   ` Jernej Škrabec
2022-06-27 20:43     ` Jernej Škrabec
2022-06-28  3:29     ` Samuel Holland
2022-06-28  3:29       ` Samuel Holland
2022-07-02 19:48       ` Jernej Škrabec
2022-07-02 19:48         ` Jernej Škrabec
2022-07-01 13:04   ` Heiko Stuebner
2022-07-01 13:04     ` Heiko Stuebner
2022-06-26  2:11 ` [PATCH 4/6] pinctrl: sunxi: Refactor register/offset calculation Samuel Holland
2022-06-26  2:11   ` Samuel Holland
2022-07-01 13:07   ` Heiko Stuebner
2022-07-01 13:07     ` Heiko Stuebner
2022-07-02 20:29   ` Jernej Škrabec
2022-07-02 20:29     ` Jernej Škrabec
2022-06-26  2:11 ` [PATCH 5/6] pinctrl: sunxi: Make some layout parameters dynamic Samuel Holland
2022-06-26  2:11   ` Samuel Holland
2022-07-01 13:09   ` Heiko Stuebner
2022-07-01 13:09     ` Heiko Stuebner
2022-07-02 20:33   ` Jernej Škrabec
2022-07-02 20:33     ` Jernej Škrabec
2022-06-26  2:11 ` [PATCH 6/6] pinctrl: sunxi: Add driver for Allwinner D1/D1s Samuel Holland
2022-06-26  2:11   ` Samuel Holland
2022-07-01 13:13   ` Heiko Stuebner
2022-07-01 13:13     ` Heiko Stuebner
2022-07-01 15:16     ` Samuel Holland
2022-07-01 15:16       ` Samuel Holland
2022-07-02 14:47   ` Andre Przywara
2022-07-02 14:47     ` Andre Przywara
2022-07-02 15:43     ` Samuel Holland
2022-07-02 15:43       ` Samuel Holland
2022-07-04  9:42       ` Andre Przywara
2022-07-04  9:42         ` Andre Przywara

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.