]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
pinctrl: starfive: Add StarFive JH7110 driver
authorKuan Lim Lee <kuanlim.lee@linux.starfivetech.com>
Wed, 29 Mar 2023 03:42:15 +0000 (11:42 +0800)
committerLeo Yu-Chi Liang <ycliang@andestech.com>
Thu, 20 Apr 2023 08:08:44 +0000 (16:08 +0800)
Add pinctrl driver for StarFive JH7110 SoC.

Signed-off-by: Kuan Lim Lee <kuanlim.lee@linux.starfivetech.com>
Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
Signed-off-by: Jianlong Huang <jianlong.huang@starfivetech.com>
Signed-off-by: Yanhong Wang <yanhong.wang@starfivetech.com>
Tested-by: Conor Dooley <conor.dooley@microchip.com>
drivers/pinctrl/Kconfig
drivers/pinctrl/Makefile
drivers/pinctrl/starfive/Kconfig [new file with mode: 0644]
drivers/pinctrl/starfive/Makefile [new file with mode: 0644]
drivers/pinctrl/starfive/pinctrl-jh7110-aon.c [new file with mode: 0644]
drivers/pinctrl/starfive/pinctrl-jh7110-sys.c [new file with mode: 0644]
drivers/pinctrl/starfive/pinctrl-starfive.c [new file with mode: 0644]
drivers/pinctrl/starfive/pinctrl-starfive.h [new file with mode: 0644]

index b6ef2acced2d9b7bd95cd418209975f4944f4294..75b3ff47a2e8888f109a9db3dbc5d11ac18a77ed 100644 (file)
@@ -359,5 +359,6 @@ source "drivers/pinctrl/renesas/Kconfig"
 source "drivers/pinctrl/rockchip/Kconfig"
 source "drivers/pinctrl/sunxi/Kconfig"
 source "drivers/pinctrl/uniphier/Kconfig"
+source "drivers/pinctrl/starfive/Kconfig"
 
 endmenu
index 3b167d099fcae23915eeb8aec22c2a3cb52dc1b5..852adee4b4f76d9c94f43dc47118af96b2fa617c 100644 (file)
@@ -32,3 +32,4 @@ obj-$(CONFIG_PINCTRL_STM32)   += pinctrl_stm32.o
 obj-$(CONFIG_$(SPL_)PINCTRL_STMFX)     += pinctrl-stmfx.o
 obj-y                          += broadcom/
 obj-$(CONFIG_PINCTRL_ZYNQMP)   += pinctrl-zynqmp.o
+obj-$(CONFIG_PINCTRL_STARFIVE) += starfive/
diff --git a/drivers/pinctrl/starfive/Kconfig b/drivers/pinctrl/starfive/Kconfig
new file mode 100644 (file)
index 0000000..1b859c8
--- /dev/null
@@ -0,0 +1,28 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+config SPL_PINCTRL_STARFIVE
+       bool "Support Pinctrl driver for StarFive SoC in SPL"
+       depends on SPL_PINCTRL_FULL && STARFIVE_JH7110
+       help
+         Enable support pin control driver for StarFive SoC.
+
+config SPL_PINCTRL_STARFIVE_JH7110
+       bool "Support Pinctrl and GPIO driver for StarFive JH7110 SoC in SPL"
+       depends on  SPL_PINCTRL_STARFIVE
+       help
+         Enable support pinctrl and gpio driver for StarFive JH7110 in SPL.
+
+config PINCTRL_STARFIVE
+       bool "Pinctrl driver for StarFive SoC"
+       depends on PINCTRL_FULL && STARFIVE_JH7110
+       help
+         Say yes here to support pin control on the StarFive RISC-V SoC.
+         This also provides an interface to the GPIO pins not used by other
+         peripherals supporting inputs, outputs, configuring pull-up/pull-down
+         and interrupts on input changes.
+
+config PINCTRL_STARFIVE_JH7110
+       bool "Pinctrl and GPIO driver for StarFive JH7110 SoC"
+       depends on  PINCTRL_STARFIVE
+       help
+         This selects the pinctrl driver for JH7110 starfive.
diff --git a/drivers/pinctrl/starfive/Makefile b/drivers/pinctrl/starfive/Makefile
new file mode 100644 (file)
index 0000000..a4a1206
--- /dev/null
@@ -0,0 +1,6 @@
+
+# SPDX-License-Identifier: GPL-2.0
+# Core
+obj-$(CONFIG_$(SPL_TPL_)PINCTRL_STARFIVE) += pinctrl-starfive.o
+# SoC Drivers
+obj-$(CONFIG_$(SPL_TPL_)PINCTRL_STARFIVE_JH7110)       += pinctrl-jh7110-sys.o pinctrl-jh7110-aon.o
diff --git a/drivers/pinctrl/starfive/pinctrl-jh7110-aon.c b/drivers/pinctrl/starfive/pinctrl-jh7110-aon.c
new file mode 100644 (file)
index 0000000..2d73990
--- /dev/null
@@ -0,0 +1,113 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Pinctrl / GPIO driver for StarFive JH7110 SoC
+ *
+ * Copyright (C) 2022 StarFive Technology Co., Ltd.
+ *   Author: Lee Kuan Lim <kuanlim.lee@starfivetech.com>
+ *   Author: Jianlong Huang <jianlong.huang@starfivetech.com>
+ */
+
+#include <dm/read.h>
+#include <dm/device_compat.h>
+#include <linux/io.h>
+
+#include <dt-bindings/pinctrl/pinctrl-starfive-jh7110.h>
+#include "pinctrl-starfive.h"
+
+#define JH7110_AON_NGPIO               4
+#define JH7110_AON_GC_BASE             64
+
+/* registers */
+#define JH7110_AON_DOEN                0x0
+#define JH7110_AON_DOUT                0x4
+#define JH7110_AON_GPI                 0x8
+#define JH7110_AON_GPIOIN              0x2c
+
+#define JH7110_AON_GPIOEN              0xc
+#define JH7110_AON_GPIOIS              0x10
+#define JH7110_AON_GPIOIC              0x14
+#define JH7110_AON_GPIOIBE             0x18
+#define JH7110_AON_GPIOIEV             0x1c
+#define JH7110_AON_GPIOIE              0x20
+#define JH7110_AON_GPIORIS             0x28
+#define JH7110_AON_GPIOMIS             0x28
+
+#define AON_GPO_PDA_0_5_CFG            0x30
+
+static int jh7110_aon_set_one_pin_mux(struct udevice *dev, unsigned int pin,
+                                     unsigned int din, u32 dout,
+                                     u32 doen, u32 func)
+{
+       struct starfive_pinctrl_priv *priv = dev_get_priv(dev);
+
+       if (pin < priv->info->ngpios && func == 0)
+               starfive_set_gpiomux(dev, pin, din, dout, doen);
+
+       return 0;
+}
+
+static int jh7110_aon_get_padcfg_base(struct udevice *dev,
+                                     unsigned int pin)
+{
+       if (pin < PAD_GMAC0_MDC)
+               return AON_GPO_PDA_0_5_CFG;
+
+       return -1;
+}
+
+static void jh7110_aon_init_hw(struct udevice *dev)
+{
+       struct starfive_pinctrl_priv *priv = dev_get_priv(dev);
+
+       /* mask all GPIO interrupts */
+       writel(0, priv->base + JH7110_AON_GPIOIE);
+       /* clear edge interrupt flags */
+       writel(0, priv->base + JH7110_AON_GPIOIC);
+       writel(0x0f, priv->base + JH7110_AON_GPIOIC);
+       /* enable GPIO interrupts */
+       writel(1, priv->base + JH7110_AON_GPIOEN);
+}
+
+const struct starfive_pinctrl_soc_info jh7110_aon_pinctrl_info = {
+       /* pin conf */
+       .set_one_pinmux = jh7110_aon_set_one_pin_mux,
+       .get_padcfg_base  = jh7110_aon_get_padcfg_base,
+
+       /* gpio dout/doen/din/gpioinput register */
+       .dout_reg_base = JH7110_AON_DOUT,
+       .dout_mask = GENMASK(3, 0),
+       .doen_reg_base = JH7110_AON_DOEN,
+       .doen_mask = GENMASK(2, 0),
+       .gpi_reg_base = JH7110_AON_GPI,
+       .gpi_mask = GENMASK(3, 0),
+       .gpioin_reg_base = JH7110_AON_GPIOIN,
+
+       /* gpio */
+       .gpio_bank_name = "RGPIO",
+       .ngpios = JH7110_AON_NGPIO,
+       .gpio_init_hw = jh7110_aon_init_hw,
+};
+
+static int jh7110_aon_pinctrl_probe(struct udevice *dev)
+{
+       struct starfive_pinctrl_soc_info *info =
+               (struct starfive_pinctrl_soc_info *)dev_get_driver_data(dev);
+
+       return starfive_pinctrl_probe(dev, info);
+}
+
+static const struct udevice_id jh7110_aon_pinctrl_ids[] = {
+       /* JH7110 aon pinctrl */
+       { .compatible = "starfive,jh7110-aon-pinctrl",
+         .data = (ulong)&jh7110_aon_pinctrl_info, },
+       { /* sentinel */ }
+};
+
+U_BOOT_DRIVER(jh7110_aon_pinctrl) = {
+       .name           = "jh7110-aon-pinctrl",
+       .id             = UCLASS_PINCTRL,
+       .of_match       = jh7110_aon_pinctrl_ids,
+       .priv_auto      = sizeof(struct starfive_pinctrl_priv),
+       .ops            = &starfive_pinctrl_ops,
+       .probe          = jh7110_aon_pinctrl_probe,
+};
diff --git a/drivers/pinctrl/starfive/pinctrl-jh7110-sys.c b/drivers/pinctrl/starfive/pinctrl-jh7110-sys.c
new file mode 100644 (file)
index 0000000..dafba65
--- /dev/null
@@ -0,0 +1,399 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Pinctrl / GPIO driver for StarFive JH7110 SoC
+ *
+ * Copyright (C) 2022 StarFive Technology Co., Ltd.
+ *   Author: Lee Kuan Lim <kuanlim.lee@starfivetech.com>
+ *   Author: Jianlong Huang <jianlong.huang@starfivetech.com>
+ */
+
+#include <dm/read.h>
+#include <dm/device_compat.h>
+#include <linux/io.h>
+
+#include <dt-bindings/pinctrl/pinctrl-starfive-jh7110.h>
+#include "pinctrl-starfive.h"
+
+#define JH7110_SYS_NGPIO               64
+#define JH7110_SYS_GC_BASE             0
+
+/* registers */
+#define JH7110_SYS_DOEN                0x000
+#define JH7110_SYS_DOUT                0x040
+#define JH7110_SYS_GPI                 0x080
+#define JH7110_SYS_GPIOIN              0x118
+
+#define JH7110_SYS_GPIOEN              0x0dc
+#define JH7110_SYS_GPIOIS0             0x0e0
+#define JH7110_SYS_GPIOIS1             0x0e4
+#define JH7110_SYS_GPIOIC0             0x0e8
+#define JH7110_SYS_GPIOIC1             0x0ec
+#define JH7110_SYS_GPIOIBE0            0x0f0
+#define JH7110_SYS_GPIOIBE1            0x0f4
+#define JH7110_SYS_GPIOIEV0            0x0f8
+#define JH7110_SYS_GPIOIEV1            0x0fc
+#define JH7110_SYS_GPIOIE0             0x100
+#define JH7110_SYS_GPIOIE1             0x104
+#define JH7110_SYS_GPIORIS0            0x108
+#define JH7110_SYS_GPIORIS1            0x10c
+#define JH7110_SYS_GPIOMIS0            0x110
+#define JH7110_SYS_GPIOMIS1            0x114
+
+#define SYS_GPO_PDA_0_74_CFG           0x120
+#define SYS_GPO_PDA_89_94_CFG          0x284
+
+static const struct starfive_pinctrl_pin jh7110_sys_pins[] = {
+       STARFIVE_PINCTRL(PAD_GPIO0,             "GPIO0"),
+       STARFIVE_PINCTRL(PAD_GPIO1,             "GPIO1"),
+       STARFIVE_PINCTRL(PAD_GPIO2,             "GPIO2"),
+       STARFIVE_PINCTRL(PAD_GPIO3,             "GPIO3"),
+       STARFIVE_PINCTRL(PAD_GPIO4,             "GPIO4"),
+       STARFIVE_PINCTRL(PAD_GPIO5,             "GPIO5"),
+       STARFIVE_PINCTRL(PAD_GPIO6,             "GPIO6"),
+       STARFIVE_PINCTRL(PAD_GPIO7,             "GPIO7"),
+       STARFIVE_PINCTRL(PAD_GPIO8,             "GPIO8"),
+       STARFIVE_PINCTRL(PAD_GPIO9,             "GPIO9"),
+       STARFIVE_PINCTRL(PAD_GPIO10,            "GPIO10"),
+       STARFIVE_PINCTRL(PAD_GPIO11,            "GPIO11"),
+       STARFIVE_PINCTRL(PAD_GPIO12,            "GPIO12"),
+       STARFIVE_PINCTRL(PAD_GPIO13,            "GPIO13"),
+       STARFIVE_PINCTRL(PAD_GPIO14,            "GPIO14"),
+       STARFIVE_PINCTRL(PAD_GPIO15,            "GPIO15"),
+       STARFIVE_PINCTRL(PAD_GPIO16,            "GPIO16"),
+       STARFIVE_PINCTRL(PAD_GPIO17,            "GPIO17"),
+       STARFIVE_PINCTRL(PAD_GPIO18,            "GPIO18"),
+       STARFIVE_PINCTRL(PAD_GPIO19,            "GPIO19"),
+       STARFIVE_PINCTRL(PAD_GPIO20,            "GPIO20"),
+       STARFIVE_PINCTRL(PAD_GPIO21,            "GPIO21"),
+       STARFIVE_PINCTRL(PAD_GPIO22,            "GPIO22"),
+       STARFIVE_PINCTRL(PAD_GPIO23,            "GPIO23"),
+       STARFIVE_PINCTRL(PAD_GPIO24,            "GPIO24"),
+       STARFIVE_PINCTRL(PAD_GPIO25,            "GPIO25"),
+       STARFIVE_PINCTRL(PAD_GPIO26,            "GPIO26"),
+       STARFIVE_PINCTRL(PAD_GPIO27,            "GPIO27"),
+       STARFIVE_PINCTRL(PAD_GPIO28,            "GPIO28"),
+       STARFIVE_PINCTRL(PAD_GPIO29,            "GPIO29"),
+       STARFIVE_PINCTRL(PAD_GPIO30,            "GPIO30"),
+       STARFIVE_PINCTRL(PAD_GPIO31,            "GPIO31"),
+       STARFIVE_PINCTRL(PAD_GPIO32,            "GPIO32"),
+       STARFIVE_PINCTRL(PAD_GPIO33,            "GPIO33"),
+       STARFIVE_PINCTRL(PAD_GPIO34,            "GPIO34"),
+       STARFIVE_PINCTRL(PAD_GPIO35,            "GPIO35"),
+       STARFIVE_PINCTRL(PAD_GPIO36,            "GPIO36"),
+       STARFIVE_PINCTRL(PAD_GPIO37,            "GPIO37"),
+       STARFIVE_PINCTRL(PAD_GPIO38,            "GPIO38"),
+       STARFIVE_PINCTRL(PAD_GPIO39,            "GPIO39"),
+       STARFIVE_PINCTRL(PAD_GPIO40,            "GPIO40"),
+       STARFIVE_PINCTRL(PAD_GPIO41,            "GPIO41"),
+       STARFIVE_PINCTRL(PAD_GPIO42,            "GPIO42"),
+       STARFIVE_PINCTRL(PAD_GPIO43,            "GPIO43"),
+       STARFIVE_PINCTRL(PAD_GPIO44,            "GPIO44"),
+       STARFIVE_PINCTRL(PAD_GPIO45,            "GPIO45"),
+       STARFIVE_PINCTRL(PAD_GPIO46,            "GPIO46"),
+       STARFIVE_PINCTRL(PAD_GPIO47,            "GPIO47"),
+       STARFIVE_PINCTRL(PAD_GPIO48,            "GPIO48"),
+       STARFIVE_PINCTRL(PAD_GPIO49,            "GPIO49"),
+       STARFIVE_PINCTRL(PAD_GPIO50,            "GPIO50"),
+       STARFIVE_PINCTRL(PAD_GPIO51,            "GPIO51"),
+       STARFIVE_PINCTRL(PAD_GPIO52,            "GPIO52"),
+       STARFIVE_PINCTRL(PAD_GPIO53,            "GPIO53"),
+       STARFIVE_PINCTRL(PAD_GPIO54,            "GPIO54"),
+       STARFIVE_PINCTRL(PAD_GPIO55,            "GPIO55"),
+       STARFIVE_PINCTRL(PAD_GPIO56,            "GPIO56"),
+       STARFIVE_PINCTRL(PAD_GPIO57,            "GPIO57"),
+       STARFIVE_PINCTRL(PAD_GPIO58,            "GPIO58"),
+       STARFIVE_PINCTRL(PAD_GPIO59,            "GPIO59"),
+       STARFIVE_PINCTRL(PAD_GPIO60,            "GPIO60"),
+       STARFIVE_PINCTRL(PAD_GPIO61,            "GPIO61"),
+       STARFIVE_PINCTRL(PAD_GPIO62,            "GPIO62"),
+       STARFIVE_PINCTRL(PAD_GPIO63,            "GPIO63"),
+       STARFIVE_PINCTRL(PAD_SD0_CLK,           "SD0_CLK"),
+       STARFIVE_PINCTRL(PAD_SD0_CMD,           "SD0_CMD"),
+       STARFIVE_PINCTRL(PAD_SD0_DATA0,         "SD0_DATA0"),
+       STARFIVE_PINCTRL(PAD_SD0_DATA1,         "SD0_DATA1"),
+       STARFIVE_PINCTRL(PAD_SD0_DATA2,         "SD0_DATA2"),
+       STARFIVE_PINCTRL(PAD_SD0_DATA3,         "SD0_DATA3"),
+       STARFIVE_PINCTRL(PAD_SD0_DATA4,         "SD0_DATA4"),
+       STARFIVE_PINCTRL(PAD_SD0_DATA5,         "SD0_DATA5"),
+       STARFIVE_PINCTRL(PAD_SD0_DATA6,         "SD0_DATA6"),
+       STARFIVE_PINCTRL(PAD_SD0_DATA7,         "SD0_DATA7"),
+       STARFIVE_PINCTRL(PAD_SD0_STRB,          "SD0_STRB"),
+       STARFIVE_PINCTRL(PAD_GMAC1_MDC,         "GMAC1_MDC"),
+       STARFIVE_PINCTRL(PAD_GMAC1_MDIO,        "GMAC1_MDIO"),
+       STARFIVE_PINCTRL(PAD_GMAC1_RXD0,        "GMAC1_RXD0"),
+       STARFIVE_PINCTRL(PAD_GMAC1_RXD1,        "GMAC1_RXD1"),
+       STARFIVE_PINCTRL(PAD_GMAC1_RXD2,        "GMAC1_RXD2"),
+       STARFIVE_PINCTRL(PAD_GMAC1_RXD3,        "GMAC1_RXD3"),
+       STARFIVE_PINCTRL(PAD_GMAC1_RXDV,        "GMAC1_RXDV"),
+       STARFIVE_PINCTRL(PAD_GMAC1_RXC,         "GMAC1_RXC"),
+       STARFIVE_PINCTRL(PAD_GMAC1_TXD0,        "GMAC1_TXD0"),
+       STARFIVE_PINCTRL(PAD_GMAC1_TXD1,        "GMAC1_TXD1"),
+       STARFIVE_PINCTRL(PAD_GMAC1_TXD2,        "GMAC1_TXD2"),
+       STARFIVE_PINCTRL(PAD_GMAC1_TXD3,        "GMAC1_TXD3"),
+       STARFIVE_PINCTRL(PAD_GMAC1_TXEN,        "GMAC1_TXEN"),
+       STARFIVE_PINCTRL(PAD_GMAC1_TXC,         "GMAC1_TXC"),
+       STARFIVE_PINCTRL(PAD_QSPI_SCLK,         "QSPI_SCLK"),
+       STARFIVE_PINCTRL(PAD_QSPI_CS0,          "QSPI_CS0"),
+       STARFIVE_PINCTRL(PAD_QSPI_DATA0,        "QSPI_DATA0"),
+       STARFIVE_PINCTRL(PAD_QSPI_DATA1,        "QSPI_DATA1"),
+       STARFIVE_PINCTRL(PAD_QSPI_DATA2,        "QSPI_DATA2"),
+       STARFIVE_PINCTRL(PAD_QSPI_DATA3,        "QSPI_DATA3"),
+};
+
+struct jh7110_func_sel {
+       u16 offset;
+       u8 shift;
+       u8 max;
+};
+
+static const struct jh7110_func_sel
+       jh7110_sys_func_sel[ARRAY_SIZE(jh7110_sys_pins)] = {
+       [PAD_GMAC1_RXC] = { 0x29c,  0, 1 },
+       [PAD_GPIO10]    = { 0x29c,  2, 3 },
+       [PAD_GPIO11]    = { 0x29c,  5, 3 },
+       [PAD_GPIO12]    = { 0x29c,  8, 3 },
+       [PAD_GPIO13]    = { 0x29c, 11, 3 },
+       [PAD_GPIO14]    = { 0x29c, 14, 3 },
+       [PAD_GPIO15]    = { 0x29c, 17, 3 },
+       [PAD_GPIO16]    = { 0x29c, 20, 3 },
+       [PAD_GPIO17]    = { 0x29c, 23, 3 },
+       [PAD_GPIO18]    = { 0x29c, 26, 3 },
+       [PAD_GPIO19]    = { 0x29c, 29, 3 },
+
+       [PAD_GPIO20]    = { 0x2a0,  0, 3 },
+       [PAD_GPIO21]    = { 0x2a0,  3, 3 },
+       [PAD_GPIO22]    = { 0x2a0,  6, 3 },
+       [PAD_GPIO23]    = { 0x2a0,  9, 3 },
+       [PAD_GPIO24]    = { 0x2a0, 12, 3 },
+       [PAD_GPIO25]    = { 0x2a0, 15, 3 },
+       [PAD_GPIO26]    = { 0x2a0, 18, 3 },
+       [PAD_GPIO27]    = { 0x2a0, 21, 3 },
+       [PAD_GPIO28]    = { 0x2a0, 24, 3 },
+       [PAD_GPIO29]    = { 0x2a0, 27, 3 },
+
+       [PAD_GPIO30]    = { 0x2a4,  0, 3 },
+       [PAD_GPIO31]    = { 0x2a4,  3, 3 },
+       [PAD_GPIO32]    = { 0x2a4,  6, 3 },
+       [PAD_GPIO33]    = { 0x2a4,  9, 3 },
+       [PAD_GPIO34]    = { 0x2a4, 12, 3 },
+       [PAD_GPIO35]    = { 0x2a4, 15, 3 },
+       [PAD_GPIO36]    = { 0x2a4, 17, 3 },
+       [PAD_GPIO37]    = { 0x2a4, 20, 3 },
+       [PAD_GPIO38]    = { 0x2a4, 23, 3 },
+       [PAD_GPIO39]    = { 0x2a4, 26, 3 },
+       [PAD_GPIO40]    = { 0x2a4, 29, 3 },
+
+       [PAD_GPIO41]    = { 0x2a8,  0, 3 },
+       [PAD_GPIO42]    = { 0x2a8,  3, 3 },
+       [PAD_GPIO43]    = { 0x2a8,  6, 3 },
+       [PAD_GPIO44]    = { 0x2a8,  9, 3 },
+       [PAD_GPIO45]    = { 0x2a8, 12, 3 },
+       [PAD_GPIO46]    = { 0x2a8, 15, 3 },
+       [PAD_GPIO47]    = { 0x2a8, 18, 3 },
+       [PAD_GPIO48]    = { 0x2a8, 21, 3 },
+       [PAD_GPIO49]    = { 0x2a8, 24, 3 },
+       [PAD_GPIO50]    = { 0x2a8, 27, 3 },
+       [PAD_GPIO51]    = { 0x2a8, 30, 3 },
+
+       [PAD_GPIO52]    = { 0x2ac,  0, 3 },
+       [PAD_GPIO53]    = { 0x2ac,  2, 3 },
+       [PAD_GPIO54]    = { 0x2ac,  4, 3 },
+       [PAD_GPIO55]    = { 0x2ac,  6, 3 },
+       [PAD_GPIO56]    = { 0x2ac,  9, 3 },
+       [PAD_GPIO57]    = { 0x2ac, 12, 3 },
+       [PAD_GPIO58]    = { 0x2ac, 15, 3 },
+       [PAD_GPIO59]    = { 0x2ac, 18, 3 },
+       [PAD_GPIO60]    = { 0x2ac, 21, 3 },
+       [PAD_GPIO61]    = { 0x2ac, 24, 3 },
+       [PAD_GPIO62]    = { 0x2ac, 27, 3 },
+       [PAD_GPIO63]    = { 0x2ac, 30, 3 },
+
+       [PAD_GPIO6]     = { 0x2b0,  0, 3 },
+       [PAD_GPIO7]     = { 0x2b0,  2, 3 },
+       [PAD_GPIO8]     = { 0x2b0,  5, 3 },
+       [PAD_GPIO9]     = { 0x2b0,  8, 3 },
+};
+
+struct jh7110_vin_group_sel {
+       u16 offset;
+       u8 shift;
+       u8 group;
+};
+
+static const struct jh7110_vin_group_sel
+       jh7110_sys_vin_group_sel[ARRAY_SIZE(jh7110_sys_pins)] = {
+       [PAD_GPIO6]     = { 0x2b4, 21, 0 },
+       [PAD_GPIO7]     = { 0x2b4, 18, 0 },
+       [PAD_GPIO8]     = { 0x2b4, 15, 0 },
+       [PAD_GPIO9]     = { 0x2b0, 11, 0 },
+       [PAD_GPIO10]    = { 0x2b0, 20, 0 },
+       [PAD_GPIO11]    = { 0x2b0, 23, 0 },
+       [PAD_GPIO12]    = { 0x2b0, 26, 0 },
+       [PAD_GPIO13]    = { 0x2b0, 29, 0 },
+       [PAD_GPIO14]    = { 0x2b4,  0, 0 },
+       [PAD_GPIO15]    = { 0x2b4,  3, 0 },
+       [PAD_GPIO16]    = { 0x2b4,  6, 0 },
+       [PAD_GPIO17]    = { 0x2b4,  9, 0 },
+       [PAD_GPIO18]    = { 0x2b4, 12, 0 },
+       [PAD_GPIO19]    = { 0x2b0, 14, 0 },
+       [PAD_GPIO20]    = { 0x2b0, 17, 0 },
+
+       [PAD_GPIO21]    = { 0x2b4, 21, 1 },
+       [PAD_GPIO22]    = { 0x2b4, 18, 1 },
+       [PAD_GPIO23]    = { 0x2b4, 15, 1 },
+       [PAD_GPIO24]    = { 0x2b0, 11, 1 },
+       [PAD_GPIO25]    = { 0x2b0, 20, 1 },
+       [PAD_GPIO26]    = { 0x2b0, 23, 1 },
+       [PAD_GPIO27]    = { 0x2b0, 26, 1 },
+       [PAD_GPIO28]    = { 0x2b0, 29, 1 },
+       [PAD_GPIO29]    = { 0x2b4,  0, 1 },
+       [PAD_GPIO30]    = { 0x2b4,  3, 1 },
+       [PAD_GPIO31]    = { 0x2b4,  6, 1 },
+       [PAD_GPIO32]    = { 0x2b4,  9, 1 },
+       [PAD_GPIO33]    = { 0x2b4, 12, 1 },
+       [PAD_GPIO34]    = { 0x2b0, 14, 1 },
+       [PAD_GPIO35]    = { 0x2b0, 17, 1 },
+
+       [PAD_GPIO36]    = { 0x2b4, 21, 2 },
+       [PAD_GPIO37]    = { 0x2b4, 18, 2 },
+       [PAD_GPIO38]    = { 0x2b4, 15, 2 },
+       [PAD_GPIO39]    = { 0x2b0, 11, 2 },
+       [PAD_GPIO40]    = { 0x2b0, 20, 2 },
+       [PAD_GPIO41]    = { 0x2b0, 23, 2 },
+       [PAD_GPIO42]    = { 0x2b0, 26, 2 },
+       [PAD_GPIO43]    = { 0x2b0, 29, 2 },
+       [PAD_GPIO44]    = { 0x2b4,  0, 2 },
+       [PAD_GPIO45]    = { 0x2b4,  3, 2 },
+       [PAD_GPIO46]    = { 0x2b4,  6, 2 },
+       [PAD_GPIO47]    = { 0x2b4,  9, 2 },
+       [PAD_GPIO48]    = { 0x2b4, 12, 2 },
+       [PAD_GPIO49]    = { 0x2b0, 14, 2 },
+       [PAD_GPIO50]    = { 0x2b0, 17, 2 },
+};
+
+static void jh7110_set_function(struct udevice *dev,
+                               unsigned int pin, u32 func)
+{
+       const struct jh7110_func_sel *fs = &jh7110_sys_func_sel[pin];
+       struct starfive_pinctrl_priv *priv = dev_get_priv(dev);
+       void __iomem *reg;
+       u32 mask;
+
+       if (!fs->offset)
+               return;
+
+       if (func > fs->max)
+               return;
+
+       reg = priv->base + fs->offset;
+       func = func << fs->shift;
+       mask = 0x3U << fs->shift;
+
+       func |= readl(reg) & ~mask;
+       writel(func, reg);
+}
+
+static void jh7110_set_vin_group(struct udevice *dev, unsigned int pin)
+{
+       const struct jh7110_vin_group_sel *gs =
+               &jh7110_sys_vin_group_sel[pin];
+       struct starfive_pinctrl_priv *priv = dev_get_priv(dev);
+       void __iomem *reg;
+       u32 mask;
+       u32 grp;
+
+       if (!gs->offset)
+               return;
+
+       reg = priv->base + gs->offset;
+       grp = gs->group << gs->shift;
+       mask = 0x3U << gs->shift;
+
+       grp |= readl(reg) & ~mask;
+       writel(grp, reg);
+}
+
+static int jh7110_sys_set_one_pin_mux(struct udevice *dev, unsigned int pin,
+                                     unsigned int din, u32 dout, u32 doen, u32 func)
+{
+       struct starfive_pinctrl_priv *priv = dev_get_priv(dev);
+
+       if (pin < priv->info->ngpios && func == 0)
+               starfive_set_gpiomux(dev, pin, din, dout, doen);
+
+       jh7110_set_function(dev, pin, func);
+
+       if (pin < priv->info->ngpios && func == 2)
+               jh7110_set_vin_group(dev, pin);
+
+       return 0;
+}
+
+static int jh7110_sys_get_padcfg_base(struct udevice *dev,
+                                     unsigned int pin)
+{
+       if (pin < PAD_GMAC1_MDC)
+               return SYS_GPO_PDA_0_74_CFG;
+       else if (pin > PAD_GMAC1_TXC && pin <= PAD_QSPI_DATA3)
+               return SYS_GPO_PDA_89_94_CFG;
+       else
+               return -1;
+}
+
+static void jh7110_sys_init_hw(struct udevice *dev)
+{
+       struct starfive_pinctrl_priv *priv = dev_get_priv(dev);
+
+       /* mask all GPIO interrupts */
+       writel(0U, priv->base + JH7110_SYS_GPIOIE0);
+       writel(0U, priv->base + JH7110_SYS_GPIOIE1);
+       /* clear edge interrupt flags */
+       writel(~0U, priv->base + JH7110_SYS_GPIOIC0);
+       writel(~0U, priv->base + JH7110_SYS_GPIOIC1);
+       /* enable GPIO interrupts */
+       writel(1U, priv->base + JH7110_SYS_GPIOEN);
+}
+
+const struct starfive_pinctrl_soc_info jh7110_sys_pinctrl_info = {
+       /* pin conf */
+       .set_one_pinmux = jh7110_sys_set_one_pin_mux,
+       .get_padcfg_base = jh7110_sys_get_padcfg_base,
+
+       /* gpio dout/doen/din/gpioinput register */
+       .dout_reg_base = JH7110_SYS_DOUT,
+       .dout_mask = GENMASK(6, 0),
+       .doen_reg_base = JH7110_SYS_DOEN,
+       .doen_mask = GENMASK(5, 0),
+       .gpi_reg_base = JH7110_SYS_GPI,
+       .gpi_mask = GENMASK(6, 0),
+       .gpioin_reg_base = JH7110_SYS_GPIOIN,
+
+       /* gpio */
+       .gpio_bank_name = "GPIO",
+       .ngpios = JH7110_SYS_NGPIO,
+       .gpio_init_hw = jh7110_sys_init_hw,
+};
+
+static int jh7110_sys_pinctrl_probe(struct udevice *dev)
+{
+       struct starfive_pinctrl_soc_info *info =
+               (struct starfive_pinctrl_soc_info *)dev_get_driver_data(dev);
+
+       return starfive_pinctrl_probe(dev, info);
+}
+
+static const struct udevice_id jh7110_sys_pinctrl_ids[] = {
+       /* JH7110 sys pinctrl */
+       { .compatible = "starfive,jh7110-sys-pinctrl",
+         .data = (ulong)&jh7110_sys_pinctrl_info, },
+       { /* sentinel */ }
+};
+
+U_BOOT_DRIVER(jh7110_sys_pinctrl) = {
+       .name           = "jh7110-sys-pinctrl",
+       .id             = UCLASS_PINCTRL,
+       .of_match       = jh7110_sys_pinctrl_ids,
+       .priv_auto      = sizeof(struct starfive_pinctrl_priv),
+       .ops            = &starfive_pinctrl_ops,
+       .probe          = jh7110_sys_pinctrl_probe,
+};
diff --git a/drivers/pinctrl/starfive/pinctrl-starfive.c b/drivers/pinctrl/starfive/pinctrl-starfive.c
new file mode 100644 (file)
index 0000000..9b09cc2
--- /dev/null
@@ -0,0 +1,398 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Pinctrl / GPIO driver for StarFive JH7100 SoC
+ *
+ * Copyright (C) 2022 Shanghai StarFive Technology Co., Ltd.
+ *   Author: Lee Kuan Lim <kuanlim.lee@starfivetech.com>
+ *   Author: Jianlong Huang <jianlong.huang@starfivetech.com>
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <dm/device-internal.h>
+#include <dm/lists.h>
+#include <dm/pinctrl.h>
+#include <asm-generic/gpio.h>
+#include <linux/bitops.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <dm/device_compat.h>
+#include <dt-bindings/pinctrl/pinctrl-starfive-jh7110.h>
+
+#include "pinctrl-starfive.h"
+
+/* pad control bits */
+#define STARFIVE_PADCFG_POS    BIT(7)
+#define STARFIVE_PADCFG_SMT    BIT(6)
+#define STARFIVE_PADCFG_SLEW   BIT(5)
+#define STARFIVE_PADCFG_PD     BIT(4)
+#define STARFIVE_PADCFG_PU     BIT(3)
+#define STARFIVE_PADCFG_BIAS   (STARFIVE_PADCFG_PD | STARFIVE_PADCFG_PU)
+#define STARFIVE_PADCFG_DS_MASK        GENMASK(2, 1)
+#define STARFIVE_PADCFG_DS_2MA (0U << 1)
+#define STARFIVE_PADCFG_DS_4MA BIT(1)
+#define STARFIVE_PADCFG_DS_8MA (2U << 1)
+#define STARFIVE_PADCFG_DS_12MA        (3U << 1)
+#define STARFIVE_PADCFG_IE     BIT(0)
+#define GPIO_NUM_PER_WORD      32
+
+/*
+ * The packed pinmux values from the device tree look like this:
+ *
+ *  | 31 - 24 | 23 - 16 | 15 - 10 |  9 - 8   | 7 - 0 |
+ *  |   din   |  dout   |  doen   | function |  pin  |
+ */
+static unsigned int starfive_pinmux_din(u32 v)
+{
+       return (v & GENMASK(31, 24)) >> 24;
+}
+
+static u32 starfive_pinmux_dout(u32 v)
+{
+       return (v & GENMASK(23, 16)) >> 16;
+}
+
+static u32 starfive_pinmux_doen(u32 v)
+{
+       return (v & GENMASK(15, 10)) >> 10;
+}
+
+static u32 starfive_pinmux_function(u32 v)
+{
+       return (v & GENMASK(9, 8)) >> 8;
+}
+
+static unsigned int starfive_pinmux_pin(u32 v)
+{
+       return v & GENMASK(7, 0);
+}
+
+void starfive_set_gpiomux(struct udevice *dev, unsigned int pin,
+                         unsigned int din, u32 dout, u32 doen)
+{
+       struct starfive_pinctrl_priv *priv = dev_get_priv(dev);
+       const struct starfive_pinctrl_soc_info *info = priv->info;
+
+       unsigned int offset = 4 * (pin / 4);
+       unsigned int shift  = 8 * (pin % 4);
+       u32 dout_mask = info->dout_mask << shift;
+       u32 done_mask = info->doen_mask << shift;
+       u32 ival, imask;
+       void __iomem *reg_dout;
+       void __iomem *reg_doen;
+       void __iomem *reg_din;
+
+       reg_dout = priv->base + info->dout_reg_base + offset;
+       reg_doen = priv->base + info->doen_reg_base + offset;
+       dout <<= shift;
+       doen <<= shift;
+       if (din != GPI_NONE) {
+               unsigned int ioffset = 4 * (din / 4);
+               unsigned int ishift  = 8 * (din % 4);
+
+               reg_din = priv->base + info->gpi_reg_base + ioffset;
+               ival = (pin + 2) << ishift;
+               imask = info->gpi_mask << ishift;
+       } else {
+               reg_din = NULL;
+       }
+
+       dout |= readl(reg_dout) & ~dout_mask;
+       writel(dout, reg_dout);
+       doen |= readl(reg_doen) & ~done_mask;
+       writel(doen, reg_doen);
+       if (reg_din) {
+               ival |= readl(reg_din) & ~imask;
+               writel(ival, reg_din);
+       }
+}
+
+static const struct pinconf_param starfive_pinconf_params[] = {
+       { "bias-disable",       PIN_CONFIG_BIAS_DISABLE,        0 },
+       { "bias-pull-up",       PIN_CONFIG_BIAS_PULL_UP,        1 },
+       { "bias-pull-down",     PIN_CONFIG_BIAS_PULL_DOWN,      1 },
+       { "drive-strength",     PIN_CONFIG_DRIVE_STRENGTH,      0 },
+       { "input-schmitt-enable",  PIN_CONFIG_INPUT_SCHMITT_ENABLE, 1 },
+       { "input-schmitt-disable", PIN_CONFIG_INPUT_SCHMITT_ENABLE, 0 },
+       { "input-enable",       PIN_CONFIG_INPUT_ENABLE,        1 },
+       { "input-disable",      PIN_CONFIG_INPUT_ENABLE,        0 },
+       { "slew-rate",          PIN_CONFIG_SLEW_RATE,           0 },
+};
+
+static const u8 starfive_drive_strength_mA[4] = { 2, 4, 8, 12 };
+
+static u32 starfive_padcfg_ds_from_mA(u32 v)
+{
+       int i;
+
+       for (i = 0; i < 3; i++) {
+               if (v <= starfive_drive_strength_mA[i])
+                       break;
+       }
+       return i << 1;
+}
+
+static void starfive_padcfg_rmw(struct udevice *dev,
+                               unsigned int pin, u32 mask, u32 value)
+{
+       struct starfive_pinctrl_priv *priv = dev_get_priv(dev);
+       struct starfive_pinctrl_soc_info *info = priv->info;
+       void __iomem *reg;
+       int padcfg_base;
+
+       if (!info->get_padcfg_base)
+               return;
+
+       padcfg_base = info->get_padcfg_base(dev, pin);
+       if (padcfg_base < 0)
+               return;
+
+       reg = priv->base + padcfg_base + 4 * pin;
+       value &= mask;
+
+       value |= readl(reg) & ~mask;
+       writel(value, reg);
+}
+
+static int starfive_pinconf_set(struct udevice *dev, unsigned int pin,
+                               unsigned int param, unsigned int arg)
+{
+       u16 mask = 0;
+       u16 value = 0;
+
+       switch (param) {
+       case PIN_CONFIG_BIAS_DISABLE:
+               mask |= STARFIVE_PADCFG_BIAS;
+               value &= ~STARFIVE_PADCFG_BIAS;
+               break;
+       case PIN_CONFIG_BIAS_PULL_DOWN:
+               if (arg == 0)
+                       return -EINVAL;
+               mask |= STARFIVE_PADCFG_BIAS;
+               value = (value & ~STARFIVE_PADCFG_BIAS) | STARFIVE_PADCFG_PD;
+               break;
+       case PIN_CONFIG_BIAS_PULL_UP:
+               if (arg == 0)
+                       return -EINVAL;
+               mask |= STARFIVE_PADCFG_BIAS;
+               value = (value & ~STARFIVE_PADCFG_BIAS) | STARFIVE_PADCFG_PU;
+               break;
+       case PIN_CONFIG_DRIVE_STRENGTH:
+               mask |= STARFIVE_PADCFG_DS_MASK;
+               value = (value & ~STARFIVE_PADCFG_DS_MASK) |
+                       starfive_padcfg_ds_from_mA(arg);
+               break;
+       case PIN_CONFIG_INPUT_ENABLE:
+               mask |= STARFIVE_PADCFG_IE;
+               if (arg)
+                       value |= STARFIVE_PADCFG_IE;
+               else
+                       value &= ~STARFIVE_PADCFG_IE;
+               break;
+       case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
+               mask |= STARFIVE_PADCFG_SMT;
+               if (arg)
+                       value |= STARFIVE_PADCFG_SMT;
+               else
+                       value &= ~STARFIVE_PADCFG_SMT;
+               break;
+       case PIN_CONFIG_SLEW_RATE:
+               mask |= STARFIVE_PADCFG_SLEW;
+               if (arg)
+                       value |= STARFIVE_PADCFG_SLEW;
+               else
+                       value &= ~STARFIVE_PADCFG_SLEW;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       starfive_padcfg_rmw(dev, pin, mask, value);
+
+       return 0;
+}
+
+static int starfive_property_set(struct udevice *dev, u32 pinmux_group)
+{
+       struct starfive_pinctrl_priv *priv = dev_get_priv(dev);
+       struct starfive_pinctrl_soc_info *info = priv->info;
+
+       if (info->set_one_pinmux)
+               info->set_one_pinmux(dev,
+                       starfive_pinmux_pin(pinmux_group),
+                       starfive_pinmux_din(pinmux_group),
+                       starfive_pinmux_dout(pinmux_group),
+                       starfive_pinmux_doen(pinmux_group),
+                       starfive_pinmux_function(pinmux_group));
+
+       return starfive_pinmux_pin(pinmux_group);
+}
+
+const struct pinctrl_ops starfive_pinctrl_ops = {
+       .set_state = pinctrl_generic_set_state,
+       .pinconf_num_params     = ARRAY_SIZE(starfive_pinconf_params),
+       .pinconf_params         = starfive_pinconf_params,
+       .pinconf_set            = starfive_pinconf_set,
+       .pinmux_property_set = starfive_property_set,
+};
+
+static int starfive_gpio_get_direction(struct udevice *dev, unsigned int off)
+{
+       struct udevice *pdev = dev->parent;
+       struct starfive_pinctrl_priv *priv = dev_get_priv(pdev);
+       struct starfive_pinctrl_soc_info *info = priv->info;
+
+       unsigned int offset = 4 * (off / 4);
+       unsigned int shift  = 8 * (off % 4);
+       u32 doen = readl(priv->base + info->doen_reg_base + offset);
+
+       doen = (doen >> shift) & info->doen_mask;
+
+       return doen == GPOEN_ENABLE ? GPIOF_OUTPUT : GPIOF_INPUT;
+}
+
+static int starfive_gpio_direction_input(struct udevice *dev, unsigned int off)
+{
+       struct udevice *pdev = dev->parent;
+       struct starfive_pinctrl_priv *priv = dev_get_priv(pdev);
+       struct starfive_pinctrl_soc_info *info = priv->info;
+
+       /* enable input and schmitt trigger */
+       starfive_padcfg_rmw(pdev, off,
+                           STARFIVE_PADCFG_IE | STARFIVE_PADCFG_SMT,
+                           STARFIVE_PADCFG_IE | STARFIVE_PADCFG_SMT);
+
+       if (info->set_one_pinmux)
+               info->set_one_pinmux(pdev, off,
+                               GPI_NONE, GPOUT_LOW, GPOEN_DISABLE, 0);
+
+       return 0;
+}
+
+static int starfive_gpio_direction_output(struct udevice *dev,
+                                         unsigned int off, int val)
+{
+       struct udevice *pdev = dev->parent;
+       struct starfive_pinctrl_priv *priv = dev_get_priv(pdev);
+       struct starfive_pinctrl_soc_info *info = priv->info;
+
+       if (info->set_one_pinmux)
+               info->set_one_pinmux(pdev, off,
+                               GPI_NONE, val ? GPOUT_HIGH : GPOUT_LOW,
+                               GPOEN_ENABLE, 0);
+
+       /* disable input, schmitt trigger and bias */
+       starfive_padcfg_rmw(pdev, off,
+                           STARFIVE_PADCFG_IE | STARFIVE_PADCFG_SMT
+                           | STARFIVE_PADCFG_BIAS,
+                           0);
+
+       return 0;
+}
+
+static int starfive_gpio_get_value(struct udevice *dev, unsigned int off)
+{
+       struct udevice *pdev = dev->parent;
+       struct starfive_pinctrl_priv *priv = dev_get_priv(pdev);
+       struct starfive_pinctrl_soc_info *info = priv->info;
+
+       void __iomem *reg = priv->base + info->gpioin_reg_base
+                       + 4 * (off / GPIO_NUM_PER_WORD);
+
+       return !!(readl(reg) & BIT(off % GPIO_NUM_PER_WORD));
+}
+
+static int starfive_gpio_set_value(struct udevice *dev,
+                                  unsigned int off, int val)
+{
+       struct udevice *pdev = dev->parent;
+       struct starfive_pinctrl_priv *priv = dev_get_priv(pdev);
+       struct starfive_pinctrl_soc_info *info = priv->info;
+
+       unsigned int offset = 4 * (off / 4);
+       unsigned int shift  = 8 * (off % 4);
+       void __iomem *reg_dout = priv->base + info->dout_reg_base + offset;
+       u32 dout = (val ? GPOUT_HIGH : GPOUT_LOW) << shift;
+       u32 mask = info->dout_mask << shift;
+
+       dout |= readl(reg_dout) & ~mask;
+       writel(dout, reg_dout);
+
+       return 0;
+}
+
+static int starfive_gpio_probe(struct udevice *dev)
+{
+       struct gpio_dev_priv *uc_priv;
+       struct udevice *pdev = dev->parent;
+       struct starfive_pinctrl_priv *priv = dev_get_priv(pdev);
+       struct starfive_pinctrl_soc_info *info = priv->info;
+
+       uc_priv = dev_get_uclass_priv(dev);
+       uc_priv->bank_name = info->gpio_bank_name;
+       uc_priv->gpio_count = info->ngpios;
+
+       if (!info->gpio_init_hw)
+               return -ENXIO;
+
+       info->gpio_init_hw(pdev);
+
+       return 0;
+}
+
+static const struct dm_gpio_ops starfive_gpio_ops = {
+       .get_function = starfive_gpio_get_direction,
+       .direction_input = starfive_gpio_direction_input,
+       .direction_output = starfive_gpio_direction_output,
+       .get_value = starfive_gpio_get_value,
+       .set_value = starfive_gpio_set_value,
+};
+
+static struct driver starfive_gpio_driver = {
+       .name = "starfive_gpio",
+       .id = UCLASS_GPIO,
+       .probe = starfive_gpio_probe,
+       .ops = &starfive_gpio_ops,
+};
+
+static int starfive_gpiochip_register(struct udevice *parent)
+{
+       struct uclass_driver *drv;
+       struct udevice *dev;
+       int ret;
+       ofnode node;
+
+       drv = lists_uclass_lookup(UCLASS_GPIO);
+       if (!drv)
+               return -ENOENT;
+
+       node = dev_ofnode(parent);
+       ret = device_bind_with_driver_data(parent, &starfive_gpio_driver,
+                                          "starfive_gpio", 0, node, &dev);
+
+       return (ret == 0) ? 0 : ret;
+}
+
+int starfive_pinctrl_probe(struct udevice *dev,
+                          const struct starfive_pinctrl_soc_info *info)
+{
+       struct starfive_pinctrl_priv *priv = dev_get_priv(dev);
+       int ret;
+
+       /* Bind pinctrl_info from .data to priv */
+       priv->info =
+               (struct starfive_pinctrl_soc_info *)dev_get_driver_data(dev);
+
+       if (!priv->info)
+               return -EINVAL;
+
+       priv->base = dev_read_addr_ptr(dev);
+       if (!priv->base)
+               return -EINVAL;
+
+       /* gpiochip register */
+       ret = starfive_gpiochip_register(dev);
+
+       return (ret == 0) ? 0 : ret;
+}
diff --git a/drivers/pinctrl/starfive/pinctrl-starfive.h b/drivers/pinctrl/starfive/pinctrl-starfive.h
new file mode 100644 (file)
index 0000000..5721c3c
--- /dev/null
@@ -0,0 +1,55 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Pinctrl / GPIO driver for StarFive SoC
+ *
+ * Copyright (C) 2022 Shanghai StarFive Technology Co., Ltd.
+ *   Author: Lee Kuan Lim <kuanlim.lee@starfivetech.com>
+ *   Author: Jianlong Huang <jianlong.huang@starfivetech.com>
+ */
+
+#define STARFIVE_PINCTRL(a, b) { .number = a, .name = b }
+
+extern const struct pinctrl_ops starfive_pinctrl_ops;
+
+struct starfive_pinctrl_pin {
+       unsigned int number;
+       const char *name;
+};
+
+struct starfive_pinctrl_soc_info {
+       /* pinctrl */
+       int (*set_one_pinmux)(struct udevice *dev, unsigned int pin,
+                             unsigned int din, u32 dout, u32 doen, u32 func);
+       int (*get_padcfg_base)(struct udevice *dev,
+                              unsigned int pin);
+
+       /* gpio dout/doen/din/gpioinput register */
+       unsigned int dout_reg_base;
+       unsigned int dout_mask;
+       unsigned int doen_reg_base;
+       unsigned int doen_mask;
+       unsigned int gpi_reg_base;
+       unsigned int gpi_mask;
+       unsigned int gpioin_reg_base;
+
+       /* gpio */
+       const char *gpio_bank_name;
+       int ngpios;
+       void (*gpio_init_hw)(struct udevice *dev);
+};
+
+/*
+ * struct starfive_pinctrl_priv - private data for Starfive pinctrl driver
+ *
+ * @padctl_base: base address of the pinctrl device
+ * @info: SoC specific data & function
+ */
+struct starfive_pinctrl_priv {
+       void __iomem *base;
+       struct starfive_pinctrl_soc_info *info;
+};
+
+void starfive_set_gpiomux(struct udevice *dev, unsigned int pin,
+                         unsigned int din, u32 dout, u32 doen);
+int starfive_pinctrl_probe(struct udevice *dev,
+                          const struct starfive_pinctrl_soc_info *info);