VisionFive2 Linux kernel

StarFive Tech Linux Kernel for VisionFive (JH7110) boards (mirror)

More than 9999 Commits   33 Branches   57 Tags
author: “zpc-123” <“jenny.zhang@starfivetech.com”> 2021-11-19 02:28:09 -0800 committer: “zpc-123” <“jenny.zhang@starfivetech.com”> 2021-11-19 02:28:09 -0800 commit: 8f0997b2ea609ba50830df8f0c08c1d491b2addb parent: dff6ddff161c09255eeed5c790605d9eae4ee9b0
Commit Summary:
[pinctrl] add vic7100 pinctrl driver
Diffstat:
7 files changed, 1648 insertions, 0 deletions
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
old mode 100644
new mode 100755
index 815095326e2d..87ff4984b3c6
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -400,6 +400,7 @@ source "drivers/pinctrl/zte/Kconfig"
 source "drivers/pinctrl/meson/Kconfig"
 source "drivers/pinctrl/cirrus/Kconfig"
 source "drivers/pinctrl/visconti/Kconfig"
+source "drivers/pinctrl/starfive/Kconfig"
 
 config PINCTRL_XWAY
 	bool
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
old mode 100644
new mode 100755
index f53933b2ff02..e8a17103d1c5
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -72,3 +72,4 @@ obj-y				+= mediatek/
 obj-$(CONFIG_PINCTRL_ZX)	+= zte/
 obj-y				+= cirrus/
 obj-$(CONFIG_PINCTRL_VISCONTI)	+= visconti/
+obj-$(CONFIG_PINCTRL_STARFIVE)	+= starfive/
\ No newline at end of file
diff --git a/drivers/pinctrl/starfive/Kconfig b/drivers/pinctrl/starfive/Kconfig
new file mode 100755
index 000000000000..772fcf850d05
--- /dev/null
+++ b/drivers/pinctrl/starfive/Kconfig
@@ -0,0 +1,24 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+config PINCTRL_STARFIVE
+	bool "Pinctrl driver for the StarFive SoC"
+	depends on OF
+	depends on RISCV || COMPILE_TEST
+	select GENERIC_PINCTRL_GROUPS
+	select GENERIC_PINMUX_FUNCTIONS
+	select GENERIC_PINCONF
+	select GPIOLIB
+	select GPIOLIB_IRQCHIP
+	select OF_GPIO
+	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_VIC7100
+	bool "Pinctrl and GPIO driver for the StarFive vic7100 SoC"
+	depends on PINCTRL_STARFIVE
+	help
+	  This selects the pinctrl driver for vic7100 starfive.
+	
\ No newline at end of file
diff --git a/drivers/pinctrl/starfive/Makefile b/drivers/pinctrl/starfive/Makefile
new file mode 100755
index 000000000000..f187336fb793
--- /dev/null
+++ b/drivers/pinctrl/starfive/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0
+# Core
+obj-$(CONFIG_PINCTRL_STARFIVE) += pinctrl-starfive.o
+
+# SoC Drivers
+obj-$(CONFIG_PINCTRL_STARFIVE_VIC7100)	+= pinctrl-starfive-vic7100.o
diff --git a/drivers/pinctrl/starfive/pinctrl-starfive-vic7100.c b/drivers/pinctrl/starfive/pinctrl-starfive-vic7100.c
new file mode 100755
index 000000000000..6486a38a2a14
--- /dev/null
+++ b/drivers/pinctrl/starfive/pinctrl-starfive-vic7100.c
@@ -0,0 +1,1070 @@
+/**
+  ******************************************************************************
+  * @file  pinctrl-starfive-vic7100.c
+  * @author  StarFive Technology
+  * @version  V1.0
+  * @date  11/19/2021
+  * @brief
+  ******************************************************************************
+  * @copy
+  *
+  * THE PRESENT SOFTWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
+  * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
+  * TIME. AS A RESULT, STARFIVE SHALL NOT BE HELD LIABLE FOR ANY
+  * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
+  * FROM THE CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
+  * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
+  *
+  * <h2><center>&copy; COPYRIGHT 20120 Shanghai StarFive Technology Co., Ltd. </center></h2>
+  */
+
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/of.h>
+#include <linux/gpio/driver.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/of_device.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+
+#include "../core.h"
+#include "../pinconf.h"
+#include "../pinmux.h"
+#include "pinctrl-starfive.h"
+
+#define IO_PAD_SCFG_QSPI_IOCTRL			0x19c
+#define IO_PADSHARE_SEL_REG_REG			0x1a0
+#define IO_PAD_CTRL_SEL_FUNC_0_REG_ADDR    	0x0
+#define IO_PAD_CTRL_SEL_FUNC_1_REG_ADDR    	0x0
+#define IO_PAD_CTRL_SEL_FUNC_2_REG_ADDR    	0x110
+#define IO_PAD_CTRL_SEL_FUNC_3_REG_ADDR    	0x10c
+#define IO_PAD_CTRL_SEL_FUNC_4_REG_ADDR    	0x80
+#define IO_PAD_CTRL_SEL_FUNC_5_REG_ADDR    	0x80
+#define IO_PAD_CTRL_SEL_FUNC_6_REG_ADDR    	0x80
+#define IO_PADSHARE_SEL_REG_MAX		   	6
+
+/*gpio dout/don/din reg*/
+#define GPO_DOUT_CFG_BASE_REG 			0x50
+#define GPO_DOEN_CFG_BASE_REG 			0x54
+#define GPI_DIN_CFG_BASE_REG			0x250
+
+#define GPO_DOUT_CFG_REG_OFFSET 		8
+#define GPO_DOEN_CFG_REG_OFFSET 		8
+#define GPI_DIN_CFG_REG_OFFSET 			4
+
+#define GPI_DIN_ADDR_END			74
+
+#define GPIO_EN        				0x0
+#define GPIO_IS_LOW    				0x10
+#define GPIO_IS_HIGH   				0x14
+#define GPIO_IBE_LOW   				0x18
+#define GPIO_IBE_HIGH  				0x1c
+#define GPIO_IEV_LOW   				0x20
+#define GPIO_IEV_HIGH  				0x24
+#define GPIO_IE_LOW    				0x28
+#define GPIO_IE_HIGH  				0x2c
+#define GPIO_IC_LOW    				0x30
+#define GPIO_IC_HIGH   				0x34
+//read only
+#define GPIO_RIS_LOW   				0x38
+#define GPIO_RIS_HIGH  				0x3c
+#define GPIO_MIS_LOW   				0x40
+#define GPIO_MIS_HIGH  				0x44
+#define GPIO_DIN_LOW   				0x48
+#define GPIO_DIN_HIGH  				0x4c
+
+
+enum starfive_vic700_pads {
+	PAD_GPIO_0 = 0,
+	PAD_GPIO_1 = 1,
+	PAD_GPIO_2 = 2,
+	PAD_GPIO_3 = 3,
+	PAD_GPIO_4 = 4,
+	PAD_GPIO_5 = 5,
+	PAD_GPIO_6 = 6,
+	PAD_GPIO_7 = 7,
+	PAD_GPIO_8 = 8,
+	PAD_GPIO_9 = 9,
+	PAD_GPIO_10 = 10,
+	PAD_GPIO_11 = 11,
+	PAD_GPIO_12 = 12,
+	PAD_GPIO_13 = 13,
+	PAD_GPIO_14 = 14,
+	PAD_GPIO_15 = 15,
+	PAD_GPIO_16 = 16,
+	PAD_GPIO_17 = 17,
+	PAD_GPIO_18 = 18,
+	PAD_GPIO_19 = 19,
+	PAD_GPIO_20 = 20,
+	PAD_GPIO_21 = 21,
+	PAD_GPIO_22 = 22,
+	PAD_GPIO_23 = 23,
+	PAD_GPIO_24 = 24,
+	PAD_GPIO_25 = 25,
+	PAD_GPIO_26 = 26,
+	PAD_GPIO_27 = 27,
+	PAD_GPIO_28 = 28,
+	PAD_GPIO_29 = 29,
+	PAD_GPIO_30 = 30,
+	PAD_GPIO_31 = 31,
+	PAD_GPIO_32 = 32,
+	PAD_GPIO_33 = 33,
+	PAD_GPIO_34 = 34,
+	PAD_GPIO_35 = 35,
+	PAD_GPIO_36 = 36,
+	PAD_GPIO_37 = 37,
+	PAD_GPIO_38 = 38,
+	PAD_GPIO_39 = 39,
+	PAD_GPIO_40 = 40,
+	PAD_GPIO_41 = 41,
+	PAD_GPIO_42 = 42,
+	PAD_GPIO_43 = 43,
+	PAD_GPIO_44 = 44,
+	PAD_GPIO_45 = 45,
+	PAD_GPIO_46 = 46,
+	PAD_GPIO_47 = 47,
+	PAD_GPIO_48 = 48,
+	PAD_GPIO_49 = 49,
+	PAD_GPIO_50 = 50,
+	PAD_GPIO_51 = 51,
+	PAD_GPIO_52 = 52,
+	PAD_GPIO_53 = 53,
+	PAD_GPIO_54 = 54,
+	PAD_GPIO_55 = 55,
+	PAD_GPIO_56 = 56,
+	PAD_GPIO_57 = 57,
+	PAD_GPIO_58 = 58,
+	PAD_GPIO_59 = 59,
+	PAD_GPIO_60 = 60,
+	PAD_GPIO_61 = 61,
+	PAD_GPIO_62 = 62,
+	PAD_GPIO_63 = 63,
+	PAD_FUNC_SHARE_0 = 64,
+	PAD_FUNC_SHARE_1 = 65,
+	PAD_FUNC_SHARE_2 = 66,
+	PAD_FUNC_SHARE_3 = 67,
+	PAD_FUNC_SHARE_4 = 68,
+	PAD_FUNC_SHARE_5 = 69,
+	PAD_FUNC_SHARE_6 = 70,
+	PAD_FUNC_SHARE_7 = 71,
+	PAD_FUNC_SHARE_8 = 72,
+	PAD_FUNC_SHARE_9 = 73,
+	PAD_FUNC_SHARE_10 = 74,
+	PAD_FUNC_SHARE_11 = 75,
+	PAD_FUNC_SHARE_12 = 76,
+	PAD_FUNC_SHARE_13 = 77,
+	PAD_FUNC_SHARE_14 = 78,
+	PAD_FUNC_SHARE_15 = 79,
+	PAD_FUNC_SHARE_16 = 80,
+	PAD_FUNC_SHARE_17 = 81,
+	PAD_FUNC_SHARE_18 = 82,
+	PAD_FUNC_SHARE_19 = 83,
+	PAD_FUNC_SHARE_20 = 84,
+	PAD_FUNC_SHARE_21 = 85,
+	PAD_FUNC_SHARE_22 = 86,
+	PAD_FUNC_SHARE_23 = 87,
+	PAD_FUNC_SHARE_24 = 88,
+	PAD_FUNC_SHARE_25 = 89,
+	PAD_FUNC_SHARE_26 = 90,
+	PAD_FUNC_SHARE_27 = 91,
+	PAD_FUNC_SHARE_28 = 92,
+	PAD_FUNC_SHARE_29 = 93,
+	PAD_FUNC_SHARE_30 = 94,
+	PAD_FUNC_SHARE_31 = 95,
+	PAD_FUNC_SHARE_32 = 96,
+	PAD_FUNC_SHARE_33 = 97,
+	PAD_FUNC_SHARE_34 = 98,
+	PAD_FUNC_SHARE_35 = 99,
+	PAD_FUNC_SHARE_36 = 100,
+	PAD_FUNC_SHARE_37 = 101,
+	PAD_FUNC_SHARE_38 = 102,
+	PAD_FUNC_SHARE_39 = 103,
+	PAD_FUNC_SHARE_40 = 104,
+	PAD_FUNC_SHARE_41 = 105,
+	PAD_FUNC_SHARE_42 = 106,
+	PAD_FUNC_SHARE_43 = 107,
+	PAD_FUNC_SHARE_44 = 108,
+	PAD_FUNC_SHARE_45 = 109,
+	PAD_FUNC_SHARE_46 = 110,
+	PAD_FUNC_SHARE_47 = 111,
+	PAD_FUNC_SHARE_48 = 112,
+	PAD_FUNC_SHARE_49 = 113,
+	PAD_FUNC_SHARE_50 = 114,
+	PAD_FUNC_SHARE_51 = 115,
+	PAD_FUNC_SHARE_52 = 116,
+	PAD_FUNC_SHARE_53 = 117,
+	PAD_FUNC_SHARE_54 = 118,
+	PAD_FUNC_SHARE_55 = 119,
+	PAD_FUNC_SHARE_56 = 120,
+	PAD_FUNC_SHARE_57 = 121,
+	PAD_FUNC_SHARE_58 = 122,
+	PAD_FUNC_SHARE_59 = 123,
+	PAD_FUNC_SHARE_60 = 124,
+	PAD_FUNC_SHARE_61 = 125,
+	PAD_FUNC_SHARE_62 = 126,
+	PAD_FUNC_SHARE_63 = 127,
+	PAD_FUNC_SHARE_64 = 128,
+	PAD_FUNC_SHARE_65 = 129,
+	PAD_FUNC_SHARE_66 = 130,
+	PAD_FUNC_SHARE_67 = 131,
+	PAD_FUNC_SHARE_68 = 132,
+	PAD_FUNC_SHARE_69 = 133,
+	PAD_FUNC_SHARE_70 = 134,
+	PAD_FUNC_SHARE_71 = 135,
+	PAD_FUNC_SHARE_72 = 136,
+	PAD_FUNC_SHARE_73 = 137,
+	PAD_FUNC_SHARE_74 = 138,
+	PAD_FUNC_SHARE_75 = 139,
+	PAD_FUNC_SHARE_76 = 140,
+	PAD_FUNC_SHARE_77 = 141,
+	PAD_FUNC_SHARE_78 = 142,
+	PAD_FUNC_SHARE_79 = 143,
+	PAD_FUNC_SHARE_80 = 144,
+	PAD_FUNC_SHARE_81 = 145,
+	PAD_FUNC_SHARE_82 = 146,
+	PAD_FUNC_SHARE_83 = 147,
+	PAD_FUNC_SHARE_84 = 148,
+	PAD_FUNC_SHARE_85 = 149,
+	PAD_FUNC_SHARE_86 = 150,
+	PAD_FUNC_SHARE_87 = 151,
+	PAD_FUNC_SHARE_88 = 152,
+	PAD_FUNC_SHARE_89 = 153,
+	PAD_FUNC_SHARE_90 = 154,
+	PAD_FUNC_SHARE_91 = 155,
+	PAD_FUNC_SHARE_92 = 156,
+	PAD_FUNC_SHARE_93 = 157,
+	PAD_FUNC_SHARE_94 = 158,
+	PAD_FUNC_SHARE_95 = 159,
+	PAD_FUNC_SHARE_96 = 160,
+	PAD_FUNC_SHARE_97 = 161,
+	PAD_FUNC_SHARE_98 = 162,
+	PAD_FUNC_SHARE_99 = 163,
+	PAD_FUNC_SHARE_100 = 164,
+	PAD_FUNC_SHARE_101 = 165,
+	PAD_FUNC_SHARE_102 = 166,
+	PAD_FUNC_SHARE_103 = 167,
+	PAD_FUNC_SHARE_104 = 168,
+	PAD_FUNC_SHARE_105 = 169,
+	PAD_FUNC_SHARE_106 = 170,
+	PAD_FUNC_SHARE_107 = 171,
+	PAD_FUNC_SHARE_108 = 172,
+	PAD_FUNC_SHARE_109 = 173,
+	PAD_FUNC_SHARE_110 = 174,
+	PAD_FUNC_SHARE_111 = 175,
+	PAD_FUNC_SHARE_112 = 176,
+	PAD_FUNC_SHARE_113 = 177,
+	PAD_FUNC_SHARE_114 = 178,
+	PAD_FUNC_SHARE_115 = 179,
+	PAD_FUNC_SHARE_116 = 180,
+	PAD_FUNC_SHARE_117 = 181,
+	PAD_FUNC_SHARE_118 = 182,
+	PAD_FUNC_SHARE_119 = 183,
+	PAD_FUNC_SHARE_120 = 184,
+	PAD_FUNC_SHARE_121 = 185,
+	PAD_FUNC_SHARE_122 = 186,
+	PAD_FUNC_SHARE_123 = 187,
+	PAD_FUNC_SHARE_124 = 188,
+	PAD_FUNC_SHARE_125 = 189,
+	PAD_FUNC_SHARE_126 = 190,
+	PAD_FUNC_SHARE_127 = 191,
+	PAD_FUNC_SHARE_128 = 192,
+	PAD_FUNC_SHARE_129 = 193,
+	PAD_FUNC_SHARE_130 = 194,
+	PAD_FUNC_SHARE_131 = 195,
+	PAD_FUNC_SHARE_132 = 196,
+	PAD_FUNC_SHARE_133 = 197,
+	PAD_FUNC_SHARE_134 = 198,
+	PAD_FUNC_SHARE_135 = 199,
+	PAD_FUNC_SHARE_136 = 200,
+	PAD_FUNC_SHARE_137 = 201,
+	PAD_FUNC_SHARE_138 = 202,
+	PAD_FUNC_SHARE_139 = 203,
+	PAD_FUNC_SHARE_140 = 204,
+	PAD_FUNC_SHARE_141 = 205,
+};
+
+
+/* Pad names for the pinmux subsystem */
+static const struct pinctrl_pin_desc starfive_vic7100_pinctrl_pads[] = {
+	STARFIVE_PINCTRL_PIN(PAD_GPIO_0),
+	STARFIVE_PINCTRL_PIN(PAD_GPIO_1),
+	STARFIVE_PINCTRL_PIN(PAD_GPIO_2),
+	STARFIVE_PINCTRL_PIN(PAD_GPIO_3),
+	STARFIVE_PINCTRL_PIN(PAD_GPIO_4),
+	STARFIVE_PINCTRL_PIN(PAD_GPIO_5),
+	STARFIVE_PINCTRL_PIN(PAD_GPIO_6),
+	STARFIVE_PINCTRL_PIN(PAD_GPIO_7),
+	STARFIVE_PINCTRL_PIN(PAD_GPIO_8),
+	STARFIVE_PINCTRL_PIN(PAD_GPIO_9),
+	STARFIVE_PINCTRL_PIN(PAD_GPIO_10),
+	STARFIVE_PINCTRL_PIN(PAD_GPIO_11),
+	STARFIVE_PINCTRL_PIN(PAD_GPIO_12),
+	STARFIVE_PINCTRL_PIN(PAD_GPIO_13),
+	STARFIVE_PINCTRL_PIN(PAD_GPIO_14),
+	STARFIVE_PINCTRL_PIN(PAD_GPIO_15),
+	STARFIVE_PINCTRL_PIN(PAD_GPIO_16),
+	STARFIVE_PINCTRL_PIN(PAD_GPIO_17),
+	STARFIVE_PINCTRL_PIN(PAD_GPIO_18),
+	STARFIVE_PINCTRL_PIN(PAD_GPIO_19),
+	STARFIVE_PINCTRL_PIN(PAD_GPIO_20),
+	STARFIVE_PINCTRL_PIN(PAD_GPIO_21),
+	STARFIVE_PINCTRL_PIN(PAD_GPIO_22),
+	STARFIVE_PINCTRL_PIN(PAD_GPIO_23),
+	STARFIVE_PINCTRL_PIN(PAD_GPIO_24),
+	STARFIVE_PINCTRL_PIN(PAD_GPIO_25),
+	STARFIVE_PINCTRL_PIN(PAD_GPIO_26),
+	STARFIVE_PINCTRL_PIN(PAD_GPIO_27),
+	STARFIVE_PINCTRL_PIN(PAD_GPIO_28),
+	STARFIVE_PINCTRL_PIN(PAD_GPIO_29),
+	STARFIVE_PINCTRL_PIN(PAD_GPIO_30),
+	STARFIVE_PINCTRL_PIN(PAD_GPIO_31),
+	STARFIVE_PINCTRL_PIN(PAD_GPIO_32),
+	STARFIVE_PINCTRL_PIN(PAD_GPIO_33),
+	STARFIVE_PINCTRL_PIN(PAD_GPIO_34),
+	STARFIVE_PINCTRL_PIN(PAD_GPIO_35),
+	STARFIVE_PINCTRL_PIN(PAD_GPIO_36),
+	STARFIVE_PINCTRL_PIN(PAD_GPIO_37),
+	STARFIVE_PINCTRL_PIN(PAD_GPIO_38),
+	STARFIVE_PINCTRL_PIN(PAD_GPIO_39),
+	STARFIVE_PINCTRL_PIN(PAD_GPIO_40),
+	STARFIVE_PINCTRL_PIN(PAD_GPIO_41),
+	STARFIVE_PINCTRL_PIN(PAD_GPIO_42),
+	STARFIVE_PINCTRL_PIN(PAD_GPIO_43),
+	STARFIVE_PINCTRL_PIN(PAD_GPIO_44),
+	STARFIVE_PINCTRL_PIN(PAD_GPIO_45),
+	STARFIVE_PINCTRL_PIN(PAD_GPIO_46),
+	STARFIVE_PINCTRL_PIN(PAD_GPIO_47),
+	STARFIVE_PINCTRL_PIN(PAD_GPIO_48),
+	STARFIVE_PINCTRL_PIN(PAD_GPIO_49),
+	STARFIVE_PINCTRL_PIN(PAD_GPIO_50),
+	STARFIVE_PINCTRL_PIN(PAD_GPIO_51),
+	STARFIVE_PINCTRL_PIN(PAD_GPIO_52),
+	STARFIVE_PINCTRL_PIN(PAD_GPIO_53),
+	STARFIVE_PINCTRL_PIN(PAD_GPIO_54),
+	STARFIVE_PINCTRL_PIN(PAD_GPIO_55),
+	STARFIVE_PINCTRL_PIN(PAD_GPIO_56),
+	STARFIVE_PINCTRL_PIN(PAD_GPIO_57),
+	STARFIVE_PINCTRL_PIN(PAD_GPIO_58),
+	STARFIVE_PINCTRL_PIN(PAD_GPIO_59),
+	STARFIVE_PINCTRL_PIN(PAD_GPIO_60),
+	STARFIVE_PINCTRL_PIN(PAD_GPIO_61),
+	STARFIVE_PINCTRL_PIN(PAD_GPIO_62),
+	STARFIVE_PINCTRL_PIN(PAD_GPIO_63),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_0),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_1),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_2),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_3),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_4),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_5),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_6),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_7),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_8),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_9),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_10),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_11),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_12),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_13),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_14),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_15),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_16),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_17),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_18),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_19),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_20),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_21),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_22),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_23),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_24),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_25),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_26),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_27),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_28),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_29),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_30),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_31),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_32),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_33),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_34),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_35),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_36),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_37),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_38),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_39),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_40),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_41),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_42),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_43),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_44),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_45),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_46),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_47),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_48),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_49),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_50),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_51),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_52),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_53),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_54),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_55),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_56),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_57),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_58),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_59),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_60),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_61),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_62),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_63),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_64),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_65),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_66),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_67),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_68),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_69),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_70),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_71),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_72),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_73),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_74),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_75),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_76),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_77),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_78),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_79),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_80),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_81),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_82),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_83),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_84),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_85),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_86),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_87),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_88),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_89),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_90),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_91),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_92),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_93),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_94),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_95),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_96),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_97),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_98),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_99),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_100),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_101),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_102),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_103),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_104),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_105),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_106),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_107),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_108),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_109),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_110),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_111),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_112),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_113),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_114),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_115),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_116),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_117),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_118),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_119),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_120),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_121),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_122),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_123),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_124),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_125),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_126),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_127),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_128),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_129),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_130),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_131),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_132),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_133),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_134),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_135),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_136),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_137),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_138),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_139),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_140),
+	STARFIVE_PINCTRL_PIN(PAD_FUNC_SHARE_141),
+};
+	
+static unsigned int starfive_vic7100_gpio_to_pin(const struct starfive_pinctrl *chip,
+					 unsigned int gpio)
+{
+	return gpio + chip->gpios.pin_base;
+}
+
+static void starfive_vic7100_padctl_rmw(struct starfive_pinctrl *chip,
+				unsigned int pin,
+				u16 _mask, u16 _value)
+{
+	void __iomem *reg = chip->padctl_base + 4 * (pin / 2);
+	u32 mask = _mask;
+	u32 value = _value;
+	unsigned long flags;
+
+	if (pin & 1U) {
+		value <<= 16;
+		mask <<= 16;
+	}
+
+	raw_spin_lock_irqsave(&chip->lock, flags);
+	value |= readl_relaxed(reg) & ~mask;
+	writel_relaxed(value, reg);
+	raw_spin_unlock_irqrestore(&chip->lock, flags);
+}
+
+
+static int starfive_vic7100_direction_input(struct gpio_chip *gc, unsigned gpio)
+{
+	struct starfive_pinctrl *chip = gpiochip_get_data(gc);
+	unsigned long flags;
+
+	if (gpio >= gc->ngpio)
+		return -EINVAL;
+	
+	/* enable input and schmitt trigger */
+	starfive_vic7100_padctl_rmw(chip, starfive_vic7100_gpio_to_pin(chip, gpio),
+			PAD_INPUT_ENABLE | PAD_INPUT_SCHMITT_ENABLE,
+			PAD_INPUT_ENABLE | PAD_INPUT_SCHMITT_ENABLE);
+
+	raw_spin_lock_irqsave(&chip->lock, flags);
+	writel_relaxed(0x1, chip->gpio_base + GPO_DOEN_CFG_BASE_REG + gpio * 8);
+	raw_spin_unlock_irqrestore(&chip->lock, flags);
+
+	return 0;
+}
+
+static int starfive_vic7100_direction_output(struct gpio_chip *gc, unsigned gpio, int value)
+{
+	struct starfive_pinctrl *chip = gpiochip_get_data(gc);
+	unsigned long flags;
+
+	if (gpio >= gc->ngpio)
+		return -EINVAL;
+	
+	raw_spin_lock_irqsave(&chip->lock, flags);
+	writel_relaxed(0x0, chip->gpio_base + GPO_DOEN_CFG_BASE_REG + gpio * 8);
+	writel_relaxed(value, chip->gpio_base + GPO_DOUT_CFG_BASE_REG + gpio * 8);
+	raw_spin_unlock_irqrestore(&chip->lock, flags);
+
+	/* disable input, schmitt trigger and bias */
+	starfive_vic7100_padctl_rmw(chip, starfive_vic7100_gpio_to_pin(chip, gpio),
+			PAD_BIAS_MASK | PAD_INPUT_ENABLE | PAD_INPUT_SCHMITT_ENABLE,
+			PAD_BIAS_DISABLE);
+
+	return 0;
+}
+
+static int starfive_vic7100_get_direction(struct gpio_chip *gc, unsigned gpio)
+{
+	struct starfive_pinctrl *chip = gpiochip_get_data(gc);
+
+	if (gpio >= gc->ngpio)
+		return -EINVAL;
+
+	return readl_relaxed(chip->gpio_base + GPO_DOEN_CFG_BASE_REG + gpio * 8) & 0x1;
+}
+
+static int starfive_vic7100_get_value(struct gpio_chip *gc, unsigned gpio)
+{
+	struct starfive_pinctrl *chip = gpiochip_get_data(gc);
+	int value;
+
+	if (gpio >= gc->ngpio)
+		return -EINVAL;
+
+	if(gpio < 32){
+		value = readl_relaxed(chip->gpio_base + GPIO_DIN_LOW);
+		return (value >> gpio) & 0x1;
+	} else {
+		value = readl_relaxed(chip->gpio_base + GPIO_DIN_HIGH);
+		return (value >> (gpio - 32)) & 0x1;
+	}
+}
+
+static void starfive_vic7100_set_value(struct gpio_chip *gc, unsigned gpio, int value)
+{
+	struct starfive_pinctrl *chip = gpiochip_get_data(gc);
+	unsigned long flags;
+
+	if (gpio >= gc->ngpio)
+		return;
+
+	raw_spin_lock_irqsave(&chip->lock, flags);
+	writel_relaxed(value, chip->gpio_base + GPO_DOUT_CFG_BASE_REG + gpio * 8);
+	raw_spin_unlock_irqrestore(&chip->lock, flags);
+}
+
+static void starfive_vic7100_set_ie(struct starfive_pinctrl *chip, int gpio)
+{
+	unsigned long flags;
+	int old_value, new_value;
+	int reg_offset, index;
+
+	if(gpio < 32) {
+		reg_offset = 0;
+		index = gpio;
+	} else {
+		reg_offset = 4;
+		index = gpio - 32;
+	}
+	raw_spin_lock_irqsave(&chip->lock, flags);
+	old_value = readl_relaxed(chip->gpio_base + GPIO_IE_LOW + reg_offset);
+	new_value = old_value | ( 1 << index);
+	writel_relaxed(new_value, chip->gpio_base + GPIO_IE_LOW + reg_offset);
+	raw_spin_unlock_irqrestore(&chip->lock, flags);
+}
+
+static int starfive_vic7100_irq_set_type(struct irq_data *d, unsigned trigger)
+{
+	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+	struct starfive_pinctrl *chip = gpiochip_get_data(gc);
+	int offset = irqd_to_hwirq(d);
+	unsigned int reg_is, reg_ibe, reg_iev;
+	int reg_offset, index;
+
+	if (offset < 0 || offset >= gc->ngpio)
+		return -EINVAL;
+
+	if(offset < 32) {
+		reg_offset = 0;
+		index = offset;
+	} else {
+		reg_offset = 4;
+		index = offset - 32;
+	}
+	switch(trigger) {
+	case IRQ_TYPE_LEVEL_HIGH:
+		reg_is = readl_relaxed(chip->gpio_base + GPIO_IS_LOW + reg_offset);
+		reg_ibe = readl_relaxed(chip->gpio_base + GPIO_IBE_LOW + reg_offset);
+		reg_iev = readl_relaxed(chip->gpio_base + GPIO_IEV_LOW + reg_offset);
+		reg_is  &= (~(0x1<< index));
+		reg_ibe &= (~(0x1<< index));
+		reg_iev |= (0x1<< index);
+		writel_relaxed(reg_is, chip->gpio_base + GPIO_IS_LOW + reg_offset);
+		writel_relaxed(reg_is, chip->gpio_base + GPIO_IS_LOW + reg_offset);
+		writel_relaxed(reg_is, chip->gpio_base + GPIO_IS_LOW + reg_offset);
+		break;
+	case IRQ_TYPE_LEVEL_LOW:
+		reg_is = readl_relaxed(chip->gpio_base + GPIO_IS_LOW + reg_offset);
+		reg_ibe = readl_relaxed(chip->gpio_base + GPIO_IBE_LOW + reg_offset);
+		reg_iev = readl_relaxed(chip->gpio_base + GPIO_IEV_LOW + reg_offset);
+		reg_is  &= (~(0x1<< index));
+		reg_ibe &= (~(0x1<< index));
+		reg_iev &= (0x1<< index);
+		writel_relaxed(reg_is, chip->gpio_base + GPIO_IS_LOW + reg_offset);
+		writel_relaxed(reg_is, chip->gpio_base + GPIO_IS_LOW + reg_offset);
+		writel_relaxed(reg_is, chip->gpio_base + GPIO_IS_LOW + reg_offset);
+		break;
+	case IRQ_TYPE_EDGE_BOTH:
+		reg_is = readl_relaxed(chip->gpio_base + GPIO_IS_LOW + reg_offset);
+		reg_ibe = readl_relaxed(chip->gpio_base + GPIO_IBE_LOW + reg_offset);
+		//reg_iev = readl_relaxed(chip->gpio_base + GPIO_IEV_LOW + reg_offset);
+		reg_is  |= (~(0x1<< index));
+		reg_ibe |= (~(0x1<< index));
+		//reg_iev |= (0x1<< index);
+		writel_relaxed(reg_is, chip->gpio_base + GPIO_IS_LOW + reg_offset);
+		writel_relaxed(reg_is, chip->gpio_base + GPIO_IS_LOW + reg_offset);
+		//writel_relaxed(reg_is, chip->gpio_base + GPIO_IS_LOW + reg_offset);
+		break;
+	case IRQ_TYPE_EDGE_RISING:
+		reg_is = readl_relaxed(chip->gpio_base + GPIO_IS_LOW + reg_offset);
+		reg_ibe = readl_relaxed(chip->gpio_base + GPIO_IBE_LOW + reg_offset);
+		reg_iev = readl_relaxed(chip->gpio_base + GPIO_IEV_LOW + reg_offset);
+		reg_is  |= (~(0x1<< index));
+		reg_ibe &= (~(0x1<< index));
+		reg_iev |= (0x1<< index);
+		writel_relaxed(reg_is, chip->gpio_base + GPIO_IS_LOW + reg_offset);
+		writel_relaxed(reg_is, chip->gpio_base + GPIO_IS_LOW + reg_offset);
+		writel_relaxed(reg_is, chip->gpio_base + GPIO_IS_LOW + reg_offset);
+		break;
+	case IRQ_TYPE_EDGE_FALLING:
+		reg_is = readl_relaxed(chip->gpio_base + GPIO_IS_LOW + reg_offset);
+		reg_ibe = readl_relaxed(chip->gpio_base + GPIO_IBE_LOW + reg_offset);
+		reg_iev = readl_relaxed(chip->gpio_base + GPIO_IEV_LOW + reg_offset);
+		reg_is  |= (~(0x1<< index));
+		reg_ibe &= (~(0x1<< index));
+		reg_iev &= (0x1<< index);
+		writel_relaxed(reg_is, chip->gpio_base + GPIO_IS_LOW + reg_offset);
+		writel_relaxed(reg_is, chip->gpio_base + GPIO_IS_LOW + reg_offset);
+		writel_relaxed(reg_is, chip->gpio_base + GPIO_IS_LOW + reg_offset);
+		break;
+	}
+
+	chip->trigger[offset] = trigger;
+	starfive_vic7100_set_ie(chip, offset);
+	return 0;
+}
+
+
+/* chained_irq_{enter,exit} already mask the parent */
+static void starfive_vic7100_irq_mask(struct irq_data *d)
+{
+	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+	struct starfive_pinctrl *chip = gpiochip_get_data(gc);
+	unsigned int value;
+	int offset = irqd_to_hwirq(d);
+	int reg_offset, index;
+
+	if (offset < 0 || offset >= gc->ngpio)
+		return;
+
+	if(offset < 32) {
+		reg_offset = 0;
+		index = offset;
+	} else {
+		reg_offset = 4;
+		index = offset - 32;
+	}
+
+	value = readl_relaxed(chip->gpio_base + GPIO_IE_LOW + reg_offset);
+	value &= ~(0x1 << index);
+	writel_relaxed(value,chip->gpio_base + GPIO_IE_LOW + reg_offset);
+}
+
+static void starfive_vic7100_irq_unmask(struct irq_data *d)
+{
+	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+	struct starfive_pinctrl *chip = gpiochip_get_data(gc);
+	unsigned int value;
+	int offset = irqd_to_hwirq(d);
+	int reg_offset, index;
+
+	if (offset < 0 || offset >= gc->ngpio)
+		return;
+
+	if(offset < 32) {
+		reg_offset = 0;
+		index = offset;
+	} else {
+		reg_offset = 4;
+		index = offset - 32;
+	}
+
+	value = readl_relaxed(chip->gpio_base + GPIO_IE_LOW + reg_offset);
+	value |= (0x1 << index);
+	writel_relaxed(value,chip->gpio_base + GPIO_IE_LOW + reg_offset);
+}
+
+static void starfive_vic7100_irq_enable(struct irq_data *d)
+{
+	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+	struct starfive_pinctrl *chip = gpiochip_get_data(gc);
+	int offset = irqd_to_hwirq(d);
+
+	starfive_vic7100_irq_unmask(d);
+	assign_bit(offset, &chip->enabled, 1);
+}
+
+static void starfive_vic7100_irq_disable(struct irq_data *d)
+{
+	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+	struct starfive_pinctrl *chip = gpiochip_get_data(gc);
+	int offset = irqd_to_hwirq(d) % MAX_GPIO; // must not fail
+
+	assign_bit(offset, &chip->enabled, 0);
+	starfive_vic7100_set_ie(chip, offset);
+}
+
+static struct irq_chip starfive_irqchip = {
+	.name		= "starfive-gpio",
+	.irq_set_type	= starfive_vic7100_irq_set_type,
+	.irq_mask	= starfive_vic7100_irq_mask,
+	.irq_unmask	= starfive_vic7100_irq_unmask,
+	.irq_enable	= starfive_vic7100_irq_enable,
+	.irq_disable	= starfive_vic7100_irq_disable,
+};
+
+static irqreturn_t starfive_vic7100_irq_handler(int irq, void *gc)
+{
+	int offset;
+	// = self_ptr - &chip->self_ptr[0];
+	int reg_offset, index;
+	unsigned int value;
+	unsigned long flags;
+	struct starfive_pinctrl *chip = gc;
+
+	for (offset = 0; offset < 64; offset++) {
+		if(offset < 32) {
+			reg_offset = 0;
+			index = offset;
+		} else {
+			reg_offset = 4;
+			index = offset - 32;
+		}
+
+		raw_spin_lock_irqsave(&chip->lock, flags);
+		value = readl_relaxed(chip->gpio_base + GPIO_MIS_LOW + reg_offset);
+		if(value & BIT(index))
+			writel_relaxed(BIT(index), chip->gpio_base + GPIO_IC_LOW +
+						   reg_offset);
+
+		//generic_handle_irq(irq_find_mapping(chip->gc.irq.domain,
+		//				      offset));
+		raw_spin_unlock_irqrestore(&chip->lock, flags);
+	}
+
+	return IRQ_HANDLED;
+}
+
+
+static int starfive_vic7100_gpio_register(struct platform_device *pdev,
+					struct starfive_pinctrl *ipctl)
+{
+	struct device *dev = &pdev->dev;
+	struct resource *res;
+	int irq, ret, ngpio;
+
+	ngpio = MAX_GPIO;
+	
+	ipctl->gc.direction_input = starfive_vic7100_direction_input;
+	ipctl->gc.direction_output = starfive_vic7100_direction_output;
+	ipctl->gc.get_direction = starfive_vic7100_get_direction;
+	ipctl->gc.get = starfive_vic7100_get_value;
+	ipctl->gc.set = starfive_vic7100_set_value;
+	ipctl->gc.base = 0;
+	ipctl->gc.ngpio = ngpio;
+	ipctl->gc.label = dev_name(dev);
+	ipctl->gc.parent = dev;
+	ipctl->gc.owner = THIS_MODULE;
+
+	ret = gpiochip_add_data(&ipctl->gc, ipctl);
+	if (ret){
+		dev_err(dev, "gpiochip_add_data ret=%d!\n", ret);
+		return ret;
+	}
+
+	/* Disable all GPIO interrupts before enabling parent interrupts */
+	iowrite32(0, ipctl->gpio_base + GPIO_IE_HIGH);
+	iowrite32(0, ipctl->gpio_base + GPIO_IE_LOW);
+	ipctl->enabled = 0;
+
+	ret = gpiochip_irqchip_add(&ipctl->gc, &starfive_irqchip, 0,
+				   handle_simple_irq, IRQ_TYPE_NONE);
+	if (ret) {
+		dev_err(dev, "could not add irqchip\n");
+		gpiochip_remove(&ipctl->gc);
+		return ret;
+	}
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(dev, "Cannot get IRQ resource\n");
+		return irq;
+	}
+
+	ret = devm_request_irq(dev, irq, starfive_vic7100_irq_handler, IRQF_SHARED,
+			       dev_name(dev), ipctl);
+	if (ret) {
+		dev_err(dev, "IRQ handler registering failed (%d)\n", ret);
+		return ret;
+	}
+
+	writel_relaxed(1, ipctl->gpio_base + GPIO_EN);
+
+	return 0;
+}
+
+
+static int starfive_vic7100_pinconf_get(struct pinctrl_dev *pctldev, unsigned pin_id,
+				unsigned long *config)
+{
+	struct starfive_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
+	const struct starfive_pinctrl_soc_info *info = ipctl->info;
+	const struct starfive_pin_reg *pin_reg = &ipctl->pin_regs[pin_id];
+	unsigned int offset_reg;
+	u32 value;
+		
+	if (pin_reg->io_conf_reg == -1) {
+		dev_err(ipctl->dev, "Pin(%s) does not support config function\n",
+			info->pins[pin_id].name);
+		return -EINVAL;
+	}
+	offset_reg = (pin_reg->io_conf_reg/2)*4;
+	value = readl_relaxed(ipctl->padctl_base + offset_reg);
+
+	if(pin_reg->io_conf_reg%2)
+		*config = value >> 16; //high 16bit
+	else
+		*config = value & 0xFFFF; //low 16bit
+
+	return 0;
+}
+
+		       
+static int starfive_vic7100_pinconf_set(struct pinctrl_dev *pctldev,
+				unsigned pin_id, unsigned long *configs,
+				unsigned num_configs)
+{
+	struct starfive_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
+	const struct starfive_pinctrl_soc_info *info = ipctl->info;
+	const struct starfive_pin_reg *pin_reg = &ipctl->pin_regs[pin_id];
+	int i;
+	unsigned int offset_reg;
+	u32 value;
+	unsigned long flags;
+
+	if (pin_reg->io_conf_reg == -1) {
+		dev_err(ipctl->dev, "Pin(%s) does not support config function\n",
+			info->pins[pin_id].name);
+		return -EINVAL;
+	}
+	
+	raw_spin_lock_irqsave(&ipctl->lock, flags);
+	for (i = 0; i < num_configs; i++) {
+	
+		offset_reg = (pin_reg->io_conf_reg/2)*4;
+		value = readl_relaxed(ipctl->padctl_base + offset_reg);
+	
+		if(pin_reg->io_conf_reg%2)
+			value = value|((configs[i] & 0xFFFF) << 16);//high 16bit
+		else
+			value = value|(configs[i] & 0xFFFF);//low 16bit
+	
+		writel_relaxed(value, ipctl->padctl_base + offset_reg);
+	} 
+	raw_spin_unlock_irqrestore(&ipctl->lock, flags);
+
+	return 0;
+}
+
+static int starfive_vic7100_iopad_sel_func(struct starfive_pinctrl *ipctl, unsigned int func_id)
+{
+	unsigned int value;
+
+	value = readl_relaxed(ipctl->padctl_base + IO_PADSHARE_SEL_REG_REG);
+	value &= 0x7;
+
+	if (value <= IO_PADSHARE_SEL_REG_MAX){
+		switch (value) {
+			case 0:
+				ipctl->padctl_gpio_base = IO_PAD_CTRL_SEL_FUNC_0_REG_ADDR;
+				ipctl->padctl_gpio0 = PAD_GPIO_0;
+				break;
+			case 1:
+				ipctl->padctl_gpio_base = IO_PAD_CTRL_SEL_FUNC_1_REG_ADDR;
+				ipctl->padctl_gpio0 = PAD_GPIO_0;
+				break;
+			case 2:
+				ipctl->padctl_gpio_base = IO_PAD_CTRL_SEL_FUNC_2_REG_ADDR;
+				ipctl->padctl_gpio0 = PAD_FUNC_SHARE_72;
+				break;
+			case 3:
+				ipctl->padctl_gpio_base = IO_PAD_CTRL_SEL_FUNC_3_REG_ADDR;
+				ipctl->padctl_gpio0 = PAD_FUNC_SHARE_70;
+				break;
+			case 4: case 5: case 6:
+				ipctl->padctl_gpio_base = IO_PAD_CTRL_SEL_FUNC_4_REG_ADDR;
+				ipctl->padctl_gpio0 = PAD_FUNC_SHARE_0;
+				break;
+			default:
+				dev_err(ipctl->dev, "invalid signal group %u\n", func_id);
+				return -EINVAL;
+		}
+		return 0;
+	}
+	else{
+		dev_err(ipctl->dev,"invalid signal group %u\n", func_id);
+		return -EINVAL;
+	}
+}
+
+
+static int starfive_vic7100_pmx_set_one_pin_mux(struct starfive_pinctrl *ipctl,
+				    struct starfive_pin *pin)
+{
+	const struct starfive_pinctrl_soc_info *info = ipctl->info;
+	struct starfive_pin_config *pin_config = &pin->pin_config;
+	const struct starfive_pin_reg *pin_reg;
+	unsigned int pin_id;
+	u32 value;
+	int i;
+	unsigned long flags;
+	
+	pin_id = pin->pin;
+	pin_reg = &ipctl->pin_regs[pin_id];
+	
+	raw_spin_lock_irqsave(&ipctl->lock, flags);
+	if(pin_config->pinmux_func == PINMUX_GPIO_FUNC){
+		if(pin_reg->gpo_dout_reg != -1){
+			writel_relaxed(pin_config->gpio_dout, ipctl->gpio_base + pin_reg->gpo_dout_reg);
+		}
+
+		if(pin_reg->gpo_doen_reg != -1){
+			writel_relaxed(pin_config->gpio_doen, ipctl->gpio_base + pin_reg->gpo_doen_reg);
+		}
+
+		for(i = 0; i < pin_config->gpio_din_num; i++){
+			if((pin_config->gpio_din_reg[i] >= info->din_reg_base) &&
+			  (pin_config->gpio_din_reg[i] <= info->din_reg_base + GPI_DIN_ADDR_END*info->din_reg_offset)){
+				writel_relaxed((pin_config->gpio_num + 2), ipctl->gpio_base + pin_config->gpio_din_reg[i]);
+			}
+		}
+	}
+	raw_spin_unlock_irqrestore(&ipctl->lock, flags);
+	
+	return 0;
+}
+
+
+static const struct starfive_pinctrl_soc_info starfive_vic7100_pinctrl_info = {
+	.pins = starfive_vic7100_pinctrl_pads,
+	.npins = ARRAY_SIZE(starfive_vic7100_pinctrl_pads),
+	.dout_reg_base = GPO_DOUT_CFG_BASE_REG,
+	.dout_reg_offset = GPO_DOUT_CFG_REG_OFFSET,
+	.doen_reg_base = GPO_DOEN_CFG_BASE_REG,
+	.doen_reg_offset = GPO_DOEN_CFG_REG_OFFSET,
+	.din_reg_base = GPI_DIN_CFG_BASE_REG,
+	.din_reg_offset = GPI_DIN_CFG_REG_OFFSET,
+	.starfive_iopad_sel_func = starfive_vic7100_iopad_sel_func,
+	.starfive_pinconf_get = starfive_vic7100_pinconf_get,
+	.starfive_pinconf_set = starfive_vic7100_pinconf_set,
+	.starfive_pmx_set_one_pin_mux = starfive_vic7100_pmx_set_one_pin_mux,
+	.starfive_gpio_register = starfive_vic7100_gpio_register,
+};
+
+
+static const struct of_device_id starfive_vic7100_pinctrl_of_match[] = {
+	{ .compatible = "starfive_vic7100-pinctrl", .data = &starfive_vic7100_pinctrl_info, },
+	{ /* sentinel */ }
+};
+
+static int starfive_vic7100_pinctrl_probe(struct platform_device *pdev)
+{
+	const struct starfive_pinctrl_soc_info *pinctrl_info;
+
+	pinctrl_info = of_device_get_match_data(&pdev->dev);
+	if (!pinctrl_info)
+		return -ENODEV;
+	
+
+	return starfive_pinctrl_probe(pdev, pinctrl_info);
+}
+
+static struct platform_driver starfive_vic7100_pinctrl_driver = {
+	.driver = {
+		.name = "starfive_vic7100-pinctrl",
+		.of_match_table = of_match_ptr(starfive_vic7100_pinctrl_of_match),
+	},
+	.probe = starfive_vic7100_pinctrl_probe,
+};
+
+static int __init starfive_vic7100_pinctrl_init(void)
+{
+	return platform_driver_register(&starfive_vic7100_pinctrl_driver);
+}
+arch_initcall(starfive_vic7100_pinctrl_init);
diff --git a/drivers/pinctrl/starfive/pinctrl-starfive.c b/drivers/pinctrl/starfive/pinctrl-starfive.c
new file mode 100755
index 000000000000..2f9f99d47040
--- /dev/null
+++ b/drivers/pinctrl/starfive/pinctrl-starfive.c
@@ -0,0 +1,592 @@
+/**
+  ******************************************************************************
+  * @file  pinctrl-starfive.c
+  * @author  StarFive Technology
+  * @version  V1.0
+  * @date  11/19/2021
+  * @brief
+  ******************************************************************************
+  * @copy
+  *
+  * THE PRESENT SOFTWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
+  * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
+  * TIME. AS A RESULT, STARFIVE SHALL NOT BE HELD LIABLE FOR ANY
+  * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
+  * FROM THE CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
+  * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
+  *
+  * <h2><center>&copy; COPYRIGHT 20120 Shanghai StarFive Technology Co., Ltd. </center></h2>
+  */
+
+#include <linux/gpio/driver.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/of_device.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+
+
+#include "../core.h"
+#include "../pinconf.h"
+#include "../pinmux.h"
+#include "pinctrl-starfive.h"
+
+
+static inline const struct group_desc *starfive_pinctrl_find_group_by_name(
+				struct pinctrl_dev *pctldev,
+				const char *name)
+{
+	const struct group_desc *grp = NULL;
+	int i,j;
+	int pinnum;
+	
+	for (i = 0; i < pctldev->num_groups; i++) {
+		grp = pinctrl_generic_get_group(pctldev, i);
+   		if (grp && !strcmp(grp->name, name))
+			break;
+	}
+
+	return grp;
+}
+
+static void starfive_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
+		   unsigned offset)
+{
+	seq_printf(s, "%s", dev_name(pctldev->dev));
+}
+
+static int starfive_dt_node_to_map(struct pinctrl_dev *pctldev,
+			struct device_node *np,
+			struct pinctrl_map **map, unsigned *num_maps)
+{
+	struct starfive_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
+	const struct starfive_pinctrl_soc_info *info = ipctl->info;
+	const struct group_desc *grp;
+	struct pinctrl_map *new_map;
+	struct device_node *parent;
+	struct starfive_pin *pin;
+	int map_num = 1;
+	int i, j;	
+
+	/*
+	 * first find the group of this node and check if we need create
+	 * config maps for pins
+	 */
+	grp = starfive_pinctrl_find_group_by_name(pctldev, np->name);
+	if (!grp) {
+		dev_err(ipctl->dev, "unable to find group for node %pOFn\n", np);
+		return -EINVAL;
+	}
+	 	
+	map_num = grp->num_pins + 1;
+	new_map = kmalloc_array(map_num, sizeof(struct pinctrl_map),
+				GFP_KERNEL);
+	if (!new_map)
+		return -ENOMEM;
+
+	*map = new_map;
+	*num_maps = map_num;
+
+	/* create mux map */
+	parent = of_get_parent(np);
+	if (!parent) {
+		kfree(new_map);
+		return -EINVAL;
+	}
+	new_map[0].type = PIN_MAP_TYPE_MUX_GROUP;
+	new_map[0].data.mux.function = parent->name;
+	new_map[0].data.mux.group = np->name;
+	of_node_put(parent);
+
+	/* create config map */
+	new_map++;
+	for (i = j = 0; i < grp->num_pins; i++) {
+		pin = &((struct starfive_pin *)(grp->data))[i];
+
+		new_map[j].type = PIN_MAP_TYPE_CONFIGS_PIN;
+		new_map[j].data.configs.group_or_pin =
+					pin_get_name(pctldev, pin->pin);
+		new_map[j].data.configs.configs =
+					&pin->pin_config.io_config;
+		new_map[j].data.configs.num_configs = 1;
+ 		j++;
+	}
+
+	return 0;
+}
+
+static void starfive_dt_free_map(struct pinctrl_dev *pctldev,
+				struct pinctrl_map *map, unsigned num_maps)
+{
+	kfree(map);
+}
+
+static const struct pinctrl_ops starfive_pctrl_ops = {
+	.get_groups_count = pinctrl_generic_get_group_count,
+	.get_group_name = pinctrl_generic_get_group_name,
+	.get_group_pins = pinctrl_generic_get_group_pins,
+	.pin_dbg_show = starfive_pin_dbg_show,
+	.dt_node_to_map = starfive_dt_node_to_map,
+	.dt_free_map = starfive_dt_free_map,
+};
+
+
+static int starfive_pmx_set(struct pinctrl_dev *pctldev, unsigned selector,
+		       unsigned group)
+{
+	struct starfive_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
+	const struct starfive_pinctrl_soc_info *info = ipctl->info;
+	struct function_desc *func;
+	struct group_desc *grp;
+	struct starfive_pin *pin;
+	unsigned int npins;
+	int i, err;
+
+	grp = pinctrl_generic_get_group(pctldev, group);
+	if (!grp)
+		return -EINVAL;
+
+	func = pinmux_generic_get_function(pctldev, selector);
+	if (!func)
+		return -EINVAL;
+
+	npins = grp->num_pins;
+
+	dev_dbg(ipctl->dev, "enable function %s group %s\n",
+		func->name, grp->name);
+
+	for (i = 0; i < npins; i++) {
+		pin = &((struct starfive_pin *)(grp->data))[i];
+		if(info->starfive_pmx_set_one_pin_mux){
+			err = info->starfive_pmx_set_one_pin_mux(ipctl, pin);
+			if (err)
+				return err;
+		}
+	}
+
+	return 0;
+}
+
+struct pinmux_ops starfive_pmx_ops = {
+	.get_functions_count = pinmux_generic_get_function_count,
+	.get_function_name = pinmux_generic_get_function_name,
+	.get_function_groups = pinmux_generic_get_function_groups,
+	.set_mux = starfive_pmx_set,
+};
+
+
+static int starfive_pinconf_get(struct pinctrl_dev *pctldev,
+			   unsigned pin_id, unsigned long *config)
+{
+	struct starfive_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
+	const struct starfive_pinctrl_soc_info *info = ipctl->info;
+		
+	if(info->starfive_pinconf_get)
+		return info->starfive_pinconf_get(pctldev, pin_id, config);
+		
+	return 0;
+}
+
+static int starfive_pinconf_set(struct pinctrl_dev *pctldev,
+			   unsigned pin_id, unsigned long *configs,
+			   unsigned num_configs)
+{
+	struct starfive_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
+	const struct starfive_pinctrl_soc_info *info = ipctl->info;
+
+	
+	if(info->starfive_pinconf_set)
+		return info->starfive_pinconf_set(pctldev, pin_id,
+				configs, num_configs);
+	return 0;
+}
+
+static void starfive_pinconf_dbg_show(struct pinctrl_dev *pctldev,
+				   struct seq_file *s, unsigned pin_id)
+{
+	struct starfive_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
+	const struct starfive_pinctrl_soc_info *info = ipctl->info;
+	const struct starfive_pin_reg *pin_reg;
+	unsigned long config;
+	int ret;
+
+	pin_reg = &ipctl->pin_regs[pin_id];
+	if (pin_reg->io_conf_reg == -1) {
+		seq_puts(s, "N/A");
+		return;
+	}
+	
+	ret = starfive_pinconf_get(pctldev, pin_id, &config);
+	if (ret)
+		return;
+	seq_printf(s, "0x%lx", config);
+}
+
+static void starfive_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
+					 struct seq_file *s, unsigned group)
+{
+	struct group_desc *grp;
+	unsigned long config;
+	const char *name;
+	int i, ret;
+
+	if (group >= pctldev->num_groups)
+		return;
+
+	seq_puts(s, "\n");
+	grp = pinctrl_generic_get_group(pctldev, group);
+	if (!grp)
+		return;
+
+	for (i = 0; i < grp->num_pins; i++) {
+		struct starfive_pin *pin = &((struct starfive_pin *)(grp->data))[i];
+
+		name = pin_get_name(pctldev, pin->pin);
+		ret = starfive_pinconf_get(pctldev, pin->pin, &config);
+		if (ret)
+			return;
+		seq_printf(s, "  %s: 0x%lx\n", name, config);
+	}
+}
+
+static const struct pinconf_ops starfive_pinconf_ops = {
+	.pin_config_get = starfive_pinconf_get,
+	.pin_config_set = starfive_pinconf_set,
+	.pin_config_dbg_show = starfive_pinconf_dbg_show,
+	.pin_config_group_dbg_show = starfive_pinconf_group_dbg_show,
+};
+
+static int starfive_pinctrl_parse_groups(struct device_node *np,
+				    struct group_desc *grp,
+				    struct starfive_pinctrl *ipctl,
+				    u32 index)
+{
+	const struct starfive_pinctrl_soc_info *info = ipctl->info;
+	struct starfive_pin *pin_data;
+	struct device_node *child;
+	struct starfive_pin_reg *pin_reg;
+	int *pins_id;
+	int psize, pin_size;
+	int size = 0;
+	int offset = 0;
+	const __be32 *list;
+	const __be32 *list_din;
+	int size_din;
+	int i, j, child_num_pins;
+	u32 value;
+	
+	pin_size = STARFIVE_PINS_SIZE;
+
+	/* Initialise group */
+	grp->name = np->name;
+	
+	for_each_child_of_node(np, child) {
+		list = of_get_property(child, "sf,pins", &psize);
+		if (!list) {
+			dev_err(ipctl->dev,
+				"no sf,pins and pins property in node %pOF\n", np);
+			return -EINVAL;
+		}
+		size += psize;
+	}
+
+	if (!size || size % pin_size) {
+		dev_err(ipctl->dev, 
+			"Invalid sf,pins or pins property in node %pOF\n", np);
+		return -EINVAL;
+	}
+	
+	grp->num_pins = size / pin_size;
+	grp->data = devm_kcalloc(ipctl->dev,
+				 grp->num_pins, sizeof(struct starfive_pin),
+				 GFP_KERNEL);
+	grp->pins = devm_kcalloc(ipctl->dev,
+				 grp->num_pins, sizeof(int),
+				 GFP_KERNEL);
+	if (!grp->pins || !grp->data)
+		return -ENOMEM;	
+		
+	for_each_child_of_node(np, child) {
+		list = of_get_property(child, "sf,pins", &psize);
+		if (!list) {
+			dev_err(ipctl->dev,
+				"no sf,pins and pins property in node %pOF\n", np);
+			return -EINVAL;
+		}
+		
+		child_num_pins = psize / pin_size;
+		for (j = 0; j < child_num_pins; j++) {
+			pin_data = &((struct starfive_pin *)(grp->data))[j + offset];
+			pins_id =  &(grp->pins)[j + offset];
+
+			*pins_id = be32_to_cpu(*list++);
+			pin_data->pin = *pins_id;
+			
+			pin_reg = &ipctl->pin_regs[*pins_id];
+			pin_reg->io_conf_reg = *pins_id;
+
+			if (!of_property_read_u32(child, "sf,pin-ioconfig", &value)) {
+				pin_data->pin_config.io_config = value;
+			}
+
+			if (!of_property_read_u32(child, "sf,pinmux", &value)) {
+ 				pin_data->pin_config.pinmux_func = value & PINMUX_GPIO_FUNC_MASK;
+				
+				if(pin_data->pin_config.pinmux_func == PINMUX_GPIO_FUNC){
+					pin_data->pin_config.gpio_num = value & PINMUX_GPIO_NUM_MASK;
+
+					if (!of_property_read_u32(child, "sf,pin-gpio-dout", &value)) {
+						pin_data->pin_config.gpio_dout = value;
+						pin_reg->gpo_dout_reg = info->dout_reg_base + \
+									(pin_data->pin_config.gpio_num * info->dout_reg_offset);
+					}
+					
+					if (!of_property_read_u32(child, "sf,pin-gpio-doen", &value)) {
+						pin_data->pin_config.gpio_doen = value;
+						pin_reg->gpo_doen_reg = info->doen_reg_base + \
+									(pin_data->pin_config.gpio_num * info->doen_reg_offset);
+					}
+
+					list_din = of_get_property(child, "sf,pin-gpio-din", &size_din);
+					if (list_din) {
+						if (!size_din || size_din % pin_size) {
+							dev_err(ipctl->dev, 
+								"Invalid sf,pin-gpio-din or pins property in node %pOF\n", child);
+							return -EINVAL;
+						}
+						
+						pin_data->pin_config.gpio_din_num = size_din / pin_size;
+						pin_data->pin_config.gpio_din_reg = devm_kcalloc(ipctl->dev,
+									 pin_data->pin_config.gpio_din_num, sizeof(s32),
+									 GFP_KERNEL);
+						
+						for(i = 0; i < pin_data->pin_config.gpio_din_num; i++){
+							value = be32_to_cpu(*list_din++);
+							pin_data->pin_config.gpio_din_reg[i] = info->din_reg_base + \
+											       value*info->din_reg_offset;
+						}
+					}
+				}
+			}
+		}
+		offset += j;
+	}
+	
+	return 0;
+}
+				    
+static int starfive_pinctrl_parse_functions(struct device_node *np,
+				       struct starfive_pinctrl *ipctl,
+				       u32 index)
+{
+	struct pinctrl_dev *pctl = ipctl->pctl;
+	struct device_node *child;
+	struct function_desc *func;
+	struct group_desc *grp;
+	u32 i = 0;	
+
+	func = pinmux_generic_get_function(pctl, index);
+	if (!func)
+		return -EINVAL;
+
+	/* Initialise function */
+	func->name = np->name;
+	func->num_group_names = of_get_child_count(np);
+	if (func->num_group_names == 0) {
+		dev_err(ipctl->dev, "no groups defined in %pOF\n", np);
+		return -EINVAL;
+	}
+	func->group_names = devm_kcalloc(ipctl->dev, func->num_group_names,
+					 sizeof(char *), GFP_KERNEL);
+	if (!func->group_names)
+		return -ENOMEM;
+	
+	for_each_child_of_node(np, child) {
+		func->group_names[i] = child->name;
+ 		grp = devm_kzalloc(ipctl->dev, sizeof(struct group_desc),
+				   GFP_KERNEL);
+		if (!grp) {
+			of_node_put(child);
+			return -ENOMEM;
+		}
+		
+		mutex_lock(&ipctl->mutex);
+		radix_tree_insert(&pctl->pin_group_tree,
+				  ipctl->group_index++, grp);
+		mutex_unlock(&ipctl->mutex);
+
+		starfive_pinctrl_parse_groups(child, grp, ipctl, i++);
+	}
+
+	return 0;
+}
+
+static int starfive_pinctrl_probe_dt(struct platform_device *pdev,
+				struct starfive_pinctrl *ipctl)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct device_node *child;
+	struct pinctrl_dev *pctl = ipctl->pctl;
+	u32 nfuncs = 1;
+	u32 i = 0;
+	int ret;
+
+	if (!np)
+		return -ENODEV;
+
+	for (i = 0; i < nfuncs; i++) {
+		struct function_desc *function;
+
+		function = devm_kzalloc(&pdev->dev, sizeof(*function),
+					GFP_KERNEL);
+		if (!function)
+			return -ENOMEM;
+
+		mutex_lock(&ipctl->mutex);
+		radix_tree_insert(&pctl->pin_function_tree, i, function);
+		mutex_unlock(&ipctl->mutex);
+	}
+	
+	pctl->num_functions = nfuncs;
+	ipctl->group_index = 0;
+	pctl->num_groups = of_get_child_count(np);
+	starfive_pinctrl_parse_functions(np, ipctl, 0);
+
+ 	return 0;
+}
+
+int starfive_pinctrl_probe(struct platform_device *pdev,
+		      const struct starfive_pinctrl_soc_info *info)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *dev_np = pdev->dev.of_node;
+	struct pinctrl_desc *starfive_pinctrl_desc;
+	struct device_node *np;
+	struct starfive_pinctrl *ipctl;
+	struct pinctrl_pin_desc *pins;
+	int ret, i,irq;
+	u32 value;
+
+ 
+	if (!info || !info->pins || !info->npins) {
+		dev_err(&pdev->dev, "wrong pinctrl info\n");
+		return -EINVAL;
+	}
+
+	/* Create state holders etc for this driver */
+	ipctl = devm_kzalloc(&pdev->dev, sizeof(*ipctl), GFP_KERNEL);
+	if (!ipctl)
+		return -ENOMEM;
+
+	ipctl->pin_regs = devm_kmalloc_array(&pdev->dev, info->npins,
+					     sizeof(*ipctl->pin_regs),
+					     GFP_KERNEL);
+	if (!ipctl->pin_regs)
+		return -ENOMEM;
+
+	for (i = 0; i < info->npins; i++) {
+		ipctl->pin_regs[i].io_conf_reg = -1;
+		ipctl->pin_regs[i].gpo_dout_reg = -1;
+		ipctl->pin_regs[i].gpo_doen_reg = -1;
+	}
+	
+	ipctl->padctl_base = devm_platform_ioremap_resource_byname(pdev, "padctl");
+	if (IS_ERR(ipctl->padctl_base))
+		return PTR_ERR(ipctl->padctl_base);
+ 
+	ipctl->gpio_base = devm_platform_ioremap_resource_byname(pdev, "gpio");
+	if (IS_ERR(ipctl->gpio_base))
+		return PTR_ERR(ipctl->gpio_base);
+	
+	if (info->starfive_iopad_sel_func) {
+		ret = info->starfive_iopad_sel_func(ipctl,value);
+		if (ret) 
+			return ret;
+	}
+  
+	starfive_pinctrl_desc = devm_kzalloc(&pdev->dev, sizeof(*starfive_pinctrl_desc),
+					GFP_KERNEL);
+	if (!starfive_pinctrl_desc)
+		return -ENOMEM;
+	
+	raw_spin_lock_init(&ipctl->lock);
+
+	starfive_pinctrl_desc->name = dev_name(&pdev->dev);
+	starfive_pinctrl_desc->pins = info->pins;
+	starfive_pinctrl_desc->npins = info->npins;
+	starfive_pinctrl_desc->pctlops = &starfive_pctrl_ops;
+	starfive_pinctrl_desc->pmxops = &starfive_pmx_ops;
+	starfive_pinctrl_desc->confops = &starfive_pinconf_ops;
+	starfive_pinctrl_desc->owner = THIS_MODULE;
+
+	mutex_init(&ipctl->mutex);
+
+	ipctl->info = info;
+	ipctl->dev = &pdev->dev;
+	platform_set_drvdata(pdev, ipctl);
+	ipctl->gc.parent = dev;
+	ret = devm_pinctrl_register_and_init(&pdev->dev,
+					     starfive_pinctrl_desc, ipctl,
+					     &ipctl->pctl);
+	if (ret) {
+		dev_err(&pdev->dev, 
+			"could not register starfive pinctrl driver\n");
+		return ret;
+	}
+
+	ret = starfive_pinctrl_probe_dt(pdev, ipctl);
+	if (ret) {
+		dev_err(&pdev->dev, 
+			"fail to probe dt properties\n");
+		return ret;
+	}
+	
+ 	ret = pinctrl_enable(ipctl->pctl);
+	if (ret) {
+		dev_err(&pdev->dev, 
+			"pin controller failed to start\n");
+		return ret;
+	}
+
+	if(info->starfive_gpio_register){
+		ret = info->starfive_gpio_register(pdev,ipctl);
+		if (ret) {
+			dev_err(&pdev->dev,
+				"starfive_gpio_register failed to register\n");
+			return ret;
+		}
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(starfive_pinctrl_probe);
+
+static int __maybe_unused starfive_pinctrl_suspend(struct device *dev)
+{
+	struct starfive_pinctrl *ipctl = dev_get_drvdata(dev);
+
+	return pinctrl_force_sleep(ipctl->pctl);
+}
+
+static int __maybe_unused starfive_pinctrl_resume(struct device *dev)
+{
+	struct starfive_pinctrl *ipctl = dev_get_drvdata(dev);
+
+	return pinctrl_force_default(ipctl->pctl);
+}
+
+const struct dev_pm_ops starfive_pinctrl_pm_ops = {
+	SET_LATE_SYSTEM_SLEEP_PM_OPS(starfive_pinctrl_suspend,
+					starfive_pinctrl_resume)
+};
+EXPORT_SYMBOL_GPL(starfive_pinctrl_pm_ops);
+MODULE_AUTHOR("jenny.zhang <jenny.zhang@starfivetech.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/starfive/pinctrl-starfive.h b/drivers/pinctrl/starfive/pinctrl-starfive.h
new file mode 100755
index 000000000000..c9e8ca8345ba
--- /dev/null
+++ b/drivers/pinctrl/starfive/pinctrl-starfive.h
@@ -0,0 +1,138 @@
+/**
+  ******************************************************************************
+  * @file  pinctrl-starfive.h
+  * @author  StarFive Technology
+  * @version  V1.0
+  * @date  05/27/2021
+  * @brief
+  ******************************************************************************
+  * @copy
+  *
+  * THE PRESENT SOFTWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
+  * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
+  * TIME. AS A RESULT, STARFIVE SHALL NOT BE HELD LIABLE FOR ANY
+  * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
+  * FROM THE CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
+  * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
+  *
+  * <h2><center>&copy; COPYRIGHT 20120 Shanghai StarFive Technology Co., Ltd. </center></h2>
+  */
+
+#ifndef __DRIVERS_PINCTRL_STARFIVE_H
+#define __DRIVERS_PINCTRL_STARFIVE_H
+
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/pinctrl/pinmux.h>
+
+
+#define MAX_GPIO			64
+
+#define PAD_SLEW_RATE_MASK		0xe00U
+#define PAD_SLEW_RATE_POS		9
+#define PAD_BIAS_STRONG_PULL_UP		0x100U
+#define PAD_INPUT_ENABLE		0x080U
+#define PAD_INPUT_SCHMITT_ENABLE	0x040U
+#define PAD_BIAS_DISABLE		0x020U
+#define PAD_BIAS_PULL_DOWN		0x010U
+#define PAD_BIAS_MASK			0x130U
+#define PAD_DRIVE_STRENGTH_MASK		0x007U
+#define PAD_DRIVE_STRENGTH_POS		0
+
+
+#define STARFIVE_PINS_SIZE 		4
+
+//pinmux
+#define PINMUX_GPIO_NUM_MASK		0xFF
+#define PINMUX_GPIO_FUNC_MASK		0xF00
+#define PINMUX_GPIO_FUNC		0x100
+
+struct platform_device;
+
+extern struct pinmux_ops starfive_pmx_ops;
+extern const struct dev_pm_ops starfive_pinctrl_pm_ops;
+
+struct starfive_pin_config {
+	unsigned long io_config;
+	u32 pinmux_func;
+	u32 gpio_num;
+	u32 gpio_dout;
+	u32 gpio_doen;
+	u32 gpio_din_num;
+	s32 *gpio_din_reg;
+};
+
+struct starfive_pin {
+	unsigned int pin;
+	struct starfive_pin_config pin_config;
+};
+
+struct starfive_pin_reg {
+	s32 io_conf_reg;
+	s32 gpo_dout_reg; 
+	s32 gpo_doen_reg; 
+};
+
+struct starfive_iopad_sel_func_inf {
+	unsigned int padctl_gpio_base;
+	unsigned int padctl_gpio0;
+};
+
+
+struct starfive_pinctrl {
+	struct device *dev;
+	struct pinctrl_dev *pctl;
+	void __iomem *padctl_base;
+	void __iomem *gpio_base;
+	unsigned int padctl_gpio_base;
+	unsigned int padctl_gpio0;
+	const struct starfive_pinctrl_soc_info *info;
+	struct starfive_pin_reg *pin_regs;
+	unsigned int group_index;
+	
+	struct mutex mutex;
+	raw_spinlock_t lock;
+	
+	struct gpio_chip gc;
+	struct pinctrl_gpio_range gpios;
+	unsigned long enabled;
+	unsigned trigger[MAX_GPIO];
+};
+
+
+struct starfive_pinctrl_soc_info {
+	const struct pinctrl_pin_desc *pins;
+	unsigned int npins;
+	
+	/*gpio dout/doen/din register*/
+	unsigned int dout_reg_base;
+	unsigned int dout_reg_offset;
+	unsigned int doen_reg_base;
+	unsigned int doen_reg_offset;
+	unsigned int din_reg_base;
+	unsigned int din_reg_offset;
+	
+	/* sel-function */
+	int (*starfive_iopad_sel_func)(struct starfive_pinctrl *ipctl, 
+				unsigned int func_id);
+	/* generic pinconf */
+	int (*starfive_pinconf_get)(struct pinctrl_dev *pctldev, unsigned int pin_id,
+			       unsigned long *config);
+	int (*starfive_pinconf_set)(struct pinctrl_dev *pctldev,
+				unsigned pin_id, unsigned long *configs,
+				unsigned num_configs);
+	
+	/* generic pinmux */
+	int (*starfive_pmx_set_one_pin_mux)(struct starfive_pinctrl *ipctl,
+				struct starfive_pin *pin);
+	/* gpio chip */
+	int (*starfive_gpio_register)(struct platform_device *pdev,
+				struct starfive_pinctrl *ipctl);
+};
+
+
+#define	STARFIVE_PINCTRL_PIN(pin) PINCTRL_PIN(pin, #pin)
+
+int starfive_pinctrl_probe(struct platform_device *pdev,
+			const struct starfive_pinctrl_soc_info *info);
+
+#endif /* __DRIVERS_PINCTRL_STARFIVE_H */