[PATCH v2 3/8] pinctrl: sophgo: generalize shareable code of cv18xx pinctrl driver

Inochi Amaoto posted 8 patches 12 months ago
[PATCH v2 3/8] pinctrl: sophgo: generalize shareable code of cv18xx pinctrl driver
Posted by Inochi Amaoto 12 months ago
With generic data structure, it is possible to generalize vddio
operators and DT parsing code of cv18xx pinctrl driver. Introduce
sophgo_cfg_ops callback to allow the driver to adjust the soc
logic and share common code.

Signed-off-by: Inochi Amaoto <inochiama@gmail.com>
---
 drivers/pinctrl/sophgo/Kconfig                |  19 +-
 drivers/pinctrl/sophgo/Makefile               |   5 +-
 drivers/pinctrl/sophgo/pinctrl-cv1800b.c      |   1 +
 drivers/pinctrl/sophgo/pinctrl-cv1812h.c      |   1 +
 drivers/pinctrl/sophgo/pinctrl-cv18xx.c       | 423 +++---------------
 drivers/pinctrl/sophgo/pinctrl-cv18xx.h       |   2 +
 drivers/pinctrl/sophgo/pinctrl-sg2000.c       |   1 +
 drivers/pinctrl/sophgo/pinctrl-sg2002.c       |   1 +
 .../pinctrl/sophgo/pinctrl-sophgo-common.c    | 404 +++++++++++++++++
 drivers/pinctrl/sophgo/pinctrl-sophgo.h       |  63 +++
 10 files changed, 545 insertions(+), 375 deletions(-)
 create mode 100644 drivers/pinctrl/sophgo/pinctrl-sophgo-common.c

diff --git a/drivers/pinctrl/sophgo/Kconfig b/drivers/pinctrl/sophgo/Kconfig
index c05f909a8838..f473ece940ab 100644
--- a/drivers/pinctrl/sophgo/Kconfig
+++ b/drivers/pinctrl/sophgo/Kconfig
@@ -3,17 +3,21 @@
 # Sophgo SoC PINCTRL drivers
 #
 
-config PINCTRL_SOPHGO_CV18XX
-	bool
+config PINCTRL_SOPHGO_COMMON
+	tristate
 	select GENERIC_PINCTRL_GROUPS
 	select GENERIC_PINMUX_FUNCTIONS
 	select GENERIC_PINCONF
 
+config PINCTRL_SOPHGO_CV18XX_OPS
+	bool
+
 config PINCTRL_SOPHGO_CV1800B
 	tristate "Sophgo CV1800B SoC Pinctrl driver"
 	depends on ARCH_SOPHGO || COMPILE_TEST
 	depends on OF
-	select PINCTRL_SOPHGO_CV18XX
+	select PINCTRL_SOPHGO_COMMON
+	select PINCTRL_SOPHGO_CV18XX_OPS
 	help
 	  Say Y to select the pinctrl driver for CV1800B SoC.
 	  This pin controller allows selecting the mux function for
@@ -24,7 +28,8 @@ config PINCTRL_SOPHGO_CV1812H
 	tristate "Sophgo CV1812H SoC Pinctrl driver"
 	depends on ARCH_SOPHGO || COMPILE_TEST
 	depends on OF
-	select PINCTRL_SOPHGO_CV18XX
+	select PINCTRL_SOPHGO_COMMON
+	select PINCTRL_SOPHGO_CV18XX_OPS
 	help
 	  Say Y to select the pinctrl driver for CV1812H SoC.
 	  This pin controller allows selecting the mux function for
@@ -35,7 +40,8 @@ config PINCTRL_SOPHGO_SG2000
 	tristate "Sophgo SG2000 SoC Pinctrl driver"
 	depends on ARCH_SOPHGO || COMPILE_TEST
 	depends on OF
-	select PINCTRL_SOPHGO_CV18XX
+	select PINCTRL_SOPHGO_COMMON
+	select PINCTRL_SOPHGO_CV18XX_OPS
 	help
 	  Say Y to select the pinctrl driver for SG2000 SoC.
 	  This pin controller allows selecting the mux function for
@@ -46,7 +52,8 @@ config PINCTRL_SOPHGO_SG2002
 	tristate "Sophgo SG2002 SoC Pinctrl driver"
 	depends on ARCH_SOPHGO || COMPILE_TEST
 	depends on OF
-	select PINCTRL_SOPHGO_CV18XX
+	select PINCTRL_SOPHGO_COMMON
+	select PINCTRL_SOPHGO_CV18XX_OPS
 	help
 	  Say Y to select the pinctrl driver for SG2002 SoC.
 	  This pin controller allows selecting the mux function for
diff --git a/drivers/pinctrl/sophgo/Makefile b/drivers/pinctrl/sophgo/Makefile
index 4113a5c9191b..5f24550750d6 100644
--- a/drivers/pinctrl/sophgo/Makefile
+++ b/drivers/pinctrl/sophgo/Makefile
@@ -1,6 +1,9 @@
 # SPDX-License-Identifier: GPL-2.0
 
-obj-$(CONFIG_PINCTRL_SOPHGO_CV18XX)	+= pinctrl-cv18xx.o
+obj-$(CONFIG_PINCTRL_SOPHGO_COMMON)	+= pinctrl-sophgo.o
+pinctrl-sophgo-objs			+= pinctrl-sophgo-common.o
+pinctrl-sophgo-$(CONFIG_PINCTRL_SOPHGO_CV18XX_OPS) += pinctrl-cv18xx.o
+
 obj-$(CONFIG_PINCTRL_SOPHGO_CV1800B)	+= pinctrl-cv1800b.o
 obj-$(CONFIG_PINCTRL_SOPHGO_CV1812H)	+= pinctrl-cv1812h.o
 obj-$(CONFIG_PINCTRL_SOPHGO_SG2000)	+= pinctrl-sg2000.o
diff --git a/drivers/pinctrl/sophgo/pinctrl-cv1800b.c b/drivers/pinctrl/sophgo/pinctrl-cv1800b.c
index 45529e2ed23a..ca6fb374ee15 100644
--- a/drivers/pinctrl/sophgo/pinctrl-cv1800b.c
+++ b/drivers/pinctrl/sophgo/pinctrl-cv1800b.c
@@ -442,6 +442,7 @@ static const struct sophgo_pinctrl_data cv1800b_pindata = {
 	.pindata	= cv1800b_pin_data,
 	.pdnames	= cv1800b_power_domain_desc,
 	.vddio_ops	= &cv1800b_vddio_cfg_ops,
+	.cfg_ops	= &cv1800_cfg_ops,
 	.npins		= ARRAY_SIZE(cv1800b_pins),
 	.npds		= ARRAY_SIZE(cv1800b_power_domain_desc),
 	.pinsize	= sizeof(struct cv1800_pin),
diff --git a/drivers/pinctrl/sophgo/pinctrl-cv1812h.c b/drivers/pinctrl/sophgo/pinctrl-cv1812h.c
index 4e30a1cc9d7d..df2c2697a1fd 100644
--- a/drivers/pinctrl/sophgo/pinctrl-cv1812h.c
+++ b/drivers/pinctrl/sophgo/pinctrl-cv1812h.c
@@ -751,6 +751,7 @@ static const struct sophgo_pinctrl_data cv1812h_pindata = {
 	.pindata	= cv1812h_pin_data,
 	.pdnames	= cv1812h_power_domain_desc,
 	.vddio_ops	= &cv1812h_vddio_cfg_ops,
+	.cfg_ops	= &cv1800_cfg_ops,
 	.npins		= ARRAY_SIZE(cv1812h_pins),
 	.npds		= ARRAY_SIZE(cv1812h_power_domain_desc),
 	.pinsize	= sizeof(struct cv1800_pin),
diff --git a/drivers/pinctrl/sophgo/pinctrl-cv18xx.c b/drivers/pinctrl/sophgo/pinctrl-cv18xx.c
index 573e00d2c752..66111110c4b3 100644
--- a/drivers/pinctrl/sophgo/pinctrl-cv18xx.c
+++ b/drivers/pinctrl/sophgo/pinctrl-cv18xx.c
@@ -34,11 +34,6 @@ struct cv1800_priv {
 	void __iomem				*regs[2];
 };
 
-static unsigned int cv1800_dt_get_pin(u32 value)
-{
-	return value & GENMASK(15, 0);
-}
-
 static unsigned int cv1800_dt_get_pin_mux(u32 value)
 {
 	return (value >> 16) & GENMASK(7, 0);
@@ -52,15 +47,6 @@ static unsigned int cv1800_dt_get_pin_mux2(u32 value)
 #define cv1800_pinctrl_get_component_addr(pctrl, _comp)		\
 	((pctrl)->regs[(_comp)->area] + (_comp)->offset)
 
-static int cv1800_cmp_pin(const void *key, const void *pivot)
-{
-	const struct sophgo_pin *pin = pivot;
-	int pin_id = (long)key;
-	int pivid = pin->id;
-
-	return pin_id - pivid;
-}
-
 static int cv1800_set_power_cfg(struct sophgo_pinctrl *pctrl,
 				u8 domain, u32 cfg)
 {
@@ -85,13 +71,6 @@ static int cv1800_get_power_cfg(struct sophgo_pinctrl *pctrl,
 	return priv->power_cfg[domain];
 }
 
-static const struct sophgo_pin *cv1800_get_pin(struct sophgo_pinctrl *pctrl,
-					       unsigned long pin)
-{
-	return bsearch((void *)pin, pctrl->data->pindata, pctrl->data->npins,
-		       pctrl->data->pinsize, cv1800_cmp_pin);
-}
-
 #define PIN_BGA_ID_OFFSET		8
 #define PIN_BGA_ID_MASK			0xff
 
@@ -113,7 +92,7 @@ static void cv1800_pctrl_dbg_show(struct pinctrl_dev *pctldev,
 {
 	struct sophgo_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
 	struct cv1800_priv *priv = pctrl->priv_ctrl;
-	const struct sophgo_pin *sp = cv1800_get_pin(pctrl, pin_id);
+	const struct sophgo_pin *sp = sophgo_get_pin(pctrl, pin_id);
 	const struct cv1800_pin *pin = sophgo_to_cv1800_pin(sp);
 	enum cv1800_pin_io_type type = cv1800_pin_io_type(pin);
 	u32 pin_hwid = pin->pin.id;
@@ -172,7 +151,7 @@ static int cv1800_verify_pinmux_config(const struct sophgo_pin_mux_config *confi
 }
 
 static int cv1800_verify_pin_group(const struct sophgo_pin_mux_config *mux,
-				   unsigned long npins)
+				   unsigned int npins)
 {
 	struct cv1800_pin *pin;
 	enum cv1800_pin_io_type type;
@@ -197,165 +176,23 @@ static int cv1800_verify_pin_group(const struct sophgo_pin_mux_config *mux,
 	return 0;
 }
 
-static int cv1800_pctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
-				       struct device_node *np,
-				       struct pinctrl_map **maps,
-				       unsigned int *num_maps)
+static int cv1800_dt_node_to_map_post(struct device_node *cur,
+				      struct sophgo_pinctrl *pctrl,
+				      struct sophgo_pin_mux_config *pinmuxs,
+				      unsigned int npins)
 {
-	struct sophgo_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
-	struct device *dev = pctrl->dev;
-	struct device_node *child;
-	struct pinctrl_map *map;
-	const char **grpnames;
-	const char *grpname;
-	int ngroups = 0;
-	int nmaps = 0;
+	const struct cv1800_pin *pin = sophgo_to_cv1800_pin(pinmuxs[0].pin);
+	u32 power;
 	int ret;
 
-	for_each_available_child_of_node(np, child)
-		ngroups += 1;
+	ret = of_property_read_u32(cur, "power-source", &power);
+	if (ret)
+		return ret;
 
-	grpnames = devm_kcalloc(dev, ngroups, sizeof(*grpnames), GFP_KERNEL);
-	if (!grpnames)
-		return -ENOMEM;
+	if (!(power == PIN_POWER_STATE_3V3 || power == PIN_POWER_STATE_1V8))
+		return -ENOTSUPP;
 
-	map = kcalloc(ngroups * 2, sizeof(*map), GFP_KERNEL);
-	if (!map)
-		return -ENOMEM;
-
-	ngroups = 0;
-	mutex_lock(&pctrl->mutex);
-	for_each_available_child_of_node(np, child) {
-		int npins = of_property_count_u32_elems(child, "pinmux");
-		unsigned int *pins;
-		struct sophgo_pin_mux_config *pinmuxs;
-		struct cv1800_pin *pin;
-		u32 config, power;
-		int i;
-
-		if (npins < 1) {
-			dev_err(dev, "invalid pinctrl group %pOFn.%pOFn\n",
-				np, child);
-			ret = -EINVAL;
-			goto dt_failed;
-		}
-
-		grpname = devm_kasprintf(dev, GFP_KERNEL, "%pOFn.%pOFn",
-					 np, child);
-		if (!grpname) {
-			ret = -ENOMEM;
-			goto dt_failed;
-		}
-
-		grpnames[ngroups++] = grpname;
-
-		pins = devm_kcalloc(dev, npins, sizeof(*pins), GFP_KERNEL);
-		if (!pins) {
-			ret = -ENOMEM;
-			goto dt_failed;
-		}
-
-		pinmuxs = devm_kcalloc(dev, npins, sizeof(*pinmuxs), GFP_KERNEL);
-		if (!pinmuxs) {
-			ret = -ENOMEM;
-			goto dt_failed;
-		}
-
-		for (i = 0; i < npins; i++) {
-			ret = of_property_read_u32_index(child, "pinmux",
-							 i, &config);
-			if (ret)
-				goto dt_failed;
-
-			pins[i] = cv1800_dt_get_pin(config);
-			pinmuxs[i].config = config;
-			pinmuxs[i].pin = cv1800_get_pin(pctrl, pins[i]);
-
-			if (!pinmuxs[i].pin) {
-				dev_err(dev, "failed to get pin %d\n", pins[i]);
-				ret = -ENODEV;
-				goto dt_failed;
-			}
-
-			ret = cv1800_verify_pinmux_config(&pinmuxs[i]);
-			if (ret) {
-				dev_err(dev, "group %s pin %d is invalid\n",
-					grpname, i);
-				goto dt_failed;
-			}
-		}
-
-		ret = cv1800_verify_pin_group(pinmuxs, npins);
-		if (ret) {
-			dev_err(dev, "group %s is invalid\n", grpname);
-			goto dt_failed;
-		}
-
-		ret = of_property_read_u32(child, "power-source", &power);
-		if (ret)
-			goto dt_failed;
-
-		if (!(power == PIN_POWER_STATE_3V3 || power == PIN_POWER_STATE_1V8)) {
-			dev_err(dev, "group %s have unsupported power: %u\n",
-				grpname, power);
-			ret = -ENOTSUPP;
-			goto dt_failed;
-		}
-
-		pin = sophgo_to_cv1800_pin(pinmuxs[0].pin);
-		ret = cv1800_set_power_cfg(pctrl, pin->power_domain, power);
-		if (ret)
-			goto dt_failed;
-
-		map[nmaps].type = PIN_MAP_TYPE_MUX_GROUP;
-		map[nmaps].data.mux.function = np->name;
-		map[nmaps].data.mux.group = grpname;
-		nmaps += 1;
-
-		ret = pinconf_generic_parse_dt_config(child, pctldev,
-						      &map[nmaps].data.configs.configs,
-						      &map[nmaps].data.configs.num_configs);
-		if (ret) {
-			dev_err(dev, "failed to parse pin config of group %s: %d\n",
-				grpname, ret);
-			goto dt_failed;
-		}
-
-		ret = pinctrl_generic_add_group(pctldev, grpname,
-						pins, npins, pinmuxs);
-		if (ret < 0) {
-			dev_err(dev, "failed to add group %s: %d\n", grpname, ret);
-			goto dt_failed;
-		}
-
-		/* don't create a map if there are no pinconf settings */
-		if (map[nmaps].data.configs.num_configs == 0)
-			continue;
-
-		map[nmaps].type = PIN_MAP_TYPE_CONFIGS_GROUP;
-		map[nmaps].data.configs.group_or_pin = grpname;
-		nmaps += 1;
-	}
-
-	ret = pinmux_generic_add_function(pctldev, np->name,
-					  grpnames, ngroups, NULL);
-	if (ret < 0) {
-		dev_err(dev, "error adding function %s: %d\n", np->name, ret);
-		goto function_failed;
-	}
-
-	*maps = map;
-	*num_maps = nmaps;
-	mutex_unlock(&pctrl->mutex);
-
-	return 0;
-
-dt_failed:
-	of_node_put(child);
-function_failed:
-	pinctrl_utils_free_map(pctldev, map, nmaps);
-	mutex_unlock(&pctrl->mutex);
-	return ret;
+	return cv1800_set_power_cfg(pctrl, pin->power_domain, power);
 }
 
 static const struct pinctrl_ops cv1800_pctrl_ops = {
@@ -363,54 +200,35 @@ static const struct pinctrl_ops cv1800_pctrl_ops = {
 	.get_group_name		= pinctrl_generic_get_group_name,
 	.get_group_pins		= pinctrl_generic_get_group_pins,
 	.pin_dbg_show		= cv1800_pctrl_dbg_show,
-	.dt_node_to_map		= cv1800_pctrl_dt_node_to_map,
+	.dt_node_to_map		= sophgo_pctrl_dt_node_to_map,
 	.dt_free_map		= pinctrl_utils_free_map,
 };
 
-static int cv1800_pmx_set_mux(struct pinctrl_dev *pctldev,
-			      unsigned int fsel, unsigned int gsel)
+static void cv1800_set_pinmux_config(struct sophgo_pinctrl *pctrl,
+				     const struct sophgo_pin *sp, u32 config)
 {
-	struct sophgo_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
+	const struct cv1800_pin *pin = sophgo_to_cv1800_pin(sp);
 	struct cv1800_priv *priv = pctrl->priv_ctrl;
-	const struct group_desc *group;
-	const struct sophgo_pin_mux_config *configs;
-	unsigned int i;
-
-	group = pinctrl_generic_get_group(pctldev, gsel);
-	if (!group)
-		return -EINVAL;
-
-	configs = group->data;
-
-	for (i = 0; i < group->grp.npins; i++) {
-		const struct cv1800_pin *pin = sophgo_to_cv1800_pin(configs[i].pin);
-		u32 value = configs[i].config;
-		void __iomem *reg_mux;
-		void __iomem *reg_mux2;
-		unsigned long flags;
-		u32 mux;
-		u32 mux2;
-
-		reg_mux = cv1800_pinctrl_get_component_addr(priv, &pin->mux);
-		reg_mux2 = cv1800_pinctrl_get_component_addr(priv, &pin->mux2);
-		mux = cv1800_dt_get_pin_mux(value);
-		mux2 = cv1800_dt_get_pin_mux2(value);
-
-		raw_spin_lock_irqsave(&pctrl->lock, flags);
-		writel_relaxed(mux, reg_mux);
-		if (mux2 != PIN_MUX_INVALD)
-			writel_relaxed(mux2, reg_mux2);
-		raw_spin_unlock_irqrestore(&pctrl->lock, flags);
-	}
-
-	return 0;
+	void __iomem *reg_mux;
+	void __iomem *reg_mux2;
+	u32 mux;
+	u32 mux2;
+
+	reg_mux = cv1800_pinctrl_get_component_addr(priv, &pin->mux);
+	reg_mux2 = cv1800_pinctrl_get_component_addr(priv, &pin->mux2);
+	mux = cv1800_dt_get_pin_mux(config);
+	mux2 = cv1800_dt_get_pin_mux2(config);
+
+	writel_relaxed(mux, reg_mux);
+	if (mux2 != PIN_MUX_INVALD)
+		writel_relaxed(mux2, reg_mux2);
 }
 
 static const struct pinmux_ops cv1800_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		= cv1800_pmx_set_mux,
+	.set_mux		= sophgo_pmx_set_mux,
 	.strict			= true,
 };
 
@@ -421,99 +239,13 @@ static const struct pinmux_ops cv1800_pmx_ops = {
 #define PIN_IO_BUS_HOLD		BIT(10)
 #define PIN_IO_OUT_FAST_SLEW	BIT(11)
 
-static u32 cv1800_pull_down_typical_resistor(struct sophgo_pinctrl *pctrl,
-					     const struct sophgo_pin *pin,
-					     const u32 *power_cfg)
-{
-	return pctrl->data->vddio_ops->get_pull_down(pin, power_cfg);
-}
-
-static u32 cv1800_pull_up_typical_resistor(struct sophgo_pinctrl *pctrl,
-					   const struct sophgo_pin *pin,
-					   const u32 *power_cfg)
-{
-	return pctrl->data->vddio_ops->get_pull_up(pin, power_cfg);
-}
-
-static int cv1800_pinctrl_oc2reg(struct sophgo_pinctrl *pctrl,
-				 const struct sophgo_pin *pin,
-				 const u32 *power_cfg, u32 target)
-{
-	const u32 *map;
-	int i, len;
-
-	len = pctrl->data->vddio_ops->get_oc_map(pin, power_cfg, &map);
-	if (len < 0)
-		return len;
-
-	for (i = 0; i < len; i++) {
-		if (map[i] >= target)
-			return i;
-	}
-
-	return -EINVAL;
-}
-
-static int cv1800_pinctrl_reg2oc(struct sophgo_pinctrl *pctrl,
-				 const struct sophgo_pin *pin,
-				 const u32 *power_cfg, u32 reg)
-{
-	const u32 *map;
-	int len;
-
-	len = pctrl->data->vddio_ops->get_oc_map(pin, power_cfg, &map);
-	if (len < 0)
-		return len;
-
-	if (reg >= len)
-		return -EINVAL;
-
-	return map[reg];
-}
-
-static int cv1800_pinctrl_schmitt2reg(struct sophgo_pinctrl *pctrl,
-				      const struct sophgo_pin *pin,
-				      const u32 *power_cfg, u32 target)
-{
-	const u32 *map;
-	int i, len;
-
-	len = pctrl->data->vddio_ops->get_schmitt_map(pin, power_cfg, &map);
-	if (len < 0)
-		return len;
-
-	for (i = 0; i < len; i++) {
-		if (map[i] == target)
-			return i;
-	}
-
-	return -EINVAL;
-}
-
-static int cv1800_pinctrl_reg2schmitt(struct sophgo_pinctrl *pctrl,
-				      const struct sophgo_pin *pin,
-				      const u32 *power_cfg, u32 reg)
-{
-	const u32 *map;
-	int len;
-
-	len = pctrl->data->vddio_ops->get_schmitt_map(pin, power_cfg, &map);
-	if (len < 0)
-		return len;
-
-	if (reg >= len)
-		return -EINVAL;
-
-	return map[reg];
-}
-
 static int cv1800_pconf_get(struct pinctrl_dev *pctldev,
 			    unsigned int pin_id, unsigned long *config)
 {
 	struct sophgo_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
 	struct cv1800_priv *priv = pctrl->priv_ctrl;
 	int param = pinconf_to_config_param(*config);
-	const struct sophgo_pin *sp = cv1800_get_pin(pctrl, pin_id);
+	const struct sophgo_pin *sp = sophgo_get_pin(pctrl, pin_id);
 	const struct cv1800_pin *pin = sophgo_to_cv1800_pin(sp);
 	enum cv1800_pin_io_type type;
 	u32 value;
@@ -533,23 +265,23 @@ static int cv1800_pconf_get(struct pinctrl_dev *pctldev,
 	switch (param) {
 	case PIN_CONFIG_BIAS_PULL_DOWN:
 		enabled = FIELD_GET(PIN_IO_PULLDOWN, value);
-		arg = cv1800_pull_down_typical_resistor(pctrl, sp, priv->power_cfg);
+		arg = sophgo_pinctrl_typical_pull_down(pctrl, sp, priv->power_cfg);
 		break;
 	case PIN_CONFIG_BIAS_PULL_UP:
 		enabled = FIELD_GET(PIN_IO_PULLUP, value);
-		arg = cv1800_pull_up_typical_resistor(pctrl, sp, priv->power_cfg);
+		arg = sophgo_pinctrl_typical_pull_up(pctrl, sp, priv->power_cfg);
 		break;
 	case PIN_CONFIG_DRIVE_STRENGTH_UA:
 		enabled = true;
 		arg = FIELD_GET(PIN_IO_DRIVE, value);
-		ret = cv1800_pinctrl_reg2oc(pctrl, sp, priv->power_cfg, arg);
+		ret = sophgo_pinctrl_reg2oc(pctrl, sp, priv->power_cfg, arg);
 		if (ret < 0)
 			return ret;
 		arg = ret;
 		break;
 	case PIN_CONFIG_INPUT_SCHMITT_UV:
 		arg = FIELD_GET(PIN_IO_SCHMITT, value);
-		ret = cv1800_pinctrl_reg2schmitt(pctrl, sp, priv->power_cfg, arg);
+		ret = sophgo_pinctrl_reg2schmitt(pctrl, sp, priv->power_cfg, arg);
 		if (ret < 0)
 			return ret;
 		arg = ret;
@@ -612,7 +344,7 @@ static int cv1800_pinconf_compute_config(struct sophgo_pinctrl *pctrl,
 			m |= PIN_IO_PULLUP;
 			break;
 		case PIN_CONFIG_DRIVE_STRENGTH_UA:
-			ret = cv1800_pinctrl_oc2reg(pctrl, sp,
+			ret = sophgo_pinctrl_oc2reg(pctrl, sp,
 						    priv->power_cfg, arg);
 			if (ret < 0)
 				return ret;
@@ -621,7 +353,7 @@ static int cv1800_pinconf_compute_config(struct sophgo_pinctrl *pctrl,
 			m |= PIN_IO_DRIVE;
 			break;
 		case PIN_CONFIG_INPUT_SCHMITT_UV:
-			ret = cv1800_pinctrl_schmitt2reg(pctrl, sp,
+			ret = sophgo_pinctrl_schmitt2reg(pctrl, sp,
 							 priv->power_cfg, arg);
 			if (ret < 0)
 				return ret;
@@ -653,84 +385,29 @@ static int cv1800_pinconf_compute_config(struct sophgo_pinctrl *pctrl,
 	return 0;
 }
 
-static int cv1800_pin_set_config(struct sophgo_pinctrl *pctrl,
-				 unsigned int pin_id,
-				 u32 value, u32 mask)
+static int cv1800_set_pinconf_config(struct sophgo_pinctrl *pctrl,
+				     const struct sophgo_pin *sp,
+				     u32 value, u32 mask)
 {
 	struct cv1800_priv *priv = pctrl->priv_ctrl;
-	const struct sophgo_pin *sp = cv1800_get_pin(pctrl, pin_id);
-	struct cv1800_pin *pin;
-	unsigned long flags;
+	struct cv1800_pin *pin = sophgo_to_cv1800_pin(sp);
 	void __iomem *addr;
 	u32 reg;
 
-	if (!sp)
-		return -EINVAL;
-	pin = sophgo_to_cv1800_pin(sp);
-
 	addr = cv1800_pinctrl_get_component_addr(priv, &pin->conf);
 
-	raw_spin_lock_irqsave(&pctrl->lock, flags);
 	reg = readl(addr);
 	reg &= ~mask;
 	reg |= value;
 	writel(reg, addr);
-	raw_spin_unlock_irqrestore(&pctrl->lock, flags);
-
-	return 0;
-}
-
-static int cv1800_pconf_set(struct pinctrl_dev *pctldev,
-			    unsigned int pin_id, unsigned long *configs,
-			    unsigned int num_configs)
-{
-	struct sophgo_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
-	const struct sophgo_pin *sp = cv1800_get_pin(pctrl, pin_id);
-	u32 value, mask;
-
-	if (!sp)
-		return -EINVAL;
-
-	if (cv1800_pinconf_compute_config(pctrl, sp,
-					  configs, num_configs,
-					  &value, &mask))
-		return -ENOTSUPP;
-
-	return cv1800_pin_set_config(pctrl, pin_id, value, mask);
-}
-
-static int cv1800_pconf_group_set(struct pinctrl_dev *pctldev,
-				  unsigned int gsel,
-				  unsigned long *configs,
-				  unsigned int num_configs)
-{
-	struct sophgo_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
-	const struct group_desc *group;
-	const struct sophgo_pin_mux_config *pinmuxs;
-	u32 value, mask;
-	int i;
-
-	group = pinctrl_generic_get_group(pctldev, gsel);
-	if (!group)
-		return -EINVAL;
-
-	pinmuxs = group->data;
-
-	if (cv1800_pinconf_compute_config(pctrl, pinmuxs[0].pin,
-					  configs, num_configs,
-					  &value, &mask))
-		return -ENOTSUPP;
-
-	for (i = 0; i < group->grp.npins; i++)
-		cv1800_pin_set_config(pctrl, group->grp.pins[i], value, mask);
 
 	return 0;
 }
 
 static const struct pinconf_ops cv1800_pconf_ops = {
 	.pin_config_get			= cv1800_pconf_get,
-	.pin_config_set			= cv1800_pconf_set,
-	.pin_config_group_set		= cv1800_pconf_group_set,
+	.pin_config_set			= sophgo_pconf_set,
+	.pin_config_group_set		= sophgo_pconf_group_set,
 	.is_generic			= true,
 };
 
@@ -795,3 +472,13 @@ int cv1800_pinctrl_probe(struct platform_device *pdev)
 	return pinctrl_enable(pctrl->pctrl_dev);
 }
 EXPORT_SYMBOL_GPL(cv1800_pinctrl_probe);
+
+const struct sophgo_cfg_ops cv1800_cfg_ops = {
+	.verify_pinmux_config = cv1800_verify_pinmux_config,
+	.verify_pin_group = cv1800_verify_pin_group,
+	.dt_node_to_map_post = cv1800_dt_node_to_map_post,
+	.compute_pinconf_config = cv1800_pinconf_compute_config,
+	.set_pinconf_config = cv1800_set_pinconf_config,
+	.set_pinmux_config = cv1800_set_pinmux_config,
+};
+EXPORT_SYMBOL_GPL(cv1800_cfg_ops);
diff --git a/drivers/pinctrl/sophgo/pinctrl-cv18xx.h b/drivers/pinctrl/sophgo/pinctrl-cv18xx.h
index f095a6e85e52..821e554e550b 100644
--- a/drivers/pinctrl/sophgo/pinctrl-cv18xx.h
+++ b/drivers/pinctrl/sophgo/pinctrl-cv18xx.h
@@ -68,6 +68,8 @@ static inline enum cv1800_pin_io_type cv1800_pin_io_type(const struct cv1800_pin
 	return FIELD_GET(CV1800_PIN_IO_TYPE, pin->pin.flags);
 };
 
+extern const struct sophgo_cfg_ops cv1800_cfg_ops;
+
 int cv1800_pinctrl_probe(struct platform_device *pdev);
 
 #define CV1800_FUNC_PIN(_id, _power_domain, _type,			\
diff --git a/drivers/pinctrl/sophgo/pinctrl-sg2000.c b/drivers/pinctrl/sophgo/pinctrl-sg2000.c
index a83dae233cdf..9580bd285699 100644
--- a/drivers/pinctrl/sophgo/pinctrl-sg2000.c
+++ b/drivers/pinctrl/sophgo/pinctrl-sg2000.c
@@ -751,6 +751,7 @@ static const struct sophgo_pinctrl_data sg2000_pindata = {
 	.pindata	= sg2000_pin_data,
 	.pdnames	= sg2000_power_domain_desc,
 	.vddio_ops	= &sg2000_vddio_cfg_ops,
+	.cfg_ops	= &cv1800_cfg_ops,
 	.npins		= ARRAY_SIZE(sg2000_pins),
 	.npds		= ARRAY_SIZE(sg2000_power_domain_desc),
 	.pinsize	= sizeof(struct cv1800_pin),
diff --git a/drivers/pinctrl/sophgo/pinctrl-sg2002.c b/drivers/pinctrl/sophgo/pinctrl-sg2002.c
index 4366486d8b7f..e3041a8b8ba6 100644
--- a/drivers/pinctrl/sophgo/pinctrl-sg2002.c
+++ b/drivers/pinctrl/sophgo/pinctrl-sg2002.c
@@ -522,6 +522,7 @@ static const struct sophgo_pinctrl_data sg2002_pindata = {
 	.pindata	= sg2002_pin_data,
 	.pdnames	= sg2002_power_domain_desc,
 	.vddio_ops	= &sg2002_vddio_cfg_ops,
+	.cfg_ops	= &cv1800_cfg_ops,
 	.npins		= ARRAY_SIZE(sg2002_pins),
 	.npds		= ARRAY_SIZE(sg2002_power_domain_desc),
 	.pinsize	= sizeof(struct cv1800_pin),
diff --git a/drivers/pinctrl/sophgo/pinctrl-sophgo-common.c b/drivers/pinctrl/sophgo/pinctrl-sophgo-common.c
new file mode 100644
index 000000000000..957d84e75643
--- /dev/null
+++ b/drivers/pinctrl/sophgo/pinctrl-sophgo-common.c
@@ -0,0 +1,404 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Sophgo SoCs pinctrl common ops.
+ *
+ * Copyright (C) 2024 Inochi Amaoto <inochiama@outlook.com>
+ *
+ */
+
+#include <linux/bsearch.h>
+#include <linux/cleanup.h>
+#include <linux/export.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/seq_file.h>
+#include <linux/spinlock.h>
+
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/pinctrl/pinctrl.h>
+
+#include "../pinctrl-utils.h"
+#include "../pinconf.h"
+#include "../pinmux.h"
+
+#include "pinctrl-sophgo.h"
+
+static u16 sophgo_dt_get_pin(u32 value)
+{
+	return value;
+}
+
+static int sophgo_cmp_pin(const void *key, const void *pivot)
+{
+	const struct sophgo_pin *pin = pivot;
+	int pin_id = (long)key;
+	int pivid = pin->id;
+
+	return pin_id - pivid;
+}
+
+const struct sophgo_pin *sophgo_get_pin(struct sophgo_pinctrl *pctrl,
+					unsigned long pin_id)
+{
+	return bsearch((void *)pin_id, pctrl->data->pindata, pctrl->data->npins,
+		       pctrl->data->pinsize, sophgo_cmp_pin);
+}
+
+static int sophgo_verify_pinmux_config(struct sophgo_pinctrl *pctrl,
+				       const struct sophgo_pin_mux_config *config)
+{
+	if (pctrl->data->cfg_ops->verify_pinmux_config)
+		return pctrl->data->cfg_ops->verify_pinmux_config(config);
+	return 0;
+}
+
+static int sophgo_verify_pin_group(struct sophgo_pinctrl *pctrl,
+				   const struct sophgo_pin_mux_config *config,
+				   unsigned int npins)
+{
+	if (pctrl->data->cfg_ops->verify_pin_group)
+		return pctrl->data->cfg_ops->verify_pin_group(config, npins);
+	return 0;
+}
+
+static int sophgo_dt_node_to_map_post(struct device_node *cur,
+				      struct sophgo_pinctrl *pctrl,
+				      struct sophgo_pin_mux_config *config,
+				      unsigned int npins)
+{
+	if (pctrl->data->cfg_ops->dt_node_to_map_post)
+		return pctrl->data->cfg_ops->dt_node_to_map_post(cur, pctrl,
+								 config, npins);
+	return 0;
+}
+
+int sophgo_pctrl_dt_node_to_map(struct pinctrl_dev *pctldev, struct device_node *np,
+				struct pinctrl_map **maps, unsigned int *num_maps)
+{
+	struct sophgo_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
+	struct device *dev = pctrl->dev;
+	struct device_node *child;
+	struct pinctrl_map *map;
+	const char **grpnames;
+	const char *grpname;
+	int ngroups = 0;
+	int nmaps = 0;
+	int ret;
+
+	for_each_available_child_of_node(np, child)
+		ngroups += 1;
+
+	grpnames = devm_kcalloc(dev, ngroups, sizeof(*grpnames), GFP_KERNEL);
+	if (!grpnames)
+		return -ENOMEM;
+
+	map = kcalloc(ngroups * 2, sizeof(*map), GFP_KERNEL);
+	if (!map)
+		return -ENOMEM;
+
+	ngroups = 0;
+	guard(mutex)(&pctrl->mutex);
+	for_each_available_child_of_node(np, child) {
+		int npins = of_property_count_u32_elems(child, "pinmux");
+		unsigned int *pins;
+		struct sophgo_pin_mux_config *pinmuxs;
+		u32 config;
+		int i;
+
+		if (npins < 1) {
+			dev_err(dev, "invalid pinctrl group %pOFn.%pOFn\n",
+				np, child);
+			ret = -EINVAL;
+			goto dt_failed;
+		}
+
+		grpname = devm_kasprintf(dev, GFP_KERNEL, "%pOFn.%pOFn",
+					 np, child);
+		if (!grpname) {
+			ret = -ENOMEM;
+			goto dt_failed;
+		}
+
+		grpnames[ngroups++] = grpname;
+
+		pins = devm_kcalloc(dev, npins, sizeof(*pins), GFP_KERNEL);
+		if (!pins) {
+			ret = -ENOMEM;
+			goto dt_failed;
+		}
+
+		pinmuxs = devm_kcalloc(dev, npins, sizeof(*pinmuxs), GFP_KERNEL);
+		if (!pinmuxs) {
+			ret = -ENOMEM;
+			goto dt_failed;
+		}
+
+		for (i = 0; i < npins; i++) {
+			ret = of_property_read_u32_index(child, "pinmux",
+							 i, &config);
+			if (ret)
+				goto dt_failed;
+
+			pins[i] = sophgo_dt_get_pin(config);
+			pinmuxs[i].config = config;
+			pinmuxs[i].pin = sophgo_get_pin(pctrl, pins[i]);
+
+			if (!pinmuxs[i].pin) {
+				dev_err(dev, "failed to get pin %d\n", pins[i]);
+				ret = -ENODEV;
+				goto dt_failed;
+			}
+
+			ret = sophgo_verify_pinmux_config(pctrl, &pinmuxs[i]);
+			if (ret) {
+				dev_err(dev, "group %s pin %d is invalid\n",
+					grpname, i);
+				goto dt_failed;
+			}
+		}
+
+		ret = sophgo_verify_pin_group(pctrl, pinmuxs, npins);
+		if (ret) {
+			dev_err(dev, "group %s is invalid\n", grpname);
+			goto dt_failed;
+		}
+
+		ret = sophgo_dt_node_to_map_post(child, pctrl, pinmuxs, npins);
+		if (ret)
+			goto dt_failed;
+
+		map[nmaps].type = PIN_MAP_TYPE_MUX_GROUP;
+		map[nmaps].data.mux.function = np->name;
+		map[nmaps].data.mux.group = grpname;
+		nmaps += 1;
+
+		ret = pinconf_generic_parse_dt_config(child, pctldev,
+						      &map[nmaps].data.configs.configs,
+						      &map[nmaps].data.configs.num_configs);
+		if (ret) {
+			dev_err(dev, "failed to parse pin config of group %s: %d\n",
+				grpname, ret);
+			goto dt_failed;
+		}
+
+		ret = pinctrl_generic_add_group(pctldev, grpname,
+						pins, npins, pinmuxs);
+		if (ret < 0) {
+			dev_err(dev, "failed to add group %s: %d\n", grpname, ret);
+			goto dt_failed;
+		}
+
+		/* don't create a map if there are no pinconf settings */
+		if (map[nmaps].data.configs.num_configs == 0)
+			continue;
+
+		map[nmaps].type = PIN_MAP_TYPE_CONFIGS_GROUP;
+		map[nmaps].data.configs.group_or_pin = grpname;
+		nmaps += 1;
+	}
+
+	ret = pinmux_generic_add_function(pctldev, np->name,
+					  grpnames, ngroups, NULL);
+	if (ret < 0) {
+		dev_err(dev, "error adding function %s: %d\n", np->name, ret);
+		goto function_failed;
+	}
+
+	*maps = map;
+	*num_maps = nmaps;
+
+	return 0;
+
+dt_failed:
+	of_node_put(child);
+function_failed:
+	pinctrl_utils_free_map(pctldev, map, nmaps);
+	return ret;
+}
+
+int sophgo_pmx_set_mux(struct pinctrl_dev *pctldev,
+		       unsigned int fsel, unsigned int gsel)
+{
+	struct sophgo_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
+	const struct group_desc *group;
+	const struct sophgo_pin_mux_config *configs;
+	unsigned int i;
+
+	group = pinctrl_generic_get_group(pctldev, gsel);
+	if (!group)
+		return -EINVAL;
+
+	configs = group->data;
+
+	for (i = 0; i < group->grp.npins; i++) {
+		const struct sophgo_pin *pin = configs[i].pin;
+		u32 value = configs[i].config;
+
+		guard(raw_spinlock_irqsave)(&pctrl->lock);
+
+		pctrl->data->cfg_ops->set_pinmux_config(pctrl, pin, value);
+	}
+
+	return 0;
+}
+
+static int sophgo_pin_set_config(struct sophgo_pinctrl *pctrl,
+				 unsigned int pin_id,
+				 u32 value, u32 mask)
+{
+	const struct sophgo_pin *pin = sophgo_get_pin(pctrl, pin_id);
+
+	if (!pin)
+		return -EINVAL;
+
+	guard(raw_spinlock_irqsave)(&pctrl->lock);
+
+	return pctrl->data->cfg_ops->set_pinconf_config(pctrl, pin, value, mask);
+}
+
+int sophgo_pconf_set(struct pinctrl_dev *pctldev, unsigned int pin_id,
+		     unsigned long *configs, unsigned int num_configs)
+{
+	struct sophgo_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
+	const struct sophgo_pin *pin = sophgo_get_pin(pctrl, pin_id);
+	u32 value, mask;
+
+	if (!pin)
+		return -ENODEV;
+
+	if (pctrl->data->cfg_ops->compute_pinconf_config(pctrl, pin,
+							 configs, num_configs,
+							 &value, &mask))
+		return -ENOTSUPP;
+
+	return sophgo_pin_set_config(pctrl, pin_id, value, mask);
+}
+
+int sophgo_pconf_group_set(struct pinctrl_dev *pctldev, unsigned int gsel,
+			   unsigned long *configs, unsigned int num_configs)
+{
+	struct sophgo_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
+	const struct group_desc *group;
+	const struct sophgo_pin_mux_config *pinmuxs;
+	u32 value, mask;
+	int i;
+
+	group = pinctrl_generic_get_group(pctldev, gsel);
+	if (!group)
+		return -EINVAL;
+
+	pinmuxs = group->data;
+
+	if (pctrl->data->cfg_ops->compute_pinconf_config(pctrl, pinmuxs[0].pin,
+							 configs, num_configs,
+							 &value, &mask))
+		return -ENOTSUPP;
+
+	for (i = 0; i < group->grp.npins; i++)
+		sophgo_pin_set_config(pctrl,  group->grp.pins[i], value, mask);
+
+	return 0;
+}
+
+u32 sophgo_pinctrl_typical_pull_down(struct sophgo_pinctrl *pctrl,
+				     const struct sophgo_pin *pin,
+				     const u32 *power_cfg)
+{
+	return pctrl->data->vddio_ops->get_pull_down(pin, power_cfg);
+}
+
+u32 sophgo_pinctrl_typical_pull_up(struct sophgo_pinctrl *pctrl,
+				   const struct sophgo_pin *pin,
+				   const u32 *power_cfg)
+{
+	return pctrl->data->vddio_ops->get_pull_up(pin, power_cfg);
+}
+
+int sophgo_pinctrl_oc2reg(struct sophgo_pinctrl *pctrl,
+			  const struct sophgo_pin *pin,
+			  const u32 *power_cfg, u32 target)
+{
+	const u32 *map;
+	int i, len;
+
+	if (!pctrl->data->vddio_ops->get_oc_map)
+		return -ENOTSUPP;
+
+	len = pctrl->data->vddio_ops->get_oc_map(pin, power_cfg, &map);
+	if (len < 0)
+		return len;
+
+	for (i = 0; i < len; i++) {
+		if (map[i] >= target)
+			return i;
+	}
+
+	return -EINVAL;
+}
+
+int sophgo_pinctrl_reg2oc(struct sophgo_pinctrl *pctrl,
+			  const struct sophgo_pin *pin,
+			  const u32 *power_cfg, u32 reg)
+{
+	const u32 *map;
+	int len;
+
+	if (!pctrl->data->vddio_ops->get_oc_map)
+		return -ENOTSUPP;
+
+	len = pctrl->data->vddio_ops->get_oc_map(pin, power_cfg, &map);
+	if (len < 0)
+		return len;
+
+	if (reg >= len)
+		return -EINVAL;
+
+	return map[reg];
+}
+
+int sophgo_pinctrl_schmitt2reg(struct sophgo_pinctrl *pctrl,
+			       const struct sophgo_pin *pin,
+			       const u32 *power_cfg, u32 target)
+{
+	const u32 *map;
+	int i, len;
+
+	if (!pctrl->data->vddio_ops->get_schmitt_map)
+		return -ENOTSUPP;
+
+	len = pctrl->data->vddio_ops->get_schmitt_map(pin, power_cfg, &map);
+	if (len < 0)
+		return len;
+
+	for (i = 0; i < len; i++) {
+		if (map[i] == target)
+			return i;
+	}
+
+	return -EINVAL;
+}
+
+int sophgo_pinctrl_reg2schmitt(struct sophgo_pinctrl *pctrl,
+			       const struct sophgo_pin *pin,
+			       const u32 *power_cfg, u32 reg)
+{
+	const u32 *map;
+	int len;
+
+	if (!pctrl->data->vddio_ops->get_schmitt_map)
+		return -ENOTSUPP;
+
+	len = pctrl->data->vddio_ops->get_schmitt_map(pin, power_cfg, &map);
+	if (len < 0)
+		return len;
+
+	if (reg >= len)
+		return -EINVAL;
+
+	return map[reg];
+}
+
+MODULE_DESCRIPTION("Common pinctrl helper function for the Sophgo SoC");
+MODULE_LICENSE("GPL");
diff --git a/drivers/pinctrl/sophgo/pinctrl-sophgo.h b/drivers/pinctrl/sophgo/pinctrl-sophgo.h
index e43b4f30f18a..f8b094a09f7c 100644
--- a/drivers/pinctrl/sophgo/pinctrl-sophgo.h
+++ b/drivers/pinctrl/sophgo/pinctrl-sophgo.h
@@ -9,10 +9,13 @@
 #include <linux/device.h>
 #include <linux/mutex.h>
 #include <linux/pinctrl/pinctrl.h>
+#include <linux/platform_device.h>
 #include <linux/spinlock.h>
 
 #include "../core.h"
 
+struct sophgo_pinctrl;
+
 struct sophgo_pin {
 	u16				id;
 	u16				flags;
@@ -23,6 +26,36 @@ struct sophgo_pin_mux_config {
 	u32			config;
 };
 
+/**
+ * struct sophgo_cfg_ops - pin configuration operations
+ *
+ * @verify_pinmux_config: verify the pinmux config for a pin
+ * @verify_pin_group: verify the whole pinmux group
+ * @dt_node_to_map_post: post init for the pinmux config map
+ * @compute_pinconf_config: compute pinconf config
+ * @set_pinconf_config: set pinconf config (the caller holds lock)
+ * @set_pinmux_config: set mux config (the caller holds lock)
+ */
+struct sophgo_cfg_ops {
+	int (*verify_pinmux_config)(const struct sophgo_pin_mux_config *config);
+	int (*verify_pin_group)(const struct sophgo_pin_mux_config *pinmuxs,
+				unsigned int npins);
+	int (*dt_node_to_map_post)(struct device_node *cur,
+				   struct sophgo_pinctrl *pctrl,
+				   struct sophgo_pin_mux_config *pinmuxs,
+				   unsigned int npins);
+	int (*compute_pinconf_config)(struct sophgo_pinctrl *pctrl,
+				      const struct sophgo_pin *sp,
+				      unsigned long *configs,
+				      unsigned int num_configs,
+				      u32 *value, u32 *mask);
+	int (*set_pinconf_config)(struct sophgo_pinctrl *pctrl,
+				  const struct sophgo_pin *sp,
+				  u32 value, u32 mask);
+	void (*set_pinmux_config)(struct sophgo_pinctrl *pctrl,
+				  const struct sophgo_pin *sp, u32 config);
+};
+
 /**
  * struct sophgo_vddio_cfg_ops - pin vddio operations
  *
@@ -47,6 +80,7 @@ struct sophgo_pinctrl_data {
 	const void				*pindata;
 	const char				* const *pdnames;
 	const struct sophgo_vddio_cfg_ops	*vddio_ops;
+	const struct sophgo_cfg_ops		*cfg_ops;
 	u16					npins;
 	u16					npds;
 	u16					pinsize;
@@ -63,4 +97,33 @@ struct sophgo_pinctrl {
 	void					*priv_ctrl;
 };
 
+const struct sophgo_pin *sophgo_get_pin(struct sophgo_pinctrl *pctrl,
+					unsigned long pin_id);
+int sophgo_pctrl_dt_node_to_map(struct pinctrl_dev *pctldev, struct device_node *np,
+				struct pinctrl_map **maps, unsigned int *num_maps);
+int sophgo_pmx_set_mux(struct pinctrl_dev *pctldev,
+		       unsigned int fsel, unsigned int gsel);
+int sophgo_pconf_set(struct pinctrl_dev *pctldev, unsigned int pin_id,
+		     unsigned long *configs, unsigned int num_configs);
+int sophgo_pconf_group_set(struct pinctrl_dev *pctldev, unsigned int gsel,
+			   unsigned long *configs, unsigned int num_configs);
+u32 sophgo_pinctrl_typical_pull_down(struct sophgo_pinctrl *pctrl,
+				     const struct sophgo_pin *pin,
+				     const u32 *power_cfg);
+u32 sophgo_pinctrl_typical_pull_up(struct sophgo_pinctrl *pctrl,
+				   const struct sophgo_pin *pin,
+				   const u32 *power_cfg);
+int sophgo_pinctrl_oc2reg(struct sophgo_pinctrl *pctrl,
+			  const struct sophgo_pin *pin,
+			  const u32 *power_cfg, u32 target);
+int sophgo_pinctrl_reg2oc(struct sophgo_pinctrl *pctrl,
+			  const struct sophgo_pin *pin,
+			  const u32 *power_cfg, u32 reg);
+int sophgo_pinctrl_schmitt2reg(struct sophgo_pinctrl *pctrl,
+			       const struct sophgo_pin *pin,
+			       const u32 *power_cfg, u32 target);
+int sophgo_pinctrl_reg2schmitt(struct sophgo_pinctrl *pctrl,
+			       const struct sophgo_pin *pin,
+			       const u32 *power_cfg, u32 reg);
+
 #endif /* _PINCTRL_SOPHGO_H */
-- 
2.48.1