diff mbox series

[03/12] pinctrl: sunxi: add driver for Allwinner V853.

Message ID 20250110123923.270626-4-szemzo.andras@gmail.com
State New
Headers show
Series Support for Allwinner V853 SoC | expand

Commit Message

András Szemző Jan. 10, 2025, 12:39 p.m. UTC
The V853 family has multiple package variants, from BGA to QFN88.
The latter has co-packaged DRAM and fewer pins, and less features (pin muxes).
All family members can be supported by a single driver, as the available pins
with allowed muxes is the same across the devices.

Signed-off-by: Andras Szemzo <szemzo.andras@gmail.com>
---
 drivers/pinctrl/sunxi/Kconfig              |   5 +
 drivers/pinctrl/sunxi/Makefile             |   1 +
 drivers/pinctrl/sunxi/pinctrl-sun8i-v853.c | 980 +++++++++++++++++++++
 drivers/pinctrl/sunxi/pinctrl-sunxi.h      |   1 +
 4 files changed, 987 insertions(+)
 create mode 100644 drivers/pinctrl/sunxi/pinctrl-sun8i-v853.c

Comments

Linus Walleij Jan. 14, 2025, 2:14 p.m. UTC | #1
On Fri, Jan 10, 2025 at 1:39 PM Andras Szemzo <szemzo.andras@gmail.com> wrote:

> The V853 family has multiple package variants, from BGA to QFN88.
> The latter has co-packaged DRAM and fewer pins, and less features (pin muxes).
> All family members can be supported by a single driver, as the available pins
> with allowed muxes is the same across the devices.
>
> Signed-off-by: Andras Szemzo <szemzo.andras@gmail.com>

Looks good to me, waiting for a review of the bindings before applying,
but I see no problem with the patch as it's just using the core sunxi
infrastructure and any minor issues can be fixed in-tree.

Yours,
Linus Walleij
Andre Przywara Jan. 14, 2025, 2:19 p.m. UTC | #2
On Fri, 10 Jan 2025 13:39:14 +0100
Andras Szemzo <szemzo.andras@gmail.com> wrote:

Hi,

> The V853 family has multiple package variants, from BGA to QFN88.
> The latter has co-packaged DRAM and fewer pins, and less features (pin muxes).
> All family members can be supported by a single driver, as the available pins
> with allowed muxes is the same across the devices.

It depends a bit on the outcome of the discussion on the A523 pinctrl
driver [1], but I think we should use the same approach here (and for
every "new" Allwinner SoC coming up, really): put the pinmux value in the
DT, and get rid of this entire table altogether:
[1]

The SoC specific pinctrl driver would then be very small ([2]), so this
pinctrl support patch here would actually become much smaller.

Just feel a bit sorry for you having created this table, in a tedious and
eye-straining exercise - been there, done that ;-)

Cheers,
Andre

> Signed-off-by: Andras Szemzo <szemzo.andras@gmail.com>
> ---
>  drivers/pinctrl/sunxi/Kconfig              |   5 +
>  drivers/pinctrl/sunxi/Makefile             |   1 +
>  drivers/pinctrl/sunxi/pinctrl-sun8i-v853.c | 980 +++++++++++++++++++++
>  drivers/pinctrl/sunxi/pinctrl-sunxi.h      |   1 +
>  4 files changed, 987 insertions(+)
>  create mode 100644 drivers/pinctrl/sunxi/pinctrl-sun8i-v853.c
> 
> diff --git a/drivers/pinctrl/sunxi/Kconfig b/drivers/pinctrl/sunxi/Kconfig
> index a78fdbbdfc0c..df67310672ac 100644
> --- a/drivers/pinctrl/sunxi/Kconfig
> +++ b/drivers/pinctrl/sunxi/Kconfig
> @@ -86,6 +86,11 @@ config PINCTRL_SUN20I_D1
>  	default MACH_SUN8I || (RISCV && ARCH_SUNXI)
>  	select PINCTRL_SUNXI
>  
> +config PINCTRL_SUN8I_V853
> +        bool "Support for the Allwinner V853 PIO"
> +        default MACH_SUN8I
> +        select PINCTRL_SUNXI
> +
>  config PINCTRL_SUN50I_A64
>  	bool "Support for the Allwinner A64 PIO"
>  	default ARM64 && ARCH_SUNXI
> diff --git a/drivers/pinctrl/sunxi/Makefile b/drivers/pinctrl/sunxi/Makefile
> index 2ff5a55927ad..2042276e85d6 100644
> --- a/drivers/pinctrl/sunxi/Makefile
> +++ b/drivers/pinctrl/sunxi/Makefile
> @@ -28,3 +28,4 @@ obj-$(CONFIG_PINCTRL_SUN50I_H616)	+= pinctrl-sun50i-h616.o
>  obj-$(CONFIG_PINCTRL_SUN50I_H616_R)	+= pinctrl-sun50i-h616-r.o
>  obj-$(CONFIG_PINCTRL_SUN9I_A80)		+= pinctrl-sun9i-a80.o
>  obj-$(CONFIG_PINCTRL_SUN9I_A80_R)	+= pinctrl-sun9i-a80-r.o
> +obj-$(CONFIG_PINCTRL_SUN8I_V853)	+= pinctrl-sun8i-v853.o
> diff --git a/drivers/pinctrl/sunxi/pinctrl-sun8i-v853.c b/drivers/pinctrl/sunxi/pinctrl-sun8i-v853.c
> new file mode 100644
> index 000000000000..62b84404bd14
> --- /dev/null
> +++ b/drivers/pinctrl/sunxi/pinctrl-sun8i-v853.c
> @@ -0,0 +1,980 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Allwinner V853 SoC pinctrl driver.
> + *
> + * Copyright (c) 2016-2021  weidonghui <weidonghui@allwinnertech.com>
> + * Copyright (c) 2023 Andras Szemzo <szemzo.andras@gmail.com>
> + */
> +
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/of.h>
> +#include <linux/of_device.h>
> +#include <linux/pinctrl/pinctrl.h>
> +#include <linux/io.h>
> +
> +#include "pinctrl-sunxi.h"
> +
> +/* Pin banks are: A C D E F G H I */
> +static const struct sunxi_desc_pin sun8i_v853_pins[] = {
> +
> +	/* bank A */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 0),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "csi"),		/* CKOP */
> +		SUNXI_FUNCTION(0x3, "ncsi"),		/* D8 */
> +		SUNXI_FUNCTION(0x5, "test"),
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 0)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 1),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "csi"),		/* CKON */
> +		SUNXI_FUNCTION(0x3, "ncsi"),		/* D9 */
> +		SUNXI_FUNCTION(0x5, "test"),		/* test */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 1)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 2),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "csi"),		/* D1N */
> +		SUNXI_FUNCTION(0x3, "ncsi"),		/* D10 */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 2)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 3),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "csi"),		/* D1P */
> +		SUNXI_FUNCTION(0x3, "ncsi"),		/* D11 */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 3)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 4),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "csi"),		/* D0P */
> +		SUNXI_FUNCTION(0x3, "ncsi"),		/* D12 */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 4)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 5),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "csi"),		/* D0N */
> +		SUNXI_FUNCTION(0x3, "ncsi"),		/* D13 */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 5)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 6),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "csi"),		/* D0N/D2N */
> +		SUNXI_FUNCTION(0x3, "ncsi"),		/* D14 */
> +		SUNXI_FUNCTION(0x4, "i2c1"),		/* SCK */
> +		SUNXI_FUNCTION(0x5, "pwm0"),
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 6)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 7),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "csi"),		/* D0P/D2P */
> +		SUNXI_FUNCTION(0x3, "ncsi"),		/* D15 */
> +		SUNXI_FUNCTION(0x4, "i2c1"),		/* SDA */
> +		SUNXI_FUNCTION(0x5, "pwm1"),
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 7)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 8),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "csi"),		/* D1N/D3N */
> +		SUNXI_FUNCTION(0x3, "i2c4"),		/* SCK */
> +		SUNXI_FUNCTION(0x4, "i2c3"),		/* SCK */
> +		SUNXI_FUNCTION(0x5, "pwm2"),
> +		SUNXI_FUNCTION(0x6, "uart2"),		/* TX */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 8)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 9),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "csi"),		/* D1P/D3P */
> +		SUNXI_FUNCTION(0x3, "i2c4"),		/* SDA */
> +		SUNXI_FUNCTION(0x4, "i2c3"),		/* SDA */
> +		SUNXI_FUNCTION(0x5, "pwm3"),
> +		SUNXI_FUNCTION(0x6, "uart2"),		/* RX */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 9)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 10),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "csi"),		/* CKON */
> +		SUNXI_FUNCTION(0x3, "ncsi"),		/* HSYNC */
> +		SUNXI_FUNCTION(0x4, "csi_mclk"),	/* MCLK0 */
> +		SUNXI_FUNCTION(0x5, "i2c0"),		/* SCK */
> +		SUNXI_FUNCTION(0x6, "clk"),		/* FANOUT0 */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 10)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 11),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "csi"),		/* CKOP */
> +		SUNXI_FUNCTION(0x3, "ncsi"),		/* VSYNC */
> +		SUNXI_FUNCTION(0x4, "csi_mclk"),	/* MCLK1 */
> +		SUNXI_FUNCTION(0x5, "i2c0"),		/* SDA */
> +		SUNXI_FUNCTION(0x6, "clk"),		/* FANOUT1 */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 11)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 12),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x3, "ncsi"),		/* D0 */
> +		SUNXI_FUNCTION(0x4, "csi_mclk"),	/* MCLK0 */
> +		SUNXI_FUNCTION(0x5, "uart0"),		/* TX */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 12)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 13),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x3, "ncsi"),		/* D1 */
> +		SUNXI_FUNCTION(0x4, "csi_mclk"),	/* MCLK1 */
> +		SUNXI_FUNCTION(0x5, "uart0"),		/* RX */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 13)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 14),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x3, "ncsi"),		/* D2 */
> +		SUNXI_FUNCTION(0x4, "i2c1"),		/* SCK */
> +		SUNXI_FUNCTION(0x5, "clk"),		/* FANOUT0 */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 14)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 15),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x3, "ncsi"),		/* D3 */
> +		SUNXI_FUNCTION(0x4, "i2c1"),		/* SDA */
> +		SUNXI_FUNCTION(0x5, "clk"),		/* FANOUT1 */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 15)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 16),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x3, "ncsi"),		/* D4 */
> +		SUNXI_FUNCTION(0x4, "i2c0"),		/* SCK */
> +		SUNXI_FUNCTION(0x5, "uart3"),		/* TX */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 16)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 17),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x3, "ncsi"),		/* D5 */
> +		SUNXI_FUNCTION(0x4, "i2c0"),		/* SDA */
> +		SUNXI_FUNCTION(0x5, "uart3"),		/* RX */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 17)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 18),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x3, "ncsi"),		/* D6 */
> +		SUNXI_FUNCTION(0x4, "wiegand"),		/* D0	*/
> +		SUNXI_FUNCTION(0x5, "uart3"),		/* RTS */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 18)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 19),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x3, "ncsi"),		/* D7 */
> +		SUNXI_FUNCTION(0x4, "wiegand"),		/* D1	*/
> +		SUNXI_FUNCTION(0x5, "uart3"),		/* CTS */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 19)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 20),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x3, "ncsi"),		/* MCLK */
> +		SUNXI_FUNCTION(0x4, "csi"),		/* SM_VS */
> +		SUNXI_FUNCTION(0x5, "tcon"),		/* TRIG */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 20)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 21),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x3, "ncsi"),		/* PCLK */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 21)),
> +	/* bank C */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 0),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "spif"),		/* CLK */
> +		SUNXI_FUNCTION(0x3, "sdc2"),		/* CLK */
> +		SUNXI_FUNCTION(0x4, "spi0"),		/* CLK */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 0)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 1),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "spif"),		/* CS0 */
> +		SUNXI_FUNCTION(0x3, "sdc2"),		/* CMD */
> +		SUNXI_FUNCTION(0x4, "spi0"),		/* CS0 */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 1)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 2),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "spif"),		/* MOSI_IO0 */
> +		SUNXI_FUNCTION(0x3, "sdc2"),		/* D2 */
> +		SUNXI_FUNCTION(0x4, "spi0"),		/* MOSI */
> +		SUNXI_FUNCTION(0x5, "boot_sel0"),	/* SEL0 */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 2)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 3),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "spif"),		/* MOSI_IO1 */
> +		SUNXI_FUNCTION(0x3, "sdc2"),		/* D1 */
> +		SUNXI_FUNCTION(0x4, "spi0"),		/* MISO */
> +		SUNXI_FUNCTION(0x5, "boot_sel1"),	/* SEL1 */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 3)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 4),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "spif"),		/* WP_IO2 */
> +		SUNXI_FUNCTION(0x3, "sdc2"),		/* D0 */
> +		SUNXI_FUNCTION(0x4, "spi0"),		/* WP */
> +		SUNXI_FUNCTION(0x5, "pwm4"),
> +		SUNXI_FUNCTION(0x6, "i2c1"),		/* SCK */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 4)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 5),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "spif"),		/* HOLD_IO3 */
> +		SUNXI_FUNCTION(0x3, "sdc2"),		/* D3 */
> +		SUNXI_FUNCTION(0x4, "spi0"),		/* HOLD */
> +		SUNXI_FUNCTION(0x5, "pwm4"),
> +		SUNXI_FUNCTION(0x6, "i2c1"),		/* SDA */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 5)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 6),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "spif"),		/* IO4 */
> +		SUNXI_FUNCTION(0x3, "sdc2"),		/* D4 */
> +		SUNXI_FUNCTION(0x4, "spi0"),		/* CSI */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 6)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 7),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "spif"),		/* IO5 */
> +		SUNXI_FUNCTION(0x3, "sdc2"),		/* D5 */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 7)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 8),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "spif"),		/* IO6 */
> +		SUNXI_FUNCTION(0x3, "sdc2"),		/* D6 */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 8)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 9),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "spif"),		/* IO7 */
> +		SUNXI_FUNCTION(0x3, "sdc2"),		/* D7 */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 9)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 10),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "spif"),		/* DQS */
> +		SUNXI_FUNCTION(0x3, "sdc2"),		/* DS */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 10)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 11),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x3, "sdc2"),		/* RTS */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 11)),
> +	/* bank D */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 0),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd"),		/* D2 */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 0)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 1),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd"),		/* D3 */
> +		SUNXI_FUNCTION(0x3, "pwm0"),
> +		SUNXI_FUNCTION(0x4, "emac"),		/* RXD1 */
> +		SUNXI_FUNCTION(0x5, "dsi"),		/* D0N */
> +		SUNXI_FUNCTION(0x6, "spi1"),		/* CS0/CSX */
> +		SUNXI_FUNCTION(0x7, "emac"),		/* TXD0 */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 1)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 2),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd"),		/* D4 */
> +		SUNXI_FUNCTION(0x3, "pwm1"),
> +		SUNXI_FUNCTION(0x4, "emac"),		/* RXD0 */
> +		SUNXI_FUNCTION(0x5, "dsi"),		/* D1P */
> +		SUNXI_FUNCTION(0x6, "spi1"),		/* CLK/SCLK */
> +		SUNXI_FUNCTION(0x7, "emac"),		/* TXD1 */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 2)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 3),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd"),		/* D5 */
> +		SUNXI_FUNCTION(0x3, "pwm2"),
> +		SUNXI_FUNCTION(0x4, "emac"),		/* CRS_DV */
> +		SUNXI_FUNCTION(0x5, "dsi"),		/* D1N */
> +		SUNXI_FUNCTION(0x6, "spi1"),		/* MOSI/SDO */
> +		SUNXI_FUNCTION(0x7, "emac"),		/* RXER */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 3)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 4),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd"),		/* D6 */
> +		SUNXI_FUNCTION(0x3, "pwm3"),
> +		SUNXI_FUNCTION(0x4, "emac"),		/* RXER */
> +		SUNXI_FUNCTION(0x5, "dsi"),		/* D1P */
> +		SUNXI_FUNCTION(0x6, "spi1"),		/* MISO/SDI/TE/DCX */
> +		SUNXI_FUNCTION(0x7, "emac"),		/* CRS_DV */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 4)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 5),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd"),		/* D7 */
> +		SUNXI_FUNCTION(0x3, "pwm4"),
> +		SUNXI_FUNCTION(0x4, "emac"),		/* TXD1 */
> +		SUNXI_FUNCTION(0x5, "dsi"),		/* CKN */
> +		SUNXI_FUNCTION(0x6, "spi1"),		/* HOLD/DCX/WRX */
> +		SUNXI_FUNCTION(0x7, "emac"),		/* RXD1 */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 5)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 6),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd"),		/* D10 */
> +		SUNXI_FUNCTION(0x3, "pwm5"),
> +		SUNXI_FUNCTION(0x4, "emac"),		/* TXD0 */
> +		SUNXI_FUNCTION(0x5, "dsi"),		/* CKP */
> +		SUNXI_FUNCTION(0x6, "spi1"),		/* WP/TE */
> +		SUNXI_FUNCTION(0x7, "emac"),		/* RXD */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 6)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 7),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd"),		/* D11 */
> +		SUNXI_FUNCTION(0x3, "pwm6"),
> +		SUNXI_FUNCTION(0x4, "emac"),		/* TXCK */
> +		SUNXI_FUNCTION(0x5, "dsi"),		/* D2N */
> +		SUNXI_FUNCTION(0x6, "spi1"),		/* CS1 */
> +		SUNXI_FUNCTION(0x7, "emac"),		/* MDC */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 7)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 8),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd"),		/* D12 */
> +		SUNXI_FUNCTION(0x3, "pwm7"),
> +		SUNXI_FUNCTION(0x4, "emac"),		/* TXEN */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 8)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 9),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd"),		/* D13 */
> +		SUNXI_FUNCTION(0x3, "pwm8"),
> +		SUNXI_FUNCTION(0x5, "dsi"),		/* D2P */
> +		SUNXI_FUNCTION(0x7, "emac"),		/* MDIO */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 9)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 10),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd"),		/* D14 */
> +		SUNXI_FUNCTION(0x3, "i2s1"),		/* MCLK */
> +		SUNXI_FUNCTION(0x5, "dsi"),		/* D3N */
> +		SUNXI_FUNCTION(0x7, "emac"),		/* TXEN */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 10)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 11),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd"),		/* D15 */
> +		SUNXI_FUNCTION(0x3, "i2s1"),		/* BCLK */
> +		SUNXI_FUNCTION(0x5, "dsi"),		/* D3P */
> +		SUNXI_FUNCTION(0x7, "emac"),		/* TXCKk */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 11)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 12),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd"),		/* D18 */
> +		SUNXI_FUNCTION(0x3, "i2s1"),		/* LCLK */
> +		SUNXI_FUNCTION(0x5, "dmic"),		/* DATA3 */
> +		SUNXI_FUNCTION(0x7, "pwm11"),
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 12)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 13),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd"),		/* D19 */
> +		SUNXI_FUNCTION(0x3, "i2s1"),		/* DOUT0 */
> +		SUNXI_FUNCTION(0x5, "dmic"),		/* DATA2 */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 13)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 14),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd"),		/* D20 */
> +		SUNXI_FUNCTION(0x3, "i2s1"),		/* DOUT1 */
> +		SUNXI_FUNCTION(0x4, "i2s1"),		/* DIN1 */
> +		SUNXI_FUNCTION(0x5, "dmic"),		/* DATA1 */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 14)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 15),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd"),		/* D21 */
> +		SUNXI_FUNCTION(0x3, "i2s1"),		/* DOUT2 */
> +		SUNXI_FUNCTION(0x4, "i2s1"),		/* DIN2 */
> +		SUNXI_FUNCTION(0x5, "dmic"),		/* DATA0 */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 15)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 16),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd"),		/* D22 */
> +		SUNXI_FUNCTION(0x3, "i2s1"),		/* DOUT3 */
> +		SUNXI_FUNCTION(0x4, "i2s1"),		/* DIN3 */
> +		SUNXI_FUNCTION(0x5, "dmic"),		/* CLK */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 16)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 17),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd"),		/* D23 */
> +		SUNXI_FUNCTION(0x3, "i2s1"),		/* DIN0 */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 17)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 18),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd"),		/* CLK */
> +		SUNXI_FUNCTION(0x4, "emac"),		/* EPHY_25M */
> +		SUNXI_FUNCTION(0x5, "spi2"),		/* CLK */
> +		SUNXI_FUNCTION(0x6, "i2c3"),		/* SCK */
> +		SUNXI_FUNCTION(0x7, "uart2"),		/* TX */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 18)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 19),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd"),		/* DE */
> +		SUNXI_FUNCTION(0x3, "pwm9"),
> +		SUNXI_FUNCTION(0x4, "tcon"),		/* TRIG */
> +		SUNXI_FUNCTION(0x5, "spi2"),		/* MOSI */
> +		SUNXI_FUNCTION(0x6, "i2c3"),		/* SDA */
> +		SUNXI_FUNCTION(0x7, "uart2"),		/* RX */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 19)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 20),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd"),		/* HSYNC */
> +		SUNXI_FUNCTION(0x3, "pwm10"),
> +		SUNXI_FUNCTION(0x4, "emac"),		/* MDC */
> +		SUNXI_FUNCTION(0x5, "spi2"),		/* MISO */
> +		SUNXI_FUNCTION(0x6, "i2c2"),		/* SCK */
> +		SUNXI_FUNCTION(0x7, "uart2"),		/* RTS */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 20)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 21),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "lcd"),		/* VSYNC */
> +		SUNXI_FUNCTION(0x4, "emac"),		/* MDIO */
> +		SUNXI_FUNCTION(0x5, "spi2"),		/* CS0 */
> +		SUNXI_FUNCTION(0x6, "i2c2"),		/* SDA */
> +		SUNXI_FUNCTION(0x7, "uart2"),		/* CTS */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 21)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 22),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "pwm9"),
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 22)),
> +	/* bank E */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 0),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "ncsi"),		/* PCLK */
> +		SUNXI_FUNCTION(0x3, "emac"),		/* RXD/RXD1 */
> +		SUNXI_FUNCTION(0x4, "i2s1"),		/* MCLK */
> +		SUNXI_FUNCTION(0x5, "pwm0"),
> +		SUNXI_FUNCTION(0x6, "sdc1"),		/* CLK */
> +		SUNXI_FUNCTION(0x7, "uart3"),		/* TX */
> +		SUNXI_FUNCTION(0x8, "i2c3"),		/* SCK */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 0)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 1),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "ncsi"),		/* MCLK */
> +		SUNXI_FUNCTION(0x3, "emac"),		/* RXCK/TXCK */
> +		SUNXI_FUNCTION(0x4, "i2s1"),		/* BCLK */
> +		SUNXI_FUNCTION(0x5, "pwm1"),
> +		SUNXI_FUNCTION(0x6, "sdc1"),		/* CMD */
> +		SUNXI_FUNCTION(0x7, "uart3"),		/* RX */
> +		SUNXI_FUNCTION(0x8, "i2c3"),		/* SDA */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 1)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 2),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "ncsi"),		/* HSYNC */
> +		SUNXI_FUNCTION(0x3, "emac"),		/* RXCTL/CRS_DV */
> +		SUNXI_FUNCTION(0x4, "i2s1"),		/* LCLK */
> +		SUNXI_FUNCTION(0x5, "pwm2"),
> +		SUNXI_FUNCTION(0x6, "sdc1"),		/* D0 */
> +		SUNXI_FUNCTION(0x7, "uart3"),		/* CTS */
> +		SUNXI_FUNCTION(0x8, "i2c1"),		/* SCK */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 2)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 3),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "ncsi"),		/* VSYNC */
> +		SUNXI_FUNCTION(0x3, "emac"),		/* RXD0 */
> +		SUNXI_FUNCTION(0x4, "i2s1"),		/* DIN0 */
> +		SUNXI_FUNCTION(0x5, "pwm3"),
> +		SUNXI_FUNCTION(0x6, "sdc1"),		/* D1 */
> +		SUNXI_FUNCTION(0x7, "uart3"),		/* RTS */
> +		SUNXI_FUNCTION(0x8, "i2c1"),		/* SDA */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 3)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 4),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "ncsi"),		/* D0 */
> +		SUNXI_FUNCTION(0x3, "emac"),		/* TXD0 */
> +		SUNXI_FUNCTION(0x4, "i2s1"),		/* DOUT0 */
> +		SUNXI_FUNCTION(0x5, "pwm4"),
> +		SUNXI_FUNCTION(0x6, "sdc1"),		/* D2 */
> +		SUNXI_FUNCTION(0x7, "i2c3"),		/* SCK */
> +		SUNXI_FUNCTION(0x8, "i2c0"),		/* SCK */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 4)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 5),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "ncsi"),		/* D1 */
> +		SUNXI_FUNCTION(0x3, "emac"),		/* TXD1 */
> +		SUNXI_FUNCTION(0x5, "pwm5"),
> +		SUNXI_FUNCTION(0x6, "sdc1"),		/* D3 */
> +		SUNXI_FUNCTION(0x7, "i2c3"),		/* SDA */
> +		SUNXI_FUNCTION(0x8, "i2c0"),		/* SDA */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 5)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 6),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "ncsi"),		/* D2 */
> +		SUNXI_FUNCTION(0x3, "emac"),		/* TXCTL/TXEN */
> +		SUNXI_FUNCTION(0x4, "lcd"),		/* D2 */
> +		SUNXI_FUNCTION(0x5, "pwm6"),
> +		SUNXI_FUNCTION(0x6, "uart1"),		/* TX */
> +		SUNXI_FUNCTION(0x8, "i2c4"),		/* SCK */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 6)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 7),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "ncsi"),		/* D3 */
> +		SUNXI_FUNCTION(0x3, "emac"),		/* CLKIN/RXER */
> +		SUNXI_FUNCTION(0x4, "lcd"),		/* D15 */
> +		SUNXI_FUNCTION(0x5, "pwm7"),
> +		SUNXI_FUNCTION(0x6, "uart1"),		/* TX */
> +		SUNXI_FUNCTION(0x7, "i2s1"),		/* DOUT0 */
> +		SUNXI_FUNCTION(0x8, "i2c4"),		/* SDA */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 7)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 8),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "ncsi"),		/* D4 */
> +		SUNXI_FUNCTION(0x3, "emac"),		/* MDC */
> +		SUNXI_FUNCTION(0x4, "lcd"),		/* D18 */
> +		SUNXI_FUNCTION(0x5, "pwm8"),
> +		SUNXI_FUNCTION(0x6, "wiegand"),		/* D0 */
> +		SUNXI_FUNCTION(0x7, "i2s1"),		/* DIN0 */
> +		SUNXI_FUNCTION(0x8, "i2c1"),		/* SCK */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 8)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 9),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "ncsi"),		/* D5 */
> +		SUNXI_FUNCTION(0x3, "emac"),		/* MDIO */
> +		SUNXI_FUNCTION(0x4, "lcd"),		/* D19 */
> +		SUNXI_FUNCTION(0x5, "pwm9"),
> +		SUNXI_FUNCTION(0x6, "wiegand"),		/* D1 */
> +		SUNXI_FUNCTION(0x7, "i2s1"),		/* LRCK */
> +		SUNXI_FUNCTION(0x8, "i2c1"),		/* SDA */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 9)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 10),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "ncsi"),		/* D6 */
> +		SUNXI_FUNCTION(0x3, "emac"),		/* EPHY_25M */
> +		SUNXI_FUNCTION(0x4, "lcd"),		/* D20 */
> +		SUNXI_FUNCTION(0x5, "pwm10"),
> +		SUNXI_FUNCTION(0x6, "uart2"),		/* RTS */
> +		SUNXI_FUNCTION(0x7, "i2s1"),		/* BCLK */
> +		SUNXI_FUNCTION(0x8, "wiegand"),		/* D0 */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 10)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 11),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "ncsi"),		/* D7 */
> +		SUNXI_FUNCTION(0x3, "emac"),		/* RXD3 */
> +		SUNXI_FUNCTION(0x4, "lcd"),		/* D21 */
> +		SUNXI_FUNCTION(0x5, "csi"),		/* SM_VS */
> +		SUNXI_FUNCTION(0x6, "uart2"),		/* CTS */
> +		SUNXI_FUNCTION(0x7, "i2s1"),		/* MCLK */
> +		SUNXI_FUNCTION(0x8, "wiegand"),		/* D1 */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 11)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 12),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "ncsi"),		/* D8 */
> +		SUNXI_FUNCTION(0x3, "emac"),		/* RXD2 */
> +		SUNXI_FUNCTION(0x4, "lcd"),		/* D22 */
> +		SUNXI_FUNCTION(0x5, "csi"),		/* MCLK0 */
> +		SUNXI_FUNCTION(0x6, "uart2"),		/* TX */
> +		SUNXI_FUNCTION(0x7, "uart3"),		/* TX */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 12)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 13),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "ncsi"),		/* D9 */
> +		SUNXI_FUNCTION(0x3, "emac"),		/* RXCK */
> +		SUNXI_FUNCTION(0x4, "lcd"),		/* D23 */
> +		SUNXI_FUNCTION(0x5, "csi"),		/* MCLK1 */
> +		SUNXI_FUNCTION(0x6, "uart2"),		/* RX */
> +		SUNXI_FUNCTION(0x7, "uart3"),		/* RX */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 13)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 14),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "ncsi"),		/* D10 */
> +		SUNXI_FUNCTION(0x3, "emac"),		/* TXD3 */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 14)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 15),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "ncsi"),		/* D11 */
> +		SUNXI_FUNCTION(0x3, "emac"),		/* TXD2 */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 15)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 16),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "i2c0"),		/* SCK */
> +		SUNXI_FUNCTION(0x3, "i2c4"),		/* SCK */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 16)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 17),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "i2c0"),		/* SDA */
> +		SUNXI_FUNCTION(0x3, "i2c4"),		/* SDA */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 17)),
> +	/* bank F */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 0),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "sdc0"),		/* D1 */
> +		SUNXI_FUNCTION(0x3, "jtag"),		/* MS */
> +		SUNXI_FUNCTION(0x4, "spi0"),		/* CLK */
> +		SUNXI_FUNCTION(0x5, "spi2"),		/* CLK */
> +		SUNXI_FUNCTION(0x6, "r_jtag"),		/* MS */
> +		SUNXI_FUNCTION(0x7, "cpu"),		/* BIST0 */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 0)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 1),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "sdc0"),		/* D0 */
> +		SUNXI_FUNCTION(0x3, "jtag"),		/* DI */
> +		SUNXI_FUNCTION(0x4, "spi0"),		/* MOSI */
> +		SUNXI_FUNCTION(0x5, "spi2"),		/* MOSI */
> +		SUNXI_FUNCTION(0x6, "r_jtag"),		/* DI */
> +		SUNXI_FUNCTION(0x7, "cpu"),		/* BIST1 */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 1)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 2),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "sdc0"),		/* CLK */
> +		SUNXI_FUNCTION(0x3, "uart0"),		/* TX */
> +		SUNXI_FUNCTION(0x4, "spi0"),		/* MISO */
> +		SUNXI_FUNCTION(0x5, "spi2"),		/* MISO */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 2)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 3),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "sdc0"),		/* CMD */
> +		SUNXI_FUNCTION(0x3, "jtag"),		/* DO */
> +		SUNXI_FUNCTION(0x4, "spi0"),		/* CSO */
> +		SUNXI_FUNCTION(0x5, "spi2"),		/* CS0 */
> +		SUNXI_FUNCTION(0x6, "r_jtag"),		/* DO */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 3)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 4),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "sdc0"),		/* D3 */
> +		SUNXI_FUNCTION(0x3, "uart0"),		/* RX */
> +		SUNXI_FUNCTION(0x4, "spi0"),		/* CS1 */
> +		SUNXI_FUNCTION(0x5, "spi2"),		/* CS1 */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 4)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 5),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "sdc0"),		/* D2 */
> +		SUNXI_FUNCTION(0x3, "jtag"),		/* CK */
> +		SUNXI_FUNCTION(0x6, "r_jtag"),		/* CK */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 5)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 6),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "dbg_clk"),
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 6)),
> +	/* bank G */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 0),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "sdc1"),		/* CLK */
> +		SUNXI_FUNCTION(0x3, "lcd"),		/* D0 */
> +		SUNXI_FUNCTION(0x4, "uart3"),		/* TX */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 0)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 1),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "sdc1"),		/* CMD */
> +		SUNXI_FUNCTION(0x3, "lcd"),		/* D1 */
> +		SUNXI_FUNCTION(0x4, "uart3"),		/* RX */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 1)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 2),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "sdc1"),		/* D0 */
> +		SUNXI_FUNCTION(0x3, "lcd"),		/* D8 */
> +		SUNXI_FUNCTION(0x4, "uart3"),		/* CTS */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 2)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 3),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "sdc1"),		/* D1 */
> +		SUNXI_FUNCTION(0x3, "lcd"),		/* D9 */
> +		SUNXI_FUNCTION(0x4, "uart3"),		/* RTS */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 3)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 4),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "sdc1"),		/* D2 */
> +		SUNXI_FUNCTION(0x3, "lcd"),		/* D16 */
> +		SUNXI_FUNCTION(0x4, "uart1"),		/* RTS */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 4)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 5),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "sdc1"),		/* D3 */
> +		SUNXI_FUNCTION(0x3, "lcd"),		/* D17 */
> +		SUNXI_FUNCTION(0x4, "uart1"),		/* CTS */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 5)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 6),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "i2c4"),		/* SCK */
> +		SUNXI_FUNCTION(0x3, "clk"),		/* FANOUT0 */
> +		SUNXI_FUNCTION(0x4, "uart1"),		/* TX */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 6)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 7),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "i2c4"),		/* SDA */
> +		SUNXI_FUNCTION(0x3, "clk"),		/* FANOUT1 */
> +		SUNXI_FUNCTION(0x4, "uart1"),		/* RX */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 7)),
> +	/* bank H */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 0),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "pwm0"),
> +		SUNXI_FUNCTION(0x3, "i2s0"),		/* MCLK */
> +		SUNXI_FUNCTION(0x4, "spi1"),		/* CLK */
> +		SUNXI_FUNCTION(0x5, "uart3"),		/* TX */
> +		SUNXI_FUNCTION(0x6, "dmic"),		/* DATA3 */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 0)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 1),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "pwm1"),
> +		SUNXI_FUNCTION(0x3, "i2s0"),		/* BCLK */
> +		SUNXI_FUNCTION(0x4, "spi1"),		/* MOSI */
> +		SUNXI_FUNCTION(0x5, "uart3"),		/* RX */
> +		SUNXI_FUNCTION(0x6, "dmic"),		/* DATA2 */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 1)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 2),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "pwm2"),
> +		SUNXI_FUNCTION(0x3, "i2s0"),		/* LRCK */
> +		SUNXI_FUNCTION(0x4, "spi1"),		/* MISO */
> +		SUNXI_FUNCTION(0x5, "uart3"),		/* CTS */
> +		SUNXI_FUNCTION(0x6, "dmic"),		/* DATA1 */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 2)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 3),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "pwm3"),
> +		SUNXI_FUNCTION(0x3, "i2s0"),		/* DOUT0 */
> +		SUNXI_FUNCTION(0x4, "spi1"),		/* CS0 */
> +		SUNXI_FUNCTION(0x5, "uart3"),		/* RTS */
> +		SUNXI_FUNCTION(0x6, "dmic"),		/* DATA0 */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 3)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 4),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "pwm4"),
> +		SUNXI_FUNCTION(0x3, "i2s0"),		/* DIN0 */
> +		SUNXI_FUNCTION(0x4, "spi1"),		/* CS1 */
> +		SUNXI_FUNCTION(0x5, "clk"),		/* FANOUT2 */
> +		SUNXI_FUNCTION(0x6, "dmic"),		/* CLK */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 4)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 5),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "pwm5"),
> +		SUNXI_FUNCTION(0x3, "emac"),		/* RXD1 */
> +		SUNXI_FUNCTION(0x4, "i2c2"),		/* SCK */
> +		SUNXI_FUNCTION(0x5, "uart2"),		/* TX */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 5)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 6),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "pwm6"),
> +		SUNXI_FUNCTION(0x3, "emac"),		/* RXD0 */
> +		SUNXI_FUNCTION(0x4, "i2c2"),		/* SDA */
> +		SUNXI_FUNCTION(0x5, "uart2"),		/* RX */
> +		SUNXI_FUNCTION(0x6, "i2s1"),		/* MCLK */
> +		SUNXI_FUNCTION(0x7, "dmic"),		/* DATA3 */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 6)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 7),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "pwm7"),
> +		SUNXI_FUNCTION(0x3, "emac"),		/* CRS_DV */
> +		SUNXI_FUNCTION(0x4, "uart0"),		/* TX */
> +		SUNXI_FUNCTION(0x5, "uart2"),		/* RTS */
> +		SUNXI_FUNCTION(0x6, "i2s1"),		/* BCLK */
> +		SUNXI_FUNCTION(0x7, "dmic"),		/* DATA2 */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 7)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 8),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "pwm8"),
> +		SUNXI_FUNCTION(0x3, "emac"),		/* RXER */
> +		SUNXI_FUNCTION(0x4, "uart0"),		/* RX */
> +		SUNXI_FUNCTION(0x5, "uart2"),		/* CTS */
> +		SUNXI_FUNCTION(0x6, "i2s1"),		/* LRCK */
> +		SUNXI_FUNCTION(0x7, "dmic"),		/* DATA1 */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 8)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 9),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "pwm9"),
> +		SUNXI_FUNCTION(0x3, "emac"),		/* TXD1 */
> +		SUNXI_FUNCTION(0x4, "i2c3"),		/* SCK */
> +		SUNXI_FUNCTION(0x5, "uart0"),		/* TX */
> +		SUNXI_FUNCTION(0x6, "i2s1"),		/* DIN0 */
> +		SUNXI_FUNCTION(0x7, "dmic"),		/* DATA0 */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 9)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 10),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "pwm10"),
> +		SUNXI_FUNCTION(0x3, "emac"),		/* TXD0 */
> +		SUNXI_FUNCTION(0x4, "i2c3"),		/* SDA */
> +		SUNXI_FUNCTION(0x5, "uart0"),		/* RX */
> +		SUNXI_FUNCTION(0x6, "i2s1"),		/* DOUT0 */
> +		SUNXI_FUNCTION(0x7, "dmic"),		/* CLK */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 10)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 11),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "jtag"),		/* MS */
> +		SUNXI_FUNCTION(0x3, "emac"),		/* TXCK */
> +		SUNXI_FUNCTION(0x4, "r_jtag"),		/* MS */
> +		SUNXI_FUNCTION(0x5, "i2c2"),		/* SCK */
> +		SUNXI_FUNCTION(0x6, "spi3"),		/* CLK */
> +		SUNXI_FUNCTION(0x7, "clk"),		/* FANOUT0 */
> +		SUNXI_FUNCTION(0x8, "pwm4"),
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 11)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 12),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "jtag"),		/* CK */
> +		SUNXI_FUNCTION(0x3, "emac"),		/* TXEN */
> +		SUNXI_FUNCTION(0x4, "r_jtag"),		/* CK */
> +		SUNXI_FUNCTION(0x5, "i2c2"),		/* SDA */
> +		SUNXI_FUNCTION(0x6, "spi3"),		/* MOSI */
> +		SUNXI_FUNCTION(0x7, "clk"),		/* FANOUT1 */
> +		SUNXI_FUNCTION(0x8, "pwm5"),
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 12)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 13),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "jtag"),		/* DO */
> +		SUNXI_FUNCTION(0x3, "emac"),		/* MDC */
> +		SUNXI_FUNCTION(0x4, "r_jtag"),		/* DO */
> +		SUNXI_FUNCTION(0x5, "i2c3"),		/* SCK */
> +		SUNXI_FUNCTION(0x6, "spi3"),		/* MISO */
> +		SUNXI_FUNCTION(0x7, "wiegand"),		/* D0 */
> +		SUNXI_FUNCTION(0x8, "pwm6"),
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 13)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 14),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "jtag"),		/* DI */
> +		SUNXI_FUNCTION(0x3, "emac"),		/* MDIO */
> +		SUNXI_FUNCTION(0x4, "r_jtag"),		/* DI */
> +		SUNXI_FUNCTION(0x5, "i2c3"),		/* SDA */
> +		SUNXI_FUNCTION(0x6, "spi3"),		/* CS0 */
> +		SUNXI_FUNCTION(0x7, "wiegand"),		/* D1 */
> +		SUNXI_FUNCTION(0x8, "pwm7"),
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 14)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 15),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "clk"),		/* FANOUT2 */
> +		SUNXI_FUNCTION(0x3, "ephy_25m"),	/* EPHY_25M */
> +		SUNXI_FUNCTION(0x6, "spi3"),		/* CS1 */
> +		SUNXI_FUNCTION(0x8, "pwm8"),
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 15)),
> +	/* bank I */
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 0),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "csi"),		/* MCLK0 */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 7, 0)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 1),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "csi"),		/* SM_HS */
> +		SUNXI_FUNCTION(0x4, "spi2"),		/* CLK */
> +		SUNXI_FUNCTION(0x5, "i2c1"),		/* SCK */
> +		SUNXI_FUNCTION(0x6, "i2c4"),		/* SCK */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 7, 1)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 2),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x2, "csi"),		/* SM_VS */
> +		SUNXI_FUNCTION(0x3, "tcon"),		/* TRIG */
> +		SUNXI_FUNCTION(0x4, "spi2"),		/* MOSI */
> +		SUNXI_FUNCTION(0x5, "i2c1"),		/* SDA */
> +		SUNXI_FUNCTION(0x6, "i2c4"),		/* SDA */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 7, 2)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 3),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x4, "spi2"),		/* MISO */
> +		SUNXI_FUNCTION(0x5, "i2c0"),		/* SCA */
> +		SUNXI_FUNCTION(0x6, "i2c3"),		/* SCK */
> +		SUNXI_FUNCTION(0x7, "clk"),		/* FANOUT0 */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 7, 3)),
> +	SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 4),
> +		SUNXI_FUNCTION(0x0, "gpio_in"),
> +		SUNXI_FUNCTION(0x1, "gpio_out"),
> +		SUNXI_FUNCTION(0x4, "spi2"),		/* CS0 */
> +		SUNXI_FUNCTION(0x5, "i2c0"),		/* SDA */
> +		SUNXI_FUNCTION(0x6, "i2c3"),		/* SDA */
> +		SUNXI_FUNCTION(0x7, "clk"),		/* FANOUT1 */
> +		SUNXI_FUNCTION_IRQ_BANK(0xe, 7, 4)),
> +};
> +
> +static const unsigned int sun8i_v853_irq_bank_map[] = { 0, 2, 3, 4, 5, 6, 7, 8 };
> +
> +static const struct sunxi_pinctrl_desc sun8i_v853_pinctrl_data = {
> +	.pins = sun8i_v853_pins,
> +	.npins = ARRAY_SIZE(sun8i_v853_pins),
> +	.pin_base = 0,
> +	.irq_banks = ARRAY_SIZE(sun8i_v853_irq_bank_map),
> +	.irq_bank_map = sun8i_v853_irq_bank_map,
> +	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_CTL,
> +};
> +
> +static int sun8i_v853_pinctrl_probe(struct platform_device *pdev)
> +{
> +	unsigned long variant = (unsigned long)of_device_get_match_data(&pdev->dev);
> +
> +	return sunxi_pinctrl_init_with_variant(pdev, &sun8i_v853_pinctrl_data, variant);
> +}
> +
> +static const struct of_device_id sun8i_v853_pinctrl_match[] = {
> +	{
> +		.compatible = "allwinner,sun8i-v853-pinctrl",
> +		.data = (void *)PINCTRL_SUN8I_V853
> +	},
> +	{}
> +};
> +
> +static struct platform_driver sun8i_v853_pinctrl_driver = {
> +	.probe	= sun8i_v853_pinctrl_probe,
> +	.driver	= {
> +		.name		= "sun8i-v853-pinctrl",
> +		.of_match_table	= sun8i_v853_pinctrl_match,
> +	},
> +};
> +builtin_platform_driver(sun8i_v853_pinctrl_driver);
> diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.h b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
> index a87a2f944d60..f4b64f9156f1 100644
> --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.h
> +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
> @@ -94,6 +94,7 @@
>  #define PINCTRL_SUN8I_V3S	BIT(10)
>  /* Variants below here have an updated register layout. */
>  #define PINCTRL_SUN20I_D1	BIT(11)
> +#define PINCTRL_SUN8I_V853	BIT(12)
>  
>  #define PIO_POW_MOD_SEL_REG	0x340
>  #define PIO_POW_MOD_CTL_REG	0x344
Andre Przywara Jan. 14, 2025, 2:30 p.m. UTC | #3
On Tue, 14 Jan 2025 14:19:54 +0000
Andre Przywara <andre.przywara@arm.com> wrote:

Hi,

adding the actual references I hinted at ....

> On Fri, 10 Jan 2025 13:39:14 +0100
> Andras Szemzo <szemzo.andras@gmail.com> wrote:
> 
> Hi,
> 
> > The V853 family has multiple package variants, from BGA to QFN88.
> > The latter has co-packaged DRAM and fewer pins, and less features (pin muxes).
> > All family members can be supported by a single driver, as the available pins
> > with allowed muxes is the same across the devices.  
> 
> It depends a bit on the outcome of the discussion on the A523 pinctrl
> driver [1], but I think we should use the same approach here (and for
> every "new" Allwinner SoC coming up, really): put the pinmux value in the
> DT, and get rid of this entire table altogether:
> [1]

[1]
https://lore.kernel.org/linux-sunxi/20241111005750.13071-5-andre.przywara@arm.com/T/#u

> The SoC specific pinctrl driver would then be very small ([2]), so this
> pinctrl support patch here would actually become much smaller.

[2]
https://lore.kernel.org/linux-sunxi/20241111005750.13071-7-andre.przywara@arm.com/T/#u

Cheers,
Andre

> 
> Just feel a bit sorry for you having created this table, in a tedious and
> eye-straining exercise - been there, done that ;-)
> 
> Cheers,
> Andre
> 
> > Signed-off-by: Andras Szemzo <szemzo.andras@gmail.com>
> > ---
> >  drivers/pinctrl/sunxi/Kconfig              |   5 +
> >  drivers/pinctrl/sunxi/Makefile             |   1 +
> >  drivers/pinctrl/sunxi/pinctrl-sun8i-v853.c | 980 +++++++++++++++++++++
> >  drivers/pinctrl/sunxi/pinctrl-sunxi.h      |   1 +
> >  4 files changed, 987 insertions(+)
> >  create mode 100644 drivers/pinctrl/sunxi/pinctrl-sun8i-v853.c
> > 
> > diff --git a/drivers/pinctrl/sunxi/Kconfig b/drivers/pinctrl/sunxi/Kconfig
> > index a78fdbbdfc0c..df67310672ac 100644
> > --- a/drivers/pinctrl/sunxi/Kconfig
> > +++ b/drivers/pinctrl/sunxi/Kconfig
> > @@ -86,6 +86,11 @@ config PINCTRL_SUN20I_D1
> >  	default MACH_SUN8I || (RISCV && ARCH_SUNXI)
> >  	select PINCTRL_SUNXI
> >  
> > +config PINCTRL_SUN8I_V853
> > +        bool "Support for the Allwinner V853 PIO"
> > +        default MACH_SUN8I
> > +        select PINCTRL_SUNXI
> > +
> >  config PINCTRL_SUN50I_A64
> >  	bool "Support for the Allwinner A64 PIO"
> >  	default ARM64 && ARCH_SUNXI
> > diff --git a/drivers/pinctrl/sunxi/Makefile b/drivers/pinctrl/sunxi/Makefile
> > index 2ff5a55927ad..2042276e85d6 100644
> > --- a/drivers/pinctrl/sunxi/Makefile
> > +++ b/drivers/pinctrl/sunxi/Makefile
> > @@ -28,3 +28,4 @@ obj-$(CONFIG_PINCTRL_SUN50I_H616)	+= pinctrl-sun50i-h616.o
> >  obj-$(CONFIG_PINCTRL_SUN50I_H616_R)	+= pinctrl-sun50i-h616-r.o
> >  obj-$(CONFIG_PINCTRL_SUN9I_A80)		+= pinctrl-sun9i-a80.o
> >  obj-$(CONFIG_PINCTRL_SUN9I_A80_R)	+= pinctrl-sun9i-a80-r.o
> > +obj-$(CONFIG_PINCTRL_SUN8I_V853)	+= pinctrl-sun8i-v853.o
> > diff --git a/drivers/pinctrl/sunxi/pinctrl-sun8i-v853.c b/drivers/pinctrl/sunxi/pinctrl-sun8i-v853.c
> > new file mode 100644
> > index 000000000000..62b84404bd14
> > --- /dev/null
> > +++ b/drivers/pinctrl/sunxi/pinctrl-sun8i-v853.c
> > @@ -0,0 +1,980 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * Allwinner V853 SoC pinctrl driver.
> > + *
> > + * Copyright (c) 2016-2021  weidonghui <weidonghui@allwinnertech.com>
> > + * Copyright (c) 2023 Andras Szemzo <szemzo.andras@gmail.com>
> > + */
> > +
> > +#include <linux/module.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/of.h>
> > +#include <linux/of_device.h>
> > +#include <linux/pinctrl/pinctrl.h>
> > +#include <linux/io.h>
> > +
> > +#include "pinctrl-sunxi.h"
> > +
> > +/* Pin banks are: A C D E F G H I */
> > +static const struct sunxi_desc_pin sun8i_v853_pins[] = {
> > +
> > +	/* bank A */
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 0),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "csi"),		/* CKOP */
> > +		SUNXI_FUNCTION(0x3, "ncsi"),		/* D8 */
> > +		SUNXI_FUNCTION(0x5, "test"),
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 0)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 1),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "csi"),		/* CKON */
> > +		SUNXI_FUNCTION(0x3, "ncsi"),		/* D9 */
> > +		SUNXI_FUNCTION(0x5, "test"),		/* test */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 1)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 2),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "csi"),		/* D1N */
> > +		SUNXI_FUNCTION(0x3, "ncsi"),		/* D10 */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 2)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 3),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "csi"),		/* D1P */
> > +		SUNXI_FUNCTION(0x3, "ncsi"),		/* D11 */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 3)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 4),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "csi"),		/* D0P */
> > +		SUNXI_FUNCTION(0x3, "ncsi"),		/* D12 */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 4)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 5),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "csi"),		/* D0N */
> > +		SUNXI_FUNCTION(0x3, "ncsi"),		/* D13 */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 5)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 6),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "csi"),		/* D0N/D2N */
> > +		SUNXI_FUNCTION(0x3, "ncsi"),		/* D14 */
> > +		SUNXI_FUNCTION(0x4, "i2c1"),		/* SCK */
> > +		SUNXI_FUNCTION(0x5, "pwm0"),
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 6)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 7),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "csi"),		/* D0P/D2P */
> > +		SUNXI_FUNCTION(0x3, "ncsi"),		/* D15 */
> > +		SUNXI_FUNCTION(0x4, "i2c1"),		/* SDA */
> > +		SUNXI_FUNCTION(0x5, "pwm1"),
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 7)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 8),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "csi"),		/* D1N/D3N */
> > +		SUNXI_FUNCTION(0x3, "i2c4"),		/* SCK */
> > +		SUNXI_FUNCTION(0x4, "i2c3"),		/* SCK */
> > +		SUNXI_FUNCTION(0x5, "pwm2"),
> > +		SUNXI_FUNCTION(0x6, "uart2"),		/* TX */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 8)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 9),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "csi"),		/* D1P/D3P */
> > +		SUNXI_FUNCTION(0x3, "i2c4"),		/* SDA */
> > +		SUNXI_FUNCTION(0x4, "i2c3"),		/* SDA */
> > +		SUNXI_FUNCTION(0x5, "pwm3"),
> > +		SUNXI_FUNCTION(0x6, "uart2"),		/* RX */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 9)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 10),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "csi"),		/* CKON */
> > +		SUNXI_FUNCTION(0x3, "ncsi"),		/* HSYNC */
> > +		SUNXI_FUNCTION(0x4, "csi_mclk"),	/* MCLK0 */
> > +		SUNXI_FUNCTION(0x5, "i2c0"),		/* SCK */
> > +		SUNXI_FUNCTION(0x6, "clk"),		/* FANOUT0 */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 10)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 11),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "csi"),		/* CKOP */
> > +		SUNXI_FUNCTION(0x3, "ncsi"),		/* VSYNC */
> > +		SUNXI_FUNCTION(0x4, "csi_mclk"),	/* MCLK1 */
> > +		SUNXI_FUNCTION(0x5, "i2c0"),		/* SDA */
> > +		SUNXI_FUNCTION(0x6, "clk"),		/* FANOUT1 */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 11)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 12),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x3, "ncsi"),		/* D0 */
> > +		SUNXI_FUNCTION(0x4, "csi_mclk"),	/* MCLK0 */
> > +		SUNXI_FUNCTION(0x5, "uart0"),		/* TX */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 12)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 13),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x3, "ncsi"),		/* D1 */
> > +		SUNXI_FUNCTION(0x4, "csi_mclk"),	/* MCLK1 */
> > +		SUNXI_FUNCTION(0x5, "uart0"),		/* RX */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 13)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 14),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x3, "ncsi"),		/* D2 */
> > +		SUNXI_FUNCTION(0x4, "i2c1"),		/* SCK */
> > +		SUNXI_FUNCTION(0x5, "clk"),		/* FANOUT0 */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 14)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 15),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x3, "ncsi"),		/* D3 */
> > +		SUNXI_FUNCTION(0x4, "i2c1"),		/* SDA */
> > +		SUNXI_FUNCTION(0x5, "clk"),		/* FANOUT1 */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 15)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 16),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x3, "ncsi"),		/* D4 */
> > +		SUNXI_FUNCTION(0x4, "i2c0"),		/* SCK */
> > +		SUNXI_FUNCTION(0x5, "uart3"),		/* TX */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 16)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 17),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x3, "ncsi"),		/* D5 */
> > +		SUNXI_FUNCTION(0x4, "i2c0"),		/* SDA */
> > +		SUNXI_FUNCTION(0x5, "uart3"),		/* RX */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 17)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 18),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x3, "ncsi"),		/* D6 */
> > +		SUNXI_FUNCTION(0x4, "wiegand"),		/* D0	*/
> > +		SUNXI_FUNCTION(0x5, "uart3"),		/* RTS */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 18)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 19),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x3, "ncsi"),		/* D7 */
> > +		SUNXI_FUNCTION(0x4, "wiegand"),		/* D1	*/
> > +		SUNXI_FUNCTION(0x5, "uart3"),		/* CTS */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 19)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 20),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x3, "ncsi"),		/* MCLK */
> > +		SUNXI_FUNCTION(0x4, "csi"),		/* SM_VS */
> > +		SUNXI_FUNCTION(0x5, "tcon"),		/* TRIG */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 20)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 21),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x3, "ncsi"),		/* PCLK */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 21)),
> > +	/* bank C */
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 0),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "spif"),		/* CLK */
> > +		SUNXI_FUNCTION(0x3, "sdc2"),		/* CLK */
> > +		SUNXI_FUNCTION(0x4, "spi0"),		/* CLK */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 0)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 1),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "spif"),		/* CS0 */
> > +		SUNXI_FUNCTION(0x3, "sdc2"),		/* CMD */
> > +		SUNXI_FUNCTION(0x4, "spi0"),		/* CS0 */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 1)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 2),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "spif"),		/* MOSI_IO0 */
> > +		SUNXI_FUNCTION(0x3, "sdc2"),		/* D2 */
> > +		SUNXI_FUNCTION(0x4, "spi0"),		/* MOSI */
> > +		SUNXI_FUNCTION(0x5, "boot_sel0"),	/* SEL0 */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 2)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 3),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "spif"),		/* MOSI_IO1 */
> > +		SUNXI_FUNCTION(0x3, "sdc2"),		/* D1 */
> > +		SUNXI_FUNCTION(0x4, "spi0"),		/* MISO */
> > +		SUNXI_FUNCTION(0x5, "boot_sel1"),	/* SEL1 */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 3)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 4),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "spif"),		/* WP_IO2 */
> > +		SUNXI_FUNCTION(0x3, "sdc2"),		/* D0 */
> > +		SUNXI_FUNCTION(0x4, "spi0"),		/* WP */
> > +		SUNXI_FUNCTION(0x5, "pwm4"),
> > +		SUNXI_FUNCTION(0x6, "i2c1"),		/* SCK */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 4)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 5),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "spif"),		/* HOLD_IO3 */
> > +		SUNXI_FUNCTION(0x3, "sdc2"),		/* D3 */
> > +		SUNXI_FUNCTION(0x4, "spi0"),		/* HOLD */
> > +		SUNXI_FUNCTION(0x5, "pwm4"),
> > +		SUNXI_FUNCTION(0x6, "i2c1"),		/* SDA */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 5)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 6),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "spif"),		/* IO4 */
> > +		SUNXI_FUNCTION(0x3, "sdc2"),		/* D4 */
> > +		SUNXI_FUNCTION(0x4, "spi0"),		/* CSI */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 6)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 7),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "spif"),		/* IO5 */
> > +		SUNXI_FUNCTION(0x3, "sdc2"),		/* D5 */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 7)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 8),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "spif"),		/* IO6 */
> > +		SUNXI_FUNCTION(0x3, "sdc2"),		/* D6 */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 8)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 9),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "spif"),		/* IO7 */
> > +		SUNXI_FUNCTION(0x3, "sdc2"),		/* D7 */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 9)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 10),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "spif"),		/* DQS */
> > +		SUNXI_FUNCTION(0x3, "sdc2"),		/* DS */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 10)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 11),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x3, "sdc2"),		/* RTS */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 11)),
> > +	/* bank D */
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 0),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "lcd"),		/* D2 */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 0)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 1),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "lcd"),		/* D3 */
> > +		SUNXI_FUNCTION(0x3, "pwm0"),
> > +		SUNXI_FUNCTION(0x4, "emac"),		/* RXD1 */
> > +		SUNXI_FUNCTION(0x5, "dsi"),		/* D0N */
> > +		SUNXI_FUNCTION(0x6, "spi1"),		/* CS0/CSX */
> > +		SUNXI_FUNCTION(0x7, "emac"),		/* TXD0 */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 1)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 2),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "lcd"),		/* D4 */
> > +		SUNXI_FUNCTION(0x3, "pwm1"),
> > +		SUNXI_FUNCTION(0x4, "emac"),		/* RXD0 */
> > +		SUNXI_FUNCTION(0x5, "dsi"),		/* D1P */
> > +		SUNXI_FUNCTION(0x6, "spi1"),		/* CLK/SCLK */
> > +		SUNXI_FUNCTION(0x7, "emac"),		/* TXD1 */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 2)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 3),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "lcd"),		/* D5 */
> > +		SUNXI_FUNCTION(0x3, "pwm2"),
> > +		SUNXI_FUNCTION(0x4, "emac"),		/* CRS_DV */
> > +		SUNXI_FUNCTION(0x5, "dsi"),		/* D1N */
> > +		SUNXI_FUNCTION(0x6, "spi1"),		/* MOSI/SDO */
> > +		SUNXI_FUNCTION(0x7, "emac"),		/* RXER */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 3)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 4),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "lcd"),		/* D6 */
> > +		SUNXI_FUNCTION(0x3, "pwm3"),
> > +		SUNXI_FUNCTION(0x4, "emac"),		/* RXER */
> > +		SUNXI_FUNCTION(0x5, "dsi"),		/* D1P */
> > +		SUNXI_FUNCTION(0x6, "spi1"),		/* MISO/SDI/TE/DCX */
> > +		SUNXI_FUNCTION(0x7, "emac"),		/* CRS_DV */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 4)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 5),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "lcd"),		/* D7 */
> > +		SUNXI_FUNCTION(0x3, "pwm4"),
> > +		SUNXI_FUNCTION(0x4, "emac"),		/* TXD1 */
> > +		SUNXI_FUNCTION(0x5, "dsi"),		/* CKN */
> > +		SUNXI_FUNCTION(0x6, "spi1"),		/* HOLD/DCX/WRX */
> > +		SUNXI_FUNCTION(0x7, "emac"),		/* RXD1 */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 5)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 6),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "lcd"),		/* D10 */
> > +		SUNXI_FUNCTION(0x3, "pwm5"),
> > +		SUNXI_FUNCTION(0x4, "emac"),		/* TXD0 */
> > +		SUNXI_FUNCTION(0x5, "dsi"),		/* CKP */
> > +		SUNXI_FUNCTION(0x6, "spi1"),		/* WP/TE */
> > +		SUNXI_FUNCTION(0x7, "emac"),		/* RXD */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 6)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 7),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "lcd"),		/* D11 */
> > +		SUNXI_FUNCTION(0x3, "pwm6"),
> > +		SUNXI_FUNCTION(0x4, "emac"),		/* TXCK */
> > +		SUNXI_FUNCTION(0x5, "dsi"),		/* D2N */
> > +		SUNXI_FUNCTION(0x6, "spi1"),		/* CS1 */
> > +		SUNXI_FUNCTION(0x7, "emac"),		/* MDC */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 7)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 8),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "lcd"),		/* D12 */
> > +		SUNXI_FUNCTION(0x3, "pwm7"),
> > +		SUNXI_FUNCTION(0x4, "emac"),		/* TXEN */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 8)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 9),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "lcd"),		/* D13 */
> > +		SUNXI_FUNCTION(0x3, "pwm8"),
> > +		SUNXI_FUNCTION(0x5, "dsi"),		/* D2P */
> > +		SUNXI_FUNCTION(0x7, "emac"),		/* MDIO */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 9)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 10),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "lcd"),		/* D14 */
> > +		SUNXI_FUNCTION(0x3, "i2s1"),		/* MCLK */
> > +		SUNXI_FUNCTION(0x5, "dsi"),		/* D3N */
> > +		SUNXI_FUNCTION(0x7, "emac"),		/* TXEN */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 10)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 11),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "lcd"),		/* D15 */
> > +		SUNXI_FUNCTION(0x3, "i2s1"),		/* BCLK */
> > +		SUNXI_FUNCTION(0x5, "dsi"),		/* D3P */
> > +		SUNXI_FUNCTION(0x7, "emac"),		/* TXCKk */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 11)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 12),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "lcd"),		/* D18 */
> > +		SUNXI_FUNCTION(0x3, "i2s1"),		/* LCLK */
> > +		SUNXI_FUNCTION(0x5, "dmic"),		/* DATA3 */
> > +		SUNXI_FUNCTION(0x7, "pwm11"),
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 12)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 13),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "lcd"),		/* D19 */
> > +		SUNXI_FUNCTION(0x3, "i2s1"),		/* DOUT0 */
> > +		SUNXI_FUNCTION(0x5, "dmic"),		/* DATA2 */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 13)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 14),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "lcd"),		/* D20 */
> > +		SUNXI_FUNCTION(0x3, "i2s1"),		/* DOUT1 */
> > +		SUNXI_FUNCTION(0x4, "i2s1"),		/* DIN1 */
> > +		SUNXI_FUNCTION(0x5, "dmic"),		/* DATA1 */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 14)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 15),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "lcd"),		/* D21 */
> > +		SUNXI_FUNCTION(0x3, "i2s1"),		/* DOUT2 */
> > +		SUNXI_FUNCTION(0x4, "i2s1"),		/* DIN2 */
> > +		SUNXI_FUNCTION(0x5, "dmic"),		/* DATA0 */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 15)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 16),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "lcd"),		/* D22 */
> > +		SUNXI_FUNCTION(0x3, "i2s1"),		/* DOUT3 */
> > +		SUNXI_FUNCTION(0x4, "i2s1"),		/* DIN3 */
> > +		SUNXI_FUNCTION(0x5, "dmic"),		/* CLK */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 16)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 17),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "lcd"),		/* D23 */
> > +		SUNXI_FUNCTION(0x3, "i2s1"),		/* DIN0 */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 17)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 18),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "lcd"),		/* CLK */
> > +		SUNXI_FUNCTION(0x4, "emac"),		/* EPHY_25M */
> > +		SUNXI_FUNCTION(0x5, "spi2"),		/* CLK */
> > +		SUNXI_FUNCTION(0x6, "i2c3"),		/* SCK */
> > +		SUNXI_FUNCTION(0x7, "uart2"),		/* TX */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 18)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 19),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "lcd"),		/* DE */
> > +		SUNXI_FUNCTION(0x3, "pwm9"),
> > +		SUNXI_FUNCTION(0x4, "tcon"),		/* TRIG */
> > +		SUNXI_FUNCTION(0x5, "spi2"),		/* MOSI */
> > +		SUNXI_FUNCTION(0x6, "i2c3"),		/* SDA */
> > +		SUNXI_FUNCTION(0x7, "uart2"),		/* RX */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 19)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 20),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "lcd"),		/* HSYNC */
> > +		SUNXI_FUNCTION(0x3, "pwm10"),
> > +		SUNXI_FUNCTION(0x4, "emac"),		/* MDC */
> > +		SUNXI_FUNCTION(0x5, "spi2"),		/* MISO */
> > +		SUNXI_FUNCTION(0x6, "i2c2"),		/* SCK */
> > +		SUNXI_FUNCTION(0x7, "uart2"),		/* RTS */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 20)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 21),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "lcd"),		/* VSYNC */
> > +		SUNXI_FUNCTION(0x4, "emac"),		/* MDIO */
> > +		SUNXI_FUNCTION(0x5, "spi2"),		/* CS0 */
> > +		SUNXI_FUNCTION(0x6, "i2c2"),		/* SDA */
> > +		SUNXI_FUNCTION(0x7, "uart2"),		/* CTS */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 21)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 22),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "pwm9"),
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 22)),
> > +	/* bank E */
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 0),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "ncsi"),		/* PCLK */
> > +		SUNXI_FUNCTION(0x3, "emac"),		/* RXD/RXD1 */
> > +		SUNXI_FUNCTION(0x4, "i2s1"),		/* MCLK */
> > +		SUNXI_FUNCTION(0x5, "pwm0"),
> > +		SUNXI_FUNCTION(0x6, "sdc1"),		/* CLK */
> > +		SUNXI_FUNCTION(0x7, "uart3"),		/* TX */
> > +		SUNXI_FUNCTION(0x8, "i2c3"),		/* SCK */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 0)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 1),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "ncsi"),		/* MCLK */
> > +		SUNXI_FUNCTION(0x3, "emac"),		/* RXCK/TXCK */
> > +		SUNXI_FUNCTION(0x4, "i2s1"),		/* BCLK */
> > +		SUNXI_FUNCTION(0x5, "pwm1"),
> > +		SUNXI_FUNCTION(0x6, "sdc1"),		/* CMD */
> > +		SUNXI_FUNCTION(0x7, "uart3"),		/* RX */
> > +		SUNXI_FUNCTION(0x8, "i2c3"),		/* SDA */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 1)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 2),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "ncsi"),		/* HSYNC */
> > +		SUNXI_FUNCTION(0x3, "emac"),		/* RXCTL/CRS_DV */
> > +		SUNXI_FUNCTION(0x4, "i2s1"),		/* LCLK */
> > +		SUNXI_FUNCTION(0x5, "pwm2"),
> > +		SUNXI_FUNCTION(0x6, "sdc1"),		/* D0 */
> > +		SUNXI_FUNCTION(0x7, "uart3"),		/* CTS */
> > +		SUNXI_FUNCTION(0x8, "i2c1"),		/* SCK */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 2)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 3),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "ncsi"),		/* VSYNC */
> > +		SUNXI_FUNCTION(0x3, "emac"),		/* RXD0 */
> > +		SUNXI_FUNCTION(0x4, "i2s1"),		/* DIN0 */
> > +		SUNXI_FUNCTION(0x5, "pwm3"),
> > +		SUNXI_FUNCTION(0x6, "sdc1"),		/* D1 */
> > +		SUNXI_FUNCTION(0x7, "uart3"),		/* RTS */
> > +		SUNXI_FUNCTION(0x8, "i2c1"),		/* SDA */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 3)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 4),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "ncsi"),		/* D0 */
> > +		SUNXI_FUNCTION(0x3, "emac"),		/* TXD0 */
> > +		SUNXI_FUNCTION(0x4, "i2s1"),		/* DOUT0 */
> > +		SUNXI_FUNCTION(0x5, "pwm4"),
> > +		SUNXI_FUNCTION(0x6, "sdc1"),		/* D2 */
> > +		SUNXI_FUNCTION(0x7, "i2c3"),		/* SCK */
> > +		SUNXI_FUNCTION(0x8, "i2c0"),		/* SCK */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 4)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 5),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "ncsi"),		/* D1 */
> > +		SUNXI_FUNCTION(0x3, "emac"),		/* TXD1 */
> > +		SUNXI_FUNCTION(0x5, "pwm5"),
> > +		SUNXI_FUNCTION(0x6, "sdc1"),		/* D3 */
> > +		SUNXI_FUNCTION(0x7, "i2c3"),		/* SDA */
> > +		SUNXI_FUNCTION(0x8, "i2c0"),		/* SDA */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 5)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 6),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "ncsi"),		/* D2 */
> > +		SUNXI_FUNCTION(0x3, "emac"),		/* TXCTL/TXEN */
> > +		SUNXI_FUNCTION(0x4, "lcd"),		/* D2 */
> > +		SUNXI_FUNCTION(0x5, "pwm6"),
> > +		SUNXI_FUNCTION(0x6, "uart1"),		/* TX */
> > +		SUNXI_FUNCTION(0x8, "i2c4"),		/* SCK */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 6)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 7),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "ncsi"),		/* D3 */
> > +		SUNXI_FUNCTION(0x3, "emac"),		/* CLKIN/RXER */
> > +		SUNXI_FUNCTION(0x4, "lcd"),		/* D15 */
> > +		SUNXI_FUNCTION(0x5, "pwm7"),
> > +		SUNXI_FUNCTION(0x6, "uart1"),		/* TX */
> > +		SUNXI_FUNCTION(0x7, "i2s1"),		/* DOUT0 */
> > +		SUNXI_FUNCTION(0x8, "i2c4"),		/* SDA */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 7)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 8),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "ncsi"),		/* D4 */
> > +		SUNXI_FUNCTION(0x3, "emac"),		/* MDC */
> > +		SUNXI_FUNCTION(0x4, "lcd"),		/* D18 */
> > +		SUNXI_FUNCTION(0x5, "pwm8"),
> > +		SUNXI_FUNCTION(0x6, "wiegand"),		/* D0 */
> > +		SUNXI_FUNCTION(0x7, "i2s1"),		/* DIN0 */
> > +		SUNXI_FUNCTION(0x8, "i2c1"),		/* SCK */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 8)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 9),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "ncsi"),		/* D5 */
> > +		SUNXI_FUNCTION(0x3, "emac"),		/* MDIO */
> > +		SUNXI_FUNCTION(0x4, "lcd"),		/* D19 */
> > +		SUNXI_FUNCTION(0x5, "pwm9"),
> > +		SUNXI_FUNCTION(0x6, "wiegand"),		/* D1 */
> > +		SUNXI_FUNCTION(0x7, "i2s1"),		/* LRCK */
> > +		SUNXI_FUNCTION(0x8, "i2c1"),		/* SDA */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 9)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 10),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "ncsi"),		/* D6 */
> > +		SUNXI_FUNCTION(0x3, "emac"),		/* EPHY_25M */
> > +		SUNXI_FUNCTION(0x4, "lcd"),		/* D20 */
> > +		SUNXI_FUNCTION(0x5, "pwm10"),
> > +		SUNXI_FUNCTION(0x6, "uart2"),		/* RTS */
> > +		SUNXI_FUNCTION(0x7, "i2s1"),		/* BCLK */
> > +		SUNXI_FUNCTION(0x8, "wiegand"),		/* D0 */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 10)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 11),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "ncsi"),		/* D7 */
> > +		SUNXI_FUNCTION(0x3, "emac"),		/* RXD3 */
> > +		SUNXI_FUNCTION(0x4, "lcd"),		/* D21 */
> > +		SUNXI_FUNCTION(0x5, "csi"),		/* SM_VS */
> > +		SUNXI_FUNCTION(0x6, "uart2"),		/* CTS */
> > +		SUNXI_FUNCTION(0x7, "i2s1"),		/* MCLK */
> > +		SUNXI_FUNCTION(0x8, "wiegand"),		/* D1 */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 11)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 12),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "ncsi"),		/* D8 */
> > +		SUNXI_FUNCTION(0x3, "emac"),		/* RXD2 */
> > +		SUNXI_FUNCTION(0x4, "lcd"),		/* D22 */
> > +		SUNXI_FUNCTION(0x5, "csi"),		/* MCLK0 */
> > +		SUNXI_FUNCTION(0x6, "uart2"),		/* TX */
> > +		SUNXI_FUNCTION(0x7, "uart3"),		/* TX */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 12)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 13),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "ncsi"),		/* D9 */
> > +		SUNXI_FUNCTION(0x3, "emac"),		/* RXCK */
> > +		SUNXI_FUNCTION(0x4, "lcd"),		/* D23 */
> > +		SUNXI_FUNCTION(0x5, "csi"),		/* MCLK1 */
> > +		SUNXI_FUNCTION(0x6, "uart2"),		/* RX */
> > +		SUNXI_FUNCTION(0x7, "uart3"),		/* RX */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 13)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 14),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "ncsi"),		/* D10 */
> > +		SUNXI_FUNCTION(0x3, "emac"),		/* TXD3 */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 14)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 15),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "ncsi"),		/* D11 */
> > +		SUNXI_FUNCTION(0x3, "emac"),		/* TXD2 */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 15)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 16),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "i2c0"),		/* SCK */
> > +		SUNXI_FUNCTION(0x3, "i2c4"),		/* SCK */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 16)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 17),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "i2c0"),		/* SDA */
> > +		SUNXI_FUNCTION(0x3, "i2c4"),		/* SDA */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 17)),
> > +	/* bank F */
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 0),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "sdc0"),		/* D1 */
> > +		SUNXI_FUNCTION(0x3, "jtag"),		/* MS */
> > +		SUNXI_FUNCTION(0x4, "spi0"),		/* CLK */
> > +		SUNXI_FUNCTION(0x5, "spi2"),		/* CLK */
> > +		SUNXI_FUNCTION(0x6, "r_jtag"),		/* MS */
> > +		SUNXI_FUNCTION(0x7, "cpu"),		/* BIST0 */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 0)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 1),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "sdc0"),		/* D0 */
> > +		SUNXI_FUNCTION(0x3, "jtag"),		/* DI */
> > +		SUNXI_FUNCTION(0x4, "spi0"),		/* MOSI */
> > +		SUNXI_FUNCTION(0x5, "spi2"),		/* MOSI */
> > +		SUNXI_FUNCTION(0x6, "r_jtag"),		/* DI */
> > +		SUNXI_FUNCTION(0x7, "cpu"),		/* BIST1 */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 1)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 2),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "sdc0"),		/* CLK */
> > +		SUNXI_FUNCTION(0x3, "uart0"),		/* TX */
> > +		SUNXI_FUNCTION(0x4, "spi0"),		/* MISO */
> > +		SUNXI_FUNCTION(0x5, "spi2"),		/* MISO */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 2)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 3),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "sdc0"),		/* CMD */
> > +		SUNXI_FUNCTION(0x3, "jtag"),		/* DO */
> > +		SUNXI_FUNCTION(0x4, "spi0"),		/* CSO */
> > +		SUNXI_FUNCTION(0x5, "spi2"),		/* CS0 */
> > +		SUNXI_FUNCTION(0x6, "r_jtag"),		/* DO */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 3)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 4),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "sdc0"),		/* D3 */
> > +		SUNXI_FUNCTION(0x3, "uart0"),		/* RX */
> > +		SUNXI_FUNCTION(0x4, "spi0"),		/* CS1 */
> > +		SUNXI_FUNCTION(0x5, "spi2"),		/* CS1 */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 4)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 5),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "sdc0"),		/* D2 */
> > +		SUNXI_FUNCTION(0x3, "jtag"),		/* CK */
> > +		SUNXI_FUNCTION(0x6, "r_jtag"),		/* CK */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 5)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 6),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "dbg_clk"),
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 6)),
> > +	/* bank G */
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 0),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "sdc1"),		/* CLK */
> > +		SUNXI_FUNCTION(0x3, "lcd"),		/* D0 */
> > +		SUNXI_FUNCTION(0x4, "uart3"),		/* TX */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 0)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 1),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "sdc1"),		/* CMD */
> > +		SUNXI_FUNCTION(0x3, "lcd"),		/* D1 */
> > +		SUNXI_FUNCTION(0x4, "uart3"),		/* RX */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 1)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 2),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "sdc1"),		/* D0 */
> > +		SUNXI_FUNCTION(0x3, "lcd"),		/* D8 */
> > +		SUNXI_FUNCTION(0x4, "uart3"),		/* CTS */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 2)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 3),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "sdc1"),		/* D1 */
> > +		SUNXI_FUNCTION(0x3, "lcd"),		/* D9 */
> > +		SUNXI_FUNCTION(0x4, "uart3"),		/* RTS */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 3)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 4),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "sdc1"),		/* D2 */
> > +		SUNXI_FUNCTION(0x3, "lcd"),		/* D16 */
> > +		SUNXI_FUNCTION(0x4, "uart1"),		/* RTS */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 4)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 5),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "sdc1"),		/* D3 */
> > +		SUNXI_FUNCTION(0x3, "lcd"),		/* D17 */
> > +		SUNXI_FUNCTION(0x4, "uart1"),		/* CTS */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 5)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 6),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "i2c4"),		/* SCK */
> > +		SUNXI_FUNCTION(0x3, "clk"),		/* FANOUT0 */
> > +		SUNXI_FUNCTION(0x4, "uart1"),		/* TX */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 6)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 7),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "i2c4"),		/* SDA */
> > +		SUNXI_FUNCTION(0x3, "clk"),		/* FANOUT1 */
> > +		SUNXI_FUNCTION(0x4, "uart1"),		/* RX */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 7)),
> > +	/* bank H */
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 0),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "pwm0"),
> > +		SUNXI_FUNCTION(0x3, "i2s0"),		/* MCLK */
> > +		SUNXI_FUNCTION(0x4, "spi1"),		/* CLK */
> > +		SUNXI_FUNCTION(0x5, "uart3"),		/* TX */
> > +		SUNXI_FUNCTION(0x6, "dmic"),		/* DATA3 */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 0)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 1),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "pwm1"),
> > +		SUNXI_FUNCTION(0x3, "i2s0"),		/* BCLK */
> > +		SUNXI_FUNCTION(0x4, "spi1"),		/* MOSI */
> > +		SUNXI_FUNCTION(0x5, "uart3"),		/* RX */
> > +		SUNXI_FUNCTION(0x6, "dmic"),		/* DATA2 */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 1)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 2),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "pwm2"),
> > +		SUNXI_FUNCTION(0x3, "i2s0"),		/* LRCK */
> > +		SUNXI_FUNCTION(0x4, "spi1"),		/* MISO */
> > +		SUNXI_FUNCTION(0x5, "uart3"),		/* CTS */
> > +		SUNXI_FUNCTION(0x6, "dmic"),		/* DATA1 */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 2)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 3),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "pwm3"),
> > +		SUNXI_FUNCTION(0x3, "i2s0"),		/* DOUT0 */
> > +		SUNXI_FUNCTION(0x4, "spi1"),		/* CS0 */
> > +		SUNXI_FUNCTION(0x5, "uart3"),		/* RTS */
> > +		SUNXI_FUNCTION(0x6, "dmic"),		/* DATA0 */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 3)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 4),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "pwm4"),
> > +		SUNXI_FUNCTION(0x3, "i2s0"),		/* DIN0 */
> > +		SUNXI_FUNCTION(0x4, "spi1"),		/* CS1 */
> > +		SUNXI_FUNCTION(0x5, "clk"),		/* FANOUT2 */
> > +		SUNXI_FUNCTION(0x6, "dmic"),		/* CLK */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 4)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 5),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "pwm5"),
> > +		SUNXI_FUNCTION(0x3, "emac"),		/* RXD1 */
> > +		SUNXI_FUNCTION(0x4, "i2c2"),		/* SCK */
> > +		SUNXI_FUNCTION(0x5, "uart2"),		/* TX */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 5)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 6),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "pwm6"),
> > +		SUNXI_FUNCTION(0x3, "emac"),		/* RXD0 */
> > +		SUNXI_FUNCTION(0x4, "i2c2"),		/* SDA */
> > +		SUNXI_FUNCTION(0x5, "uart2"),		/* RX */
> > +		SUNXI_FUNCTION(0x6, "i2s1"),		/* MCLK */
> > +		SUNXI_FUNCTION(0x7, "dmic"),		/* DATA3 */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 6)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 7),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "pwm7"),
> > +		SUNXI_FUNCTION(0x3, "emac"),		/* CRS_DV */
> > +		SUNXI_FUNCTION(0x4, "uart0"),		/* TX */
> > +		SUNXI_FUNCTION(0x5, "uart2"),		/* RTS */
> > +		SUNXI_FUNCTION(0x6, "i2s1"),		/* BCLK */
> > +		SUNXI_FUNCTION(0x7, "dmic"),		/* DATA2 */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 7)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 8),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "pwm8"),
> > +		SUNXI_FUNCTION(0x3, "emac"),		/* RXER */
> > +		SUNXI_FUNCTION(0x4, "uart0"),		/* RX */
> > +		SUNXI_FUNCTION(0x5, "uart2"),		/* CTS */
> > +		SUNXI_FUNCTION(0x6, "i2s1"),		/* LRCK */
> > +		SUNXI_FUNCTION(0x7, "dmic"),		/* DATA1 */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 8)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 9),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "pwm9"),
> > +		SUNXI_FUNCTION(0x3, "emac"),		/* TXD1 */
> > +		SUNXI_FUNCTION(0x4, "i2c3"),		/* SCK */
> > +		SUNXI_FUNCTION(0x5, "uart0"),		/* TX */
> > +		SUNXI_FUNCTION(0x6, "i2s1"),		/* DIN0 */
> > +		SUNXI_FUNCTION(0x7, "dmic"),		/* DATA0 */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 9)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 10),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "pwm10"),
> > +		SUNXI_FUNCTION(0x3, "emac"),		/* TXD0 */
> > +		SUNXI_FUNCTION(0x4, "i2c3"),		/* SDA */
> > +		SUNXI_FUNCTION(0x5, "uart0"),		/* RX */
> > +		SUNXI_FUNCTION(0x6, "i2s1"),		/* DOUT0 */
> > +		SUNXI_FUNCTION(0x7, "dmic"),		/* CLK */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 10)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 11),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "jtag"),		/* MS */
> > +		SUNXI_FUNCTION(0x3, "emac"),		/* TXCK */
> > +		SUNXI_FUNCTION(0x4, "r_jtag"),		/* MS */
> > +		SUNXI_FUNCTION(0x5, "i2c2"),		/* SCK */
> > +		SUNXI_FUNCTION(0x6, "spi3"),		/* CLK */
> > +		SUNXI_FUNCTION(0x7, "clk"),		/* FANOUT0 */
> > +		SUNXI_FUNCTION(0x8, "pwm4"),
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 11)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 12),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "jtag"),		/* CK */
> > +		SUNXI_FUNCTION(0x3, "emac"),		/* TXEN */
> > +		SUNXI_FUNCTION(0x4, "r_jtag"),		/* CK */
> > +		SUNXI_FUNCTION(0x5, "i2c2"),		/* SDA */
> > +		SUNXI_FUNCTION(0x6, "spi3"),		/* MOSI */
> > +		SUNXI_FUNCTION(0x7, "clk"),		/* FANOUT1 */
> > +		SUNXI_FUNCTION(0x8, "pwm5"),
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 12)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 13),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "jtag"),		/* DO */
> > +		SUNXI_FUNCTION(0x3, "emac"),		/* MDC */
> > +		SUNXI_FUNCTION(0x4, "r_jtag"),		/* DO */
> > +		SUNXI_FUNCTION(0x5, "i2c3"),		/* SCK */
> > +		SUNXI_FUNCTION(0x6, "spi3"),		/* MISO */
> > +		SUNXI_FUNCTION(0x7, "wiegand"),		/* D0 */
> > +		SUNXI_FUNCTION(0x8, "pwm6"),
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 13)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 14),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "jtag"),		/* DI */
> > +		SUNXI_FUNCTION(0x3, "emac"),		/* MDIO */
> > +		SUNXI_FUNCTION(0x4, "r_jtag"),		/* DI */
> > +		SUNXI_FUNCTION(0x5, "i2c3"),		/* SDA */
> > +		SUNXI_FUNCTION(0x6, "spi3"),		/* CS0 */
> > +		SUNXI_FUNCTION(0x7, "wiegand"),		/* D1 */
> > +		SUNXI_FUNCTION(0x8, "pwm7"),
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 14)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 15),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "clk"),		/* FANOUT2 */
> > +		SUNXI_FUNCTION(0x3, "ephy_25m"),	/* EPHY_25M */
> > +		SUNXI_FUNCTION(0x6, "spi3"),		/* CS1 */
> > +		SUNXI_FUNCTION(0x8, "pwm8"),
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 15)),
> > +	/* bank I */
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 0),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "csi"),		/* MCLK0 */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 7, 0)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 1),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "csi"),		/* SM_HS */
> > +		SUNXI_FUNCTION(0x4, "spi2"),		/* CLK */
> > +		SUNXI_FUNCTION(0x5, "i2c1"),		/* SCK */
> > +		SUNXI_FUNCTION(0x6, "i2c4"),		/* SCK */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 7, 1)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 2),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x2, "csi"),		/* SM_VS */
> > +		SUNXI_FUNCTION(0x3, "tcon"),		/* TRIG */
> > +		SUNXI_FUNCTION(0x4, "spi2"),		/* MOSI */
> > +		SUNXI_FUNCTION(0x5, "i2c1"),		/* SDA */
> > +		SUNXI_FUNCTION(0x6, "i2c4"),		/* SDA */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 7, 2)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 3),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x4, "spi2"),		/* MISO */
> > +		SUNXI_FUNCTION(0x5, "i2c0"),		/* SCA */
> > +		SUNXI_FUNCTION(0x6, "i2c3"),		/* SCK */
> > +		SUNXI_FUNCTION(0x7, "clk"),		/* FANOUT0 */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 7, 3)),
> > +	SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 4),
> > +		SUNXI_FUNCTION(0x0, "gpio_in"),
> > +		SUNXI_FUNCTION(0x1, "gpio_out"),
> > +		SUNXI_FUNCTION(0x4, "spi2"),		/* CS0 */
> > +		SUNXI_FUNCTION(0x5, "i2c0"),		/* SDA */
> > +		SUNXI_FUNCTION(0x6, "i2c3"),		/* SDA */
> > +		SUNXI_FUNCTION(0x7, "clk"),		/* FANOUT1 */
> > +		SUNXI_FUNCTION_IRQ_BANK(0xe, 7, 4)),
> > +};
> > +
> > +static const unsigned int sun8i_v853_irq_bank_map[] = { 0, 2, 3, 4, 5, 6, 7, 8 };
> > +
> > +static const struct sunxi_pinctrl_desc sun8i_v853_pinctrl_data = {
> > +	.pins = sun8i_v853_pins,
> > +	.npins = ARRAY_SIZE(sun8i_v853_pins),
> > +	.pin_base = 0,
> > +	.irq_banks = ARRAY_SIZE(sun8i_v853_irq_bank_map),
> > +	.irq_bank_map = sun8i_v853_irq_bank_map,
> > +	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_CTL,
> > +};
> > +
> > +static int sun8i_v853_pinctrl_probe(struct platform_device *pdev)
> > +{
> > +	unsigned long variant = (unsigned long)of_device_get_match_data(&pdev->dev);
> > +
> > +	return sunxi_pinctrl_init_with_variant(pdev, &sun8i_v853_pinctrl_data, variant);
> > +}
> > +
> > +static const struct of_device_id sun8i_v853_pinctrl_match[] = {
> > +	{
> > +		.compatible = "allwinner,sun8i-v853-pinctrl",
> > +		.data = (void *)PINCTRL_SUN8I_V853
> > +	},
> > +	{}
> > +};
> > +
> > +static struct platform_driver sun8i_v853_pinctrl_driver = {
> > +	.probe	= sun8i_v853_pinctrl_probe,
> > +	.driver	= {
> > +		.name		= "sun8i-v853-pinctrl",
> > +		.of_match_table	= sun8i_v853_pinctrl_match,
> > +	},
> > +};
> > +builtin_platform_driver(sun8i_v853_pinctrl_driver);
> > diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.h b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
> > index a87a2f944d60..f4b64f9156f1 100644
> > --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.h
> > +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
> > @@ -94,6 +94,7 @@
> >  #define PINCTRL_SUN8I_V3S	BIT(10)
> >  /* Variants below here have an updated register layout. */
> >  #define PINCTRL_SUN20I_D1	BIT(11)
> > +#define PINCTRL_SUN8I_V853	BIT(12)
> >  
> >  #define PIO_POW_MOD_SEL_REG	0x340
> >  #define PIO_POW_MOD_CTL_REG	0x344  
> 
>
Linus Walleij Jan. 15, 2025, 10:23 a.m. UTC | #4
On Tue, Jan 14, 2025 at 3:20 PM Andre Przywara <andre.przywara@arm.com> wrote:
> Andras Szemzo <szemzo.andras@gmail.com> wrote:

> > The V853 family has multiple package variants, from BGA to QFN88.
> > The latter has co-packaged DRAM and fewer pins, and less features (pin muxes).
> > All family members can be supported by a single driver, as the available pins
> > with allowed muxes is the same across the devices.
>
> It depends a bit on the outcome of the discussion on the A523 pinctrl
> driver [1], but I think we should use the same approach here (and for
> every "new" Allwinner SoC coming up, really): put the pinmux value in the
> DT, and get rid of this entire table altogether:
> [1]
>
> The SoC specific pinctrl driver would then be very small ([2]), so this
> pinctrl support patch here would actually become much smaller.
>
> Just feel a bit sorry for you having created this table, in a tedious and
> eye-straining exercise - been there, done that ;-)

It's pretty stressful for the pin control maintainer as well.
Andre Przywara Jan. 15, 2025, 3:26 p.m. UTC | #5
On Wed, 15 Jan 2025 11:23:50 +0100
Linus Walleij <linus.walleij@linaro.org> wrote:

Hi Linus,

thanks for the reply, I was hoping to get some insight and discuss this!

> On Tue, Jan 14, 2025 at 3:20 PM Andre Przywara <andre.przywara@arm.com> wrote:
> > Andras Szemzo <szemzo.andras@gmail.com> wrote:  
> 
> > > The V853 family has multiple package variants, from BGA to QFN88.
> > > The latter has co-packaged DRAM and fewer pins, and less features (pin muxes).
> > > All family members can be supported by a single driver, as the available pins
> > > with allowed muxes is the same across the devices.  
> >
> > It depends a bit on the outcome of the discussion on the A523 pinctrl
> > driver [1], but I think we should use the same approach here (and for
> > every "new" Allwinner SoC coming up, really): put the pinmux value in the
> > DT, and get rid of this entire table altogether:
> > [1]
> >
> > The SoC specific pinctrl driver would then be very small ([2]), so this
> > pinctrl support patch here would actually become much smaller.
> >
> > Just feel a bit sorry for you having created this table, in a tedious and
> > eye-straining exercise - been there, done that ;-)  
> 
> It's pretty stressful for the pin control maintainer as well.
> 
> From the subsystems point of view, groups matches to functions by
> strings is the best. ("fun1") + ("group1", "group2"):
> 
> pio: pinctrl@1c20800 {
>                         compatible = "allwinner,sun8i-r40-pinctrl";
> (...)
>                         i2c0_pins: i2c0-pins {
>                                 pins = "PB0", "PB1";
>                                 function = "i2c0";
>                         };
> 
> abstract, strings, nice. The driver handles the particulars.

What bugs me about this it that this has quite some seemingly redundant
information (Who would have thought that the i2c0 pins use function
"i2c0"?), but misses out on the actual 4 bits(!) of information.
So the A523 version [1] just *adds* this one property:
		allwinner,pinmux = <2>;

[1]https://lore.kernel.org/linux-sunxi/20241111005750.13071-5-andre.przywara@arm.com/

And we keep all your beloved strings ;-)

> That is like so because we are designing for users which are
> let's say customization engineers. If these engineers jump from
> project to project matching function strings to group strings will
> be a common way to set up pins, and easy to understand and
> grasp, and it makes the DTS very readable.

That's an interesting view, and I see the point of it being easy to read,
but this is partly because it doesn't convey too much actual information,
does it, as it requires another lookup or two.
And the pinctrl group nodes are actually in the .dtsi file, which are
typically written once during the initial SoC enablement, and new board
.dts files normally just reference the existing pingroup nodes. So anyone
dealing with just a new board is not bothered by this.
Also in my experience most people have no problems in understanding the
concept of pinmuxing and that there is a selector number, also where to
find this.

> Then there are the engineers creating the pin control drivers,
> and they want everything to be convinient for *them*, and they
> think an opaque hex digit in the DTS is perfect at times, thus
> pinmux = <0xdeadbeef>;
> 
> Mediatek and STM32 made a compromise by using pinmux
> and adding some macros to define them so it looks more
> pleasant:
> 
>       i2c0_pins_a: i2c0-default {
>                 pins-i2c0 {
>                         pinmux = <MT7623_PIN_75_SDA0_FUNC_SDA0>,
>                                  <MT7623_PIN_76_SCL0_FUNC_SCL0>;

Well, I don't really get why they don't use the (MTK_PIN_NO(75) | 1)
definition directly, seems to be more telling to me?
So the plan for sunxi would be: <SUNXI_PINMUX(PORTC, 23, MUX_1)>, ...
And this would not be really "opaque", since it has a fixed known mapping:
	(port << 16) | (pin << 8) | (mux << 0))
I find this both technically elegant, because it combines all the
information into just one compact cell, but also readable by outsiders,
thanks to the macro.

But please note that using the generic pinmux is just an idea at this
point, last time I checked this would require significant rework in the
sunxi pinctrl driver.
Just adding the "allwinner,pinmux" property on the other hand is a
comparably easy addition, hence my patch, as a compromise.

>                         bias-disable;
>                 };
>         };
> 
> At least the bias control is using strings, this is nice.
> 
> So I'm mostly fine with that as well, but it can be pretty
> heavy on people coming from the outside, asking us questions
> like "on MT7689 how do you mux pin nnnn to function yyy"???
> Well I don't know? Some MT7689_PIN* macro I guess?

MTK_PIN_NO(nnn, yyy)?

> If it was just strings I would know what the
> expected behaviour and looks would be at least, then the driver
> could be buggy or missing things but that's clearly cut. That's
> why I prefer the strings.

My main arguments against the current (string-based) approach:
- They require the mapping table to be in every DT user, so not only the
  Linux kernel, but also U-Boot, FreeBSD, you name it...
https://source.denx.de/u-boot/u-boot/-/blob/master/drivers/pinctrl/sunxi/pinctrl-sunxi.c?ref_type=heads#L236-768
https://cgit.freebsd.org/src/tree/sys/arm/allwinner/h6/h6_padconf.c
- The tables are getting quite large, and they pollute the single image
  Linux kernel, with tons of very specific information for a number of very
  pitiful Allwinner SoCs. At the moment the tally is at 145KB of code+data
  for the existing arm64 SoCs, with the newer SoCs ever growing (H616 alone
  is 27KB, A523 would be quite larger even, I guess 40K). The new A523
  specific pinctrl support adds 872 Bytes.
- Most of the mappings are untested at pinctrl driver commit time, since we
  don't have the device drivers ready yet - by a margin. The new approach
  would add the pinmux values when we need them and can test them.
- The comments in the table give away that something is not quite right:
                  SUNXI_FUNCTION(0x2, "i2c0")),         /* SDA */
  This is just a comment, so has no relevance for the code, but it's not
  meant for humans either. Yet we try to make this correct and maintain
  it. Odd.

Cheers,
Andre
Linus Walleij Jan. 16, 2025, 9:34 a.m. UTC | #6
Hi Andre,

some nice talk here, actually the following is just opinions, I will
be likely happy with whatever approach is taken eventually.

On Wed, Jan 15, 2025 at 4:26 PM Andre Przywara <andre.przywara@arm.com> wrote:

> > pio: pinctrl@1c20800 {
> >                         compatible = "allwinner,sun8i-r40-pinctrl";
> > (...)
> >                         i2c0_pins: i2c0-pins {
> >                                 pins = "PB0", "PB1";
> >                                 function = "i2c0";
> >                         };
> >
> > abstract, strings, nice. The driver handles the particulars.
>
> What bugs me about this it that this has quite some seemingly redundant
> information (Who would have thought that the i2c0 pins use function
> "i2c0"?), but misses out on the actual 4 bits(!) of information.

the pins in this example are called PB0 and PB1 though. The designation
on the package. And often pins actually named "i2c0_1" "i2c0_2" are
for that primary function, but muxable to a few other functions,
at least GPIO in most cases. So it's just some name for the pin
really.

> > That is like so because we are designing for users which are
> > let's say customization engineers. If these engineers jump from
> > project to project matching function strings to group strings will
> > be a common way to set up pins, and easy to understand and
> > grasp, and it makes the DTS very readable.
>
> That's an interesting view, and I see the point of it being easy to read,
> but this is partly because it doesn't convey too much actual information,
> does it, as it requires another lookup or two.
> And the pinctrl group nodes are actually in the .dtsi file, which are
> typically written once during the initial SoC enablement, and new board
> .dts files normally just reference the existing pingroup nodes. So anyone
> dealing with just a new board is not bothered by this.

You have a point, and when working with a system the application
engineer often finds bugs in the pin control driver, and has to go
and fix the actual driver and then all the information hiding and
simplification is moot.

This can become an expensive lesson for the current attempts
to push pin control into firmware where the configuration is
mostly "dead simple" (and just using strings) - the bugs will be
in the firmware instead, and impossible or really hard to fix.

> Also in my experience most people have no problems in understanding the
> concept of pinmuxing and that there is a selector number, also where to
> find this.

Yeah the ambition with the strings was to avoid forcing application
engineers to know all about that. If they do, they are then
developing the driver, not just using it.

> > Mediatek and STM32 made a compromise by using pinmux
> > and adding some macros to define them so it looks more
> > pleasant:
> >
> >       i2c0_pins_a: i2c0-default {
> >                 pins-i2c0 {
> >                         pinmux = <MT7623_PIN_75_SDA0_FUNC_SDA0>,
> >                                  <MT7623_PIN_76_SCL0_FUNC_SCL0>;
>
> Well, I don't really get why they don't use the (MTK_PIN_NO(75) | 1)
> definition directly, seems to be more telling to me?

That's what STM32 does as well and it's usable.

But of course it drives a truck through the initial ambition that pins
on all systems be configured the same way, with strings. So now
there are some families of drivers all "necessarily different" which
is not so nice for people jumping between different SoCs, but
very compelling for people focusing on just one SoC.

Well, unless this way of doing things becomes so prevalent that
it's the new black.

> So the plan for sunxi would be: <SUNXI_PINMUX(PORTC, 23, MUX_1)>, ...
> And this would not be really "opaque", since it has a fixed known mapping:
>         (port << 16) | (pin << 8) | (mux << 0))
> I find this both technically elegant, because it combines all the
> information into just one compact cell, but also readable by outsiders,
> thanks to the macro.

And a new standard, to add to the other standards, so that
is my problem as maintainer. It makes sense on its own, and it
complicates the bigger picture.

> My main arguments against the current (string-based) approach:
> - They require the mapping table to be in every DT user, so not only the
>   Linux kernel, but also U-Boot, FreeBSD, you name it...

That's true.

This comes from the DT ambition to describe hardware and config,
but not *define* hardware, i.e. to stop device tree to turn into
Verilog or SystemC, which is what will happen if we take the
1:1 reflection of hardware to device tree too far.

I don't think anyone really knows where to cut the line.

> - The tables are getting quite large, and they pollute the single image
>   Linux kernel, with tons of very specific information for a number of very
>   pitiful Allwinner SoCs. At the moment the tally is at 145KB of code+data
>   for the existing arm64 SoCs, with the newer SoCs ever growing (H616 alone
>   is 27KB, A523 would be quite larger even, I guess 40K). The new A523
>   specific pinctrl support adds 872 Bytes.

This is a generic problem though, look at GPU drivers.

The community (especially Android) seem set on fixing this by using
modules.

> - Most of the mappings are untested at pinctrl driver commit time, since we
>   don't have the device drivers ready yet - by a margin. The new approach
>   would add the pinmux values when we need them and can test them.

I like this argument the best.

However this also reads "upfront firmware to handle pin control is a
dead end" yet there are people dedicatedly working on exactly that.
(Not that its' the Allwinner developers' problem...)

> - The comments in the table give away that something is not quite right:
>                   SUNXI_FUNCTION(0x2, "i2c0")),         /* SDA */
>   This is just a comment, so has no relevance for the code, but it's not
>   meant for humans either. Yet we try to make this correct and maintain
>   it. Odd.

So i2c0 is SDA and i2c1 is SCL or something?
It seems common, but yeah it can be confusing.

Yours,
Linus Walleij
András Szemző Jan. 17, 2025, 7:25 a.m. UTC | #7
I’ve actually already converted the pinctrl driver to the new dt based pinmux, as Andre
suggested. It’s simple, get rid of those huge pinmux tables, and easy to understand to
add the mux settings to the dtsi.


> On 16 Jan 2025, at 10:34, Linus Walleij <linus.walleij@linaro.org> wrote:
> 
> Hi Andre,
> 
> some nice talk here, actually the following is just opinions, I will
> be likely happy with whatever approach is taken eventually.
> 
> On Wed, Jan 15, 2025 at 4:26 PM Andre Przywara <andre.przywara@arm.com> wrote:
> 
>>> pio: pinctrl@1c20800 {
>>>                        compatible = "allwinner,sun8i-r40-pinctrl";
>>> (...)
>>>                        i2c0_pins: i2c0-pins {
>>>                                pins = "PB0", "PB1";
>>>                                function = "i2c0";
>>>                        };
>>> 
>>> abstract, strings, nice. The driver handles the particulars.
>> 
>> What bugs me about this it that this has quite some seemingly redundant
>> information (Who would have thought that the i2c0 pins use function
>> "i2c0"?), but misses out on the actual 4 bits(!) of information.
> 
> the pins in this example are called PB0 and PB1 though. The designation
> on the package. And often pins actually named "i2c0_1" "i2c0_2" are
> for that primary function, but muxable to a few other functions,
> at least GPIO in most cases. So it's just some name for the pin
> really.
> 
>>> That is like so because we are designing for users which are
>>> let's say customization engineers. If these engineers jump from
>>> project to project matching function strings to group strings will
>>> be a common way to set up pins, and easy to understand and
>>> grasp, and it makes the DTS very readable.
>> 
>> That's an interesting view, and I see the point of it being easy to read,
>> but this is partly because it doesn't convey too much actual information,
>> does it, as it requires another lookup or two.
>> And the pinctrl group nodes are actually in the .dtsi file, which are
>> typically written once during the initial SoC enablement, and new board
>> .dts files normally just reference the existing pingroup nodes. So anyone
>> dealing with just a new board is not bothered by this.
> 
> You have a point, and when working with a system the application
> engineer often finds bugs in the pin control driver, and has to go
> and fix the actual driver and then all the information hiding and
> simplification is moot.
> 
> This can become an expensive lesson for the current attempts
> to push pin control into firmware where the configuration is
> mostly "dead simple" (and just using strings) - the bugs will be
> in the firmware instead, and impossible or really hard to fix.
> 
>> Also in my experience most people have no problems in understanding the
>> concept of pinmuxing and that there is a selector number, also where to
>> find this.
> 
> Yeah the ambition with the strings was to avoid forcing application
> engineers to know all about that. If they do, they are then
> developing the driver, not just using it.
> 
>>> Mediatek and STM32 made a compromise by using pinmux
>>> and adding some macros to define them so it looks more
>>> pleasant:
>>> 
>>>      i2c0_pins_a: i2c0-default {
>>>                pins-i2c0 {
>>>                        pinmux = <MT7623_PIN_75_SDA0_FUNC_SDA0>,
>>>                                 <MT7623_PIN_76_SCL0_FUNC_SCL0>;
>> 
>> Well, I don't really get why they don't use the (MTK_PIN_NO(75) | 1)
>> definition directly, seems to be more telling to me?
> 
> That's what STM32 does as well and it's usable.
> 
> But of course it drives a truck through the initial ambition that pins
> on all systems be configured the same way, with strings. So now
> there are some families of drivers all "necessarily different" which
> is not so nice for people jumping between different SoCs, but
> very compelling for people focusing on just one SoC.
> 
> Well, unless this way of doing things becomes so prevalent that
> it's the new black.
> 
>> So the plan for sunxi would be: <SUNXI_PINMUX(PORTC, 23, MUX_1)>, ...
>> And this would not be really "opaque", since it has a fixed known mapping:
>>        (port << 16) | (pin << 8) | (mux << 0))
>> I find this both technically elegant, because it combines all the
>> information into just one compact cell, but also readable by outsiders,
>> thanks to the macro.
> 
> And a new standard, to add to the other standards, so that
> is my problem as maintainer. It makes sense on its own, and it
> complicates the bigger picture.
> 
>> My main arguments against the current (string-based) approach:
>> - They require the mapping table to be in every DT user, so not only the
>>  Linux kernel, but also U-Boot, FreeBSD, you name it...
> 
> That's true.
> 
> This comes from the DT ambition to describe hardware and config,
> but not *define* hardware, i.e. to stop device tree to turn into
> Verilog or SystemC, which is what will happen if we take the
> 1:1 reflection of hardware to device tree too far.
> 
> I don't think anyone really knows where to cut the line.
> 
>> - The tables are getting quite large, and they pollute the single image
>>  Linux kernel, with tons of very specific information for a number of very
>>  pitiful Allwinner SoCs. At the moment the tally is at 145KB of code+data
>>  for the existing arm64 SoCs, with the newer SoCs ever growing (H616 alone
>>  is 27KB, A523 would be quite larger even, I guess 40K). The new A523
>>  specific pinctrl support adds 872 Bytes.
> 
> This is a generic problem though, look at GPU drivers.
> 
> The community (especially Android) seem set on fixing this by using
> modules.
> 
>> - Most of the mappings are untested at pinctrl driver commit time, since we
>>  don't have the device drivers ready yet - by a margin. The new approach
>>  would add the pinmux values when we need them and can test them.
> 
> I like this argument the best.
> 
> However this also reads "upfront firmware to handle pin control is a
> dead end" yet there are people dedicatedly working on exactly that.
> (Not that its' the Allwinner developers' problem...)
> 
>> - The comments in the table give away that something is not quite right:
>>                  SUNXI_FUNCTION(0x2, "i2c0")),         /* SDA */
>>  This is just a comment, so has no relevance for the code, but it's not
>>  meant for humans either. Yet we try to make this correct and maintain
>>  it. Odd.
> 
> So i2c0 is SDA and i2c1 is SCL or something?
> It seems common, but yeah it can be confusing.
> 
> Yours,
> Linus Walleij
Andre Przywara Jan. 17, 2025, 2:52 p.m. UTC | #8
On Thu, 16 Jan 2025 10:34:26 +0100
Linus Walleij <linus.walleij@linaro.org> wrote:

Hi Linus,

> some nice talk here, actually the following is just opinions, I will
> be likely happy with whatever approach is taken eventually.

it's indeed an intriguing discussion, made me think a bit ...
And thanks for describing your maintainer's view, that's definitely
helpful.

> On Wed, Jan 15, 2025 at 4:26 PM Andre Przywara <andre.przywara@arm.com> wrote:
> 
> > > pio: pinctrl@1c20800 {
> > >                         compatible = "allwinner,sun8i-r40-pinctrl";
> > > (...)
> > >                         i2c0_pins: i2c0-pins {
> > >                                 pins = "PB0", "PB1";
> > >                                 function = "i2c0";
> > >                         };
> > >
> > > abstract, strings, nice. The driver handles the particulars.  
> >
> > What bugs me about this it that this has quite some seemingly redundant
> > information (Who would have thought that the i2c0 pins use function
> > "i2c0"?), but misses out on the actual 4 bits(!) of information.  
> 
> the pins in this example are called PB0 and PB1 though. The designation
> on the package. And often pins actually named "i2c0_1" "i2c0_2" are
> for that primary function, but muxable to a few other functions,
> at least GPIO in most cases. So it's just some name for the pin
> really.

Sure, there is information in the form that marks those two pins for
being usable as I2C pins. But I feel like the function parameter is not
living up to its promise (see below).

> > > That is like so because we are designing for users which are
> > > let's say customization engineers. If these engineers jump from
> > > project to project matching function strings to group strings will
> > > be a common way to set up pins, and easy to understand and
> > > grasp, and it makes the DTS very readable.  
> >
> > That's an interesting view, and I see the point of it being easy to read,
> > but this is partly because it doesn't convey too much actual information,
> > does it, as it requires another lookup or two.
> > And the pinctrl group nodes are actually in the .dtsi file, which are
> > typically written once during the initial SoC enablement, and new board
> > .dts files normally just reference the existing pingroup nodes. So anyone
> > dealing with just a new board is not bothered by this.  
> 
> You have a point, and when working with a system the application
> engineer often finds bugs in the pin control driver, and has to go
> and fix the actual driver and then all the information hiding and
> simplification is moot.
> 
> This can become an expensive lesson for the current attempts
> to push pin control into firmware where the configuration is
> mostly "dead simple" (and just using strings) - the bugs will be
> in the firmware instead, and impossible or really hard to fix.

... in that old embedded world where firmware is an opaque closed source
unfixable blob. Mainline Allwinner is all "organic": we have upstreamed
U-Boot and TF-A support, actively maintained, plus an Open Source
management firmware. Updating the firmware is a matter of "dd" or
"flashcp" - at least in theory. And I'd rather think of the kernel being
not easy to change - think Debian installer image, or getting it upstream
first, then backported, then picked up by a distro.
But I think this discussion slightly digresses here - at least following it
would double the length of this email ;-)

> > Also in my experience most people have no problems in understanding the
> > concept of pinmuxing and that there is a selector number, also where to
> > find this.  
> 
> Yeah the ambition with the strings was to avoid forcing application
> engineers to know all about that. If they do, they are then
> developing the driver, not just using it.

I'd argue that an application engineer just has to choose the right
pingroup DT node:
	pinctrl-0 = <&i2c2_pb_pins>;
In the worst case they go ahead and ask their hardware buddy, and create
a new pingroup node. In my experience the typical Allwinner users are more
on the hardware side, so are no strangers to looking up data sheets.

> > > Mediatek and STM32 made a compromise by using pinmux
> > > and adding some macros to define them so it looks more
> > > pleasant:
> > >
> > >       i2c0_pins_a: i2c0-default {
> > >                 pins-i2c0 {
> > >                         pinmux = <MT7623_PIN_75_SDA0_FUNC_SDA0>,
> > >                                  <MT7623_PIN_76_SCL0_FUNC_SCL0>;  
> >
> > Well, I don't really get why they don't use the (MTK_PIN_NO(75) | 1)
> > definition directly, seems to be more telling to me?  
> 
> That's what STM32 does as well and it's usable.
> 
> But of course it drives a truck through the initial ambition that pins
> on all systems be configured the same way, with strings. So now
> there are some families of drivers all "necessarily different" which
> is not so nice for people jumping between different SoCs, but
> very compelling for people focusing on just one SoC.

Ah, I think I get your point.

> Well, unless this way of doing things becomes so prevalent that
> it's the new black.

That is actually a good argument: At the moment I am happy with my
proposal (the allwinner,pinmux = <number>; property), but that seems like
standard #15 then.
So would biting the bullet and adopting the Apple/STM32 way then be more
sustainable?
On the other hand: the allwinner,pinmux solution has the advantage of being
already written and proven working, also it stays very close to the
existing description/binding - so implementations like U-Boot could just
keep on using the "function" string.

I am a bit torn here... I don't think I will find the solitude to
implement this "Apple" approach in the next few weeks.

> > So the plan for sunxi would be: <SUNXI_PINMUX(PORTC, 23, MUX_1)>, ...
> > And this would not be really "opaque", since it has a fixed known mapping:
> >         (port << 16) | (pin << 8) | (mux << 0))
> > I find this both technically elegant, because it combines all the
> > information into just one compact cell, but also readable by outsiders,
> > thanks to the macro.  
> 
> And a new standard, to add to the other standards, so that
> is my problem as maintainer. It makes sense on its own, and it
> complicates the bigger picture.

I see your point - xkcd 927.

> > My main arguments against the current (string-based) approach:
> > - They require the mapping table to be in every DT user, so not only the
> >   Linux kernel, but also U-Boot, FreeBSD, you name it...  
> 
> That's true.
> 
> This comes from the DT ambition to describe hardware and config,
> but not *define* hardware, i.e. to stop device tree to turn into
> Verilog or SystemC, which is what will happen if we take the
> 1:1 reflection of hardware to device tree too far.
> 
> I don't think anyone really knows where to cut the line.

That's true, and I learned to step back from this ambition - it's
tempting, but indeed out of scope.
One thing to consider, though: the function names are effectively part of
the binding, since they must match exactly between the driver and DT - it's
not just a name. But they are documented nowhere. Names like "i2c0" or
"uart2" seem obvious, but there are ambiguities like "twi" vs "i2c" (the
former used in the vendor BSP), or "owa" vs "spdif" (same situation).
Also, is it "emac" or "emac0"? For some SoCs we discover a second
interface later: A523 just exposes one EMAC, but the A527 package (same
die) provides the pins for the second MAC as well. So I am afraid strings
are not as unique or straight-forward as we hope for.

So for creating a new pingroup, an application engineer would need to
check the Linux driver (or U-Boot? Or FreeBSD?) for the name to use - that
sounds somewhat wrong to me.
In the new model they just create a unique function name and enter the
pinmux from the datasheet - I think that's not too much to ask?

> > - The tables are getting quite large, and they pollute the single image
> >   Linux kernel, with tons of very specific information for a number of very
> >   pitiful Allwinner SoCs. At the moment the tally is at 145KB of code+data
> >   for the existing arm64 SoCs, with the newer SoCs ever growing (H616 alone
> >   is 27KB, A523 would be quite larger even, I guess 40K). The new A523
> >   specific pinctrl support adds 872 Bytes.  
> 
> This is a generic problem though, look at GPU drivers.

Yes, but for GPUs there is good rationale (because they are big
complicated pieces of hardware), and they are easily put into modules.
Pinctrl on the other hand is essential for *any* device to come up
(UART!), so having them in the image makes things much easier. Also
Allwinner pinctrl devices are not nearly as sexy as a Radeon or Geforce ;-)

> The community (especially Android) seem set on fixing this by using
> modules.
> 
> > - Most of the mappings are untested at pinctrl driver commit time, since we
> >   don't have the device drivers ready yet - by a margin. The new approach
> >   would add the pinmux values when we need them and can test them.  
> 
> I like this argument the best.
> 
> However this also reads "upfront firmware to handle pin control is a
> dead end" yet there are people dedicatedly working on exactly that.
> (Not that its' the Allwinner developers' problem...)

I see, but I feel it's an orthogonal problem, and relies on the a
pessimistic firmware view (see above).
Having those gory SoC specific details in firmware (which is by
definition device specific) solves one big problem, though: there is a
chance that existing kernels would already run on new SoCs/boards.
But again: different discussion thread, I guess, and not what I ask for.

> > - The comments in the table give away that something is not quite right:
> >                   SUNXI_FUNCTION(0x2, "i2c0")),         /* SDA */
> >   This is just a comment, so has no relevance for the code, but it's not
> >   meant for humans either. Yet we try to make this correct and maintain
> >   it. Odd.  
> 
> So i2c0 is SDA and i2c1 is SCL or something?

No, sorry, I cut out too much, it looks like this:

	SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 5),
		  SUNXI_FUNCTION(0x5, "i2c0"),		/* SCK */
		...
        SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 6),
		  SUNXI_FUNCTION(0x5, "i2c0"),		/* SDA */
		...
        SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 7),
		  SUNXI_FUNCTION(0x5, "i2c1"),		/* SCK */
		...
        SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 8),
		  SUNXI_FUNCTION(0x5, "i2c1"),		/* SDA */

So the function just selects the group, and the actual pin name is
completely irrelevant to the software side - hence the comment.
But this "put something not meant for the human reader into a comment"
typically points to something not being quite right.

Cheers,
Andre
Chen-Yu Tsai Jan. 17, 2025, 3:43 p.m. UTC | #9
On Thu, Jan 16, 2025 at 5:34 PM Linus Walleij <linus.walleij@linaro.org> wrote:
>
> Hi Andre,
>
> some nice talk here, actually the following is just opinions, I will
> be likely happy with whatever approach is taken eventually.
>
> On Wed, Jan 15, 2025 at 4:26 PM Andre Przywara <andre.przywara@arm.com> wrote:
>
> > > pio: pinctrl@1c20800 {
> > >                         compatible = "allwinner,sun8i-r40-pinctrl";
> > > (...)
> > >                         i2c0_pins: i2c0-pins {
> > >                                 pins = "PB0", "PB1";
> > >                                 function = "i2c0";
> > >                         };
> > >
> > > abstract, strings, nice. The driver handles the particulars.
> >
> > What bugs me about this it that this has quite some seemingly redundant
> > information (Who would have thought that the i2c0 pins use function
> > "i2c0"?), but misses out on the actual 4 bits(!) of information.
>
> the pins in this example are called PB0 and PB1 though. The designation
> on the package. And often pins actually named "i2c0_1" "i2c0_2" are
> for that primary function, but muxable to a few other functions,
> at least GPIO in most cases. So it's just some name for the pin
> really.

No. Allwinner actually names their pins like this, kind of like Rockchip
which provides standardized names such as "GPIO0_B2", but unlike MediaTek
which just names the pins after their designated primary function such as
"EINT22" or "TDM_BCLK". The ball names are a separate thing.

Even though the pin names seem a bit random, there's actually a grouping
logic underneath:

- PC pins are always for the bootable internal storage (NAND, SPI-NOR, eMMC)
- PF pins are always the external SD card / debug UART / JTAG

> > > That is like so because we are designing for users which are
> > > let's say customization engineers. If these engineers jump from
> > > project to project matching function strings to group strings will
> > > be a common way to set up pins, and easy to understand and
> > > grasp, and it makes the DTS very readable.
> >
> > That's an interesting view, and I see the point of it being easy to read,
> > but this is partly because it doesn't convey too much actual information,
> > does it, as it requires another lookup or two.
> > And the pinctrl group nodes are actually in the .dtsi file, which are
> > typically written once during the initial SoC enablement, and new board
> > .dts files normally just reference the existing pingroup nodes. So anyone
> > dealing with just a new board is not bothered by this.
>
> You have a point, and when working with a system the application
> engineer often finds bugs in the pin control driver, and has to go
> and fix the actual driver and then all the information hiding and
> simplification is moot.
>
> This can become an expensive lesson for the current attempts
> to push pin control into firmware where the configuration is
> mostly "dead simple" (and just using strings) - the bugs will be
> in the firmware instead, and impossible or really hard to fix.
>
> > Also in my experience most people have no problems in understanding the
> > concept of pinmuxing and that there is a selector number, also where to
> > find this.
>
> Yeah the ambition with the strings was to avoid forcing application
> engineers to know all about that. If they do, they are then
> developing the driver, not just using it.
>
> > > Mediatek and STM32 made a compromise by using pinmux
> > > and adding some macros to define them so it looks more
> > > pleasant:
> > >
> > >       i2c0_pins_a: i2c0-default {
> > >                 pins-i2c0 {
> > >                         pinmux = <MT7623_PIN_75_SDA0_FUNC_SDA0>,
> > >                                  <MT7623_PIN_76_SCL0_FUNC_SCL0>;
> >
> > Well, I don't really get why they don't use the (MTK_PIN_NO(75) | 1)
> > definition directly, seems to be more telling to me?
>
> That's what STM32 does as well and it's usable.
>
> But of course it drives a truck through the initial ambition that pins
> on all systems be configured the same way, with strings. So now
> there are some families of drivers all "necessarily different" which
> is not so nice for people jumping between different SoCs, but
> very compelling for people focusing on just one SoC.
>
> Well, unless this way of doing things becomes so prevalent that
> it's the new black.
>
> > So the plan for sunxi would be: <SUNXI_PINMUX(PORTC, 23, MUX_1)>, ...
> > And this would not be really "opaque", since it has a fixed known mapping:
> >         (port << 16) | (pin << 8) | (mux << 0))
> > I find this both technically elegant, because it combines all the
> > information into just one compact cell, but also readable by outsiders,
> > thanks to the macro.
>
> And a new standard, to add to the other standards, so that
> is my problem as maintainer. It makes sense on its own, and it
> complicates the bigger picture.
>
> > My main arguments against the current (string-based) approach:
> > - They require the mapping table to be in every DT user, so not only the
> >   Linux kernel, but also U-Boot, FreeBSD, you name it...
>
> That's true.
>
> This comes from the DT ambition to describe hardware and config,
> but not *define* hardware, i.e. to stop device tree to turn into
> Verilog or SystemC, which is what will happen if we take the
> 1:1 reflection of hardware to device tree too far.
>
> I don't think anyone really knows where to cut the line.
>
> > - The tables are getting quite large, and they pollute the single image
> >   Linux kernel, with tons of very specific information for a number of very
> >   pitiful Allwinner SoCs. At the moment the tally is at 145KB of code+data
> >   for the existing arm64 SoCs, with the newer SoCs ever growing (H616 alone
> >   is 27KB, A523 would be quite larger even, I guess 40K). The new A523
> >   specific pinctrl support adds 872 Bytes.
>
> This is a generic problem though, look at GPU drivers.
>
> The community (especially Android) seem set on fixing this by using
> modules.
>
> > - Most of the mappings are untested at pinctrl driver commit time, since we
> >   don't have the device drivers ready yet - by a margin. The new approach
> >   would add the pinmux values when we need them and can test them.
>
> I like this argument the best.
>
> However this also reads "upfront firmware to handle pin control is a
> dead end" yet there are people dedicatedly working on exactly that.
> (Not that its' the Allwinner developers' problem...)
>
> > - The comments in the table give away that something is not quite right:
> >                   SUNXI_FUNCTION(0x2, "i2c0")),         /* SDA */
> >   This is just a comment, so has no relevance for the code, but it's not
> >   meant for humans either. Yet we try to make this correct and maintain
> >   it. Odd.
>
> So i2c0 is SDA and i2c1 is SCL or something?
> It seems common, but yeah it can be confusing.

No. i2c0 is the actual peripheral that gets muxed in. The SDA / SCL
comments are simply denoting which signal from the peripheral this
pin & mux value carry.
diff mbox series

Patch

diff --git a/drivers/pinctrl/sunxi/Kconfig b/drivers/pinctrl/sunxi/Kconfig
index a78fdbbdfc0c..df67310672ac 100644
--- a/drivers/pinctrl/sunxi/Kconfig
+++ b/drivers/pinctrl/sunxi/Kconfig
@@ -86,6 +86,11 @@  config PINCTRL_SUN20I_D1
 	default MACH_SUN8I || (RISCV && ARCH_SUNXI)
 	select PINCTRL_SUNXI
 
+config PINCTRL_SUN8I_V853
+        bool "Support for the Allwinner V853 PIO"
+        default MACH_SUN8I
+        select PINCTRL_SUNXI
+
 config PINCTRL_SUN50I_A64
 	bool "Support for the Allwinner A64 PIO"
 	default ARM64 && ARCH_SUNXI
diff --git a/drivers/pinctrl/sunxi/Makefile b/drivers/pinctrl/sunxi/Makefile
index 2ff5a55927ad..2042276e85d6 100644
--- a/drivers/pinctrl/sunxi/Makefile
+++ b/drivers/pinctrl/sunxi/Makefile
@@ -28,3 +28,4 @@  obj-$(CONFIG_PINCTRL_SUN50I_H616)	+= pinctrl-sun50i-h616.o
 obj-$(CONFIG_PINCTRL_SUN50I_H616_R)	+= pinctrl-sun50i-h616-r.o
 obj-$(CONFIG_PINCTRL_SUN9I_A80)		+= pinctrl-sun9i-a80.o
 obj-$(CONFIG_PINCTRL_SUN9I_A80_R)	+= pinctrl-sun9i-a80-r.o
+obj-$(CONFIG_PINCTRL_SUN8I_V853)	+= pinctrl-sun8i-v853.o
diff --git a/drivers/pinctrl/sunxi/pinctrl-sun8i-v853.c b/drivers/pinctrl/sunxi/pinctrl-sun8i-v853.c
new file mode 100644
index 000000000000..62b84404bd14
--- /dev/null
+++ b/drivers/pinctrl/sunxi/pinctrl-sun8i-v853.c
@@ -0,0 +1,980 @@ 
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Allwinner V853 SoC pinctrl driver.
+ *
+ * Copyright (c) 2016-2021  weidonghui <weidonghui@allwinnertech.com>
+ * Copyright (c) 2023 Andras Szemzo <szemzo.andras@gmail.com>
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/io.h>
+
+#include "pinctrl-sunxi.h"
+
+/* Pin banks are: A C D E F G H I */
+static const struct sunxi_desc_pin sun8i_v853_pins[] = {
+
+	/* bank A */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 0),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "csi"),		/* CKOP */
+		SUNXI_FUNCTION(0x3, "ncsi"),		/* D8 */
+		SUNXI_FUNCTION(0x5, "test"),
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 0)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 1),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "csi"),		/* CKON */
+		SUNXI_FUNCTION(0x3, "ncsi"),		/* D9 */
+		SUNXI_FUNCTION(0x5, "test"),		/* test */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 1)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 2),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "csi"),		/* D1N */
+		SUNXI_FUNCTION(0x3, "ncsi"),		/* D10 */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 2)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 3),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "csi"),		/* D1P */
+		SUNXI_FUNCTION(0x3, "ncsi"),		/* D11 */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 3)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 4),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "csi"),		/* D0P */
+		SUNXI_FUNCTION(0x3, "ncsi"),		/* D12 */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 4)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 5),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "csi"),		/* D0N */
+		SUNXI_FUNCTION(0x3, "ncsi"),		/* D13 */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 5)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 6),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "csi"),		/* D0N/D2N */
+		SUNXI_FUNCTION(0x3, "ncsi"),		/* D14 */
+		SUNXI_FUNCTION(0x4, "i2c1"),		/* SCK */
+		SUNXI_FUNCTION(0x5, "pwm0"),
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 6)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 7),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "csi"),		/* D0P/D2P */
+		SUNXI_FUNCTION(0x3, "ncsi"),		/* D15 */
+		SUNXI_FUNCTION(0x4, "i2c1"),		/* SDA */
+		SUNXI_FUNCTION(0x5, "pwm1"),
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 7)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 8),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "csi"),		/* D1N/D3N */
+		SUNXI_FUNCTION(0x3, "i2c4"),		/* SCK */
+		SUNXI_FUNCTION(0x4, "i2c3"),		/* SCK */
+		SUNXI_FUNCTION(0x5, "pwm2"),
+		SUNXI_FUNCTION(0x6, "uart2"),		/* TX */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 8)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 9),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "csi"),		/* D1P/D3P */
+		SUNXI_FUNCTION(0x3, "i2c4"),		/* SDA */
+		SUNXI_FUNCTION(0x4, "i2c3"),		/* SDA */
+		SUNXI_FUNCTION(0x5, "pwm3"),
+		SUNXI_FUNCTION(0x6, "uart2"),		/* RX */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 9)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 10),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "csi"),		/* CKON */
+		SUNXI_FUNCTION(0x3, "ncsi"),		/* HSYNC */
+		SUNXI_FUNCTION(0x4, "csi_mclk"),	/* MCLK0 */
+		SUNXI_FUNCTION(0x5, "i2c0"),		/* SCK */
+		SUNXI_FUNCTION(0x6, "clk"),		/* FANOUT0 */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 10)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 11),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "csi"),		/* CKOP */
+		SUNXI_FUNCTION(0x3, "ncsi"),		/* VSYNC */
+		SUNXI_FUNCTION(0x4, "csi_mclk"),	/* MCLK1 */
+		SUNXI_FUNCTION(0x5, "i2c0"),		/* SDA */
+		SUNXI_FUNCTION(0x6, "clk"),		/* FANOUT1 */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 11)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 12),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x3, "ncsi"),		/* D0 */
+		SUNXI_FUNCTION(0x4, "csi_mclk"),	/* MCLK0 */
+		SUNXI_FUNCTION(0x5, "uart0"),		/* TX */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 12)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 13),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x3, "ncsi"),		/* D1 */
+		SUNXI_FUNCTION(0x4, "csi_mclk"),	/* MCLK1 */
+		SUNXI_FUNCTION(0x5, "uart0"),		/* RX */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 13)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 14),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x3, "ncsi"),		/* D2 */
+		SUNXI_FUNCTION(0x4, "i2c1"),		/* SCK */
+		SUNXI_FUNCTION(0x5, "clk"),		/* FANOUT0 */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 14)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 15),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x3, "ncsi"),		/* D3 */
+		SUNXI_FUNCTION(0x4, "i2c1"),		/* SDA */
+		SUNXI_FUNCTION(0x5, "clk"),		/* FANOUT1 */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 15)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 16),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x3, "ncsi"),		/* D4 */
+		SUNXI_FUNCTION(0x4, "i2c0"),		/* SCK */
+		SUNXI_FUNCTION(0x5, "uart3"),		/* TX */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 16)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 17),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x3, "ncsi"),		/* D5 */
+		SUNXI_FUNCTION(0x4, "i2c0"),		/* SDA */
+		SUNXI_FUNCTION(0x5, "uart3"),		/* RX */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 17)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 18),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x3, "ncsi"),		/* D6 */
+		SUNXI_FUNCTION(0x4, "wiegand"),		/* D0	*/
+		SUNXI_FUNCTION(0x5, "uart3"),		/* RTS */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 18)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 19),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x3, "ncsi"),		/* D7 */
+		SUNXI_FUNCTION(0x4, "wiegand"),		/* D1	*/
+		SUNXI_FUNCTION(0x5, "uart3"),		/* CTS */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 19)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 20),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x3, "ncsi"),		/* MCLK */
+		SUNXI_FUNCTION(0x4, "csi"),		/* SM_VS */
+		SUNXI_FUNCTION(0x5, "tcon"),		/* TRIG */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 20)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 21),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x3, "ncsi"),		/* PCLK */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 21)),
+	/* bank C */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 0),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "spif"),		/* CLK */
+		SUNXI_FUNCTION(0x3, "sdc2"),		/* CLK */
+		SUNXI_FUNCTION(0x4, "spi0"),		/* CLK */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 0)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 1),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "spif"),		/* CS0 */
+		SUNXI_FUNCTION(0x3, "sdc2"),		/* CMD */
+		SUNXI_FUNCTION(0x4, "spi0"),		/* CS0 */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 1)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 2),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "spif"),		/* MOSI_IO0 */
+		SUNXI_FUNCTION(0x3, "sdc2"),		/* D2 */
+		SUNXI_FUNCTION(0x4, "spi0"),		/* MOSI */
+		SUNXI_FUNCTION(0x5, "boot_sel0"),	/* SEL0 */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 2)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 3),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "spif"),		/* MOSI_IO1 */
+		SUNXI_FUNCTION(0x3, "sdc2"),		/* D1 */
+		SUNXI_FUNCTION(0x4, "spi0"),		/* MISO */
+		SUNXI_FUNCTION(0x5, "boot_sel1"),	/* SEL1 */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 3)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 4),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "spif"),		/* WP_IO2 */
+		SUNXI_FUNCTION(0x3, "sdc2"),		/* D0 */
+		SUNXI_FUNCTION(0x4, "spi0"),		/* WP */
+		SUNXI_FUNCTION(0x5, "pwm4"),
+		SUNXI_FUNCTION(0x6, "i2c1"),		/* SCK */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 4)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 5),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "spif"),		/* HOLD_IO3 */
+		SUNXI_FUNCTION(0x3, "sdc2"),		/* D3 */
+		SUNXI_FUNCTION(0x4, "spi0"),		/* HOLD */
+		SUNXI_FUNCTION(0x5, "pwm4"),
+		SUNXI_FUNCTION(0x6, "i2c1"),		/* SDA */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 5)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 6),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "spif"),		/* IO4 */
+		SUNXI_FUNCTION(0x3, "sdc2"),		/* D4 */
+		SUNXI_FUNCTION(0x4, "spi0"),		/* CSI */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 6)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 7),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "spif"),		/* IO5 */
+		SUNXI_FUNCTION(0x3, "sdc2"),		/* D5 */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 7)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 8),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "spif"),		/* IO6 */
+		SUNXI_FUNCTION(0x3, "sdc2"),		/* D6 */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 8)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 9),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "spif"),		/* IO7 */
+		SUNXI_FUNCTION(0x3, "sdc2"),		/* D7 */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 9)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 10),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "spif"),		/* DQS */
+		SUNXI_FUNCTION(0x3, "sdc2"),		/* DS */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 10)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 11),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x3, "sdc2"),		/* RTS */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 11)),
+	/* bank D */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 0),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd"),		/* D2 */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 0)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 1),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd"),		/* D3 */
+		SUNXI_FUNCTION(0x3, "pwm0"),
+		SUNXI_FUNCTION(0x4, "emac"),		/* RXD1 */
+		SUNXI_FUNCTION(0x5, "dsi"),		/* D0N */
+		SUNXI_FUNCTION(0x6, "spi1"),		/* CS0/CSX */
+		SUNXI_FUNCTION(0x7, "emac"),		/* TXD0 */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 1)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 2),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd"),		/* D4 */
+		SUNXI_FUNCTION(0x3, "pwm1"),
+		SUNXI_FUNCTION(0x4, "emac"),		/* RXD0 */
+		SUNXI_FUNCTION(0x5, "dsi"),		/* D1P */
+		SUNXI_FUNCTION(0x6, "spi1"),		/* CLK/SCLK */
+		SUNXI_FUNCTION(0x7, "emac"),		/* TXD1 */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 2)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 3),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd"),		/* D5 */
+		SUNXI_FUNCTION(0x3, "pwm2"),
+		SUNXI_FUNCTION(0x4, "emac"),		/* CRS_DV */
+		SUNXI_FUNCTION(0x5, "dsi"),		/* D1N */
+		SUNXI_FUNCTION(0x6, "spi1"),		/* MOSI/SDO */
+		SUNXI_FUNCTION(0x7, "emac"),		/* RXER */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 3)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 4),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd"),		/* D6 */
+		SUNXI_FUNCTION(0x3, "pwm3"),
+		SUNXI_FUNCTION(0x4, "emac"),		/* RXER */
+		SUNXI_FUNCTION(0x5, "dsi"),		/* D1P */
+		SUNXI_FUNCTION(0x6, "spi1"),		/* MISO/SDI/TE/DCX */
+		SUNXI_FUNCTION(0x7, "emac"),		/* CRS_DV */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 4)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 5),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd"),		/* D7 */
+		SUNXI_FUNCTION(0x3, "pwm4"),
+		SUNXI_FUNCTION(0x4, "emac"),		/* TXD1 */
+		SUNXI_FUNCTION(0x5, "dsi"),		/* CKN */
+		SUNXI_FUNCTION(0x6, "spi1"),		/* HOLD/DCX/WRX */
+		SUNXI_FUNCTION(0x7, "emac"),		/* RXD1 */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 5)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 6),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd"),		/* D10 */
+		SUNXI_FUNCTION(0x3, "pwm5"),
+		SUNXI_FUNCTION(0x4, "emac"),		/* TXD0 */
+		SUNXI_FUNCTION(0x5, "dsi"),		/* CKP */
+		SUNXI_FUNCTION(0x6, "spi1"),		/* WP/TE */
+		SUNXI_FUNCTION(0x7, "emac"),		/* RXD */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 6)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 7),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd"),		/* D11 */
+		SUNXI_FUNCTION(0x3, "pwm6"),
+		SUNXI_FUNCTION(0x4, "emac"),		/* TXCK */
+		SUNXI_FUNCTION(0x5, "dsi"),		/* D2N */
+		SUNXI_FUNCTION(0x6, "spi1"),		/* CS1 */
+		SUNXI_FUNCTION(0x7, "emac"),		/* MDC */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 7)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 8),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd"),		/* D12 */
+		SUNXI_FUNCTION(0x3, "pwm7"),
+		SUNXI_FUNCTION(0x4, "emac"),		/* TXEN */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 8)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 9),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd"),		/* D13 */
+		SUNXI_FUNCTION(0x3, "pwm8"),
+		SUNXI_FUNCTION(0x5, "dsi"),		/* D2P */
+		SUNXI_FUNCTION(0x7, "emac"),		/* MDIO */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 9)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 10),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd"),		/* D14 */
+		SUNXI_FUNCTION(0x3, "i2s1"),		/* MCLK */
+		SUNXI_FUNCTION(0x5, "dsi"),		/* D3N */
+		SUNXI_FUNCTION(0x7, "emac"),		/* TXEN */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 10)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 11),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd"),		/* D15 */
+		SUNXI_FUNCTION(0x3, "i2s1"),		/* BCLK */
+		SUNXI_FUNCTION(0x5, "dsi"),		/* D3P */
+		SUNXI_FUNCTION(0x7, "emac"),		/* TXCKk */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 11)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 12),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd"),		/* D18 */
+		SUNXI_FUNCTION(0x3, "i2s1"),		/* LCLK */
+		SUNXI_FUNCTION(0x5, "dmic"),		/* DATA3 */
+		SUNXI_FUNCTION(0x7, "pwm11"),
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 12)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 13),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd"),		/* D19 */
+		SUNXI_FUNCTION(0x3, "i2s1"),		/* DOUT0 */
+		SUNXI_FUNCTION(0x5, "dmic"),		/* DATA2 */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 13)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 14),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd"),		/* D20 */
+		SUNXI_FUNCTION(0x3, "i2s1"),		/* DOUT1 */
+		SUNXI_FUNCTION(0x4, "i2s1"),		/* DIN1 */
+		SUNXI_FUNCTION(0x5, "dmic"),		/* DATA1 */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 14)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 15),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd"),		/* D21 */
+		SUNXI_FUNCTION(0x3, "i2s1"),		/* DOUT2 */
+		SUNXI_FUNCTION(0x4, "i2s1"),		/* DIN2 */
+		SUNXI_FUNCTION(0x5, "dmic"),		/* DATA0 */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 15)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 16),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd"),		/* D22 */
+		SUNXI_FUNCTION(0x3, "i2s1"),		/* DOUT3 */
+		SUNXI_FUNCTION(0x4, "i2s1"),		/* DIN3 */
+		SUNXI_FUNCTION(0x5, "dmic"),		/* CLK */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 16)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 17),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd"),		/* D23 */
+		SUNXI_FUNCTION(0x3, "i2s1"),		/* DIN0 */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 17)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 18),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd"),		/* CLK */
+		SUNXI_FUNCTION(0x4, "emac"),		/* EPHY_25M */
+		SUNXI_FUNCTION(0x5, "spi2"),		/* CLK */
+		SUNXI_FUNCTION(0x6, "i2c3"),		/* SCK */
+		SUNXI_FUNCTION(0x7, "uart2"),		/* TX */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 18)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 19),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd"),		/* DE */
+		SUNXI_FUNCTION(0x3, "pwm9"),
+		SUNXI_FUNCTION(0x4, "tcon"),		/* TRIG */
+		SUNXI_FUNCTION(0x5, "spi2"),		/* MOSI */
+		SUNXI_FUNCTION(0x6, "i2c3"),		/* SDA */
+		SUNXI_FUNCTION(0x7, "uart2"),		/* RX */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 19)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 20),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd"),		/* HSYNC */
+		SUNXI_FUNCTION(0x3, "pwm10"),
+		SUNXI_FUNCTION(0x4, "emac"),		/* MDC */
+		SUNXI_FUNCTION(0x5, "spi2"),		/* MISO */
+		SUNXI_FUNCTION(0x6, "i2c2"),		/* SCK */
+		SUNXI_FUNCTION(0x7, "uart2"),		/* RTS */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 20)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 21),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "lcd"),		/* VSYNC */
+		SUNXI_FUNCTION(0x4, "emac"),		/* MDIO */
+		SUNXI_FUNCTION(0x5, "spi2"),		/* CS0 */
+		SUNXI_FUNCTION(0x6, "i2c2"),		/* SDA */
+		SUNXI_FUNCTION(0x7, "uart2"),		/* CTS */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 21)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 22),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "pwm9"),
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 22)),
+	/* bank E */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 0),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "ncsi"),		/* PCLK */
+		SUNXI_FUNCTION(0x3, "emac"),		/* RXD/RXD1 */
+		SUNXI_FUNCTION(0x4, "i2s1"),		/* MCLK */
+		SUNXI_FUNCTION(0x5, "pwm0"),
+		SUNXI_FUNCTION(0x6, "sdc1"),		/* CLK */
+		SUNXI_FUNCTION(0x7, "uart3"),		/* TX */
+		SUNXI_FUNCTION(0x8, "i2c3"),		/* SCK */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 0)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 1),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "ncsi"),		/* MCLK */
+		SUNXI_FUNCTION(0x3, "emac"),		/* RXCK/TXCK */
+		SUNXI_FUNCTION(0x4, "i2s1"),		/* BCLK */
+		SUNXI_FUNCTION(0x5, "pwm1"),
+		SUNXI_FUNCTION(0x6, "sdc1"),		/* CMD */
+		SUNXI_FUNCTION(0x7, "uart3"),		/* RX */
+		SUNXI_FUNCTION(0x8, "i2c3"),		/* SDA */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 1)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 2),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "ncsi"),		/* HSYNC */
+		SUNXI_FUNCTION(0x3, "emac"),		/* RXCTL/CRS_DV */
+		SUNXI_FUNCTION(0x4, "i2s1"),		/* LCLK */
+		SUNXI_FUNCTION(0x5, "pwm2"),
+		SUNXI_FUNCTION(0x6, "sdc1"),		/* D0 */
+		SUNXI_FUNCTION(0x7, "uart3"),		/* CTS */
+		SUNXI_FUNCTION(0x8, "i2c1"),		/* SCK */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 2)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 3),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "ncsi"),		/* VSYNC */
+		SUNXI_FUNCTION(0x3, "emac"),		/* RXD0 */
+		SUNXI_FUNCTION(0x4, "i2s1"),		/* DIN0 */
+		SUNXI_FUNCTION(0x5, "pwm3"),
+		SUNXI_FUNCTION(0x6, "sdc1"),		/* D1 */
+		SUNXI_FUNCTION(0x7, "uart3"),		/* RTS */
+		SUNXI_FUNCTION(0x8, "i2c1"),		/* SDA */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 3)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 4),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "ncsi"),		/* D0 */
+		SUNXI_FUNCTION(0x3, "emac"),		/* TXD0 */
+		SUNXI_FUNCTION(0x4, "i2s1"),		/* DOUT0 */
+		SUNXI_FUNCTION(0x5, "pwm4"),
+		SUNXI_FUNCTION(0x6, "sdc1"),		/* D2 */
+		SUNXI_FUNCTION(0x7, "i2c3"),		/* SCK */
+		SUNXI_FUNCTION(0x8, "i2c0"),		/* SCK */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 4)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 5),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "ncsi"),		/* D1 */
+		SUNXI_FUNCTION(0x3, "emac"),		/* TXD1 */
+		SUNXI_FUNCTION(0x5, "pwm5"),
+		SUNXI_FUNCTION(0x6, "sdc1"),		/* D3 */
+		SUNXI_FUNCTION(0x7, "i2c3"),		/* SDA */
+		SUNXI_FUNCTION(0x8, "i2c0"),		/* SDA */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 5)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 6),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "ncsi"),		/* D2 */
+		SUNXI_FUNCTION(0x3, "emac"),		/* TXCTL/TXEN */
+		SUNXI_FUNCTION(0x4, "lcd"),		/* D2 */
+		SUNXI_FUNCTION(0x5, "pwm6"),
+		SUNXI_FUNCTION(0x6, "uart1"),		/* TX */
+		SUNXI_FUNCTION(0x8, "i2c4"),		/* SCK */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 6)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 7),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "ncsi"),		/* D3 */
+		SUNXI_FUNCTION(0x3, "emac"),		/* CLKIN/RXER */
+		SUNXI_FUNCTION(0x4, "lcd"),		/* D15 */
+		SUNXI_FUNCTION(0x5, "pwm7"),
+		SUNXI_FUNCTION(0x6, "uart1"),		/* TX */
+		SUNXI_FUNCTION(0x7, "i2s1"),		/* DOUT0 */
+		SUNXI_FUNCTION(0x8, "i2c4"),		/* SDA */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 7)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 8),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "ncsi"),		/* D4 */
+		SUNXI_FUNCTION(0x3, "emac"),		/* MDC */
+		SUNXI_FUNCTION(0x4, "lcd"),		/* D18 */
+		SUNXI_FUNCTION(0x5, "pwm8"),
+		SUNXI_FUNCTION(0x6, "wiegand"),		/* D0 */
+		SUNXI_FUNCTION(0x7, "i2s1"),		/* DIN0 */
+		SUNXI_FUNCTION(0x8, "i2c1"),		/* SCK */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 8)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 9),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "ncsi"),		/* D5 */
+		SUNXI_FUNCTION(0x3, "emac"),		/* MDIO */
+		SUNXI_FUNCTION(0x4, "lcd"),		/* D19 */
+		SUNXI_FUNCTION(0x5, "pwm9"),
+		SUNXI_FUNCTION(0x6, "wiegand"),		/* D1 */
+		SUNXI_FUNCTION(0x7, "i2s1"),		/* LRCK */
+		SUNXI_FUNCTION(0x8, "i2c1"),		/* SDA */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 9)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 10),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "ncsi"),		/* D6 */
+		SUNXI_FUNCTION(0x3, "emac"),		/* EPHY_25M */
+		SUNXI_FUNCTION(0x4, "lcd"),		/* D20 */
+		SUNXI_FUNCTION(0x5, "pwm10"),
+		SUNXI_FUNCTION(0x6, "uart2"),		/* RTS */
+		SUNXI_FUNCTION(0x7, "i2s1"),		/* BCLK */
+		SUNXI_FUNCTION(0x8, "wiegand"),		/* D0 */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 10)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 11),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "ncsi"),		/* D7 */
+		SUNXI_FUNCTION(0x3, "emac"),		/* RXD3 */
+		SUNXI_FUNCTION(0x4, "lcd"),		/* D21 */
+		SUNXI_FUNCTION(0x5, "csi"),		/* SM_VS */
+		SUNXI_FUNCTION(0x6, "uart2"),		/* CTS */
+		SUNXI_FUNCTION(0x7, "i2s1"),		/* MCLK */
+		SUNXI_FUNCTION(0x8, "wiegand"),		/* D1 */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 11)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 12),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "ncsi"),		/* D8 */
+		SUNXI_FUNCTION(0x3, "emac"),		/* RXD2 */
+		SUNXI_FUNCTION(0x4, "lcd"),		/* D22 */
+		SUNXI_FUNCTION(0x5, "csi"),		/* MCLK0 */
+		SUNXI_FUNCTION(0x6, "uart2"),		/* TX */
+		SUNXI_FUNCTION(0x7, "uart3"),		/* TX */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 12)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 13),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "ncsi"),		/* D9 */
+		SUNXI_FUNCTION(0x3, "emac"),		/* RXCK */
+		SUNXI_FUNCTION(0x4, "lcd"),		/* D23 */
+		SUNXI_FUNCTION(0x5, "csi"),		/* MCLK1 */
+		SUNXI_FUNCTION(0x6, "uart2"),		/* RX */
+		SUNXI_FUNCTION(0x7, "uart3"),		/* RX */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 13)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 14),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "ncsi"),		/* D10 */
+		SUNXI_FUNCTION(0x3, "emac"),		/* TXD3 */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 14)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 15),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "ncsi"),		/* D11 */
+		SUNXI_FUNCTION(0x3, "emac"),		/* TXD2 */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 15)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 16),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "i2c0"),		/* SCK */
+		SUNXI_FUNCTION(0x3, "i2c4"),		/* SCK */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 16)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 17),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "i2c0"),		/* SDA */
+		SUNXI_FUNCTION(0x3, "i2c4"),		/* SDA */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 17)),
+	/* bank F */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 0),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "sdc0"),		/* D1 */
+		SUNXI_FUNCTION(0x3, "jtag"),		/* MS */
+		SUNXI_FUNCTION(0x4, "spi0"),		/* CLK */
+		SUNXI_FUNCTION(0x5, "spi2"),		/* CLK */
+		SUNXI_FUNCTION(0x6, "r_jtag"),		/* MS */
+		SUNXI_FUNCTION(0x7, "cpu"),		/* BIST0 */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 0)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 1),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "sdc0"),		/* D0 */
+		SUNXI_FUNCTION(0x3, "jtag"),		/* DI */
+		SUNXI_FUNCTION(0x4, "spi0"),		/* MOSI */
+		SUNXI_FUNCTION(0x5, "spi2"),		/* MOSI */
+		SUNXI_FUNCTION(0x6, "r_jtag"),		/* DI */
+		SUNXI_FUNCTION(0x7, "cpu"),		/* BIST1 */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 1)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 2),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "sdc0"),		/* CLK */
+		SUNXI_FUNCTION(0x3, "uart0"),		/* TX */
+		SUNXI_FUNCTION(0x4, "spi0"),		/* MISO */
+		SUNXI_FUNCTION(0x5, "spi2"),		/* MISO */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 2)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 3),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "sdc0"),		/* CMD */
+		SUNXI_FUNCTION(0x3, "jtag"),		/* DO */
+		SUNXI_FUNCTION(0x4, "spi0"),		/* CSO */
+		SUNXI_FUNCTION(0x5, "spi2"),		/* CS0 */
+		SUNXI_FUNCTION(0x6, "r_jtag"),		/* DO */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 3)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 4),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "sdc0"),		/* D3 */
+		SUNXI_FUNCTION(0x3, "uart0"),		/* RX */
+		SUNXI_FUNCTION(0x4, "spi0"),		/* CS1 */
+		SUNXI_FUNCTION(0x5, "spi2"),		/* CS1 */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 4)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 5),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "sdc0"),		/* D2 */
+		SUNXI_FUNCTION(0x3, "jtag"),		/* CK */
+		SUNXI_FUNCTION(0x6, "r_jtag"),		/* CK */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 5)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 6),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "dbg_clk"),
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 6)),
+	/* bank G */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 0),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "sdc1"),		/* CLK */
+		SUNXI_FUNCTION(0x3, "lcd"),		/* D0 */
+		SUNXI_FUNCTION(0x4, "uart3"),		/* TX */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 0)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 1),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "sdc1"),		/* CMD */
+		SUNXI_FUNCTION(0x3, "lcd"),		/* D1 */
+		SUNXI_FUNCTION(0x4, "uart3"),		/* RX */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 1)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 2),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "sdc1"),		/* D0 */
+		SUNXI_FUNCTION(0x3, "lcd"),		/* D8 */
+		SUNXI_FUNCTION(0x4, "uart3"),		/* CTS */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 2)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 3),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "sdc1"),		/* D1 */
+		SUNXI_FUNCTION(0x3, "lcd"),		/* D9 */
+		SUNXI_FUNCTION(0x4, "uart3"),		/* RTS */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 3)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 4),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "sdc1"),		/* D2 */
+		SUNXI_FUNCTION(0x3, "lcd"),		/* D16 */
+		SUNXI_FUNCTION(0x4, "uart1"),		/* RTS */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 4)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 5),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "sdc1"),		/* D3 */
+		SUNXI_FUNCTION(0x3, "lcd"),		/* D17 */
+		SUNXI_FUNCTION(0x4, "uart1"),		/* CTS */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 5)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 6),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "i2c4"),		/* SCK */
+		SUNXI_FUNCTION(0x3, "clk"),		/* FANOUT0 */
+		SUNXI_FUNCTION(0x4, "uart1"),		/* TX */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 6)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 7),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "i2c4"),		/* SDA */
+		SUNXI_FUNCTION(0x3, "clk"),		/* FANOUT1 */
+		SUNXI_FUNCTION(0x4, "uart1"),		/* RX */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 7)),
+	/* bank H */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 0),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "pwm0"),
+		SUNXI_FUNCTION(0x3, "i2s0"),		/* MCLK */
+		SUNXI_FUNCTION(0x4, "spi1"),		/* CLK */
+		SUNXI_FUNCTION(0x5, "uart3"),		/* TX */
+		SUNXI_FUNCTION(0x6, "dmic"),		/* DATA3 */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 0)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 1),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "pwm1"),
+		SUNXI_FUNCTION(0x3, "i2s0"),		/* BCLK */
+		SUNXI_FUNCTION(0x4, "spi1"),		/* MOSI */
+		SUNXI_FUNCTION(0x5, "uart3"),		/* RX */
+		SUNXI_FUNCTION(0x6, "dmic"),		/* DATA2 */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 1)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 2),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "pwm2"),
+		SUNXI_FUNCTION(0x3, "i2s0"),		/* LRCK */
+		SUNXI_FUNCTION(0x4, "spi1"),		/* MISO */
+		SUNXI_FUNCTION(0x5, "uart3"),		/* CTS */
+		SUNXI_FUNCTION(0x6, "dmic"),		/* DATA1 */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 2)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 3),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "pwm3"),
+		SUNXI_FUNCTION(0x3, "i2s0"),		/* DOUT0 */
+		SUNXI_FUNCTION(0x4, "spi1"),		/* CS0 */
+		SUNXI_FUNCTION(0x5, "uart3"),		/* RTS */
+		SUNXI_FUNCTION(0x6, "dmic"),		/* DATA0 */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 3)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 4),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "pwm4"),
+		SUNXI_FUNCTION(0x3, "i2s0"),		/* DIN0 */
+		SUNXI_FUNCTION(0x4, "spi1"),		/* CS1 */
+		SUNXI_FUNCTION(0x5, "clk"),		/* FANOUT2 */
+		SUNXI_FUNCTION(0x6, "dmic"),		/* CLK */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 4)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 5),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "pwm5"),
+		SUNXI_FUNCTION(0x3, "emac"),		/* RXD1 */
+		SUNXI_FUNCTION(0x4, "i2c2"),		/* SCK */
+		SUNXI_FUNCTION(0x5, "uart2"),		/* TX */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 5)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 6),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "pwm6"),
+		SUNXI_FUNCTION(0x3, "emac"),		/* RXD0 */
+		SUNXI_FUNCTION(0x4, "i2c2"),		/* SDA */
+		SUNXI_FUNCTION(0x5, "uart2"),		/* RX */
+		SUNXI_FUNCTION(0x6, "i2s1"),		/* MCLK */
+		SUNXI_FUNCTION(0x7, "dmic"),		/* DATA3 */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 6)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 7),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "pwm7"),
+		SUNXI_FUNCTION(0x3, "emac"),		/* CRS_DV */
+		SUNXI_FUNCTION(0x4, "uart0"),		/* TX */
+		SUNXI_FUNCTION(0x5, "uart2"),		/* RTS */
+		SUNXI_FUNCTION(0x6, "i2s1"),		/* BCLK */
+		SUNXI_FUNCTION(0x7, "dmic"),		/* DATA2 */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 7)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 8),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "pwm8"),
+		SUNXI_FUNCTION(0x3, "emac"),		/* RXER */
+		SUNXI_FUNCTION(0x4, "uart0"),		/* RX */
+		SUNXI_FUNCTION(0x5, "uart2"),		/* CTS */
+		SUNXI_FUNCTION(0x6, "i2s1"),		/* LRCK */
+		SUNXI_FUNCTION(0x7, "dmic"),		/* DATA1 */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 8)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 9),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "pwm9"),
+		SUNXI_FUNCTION(0x3, "emac"),		/* TXD1 */
+		SUNXI_FUNCTION(0x4, "i2c3"),		/* SCK */
+		SUNXI_FUNCTION(0x5, "uart0"),		/* TX */
+		SUNXI_FUNCTION(0x6, "i2s1"),		/* DIN0 */
+		SUNXI_FUNCTION(0x7, "dmic"),		/* DATA0 */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 9)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 10),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "pwm10"),
+		SUNXI_FUNCTION(0x3, "emac"),		/* TXD0 */
+		SUNXI_FUNCTION(0x4, "i2c3"),		/* SDA */
+		SUNXI_FUNCTION(0x5, "uart0"),		/* RX */
+		SUNXI_FUNCTION(0x6, "i2s1"),		/* DOUT0 */
+		SUNXI_FUNCTION(0x7, "dmic"),		/* CLK */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 10)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 11),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "jtag"),		/* MS */
+		SUNXI_FUNCTION(0x3, "emac"),		/* TXCK */
+		SUNXI_FUNCTION(0x4, "r_jtag"),		/* MS */
+		SUNXI_FUNCTION(0x5, "i2c2"),		/* SCK */
+		SUNXI_FUNCTION(0x6, "spi3"),		/* CLK */
+		SUNXI_FUNCTION(0x7, "clk"),		/* FANOUT0 */
+		SUNXI_FUNCTION(0x8, "pwm4"),
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 11)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 12),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "jtag"),		/* CK */
+		SUNXI_FUNCTION(0x3, "emac"),		/* TXEN */
+		SUNXI_FUNCTION(0x4, "r_jtag"),		/* CK */
+		SUNXI_FUNCTION(0x5, "i2c2"),		/* SDA */
+		SUNXI_FUNCTION(0x6, "spi3"),		/* MOSI */
+		SUNXI_FUNCTION(0x7, "clk"),		/* FANOUT1 */
+		SUNXI_FUNCTION(0x8, "pwm5"),
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 12)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 13),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "jtag"),		/* DO */
+		SUNXI_FUNCTION(0x3, "emac"),		/* MDC */
+		SUNXI_FUNCTION(0x4, "r_jtag"),		/* DO */
+		SUNXI_FUNCTION(0x5, "i2c3"),		/* SCK */
+		SUNXI_FUNCTION(0x6, "spi3"),		/* MISO */
+		SUNXI_FUNCTION(0x7, "wiegand"),		/* D0 */
+		SUNXI_FUNCTION(0x8, "pwm6"),
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 13)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 14),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "jtag"),		/* DI */
+		SUNXI_FUNCTION(0x3, "emac"),		/* MDIO */
+		SUNXI_FUNCTION(0x4, "r_jtag"),		/* DI */
+		SUNXI_FUNCTION(0x5, "i2c3"),		/* SDA */
+		SUNXI_FUNCTION(0x6, "spi3"),		/* CS0 */
+		SUNXI_FUNCTION(0x7, "wiegand"),		/* D1 */
+		SUNXI_FUNCTION(0x8, "pwm7"),
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 14)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 15),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "clk"),		/* FANOUT2 */
+		SUNXI_FUNCTION(0x3, "ephy_25m"),	/* EPHY_25M */
+		SUNXI_FUNCTION(0x6, "spi3"),		/* CS1 */
+		SUNXI_FUNCTION(0x8, "pwm8"),
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 6, 15)),
+	/* bank I */
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 0),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "csi"),		/* MCLK0 */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 7, 0)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 1),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "csi"),		/* SM_HS */
+		SUNXI_FUNCTION(0x4, "spi2"),		/* CLK */
+		SUNXI_FUNCTION(0x5, "i2c1"),		/* SCK */
+		SUNXI_FUNCTION(0x6, "i2c4"),		/* SCK */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 7, 1)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 2),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x2, "csi"),		/* SM_VS */
+		SUNXI_FUNCTION(0x3, "tcon"),		/* TRIG */
+		SUNXI_FUNCTION(0x4, "spi2"),		/* MOSI */
+		SUNXI_FUNCTION(0x5, "i2c1"),		/* SDA */
+		SUNXI_FUNCTION(0x6, "i2c4"),		/* SDA */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 7, 2)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 3),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x4, "spi2"),		/* MISO */
+		SUNXI_FUNCTION(0x5, "i2c0"),		/* SCA */
+		SUNXI_FUNCTION(0x6, "i2c3"),		/* SCK */
+		SUNXI_FUNCTION(0x7, "clk"),		/* FANOUT0 */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 7, 3)),
+	SUNXI_PIN(SUNXI_PINCTRL_PIN(I, 4),
+		SUNXI_FUNCTION(0x0, "gpio_in"),
+		SUNXI_FUNCTION(0x1, "gpio_out"),
+		SUNXI_FUNCTION(0x4, "spi2"),		/* CS0 */
+		SUNXI_FUNCTION(0x5, "i2c0"),		/* SDA */
+		SUNXI_FUNCTION(0x6, "i2c3"),		/* SDA */
+		SUNXI_FUNCTION(0x7, "clk"),		/* FANOUT1 */
+		SUNXI_FUNCTION_IRQ_BANK(0xe, 7, 4)),
+};
+
+static const unsigned int sun8i_v853_irq_bank_map[] = { 0, 2, 3, 4, 5, 6, 7, 8 };
+
+static const struct sunxi_pinctrl_desc sun8i_v853_pinctrl_data = {
+	.pins = sun8i_v853_pins,
+	.npins = ARRAY_SIZE(sun8i_v853_pins),
+	.pin_base = 0,
+	.irq_banks = ARRAY_SIZE(sun8i_v853_irq_bank_map),
+	.irq_bank_map = sun8i_v853_irq_bank_map,
+	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_CTL,
+};
+
+static int sun8i_v853_pinctrl_probe(struct platform_device *pdev)
+{
+	unsigned long variant = (unsigned long)of_device_get_match_data(&pdev->dev);
+
+	return sunxi_pinctrl_init_with_variant(pdev, &sun8i_v853_pinctrl_data, variant);
+}
+
+static const struct of_device_id sun8i_v853_pinctrl_match[] = {
+	{
+		.compatible = "allwinner,sun8i-v853-pinctrl",
+		.data = (void *)PINCTRL_SUN8I_V853
+	},
+	{}
+};
+
+static struct platform_driver sun8i_v853_pinctrl_driver = {
+	.probe	= sun8i_v853_pinctrl_probe,
+	.driver	= {
+		.name		= "sun8i-v853-pinctrl",
+		.of_match_table	= sun8i_v853_pinctrl_match,
+	},
+};
+builtin_platform_driver(sun8i_v853_pinctrl_driver);
diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.h b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
index a87a2f944d60..f4b64f9156f1 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.h
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
@@ -94,6 +94,7 @@ 
 #define PINCTRL_SUN8I_V3S	BIT(10)
 /* Variants below here have an updated register layout. */
 #define PINCTRL_SUN20I_D1	BIT(11)
+#define PINCTRL_SUN8I_V853	BIT(12)
 
 #define PIO_POW_MOD_SEL_REG	0x340
 #define PIO_POW_MOD_CTL_REG	0x344