sunxi: pinctrl: Create the driver skeleton

Create a do-nothing driver for each sunxi pin controller variant.

Since only one driver can automatically bind to a DT node, since the
GPIO driver already requires a manual binding process, and since the
pinctrl driver needs access to some of the same information, refactor
the GPIO driver to be bound by the pinctrl driver. This commit should
cause no functional change.

Signed-off-by: Samuel Holland <samuel@sholland.org>
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
diff --git a/MAINTAINERS b/MAINTAINERS
index 96582fc..712c2b1 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -520,6 +520,7 @@
 F:	board/sunxi/
 F:	drivers/clk/sunxi/
 F:	drivers/phy/allwinner/
+F:	drivers/pinctrl/sunxi/
 F:	drivers/video/sunxi/
 
 ARM TEGRA
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 4567c18..ea3d7ec 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1072,6 +1072,7 @@
 	select OF_BOARD_SETUP
 	select OF_CONTROL
 	select OF_SEPARATE
+	select PINCTRL
 	select SPECIFY_CONSOLE_INDEX
 	select SPL_SEPARATE_BSS if SPL
 	select SPL_STACK_R if SPL
diff --git a/arch/arm/include/asm/arch-sunxi/gpio.h b/arch/arm/include/asm/arch-sunxi/gpio.h
index edd0fbf..773711b 100644
--- a/arch/arm/include/asm/arch-sunxi/gpio.h
+++ b/arch/arm/include/asm/arch-sunxi/gpio.h
@@ -224,6 +224,11 @@
 #define SUNXI_GPIO_AXP0_VBUS_ENABLE	5
 #define SUNXI_GPIO_AXP0_GPIO_COUNT	6
 
+struct sunxi_gpio_plat {
+	struct sunxi_gpio	*regs;
+	char			bank_name[3];
+};
+
 void sunxi_gpio_set_cfgbank(struct sunxi_gpio *pio, int bank_offset, u32 val);
 void sunxi_gpio_set_cfgpin(u32 pin, u32 val);
 int sunxi_gpio_get_cfgbank(struct sunxi_gpio *pio, int bank_offset);
diff --git a/drivers/gpio/sunxi_gpio.c b/drivers/gpio/sunxi_gpio.c
index 6c3c108..1e85db1 100644
--- a/drivers/gpio/sunxi_gpio.c
+++ b/drivers/gpio/sunxi_gpio.c
@@ -16,15 +16,8 @@
 #include <malloc.h>
 #include <asm/io.h>
 #include <asm/gpio.h>
-#include <dm/device-internal.h>
 #include <dt-bindings/gpio/gpio.h>
 
-struct sunxi_gpio_plat {
-	struct sunxi_gpio *regs;
-	const char *bank_name;	/* Name of bank, e.g. "B" */
-	int gpio_count;
-};
-
 #if !CONFIG_IS_ENABLED(DM_GPIO)
 static int sunxi_gpio_output(u32 pin, u32 val)
 {
@@ -211,28 +204,6 @@
 	.set_flags		= sunxi_gpio_set_flags,
 };
 
-/**
- * Returns the name of a GPIO bank
- *
- * GPIO banks are named A, B, C, ...
- *
- * @bank:	Bank number (0, 1..n-1)
- * Return: allocated string containing the name
- */
-static char *gpio_bank_name(int bank)
-{
-	char *name;
-
-	name = malloc(3);
-	if (name) {
-		name[0] = 'P';
-		name[1] = 'A' + bank;
-		name[2] = '\0';
-	}
-
-	return name;
-}
-
 static int gpio_sunxi_probe(struct udevice *dev)
 {
 	struct sunxi_gpio_plat *plat = dev_get_plat(dev);
@@ -240,114 +211,17 @@
 
 	/* Tell the uclass how many GPIOs we have */
 	if (plat) {
-		uc_priv->gpio_count = plat->gpio_count;
+		uc_priv->gpio_count = SUNXI_GPIOS_PER_BANK;
 		uc_priv->bank_name = plat->bank_name;
 	}
 
 	return 0;
 }
 
-struct sunxi_gpio_soc_data {
-	int start;
-	int no_banks;
-};
-
-/**
- * We have a top-level GPIO device with no actual GPIOs. It has a child
- * device for each Sunxi bank.
- */
-static int gpio_sunxi_bind(struct udevice *parent)
-{
-	struct sunxi_gpio_soc_data *soc_data =
-		(struct sunxi_gpio_soc_data *)dev_get_driver_data(parent);
-	struct sunxi_gpio_plat *plat = dev_get_plat(parent);
-	struct sunxi_gpio_reg *ctlr;
-	int bank, ret;
-
-	/* If this is a child device, there is nothing to do here */
-	if (plat)
-		return 0;
-
-	ctlr = dev_read_addr_ptr(parent);
-	for (bank = 0; bank < soc_data->no_banks; bank++) {
-		struct sunxi_gpio_plat *plat;
-		struct udevice *dev;
-
-		plat = calloc(1, sizeof(*plat));
-		if (!plat)
-			return -ENOMEM;
-		plat->regs = &ctlr->gpio_bank[bank];
-		plat->bank_name = gpio_bank_name(soc_data->start + bank);
-		plat->gpio_count = SUNXI_GPIOS_PER_BANK;
-
-		ret = device_bind(parent, parent->driver, plat->bank_name, plat,
-				  dev_ofnode(parent), &dev);
-		if (ret)
-			return ret;
-	}
-
-	return 0;
-}
-
-static const struct sunxi_gpio_soc_data soc_data_a_all = {
-	.start = 0,
-	.no_banks = SUNXI_GPIO_BANKS,
-};
-
-static const struct sunxi_gpio_soc_data soc_data_l_1 = {
-	.start = 'L' - 'A',
-	.no_banks = 1,
-};
-
-static const struct sunxi_gpio_soc_data soc_data_l_2 = {
-	.start = 'L' - 'A',
-	.no_banks = 2,
-};
-
-static const struct sunxi_gpio_soc_data soc_data_l_3 = {
-	.start = 'L' - 'A',
-	.no_banks = 3,
-};
-
-#define ID(_compat_, _soc_data_) \
-	{ .compatible = _compat_, .data = (ulong)&soc_data_##_soc_data_ }
-
-static const struct udevice_id sunxi_gpio_ids[] = {
-	ID("allwinner,sun4i-a10-pinctrl",	a_all),
-	ID("allwinner,sun5i-a10s-pinctrl",	a_all),
-	ID("allwinner,sun5i-a13-pinctrl",	a_all),
-	ID("allwinner,sun50i-h5-pinctrl",	a_all),
-	ID("allwinner,sun6i-a31-pinctrl",	a_all),
-	ID("allwinner,sun6i-a31s-pinctrl",	a_all),
-	ID("allwinner,sun7i-a20-pinctrl",	a_all),
-	ID("allwinner,sun8i-a23-pinctrl",	a_all),
-	ID("allwinner,sun8i-a33-pinctrl",	a_all),
-	ID("allwinner,sun8i-a83t-pinctrl",	a_all),
-	ID("allwinner,sun8i-h3-pinctrl",	a_all),
-	ID("allwinner,sun8i-r40-pinctrl",	a_all),
-	ID("allwinner,sun8i-v3-pinctrl",	a_all),
-	ID("allwinner,sun8i-v3s-pinctrl",	a_all),
-	ID("allwinner,sun9i-a80-pinctrl",	a_all),
-	ID("allwinner,sun50i-a64-pinctrl",	a_all),
-	ID("allwinner,sun50i-h6-pinctrl",	a_all),
-	ID("allwinner,sun50i-h616-pinctrl",	a_all),
-	ID("allwinner,sun6i-a31-r-pinctrl",	l_2),
-	ID("allwinner,sun8i-a23-r-pinctrl",	l_1),
-	ID("allwinner,sun8i-a83t-r-pinctrl",	l_1),
-	ID("allwinner,sun8i-h3-r-pinctrl",	l_1),
-	ID("allwinner,sun9i-a80-r-pinctrl",	l_3),
-	ID("allwinner,sun50i-a64-r-pinctrl",	l_1),
-	ID("allwinner,sun50i-h6-r-pinctrl",	l_2),
-	ID("allwinner,sun50i-h616-r-pinctrl",	l_1),
-	{ }
-};
-
 U_BOOT_DRIVER(gpio_sunxi) = {
 	.name	= "gpio_sunxi",
 	.id	= UCLASS_GPIO,
-	.ops	= &gpio_sunxi_ops,
-	.of_match = sunxi_gpio_ids,
-	.bind	= gpio_sunxi_bind,
 	.probe	= gpio_sunxi_probe,
+	.ops	= &gpio_sunxi_ops,
 };
 #endif /* DM_GPIO */
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index 0394624..6a640ba 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -332,6 +332,7 @@
 source "drivers/pinctrl/nxp/Kconfig"
 source "drivers/pinctrl/renesas/Kconfig"
 source "drivers/pinctrl/rockchip/Kconfig"
+source "drivers/pinctrl/sunxi/Kconfig"
 source "drivers/pinctrl/uniphier/Kconfig"
 
 endmenu
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index df37c32..32283dd 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -14,7 +14,7 @@
 obj-$(CONFIG_ARCH_MTMIPS) += mtmips/
 obj-$(CONFIG_ARCH_RMOBILE) += renesas/
 obj-$(CONFIG_PINCTRL_SANDBOX)	+= pinctrl-sandbox.o
-
+obj-$(CONFIG_PINCTRL_SUNXI)	+= sunxi/
 obj-$(CONFIG_PINCTRL_UNIPHIER)	+= uniphier/
 obj-$(CONFIG_PINCTRL_PIC32)	+= pinctrl_pic32.o
 obj-$(CONFIG_PINCTRL_EXYNOS)	+= exynos/
diff --git a/drivers/pinctrl/sunxi/Kconfig b/drivers/pinctrl/sunxi/Kconfig
new file mode 100644
index 0000000..96c2f35
--- /dev/null
+++ b/drivers/pinctrl/sunxi/Kconfig
@@ -0,0 +1,125 @@
+# SPDX-License-Identifier: GPL-2.0
+
+if ARCH_SUNXI
+
+config PINCTRL_SUNXI
+	select PINCTRL_FULL
+	select PINCTRL_GENERIC
+	bool
+
+config PINCTRL_SUNIV_F1C100S
+	bool "Support for the Allwinner F1C100s PIO"
+	default MACH_SUNIV
+	select PINCTRL_SUNXI
+
+config PINCTRL_SUN4I_A10
+	bool "Support for the Allwinner A10 PIO"
+	default MACH_SUN4I
+	select PINCTRL_SUNXI
+
+config PINCTRL_SUN5I_A13
+	bool "Support for the Allwinner A10s/A13 PIO"
+	default MACH_SUN5I
+	select PINCTRL_SUNXI
+
+config PINCTRL_SUN6I_A31
+	bool "Support for the Allwinner A31 PIO"
+	default MACH_SUN6I
+	select PINCTRL_SUNXI
+
+config PINCTRL_SUN6I_A31_R
+	bool "Support for the Allwinner A31 R-PIO"
+	default MACH_SUN6I
+	select PINCTRL_SUNXI
+
+config PINCTRL_SUN7I_A20
+	bool "Support for the Allwinner A20/R40 PIO"
+	default MACH_SUN7I || MACH_SUN8I_R40
+	select PINCTRL_SUNXI
+
+config PINCTRL_SUN8I_A23
+	bool "Support for the Allwinner A23 PIO"
+	default MACH_SUN8I_A23
+	select PINCTRL_SUNXI
+
+config PINCTRL_SUN8I_A23_R
+	bool "Support for the Allwinner A23/A33 R-PIO"
+	default MACH_SUN8I_A23 || MACH_SUN8I_A33
+	select PINCTRL_SUNXI
+
+config PINCTRL_SUN8I_A33
+	bool "Support for the Allwinner A33 PIO"
+	default MACH_SUN8I_A33
+	select PINCTRL_SUNXI
+
+config PINCTRL_SUN8I_A83T
+	bool "Support for the Allwinner A83T PIO"
+	default MACH_SUN8I_A83T
+	select PINCTRL_SUNXI
+
+config PINCTRL_SUN8I_A83T_R
+	bool "Support for the Allwinner A83T R-PIO"
+	default MACH_SUN8I_A83T
+	select PINCTRL_SUNXI
+
+config PINCTRL_SUN8I_H3
+	bool "Support for the Allwinner H3 PIO"
+	default MACH_SUN8I_H3
+	select PINCTRL_SUNXI
+
+config PINCTRL_SUN8I_H3_R
+	bool "Support for the Allwinner H3/H5 R-PIO"
+	default MACH_SUN8I_H3 || MACH_SUN50I_H5
+	select PINCTRL_SUNXI
+
+config PINCTRL_SUN8I_V3S
+	bool "Support for the Allwinner V3s PIO"
+	default MACH_SUN8I_V3S
+	select PINCTRL_SUNXI
+
+config PINCTRL_SUN9I_A80
+	bool "Support for the Allwinner A80 PIO"
+	default MACH_SUN9I
+	select PINCTRL_SUNXI
+
+config PINCTRL_SUN9I_A80_R
+	bool "Support for the Allwinner A80 R-PIO"
+	default MACH_SUN9I
+	select PINCTRL_SUNXI
+
+config PINCTRL_SUN50I_A64
+	bool "Support for the Allwinner A64 PIO"
+	default MACH_SUN50I
+	select PINCTRL_SUNXI
+
+config PINCTRL_SUN50I_A64_R
+	bool "Support for the Allwinner A64 R-PIO"
+	default MACH_SUN50I
+	select PINCTRL_SUNXI
+
+config PINCTRL_SUN50I_H5
+	bool "Support for the Allwinner H5 PIO"
+	default MACH_SUN50I_H5
+	select PINCTRL_SUNXI
+
+config PINCTRL_SUN50I_H6
+	bool "Support for the Allwinner H6 PIO"
+	default MACH_SUN50I_H6
+	select PINCTRL_SUNXI
+
+config PINCTRL_SUN50I_H6_R
+	bool "Support for the Allwinner H6 R-PIO"
+	default MACH_SUN50I_H6
+	select PINCTRL_SUNXI
+
+config PINCTRL_SUN50I_H616
+	bool "Support for the Allwinner H616 PIO"
+	default MACH_SUN50I_H616
+	select PINCTRL_SUNXI
+
+config PINCTRL_SUN50I_H616_R
+	bool "Support for the Allwinner H616 R-PIO"
+	default MACH_SUN50I_H616
+	select PINCTRL_SUNXI
+
+endif
diff --git a/drivers/pinctrl/sunxi/Makefile b/drivers/pinctrl/sunxi/Makefile
new file mode 100644
index 0000000..6a8c01f
--- /dev/null
+++ b/drivers/pinctrl/sunxi/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-y					+= pinctrl-sunxi.o
diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
new file mode 100644
index 0000000..43bb1ec
--- /dev/null
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
@@ -0,0 +1,362 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <clk.h>
+#include <dm.h>
+#include <dm/device-internal.h>
+#include <dm/lists.h>
+#include <dm/pinctrl.h>
+#include <errno.h>
+#include <malloc.h>
+
+#include <asm/gpio.h>
+
+extern U_BOOT_DRIVER(gpio_sunxi);
+
+struct sunxi_pinctrl_desc {
+	u8					first_bank;
+	u8					num_banks;
+};
+
+struct sunxi_pinctrl_plat {
+	struct sunxi_gpio __iomem *base;
+};
+
+static const struct pinctrl_ops sunxi_pinctrl_ops = {
+	.set_state		= pinctrl_generic_set_state,
+};
+
+static int sunxi_pinctrl_bind(struct udevice *dev)
+{
+	struct sunxi_pinctrl_plat *plat = dev_get_plat(dev);
+	struct sunxi_pinctrl_desc *desc;
+	struct sunxi_gpio_plat *gpio_plat;
+	struct udevice *gpio_dev;
+	int i, ret;
+
+	desc = (void *)dev_get_driver_data(dev);
+	if (!desc)
+		return -EINVAL;
+	dev_set_priv(dev, desc);
+
+	plat->base = dev_read_addr_ptr(dev);
+
+	ret = device_bind_driver_to_node(dev, "gpio_sunxi", dev->name,
+					 dev_ofnode(dev), &gpio_dev);
+	if (ret)
+		return ret;
+
+	for (i = 0; i < desc->num_banks; ++i) {
+		gpio_plat = malloc(sizeof(*gpio_plat));
+		if (!gpio_plat)
+			return -ENOMEM;
+
+		gpio_plat->regs = plat->base + i;
+		gpio_plat->bank_name[0] = 'P';
+		gpio_plat->bank_name[1] = 'A' + desc->first_bank + i;
+		gpio_plat->bank_name[2] = '\0';
+
+		ret = device_bind(gpio_dev, DM_DRIVER_REF(gpio_sunxi),
+				  gpio_plat->bank_name, gpio_plat,
+				  ofnode_null(), NULL);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int sunxi_pinctrl_probe(struct udevice *dev)
+{
+	struct clk *apb_clk;
+
+	apb_clk = devm_clk_get(dev, "apb");
+	if (!IS_ERR(apb_clk))
+		clk_enable(apb_clk);
+
+	return 0;
+}
+
+static const struct sunxi_pinctrl_desc __maybe_unused suniv_f1c100s_pinctrl_desc = {
+	.first_bank	= SUNXI_GPIO_A,
+	.num_banks	= 6,
+};
+
+static const struct sunxi_pinctrl_desc __maybe_unused sun4i_a10_pinctrl_desc = {
+	.first_bank	= SUNXI_GPIO_A,
+	.num_banks	= 9,
+};
+
+static const struct sunxi_pinctrl_desc __maybe_unused sun5i_a13_pinctrl_desc = {
+	.first_bank	= SUNXI_GPIO_A,
+	.num_banks	= 7,
+};
+
+static const struct sunxi_pinctrl_desc __maybe_unused sun6i_a31_pinctrl_desc = {
+	.first_bank	= SUNXI_GPIO_A,
+	.num_banks	= 8,
+};
+
+static const struct sunxi_pinctrl_desc __maybe_unused sun6i_a31_r_pinctrl_desc = {
+	.first_bank	= SUNXI_GPIO_L,
+	.num_banks	= 2,
+};
+
+static const struct sunxi_pinctrl_desc __maybe_unused sun7i_a20_pinctrl_desc = {
+	.first_bank	= SUNXI_GPIO_A,
+	.num_banks	= 9,
+};
+
+static const struct sunxi_pinctrl_desc __maybe_unused sun8i_a23_pinctrl_desc = {
+	.first_bank	= SUNXI_GPIO_A,
+	.num_banks	= 8,
+};
+
+static const struct sunxi_pinctrl_desc __maybe_unused sun8i_a23_r_pinctrl_desc = {
+	.first_bank	= SUNXI_GPIO_L,
+	.num_banks	= 1,
+};
+
+static const struct sunxi_pinctrl_desc __maybe_unused sun8i_a33_pinctrl_desc = {
+	.first_bank	= SUNXI_GPIO_A,
+	.num_banks	= 8,
+};
+
+static const struct sunxi_pinctrl_desc __maybe_unused sun8i_a83t_pinctrl_desc = {
+	.first_bank	= SUNXI_GPIO_A,
+	.num_banks	= 8,
+};
+
+static const struct sunxi_pinctrl_desc __maybe_unused sun8i_a83t_r_pinctrl_desc = {
+	.first_bank	= SUNXI_GPIO_L,
+	.num_banks	= 1,
+};
+
+static const struct sunxi_pinctrl_desc __maybe_unused sun8i_h3_pinctrl_desc = {
+	.first_bank	= SUNXI_GPIO_A,
+	.num_banks	= 7,
+};
+
+static const struct sunxi_pinctrl_desc __maybe_unused sun8i_h3_r_pinctrl_desc = {
+	.first_bank	= SUNXI_GPIO_L,
+	.num_banks	= 1,
+};
+
+static const struct sunxi_pinctrl_desc __maybe_unused sun8i_v3s_pinctrl_desc = {
+	.first_bank	= SUNXI_GPIO_A,
+	.num_banks	= 7,
+};
+
+static const struct sunxi_pinctrl_desc __maybe_unused sun9i_a80_pinctrl_desc = {
+	.first_bank	= SUNXI_GPIO_A,
+	.num_banks	= 8,
+};
+
+static const struct sunxi_pinctrl_desc __maybe_unused sun9i_a80_r_pinctrl_desc = {
+	.first_bank	= SUNXI_GPIO_L,
+	.num_banks	= 3,
+};
+
+static const struct sunxi_pinctrl_desc __maybe_unused sun50i_a64_pinctrl_desc = {
+	.first_bank	= SUNXI_GPIO_A,
+	.num_banks	= 8,
+};
+
+static const struct sunxi_pinctrl_desc __maybe_unused sun50i_a64_r_pinctrl_desc = {
+	.first_bank	= SUNXI_GPIO_L,
+	.num_banks	= 1,
+};
+
+static const struct sunxi_pinctrl_desc __maybe_unused sun50i_h5_pinctrl_desc = {
+	.first_bank	= SUNXI_GPIO_A,
+	.num_banks	= 7,
+};
+
+static const struct sunxi_pinctrl_desc __maybe_unused sun50i_h6_pinctrl_desc = {
+	.first_bank	= SUNXI_GPIO_A,
+	.num_banks	= 8,
+};
+
+static const struct sunxi_pinctrl_desc __maybe_unused sun50i_h6_r_pinctrl_desc = {
+	.first_bank	= SUNXI_GPIO_L,
+	.num_banks	= 2,
+};
+
+static const struct sunxi_pinctrl_desc __maybe_unused sun50i_h616_pinctrl_desc = {
+	.first_bank	= SUNXI_GPIO_A,
+	.num_banks	= 9,
+};
+
+static const struct sunxi_pinctrl_desc __maybe_unused sun50i_h616_r_pinctrl_desc = {
+	.first_bank	= SUNXI_GPIO_L,
+	.num_banks	= 1,
+};
+
+static const struct udevice_id sunxi_pinctrl_ids[] = {
+#ifdef CONFIG_PINCTRL_SUNIV_F1C100S
+	{
+		.compatible = "allwinner,suniv-f1c100s-pinctrl",
+		.data = (ulong)&suniv_f1c100s_pinctrl_desc,
+	},
+#endif
+#ifdef CONFIG_PINCTRL_SUN4I_A10
+	{
+		.compatible = "allwinner,sun4i-a10-pinctrl",
+		.data = (ulong)&sun4i_a10_pinctrl_desc,
+	},
+#endif
+#ifdef CONFIG_PINCTRL_SUN5I_A13
+	{
+		.compatible = "allwinner,sun5i-a10s-pinctrl",
+		.data = (ulong)&sun5i_a13_pinctrl_desc,
+	},
+	{
+		.compatible = "allwinner,sun5i-a13-pinctrl",
+		.data = (ulong)&sun5i_a13_pinctrl_desc,
+	},
+#endif
+#ifdef CONFIG_PINCTRL_SUN6I_A31
+	{
+		.compatible = "allwinner,sun6i-a31-pinctrl",
+		.data = (ulong)&sun6i_a31_pinctrl_desc,
+	},
+	{
+		.compatible = "allwinner,sun6i-a31s-pinctrl",
+		.data = (ulong)&sun6i_a31_pinctrl_desc,
+	},
+#endif
+#ifdef CONFIG_PINCTRL_SUN6I_A31_R
+	{
+		.compatible = "allwinner,sun6i-a31-r-pinctrl",
+		.data = (ulong)&sun6i_a31_r_pinctrl_desc,
+	},
+#endif
+#ifdef CONFIG_PINCTRL_SUN7I_A20
+	{
+		.compatible = "allwinner,sun7i-a20-pinctrl",
+		.data = (ulong)&sun7i_a20_pinctrl_desc,
+	},
+#endif
+#ifdef CONFIG_PINCTRL_SUN8I_A23
+	{
+		.compatible = "allwinner,sun8i-a23-pinctrl",
+		.data = (ulong)&sun8i_a23_pinctrl_desc,
+	},
+#endif
+#ifdef CONFIG_PINCTRL_SUN8I_A23_R
+	{
+		.compatible = "allwinner,sun8i-a23-r-pinctrl",
+		.data = (ulong)&sun8i_a23_r_pinctrl_desc,
+	},
+#endif
+#ifdef CONFIG_PINCTRL_SUN8I_A33
+	{
+		.compatible = "allwinner,sun8i-a33-pinctrl",
+		.data = (ulong)&sun8i_a33_pinctrl_desc,
+	},
+#endif
+#ifdef CONFIG_PINCTRL_SUN8I_A83T
+	{
+		.compatible = "allwinner,sun8i-a83t-pinctrl",
+		.data = (ulong)&sun8i_a83t_pinctrl_desc,
+	},
+#endif
+#ifdef CONFIG_PINCTRL_SUN8I_A83T_R
+	{
+		.compatible = "allwinner,sun8i-a83t-r-pinctrl",
+		.data = (ulong)&sun8i_a83t_r_pinctrl_desc,
+	},
+#endif
+#ifdef CONFIG_PINCTRL_SUN8I_H3
+	{
+		.compatible = "allwinner,sun8i-h3-pinctrl",
+		.data = (ulong)&sun8i_h3_pinctrl_desc,
+	},
+#endif
+#ifdef CONFIG_PINCTRL_SUN8I_H3_R
+	{
+		.compatible = "allwinner,sun8i-h3-r-pinctrl",
+		.data = (ulong)&sun8i_h3_r_pinctrl_desc,
+	},
+#endif
+#ifdef CONFIG_PINCTRL_SUN7I_A20
+	{
+		.compatible = "allwinner,sun8i-r40-pinctrl",
+		.data = (ulong)&sun7i_a20_pinctrl_desc,
+	},
+#endif
+#ifdef CONFIG_PINCTRL_SUN8I_V3S
+	{
+		.compatible = "allwinner,sun8i-v3-pinctrl",
+		.data = (ulong)&sun8i_v3s_pinctrl_desc,
+	},
+	{
+		.compatible = "allwinner,sun8i-v3s-pinctrl",
+		.data = (ulong)&sun8i_v3s_pinctrl_desc,
+	},
+#endif
+#ifdef CONFIG_PINCTRL_SUN9I_A80
+	{
+		.compatible = "allwinner,sun9i-a80-pinctrl",
+		.data = (ulong)&sun9i_a80_pinctrl_desc,
+	},
+#endif
+#ifdef CONFIG_PINCTRL_SUN9I_A80_R
+	{
+		.compatible = "allwinner,sun9i-a80-r-pinctrl",
+		.data = (ulong)&sun9i_a80_r_pinctrl_desc,
+	},
+#endif
+#ifdef CONFIG_PINCTRL_SUN50I_A64
+	{
+		.compatible = "allwinner,sun50i-a64-pinctrl",
+		.data = (ulong)&sun50i_a64_pinctrl_desc,
+	},
+#endif
+#ifdef CONFIG_PINCTRL_SUN50I_A64_R
+	{
+		.compatible = "allwinner,sun50i-a64-r-pinctrl",
+		.data = (ulong)&sun50i_a64_r_pinctrl_desc,
+	},
+#endif
+#ifdef CONFIG_PINCTRL_SUN50I_H5
+	{
+		.compatible = "allwinner,sun50i-h5-pinctrl",
+		.data = (ulong)&sun50i_h5_pinctrl_desc,
+	},
+#endif
+#ifdef CONFIG_PINCTRL_SUN50I_H6
+	{
+		.compatible = "allwinner,sun50i-h6-pinctrl",
+		.data = (ulong)&sun50i_h6_pinctrl_desc,
+	},
+#endif
+#ifdef CONFIG_PINCTRL_SUN50I_H6_R
+	{
+		.compatible = "allwinner,sun50i-h6-r-pinctrl",
+		.data = (ulong)&sun50i_h6_r_pinctrl_desc,
+	},
+#endif
+#ifdef CONFIG_PINCTRL_SUN50I_H616
+	{
+		.compatible = "allwinner,sun50i-h616-pinctrl",
+		.data = (ulong)&sun50i_h616_pinctrl_desc,
+	},
+#endif
+#ifdef CONFIG_PINCTRL_SUN50I_H616_R
+	{
+		.compatible = "allwinner,sun50i-h616-r-pinctrl",
+		.data = (ulong)&sun50i_h616_r_pinctrl_desc,
+	},
+#endif
+	{}
+};
+
+U_BOOT_DRIVER(sunxi_pinctrl) = {
+	.name		= "sunxi-pinctrl",
+	.id		= UCLASS_PINCTRL,
+	.of_match	= sunxi_pinctrl_ids,
+	.bind		= sunxi_pinctrl_bind,
+	.probe		= sunxi_pinctrl_probe,
+	.plat_auto	= sizeof(struct sunxi_pinctrl_plat),
+	.ops		= &sunxi_pinctrl_ops,
+};