linux-gpio.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [v2 0/3] Add pinctrl support for sky1
@ 2025-09-12  6:06 Gary Yang
  2025-09-12  6:06 ` [v2 1/3] pinctrl: cix: Add pin-controller " Gary Yang
                   ` (3 more replies)
  0 siblings, 4 replies; 17+ messages in thread
From: Gary Yang @ 2025-09-12  6:06 UTC (permalink / raw)
  To: linus.walleij, robh, krzk+dt, conor+dt
  Cc: linux-gpio, devicetree, linux-kernel, linux-arm-kernel,
	cix-kernel-upstream, Gary Yang

Patch 1: add Cix pinctrl driver to support pinmux and pinconfigs
Patch 2: add Cix pinctrl nodes and header file
Patch 3: add yaml doc

Changes for v2:
- restructure the pinctrl driver to support pinmux=<..>
- redefine pinmux macros
- move header file from dt-bindings to dts
- fix the code-style issues



Gary Yang (3):
  pinctrl: cix: Add pin-controller support for sky1
  dt-bindings: pinctrl: Add cix,sky1-pinctrl
  arm64: dts: cix: Add pinctrl nodes for sky1

 .../bindings/pinctrl/cix,sky1-pinctrl.yaml    |   85 +
 arch/arm64/boot/dts/cix/sky1-orion-o6.dts     |   32 +
 arch/arm64/boot/dts/cix/sky1-pinfunc.h        |  417 +++++
 arch/arm64/boot/dts/cix/sky1.dtsi             |   10 +
 drivers/pinctrl/Kconfig                       |    1 +
 drivers/pinctrl/Makefile                      |    1 +
 drivers/pinctrl/cix/Kconfig                   |   14 +
 drivers/pinctrl/cix/Makefile                  |    4 +
 drivers/pinctrl/cix/pinctrl-sky1-base.c       |  581 +++++++
 drivers/pinctrl/cix/pinctrl-sky1.c            | 1435 +++++++++++++++++
 drivers/pinctrl/cix/pinctrl-sky1.h            |   46 +
 11 files changed, 2626 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/pinctrl/cix,sky1-pinctrl.yaml
 create mode 100644 arch/arm64/boot/dts/cix/sky1-pinfunc.h
 create mode 100644 drivers/pinctrl/cix/Kconfig
 create mode 100644 drivers/pinctrl/cix/Makefile
 create mode 100644 drivers/pinctrl/cix/pinctrl-sky1-base.c
 create mode 100644 drivers/pinctrl/cix/pinctrl-sky1.c
 create mode 100644 drivers/pinctrl/cix/pinctrl-sky1.h

-- 
2.49.0


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [v2 1/3] pinctrl: cix: Add pin-controller support for sky1
  2025-09-12  6:06 [v2 0/3] Add pinctrl support for sky1 Gary Yang
@ 2025-09-12  6:06 ` Gary Yang
  2025-09-12 11:59   ` Linus Walleij
  2025-09-12  6:06 ` [v2 2/3] dt-bindings: pinctrl: Add cix,sky1-pinctrl Gary Yang
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 17+ messages in thread
From: Gary Yang @ 2025-09-12  6:06 UTC (permalink / raw)
  To: linus.walleij, robh, krzk+dt, conor+dt
  Cc: linux-gpio, devicetree, linux-kernel, linux-arm-kernel,
	cix-kernel-upstream, Gary Yang

Add the pin-controller driver for Sky1 platform

Signed-off-by: Gary Yang <gary.yang@cixtech.com>
---
 drivers/pinctrl/Kconfig                 |    1 +
 drivers/pinctrl/Makefile                |    1 +
 drivers/pinctrl/cix/Kconfig             |   14 +
 drivers/pinctrl/cix/Makefile            |    4 +
 drivers/pinctrl/cix/pinctrl-sky1-base.c |  581 +++++++++
 drivers/pinctrl/cix/pinctrl-sky1.c      | 1435 +++++++++++++++++++++++
 drivers/pinctrl/cix/pinctrl-sky1.h      |   46 +
 7 files changed, 2082 insertions(+)
 create mode 100644 drivers/pinctrl/cix/Kconfig
 create mode 100644 drivers/pinctrl/cix/Makefile
 create mode 100644 drivers/pinctrl/cix/pinctrl-sky1-base.c
 create mode 100644 drivers/pinctrl/cix/pinctrl-sky1.c
 create mode 100644 drivers/pinctrl/cix/pinctrl-sky1.h

diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index ddd11668457c..a5b7177be115 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -653,6 +653,7 @@ source "drivers/pinctrl/aspeed/Kconfig"
 source "drivers/pinctrl/bcm/Kconfig"
 source "drivers/pinctrl/berlin/Kconfig"
 source "drivers/pinctrl/cirrus/Kconfig"
+source "drivers/pinctrl/cix/Kconfig"
 source "drivers/pinctrl/freescale/Kconfig"
 source "drivers/pinctrl/intel/Kconfig"
 source "drivers/pinctrl/mediatek/Kconfig"
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index 909ab89a56d2..8f353fc38e0e 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -67,6 +67,7 @@ obj-$(CONFIG_ARCH_ASPEED)	+= aspeed/
 obj-y				+= bcm/
 obj-$(CONFIG_PINCTRL_BERLIN)	+= berlin/
 obj-y				+= cirrus/
+obj-y				+= cix/
 obj-y				+= freescale/
 obj-$(CONFIG_X86)		+= intel/
 obj-y				+= mediatek/
diff --git a/drivers/pinctrl/cix/Kconfig b/drivers/pinctrl/cix/Kconfig
new file mode 100644
index 000000000000..42e064b6e7a2
--- /dev/null
+++ b/drivers/pinctrl/cix/Kconfig
@@ -0,0 +1,14 @@
+# SPDX-License-Identifier: GPL-2.0-only
+config PINCTRL_SKY1_BASE
+	tristate
+	select GENERIC_PINCTRL_GROUPS
+	select GENERIC_PINMUX_FUNCTIONS
+	select GENERIC_PINCONF
+	select REGMAP
+
+config PINCTRL_SKY1
+	tristate "Cix Sky1 pinctrl driver"
+	depends on ARCH_CIX
+	select PINCTRL_SKY1_BASE
+	help
+	  Say Y here to enable the sky1 pinctrl driver
diff --git a/drivers/pinctrl/cix/Makefile b/drivers/pinctrl/cix/Makefile
new file mode 100644
index 000000000000..22685d6a107b
--- /dev/null
+++ b/drivers/pinctrl/cix/Makefile
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
+# Cix Sky1 pin control drivers
+obj-$(CONFIG_PINCTRL_SKY1_BASE)	+= pinctrl-sky1-base.o
+obj-$(CONFIG_PINCTRL_SKY1)	+= pinctrl-sky1.o
diff --git a/drivers/pinctrl/cix/pinctrl-sky1-base.c b/drivers/pinctrl/cix/pinctrl-sky1-base.c
new file mode 100644
index 000000000000..f0028f255647
--- /dev/null
+++ b/drivers/pinctrl/cix/pinctrl-sky1-base.c
@@ -0,0 +1,581 @@
+// SPDX-License-Identifier: GPL-2.0+
+//
+// Author: Jerry Zhu <Jerry.Zhu@cixtech.com>
+
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_address.h>
+#include <linux/pinctrl/machine.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/platform_device.h>
+#include <linux/seq_file.h>
+#include <linux/slab.h>
+
+#include "../core.h"
+#include "../pinconf.h"
+#include "../pinctrl-utils.h"
+#include "../pinmux.h"
+#include "pinctrl-sky1.h"
+
+#define SKY1_PIN_SIZE		(0x4)
+#define SKY1_MUX_MASK		(0x180)
+#define SKY1_MUX_SHIFT		(0x7)
+#define SKY1_PULLCONF_MASK	(0x60)
+#define SKY1_PULLUP_SHIFT	(0x6)
+#define SKY1_PULLDN_SHIFT	(0x5)
+#define SKY1_DS_MASK		(0x0f)
+
+#define CIX_GET_PIN_NO(x) ((x) >> 8)
+#define CIX_GET_PIN_FUNC(x) ((x) & 0xf)
+
+static const char * const sky1_gpio_functions[] = {
+	"func0", "func1", "func2", "func3",
+};
+
+static const struct sky1_function_desc *sky1_pctrl_find_function_by_pin(
+		struct sky1_pinctrl *spctl, u32 pin_num, u32 fnum)
+{
+	const struct sky1_pin_desc *pin = spctl->info->pins + pin_num;
+	const struct sky1_function_desc *func = pin->functions;
+
+	while (func && func->name) {
+		if (func->muxval == fnum)
+			return func;
+		func++;
+	}
+
+	return NULL;
+}
+
+static bool sky1_pctrl_is_function_valid(struct sky1_pinctrl *spctl,
+		u32 pin_num, u32 fnum)
+{
+	int i;
+
+	for (i = 0; i < spctl->info->npins; i++) {
+		const struct sky1_pin_desc *pin = spctl->info->pins + i;
+
+		if (pin->pin.number == pin_num) {
+			const struct sky1_function_desc *func =
+					pin->functions;
+
+			while (func && func->name) {
+				if (func->muxval == fnum)
+					return true;
+				func++;
+			}
+
+			break;
+		}
+	}
+
+	return false;
+}
+
+static int sky1_pctrl_dt_node_to_map_func(struct sky1_pinctrl *spctl,
+		u32 pin, u32 fnum, struct sky1_pinctrl_group *grp,
+		struct pinctrl_map **map, unsigned int *reserved_maps,
+		unsigned int *num_maps)
+{
+	bool ret;
+
+	if (*num_maps == *reserved_maps)
+		return -ENOSPC;
+
+	(*map)[*num_maps].type = PIN_MAP_TYPE_MUX_GROUP;
+	(*map)[*num_maps].data.mux.group = grp->name;
+
+	ret = sky1_pctrl_is_function_valid(spctl, pin, fnum);
+	if (!ret) {
+		dev_err(spctl->dev, "invalid function %d on pin %d .\n",
+				fnum, pin);
+		return -EINVAL;
+	}
+
+	(*map)[*num_maps].data.mux.function = sky1_gpio_functions[fnum];
+	(*num_maps)++;
+
+	return 0;
+}
+
+static struct sky1_pinctrl_group *
+sky1_pctrl_find_group_by_pin(struct sky1_pinctrl *spctl, u32 pin)
+{
+	int i;
+
+	for (i = 0; i < spctl->info->npins; i++) {
+		struct sky1_pinctrl_group *grp =
+			(struct sky1_pinctrl_group *)spctl->groups + i;
+
+		if (grp->pin == pin)
+			return grp;
+	}
+
+	return NULL;
+}
+
+static int sky1_pctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev,
+				      struct device_node *node,
+				      struct pinctrl_map **map,
+				      unsigned int *reserved_maps,
+				      unsigned int *num_maps)
+{
+	struct property *pins;
+	u32 pinfunc, pin, func;
+	int num_pins, num_funcs, maps_per_pin;
+	unsigned long *configs;
+	unsigned int num_configs;
+	bool has_config = false;
+	int i, err;
+	unsigned int reserve = 0;
+	struct sky1_pinctrl_group *grp;
+	struct sky1_pinctrl *spctl = pinctrl_dev_get_drvdata(pctldev);
+
+	pins = of_find_property(node, "pinmux", NULL);
+	if (!pins) {
+		dev_err(spctl->dev, "missing pins property in node %pOFn .\n",
+				node);
+		return -EINVAL;
+	}
+
+	err = pinconf_generic_parse_dt_config(node, pctldev, &configs,
+		&num_configs);
+	if (err)
+		return err;
+
+	if (num_configs)
+		has_config = true;
+
+	num_pins = pins->length / sizeof(u32);
+	num_funcs = num_pins;
+	maps_per_pin = 0;
+	if (num_funcs)
+		maps_per_pin++;
+	if (has_config && num_pins >= 1)
+		maps_per_pin++;
+
+	if (!num_pins || !maps_per_pin) {
+		err = -EINVAL;
+		goto exit;
+	}
+
+	reserve = num_pins * maps_per_pin;
+
+	err = pinctrl_utils_reserve_map(pctldev, map,
+			reserved_maps, num_maps, reserve);
+	if (err < 0)
+		goto exit;
+
+	for (i = 0; i < num_pins; i++) {
+		err = of_property_read_u32_index(node, "pinmux",
+				i, &pinfunc);
+		if (err)
+			goto exit;
+
+		pin = CIX_GET_PIN_NO(pinfunc);
+		func = CIX_GET_PIN_FUNC(pinfunc);
+		pctldev->num_functions = 4;
+
+		if (pin >= pctldev->desc->npins ||
+			func >= pctldev->num_functions) {
+			dev_err(spctl->dev, "invalid pins value.\n");
+			err = -EINVAL;
+			goto exit;
+		}
+
+		grp = sky1_pctrl_find_group_by_pin(spctl, pin);
+		if (!grp) {
+			dev_err(spctl->dev, "unable to match pin %d to group\n",
+					pin);
+			err = -EINVAL;
+			goto exit;
+		}
+
+		err = sky1_pctrl_dt_node_to_map_func(spctl, pin, func, grp,
+				map, reserved_maps, num_maps);
+		if (err < 0)
+			goto exit;
+
+		if (has_config) {
+			err = pinctrl_utils_add_map_configs(pctldev, map,
+					reserved_maps, num_maps, grp->name,
+					configs, num_configs,
+					PIN_MAP_TYPE_CONFIGS_GROUP);
+			if (err < 0)
+				goto exit;
+		}
+	}
+
+	err = 0;
+
+exit:
+	kfree(configs);
+	return err;
+}
+
+static int sky1_pctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
+				 struct device_node *np_config,
+				 struct pinctrl_map **map, unsigned int *num_maps)
+{
+	unsigned int reserved_maps;
+	int ret;
+
+	*map = NULL;
+	*num_maps = 0;
+	reserved_maps = 0;
+
+	for_each_child_of_node_scoped(np_config, np) {
+		ret = sky1_pctrl_dt_subnode_to_map(pctldev, np, map,
+				&reserved_maps, num_maps);
+		if (ret < 0) {
+			pinctrl_utils_free_map(pctldev, *map, *num_maps);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+static void sky1_dt_free_map(struct pinctrl_dev *pctldev,
+			     struct pinctrl_map *map,
+			     unsigned int num_maps)
+{
+	kfree(map);
+}
+
+static int sky1_pctrl_get_groups_count(struct pinctrl_dev *pctldev)
+{
+	struct sky1_pinctrl *spctl = pinctrl_dev_get_drvdata(pctldev);
+
+	return spctl->info->npins;
+}
+
+static const char *sky1_pctrl_get_group_name(struct pinctrl_dev *pctldev,
+					      unsigned int group)
+{
+	struct sky1_pinctrl *spctl = pinctrl_dev_get_drvdata(pctldev);
+
+	return spctl->groups[group].name;
+}
+
+static int sky1_pctrl_get_group_pins(struct pinctrl_dev *pctldev,
+				      unsigned int group,
+				      const unsigned int **pins,
+				      unsigned int *num_pins)
+{
+	struct sky1_pinctrl *spctl = pinctrl_dev_get_drvdata(pctldev);
+
+	*pins = (unsigned int *)&spctl->groups[group].pin;
+	*num_pins = 1;
+
+	return 0;
+}
+
+static void sky1_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
+		   unsigned int offset)
+{
+	seq_printf(s, "%s", dev_name(pctldev->dev));
+}
+
+static const struct pinctrl_ops sky1_pctrl_ops = {
+	.dt_node_to_map = sky1_pctrl_dt_node_to_map,
+	.dt_free_map = sky1_dt_free_map,
+	.get_groups_count = sky1_pctrl_get_groups_count,
+	.get_group_name = sky1_pctrl_get_group_name,
+	.get_group_pins = sky1_pctrl_get_group_pins,
+	.pin_dbg_show = sky1_pin_dbg_show,
+};
+
+static int sky1_pmx_set_one_pin(struct sky1_pinctrl *spctl,
+				    unsigned int pin, unsigned char muxval)
+{
+	u32 reg_val;
+	u32 *pin_reg;
+
+	pin_reg = spctl->base + pin * SKY1_PIN_SIZE;
+	reg_val = readl(pin_reg);
+	reg_val &= ~SKY1_MUX_MASK;
+	reg_val |= muxval << SKY1_MUX_SHIFT;
+	writel(reg_val, pin_reg);
+
+	dev_dbg(spctl->dev, "write: offset 0x%x val 0x%x\n",
+		pin * SKY1_PIN_SIZE, reg_val);
+	return 0;
+}
+
+static int sky1_pmx_set_mux(struct pinctrl_dev *pctldev,
+			    unsigned int function,
+			    unsigned int group)
+{
+	bool ret;
+	const struct sky1_function_desc *desc;
+	struct sky1_pinctrl *spctl = pinctrl_dev_get_drvdata(pctldev);
+	struct sky1_pinctrl_group *g =
+		(struct sky1_pinctrl_group *)spctl->groups + group;
+
+	ret = sky1_pctrl_is_function_valid(spctl, g->pin, function);
+	if (!ret) {
+		dev_err(spctl->dev, "invalid function %d on group %d .\n",
+				function, group);
+		return -EINVAL;
+	}
+
+	desc = sky1_pctrl_find_function_by_pin(spctl, g->pin, function);
+	if (!desc)
+		return -EINVAL;
+
+	sky1_pmx_set_one_pin(spctl, g->pin, desc->muxval);
+	return 0;
+}
+
+static int sky1_pmx_get_funcs_cnt(struct pinctrl_dev *pctldev)
+{
+	return ARRAY_SIZE(sky1_gpio_functions);
+}
+
+static const char *sky1_pmx_get_func_name(struct pinctrl_dev *pctldev,
+					   unsigned int selector)
+{
+	return sky1_gpio_functions[selector];
+}
+
+static int sky1_pmx_get_func_groups(struct pinctrl_dev *pctldev,
+				     unsigned int function,
+				     const char * const **groups,
+				     unsigned int * const num_groups)
+{
+	struct sky1_pinctrl *spctl = pinctrl_dev_get_drvdata(pctldev);
+	const struct sky1_pinctrl_soc_info *info = spctl->info;
+
+	*groups = spctl->grp_names;
+	*num_groups = info->npins;
+
+	return 0;
+}
+
+static const struct pinmux_ops sky1_pmx_ops = {
+	.get_functions_count = sky1_pmx_get_funcs_cnt,
+	.get_function_groups = sky1_pmx_get_func_groups,
+	.get_function_name = sky1_pmx_get_func_name,
+	.set_mux = sky1_pmx_set_mux,
+};
+
+static int sky1_pconf_set_pull_select(struct sky1_pinctrl *spctl,
+		unsigned int pin, bool enable, bool isup)
+{
+	u32 reg_val, reg_pullsel = 0;
+	u32 *pin_reg;
+
+	pin_reg = spctl->base + pin * SKY1_PIN_SIZE;
+	reg_val = readl(pin_reg);
+	reg_val &= ~SKY1_PULLCONF_MASK;
+
+	if (!enable)
+		goto update;
+
+	if (isup)
+		reg_pullsel = BIT(SKY1_PULLUP_SHIFT);
+	else
+		reg_pullsel = BIT(SKY1_PULLDN_SHIFT);
+
+update:
+	reg_val |= reg_pullsel;
+	writel(reg_val, pin_reg);
+
+	dev_dbg(spctl->dev, "write: offset 0x%x val 0x%x\n",
+		pin * SKY1_PIN_SIZE, reg_val);
+	return 0;
+}
+
+static int sky1_pconf_set_driving(struct sky1_pinctrl *spctl,
+		unsigned int pin, unsigned char driving)
+{
+	unsigned int reg_val;
+	u32 *pin_reg;
+
+	if (pin >= spctl->info->npins)
+		return -EINVAL;
+
+	pin_reg = spctl->base + pin * SKY1_PIN_SIZE;
+	reg_val = readl(pin_reg);
+	reg_val &= ~SKY1_DS_MASK;
+	reg_val |= (driving & SKY1_DS_MASK);
+	writel(reg_val, pin_reg);
+
+	dev_dbg(spctl->dev, "write: offset 0x%x val 0x%x\n",
+		pin * SKY1_PIN_SIZE, reg_val);
+
+	return 0;
+}
+
+static int sky1_pconf_parse_conf(struct pinctrl_dev *pctldev,
+		unsigned int pin, enum pin_config_param param,
+		enum pin_config_param arg)
+{
+	int ret = 0;
+	struct sky1_pinctrl *spctl = pinctrl_dev_get_drvdata(pctldev);
+
+	switch (param) {
+	case PIN_CONFIG_BIAS_DISABLE:
+		ret = sky1_pconf_set_pull_select(spctl, pin, false, false);
+		break;
+	case PIN_CONFIG_BIAS_PULL_UP:
+		ret = sky1_pconf_set_pull_select(spctl, pin, true, true);
+		break;
+	case PIN_CONFIG_BIAS_PULL_DOWN:
+		ret = sky1_pconf_set_pull_select(spctl, pin, true, false);
+		break;
+	case PIN_CONFIG_DRIVE_STRENGTH:
+		ret = sky1_pconf_set_driving(spctl, pin, arg);
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static int sky1_pconf_group_get(struct pinctrl_dev *pctldev,
+				 unsigned int group,
+				 unsigned long *config)
+{
+	struct sky1_pinctrl *spctl = pinctrl_dev_get_drvdata(pctldev);
+	struct sky1_pinctrl_group *g = &spctl->groups[group];
+
+	*config = g->config;
+
+	return 0;
+}
+
+static int sky1_pconf_group_set(struct pinctrl_dev *pctldev, unsigned int group,
+				 unsigned long *configs, unsigned int num_configs)
+{
+	struct sky1_pinctrl *spctl = pinctrl_dev_get_drvdata(pctldev);
+	struct sky1_pinctrl_group *g = &spctl->groups[group];
+	int i, ret;
+
+	for (i = 0; i < num_configs; i++) {
+		ret = sky1_pconf_parse_conf(pctldev, g->pin,
+			pinconf_to_config_param(configs[i]),
+			pinconf_to_config_argument(configs[i]));
+		if (ret < 0)
+			return ret;
+
+		g->config = configs[i];
+	}
+
+	return 0;
+}
+
+static const struct pinconf_ops sky1_pinconf_ops = {
+	.pin_config_group_get	= sky1_pconf_group_get,
+	.pin_config_group_set	= sky1_pconf_group_set,
+};
+
+static int sky1_pctrl_build_state(struct platform_device *pdev)
+{
+	struct sky1_pinctrl *spctl = platform_get_drvdata(pdev);
+	const struct sky1_pinctrl_soc_info *info = spctl->info;
+	int i;
+
+	/* Allocate groups */
+	spctl->groups = devm_kcalloc(&pdev->dev, info->npins,
+				    sizeof(*spctl->groups), GFP_KERNEL);
+	if (!spctl->groups)
+		return -ENOMEM;
+
+	/* We assume that one pin is one group, use pin name as group name. */
+	spctl->grp_names = devm_kcalloc(&pdev->dev, info->npins,
+				       sizeof(*spctl->grp_names), GFP_KERNEL);
+	if (!spctl->grp_names)
+		return -ENOMEM;
+
+	for (i = 0; i < info->npins; i++) {
+		const struct sky1_pin_desc *pin = spctl->info->pins + i;
+		struct sky1_pinctrl_group *group =
+			(struct sky1_pinctrl_group *)spctl->groups + i;
+
+		group->name = pin->pin.name;
+		group->pin = pin->pin.number;
+		spctl->grp_names[i] = pin->pin.name;
+	}
+
+	return 0;
+}
+
+int sky1_base_pinctrl_probe(struct platform_device *pdev,
+		      const struct sky1_pinctrl_soc_info *info)
+{
+	struct pinctrl_desc *sky1_pinctrl_desc;
+	struct sky1_pinctrl *spctl;
+	struct pinctrl_pin_desc *pins;
+	int ret, i;
+
+	if (!info || !info->pins || !info->npins) {
+		dev_err(&pdev->dev, "wrong pinctrl info\n");
+		return -EINVAL;
+	}
+
+	/* Create state holders etc for this driver */
+	spctl = devm_kzalloc(&pdev->dev, sizeof(*spctl), GFP_KERNEL);
+	if (!spctl)
+		return -ENOMEM;
+
+	spctl->info = info;
+	platform_set_drvdata(pdev, spctl);
+
+	spctl->base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(spctl->base))
+		return PTR_ERR(spctl->base);
+
+	sky1_pinctrl_desc = devm_kzalloc(&pdev->dev, sizeof(*sky1_pinctrl_desc),
+					GFP_KERNEL);
+	if (!sky1_pinctrl_desc)
+		return -ENOMEM;
+
+	pins = devm_kcalloc(&pdev->dev, info->npins, sizeof(*pins),
+			    GFP_KERNEL);
+	if (!pins)
+		return -ENOMEM;
+	for (i = 0; i < info->npins; i++)
+		pins[i] = info->pins[i].pin;
+
+	ret = sky1_pctrl_build_state(pdev);
+	if (ret)
+		return ret;
+
+	sky1_pinctrl_desc->name = dev_name(&pdev->dev);
+	sky1_pinctrl_desc->pins = pins;
+	sky1_pinctrl_desc->npins = info->npins;
+	sky1_pinctrl_desc->pctlops = &sky1_pctrl_ops;
+	sky1_pinctrl_desc->pmxops = &sky1_pmx_ops;
+	sky1_pinctrl_desc->confops = &sky1_pinconf_ops;
+	sky1_pinctrl_desc->owner = THIS_MODULE;
+	spctl->dev = &pdev->dev;
+	ret = devm_pinctrl_register_and_init(&pdev->dev,
+					     sky1_pinctrl_desc, spctl,
+					     &spctl->pctl);
+	if (ret) {
+		dev_err(&pdev->dev, "could not register SKY1 pinctrl driver\n");
+		return ret;
+	}
+
+	pinctrl_provide_dummies();
+	dev_dbg(&pdev->dev, "initialized SKY1 pinctrl driver\n");
+
+	return pinctrl_enable(spctl->pctl);
+}
+EXPORT_SYMBOL_GPL(sky1_base_pinctrl_probe);
+
+
+MODULE_AUTHOR("Jerry Zhu <Jerry.Zhu@cixtech.com>");
+MODULE_DESCRIPTION("Cix SKy1 pinctrl driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/pinctrl/cix/pinctrl-sky1.c b/drivers/pinctrl/cix/pinctrl-sky1.c
new file mode 100644
index 000000000000..3205665959ca
--- /dev/null
+++ b/drivers/pinctrl/cix/pinctrl-sky1.c
@@ -0,0 +1,1435 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/platform_device.h>
+#include "linux/stddef.h"
+
+#include "../core.h"
+#include "pinctrl-sky1.h"
+
+/* Pad names for the s5 domain pinmux subsystem */
+static const struct sky1_pin_desc sky1_pinctrl_s5_pads[] = {
+	{
+		.pin = PINCTRL_PIN(0, "GPIO1"),
+		.functions = {
+			[0] = {0, "GPIO1"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(1, "GPIO2"),
+		.functions = {
+			[0] = {0, "GPIO2"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(2, "GPIO3"),
+		.functions = {
+			[0] = {0, "GPIO3"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(3, "GPIO4"),
+		.functions = {
+			[0] = {0, "GPIO4"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(4, "GPIO5"),
+		.functions = {
+			[0] = {0, "GPIO5"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(5, "GPIO6"),
+		.functions = {
+			[0] = {0, "GPIO6"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(6, "GPIO7"),
+		.functions = {
+			[0] = {0, "GPIO7"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(7, "GPIO8"),
+		.functions = {
+			[0] = {0, "GPIO8"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(8, "GPIO9"),
+		.functions = {
+			[0] = {0, "GPIO9"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(9, "GPIO10"),
+		.functions = {
+			[0] = {0, "GPIO10"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(10, "GPIO11"),
+		.functions = {
+			[0] = {0, "GPIO11"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(11, "GPIO12"),
+		.functions = {
+			[0] = {0, "GPIO12"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(12, "GPIO13"),
+		.functions = {
+			[0] = {0, "GPIO13"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(13, "GPIO14"),
+		.functions = {
+			[0] = {0, "GPIO14"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(14, "RSMRST_L"),
+	},
+	{
+		.pin = PINCTRL_PIN(15, "SRST_L"),
+	},
+	{
+		.pin = PINCTRL_PIN(16, "SLP_S3_L"),
+	},
+	{
+		.pin = PINCTRL_PIN(17, "SLP_S5_L"),
+	},
+	{
+		.pin = PINCTRL_PIN(18, "PWRGD"),
+	},
+	{
+		.pin = PINCTRL_PIN(19, "PWROK"),
+	},
+	{
+		.pin = PINCTRL_PIN(20, "PWRBTN_L"),
+	},
+	{
+		.pin = PINCTRL_PIN(21, "VDD_DDRIO_GATE"),
+	},
+	{
+		.pin = PINCTRL_PIN(22, "JTAG_GPIO_L"),
+	},
+	{
+		.pin = PINCTRL_PIN(23, "JTAG_TCK"),
+	},
+	{
+		.pin = PINCTRL_PIN(24, "JTAG_TDI"),
+	},
+	{
+		.pin = PINCTRL_PIN(25, "JTAG_TDO"),
+	},
+	{
+		.pin = PINCTRL_PIN(26, "TMS"),
+	},
+	{
+		.pin = PINCTRL_PIN(27, "TRSL_L"),
+	},
+	{
+		.pin = PINCTRL_PIN(28, "SFI_I2C0_SCL"),
+		.functions = {
+			[0] = {0, "SFI_I2C0_SCL"},
+			[1] = {1, "SFI_I3C0_SCL"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(29, "SFI_I2C0_SDA"),
+		.functions = {
+			[0] = {0, "SFI_I2C0_SDA"},
+			[1] = {1, "SFI_I3C0_SDA"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(30, "SFI_I2C1_SCL"),
+		.functions = {
+			[0] = {0, "SFI_I2C1_SCL"},
+			[1] = {1, "SFI_I3C1_SCL"},
+			[2] = {2, "SFI_SPI_CS0"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(31, "SFI_I2C1_SDA"),
+		.functions = {
+			[0] = {0, "SFI_I2C1_SDA"},
+			[1] = {1, "SFI_I3C1_SDA"},
+			[2] = {2, "SFI_SPI_CS1"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(32, "SFI_GPIO0"),
+		.functions = {
+			[0] = {0, "GPIO15"},
+			[1] = {1, "SFI_SPI_SCK"},
+			[2] = {2, "SFI_GPIO0"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(33, "SFI_GPIO1"),
+		.functions = {
+			[0] = {0, "GPIO16"},
+			[1] = {1, "SFI_SPI_MOSI"},
+			[2] = {2, "SFI_GPIO1"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(34, "SFI_GPIO2"),
+		.functions = {
+			[0] = {0, "GPIO17"},
+			[1] = {1, "SFI_SPI_MISO"},
+			[2] = {2, "SFI_GPIO2"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(35, "GPIO18"),
+		.functions = {
+			[0] = {0, "SFI_GPIO3"},
+			[1] = {1, "GPIO18"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(36, "GPIO19"),
+		.functions = {
+			[0] = {0, "SFI_GPIO4"},
+			[1] = {1, "GPIO19"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(37, "GPIO20"),
+		.functions = {
+			[0] = {0, "SFI_GPIO5"},
+			[1] = {1, "GPIO20"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(38, "GPIO21"),
+		.functions = {
+			[0] = {0, "SFI_GPIO6"},
+			[1] = {1, "GPIO21"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(39, "GPIO22"),
+		.functions = {
+			[0] = {0, "SFI_GPIO7"},
+			[1] = {1, "GPIO22"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(40, "GPIO23"),
+		.functions = {
+			[0] = {0, "SFI_GPIO8"},
+			[1] = {1, "GPIO23"},
+			[2] = {2, "SFI_I3C0_PUR_EN_L"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(41, "GPIO24"),
+		.functions = {
+			[0] = {0, "SFI_GPIO9"},
+			[1] = {1, "GPIO24"},
+			[2] = {2, "SFI_I3C1_PUR_EN_L"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(42, "SPI1_MISO"),
+		.functions = {
+			[0] = {0, "SPI1_MISO"},
+			[1] = {1, "GPIO25"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(43, "SPI1_CS0"),
+		.functions = {
+			[0] = {0, "SPI1_CS0"},
+			[1] = {1, "GPIO26"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(44, "SPI1_CS1"),
+		.functions = {
+			[0] = {0, "SPI1_CS1"},
+			[1] = {1, "GPIO27"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(45, "SPI1_MOSI"),
+		.functions = {
+			[0] = {0, "SPI1_MOSI"},
+			[1] = {1, "GPIO28"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(46, "SPI1_CLK"),
+		.functions = {
+			[0] = {0, "SPI1_CLK"},
+			[1] = {1, "GPIO29"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(47, "GPIO30"),
+		.functions = {
+			[0] = {0, "GPIO30"},
+			[1] = {1, "USB_0C0_L"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(48, "GPIO31"),
+		.functions = {
+			[0] = {0, "GPIO31"},
+			[1] = {1, "USB_0C1_L"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(49, "GPIO32"),
+		.functions = {
+			[0] = {0, "GPIO32"},
+			[1] = {1, "USB_0C2_L"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(50, "GPIO33"),
+		.functions = {
+			[0] = {0, "GPIO33"},
+			[1] = {1, "USB_0C3_L"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(51, "GPIO34"),
+		.functions = {
+			[0] = {0, "GPIO34"},
+			[1] = {1, "USB_0C4_L"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(52, "GPIO35"),
+		.functions = {
+			[0] = {0, "GPIO35"},
+			[1] = {1, "USB_0C5_L"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(53, "GPIO36"),
+		.functions = {
+			[0] = {0, "GPIO36"},
+			[1] = {1, "USB_0C6_L"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(54, "GPIO37"),
+		.functions = {
+			[0] = {0, "GPIO37"},
+			[1] = {1, "USB_0C7_L"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(55, "GPIO38"),
+		.functions = {
+			[0] = {0, "GPIO38"},
+			[1] = {1, "USB_0C8_L"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(56, "GPIO39"),
+		.functions = {
+			[0] = {0, "GPIO39"},
+			[1] = {1, "USB_0C9_L"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(57, "GPIO40"),
+		.functions = {
+			[0] = {0, "GPIO40"},
+			[1] = {1, "USB_DRIVE_VBUS0"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(58, "GPIO41"),
+		.functions = {
+			[0] = {0, "GPIO41"},
+			[1] = {1, "USB_DRIVE_VBUS4"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(59, "GPIO42"),
+		.functions = {
+			[0] = {0, "GPIO42"},
+			[1] = {1, "USB_DRIVE_VBUS5"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(60, "SE_QSPI_CLK"),
+		.functions = {
+			[0] = {0, "SE_QSPI_CLK"},
+			[1] = {1, "QSPI_CLK"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(61, "SE_QSPI_CS_L"),
+		.functions = {
+			[0] = {0, "SE_QSPI_CS_L"},
+			[1] = {1, "QSPI_CS_L"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(62, "SE_QSPI_DATA0"),
+		.functions = {
+			[0] = {0, "SE_QSPI_DATA0"},
+			[1] = {1, "QSPI_DATA0"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(63, "SE_QSPI_DATA1"),
+		.functions = {
+			[0] = {0, "SE_QSPI_DATA1"},
+			[1] = {1, "QSPI_DATA1"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(64, "SE_QSPI_DATA2"),
+		.functions = {
+			[0] = {0, "SE_QSPI_DATA2"},
+			[1] = {1, "QSPI_DATA2"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(65, "SE_QSPI_DATA3"),
+		.functions = {
+			[0] = {0, "SE_QSPI_DATA3"},
+			[1] = {1, "QSPI_DATA3"},
+		},
+	},
+};
+
+/* Pad names for the s0 domain pinmux subsystem */
+static const struct sky1_pin_desc sky1_pinctrl_pads[] = {
+	{
+		.pin = PINCTRL_PIN(0, "GPIO43"),
+		.functions = {
+			[0] = {0, "GPIO43"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(1, "GPIO44"),
+		.functions = {
+			[0] = {0, "GPIO44"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(2, "GPIO45"),
+		.functions = {
+			[0] = {0, "GPIO45"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(3, "GPIO46"),
+		.functions = {
+			[0] = {0, "GPIO46"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(4, "RESET_IN_L"),
+	},
+	{
+		.pin = PINCTRL_PIN(5, "PLT_RESET_L"),
+	},
+	{
+		.pin = PINCTRL_PIN(6, "THERMTRIP_L"),
+	},
+	{
+		.pin = PINCTRL_PIN(7, "PROCHOT_L"),
+	},
+	{
+		.pin = PINCTRL_PIN(8, "PM_I2C0_CLK"),
+	},
+	{
+		.pin = PINCTRL_PIN(9, "PM_I2C0_DATA"),
+	},
+	{
+		.pin = PINCTRL_PIN(10, "PM_I2C1_CLK"),
+	},
+	{
+		.pin = PINCTRL_PIN(11, "PM_I2C1_DATA"),
+	},
+	{
+		.pin = PINCTRL_PIN(12, "PM_I2C2_CLK"),
+	},
+	{
+		.pin = PINCTRL_PIN(13, "PM_I2C2_DATA"),
+	},
+	{
+		.pin = PINCTRL_PIN(14, "PM_I2C3_CLK"),
+	},
+	{
+		.pin = PINCTRL_PIN(15, "PM_I2C3_DATA"),
+	},
+	{
+		.pin = PINCTRL_PIN(16, "STRAP0"),
+	},
+	{
+		.pin = PINCTRL_PIN(17, "STRAP1"),
+	},
+	{
+		.pin = PINCTRL_PIN(18, "DP2_DIGON"),
+		.functions = {
+			[0] = {0, "DP2_DIGON"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(19, "DP2_BLON"),
+		.functions = {
+			[0] = {0, "DP2_BLON"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(20, "DP2_VARY_BL"),
+		.functions = {
+			[0] = {0, "DP2_VARY_BL"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(21, "I2C7_SCL"),
+		.functions = {
+			[0] = {0, "I2C7_SCL"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(22, "I2C7_SDA"),
+		.functions = {
+			[0] = {0, "I2C7_SDA"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(23, "UART6_CSU_SE_TXD"),
+	},
+	{
+		.pin = PINCTRL_PIN(24, "CLK_REQ1_L"),
+	},
+	{
+		.pin = PINCTRL_PIN(25, "CLK_REQ3_L"),
+	},
+	{
+		.pin = PINCTRL_PIN(26, "I2C5_SCL"),
+		.functions = {
+			[0] = {0, "I2C5_SCL"},
+			[1] = {1, "GPIO47"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(27, "I2C5_SDA"),
+		.functions = {
+			[0] = {0, "I2C5_SDA"},
+			[1] = {1, "GPIO48"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(28, "I2C6_SCL"),
+		.functions = {
+			[0] = {0, "I2C6_SCL"},
+			[1] = {1, "GPIO49"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(29, "I2C6_SDA"),
+		.functions = {
+			[0] = {0, "I2C6_SDA"},
+			[1] = {1, "GPIO50"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(30, "I2C0_CLK"),
+		.functions = {
+			[0] = {0, "I2C0_CLK"},
+			[1] = {1, "GPIO51"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(31, "I2C0_SDA"),
+		.functions = {
+			[0] = {0, "I2C0_SDA"},
+			[1] = {1, "GPIO52"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(32, "I2C1_CLK"),
+		.functions = {
+			[0] = {0, "I2C1_CLK"},
+			[1] = {1, "GPIO53"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(33, "I2C1_SDA"),
+		.functions = {
+			[0] = {0, "I2C5_SCL"},
+			[1] = {1, "GPIO54"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(34, "I2C2_SCL"),
+		.functions = {
+			[0] = {0, "I2C2_SCL"},
+			[1] = {1, "I3C0_SCL"},
+			[2] = {2, "GPIO55"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(35, "I2C2_SDA"),
+		.functions = {
+			[0] = {0, "I2C2_SDA"},
+			[1] = {1, "I3C0_SDA"},
+			[2] = {2, "GPIO56"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(36, "GPIO57"),
+		.functions = {
+			[0] = {0, "GPIO57"},
+			[1] = {1, "I3C0_PUR_EN_L"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(37, "I2C3_CLK"),
+		.functions = {
+			[0] = {0, "I2C3_CLK"},
+			[1] = {1, "I3C1_CLK"},
+			[2] = {2, "GPIO58"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(38, "I2C3_SDA"),
+		.functions = {
+			[0] = {0, "I2C3_SDA"},
+			[1] = {1, "I3C1_SDA"},
+			[2] = {2, "GPIO59"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(39, "GPIO60"),
+		.functions = {
+			[0] = {0, "GPIO60"},
+			[1] = {1, "I3C1_PUR_EN_L"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(40, "I2C4_CLK"),
+		.functions = {
+			[0] = {0, "I2C4_CLK"},
+			[1] = {1, "GPIO61"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(41, "I2C4_SDA"),
+		.functions = {
+			[0] = {0, "I2C4_SDA"},
+			[1] = {1, "GPIO62"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(42, "HDA_BITCLK"),
+		.functions = {
+			[0] = {0, "HDA_BITCLK"},
+			[1] = {1, "I2S0_SCK"},
+			[2] = {2, "I2S9_RSCK_DBG"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(43, "HDA_RST_L"),
+		.functions = {
+			[0] = {0, "HDA_RST_L"},
+			[1] = {1, "I2S0_DATA_IN"},
+			[2] = {2, "I2S9_DATA_IN_DBG"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(44, "HDA_SDIN0"),
+		.functions = {
+			[0] = {0, "HDA_SDIN0"},
+			[1] = {1, "I2S0_MCLK"},
+			[2] = {2, "I2S9_TSCK_DBG"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(45, "HDA_SDOUT0"),
+		.functions = {
+			[0] = {0, "HDA_SDOUT0"},
+			[1] = {1, "I2S0_DATA_OUT"},
+			[2] = {2, "I2S9_TWS_DBG"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(46, "HDA_SYNC"),
+		.functions = {
+			[0] = {0, "HDA_SYNC"},
+			[1] = {1, "I2S0_WS"},
+			[2] = {2, "I2S9_RWS_DBG"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(47, "HDA_SDIN1"),
+		.functions = {
+			[0] = {0, "HDA_SDIN1"},
+			[1] = {1, "GPIO63"},
+			[2] = {2, "I2S9_DATA_IN1_DBG"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(48, "HDA_SDOUT1"),
+		.functions = {
+			[0] = {0, "HDA_SDOUT1"},
+			[1] = {1, "GPIO64"},
+			[2] = {2, "I2S9_DATA_OUT0_DBG"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(49, "I2S1_MCLK"),
+		.functions = {
+			[0] = {0, "I2S1_MCLK"},
+			[1] = {1, "GPIO65"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(50, "I2S1_SCK"),
+		.functions = {
+			[0] = {0, "I2S1_SCK"},
+			[1] = {1, "GPIO66"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(51, "I2S1_WS"),
+		.functions = {
+			[0] = {0, "I2S1_WS"},
+			[1] = {1, "GPIO67"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(52, "I2S1_DATA_IN"),
+		.functions = {
+			[0] = {0, "I2S1_DATA_IN"},
+			[1] = {1, "GPIO68"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(53, "I2S1_DATA_OUT"),
+		.functions = {
+			[0] = {0, "I2S1_DATA_OUT"},
+			[1] = {1, "GPIO69"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(54, "I2S2_MCLK"),
+		.functions = {
+			[0] = {0, "I2S2_MCLK"},
+			[1] = {1, "GPIO70"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(55, "I2S2_RSCK"),
+		.functions = {
+			[0] = {0, "I2S2_RSCK"},
+			[1] = {1, "GPIO71"},
+			[2] = {2, "I2S5_RSCK_DBG"},
+			[3] = {3, "I2S6_RSCK_DBG"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(56, "I2S2_RWS"),
+		.functions = {
+			[0] = {0, "I2S2_RWS"},
+			[1] = {1, "GPIO72"},
+			[2] = {2, "I2S5_RWS_DBG"},
+			[3] = {3, "I2S6_RWS_DBG"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(57, "I2S2_TSCK"),
+		.functions = {
+			[0] = {0, "I2S2_TSCK"},
+			[1] = {1, "GPIO73"},
+			[2] = {2, "I2S5_TSCK_DBG"},
+			[3] = {3, "I2S6_TSCK_DBG"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(58, "I2S2_TWS"),
+		.functions = {
+			[0] = {0, "I2S2_TWS"},
+			[1] = {1, "GPIO74"},
+			[2] = {2, "I2S5_TWS_DBG"},
+			[3] = {3, "I2S6_TWS_DBG"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(59, "I2S2_DATA_IN0"),
+		.functions = {
+			[0] = {0, "I2S2_DATA_IN0"},
+			[1] = {1, "GPIO75"},
+			[2] = {2, "I2S5_DATA_IN0_DBG"},
+			[3] = {3, "I2S6_DATA_IN0_DBG"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(60, "I2S2_DATA_IN1"),
+		.functions = {
+			[0] = {0, "I2S2_DATA_IN1"},
+			[1] = {1, "GPIO76"},
+			[2] = {2, "I2S5_DATA_IN1_DBG"},
+			[3] = {3, "I2S6_DATA_IN1_DBG"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(61, "I2S2_DATA_OUT0"),
+		.functions = {
+			[0] = {0, "I2S2_DATA_OUT0"},
+			[1] = {1, "GPIO77"},
+			[2] = {2, "I2S5_DATA_OUT0_DBG"},
+			[3] = {3, "I2S6_DATA_OUT0_DBG"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(62, "I2S2_DATA_OUT1"),
+		.functions = {
+			[0] = {0, "I2S2_DATA_OUT1"},
+			[1] = {1, "GPIO78"},
+			[2] = {2, "I2S5_DATA_OUT1_DBG"},
+			[3] = {3, "I2S6_DATA_OUT1_DBG"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(63, "I2S2_DATA_OUT2"),
+		.functions = {
+			[0] = {0, "I2S2_DATA_OUT2"},
+			[1] = {1, "GPIO79"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(64, "I2S2_DATA_OUT3"),
+		.functions = {
+			[0] = {0, "I2S2_DATA_OUT3"},
+			[1] = {1, "GPIO80"},
+			[2] = {2, "I2S9_DATA_OUT1_DBG"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(65, "I2S3_MCLK"),
+		.functions = {
+			[0] = {0, "I2S3_MCLK"},
+			[1] = {1, "GPIO81"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(66, "I2S3_RSCK"),
+		.functions = {
+			[0] = {0, "I2S3_RSCK"},
+			[1] = {1, "GPIO82"},
+			[2] = {2, "I2S7_RSCK_DBG"},
+			[3] = {3, "I2S8_RSCK_DBG"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(67, "I2S3_RWS"),
+		.functions = {
+			[0] = {0, "I2S3_RWS"},
+			[1] = {1, "GPIO83"},
+			[2] = {2, "I2S7_RWS_DBG"},
+			[3] = {3, "I2S8_RWS_DBG"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(68, "I2S3_TSCK"),
+		.functions = {
+			[0] = {0, "I2S3_TSCK"},
+			[1] = {1, "GPIO84"},
+			[2] = {2, "I2S7_TSCK_DBG"},
+			[3] = {3, "I2S8_TSCK_DBG"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(69, "I2S3_TWS"),
+		.functions = {
+			[0] = {0, "I2S3_TWS"},
+			[1] = {1, "GPIO85"},
+			[2] = {2, "I2S7_TWS_DBG"},
+			[3] = {3, "I2S8_TWS_DBG"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(70, "I2S3_DATA_IN0"),
+		.functions = {
+			[0] = {0, "I2S3_DATA_IN0"},
+			[1] = {1, "GPIO86"},
+			[2] = {2, "I2S7_DATA_IN0_DBG"},
+			[3] = {3, "I2S8_DATA_IN0_DBG"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(71, "I2S3_DATA_IN1"),
+		.functions = {
+			[0] = {0, "I2S3_DATA_IN1"},
+			[1] = {1, "GPIO87"},
+			[2] = {2, "I2S7_DATA_IN1_DBG"},
+			[3] = {3, "I2S8_DATA_IN1_DBG"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(72, "I2S3_DATA_OUT0"),
+		.functions = {
+			[0] = {0, "I2S3_DATA_OUT0"},
+			[1] = {1, "GPIO88"},
+			[2] = {2, "I2S7_DATA_OUT0_DBG"},
+			[3] = {3, "I2S8_DATA_OUT0_DBG"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(73, "I2S3_DATA_OUT1"),
+		.functions = {
+			[0] = {0, "I2S3_DATA_OUT1"},
+			[1] = {1, "GPIO89"},
+			[2] = {2, "I2S7_DATA_OUT1_DBG"},
+			[3] = {3, "I2S8_DATA_OUT1_DBG"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(74, "GPIO90"),
+		.functions = {
+			[0] = {0, "GPIO90"},
+			[1] = {1, "I2S4_MCLK_LB"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(75, "GPIO91"),
+		.functions = {
+			[0] = {0, "GPIO91"},
+			[1] = {1, "I2S4_SCK_LB"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(76, "GPIO92"),
+		.functions = {
+			[0] = {0, "GPIO92"},
+			[1] = {1, "I2S4_WS_LB"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(77, "GPIO93"),
+		.functions = {
+			[0] = {0, "GPIO93"},
+			[1] = {1, "I2S4_DATA_IN_LB"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(78, "GPIO94"),
+		.functions = {
+			[0] = {0, "GPIO94"},
+			[1] = {1, "I2S4_DATA_OUT_LB"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(79, "UART0_TXD"),
+		.functions = {
+			[0] = {0, "UART0_TXD"},
+			[1] = {1, "PWM0"},
+			[2] = {2, "GPIO95"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(80, "UART0_RXD"),
+		.functions = {
+			[0] = {0, "UART0_RXD"},
+			[1] = {1, "PWM1"},
+			[2] = {2, "GPIO96"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(81, "UART0_CTS"),
+		.functions = {
+			[0] = {0, "UART0_CTS"},
+			[1] = {1, "FAN_OUT2"},
+			[2] = {2, "GPIO97"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(82, "UART0_RTS"),
+		.functions = {
+			[0] = {0, "UART0_CTS"},
+			[1] = {1, "FAN_TACH2"},
+			[2] = {2, "GPIO98"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(83, "UART1_TXD"),
+		.functions = {
+			[0] = {0, "UART0_CTS"},
+			[1] = {1, "FAN_OUT0"},
+			[2] = {2, "GPIO99"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(84, "UART1_RXD"),
+		.functions = {
+			[0] = {0, "UART0_CTS"},
+			[1] = {1, "FAN_TACH0"},
+			[2] = {2, "GPIO100"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(85, "UART1_CTS"),
+		.functions = {
+			[0] = {0, "UART1_CTS"},
+			[1] = {1, "FAN_OUT1"},
+			[2] = {2, "GPIO101"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(86, "UART1_RTS"),
+		.functions = {
+			[0] = {0, "UART1_RTS"},
+			[1] = {1, "FAN_TACH1"},
+			[2] = {2, "GPIO102"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(87, "UART2_TXD"),
+		.functions = {
+			[0] = {0, "UART2_TXD"},
+			[1] = {1, "GPIO103"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(88, "UART2_RXD"),
+		.functions = {
+			[0] = {0, "UART2_RXD"},
+			[1] = {1, "GPIO104"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(89, "UART3_TXD"),
+		.functions = {
+			[0] = {0, "UART3_TXD"},
+			[1] = {1, "GPIO105"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(90, "UART3_RXD"),
+		.functions = {
+			[0] = {0, "UART3_RXD"},
+			[1] = {1, "GPIO106"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(91, "UART3_CTS"),
+		.functions = {
+			[0] = {0, "UART3_CTS"},
+			[1] = {1, "GPIO107"},
+			[2] = {2, "TRIGIN0"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(92, "UART3_RTS"),
+		.functions = {
+			[0] = {0, "UART3_RTS"},
+			[1] = {1, "GPIO108"},
+			[2] = {2, "TRIGIN1"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(93, "UART4_CSU_PM_TXD"),
+		.functions = {
+			[0] = {0, "UART4_CSU_PM_TXD"},
+			[1] = {1, "GPIO109"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(94, "UART4_CSU_PM_RXD"),
+		.functions = {
+			[0] = {0, "UART4_CSU_PM_RXD"},
+			[1] = {1, "GPIO110"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(95, "UART5_CSU_SE_TXD"),
+		.functions = {
+			[0] = {0, "UART5_CSU_SE_TXD"},
+			[1] = {1, "GPIO111"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(96, "UART5_CSU_SE_RXD"),
+		.functions = {
+			[0] = {0, "UART5_CSU_SE_RXD"},
+			[1] = {1, "GPIO112"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(97, "UART6_CSU_SE_RXD"),
+		.functions = {
+			[0] = {0, "UART6_CSU_SE_RXD"},
+			[1] = {1, "GPIO113"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(98, "CLK_REQ0_L"),
+		.functions = {
+			[0] = {0, "CLK_REQ0_L"},
+			[1] = {1, "GPIO114"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(99, "CLK_REQ2_L"),
+		.functions = {
+			[0] = {0, "CLK_REQ2_L"},
+			[1] = {1, "GPIO115"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(100, "CLK_REQ4_L"),
+		.functions = {
+			[0] = {0, "CLK_REQ4_L"},
+			[1] = {1, "GPIO116"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(101, "CSI0_MCLK0"),
+		.functions = {
+			[0] = {0, "CSI0_MCLK0"},
+			[1] = {1, "GPIO117"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(102, "CSI0_MCLK1"),
+		.functions = {
+			[0] = {0, "CSI0_MCLK1"},
+			[1] = {1, "GPIO118"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(103, "CSI1_MCLK0"),
+		.functions = {
+			[0] = {0, "CSI1_MCLK0"},
+			[1] = {1, "GPIO119"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(104, "CSI1_MCLK1"),
+		.functions = {
+			[0] = {0, "CSI1_MCLK1"},
+			[1] = {1, "GPIO120"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(105, "GPIO121"),
+		.functions = {
+			[0] = {0, "GPIO121"},
+			[1] = {1, "GMAC0_REFCLK_25M"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(106, "GPIO122"),
+		.functions = {
+			[0] = {0, "GPIO122"},
+			[1] = {1, "GMAC0_TX_CTL"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(107, "GPIO123"),
+		.functions = {
+			[0] = {0, "GPIO123"},
+			[1] = {1, "GMAC0_TXD0"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(108, "GPIO124"),
+		.functions = {
+			[0] = {0, "GPIO124"},
+			[1] = {1, "GMAC0_TXD1"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(109, "GPIO125"),
+		.functions = {
+			[0] = {0, "GPIO125"},
+			[1] = {1, "GMAC0_TXD2"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(110, "GPIO126"),
+		.functions = {
+			[0] = {0, "GPIO126"},
+			[1] = {1, "GMAC0_TXD3"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(111, "GPIO127"),
+		.functions = {
+			[0] = {0, "GPIO127"},
+			[1] = {1, "GMAC0_TX_CLK"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(112, "GPIO128"),
+		.functions = {
+			[0] = {0, "GPIO128"},
+			[1] = {1, "GMAC0_RX_CTL"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(113, "GPIO129"),
+		.functions = {
+			[0] = {0, "GPIO129"},
+			[1] = {1, "GMAC0_RXD0"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(114, "GPIO130"),
+		.functions = {
+			[0] = {0, "GPIO130"},
+			[1] = {1, "GMAC0_RXD1"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(115, "GPIO131"),
+		.functions = {
+			[0] = {0, "GPIO131"},
+			[1] = {1, "GMAC0_RXD2"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(116, "GPIO132"),
+		.functions = {
+			[0] = {0, "GPIO132"},
+			[1] = {1, "GMAC0_RXD3"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(117, "GPIO133"),
+		.functions = {
+			[0] = {0, "GPIO133"},
+			[1] = {1, "GMAC0_RX_CLK"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(118, "GPIO134"),
+		.functions = {
+			[0] = {0, "GPIO134"},
+			[1] = {1, "GMAC0_MDC"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(119, "GPIO135"),
+		.functions = {
+			[0] = {0, "GPIO135"},
+			[1] = {1, "GMAC0_MDIO"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(120, "GPIO136"),
+		.functions = {
+			[0] = {0, "GPIO136"},
+			[1] = {1, "GMAC1_REFCLK_25M"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(121, "GPIO137"),
+		.functions = {
+			[0] = {0, "GPIO137"},
+			[1] = {1, "GMAC1_TX_CTL"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(122, "GPIO138"),
+		.functions = {
+			[0] = {0, "GPIO138"},
+			[1] = {1, "GMAC1_TXD0"},
+			[2] = {2, "SPI2_MISO"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(123, "GPIO139"),
+		.functions = {
+			[0] = {0, "GPIO139"},
+			[1] = {1, "GMAC1_TXD1"},
+			[2] = {2, "SPI2_CS0"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(124, "GPIO140"),
+		.functions = {
+			[0] = {0, "GPIO140"},
+			[1] = {1, "GMAC1_TXD2"},
+			[2] = {2, "SPI2_CS1"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(125, "GPIO141"),
+		.functions = {
+			[0] = {0, "GPIO141"},
+			[1] = {1, "GMAC1_TXD3"},
+			[2] = {2, "SPI2_MOSI"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(126, "GPIO142"),
+		.functions = {
+			[0] = {0, "GPIO142"},
+			[1] = {1, "GMAC1_TX_CLK"},
+			[2] = {2, "SPI2_CLK"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(127, "GPIO143"),
+		.functions = {
+			[0] = {0, "GPIO143"},
+			[1] = {1, "GMAC1_RX_CTL"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(128, "GPIO144"),
+		.functions = {
+			[0] = {0, "GPIO144"},
+			[1] = {1, "GMAC1_RXD0"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(129, "GPIO145"),
+		.functions = {
+			[0] = {0, "GPIO145"},
+			[1] = {1, "GMAC1_RXD1"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(130, "GPIO146"),
+		.functions = {
+			[0] = {0, "GPIO146"},
+			[1] = {1, "GMAC1_RXD2"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(131, "GPIO147"),
+		.functions = {
+			[0] = {0, "GPIO147"},
+			[1] = {1, "GMAC1_RXD3"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(132, "GPIO148"),
+		.functions = {
+			[0] = {0, "GPIO148"},
+			[1] = {1, "GMAC1_RX_CLK"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(133, "GPIO149"),
+		.functions = {
+			[0] = {0, "GPIO149"},
+			[1] = {1, "GMAC1_MDC"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(134, "GPIO150"),
+		.functions = {
+			[0] = {0, "GPIO150"},
+			[1] = {1, "GMAC1_MDIO"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(135, "GPIO151"),
+		.functions = {
+			[0] = {0, "GPIO151"},
+			[1] = {1, "PM_GPIO0"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(136, "GPIO152"),
+		.functions = {
+			[0] = {0, "GPIO152"},
+			[1] = {1, "PM_GPIO1"},
+		},
+	},
+	{
+		.pin = PINCTRL_PIN(137, "GPIO153"),
+		.functions = {
+			[0] = {0, "GPIO153"},
+			[1] = {1, "PM_GPIO2"},
+		},
+	},
+};
+
+static const struct sky1_pinctrl_soc_info sky1_pinctrl_s5_info = {
+	.pins = sky1_pinctrl_s5_pads,
+	.npins = ARRAY_SIZE(sky1_pinctrl_s5_pads),
+};
+
+static const struct sky1_pinctrl_soc_info sky1_pinctrl_info = {
+	.pins = sky1_pinctrl_pads,
+	.npins = ARRAY_SIZE(sky1_pinctrl_pads),
+};
+
+static const struct of_device_id sky1_pinctrl_of_match[] = {
+	{ .compatible = "cix,sky1-iomuxc-s5", .data = &sky1_pinctrl_s5_info, },
+	{ .compatible = "cix,sky1-iomuxc", .data = &sky1_pinctrl_info, },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, sky1_pinctrl_of_match);
+
+static int __maybe_unused sky1_pinctrl_suspend(struct device *dev)
+{
+	struct sky1_pinctrl *spctl = dev_get_drvdata(dev);
+
+	return pinctrl_force_sleep(spctl->pctl);
+}
+
+static int __maybe_unused sky1_pinctrl_resume(struct device *dev)
+{
+	struct sky1_pinctrl *spctl = dev_get_drvdata(dev);
+
+	return pinctrl_force_default(spctl->pctl);
+}
+
+const struct dev_pm_ops sky1_pinctrl_pm_ops = {
+	SET_LATE_SYSTEM_SLEEP_PM_OPS(sky1_pinctrl_suspend,
+					sky1_pinctrl_resume)
+};
+EXPORT_SYMBOL_GPL(sky1_pinctrl_pm_ops);
+
+static int sky1_pinctrl_probe(struct platform_device *pdev)
+{
+	const struct sky1_pinctrl_soc_info *pinctrl_info;
+
+	pinctrl_info = device_get_match_data(&pdev->dev);
+	if (!pinctrl_info)
+		return -ENODEV;
+
+	return sky1_base_pinctrl_probe(pdev, pinctrl_info);
+}
+
+static struct platform_driver sky1_pinctrl_driver = {
+	.driver = {
+		.name = "sky1-pinctrl",
+		.of_match_table = sky1_pinctrl_of_match,
+		.pm = &sky1_pinctrl_pm_ops,
+	},
+	.probe = sky1_pinctrl_probe,
+};
+
+static int __init sky1_pinctrl_init(void)
+{
+	return platform_driver_register(&sky1_pinctrl_driver);
+}
+arch_initcall(sky1_pinctrl_init);
+
+MODULE_AUTHOR("Jerry Zhu <Jerry.Zhu@cixtech.com>");
+MODULE_DESCRIPTION("Cix Sky1 pinctrl driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/pinctrl/cix/pinctrl-sky1.h b/drivers/pinctrl/cix/pinctrl-sky1.h
new file mode 100644
index 000000000000..49890a4afbb7
--- /dev/null
+++ b/drivers/pinctrl/cix/pinctrl-sky1.h
@@ -0,0 +1,46 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Author: Jerry Zhu <Jerry.Zhu@cixtech.com>
+ */
+
+#ifndef __DRIVERS_PINCTRL_SKY1_H
+#define __DRIVERS_PINCTRL_SKY1_H
+
+struct sky1_function_desc {
+	unsigned char muxval;
+	const char *name;
+};
+
+struct sky1_pinctrl_group {
+	const char *name;
+	unsigned long config;
+	unsigned int pin;
+};
+
+struct sky1_pin_desc {
+	const struct pinctrl_pin_desc pin;
+	const struct sky1_function_desc functions[4];
+};
+
+struct sky1_pinctrl_soc_info {
+	const struct sky1_pin_desc *pins;
+	unsigned int npins;
+};
+
+/**
+ * @dev: a pointer back to containing device
+ * @base: the offset to the controller in virtual memory
+ */
+struct sky1_pinctrl {
+	struct device *dev;
+	struct pinctrl_dev *pctl;
+	void __iomem *base;
+	const struct sky1_pinctrl_soc_info *info;
+	struct sky1_pinctrl_group *groups;
+	const char **grp_names;
+};
+
+int sky1_base_pinctrl_probe(struct platform_device *pdev,
+			const struct sky1_pinctrl_soc_info *info);
+
+#endif /* __DRIVERS_PINCTRL_SKY1_H */
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [v2 2/3] dt-bindings: pinctrl: Add cix,sky1-pinctrl
  2025-09-12  6:06 [v2 0/3] Add pinctrl support for sky1 Gary Yang
  2025-09-12  6:06 ` [v2 1/3] pinctrl: cix: Add pin-controller " Gary Yang
@ 2025-09-12  6:06 ` Gary Yang
  2025-09-12  7:39   ` Linus Walleij
                     ` (2 more replies)
  2025-09-12  6:06 ` [v2 3/3] arm64: dts: cix: Add pinctrl nodes for sky1 Gary Yang
  2025-09-12  7:45 ` [v2 0/3] Add pinctrl support " Linus Walleij
  3 siblings, 3 replies; 17+ messages in thread
From: Gary Yang @ 2025-09-12  6:06 UTC (permalink / raw)
  To: linus.walleij, robh, krzk+dt, conor+dt
  Cc: linux-gpio, devicetree, linux-kernel, linux-arm-kernel,
	cix-kernel-upstream, Gary Yang

The pin-controller is used to control the Soc pins.
There are two pin-controllers on Cix Sky1 platform.
One is used under S0 state, the other is used under
S5 state.

Signed-off-by: Gary Yang <gary.yang@cixtech.com>
---
 .../bindings/pinctrl/cix,sky1-pinctrl.yaml    | 85 +++++++++++++++++++
 1 file changed, 85 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/pinctrl/cix,sky1-pinctrl.yaml

diff --git a/Documentation/devicetree/bindings/pinctrl/cix,sky1-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/cix,sky1-pinctrl.yaml
new file mode 100644
index 000000000000..c4a127fd8330
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/cix,sky1-pinctrl.yaml
@@ -0,0 +1,85 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pinctrl/cix,sky1-pinctrl.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Cix Sky1 Pin Controller
+
+maintainers:
+  - Gary Yang <gary.yang@cixtech.com>
+
+description:
+  The pin-controller is used to control Soc pins. There are two pin-controllers
+  on Cix Sky1 platform. one is used under S0 state, the other one is used under
+  S5 state.
+
+properties:
+  compatible:
+    enum:
+      - cix,sky1-iomuxc
+      - cix,sky1-iomuxc-s5
+
+  reg:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+
+# Client device subnode's properties
+patternProperties:
+  'pins$':
+    type: object
+    additionalProperties: false
+    patternProperties:
+      '(^pins|pins?$)':
+        type: object
+        additionalProperties: false
+        description:
+          A pinctrl node should contain at least one subnodes representing the
+          pinctrl groups available on the machine. Each subnode will list the
+          pins it needs, and how they should be configured, with regard to muxer
+          configuration, pullups, and drive strength.
+        $ref: /schemas/pinctrl/pincfg-node.yaml
+
+        properties:
+          pinmux:
+            description:
+              Integer array, represents gpio pin number and mux setting.
+              Supported pin number and mux varies for different SoCs, and are
+              defined as macros in arch/arm64/boot/dts/cix/sky1-pinfunc.h directly.
+
+          bias-disable: true
+
+          bias-pull-up: true
+
+          bias-pull-down: true
+
+          drive-strength:
+            description:
+              Can support 15 levels, from DS_LEVEL1 to DS_LEVEL15.
+              See arch/arm64/boot/dts/cix/sky1-pinfunc.h for valid arguments.
+
+        required:
+          - pinmux
+
+additionalProperties: false
+
+examples:
+  # Pinmux controller node
+  - |
+    #define CIX_PAD_GPIO012_FUNC_GPIO012 (11 << 8 | 0x0)
+    #define DS_LEVEL4 (4)
+    iomuxc: pinctrl@4170000 {
+        compatible = "cix,sky1-iomuxc";
+        reg = <0x4170000 0x1000>;
+
+        wifi_vbat_gpio: wifi-vbat-gpio-pins {
+            pins-wifi-vbat-gpio {
+                pinmux = <CIX_PAD_GPIO012_FUNC_GPIO012>;
+                bias-pull-up;
+                drive-strength = <DS_LEVEL4>;
+           };
+        };
+    };
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [v2 3/3] arm64: dts: cix: Add pinctrl nodes for sky1
  2025-09-12  6:06 [v2 0/3] Add pinctrl support for sky1 Gary Yang
  2025-09-12  6:06 ` [v2 1/3] pinctrl: cix: Add pin-controller " Gary Yang
  2025-09-12  6:06 ` [v2 2/3] dt-bindings: pinctrl: Add cix,sky1-pinctrl Gary Yang
@ 2025-09-12  6:06 ` Gary Yang
  2025-09-12  7:45 ` [v2 0/3] Add pinctrl support " Linus Walleij
  3 siblings, 0 replies; 17+ messages in thread
From: Gary Yang @ 2025-09-12  6:06 UTC (permalink / raw)
  To: linus.walleij, robh, krzk+dt, conor+dt
  Cc: linux-gpio, devicetree, linux-kernel, linux-arm-kernel,
	cix-kernel-upstream, Gary Yang

Add the pin-controller nodes for Sky1 platform.

Signed-off-by: Gary Yang <gary.yang@cixtech.com>
---
 arch/arm64/boot/dts/cix/sky1-orion-o6.dts |  32 ++
 arch/arm64/boot/dts/cix/sky1-pinfunc.h    | 417 ++++++++++++++++++++++
 arch/arm64/boot/dts/cix/sky1.dtsi         |  10 +
 3 files changed, 459 insertions(+)
 create mode 100644 arch/arm64/boot/dts/cix/sky1-pinfunc.h

diff --git a/arch/arm64/boot/dts/cix/sky1-orion-o6.dts b/arch/arm64/boot/dts/cix/sky1-orion-o6.dts
index d74964d53c3b..52e5e35d3db2 100644
--- a/arch/arm64/boot/dts/cix/sky1-orion-o6.dts
+++ b/arch/arm64/boot/dts/cix/sky1-orion-o6.dts
@@ -7,6 +7,8 @@
 /dts-v1/;
 
 #include "sky1.dtsi"
+#include "sky1-pinfunc.h"
+
 / {
 	model = "Radxa Orion O6";
 	compatible = "radxa,orion-o6", "cix,sky1";
@@ -34,6 +36,36 @@ linux,cma {
 
 };
 
+&iomuxc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_hog>;
+
+	pinctrl_hog: hog-pins {
+		pins-hog {
+			pinmux = <CIX_PAD_GPIO144_FUNC_GPIO144>,
+				<CIX_PAD_GPIO145_FUNC_GPIO145>,
+				<CIX_PAD_GPIO146_FUNC_GPIO146>,
+				<CIX_PAD_GPIO147_FUNC_GPIO147>;
+			bias-pull-down;
+			drive-strength = <DS_LEVEL4>;
+		};
+	};
+};
+
+&iomuxc_s5 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_hog_s5>;
+
+	pinctrl_hog_s5: hog-s5-pins {
+		pins-hog-s5 {
+			pinmux = <CIX_PAD_GPIO014_FUNC_GPIO014>;
+			bias-pull-up;
+			drive-strength = <DS_LEVEL4>;
+
+		};
+	};
+};
+
 &uart2 {
 	status = "okay";
 };
diff --git a/arch/arm64/boot/dts/cix/sky1-pinfunc.h b/arch/arm64/boot/dts/cix/sky1-pinfunc.h
new file mode 100644
index 000000000000..bb2815903cb8
--- /dev/null
+++ b/arch/arm64/boot/dts/cix/sky1-pinfunc.h
@@ -0,0 +1,417 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+/*
+ * Copyright 2024-2025 Cix Technology Group Co., Ltd.
+ */
+
+#ifndef __CIX_SKY1_H
+#define __CIX_SKY1_H
+
+/* s5 pads */
+#define CIX_PAD_GPIO001_FUNC_GPIO001				   (0 << 8 | 0x0)
+#define CIX_PAD_GPIO002_FUNC_GPIO002				   (1 << 8 | 0x0)
+#define CIX_PAD_GPIO003_FUNC_GPIO003				   (2 << 8 | 0x0)
+#define CIX_PAD_GPIO004_FUNC_GPIO004				   (3 << 8 | 0x0)
+#define CIX_PAD_GPIO005_FUNC_GPIO005				   (4 << 8 | 0x0)
+#define CIX_PAD_GPIO006_FUNC_GPIO006				   (5 << 8 | 0x0)
+#define CIX_PAD_GPIO007_FUNC_GPIO007				   (6 << 8 | 0x0)
+#define CIX_PAD_GPIO008_FUNC_GPIO008				   (7 << 8 | 0x0)
+#define CIX_PAD_GPIO009_FUNC_GPIO009				   (8 << 8 | 0x0)
+#define CIX_PAD_GPIO010_FUNC_GPIO010				   (9 << 8 | 0x0)
+#define CIX_PAD_GPIO011_FUNC_GPIO011				   (10 << 8 | 0x0)
+#define CIX_PAD_GPIO012_FUNC_GPIO012				   (11 << 8 | 0x0)
+#define CIX_PAD_GPIO013_FUNC_GPIO013				   (12 << 8 | 0x0)
+#define CIX_PAD_GPIO014_FUNC_GPIO014				   (13 << 8 | 0x0)
+#define CIX_PAD_SFI_I2C0_SCL_FUNC_SFI_I2C0_SCL			   (28 << 8 | 0x0)
+#define CIX_PAD_SFI_I2C0_SCL_FUNC_SFI_I3C0_SCL			   (28 << 8 | 0x1)
+#define CIX_PAD_SFI_I2C0_SDA_FUNC_SFI_I2C0_SDA			   (29 << 8 | 0x0)
+#define CIX_PAD_SFI_I2C0_SDA_FUNC_SFI_I3C0_SDA			   (29 << 8 | 0x1)
+#define CIX_PAD_SFI_I2C1_SCL_FUNC_SFI_I2C1_SCL			   (30 << 8 | 0x0)
+#define CIX_PAD_SFI_I2C1_SCL_FUNC_SFI_I3C1_SCL			   (30 << 8 | 0x1)
+#define CIX_PAD_SFI_I2C1_SCL_FUNC_SFI_SPI_CS0			   (30 << 8 | 0x2)
+#define CIX_PAD_SFI_I2C1_SDA_FUNC_SFI_I2C1_SDA			   (31 << 8 | 0x0)
+#define CIX_PAD_SFI_I2C1_SDA_FUNC_SFI_I3C1_SDA			   (31 << 8 | 0x1)
+#define CIX_PAD_SFI_I2C1_SDA_FUNC_SFI_SPI_CS1			   (31 << 8 | 0x2)
+#define CIX_PAD_SFI_GPIO0_FUNC_GPIO015				   (32 << 8 | 0x0)
+#define CIX_PAD_SFI_GPIO0_FUNC_SFI_SPI_SCK			   (32 << 8 | 0x1)
+#define CIX_PAD_SFI_GPIO0_FUNC_SFI_GPIO0			   (32 << 8 | 0x2)
+#define CIX_PAD_SFI_GPIO1_FUNC_GPIO016				   (33 << 8 | 0x0)
+#define CIX_PAD_SFI_GPIO1_FUNC_SFI_SPI_MOSI			   (33 << 8 | 0x1)
+#define CIX_PAD_SFI_GPIO1_FUNC_SFI_GPIO1			   (33 << 8 | 0x2)
+#define CIX_PAD_SFI_GPIO2_FUNC_GPIO017				   (34 << 8 | 0x0)
+#define CIX_PAD_SFI_GPIO2_FUNC_SFI_SPI_MISO			   (34 << 8 | 0x1)
+#define CIX_PAD_SFI_GPIO2_FUNC_SFI_GPIO2			   (34 << 8 | 0x2)
+#define CIX_PAD_GPIO018_FUNC_SFI_GPIO3				   (35 << 8 | 0x0)
+#define CIX_PAD_GPIO018_FUNC_GPIO018				   (35 << 8 | 0x1)
+#define CIX_PAD_GPIO019_FUNC_SFI_GPIO4				   (36 << 8 | 0x0)
+#define CIX_PAD_GPIO019_FUNC_GPIO019				   (36 << 8 | 0x1)
+#define CIX_PAD_GPIO020_FUNC_SFI_GPIO5				   (37 << 8 | 0x0)
+#define CIX_PAD_GPIO020_FUNC_GPIO020				   (37 << 8 | 0x1)
+#define CIX_PAD_GPIO021_FUNC_SFI_GPIO6				   (38 << 8 | 0x0)
+#define CIX_PAD_GPIO021_FUNC_GPIO021				   (38 << 8 | 0x1)
+#define CIX_PAD_GPIO022_FUNC_SFI_GPIO7				   (39 << 8 | 0x0)
+#define CIX_PAD_GPIO022_FUNC_GPIO022				   (39 << 8 | 0x1)
+#define CIX_PAD_GPIO023_FUNC_SFI_GPIO8				   (40 << 8 | 0x0)
+#define CIX_PAD_GPIO023_FUNC_GPIO023				   (40 << 8 | 0x1)
+#define CIX_PAD_GPIO023_FUNC_SFI_I3C0_PUR_EN_L			   (40 << 8 | 0x2)
+#define CIX_PAD_GPIO024_FUNC_SFI_GPIO9				   (41 << 8 | 0x0)
+#define CIX_PAD_GPIO024_FUNC_GPIO024				   (41 << 8 | 0x1)
+#define CIX_PAD_GPIO024_FUNC_SFI_I3C1_PUR_EN_L			   (41 << 8 | 0x2)
+#define CIX_PAD_SPI1_MISO_FUNC_SPI1_MISO			   (42 << 8 | 0x0)
+#define CIX_PAD_SPI1_MISO_FUNC_GPIO025				   (42 << 8 | 0x1)
+#define CIX_PAD_SPI1_CS0_FUNC_SPI1_CS0				   (43 << 8 | 0x0)
+#define CIX_PAD_SPI1_CS0_FUNC_GPIO026				   (43 << 8 | 0x1)
+#define CIX_PAD_SPI1_CS1_FUNC_SPI1_CS1				   (44 << 8 | 0x0)
+#define CIX_PAD_SPI1_CS1_FUNC_GPIO027				   (44 << 8 | 0x1)
+#define CIX_PAD_SPI1_MOSI_FUNC_SPI1_MOSI			   (45 << 8 | 0x0)
+#define CIX_PAD_SPI1_MOSI_FUNC_GPIO028				   (45 << 8 | 0x1)
+#define CIX_PAD_SPI1_CLK_FUNC_SPI1_CLK				   (46 << 8 | 0x0)
+#define CIX_PAD_SPI1_CLK_FUNC_GPIO029				   (46 << 8 | 0x1)
+#define CIX_PAD_GPIO030_FUNC_GPIO030				   (47 << 8 | 0x0)
+#define CIX_PAD_GPIO030_FUNC_USB_OC0_L				   (47 << 8 | 0x1)
+#define CIX_PAD_GPIO031_FUNC_GPIO031				   (48 << 8 | 0x0)
+#define CIX_PAD_GPIO031_FUNC_USB_OC1_L				   (48 << 8 | 0x1)
+#define CIX_PAD_GPIO032_FUNC_GPIO032				   (49 << 8 | 0x0)
+#define CIX_PAD_GPIO032_FUNC_USB_OC2_L				   (49 << 8 | 0x1)
+#define CIX_PAD_GPIO033_FUNC_GPIO033				   (50 << 8 | 0x0)
+#define CIX_PAD_GPIO033_FUNC_USB_OC3_L				   (50 << 8 | 0x1)
+#define CIX_PAD_GPIO034_FUNC_GPIO034				   (51 << 8 | 0x0)
+#define CIX_PAD_GPIO034_FUNC_USB_OC4_L				   (51 << 8 | 0x1)
+#define CIX_PAD_GPIO035_FUNC_GPIO035				   (52 << 8 | 0x0)
+#define CIX_PAD_GPIO035_FUNC_USB_OC5_L				   (52 << 8 | 0x1)
+#define CIX_PAD_GPIO036_FUNC_GPIO036				   (53 << 8 | 0x0)
+#define CIX_PAD_GPIO036_FUNC_USB_OC6_L				   (53 << 8 | 0x1)
+#define CIX_PAD_GPIO037_FUNC_GPIO037				   (54 << 8 | 0x0)
+#define CIX_PAD_GPIO037_FUNC_USB_OC7_L				   (54 << 8 | 0x1)
+#define CIX_PAD_GPIO038_FUNC_GPIO038				   (55 << 8 | 0x0)
+#define CIX_PAD_GPIO038_FUNC_USB_OC8_L				   (55 << 8 | 0x1)
+#define CIX_PAD_GPIO039_FUNC_GPIO039				   (56 << 8 | 0x0)
+#define CIX_PAD_GPIO039_FUNC_USB_OC9_L				   (56 << 8 | 0x1)
+#define CIX_PAD_GPIO040_FUNC_GPIO040				   (57 << 8 | 0x0)
+#define CIX_PAD_GPIO040_FUNC_USB_DRIVE_VBUS0			   (57 << 8 | 0x1)
+#define CIX_PAD_GPIO041_FUNC_GPIO041				   (58 << 8 | 0x0)
+#define CIX_PAD_GPIO041_FUNC_USB_DRIVE_VBUS4			   (58 << 8 | 0x1)
+#define CIX_PAD_GPIO042_FUNC_GPIO042				   (59 << 8 | 0x0)
+#define CIX_PAD_GPIO042_FUNC_USB_DRIVE_VBUS5			   (59 << 8 | 0x1)
+#define CIX_PAD_SE_QSPI_CLK_FUNC_SE_QSPI_CLK			   (60 << 8 | 0x0)
+#define CIX_PAD_SE_QSPI_CLK_FUNC_QSPI_CLK			   (60 << 8 | 0x1)
+#define CIX_PAD_SE_QSPI_CS_L_FUNC_SE_QSPI_CS_L			   (61 << 8 | 0x0)
+#define CIX_PAD_SE_QSPI_CS_L_FUNC_QSPI_CS_L			   (61 << 8 | 0x1)
+#define CIX_PAD_SE_QSPI_DATA0_FUNC_SE_QSPI_DATA0		   (62 << 8 | 0x0)
+#define CIX_PAD_SE_QSPI_DATA0_FUNC_QSPI_DATA0			   (62 << 8 | 0x1)
+#define CIX_PAD_SE_QSPI_DATA1_FUNC_SE_QSPI_DATA1		   (63 << 8 | 0x0)
+#define CIX_PAD_SE_QSPI_DATA1_FUNC_QSPI_DATA1			   (63 << 8 | 0x1)
+#define CIX_PAD_SE_QSPI_DATA2_FUNC_SE_QSPI_DATA2		   (64 << 8 | 0x0)
+#define CIX_PAD_SE_QSPI_DATA2_FUNC_QSPI_DATA2			   (64 << 8 | 0x1)
+#define CIX_PAD_SE_QSPI_DATA3_FUNC_SE_QSPI_DATA3		   (65 << 8 | 0x0)
+#define CIX_PAD_SE_QSPI_DATA3_FUNC_QSPI_DATA3			   (65 << 8 | 0x1)
+/* s0 pads */
+#define CIX_PAD_GPIO043_FUNC_GPIO043				   (0 << 8 | 0x0)
+#define CIX_PAD_GPIO044_FUNC_GPIO044				   (1 << 8 | 0x0)
+#define CIX_PAD_GPIO045_FUNC_GPIO045				   (2 << 8 | 0x0)
+#define CIX_PAD_GPIO046_FUNC_GPIO046				   (3 << 8 | 0x0)
+#define CIX_PAD_DP2_DIGON_FUNC_DP2_DIGON			   (18 << 8 | 0x0)
+#define CIX_PAD_DP2_BLON_FUNC_DP2_BLON				   (19 << 8 | 0x0)
+#define CIX_PAD_DP2_VARY_BL_FUNC_DP2_VARY_BL			   (20 << 8 | 0x0)
+#define CIX_PAD_I2C7_SCL_FUNC_I2C7_SCL				   (21 << 8 | 0x0)
+#define CIX_PAD_I2C7_SDA_FUNC_I2C7_SDA				   (22 << 8 | 0x0)
+#define CIX_PAD_I2C5_SCL_FUNC_I2C5_SCL				   (26 << 8 | 0x0)
+#define CIX_PAD_I2C5_SCL_FUNC_GPIO047				   (26 << 8 | 0x1)
+#define CIX_PAD_I2C5_SDA_FUNC_I2C5_SDA				   (27 << 8 | 0x0)
+#define CIX_PAD_I2C5_SDA_FUNC_GPIO048				   (27 << 8 | 0x1)
+#define CIX_PAD_I2C6_SCL_FUNC_I2C6_SCL				   (28 << 8 | 0x0)
+#define CIX_PAD_I2C6_SCL_FUNC_GPIO049				   (28 << 8 | 0x1)
+#define CIX_PAD_I2C6_SDA_FUNC_I2C6_SDA				   (29 << 8 | 0x0)
+#define CIX_PAD_I2C6_SDA_FUNC_GPIO050				   (29 << 8 | 0x1)
+#define CIX_PAD_I2C0_CLK_FUNC_I2C0_CLK				   (30 << 8 | 0x0)
+#define CIX_PAD_I2C0_CLK_FUNC_GPIO051				   (30 << 8 | 0x1)
+#define CIX_PAD_I2C0_SDA_FUNC_I2C0_SDA				   (31 << 8 | 0x0)
+#define CIX_PAD_I2C0_SDA_FUNC_GPIO052				   (31 << 8 | 0x1)
+#define CIX_PAD_I2C1_CLK_FUNC_I2C1_CLK				   (32 << 8 | 0x0)
+#define CIX_PAD_I2C1_CLK_FUNC_GPIO053				   (32 << 8 | 0x1)
+#define CIX_PAD_I2C1_SDA_FUNC_I2C1_SDA				   (33 << 8 | 0x0)
+#define CIX_PAD_I2C1_SDA_FUNC_GPIO054				   (33 << 8 | 0x1)
+#define CIX_PAD_I2C2_SCL_FUNC_I2C2_SCL				   (34 << 8 | 0x0)
+#define CIX_PAD_I2C2_SCL_FUNC_I3C0_SCL				   (34 << 8 | 0x1)
+#define CIX_PAD_I2C2_SCL_FUNC_GPIO055				   (34 << 8 | 0x2)
+#define CIX_PAD_I2C2_SDA_FUNC_I2C2_SDA				   (35 << 8 | 0x0)
+#define CIX_PAD_I2C2_SDA_FUNC_I3C0_SDA				   (35 << 8 | 0x1)
+#define CIX_PAD_I2C2_SDA_FUNC_GPIO056				   (35 << 8 | 0x2)
+#define CIX_PAD_GPIO057_FUNC_GPIO057				   (36 << 8 | 0x0)
+#define CIX_PAD_GPIO057_FUNC_I3C0_PUR_EN_L			   (36 << 8 | 0x1)
+#define CIX_PAD_I2C3_CLK_FUNC_I2C3_CLK				   (37 << 8 | 0x0)
+#define CIX_PAD_I2C3_CLK_FUNC_I3C1_CLK				   (37 << 8 | 0x1)
+#define CIX_PAD_I2C3_CLK_FUNC_GPIO058				   (37 << 8 | 0x2)
+#define CIX_PAD_I2C3_SDA_FUNC_I2C3_SDA				   (38 << 8 | 0x0)
+#define CIX_PAD_I2C3_SDA_FUNC_I3C1_SDA				   (38 << 8 | 0x1)
+#define CIX_PAD_I2C3_SDA_FUNC_GPIO059				   (38 << 8 | 0x2)
+#define CIX_PAD_GPIO060_FUNC_GPIO060				   (39 << 8 | 0x0)
+#define CIX_PAD_GPIO060_FUNC_I3C1_PUR_EN_L			   (39 << 8 | 0x1)
+#define CIX_PAD_I2C4_CLK_FUNC_I2C4_CLK				   (40 << 8 | 0x0)
+#define CIX_PAD_I2C4_CLK_FUNC_GPIO061				   (40 << 8 | 0x1)
+#define CIX_PAD_I2C4_SDA_FUNC_I2C4_SDA				   (41 << 8 | 0x0)
+#define CIX_PAD_I2C4_SDA_FUNC_GPIO062				   (41 << 8 | 0x1)
+#define CIX_PAD_HDA_BITCLK_FUNC_HDA_BITCLK			   (42 << 8 | 0x0)
+#define CIX_PAD_HDA_BITCLK_FUNC_I2S0_SCK			   (42 << 8 | 0x1)
+#define CIX_PAD_HDA_BITCLK_FUNC_I2S9_RSCK_DBG			   (42 << 8 | 0x2)
+#define CIX_PAD_HDA_RST_L_FUNC_HDA_RST_L			   (43 << 8 | 0x0)
+#define CIX_PAD_HDA_RST_L_FUNC_I2S0_DATA_IN			   (43 << 8 | 0x1)
+#define CIX_PAD_HDA_RST_L_FUNC_I2S9_DATA_IN0_DBG		   (43 << 8 | 0x2)
+#define CIX_PAD_HDA_SDIN0_FUNC_HDA_SDIN0			   (44 << 8 | 0x0)
+#define CIX_PAD_HDA_SDIN0_FUNC_I2S0_MCLK			   (44 << 8 | 0x1)
+#define CIX_PAD_HDA_SDIN0_FUNC_I2S9_TSCK_DBG			   (44 << 8 | 0x2)
+#define CIX_PAD_HDA_SDOUT0_FUNC_HDA_SDOUT0			   (45 << 8 | 0x0)
+#define CIX_PAD_HDA_SDOUT0_FUNC_I2S0_DATA_OUT			   (45 << 8 | 0x1)
+#define CIX_PAD_HDA_SDOUT0_FUNC_I2S9_TWS_DBG		           (45 << 8 | 0x2)
+#define CIX_PAD_HDA_SYNC_FUNC_HDA_SYNC				   (46 << 8 | 0x0)
+#define CIX_PAD_HDA_SYNC_FUNC_I2S0_WS				   (46 << 8 | 0x1)
+#define CIX_PAD_HDA_SYNC_FUNC_I2S9_RWS_DBG			   (46 << 8 | 0x2)
+#define CIX_PAD_HDA_SDIN1_FUNC_HDA_SDIN1			   (47 << 8 | 0x0)
+#define CIX_PAD_HDA_SDIN1_FUNC_GPIO063				   (47 << 8 | 0x1)
+#define CIX_PAD_HDA_SDIN1_FUNC_I2S9_DATA_IN1_DBG		   (47 << 8 | 0x2)
+#define CIX_PAD_HDA_SDOUT1_FUNC_HDA_SDOUT1			   (48 << 8 | 0x0)
+#define CIX_PAD_HDA_SDOUT1_FUNC_GPIO064				   (48 << 8 | 0x1)
+#define CIX_PAD_HDA_SDOUT1_FUNC_I2S9_DATA_OUT0_DBG		   (48 << 8 | 0x2)
+#define CIX_PAD_I2S1_MCLK_FUNC_I2S1_MCLK			   (49 << 8 | 0x0)
+#define CIX_PAD_I2S1_MCLK_FUNC_GPIO065				   (49 << 8 | 0x1)
+#define CIX_PAD_I2S1_SCK_FUNC_I2S1_SCK				   (50 << 8 | 0x0)
+#define CIX_PAD_I2S1_SCK_FUNC_GPIO066				   (50 << 8 | 0x1)
+#define CIX_PAD_I2S1_WS_FUNC_I2S1_WS				   (51 << 8 | 0x0)
+#define CIX_PAD_I2S1_WS_FUNC_GPIO067				   (51 << 8 | 0x1)
+#define CIX_PAD_I2S1_DATA_IN_FUNC_I2S1_DATA_IN			   (52 << 8 | 0x0)
+#define CIX_PAD_I2S1_DATA_IN_FUNC_GPIO068			   (52 << 8 | 0x1)
+#define CIX_PAD_I2S1_DATA_OUT_FUNC_I2S1_DATA_OUT		   (53 << 8 | 0x0)
+#define CIX_PAD_I2S1_DATA_OUT_FUNC_GPIO069			   (53 << 8 | 0x1)
+#define CIX_PAD_I2S2_MCLK_FUNC_I2S2_MCLK			   (54 << 8 | 0x0)
+#define CIX_PAD_I2S2_MCLK_FUNC_GPIO070				   (54 << 8 | 0x1)
+#define CIX_PAD_I2S2_RSCK_FUNC_I2S2_RSCK			   (55 << 8 | 0x0)
+#define CIX_PAD_I2S2_RSCK_FUNC_GPIO071				   (55 << 8 | 0x1)
+#define CIX_PAD_I2S2_RSCK_FUNC_I2S5_RSCK_DBG			   (55 << 8 | 0x2)
+#define CIX_PAD_I2S2_RSCK_FUNC_I2S6_RSCK_DBG			   (55 << 8 | 0x3)
+#define CIX_PAD_I2S2_RWS_FUNC_I2S2_RWS				   (56 << 8 | 0x0)
+#define CIX_PAD_I2S2_RWS_FUNC_GPIO072				   (56 << 8 | 0x1)
+#define CIX_PAD_I2S2_RWS_FUNC_I2S5_RWS_DBG			   (56 << 8 | 0x2)
+#define CIX_PAD_I2S2_RWS_FUNC_I2S6_RWS_DBG			   (56 << 8 | 0x3)
+#define CIX_PAD_I2S2_TSCK_FUNC_I2S2_TSCK			   (57 << 8 | 0x0)
+#define CIX_PAD_I2S2_TSCK_FUNC_GPIO073				   (57 << 8 | 0x1)
+#define CIX_PAD_I2S2_TSCK_FUNC_I2S5_TSCK_DBG			   (57 << 8 | 0x2)
+#define CIX_PAD_I2S2_TSCK_FUNC_I2S6_TSCK_DBG			   (57 << 8 | 0x3)
+#define CIX_PAD_I2S2_TWS_FUNC_I2S2_TWS				   (58 << 8 | 0x0)
+#define CIX_PAD_I2S2_TWS_FUNC_GPIO074				   (58 << 8 | 0x1)
+#define CIX_PAD_I2S2_TWS_FUNC_I2S5_TWS_DBG			   (58 << 8 | 0x2)
+#define CIX_PAD_I2S2_TWS_FUNC_I2S6_TWS_DBG			   (58 << 8 | 0x3)
+#define CIX_PAD_I2S2_DATA_IN0_FUNC_I2S2_DATA_IN0		   (59 << 8 | 0x0)
+#define CIX_PAD_I2S2_DATA_IN0_FUNC_GPIO075			   (59 << 8 | 0x1)
+#define CIX_PAD_I2S2_DATA_IN0_FUNC_I2S5_DATA_IN0_DBG		   (59 << 8 | 0x2)
+#define CIX_PAD_I2S2_DATA_IN0_FUNC_I2S6_DATA_IN0_DBG		   (59 << 8 | 0x3)
+#define CIX_PAD_I2S2_DATA_IN1_FUNC_I2S2_DATA_IN1		   (60 << 8 | 0x0)
+#define CIX_PAD_I2S2_DATA_IN1_FUNC_GPIO076			   (60 << 8 | 0x1)
+#define CIX_PAD_I2S2_DATA_IN1_FUNC_I2S5_DATA_IN1_DBG		   (60 << 8 | 0x2)
+#define CIX_PAD_I2S2_DATA_IN1_FUNC_I2S6_DATA_IN1_DBG		   (60 << 8 | 0x3)
+#define CIX_PAD_I2S2_DATA_OUT0_FUNC_I2S2_DATA_OUT0		   (61 << 8 | 0x0)
+#define CIX_PAD_I2S2_DATA_OUT0_FUNC_GPIO077			   (61 << 8 | 0x1)
+#define CIX_PAD_I2S2_DATA_OUT0_FUNC_I2S5_DATA_OUT0_DBG		   (61 << 8 | 0x2)
+#define CIX_PAD_I2S2_DATA_OUT0_FUNC_I2S6_DATA_OUT0_DBG		   (61 << 8 | 0x3)
+#define CIX_PAD_I2S2_DATA_OUT1_FUNC_I2S2_DATA_OUT1		   (62 << 8 | 0x0)
+#define CIX_PAD_I2S2_DATA_OUT1_FUNC_GPIO078			   (62 << 8 | 0x1)
+#define CIX_PAD_I2S2_DATA_OUT1_FUNC_I2S5_DATA_OUT1_DBG		   (62 << 8 | 0x2)
+#define CIX_PAD_I2S2_DATA_OUT1_FUNC_I2S6_DATA_OUT1_DBG		   (62 << 8 | 0x3)
+#define CIX_PAD_I2S2_DATA_OUT2_FUNC_I2S2_DATA_OUT2		   (63 << 8 | 0x0)
+#define CIX_PAD_I2S2_DATA_OUT2_FUNC_GPIO079			   (63 << 8 | 0x1)
+#define CIX_PAD_I2S2_DATA_OUT3_FUNC_I2S2_DATA_OUT3		   (64 << 8 | 0x0)
+#define CIX_PAD_I2S2_DATA_OUT3_FUNC_GPIO080			   (64 << 8 | 0x1)
+#define CIX_PAD_I2S2_DATA_OUT3_FUNC_I2S9_DATA_OUT1_DBG		   (64 << 8 | 0x2)
+#define CIX_PAD_I2S3_MCLK_FUNC_I2S3_MCLK			   (65 << 8 | 0x0)
+#define CIX_PAD_I2S3_MCLK_FUNC_GPIO081				   (65 << 8 | 0x1)
+#define CIX_PAD_I2S3_RSCK_FUNC_I2S3_RSCK			   (66 << 8 | 0x0)
+#define CIX_PAD_I2S3_RSCK_FUNC_GPIO082				   (66 << 8 | 0x1)
+#define CIX_PAD_I2S3_RSCK_FUNC_I2S7_RSCK_DBG			   (66 << 8 | 0x2)
+#define CIX_PAD_I2S3_RSCK_FUNC_I2S8_RSCK_DBG			   (66 << 8 | 0x3)
+#define CIX_PAD_I2S3_RWS_FUNC_I2S3_RWS				   (67 << 8 | 0x0)
+#define CIX_PAD_I2S3_RWS_FUNC_GPIO083				   (67 << 8 | 0x1)
+#define CIX_PAD_I2S3_RWS_FUNC_I2S7_RWS_DBG			   (67 << 8 | 0x2)
+#define CIX_PAD_I2S3_RWS_FUNC_I2S8_RWS_DBG			   (67 << 8 | 0x3)
+#define CIX_PAD_I2S3_TSCK_FUNC_I2S3_TSCK			   (68 << 8 | 0x0)
+#define CIX_PAD_I2S3_TSCK_FUNC_GPIO084				   (68 << 8 | 0x1)
+#define CIX_PAD_I2S3_TSCK_FUNC_I2S7_TSCK_DBG			   (68 << 8 | 0x2)
+#define CIX_PAD_I2S3_TSCK_FUNC_I2S8_TSCK_DBG			   (68 << 8 | 0x3)
+#define CIX_PAD_I2S3_TWS_FUNC_I2S3_TWS				   (69 << 8 | 0x0)
+#define CIX_PAD_I2S3_TWS_FUNC_GPIO085				   (69 << 8 | 0x1)
+#define CIX_PAD_I2S3_TWS_FUNC_I2S7_TWS_DBG			   (69 << 8 | 0x2)
+#define CIX_PAD_I2S3_TWS_FUNC_I2S8_TWS_DBG			   (69 << 8 | 0x3)
+#define CIX_PAD_I2S3_DATA_IN0_FUNC_I2S3_DATA_IN0		   (70 << 8 | 0x0)
+#define CIX_PAD_I2S3_DATA_IN0_FUNC_GPIO086			   (70 << 8 | 0x1)
+#define CIX_PAD_I2S3_DATA_IN0_FUNC_I2S7_DATA_IN0_DBG		   (70 << 8 | 0x2)
+#define CIX_PAD_I2S3_DATA_IN0_FUNC_I2S8_DATA_IN0_DBG		   (70 << 8 | 0x3)
+#define CIX_PAD_I2S3_DATA_IN1_FUNC_I2S3_DATA_IN1		   (71 << 8 | 0x0)
+#define CIX_PAD_I2S3_DATA_IN1_FUNC_GPIO087			   (71 << 8 | 0x1)
+#define CIX_PAD_I2S3_DATA_IN1_FUNC_I2S7_DATA_IN1_DBG		   (71 << 8 | 0x2)
+#define CIX_PAD_I2S3_DATA_IN1_FUNC_I2S8_DATA_IN1_DBG		   (71 << 8 | 0x3)
+#define CIX_PAD_I2S3_DATA_OUT0_FUNC_I2S3_DATA_OUT0		   (72 << 8 | 0x0)
+#define CIX_PAD_I2S3_DATA_OUT0_FUNC_GPIO088			   (72 << 8 | 0x1)
+#define CIX_PAD_I2S3_DATA_OUT0_FUNC_I2S7_DATA_OUT0_DBG		   (72 << 8 | 0x2)
+#define CIX_PAD_I2S3_DATA_OUT0_FUNC_I2S8_DATA_OUT0_DBG		   (72 << 8 | 0x3)
+#define CIX_PAD_I2S3_DATA_OUT1_FUNC_I2S3_DATA_OUT1		   (73 << 8 | 0x0)
+#define CIX_PAD_I2S3_DATA_OUT1_FUNC_GPIO089			   (73 << 8 | 0x1)
+#define CIX_PAD_I2S3_DATA_OUT1_FUNC_I2S7_DATA_OUT1_DBG		   (73 << 8 | 0x2)
+#define CIX_PAD_I2S3_DATA_OUT1_FUNC_I2S8_DATA_OUT1_DBG		   (73 << 8 | 0x3)
+#define CIX_PAD_GPIO090_FUNC_GPIO090				   (74 << 8 | 0x0)
+#define CIX_PAD_GPIO090_FUNC_I2S4_MCLK_LB			   (74 << 8 | 0x1)
+#define CIX_PAD_GPIO091_FUNC_GPIO091				   (75 << 8 | 0x0)
+#define CIX_PAD_GPIO091_FUNC_I2S4_SCK_LB			   (75 << 8 | 0x1)
+#define CIX_PAD_GPIO092_FUNC_GPIO092				   (76 << 8 | 0x0)
+#define CIX_PAD_GPIO092_FUNC_I2S4_WS_LB				   (76 << 8 | 0x1)
+#define CIX_PAD_GPIO093_FUNC_GPIO093				   (77 << 8 | 0x0)
+#define CIX_PAD_GPIO093_FUNC_I2S4_DATA_IN_LB			   (77 << 8 | 0x1)
+#define CIX_PAD_GPIO094_FUNC_GPIO094				   (78 << 8 | 0x0)
+#define CIX_PAD_GPIO094_FUNC_I2S4_DATA_OUT_LB			   (78 << 8 | 0x1)
+#define CIX_PAD_UART0_TXD_FUNC_UART0_TXD			   (79 << 8 | 0x0)
+#define CIX_PAD_UART0_TXD_FUNC_PWM0				   (79 << 8 | 0x1)
+#define CIX_PAD_UART0_TXD_FUNC_GPIO095				   (79 << 8 | 0x2)
+#define CIX_PAD_UART0_RXD_FUNC_UART0_RXD			   (80 << 8 | 0x0)
+#define CIX_PAD_UART0_RXD_FUNC_PWM1				   (80 << 8 | 0x1)
+#define CIX_PAD_UART0_RXD_FUNC_GPIO096				   (80 << 8 | 0x2)
+#define CIX_PAD_UART0_CTS_FUNC_UART0_CTS			   (81 << 8 | 0x0)
+#define CIX_PAD_UART0_CTS_FUNC_FAN_OUT2				   (81 << 8 | 0x1)
+#define CIX_PAD_UART0_CTS_FUNC_GPIO097				   (81 << 8 | 0x2)
+#define CIX_PAD_UART0_RTS_FUNC_UART0_RTS			   (82 << 8 | 0x0)
+#define CIX_PAD_UART0_RTS_FUNC_FAN_TACH2			   (82 << 8 | 0x1)
+#define CIX_PAD_UART0_RTS_FUNC_GPIO098				   (82 << 8 | 0x2)
+#define CIX_PAD_UART1_TXD_FUNC_UART1_TXD			   (83 << 8 | 0x0)
+#define CIX_PAD_UART1_TXD_FUNC_FAN_OUT0				   (83 << 8 | 0x1)
+#define CIX_PAD_UART1_TXD_FUNC_GPIO099				   (83 << 8 | 0x2)
+#define CIX_PAD_UART1_RXD_FUNC_UART1_RXD			   (84 << 8 | 0x0)
+#define CIX_PAD_UART1_RXD_FUNC_FAN_TACH0			   (84 << 8 | 0x1)
+#define CIX_PAD_UART1_RXD_FUNC_GPIO100				   (84 << 8 | 0x2)
+#define CIX_PAD_UART1_CTS_FUNC_UART1_CTS			   (85 << 8 | 0x0)
+#define CIX_PAD_UART1_CTS_FUNC_FAN_OUT1				   (85 << 8 | 0x1)
+#define CIX_PAD_UART1_CTS_FUNC_GPIO101				   (85 << 8 | 0x2)
+#define CIX_PAD_UART1_RTS_FUNC_UART1_RTS			   (86 << 8 | 0x0)
+#define CIX_PAD_UART1_RTS_FUNC_FAN_TACH1			   (86 << 8 | 0x1)
+#define CIX_PAD_UART1_RTS_FUNC_GPIO102				   (86 << 8 | 0x2)
+#define CIX_PAD_UART2_TXD_FUNC_UART2_TXD			   (87 << 8 | 0x0)
+#define CIX_PAD_UART2_TXD_FUNC_GPIO103				   (87 << 8 | 0x1)
+#define CIX_PAD_UART2_RXD_FUNC_UART2_RXD			   (88 << 8 | 0x0)
+#define CIX_PAD_UART2_RXD_FUNC_GPIO104				   (88 << 8 | 0x1)
+#define CIX_PAD_UART3_TXD_FUNC_UART3_TXD			   (89 << 8 | 0x0)
+#define CIX_PAD_UART3_TXD_FUNC_GPIO105				   (89 << 8 | 0x1)
+#define CIX_PAD_UART3_RXD_FUNC_UART3_RXD			   (90 << 8 | 0x0)
+#define CIX_PAD_UART3_RXD_FUNC_GPIO106				   (90 << 8 | 0x1)
+#define CIX_PAD_UART3_CTS_FUNC_UART3_CTS			   (91 << 8 | 0x0)
+#define CIX_PAD_UART3_CTS_FUNC_GPIO107				   (91 << 8 | 0x1)
+#define CIX_PAD_UART3_CTS_FUNC_TRIGIN0				   (91 << 8 | 0x2)
+#define CIX_PAD_UART3_RTS_FUNC_UART3_RTS			   (92 << 8 | 0x0)
+#define CIX_PAD_UART3_RTS_FUNC_GPIO108				   (92 << 8 | 0x1)
+#define CIX_PAD_UART3_RTS_FUNC_TRIGIN1				   (92 << 8 | 0x2)
+#define CIX_PAD_UART4_CSU_PM_TXD_FUNC_UART4_CSU_PM_TXD		   (93 << 8 | 0x0)
+#define CIX_PAD_UART4_CSU_PM_TXD_FUNC_GPIO109			   (93 << 8 | 0x1)
+#define CIX_PAD_UART4_CSU_PM_RXD_FUNC_UART4_CSU_PM_RXD		   (94 << 8 | 0x0)
+#define CIX_PAD_UART4_CSU_PM_RXD_FUNC_GPIO110			   (94 << 8 | 0x1)
+#define CIX_PAD_UART5_CSU_SE_TXD_FUNC_UART5_CSU_SE_TXD		   (95 << 8 | 0x0)
+#define CIX_PAD_UART5_CSU_SE_TXD_FUNC_GPIO111			   (95 << 8 | 0x1)
+#define CIX_PAD_UART5_CSU_SE_RXD_FUNC_UART5_CSU_SE_RXD		   (96 << 8 | 0x0)
+#define CIX_PAD_UART5_CSU_SE_RXD_FUNC_GPIO112			   (96 << 8 | 0x1)
+#define CIX_PAD_UART6_CSU_SE_RXD_FUNC_UART6_CSU_SE_RXD		   (97 << 8 | 0x0)
+#define CIX_PAD_UART6_CSU_SE_RXD_FUNC_GPIO113			   (97 << 8 | 0x1)
+#define CIX_PAD_CLK_REQ0_L_FUNC_CLK_REQ0_L			   (98 << 8 | 0x0)
+#define CIX_PAD_CLK_REQ0_L_FUNC_GPIO114				   (98 << 8 | 0x1)
+#define CIX_PAD_CLK_REQ2_L_FUNC_CLK_REQ2_L			   (99 << 8 | 0x0)
+#define CIX_PAD_CLK_REQ2_L_FUNC_GPIO115				   (99 << 8 | 0x1)
+#define CIX_PAD_CLK_REQ4_L_FUNC_CLK_REQ4_L			   (100 << 8 | 0x0)
+#define CIX_PAD_CLK_REQ4_L_FUNC_GPIO116				   (100 << 8 | 0x1)
+#define CIX_PAD_CSI0_MCLK0_FUNC_CSI0_MCLK0			   (101 << 8 | 0x0)
+#define CIX_PAD_CSI0_MCLK0_FUNC_GPIO117				   (101 << 8 | 0x1)
+#define CIX_PAD_CSI0_MCLK1_FUNC_CSI0_MCLK1			   (102 << 8 | 0x0)
+#define CIX_PAD_CSI0_MCLK1_FUNC_GPIO118				   (102 << 8 | 0x1)
+#define CIX_PAD_CSI1_MCLK0_FUNC_CSI1_MCLK0			   (103 << 8 | 0x0)
+#define CIX_PAD_CSI1_MCLK0_FUNC_GPIO119				   (103 << 8 | 0x1)
+#define CIX_PAD_CSI1_MCLK1_FUNC_CSI1_MCLK1			   (104 << 8 | 0x0)
+#define CIX_PAD_CSI1_MCLK1_FUNC_GPIO120				   (104 << 8 | 0x1)
+#define CIX_PAD_GPIO121_FUNC_GPIO121				   (105 << 8 | 0x0)
+#define CIX_PAD_GPIO121_FUNC_GMAC0_REFCLK_25M			   (105 << 8 | 0x1)
+#define CIX_PAD_GPIO122_FUNC_GPIO122				   (106 << 8 | 0x0)
+#define CIX_PAD_GPIO122_FUNC_GMAC0_TX_CTL			   (106 << 8 | 0x1)
+#define CIX_PAD_GPIO123_FUNC_GPIO123				   (107 << 8 | 0x0)
+#define CIX_PAD_GPIO123_FUNC_GMAC0_TXD0				   (107 << 8 | 0x1)
+#define CIX_PAD_GPIO124_FUNC_GPIO124				   (108 << 8 | 0x0)
+#define CIX_PAD_GPIO124_FUNC_GMAC0_TXD1				   (108 << 8 | 0x1)
+#define CIX_PAD_GPIO125_FUNC_GPIO125				   (109 << 8 | 0x0)
+#define CIX_PAD_GPIO125_FUNC_GMAC0_TXD2				   (109 << 8 | 0x1)
+#define CIX_PAD_GPIO126_FUNC_GPIO126				   (110 << 8 | 0x0)
+#define CIX_PAD_GPIO126_FUNC_GMAC0_TXD3				   (110 << 8 | 0x1)
+#define CIX_PAD_GPIO127_FUNC_GPIO127				   (111 << 8 | 0x0)
+#define CIX_PAD_GPIO127_FUNC_GMAC0_TX_CLK			   (111 << 8 | 0x1)
+#define CIX_PAD_GPIO128_FUNC_GPIO128				   (112 << 8 | 0x0)
+#define CIX_PAD_GPIO128_FUNC_GMAC0_RX_CTL			   (112 << 8 | 0x1)
+#define CIX_PAD_GPIO129_FUNC_GPIO129				   (113 << 8 | 0x0)
+#define CIX_PAD_GPIO129_FUNC_GMAC0_RXD0				   (113 << 8 | 0x1)
+#define CIX_PAD_GPIO130_FUNC_GPIO130				   (114 << 8 | 0x0)
+#define CIX_PAD_GPIO130_FUNC_GMAC0_RXD1				   (114 << 8 | 0x1)
+#define CIX_PAD_GPIO131_FUNC_GPIO131				   (115 << 8 | 0x0)
+#define CIX_PAD_GPIO131_FUNC_GMAC0_RXD2				   (115 << 8 | 0x1)
+#define CIX_PAD_GPIO132_FUNC_GPIO132				   (116 << 8 | 0x0)
+#define CIX_PAD_GPIO132_FUNC_GMAC0_RXD3				   (116 << 8 | 0x1)
+#define CIX_PAD_GPIO133_FUNC_GPIO133				   (117 << 8 | 0x0)
+#define CIX_PAD_GPIO133_FUNC_GMAC0_RX_CLK			   (117 << 8 | 0x1)
+#define CIX_PAD_GPIO134_FUNC_GPIO134				   (118 << 8 | 0x0)
+#define CIX_PAD_GPIO134_FUNC_GMAC0_MDC				   (118 << 8 | 0x1)
+#define CIX_PAD_GPIO135_FUNC_GPIO135				   (119 << 8 | 0x0)
+#define CIX_PAD_GPIO135_FUNC_GMAC0_MDIO				   (119 << 8 | 0x1)
+#define CIX_PAD_GPIO136_FUNC_GPIO136				   (120 << 8 | 0x0)
+#define CIX_PAD_GPIO136_FUNC_GMAC1_REFCLK_25M			   (120 << 8 | 0x1)
+#define CIX_PAD_GPIO137_FUNC_GPIO137				   (121 << 8 | 0x0)
+#define CIX_PAD_GPIO137_FUNC_GMAC1_TX_CTL			   (121 << 8 | 0x1)
+#define CIX_PAD_GPIO138_FUNC_GPIO138				   (122 << 8 | 0x0)
+#define CIX_PAD_GPIO138_FUNC_GMAC1_TXD0				   (122 << 8 | 0x1)
+#define CIX_PAD_GPIO138_FUNC_SPI2_MISO				   (122 << 8 | 0x2)
+#define CIX_PAD_GPIO139_FUNC_GPIO139				   (123 << 8 | 0x0)
+#define CIX_PAD_GPIO139_FUNC_GMAC1_TXD1				   (123 << 8 | 0x1)
+#define CIX_PAD_GPIO139_FUNC_SPI2_CS0				   (123 << 8 | 0x2)
+#define CIX_PAD_GPIO140_FUNC_GPIO140				   (124 << 8 | 0x0)
+#define CIX_PAD_GPIO140_FUNC_GMAC1_TXD2				   (124 << 8 | 0x1)
+#define CIX_PAD_GPIO140_FUNC_SPI2_CS1				   (124 << 8 | 0x2)
+#define CIX_PAD_GPIO141_FUNC_GPIO141				   (125 << 8 | 0x0)
+#define CIX_PAD_GPIO141_FUNC_GMAC1_TXD3				   (125 << 8 | 0x1)
+#define CIX_PAD_GPIO141_FUNC_SPI2_MOSI				   (125 << 8 | 0x2)
+#define CIX_PAD_GPIO142_FUNC_GPIO142				   (126 << 8 | 0x0)
+#define CIX_PAD_GPIO142_FUNC_GMAC1_TX_CLK			   (126 << 8 | 0x1)
+#define CIX_PAD_GPIO142_FUNC_SPI2_CLK				   (126 << 8 | 0x2)
+#define CIX_PAD_GPIO143_FUNC_GPIO143				   (127 << 8 | 0x0)
+#define CIX_PAD_GPIO143_FUNC_GMAC1_RX_CTL			   (127 << 8 | 0x1)
+#define CIX_PAD_GPIO144_FUNC_GPIO144				   (128 << 8 | 0x0)
+#define CIX_PAD_GPIO144_FUNC_GMAC1_RXD0				   (128 << 8 | 0x1)
+#define CIX_PAD_GPIO145_FUNC_GPIO145				   (129 << 8 | 0x0)
+#define CIX_PAD_GPIO145_FUNC_GMAC1_RXD1				   (129 << 8 | 0x1)
+#define CIX_PAD_GPIO146_FUNC_GPIO146				   (130 << 8 | 0x0)
+#define CIX_PAD_GPIO146_FUNC_GMAC1_RXD2				   (130 << 8 | 0x1)
+#define CIX_PAD_GPIO147_FUNC_GPIO147				   (131 << 8 | 0x0)
+#define CIX_PAD_GPIO147_FUNC_GMAC1_RXD3				   (131 << 8 | 0x1)
+#define CIX_PAD_GPIO148_FUNC_GPIO148				   (132 << 8 | 0x0)
+#define CIX_PAD_GPIO148_FUNC_GMAC1_RX_CLK			   (132 << 8 | 0x1)
+#define CIX_PAD_GPIO149_FUNC_GPIO149				   (133 << 8 | 0x0)
+#define CIX_PAD_GPIO149_FUNC_GMAC1_MDC				   (133 << 8 | 0x1)
+#define CIX_PAD_GPIO150_FUNC_GPIO150				   (134 << 8 | 0x0)
+#define CIX_PAD_GPIO150_FUNC_GMAC1_MDIO				   (134 << 8 | 0x1)
+#define CIX_PAD_GPIO151_FUNC_GPIO151				   (135 << 8 | 0x0)
+#define CIX_PAD_GPIO151_FUNC_PM_GPIO0				   (135 << 8 | 0x1)
+#define CIX_PAD_GPIO152_FUNC_GPIO152				   (136 << 8 | 0x0)
+#define CIX_PAD_GPIO152_FUNC_PM_GPIO1				   (136 << 8 | 0x1)
+#define CIX_PAD_GPIO153_FUNC_GPIO153				   (137 << 8 | 0x0)
+#define CIX_PAD_GPIO153_FUNC_PM_GPIO2				   (137 << 8 | 0x1)
+
+#define DS_LEVEL1	0x1
+#define DS_LEVEL2	0x2
+#define DS_LEVEL3	0x3
+#define DS_LEVEL4	0x4
+#define DS_LEVEL5	0x5
+#define DS_LEVEL6	0x6
+#define DS_LEVEL7	0x7
+#define DS_LEVEL8	0x8
+#define DS_LEVEL9	0x9
+#define DS_LEVEL10	0xa
+#define DS_LEVEL11	0xb
+#define DS_LEVEL12	0xc
+#define DS_LEVEL13	0xd
+#define DS_LEVEL14	0xe
+#define DS_LEVEL15	0xf
+
+#endif
diff --git a/arch/arm64/boot/dts/cix/sky1.dtsi b/arch/arm64/boot/dts/cix/sky1.dtsi
index 7dfe7677e649..4c6f25fe797c 100644
--- a/arch/arm64/boot/dts/cix/sky1.dtsi
+++ b/arch/arm64/boot/dts/cix/sky1.dtsi
@@ -228,6 +228,11 @@ uart3: serial@40e0000 {
 			status = "disabled";
 		};
 
+		iomuxc: pinctrl@4170000 {
+			compatible = "cix,sky1-iomuxc";
+			reg = <0x0 0x04170000 0x0 0x1000>;
+		};
+
 		mbox_ap2se: mailbox@5060000 {
 			compatible = "cix,sky1-mbox";
 			reg = <0x0 0x05060000 0x0 0x10000>;
@@ -316,6 +321,11 @@ ppi_partition1: interrupt-partition-1 {
 				};
 			};
 		};
+
+		iomuxc_s5: pinctrl@16007000 {
+			compatible = "cix,sky1-iomuxc-s5";
+			reg = <0x0 0x16007000 0x0 0x1000>;
+		};
 	};
 
 	timer {
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Re: [v2 2/3] dt-bindings: pinctrl: Add cix,sky1-pinctrl
  2025-09-12  6:06 ` [v2 2/3] dt-bindings: pinctrl: Add cix,sky1-pinctrl Gary Yang
@ 2025-09-12  7:39   ` Linus Walleij
  2025-09-12 14:19   ` Rob Herring
  2025-09-12 14:23   ` Rob Herring (Arm)
  2 siblings, 0 replies; 17+ messages in thread
From: Linus Walleij @ 2025-09-12  7:39 UTC (permalink / raw)
  To: Gary Yang
  Cc: robh, krzk+dt, conor+dt, linux-gpio, devicetree, linux-kernel,
	linux-arm-kernel, cix-kernel-upstream

Hi Gary,

thanks for your patch!

Overall this is starting to look good.

Please make the bindings patch 1/3 because we usually put the bindings
first.

Some comments below!

On Fri, Sep 12, 2025 at 8:06 AM Gary Yang <gary.yang@cixtech.com> wrote:

> The pin-controller is used to control the Soc pins.
> There are two pin-controllers on Cix Sky1 platform.
> One is used under S0 state, the other is used under
> S5 state.
>
> Signed-off-by: Gary Yang <gary.yang@cixtech.com>
(...)
> +# Client device subnode's properties
> +patternProperties:
> +  'pins$':
> +    type: object
> +    additionalProperties: false
> +    patternProperties:
> +      '(^pins|pins?$)':
> +        type: object
> +        additionalProperties: false
> +        description:
> +          A pinctrl node should contain at least one subnodes representing the
> +          pinctrl groups available on the machine. Each subnode will list the
> +          pins it needs, and how they should be configured, with regard to muxer
> +          configuration, pullups, and drive strength.

I'm not sure the binding maintainers want this info here, if the same is inside
pincfg-node.yaml, I would just skip it.

> +        $ref: /schemas/pinctrl/pincfg-node.yaml
> +
> +        properties:
> +          pinmux:
> +            description:
> +              Integer array, represents gpio pin number and mux setting.
> +              Supported pin number and mux varies for different SoCs, and are
> +              defined as macros in arch/arm64/boot/dts/cix/sky1-pinfunc.h directly.

No reference to arch/arm64 in the bindings please. Just
drop this.

The bindings are used by U-Boot and FreeBSD as well so these
developers will be confused by any Linux-specific references.

> +
> +          bias-disable: true
> +
> +          bias-pull-up: true
> +
> +          bias-pull-down: true
> +
> +          drive-strength:
> +            description:
> +              Can support 15 levels, from DS_LEVEL1 to DS_LEVEL15.
> +              See arch/arm64/boot/dts/cix/sky1-pinfunc.h for valid arguments.

Same thing.

> +
> +        required:
> +          - pinmux
> +
> +additionalProperties: false
> +
> +examples:
> +  # Pinmux controller node
> +  - |
> +    #define CIX_PAD_GPIO012_FUNC_GPIO012 (11 << 8 | 0x0)
> +    #define DS_LEVEL4 (4)
> +    iomuxc: pinctrl@4170000 {
> +        compatible = "cix,sky1-iomuxc";
> +        reg = <0x4170000 0x1000>;
> +
> +        wifi_vbat_gpio: wifi-vbat-gpio-pins {
> +            pins-wifi-vbat-gpio {
> +                pinmux = <CIX_PAD_GPIO012_FUNC_GPIO012>;
> +                bias-pull-up;
> +                drive-strength = <DS_LEVEL4>;
> +           };
> +        };
> +    };

This looks good to me, I don't know if the bindings maintainers have
opinions on the placement of defines in examples.

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [v2 0/3] Add pinctrl support for sky1
  2025-09-12  6:06 [v2 0/3] Add pinctrl support for sky1 Gary Yang
                   ` (2 preceding siblings ...)
  2025-09-12  6:06 ` [v2 3/3] arm64: dts: cix: Add pinctrl nodes for sky1 Gary Yang
@ 2025-09-12  7:45 ` Linus Walleij
  3 siblings, 0 replies; 17+ messages in thread
From: Linus Walleij @ 2025-09-12  7:45 UTC (permalink / raw)
  To: Gary Yang
  Cc: robh, krzk+dt, conor+dt, linux-gpio, devicetree, linux-kernel,
	linux-arm-kernel, cix-kernel-upstream, Konstantin Ryabitsev

Hi Gary,

On Fri, Sep 12, 2025 at 8:06 AM Gary Yang <gary.yang@cixtech.com> wrote:

> Patch 1: add Cix pinctrl driver to support pinmux and pinconfigs
> Patch 2: add Cix pinctrl nodes and header file
> Patch 3: add yaml doc
>
> Changes for v2:
> - restructure the pinctrl driver to support pinmux=<..>
> - redefine pinmux macros
> - move header file from dt-bindings to dts
> - fix the code-style issues

If you want help for managing the different revisions of a patch series,
you can use the "b4" tool, here is a tutorial:

https://people.kernel.org/monsieuricon/sending-a-kernel-patch-with-b4-part-1

[Konstantin: the doc link on the bottom of the article is wrong
and needs to be augmented to point to latest!]

It's a bit tricky to switch to v3 since you already started without it,
but it can be done with

b4 prep --force-revision 3
(see full docs https://b4.docs.kernel.org/en/latest/ )


Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [v2 1/3] pinctrl: cix: Add pin-controller support for sky1
  2025-09-12  6:06 ` [v2 1/3] pinctrl: cix: Add pin-controller " Gary Yang
@ 2025-09-12 11:59   ` Linus Walleij
  2025-09-15  7:09     ` 回复: " Gary Yang
  0 siblings, 1 reply; 17+ messages in thread
From: Linus Walleij @ 2025-09-12 11:59 UTC (permalink / raw)
  To: Gary Yang
  Cc: robh, krzk+dt, conor+dt, linux-gpio, devicetree, linux-kernel,
	linux-arm-kernel, cix-kernel-upstream

Hi Gary,

thanks for your patch!

On Fri, Sep 12, 2025 at 8:06 AM Gary Yang <gary.yang@cixtech.com> wrote:

> Add the pin-controller driver for Sky1 platform
>

Add some more description of the pin control on the SoC here please.

> Signed-off-by: Gary Yang <gary.yang@cixtech.com>
(...)

Config structure in Kconfig looks good!

> +++ b/drivers/pinctrl/cix/pinctrl-sky1-base.c
> @@ -0,0 +1,581 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +//
> +// Author: Jerry Zhu <Jerry.Zhu@cixtech.com>
> +
> +#include <linux/device.h>
> +#include <linux/err.h>
> +#include <linux/init.h>
> +#include <linux/io.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/of_device.h>
> +#include <linux/of_address.h>
> +#include <linux/pinctrl/machine.h>
> +#include <linux/pinctrl/pinconf.h>
> +#include <linux/pinctrl/pinconf-generic.h>
> +#include <linux/pinctrl/pinctrl.h>
> +#include <linux/pinctrl/pinmux.h>
> +#include <linux/platform_device.h>
> +#include <linux/seq_file.h>
> +#include <linux/slab.h>
> +
> +#include "../core.h"
> +#include "../pinconf.h"
> +#include "../pinctrl-utils.h"
> +#include "../pinmux.h"
> +#include "pinctrl-sky1.h"
> +
> +#define SKY1_PIN_SIZE          (0x4)
> +#define SKY1_MUX_MASK          (0x180)

For masks do this:

#include <linux/bits.h>

#define SKY1_MUX_MASK GENMASK(8, 7)

GENMASK generates a bitmask from bit 7 to 8, 0x180.

If its a 32bit register you can use GENMASK_U32() to be
even clearer, etc.

> +#define SKY1_MUX_SHIFT         (0x7)
> +#define SKY1_PULLCONF_MASK     (0x60)

Same idea here.

> +#define SKY1_PULLUP_SHIFT      (0x6)
> +#define SKY1_PULLDN_SHIFT      (0x5)

I would probably do this:

#include <linus/bits.h>

#define SKY1_PULLDN BIT(5)
#define SKY1_PULLUP BIT(6)

Using simple bit references to define what each bit
is for.

> +#define SKY1_DS_MASK           (0x0f)

Use GENMASK()

> +#define CIX_GET_PIN_NO(x) ((x) >> 8)
> +#define CIX_GET_PIN_FUNC(x) ((x) & 0xf)

Maybe define 8 and 0xf as shifts?

> +static const struct sky1_function_desc *sky1_pctrl_find_function_by_pin(
> +               struct sky1_pinctrl *spctl, u32 pin_num, u32 fnum)
> +{
> +       const struct sky1_pin_desc *pin = spctl->info->pins + pin_num;
> +       const struct sky1_function_desc *func = pin->functions;
> +
> +       while (func && func->name) {
> +               if (func->muxval == fnum)
> +                       return func;
> +               func++;
> +       }

Using a NULL func->name to terminate the array looks a bit dangerous.

What about adding:

> +struct sky1_function_desc {
> +       unsigned char muxval;
> +       const char *name;

const char * const *functions;
size_t nfuncs;

> +};

Then you can use nfuncs to iterate over the array of
function names, and define a macro like this:

#define SKY_PINFUNCTION(_muxval, _functions, _nfunctions)   \
(struct sky1_function_desc) {                                  \
                .muxval = (muxval),                        \
                .functions = (_functions),                    \
                .nfuncs = (_nfunctions),                  \
        }

And then this:

+static const struct sky1_pin_desc sky1_pinctrl_s5_pads[] = {
> +       {
> +               .pin = PINCTRL_PIN(0, "GPIO1"),
> +               .functions = {
> +                       [0] = {0, "GPIO1"},
> +               },
> +       },
> +       {
> +               .pin = PINCTRL_PIN(1, "GPIO2"),
> +               .functions = {
> +                       [0] = {0, "GPIO2"},
> +               },

> +       },

becomes

static const struct sky1_pin_desc sky1_pinctrl_s5_pads[] = {
    SKY_PINFUNCTION(PINCTRL_PIN(0, "GPIO1"),  "GPIO1", 1),
    SKY_PINFUNCTION(PINCTRL_PIN(1, "GPIO2"),  "GPIO2", 1),

I don't know about using the PINCTRL_PIN() macro here though,
can't you just put in 0, 1...?

Anyway I think you get the idea.

> +static bool sky1_pctrl_is_function_valid(struct sky1_pinctrl *spctl,
> +               u32 pin_num, u32 fnum)
> +{
> +       int i;
> +
> +       for (i = 0; i < spctl->info->npins; i++) {
> +               const struct sky1_pin_desc *pin = spctl->info->pins + i;
> +
> +               if (pin->pin.number == pin_num) {
> +                       const struct sky1_function_desc *func =
> +                                       pin->functions;
> +
> +                       while (func && func->name) {

So here you could just for (i = 0; i++; i < func->nfuncs)

(etc everywhere)

> +static int sky1_pctrl_dt_node_to_map_func(struct sky1_pinctrl *spctl,
> +               u32 pin, u32 fnum, struct sky1_pinctrl_group *grp,
> +               struct pinctrl_map **map, unsigned int *reserved_maps,
> +               unsigned int *num_maps)
> +{
> +       bool ret;
> +
> +       if (*num_maps == *reserved_maps)
> +               return -ENOSPC;
> +
> +       (*map)[*num_maps].type = PIN_MAP_TYPE_MUX_GROUP;
> +       (*map)[*num_maps].data.mux.group = grp->name;
> +
> +       ret = sky1_pctrl_is_function_valid(spctl, pin, fnum);
> +       if (!ret) {
> +               dev_err(spctl->dev, "invalid function %d on pin %d .\n",
> +                               fnum, pin);
> +               return -EINVAL;
> +       }
> +
> +       (*map)[*num_maps].data.mux.function = sky1_gpio_functions[fnum];
> +       (*num_maps)++;
> +
> +       return 0;
> +}
> +
> +static struct sky1_pinctrl_group *
> +sky1_pctrl_find_group_by_pin(struct sky1_pinctrl *spctl, u32 pin)
> +{
> +       int i;
> +
> +       for (i = 0; i < spctl->info->npins; i++) {
> +               struct sky1_pinctrl_group *grp =
> +                       (struct sky1_pinctrl_group *)spctl->groups + i;
> +
> +               if (grp->pin == pin)
> +                       return grp;
> +       }
> +
> +       return NULL;
> +}

And this:

> +struct sky1_pinctrl_group {
> +       const char *name;
> +       unsigned long config;
> +       unsigned int pin;
> +};

it's a bit conceptually weird.

Usually a pin can be member of many groups.

The only time this works is when the pin controller is of the type
where every pin is placed in a single group with only that pin in it.

And that seems to be the case, because:

> +static int sky1_pctrl_get_groups_count(struct pinctrl_dev *pctldev)
> +{
> +       struct sky1_pinctrl *spctl = pinctrl_dev_get_drvdata(pctldev);
> +
> +       return spctl->info->npins;
> +}

If this is the implied pattern for this driver, write as a comment to
the above function that this pin controller place all pins into a
single group with one pin and that this is why this works.

The normal (as can be seen from the pin control documentation
https://docs.kernel.org/driver-api/pin-control.html )
is to group pins, so e.g.

uart0_rx_tx_grp = { pin1, pin2 };
i2c0_sda_scl_grp = { pin1, pin2 };

Then this is combined with functions such as uart0 and i2c0:

function, group
("uart0", uart0_rx_tx_grp)
("i2c0", i2c0_sda_scl_grp)

Here you see the two pins are used for uart in the first case
and for i2c in the second case, it's the same pins, but members
of two different groups, and these groups are then used with
a function.

The possible functions for a group are then defined somewhere
so these settings can be applied.

Maybe this pattern is something you have in your driver
because the code was copied from some other driver
which use one group per pin, it's not certain that this is the
best layout for the cix SoC so look it over!

The pinconf part of the driver looks very good to me.

Look over these things, and keep posting updates!

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [v2 2/3] dt-bindings: pinctrl: Add cix,sky1-pinctrl
  2025-09-12  6:06 ` [v2 2/3] dt-bindings: pinctrl: Add cix,sky1-pinctrl Gary Yang
  2025-09-12  7:39   ` Linus Walleij
@ 2025-09-12 14:19   ` Rob Herring
  2025-09-12 14:23   ` Rob Herring (Arm)
  2 siblings, 0 replies; 17+ messages in thread
From: Rob Herring @ 2025-09-12 14:19 UTC (permalink / raw)
  To: Gary Yang
  Cc: linus.walleij, krzk+dt, conor+dt, linux-gpio, devicetree,
	linux-kernel, linux-arm-kernel, cix-kernel-upstream

On Fri, Sep 12, 2025 at 02:06:49PM +0800, Gary Yang wrote:
> The pin-controller is used to control the Soc pins.
> There are two pin-controllers on Cix Sky1 platform.
> One is used under S0 state, the other is used under
> S5 state.

Wrap lines at 72 chars.

> 
> Signed-off-by: Gary Yang <gary.yang@cixtech.com>
> ---
>  .../bindings/pinctrl/cix,sky1-pinctrl.yaml    | 85 +++++++++++++++++++
>  1 file changed, 85 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/pinctrl/cix,sky1-pinctrl.yaml
> 
> diff --git a/Documentation/devicetree/bindings/pinctrl/cix,sky1-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/cix,sky1-pinctrl.yaml
> new file mode 100644
> index 000000000000..c4a127fd8330
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/pinctrl/cix,sky1-pinctrl.yaml
> @@ -0,0 +1,85 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/pinctrl/cix,sky1-pinctrl.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Cix Sky1 Pin Controller
> +
> +maintainers:
> +  - Gary Yang <gary.yang@cixtech.com>
> +
> +description:
> +  The pin-controller is used to control Soc pins. There are two pin-controllers
> +  on Cix Sky1 platform. one is used under S0 state, the other one is used under
> +  S5 state.
> +
> +properties:
> +  compatible:
> +    enum:
> +      - cix,sky1-iomuxc
> +      - cix,sky1-iomuxc-s5
> +
> +  reg:
> +    maxItems: 1
> +
> +required:
> +  - compatible
> +  - reg
> +
> +# Client device subnode's properties
> +patternProperties:
> +  'pins$':
> +    type: object
> +    additionalProperties: false
> +    patternProperties:
> +      '(^pins|pins?$)':
> +        type: object
> +        additionalProperties: false
> +        description:
> +          A pinctrl node should contain at least one subnodes representing the
> +          pinctrl groups available on the machine. Each subnode will list the
> +          pins it needs, and how they should be configured, with regard to muxer
> +          configuration, pullups, and drive strength.
> +        $ref: /schemas/pinctrl/pincfg-node.yaml
> +
> +        properties:
> +          pinmux:
> +            description:
> +              Integer array, represents gpio pin number and mux setting.
> +              Supported pin number and mux varies for different SoCs, and are
> +              defined as macros in arch/arm64/boot/dts/cix/sky1-pinfunc.h directly.
> +
> +          bias-disable: true
> +
> +          bias-pull-up: true
> +
> +          bias-pull-down: true
> +
> +          drive-strength:
> +            description:
> +              Can support 15 levels, from DS_LEVEL1 to DS_LEVEL15.
> +              See arch/arm64/boot/dts/cix/sky1-pinfunc.h for valid arguments.

Constraints on the values?

> +
> +        required:
> +          - pinmux
> +
> +additionalProperties: false
> +
> +examples:
> +  # Pinmux controller node
> +  - |
> +    #define CIX_PAD_GPIO012_FUNC_GPIO012 (11 << 8 | 0x0)
> +    #define DS_LEVEL4 (4)
> +    iomuxc: pinctrl@4170000 {
> +        compatible = "cix,sky1-iomuxc";
> +        reg = <0x4170000 0x1000>;
> +
> +        wifi_vbat_gpio: wifi-vbat-gpio-pins {
> +            pins-wifi-vbat-gpio {
> +                pinmux = <CIX_PAD_GPIO012_FUNC_GPIO012>;
> +                bias-pull-up;
> +                drive-strength = <DS_LEVEL4>;
> +           };
> +        };
> +    };
> -- 
> 2.49.0
> 

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [v2 2/3] dt-bindings: pinctrl: Add cix,sky1-pinctrl
  2025-09-12  6:06 ` [v2 2/3] dt-bindings: pinctrl: Add cix,sky1-pinctrl Gary Yang
  2025-09-12  7:39   ` Linus Walleij
  2025-09-12 14:19   ` Rob Herring
@ 2025-09-12 14:23   ` Rob Herring (Arm)
  2025-09-12 15:23     ` 回复: " Gary Yang
  2 siblings, 1 reply; 17+ messages in thread
From: Rob Herring (Arm) @ 2025-09-12 14:23 UTC (permalink / raw)
  To: Gary Yang
  Cc: devicetree, linux-gpio, cix-kernel-upstream, krzk+dt,
	linux-kernel, conor+dt, linus.walleij, linux-arm-kernel


On Fri, 12 Sep 2025 14:06:49 +0800, Gary Yang wrote:
> The pin-controller is used to control the Soc pins.
> There are two pin-controllers on Cix Sky1 platform.
> One is used under S0 state, the other is used under
> S5 state.
> 
> Signed-off-by: Gary Yang <gary.yang@cixtech.com>
> ---
>  .../bindings/pinctrl/cix,sky1-pinctrl.yaml    | 85 +++++++++++++++++++
>  1 file changed, 85 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/pinctrl/cix,sky1-pinctrl.yaml
> 

My bot found errors running 'make dt_binding_check' on your patch:

yamllint warnings/errors:

dtschema/dtc warnings/errors:
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/pinctrl/cix,sky1-pinctrl.example.dtb: wifi-vbat-gpio-pins: pins-wifi-vbat-gpio: {'pinmux': [2816], 'bias-pull-up': True, 'drive-strength': 4} is not of type 'array'
	from schema $id: http://devicetree.org/schemas/gpio/gpio-consumer.yaml#

doc reference errors (make refcheckdocs):

See https://patchwork.ozlabs.org/project/devicetree-bindings/patch/20250912060650.2180691-3-gary.yang@cixtech.com

The base for the series is generally the latest rc1. A different dependency
should be noted in *this* patch.

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:

pip3 install dtschema --upgrade

Please check and re-submit after running the above command yourself. Note
that DT_SCHEMA_FILES can be set to your schema file to speed up checking
your schema. However, it must be unset to test all examples with your schema.


^ permalink raw reply	[flat|nested] 17+ messages in thread

* 回复: [v2 2/3] dt-bindings: pinctrl: Add cix,sky1-pinctrl
  2025-09-12 14:23   ` Rob Herring (Arm)
@ 2025-09-12 15:23     ` Gary Yang
  0 siblings, 0 replies; 17+ messages in thread
From: Gary Yang @ 2025-09-12 15:23 UTC (permalink / raw)
  To: Rob Herring (Arm)
  Cc: devicetree@vger.kernel.org, linux-gpio@vger.kernel.org,
	cix-kernel-upstream, krzk+dt@kernel.org,
	linux-kernel@vger.kernel.org, conor+dt@kernel.org,
	linus.walleij@linaro.org, linux-arm-kernel@lists.infradead.org

Hi Rob,

Thanks for your comments

> 
> On Fri, 12 Sep 2025 14:06:49 +0800, Gary Yang wrote:
> > The pin-controller is used to control the Soc pins.
> > There are two pin-controllers on Cix Sky1 platform.
> > One is used under S0 state, the other is used under
> > S5 state.
> >
> > Signed-off-by: Gary Yang <gary.yang@cixtech.com>
> > ---
> >  .../bindings/pinctrl/cix,sky1-pinctrl.yaml    | 85 +++++++++++++++++++
> >  1 file changed, 85 insertions(+)
> >  create mode 100644
> > Documentation/devicetree/bindings/pinctrl/cix,sky1-pinctrl.yaml
> >
> 
> My bot found errors running 'make dt_binding_check' on your patch:
> 
> yamllint warnings/errors:
> 
> dtschema/dtc warnings/errors:
> /builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/pi
> nctrl/cix,sky1-pinctrl.example.dtb: wifi-vbat-gpio-pins: pins-wifi-vbat-gpio:
> {'pinmux': [2816], 'bias-pull-up': True, 'drive-strength': 4} is not of type 'array'
>         from schema $id:
> http://devicetree.org/schemas/gpio/gpio-consumer.yaml#
> 
> doc reference errors (make refcheckdocs):
> 
> See
> https://patchwork.ozlabs.org/project/devicetree-bindings/patch/2025091206
> 0650.2180691-3-gary.yang@cixtech.com
> 
> The base for the series is generally the latest rc1. A different dependency
> should be noted in *this* patch.
> 
> If you already ran 'make dt_binding_check' and didn't see the above error(s),
> then make sure 'yamllint' is installed and dt-schema is up to
> date:
> 
> pip3 install dtschema --upgrade
> 
> Please check and re-submit after running the above command yourself. Note
> that DT_SCHEMA_FILES can be set to your schema file to speed up checking
> your schema. However, it must be unset to test all examples with your schema.

As we know, must execute three commands before submit patches:
1) make O=$OUTKNL dt_binding_check DT_SCHEMA_FILES=pinctrl/cix,sky1-pinctrl.yaml
2) make CHECK_DTBS=y W=1 cix/sky1-orion-o6.dtb
3) ./scripts/checkpatch.pl 000*.patch
We don't submit any patch until no error or unexpected warning when execute three commands above.

As your suggestion, execute first command again after upgrade dtschema. But I don't see any error.
See more details as following:
gary@gary-System-Product-Name:~/workspace/upstream/kernel_upstream$ make O=$OUTKNL dt_binding_check DT_SCHEMA_FILES=pinctrl/cix,sky1-pinctrl.yaml
  SCHEMA  Documentation/devicetree/bindings/processed-schema.json
  CHKDT   ./Documentation/devicetree/bindings
  LINT    ./Documentation/devicetree/bindings
  DTEX    Documentation/devicetree/bindings/pinctrl/cix,sky1-pinctrl.example.dts
  DTC [C] Documentation/devicetree/bindings/pinctrl/cix,sky1-pinctrl.example.dtb

If I misunderstand or miss any information, please kindly remind me. 
Thanks

Best wishes
Gary


^ permalink raw reply	[flat|nested] 17+ messages in thread

* 回复: [v2 1/3] pinctrl: cix: Add pin-controller support for sky1
  2025-09-12 11:59   ` Linus Walleij
@ 2025-09-15  7:09     ` Gary Yang
  2025-09-15  8:35       ` Linus Walleij
  0 siblings, 1 reply; 17+ messages in thread
From: Gary Yang @ 2025-09-15  7:09 UTC (permalink / raw)
  To: Linus Walleij
  Cc: robh@kernel.org, krzk+dt@kernel.org, conor+dt@kernel.org,
	linux-gpio@vger.kernel.org, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org, cix-kernel-upstream

Hi Linus

Thanks for your review and suggestions below

> EXTERNAL EMAIL
> 
> Hi Gary,
> 
> thanks for your patch!
> 
> On Fri, Sep 12, 2025 at 8:06 AM Gary Yang <gary.yang@cixtech.com> wrote:
> 
> > Add the pin-controller driver for Sky1 platform
> >
> 
> Add some more description of the pin control on the SoC here please.
> 

OK, we will add more description as following, How about it?

The pin-controller is used to control Soc pins. It contains two parts: pinmux and pinconfig.
Pinmux is used to select pin function and pinconfig is used to configure pin. It includes
Pull-up,pull-down,and drive strength. There are two pin-controllers on Cix Sky1 platform. 
one is used under S0 state, the other one is used under S0 and S5 state.

> > Signed-off-by: Gary Yang <gary.yang@cixtech.com>
> (...)
> 
> Config structure in Kconfig looks good!
> 
> > +++ b/drivers/pinctrl/cix/pinctrl-sky1-base.c
> > @@ -0,0 +1,581 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +//
> > +// Author: Jerry Zhu <Jerry.Zhu@cixtech.com>
> > +
> > +#include <linux/device.h>
> > +#include <linux/err.h>
> > +#include <linux/init.h>
> > +#include <linux/io.h>
> > +#include <linux/module.h>
> > +#include <linux/of.h>
> > +#include <linux/of_device.h>
> > +#include <linux/of_address.h>
> > +#include <linux/pinctrl/machine.h>
> > +#include <linux/pinctrl/pinconf.h>
> > +#include <linux/pinctrl/pinconf-generic.h> #include
> > +<linux/pinctrl/pinctrl.h> #include <linux/pinctrl/pinmux.h> #include
> > +<linux/platform_device.h> #include <linux/seq_file.h> #include
> > +<linux/slab.h>
> > +
> > +#include "../core.h"
> > +#include "../pinconf.h"
> > +#include "../pinctrl-utils.h"
> > +#include "../pinmux.h"
> > +#include "pinctrl-sky1.h"
> > +
> > +#define SKY1_PIN_SIZE          (0x4)
> > +#define SKY1_MUX_MASK          (0x180)
> 
> For masks do this:
> 
> #include <linux/bits.h>
> 
> #define SKY1_MUX_MASK GENMASK(8, 7)
> 
> GENMASK generates a bitmask from bit 7 to 8, 0x180.
> 
> If its a 32bit register you can use GENMASK_U32() to be even clearer, etc.

Yes, it looks better. I agree this change

> 
> > +#define SKY1_MUX_SHIFT         (0x7)
> > +#define SKY1_PULLCONF_MASK     (0x60)
> 
> Same idea here.

Same things

> 
> > +#define SKY1_PULLUP_SHIFT      (0x6)
> > +#define SKY1_PULLDN_SHIFT      (0x5)
> 
> I would probably do this:
> 
> #include <linus/bits.h>
> 
> #define SKY1_PULLDN BIT(5)
> #define SKY1_PULLUP BIT(6)
> 
> Using simple bit references to define what each bit is for.
> 

Same things

> > +#define SKY1_DS_MASK           (0x0f)
> 
> Use GENMASK()
> 

Same things

> > +#define CIX_GET_PIN_NO(x) ((x) >> 8)
> > +#define CIX_GET_PIN_FUNC(x) ((x) & 0xf)
> 
> Maybe define 8 and 0xf as shifts?
> 

Same things

> > +static const struct sky1_function_desc *sky1_pctrl_find_function_by_pin(
> > +               struct sky1_pinctrl *spctl, u32 pin_num, u32 fnum) {
> > +       const struct sky1_pin_desc *pin = spctl->info->pins + pin_num;
> > +       const struct sky1_function_desc *func = pin->functions;
> > +
> > +       while (func && func->name) {
> > +               if (func->muxval == fnum)
> > +                       return func;
> > +               func++;
> > +       }
> 
> Using a NULL func->name to terminate the array looks a bit dangerous.
> 
> What about adding:
> 
> > +struct sky1_function_desc {
> > +       unsigned char muxval;
> > +       const char *name;
> 
> const char * const *functions;
> size_t nfuncs;
> 
> > +};

First, I understand your thinkings. please pay some attention to the type of func->name, it's a pointer, 

Checking whether this pointer is a null pointer is generally acceptable. A name maps to a mux value.

I think that it is safe. Of course, your suggestion is also a good idea. If you think this is not safe, we will 

change codes as your suggestions.

> 
> Then you can use nfuncs to iterate over the array of function names, and
> define a macro like this:
> 
> #define SKY_PINFUNCTION(_muxval, _functions, _nfunctions)   \
> (struct sky1_function_desc) {                                  \
>                 .muxval = (muxval),                        \
>                 .functions = (_functions),                    \
>                 .nfuncs = (_nfunctions),                  \
>         }
> 
> And then this:
> 
> +static const struct sky1_pin_desc sky1_pinctrl_s5_pads[] = {
> > +       {
> > +               .pin = PINCTRL_PIN(0, "GPIO1"),
> > +               .functions = {
> > +                       [0] = {0, "GPIO1"},
> > +               },
> > +       },
> > +       {
> > +               .pin = PINCTRL_PIN(1, "GPIO2"),
> > +               .functions = {
> > +                       [0] = {0, "GPIO2"},
> > +               },
> 
> > +       },
> 
> becomes
> 
> static const struct sky1_pin_desc sky1_pinctrl_s5_pads[] = {
>     SKY_PINFUNCTION(PINCTRL_PIN(0, "GPIO1"),  "GPIO1", 1),
>     SKY_PINFUNCTION(PINCTRL_PIN(1, "GPIO2"),  "GPIO2", 1),
> 
> I don't know about using the PINCTRL_PIN() macro here though, can't you just
> put in 0, 1...?
> 
> Anyway I think you get the idea.
> 

First, let us review the struct sky1_pin_desc, it contains two members, one is the struct pinctrl_pin_desc.

struct pinctrl_pin_desc {
        unsigned int number;
        const char *name;
        void *drv_data;
};

PINCTRL_PIN is used to initialize this struct in kernel. It locates in include/linux/pinctrl/pinctrl.h

#define PINCTRL_PIN(a, b) { .number = a, .name = b }

PINCTRL_PIN(0, "GPIO1") defines a pin, its number is 0, its name is "GPIO1".

Second, I ever think that use SKY_PINFUNCTION macro to define pins, when a pin has serval functions,

more than one function, we need define a function array for the pin and then pass the array to 

SKY_PINFUNCTION. Maybe it doesn't save anything, it takes more time in reading these codes to understand. 

What's your opinion?

> > +static bool sky1_pctrl_is_function_valid(struct sky1_pinctrl *spctl,
> > +               u32 pin_num, u32 fnum) {
> > +       int i;
> > +
> > +       for (i = 0; i < spctl->info->npins; i++) {
> > +               const struct sky1_pin_desc *pin = spctl->info->pins +
> > + i;
> > +
> > +               if (pin->pin.number == pin_num) {
> > +                       const struct sky1_function_desc *func =
> > +                                       pin->functions;
> > +
> > +                       while (func && func->name) {
> 
> So here you could just for (i = 0; i++; i < func->nfuncs)
> 
> (etc everywhere)
> 
> > +static int sky1_pctrl_dt_node_to_map_func(struct sky1_pinctrl *spctl,
> > +               u32 pin, u32 fnum, struct sky1_pinctrl_group *grp,
> > +               struct pinctrl_map **map, unsigned int *reserved_maps,
> > +               unsigned int *num_maps) {
> > +       bool ret;
> > +
> > +       if (*num_maps == *reserved_maps)
> > +               return -ENOSPC;
> > +
> > +       (*map)[*num_maps].type = PIN_MAP_TYPE_MUX_GROUP;
> > +       (*map)[*num_maps].data.mux.group = grp->name;
> > +
> > +       ret = sky1_pctrl_is_function_valid(spctl, pin, fnum);
> > +       if (!ret) {
> > +               dev_err(spctl->dev, "invalid function %d on pin %d .\n",
> > +                               fnum, pin);
> > +               return -EINVAL;
> > +       }
> > +
> > +       (*map)[*num_maps].data.mux.function =
> sky1_gpio_functions[fnum];
> > +       (*num_maps)++;
> > +
> > +       return 0;
> > +}
> > +
> > +static struct sky1_pinctrl_group *
> > +sky1_pctrl_find_group_by_pin(struct sky1_pinctrl *spctl, u32 pin) {
> > +       int i;
> > +
> > +       for (i = 0; i < spctl->info->npins; i++) {
> > +               struct sky1_pinctrl_group *grp =
> > +                       (struct sky1_pinctrl_group *)spctl->groups +
> > + i;
> > +
> > +               if (grp->pin == pin)
> > +                       return grp;
> > +       }
> > +
> > +       return NULL;
> > +}
> 
> And this:
> 
> > +struct sky1_pinctrl_group {
> > +       const char *name;
> > +       unsigned long config;
> > +       unsigned int pin;
> > +};
> 
> it's a bit conceptually weird.
> 
> Usually a pin can be member of many groups.
> 
> The only time this works is when the pin controller is of the type where every
> pin is placed in a single group with only that pin in it.
> 
> And that seems to be the case, because:
> 
> > +static int sky1_pctrl_get_groups_count(struct pinctrl_dev *pctldev) {
> > +       struct sky1_pinctrl *spctl = pinctrl_dev_get_drvdata(pctldev);
> > +
> > +       return spctl->info->npins;
> > +}
> 
> If this is the implied pattern for this driver, write as a comment to the above
> function that this pin controller place all pins into a single group with one pin
> and that this is why this works.
> 
> The normal (as can be seen from the pin control documentation
> https://docs.kernel.org/driver-api/pin-control.html ) is to group pins, so e.g.
> 
> uart0_rx_tx_grp = { pin1, pin2 };
> i2c0_sda_scl_grp = { pin1, pin2 };
> 
> Then this is combined with functions such as uart0 and i2c0:
> 
> function, group
> ("uart0", uart0_rx_tx_grp)
> ("i2c0", i2c0_sda_scl_grp)
> 
> Here you see the two pins are used for uart in the first case and for i2c in the
> second case, it's the same pins, but members of two different groups, and
> these groups are then used with a function.
> 
> The possible functions for a group are then defined somewhere so these
> settings can be applied.
> 
> Maybe this pattern is something you have in your driver because the code was
> copied from some other driver which use one group per pin, it's not certain
> that this is the best layout for the cix SoC so look it over!
> 

First maybe you ignore that fact the struct sky1_pinctrl_group is different from 

the struct group_desc. It only saves the config of a pin from dts. it doesn't include 

pin function part. As we know, a pin only has a config at the same time. One group map to a pin.

The pin function part is included in the struct sky1_function_desc. One pin can map

serval functions. There are four functions on sky1. We define the sky1_gpio_functions array.

It is used to select the pin functions. 

Second, you are right. the pinctrl driver support new scheme is seldom in kernel. You take mt723 as

an example before. Some codes come from the pinctrl driver on MTK. We modify them to adopt our platform.

If I misunderstand or miss anything, please let me know.

> The pinconf part of the driver looks very good to me.
> 
> Look over these things, and keep posting updates!
> 
> Yours,
> Linus Walleij

Best wishes
Gary


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [v2 1/3] pinctrl: cix: Add pin-controller support for sky1
  2025-09-15  7:09     ` 回复: " Gary Yang
@ 2025-09-15  8:35       ` Linus Walleij
  2025-09-17  2:19         ` 回复: " Gary Yang
  2025-09-18  6:17         ` Gary Yang
  0 siblings, 2 replies; 17+ messages in thread
From: Linus Walleij @ 2025-09-15  8:35 UTC (permalink / raw)
  To: Gary Yang
  Cc: robh@kernel.org, krzk+dt@kernel.org, conor+dt@kernel.org,
	linux-gpio@vger.kernel.org, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org, cix-kernel-upstream

On Mon, Sep 15, 2025 at 9:09 AM Gary Yang <gary.yang@cixtech.com> wrote:

> > Using a NULL func->name to terminate the array looks a bit dangerous.
>
> Checking whether this pointer is a null pointer is generally acceptable. A name maps to a mux value.
> I think that it is safe. Of course, your suggestion is also a good idea. If you think this is not safe, we will
> change codes as your suggestions.

It's OK just a suggestion. There are many ways to do this, first fix
other problems.

There are things in the language and the kernel that can help
you to check boundaries of arrays such as these functions so
you can't write code that index out of range, e.g.

+struct sky1_pin_desc {
+       const struct pinctrl_pin_desc pin;
+       const struct sky1_function_desc functions[4];
+};
+
+struct sky1_pinctrl_soc_info {
+       const struct sky1_pin_desc *pins;
+       unsigned int npins;
+};

It is possible to use a flexible array with the intrinsic
__counted by() here, e.g. instead of:

struct sky1_pin_desc {
     const struct pinctrl_pin_desc pin;
     const struct sky1_function_desc functions[4];

You can use:

+ size_t nfunctions;
+ const struct sky1_function_desc functions[] __counted_by(nfunctions);

If you grep counted_by in the kernel you find many other
examples of how we use this.

But flexible arrays is a bit complicated and dangerous so maybe you
want to avoid it altogether. Also I'm not sure it works when you put
things containing a flexible array into another array... I never tried it.

> > Then you can use nfuncs to iterate over the array of function names, and
> > define a macro like this:
> >
> > #define SKY_PINFUNCTION(_muxval, _functions, _nfunctions)   \
> > (struct sky1_function_desc) {                                  \
> >                 .muxval = (muxval),                        \
> >                 .functions = (_functions),                    \
> >                 .nfuncs = (_nfunctions),                  \
> >         }
> >
> > And then this:
> >
> > +static const struct sky1_pin_desc sky1_pinctrl_s5_pads[] = {
> > > +       {
> > > +               .pin = PINCTRL_PIN(0, "GPIO1"),
> > > +               .functions = {
> > > +                       [0] = {0, "GPIO1"},
> > > +               },
> > > +       },
> > > +       {
> > > +               .pin = PINCTRL_PIN(1, "GPIO2"),
> > > +               .functions = {
> > > +                       [0] = {0, "GPIO2"},
> > > +               },
> >
> > > +       },
> >
> > becomes
> >
> > static const struct sky1_pin_desc sky1_pinctrl_s5_pads[] = {
> >     SKY_PINFUNCTION(PINCTRL_PIN(0, "GPIO1"),  "GPIO1", 1),
> >     SKY_PINFUNCTION(PINCTRL_PIN(1, "GPIO2"),  "GPIO2", 1),
> >
> > I don't know about using the PINCTRL_PIN() macro here though, can't you just
> > put in 0, 1...?
> >
> > Anyway I think you get the idea.
> >
>
> First, let us review the struct sky1_pin_desc, it contains two members, one is the struct pinctrl_pin_desc.
>
> struct pinctrl_pin_desc {
>         unsigned int number;
>         const char *name;
>         void *drv_data;
> };
>
> PINCTRL_PIN is used to initialize this struct in kernel. It locates in include/linux/pinctrl/pinctrl.h
>
> #define PINCTRL_PIN(a, b) { .number = a, .name = b }
>
> PINCTRL_PIN(0, "GPIO1") defines a pin, its number is 0, its name is "GPIO1".

Ah I saw it wrong, sorry :(

You're right about this of course.

But I think you can still use a macro to define the long pin tables?
Albeit macros with flexible arguments is a bit hard to write.
Save it until everything else is working.

> > If this is the implied pattern for this driver, write as a comment to the above
> > function that this pin controller place all pins into a single group with one pin
> > and that this is why this works.
> >
> > The normal (as can be seen from the pin control documentation
> > https://docs.kernel.org/driver-api/pin-control.html ) is to group pins, so e.g.
> >
> > uart0_rx_tx_grp = { pin1, pin2 };
> > i2c0_sda_scl_grp = { pin1, pin2 };
> >
> > Then this is combined with functions such as uart0 and i2c0:
> >
> > function, group
> > ("uart0", uart0_rx_tx_grp)
> > ("i2c0", i2c0_sda_scl_grp)
> >
> > Here you see the two pins are used for uart in the first case and for i2c in the
> > second case, it's the same pins, but members of two different groups, and
> > these groups are then used with a function.
> >
> > The possible functions for a group are then defined somewhere so these
> > settings can be applied.
> >
> > Maybe this pattern is something you have in your driver because the code was
> > copied from some other driver which use one group per pin, it's not certain
> > that this is the best layout for the cix SoC so look it over!
>
> First maybe you ignore that fact the struct sky1_pinctrl_group is different from
> the struct group_desc. It only saves the config of a pin from dts. it doesn't include
> pin function part. As we know, a pin only has a config at the same time. One group map to a pin.
> The pin function part is included in the struct sky1_function_desc. One pin can map
> serval functions. There are four functions on sky1. We define the sky1_gpio_functions array.
> It is used to select the pin functions.
>
> Second, you are right. the pinctrl driver support new scheme is seldom in kernel. You take mt723 as
> an example before. Some codes come from the pinctrl driver on MTK. We modify them to adopt our platform.
> If I misunderstand or miss anything, please let me know.

Yes I can see that the driver is based on the MTK driver, my point is that
make sure you are not following it too closely, because what is good for
the mtk chips is not necessarily good for the cix chips.

But if you feel convenient with one group per pin and you are convinced
this is the best for your driver, go ahead with this scheme!

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 17+ messages in thread

* 回复: [v2 1/3] pinctrl: cix: Add pin-controller support for sky1
  2025-09-15  8:35       ` Linus Walleij
@ 2025-09-17  2:19         ` Gary Yang
  2025-09-18  6:17         ` Gary Yang
  1 sibling, 0 replies; 17+ messages in thread
From: Gary Yang @ 2025-09-17  2:19 UTC (permalink / raw)
  To: Linus Walleij
  Cc: robh@kernel.org, krzk+dt@kernel.org, conor+dt@kernel.org,
	linux-gpio@vger.kernel.org, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org, cix-kernel-upstream

Hi Linus,

Thanks for your kind comments

Sorry for delay reply

> EXTERNAL EMAIL
> 
> On Mon, Sep 15, 2025 at 9:09 AM Gary Yang <gary.yang@cixtech.com> wrote:
> 
> > > Using a NULL func->name to terminate the array looks a bit dangerous.
> >
> > Checking whether this pointer is a null pointer is generally acceptable. A
> name maps to a mux value.
> > I think that it is safe. Of course, your suggestion is also a good
> > idea. If you think this is not safe, we will change codes as your suggestions.
> 
> It's OK just a suggestion. There are many ways to do this, first fix other
> problems.
> 
> There are things in the language and the kernel that can help you to check
> boundaries of arrays such as these functions so you can't write code that index
> out of range, e.g.
> 
> +struct sky1_pin_desc {
> +       const struct pinctrl_pin_desc pin;
> +       const struct sky1_function_desc functions[4]; };
> +
> +struct sky1_pinctrl_soc_info {
> +       const struct sky1_pin_desc *pins;
> +       unsigned int npins;
> +};
> 
> It is possible to use a flexible array with the intrinsic __counted by() here, e.g.
> instead of:
> 
> struct sky1_pin_desc {
>      const struct pinctrl_pin_desc pin;
>      const struct sky1_function_desc functions[4];
> 
> You can use:
> 
> + size_t nfunctions;
> + const struct sky1_function_desc functions[] __counted_by(nfunctions);
> 
> If you grep counted_by in the kernel you find many other examples of how we
> use this.
> 
> But flexible arrays is a bit complicated and dangerous so maybe you want to
> avoid it altogether. Also I'm not sure it works when you put things containing a
> flexible array into another array... I never tried it.
> 

Thanks for your good idea. We will have a try. Only need take some time to debug it.

> > > Then you can use nfuncs to iterate over the array of function names,
> > > and define a macro like this:
> > >
> > > #define SKY_PINFUNCTION(_muxval, _functions, _nfunctions)   \
> > > (struct sky1_function_desc) {                                  \
> > >                 .muxval = (muxval),                        \
> > >                 .functions = (_functions),                    \
> > >                 .nfuncs = (_nfunctions),                  \
> > >         }
> > >
> > > And then this:
> > >
> > > +static const struct sky1_pin_desc sky1_pinctrl_s5_pads[] = {
> > > > +       {
> > > > +               .pin = PINCTRL_PIN(0, "GPIO1"),
> > > > +               .functions = {
> > > > +                       [0] = {0, "GPIO1"},
> > > > +               },
> > > > +       },
> > > > +       {
> > > > +               .pin = PINCTRL_PIN(1, "GPIO2"),
> > > > +               .functions = {
> > > > +                       [0] = {0, "GPIO2"},
> > > > +               },
> > >
> > > > +       },
> > >
> > > becomes
> > >
> > > static const struct sky1_pin_desc sky1_pinctrl_s5_pads[] = {
> > >     SKY_PINFUNCTION(PINCTRL_PIN(0, "GPIO1"),  "GPIO1", 1),
> > >     SKY_PINFUNCTION(PINCTRL_PIN(1, "GPIO2"),  "GPIO2", 1),
> > >
> > > I don't know about using the PINCTRL_PIN() macro here though, can't
> > > you just put in 0, 1...?
> > >
> > > Anyway I think you get the idea.
> > >
> >
> > First, let us review the struct sky1_pin_desc, it contains two members, one is
> the struct pinctrl_pin_desc.
> >
> > struct pinctrl_pin_desc {
> >         unsigned int number;
> >         const char *name;
> >         void *drv_data;
> > };
> >
> > PINCTRL_PIN is used to initialize this struct in kernel. It locates in
> > include/linux/pinctrl/pinctrl.h
> >
> > #define PINCTRL_PIN(a, b) { .number = a, .name = b }
> >
> > PINCTRL_PIN(0, "GPIO1") defines a pin, its number is 0, its name is "GPIO1".
> 
> Ah I saw it wrong, sorry :(
> 
> You're right about this of course.
> 
> But I think you can still use a macro to define the long pin tables?
> Albeit macros with flexible arguments is a bit hard to write.
> Save it until everything else is working.
> 
> > > If this is the implied pattern for this driver, write as a comment
> > > to the above function that this pin controller place all pins into a
> > > single group with one pin and that this is why this works.
> > >
> > > The normal (as can be seen from the pin control documentation
> > > https://docs.kernel.org/driver-api/pin-control.html ) is to group pins, so e.g.
> > >
> > > uart0_rx_tx_grp = { pin1, pin2 };
> > > i2c0_sda_scl_grp = { pin1, pin2 };
> > >
> > > Then this is combined with functions such as uart0 and i2c0:
> > >
> > > function, group
> > > ("uart0", uart0_rx_tx_grp)
> > > ("i2c0", i2c0_sda_scl_grp)
> > >
> > > Here you see the two pins are used for uart in the first case and
> > > for i2c in the second case, it's the same pins, but members of two
> > > different groups, and these groups are then used with a function.
> > >
> > > The possible functions for a group are then defined somewhere so
> > > these settings can be applied.
> > >
> > > Maybe this pattern is something you have in your driver because the
> > > code was copied from some other driver which use one group per pin,
> > > it's not certain that this is the best layout for the cix SoC so look it over!
> >
> > First maybe you ignore that fact the struct sky1_pinctrl_group is
> > different from the struct group_desc. It only saves the config of a
> > pin from dts. it doesn't include pin function part. As we know, a pin only has
> a config at the same time. One group map to a pin.
> > The pin function part is included in the struct sky1_function_desc.
> > One pin can map serval functions. There are four functions on sky1. We
> define the sky1_gpio_functions array.
> > It is used to select the pin functions.
> >
> > Second, you are right. the pinctrl driver support new scheme is seldom
> > in kernel. You take mt723 as an example before. Some codes come from the
> pinctrl driver on MTK. We modify them to adopt our platform.
> > If I misunderstand or miss anything, please let me know.
> 
> Yes I can see that the driver is based on the MTK driver, my point is that make
> sure you are not following it too closely, because what is good for the mtk
> chips is not necessarily good for the cix chips.
> 
> But if you feel convenient with one group per pin and you are convinced this is
> the best for your driver, go ahead with this scheme!
> 

First thanks for your understanding. If I misunderstand anything, please kindly remind me.

I think the pinmux=<> scheme is different from sky1,pin=<> scheme. 

In sky1,pin=<> scheme,It first parse the config in DTS in probe() and then create three radix trees. 
They are function tree, group tree, and pin tree. When apply setting, it finds the right group and right 
function via the name of dts node, and get the total pin number from group, and create map array, 
the first element maps to function. From second element, one element maps to a pinconfig. one pin
only has one config at the same time.

In pinmux=<> scheme, the pdata Info includes all the pins and the valid functions. It doesn't need to parse
the pin config in probe(). only when apply setting, it parses the pinconfig in DTS. It also creates map array,
it gets the right function via func in DTS and the right pinconfig via API. So it also works ok.

Second, We will try to use macros to define our pins. Just need some time to verify it.
Thanks

> Yours,
> Linus Walleij

Best wishes
Gary

^ permalink raw reply	[flat|nested] 17+ messages in thread

* 回复: [v2 1/3] pinctrl: cix: Add pin-controller support for sky1
  2025-09-15  8:35       ` Linus Walleij
  2025-09-17  2:19         ` 回复: " Gary Yang
@ 2025-09-18  6:17         ` Gary Yang
  2025-09-25 10:34           ` Gary Yang
  2025-09-30 12:34           ` Linus Walleij
  1 sibling, 2 replies; 17+ messages in thread
From: Gary Yang @ 2025-09-18  6:17 UTC (permalink / raw)
  To: Linus Walleij
  Cc: robh@kernel.org, krzk+dt@kernel.org, conor+dt@kernel.org,
	linux-gpio@vger.kernel.org, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org, cix-kernel-upstream

Hi Linus,

New scheme with macros has verified ok. I just want to confirm with you before submit codes

> EXTERNAL EMAIL
> 
> On Mon, Sep 15, 2025 at 9:09 AM Gary Yang <gary.yang@cixtech.com> wrote:
> 
> > > Using a NULL func->name to terminate the array looks a bit dangerous.
> >
> > Checking whether this pointer is a null pointer is generally acceptable. A
> name maps to a mux value.
> > I think that it is safe. Of course, your suggestion is also a good
> > idea. If you think this is not safe, we will change codes as your suggestions.
> 
> It's OK just a suggestion. There are many ways to do this, first fix other
> problems.
> 
> There are things in the language and the kernel that can help you to check
> boundaries of arrays such as these functions so you can't write code that index
> out of range, e.g.
> 
> +struct sky1_pin_desc {
> +       const struct pinctrl_pin_desc pin;
> +       const struct sky1_function_desc functions[4]; };
> +
> +struct sky1_pinctrl_soc_info {
> +       const struct sky1_pin_desc *pins;
> +       unsigned int npins;
> +};
> 
> It is possible to use a flexible array with the intrinsic __counted by() here, e.g.
> instead of:
> 
> struct sky1_pin_desc {
>      const struct pinctrl_pin_desc pin;
>      const struct sky1_function_desc functions[4];
> 
> You can use:
> 
> + size_t nfunctions;
> + const struct sky1_function_desc functions[] __counted_by(nfunctions);
> 
> If you grep counted_by in the kernel you find many other examples of how we
> use this.
> 
> But flexible arrays is a bit complicated and dangerous so maybe you want to
> avoid it altogether. Also I'm not sure it works when you put things containing a
> flexible array into another array... I never tried it.
> 
> > > Then you can use nfuncs to iterate over the array of function names,
> > > and define a macro like this:
> > >
> > > #define SKY_PINFUNCTION(_muxval, _functions, _nfunctions)   \
> > > (struct sky1_function_desc) {                                  \
> > >                 .muxval = (muxval),                        \
> > >                 .functions = (_functions),                    \
> > >                 .nfuncs = (_nfunctions),                  \
> > >         }
> > >
> > > And then this:
> > >
> > > +static const struct sky1_pin_desc sky1_pinctrl_s5_pads[] = {
> > > > +       {
> > > > +               .pin = PINCTRL_PIN(0, "GPIO1"),
> > > > +               .functions = {
> > > > +                       [0] = {0, "GPIO1"},
> > > > +               },
> > > > +       },
> > > > +       {
> > > > +               .pin = PINCTRL_PIN(1, "GPIO2"),
> > > > +               .functions = {
> > > > +                       [0] = {0, "GPIO2"},
> > > > +               },
> > >
> > > > +       },
> > >
> > > becomes
> > >
> > > static const struct sky1_pin_desc sky1_pinctrl_s5_pads[] = {
> > >     SKY_PINFUNCTION(PINCTRL_PIN(0, "GPIO1"),  "GPIO1", 1),
> > >     SKY_PINFUNCTION(PINCTRL_PIN(1, "GPIO2"),  "GPIO2", 1),
> > >
> > > I don't know about using the PINCTRL_PIN() macro here though, can't
> > > you just put in 0, 1...?
> > >
> > > Anyway I think you get the idea.
> > >
> >
> > First, let us review the struct sky1_pin_desc, it contains two members, one is
> the struct pinctrl_pin_desc.
> >
> > struct pinctrl_pin_desc {
> >         unsigned int number;
> >         const char *name;
> >         void *drv_data;
> > };
> >
> > PINCTRL_PIN is used to initialize this struct in kernel. It locates in
> > include/linux/pinctrl/pinctrl.h
> >
> > #define PINCTRL_PIN(a, b) { .number = a, .name = b }
> >
> > PINCTRL_PIN(0, "GPIO1") defines a pin, its number is 0, its name is "GPIO1".
> 
> Ah I saw it wrong, sorry :(
> 
> You're right about this of course.
> 
> But I think you can still use a macro to define the long pin tables?
> Albeit macros with flexible arguments is a bit hard to write.
> Save it until everything else is working.
> 
In header file:

struct sky1_pin_desc {
        const struct pinctrl_pin_desc pin;
        const char **func_group;
        unsigned int nfunc;
};

#define SKY_PINFUNCTION(_pin, _func)                            \
 (struct sky1_pin_desc) {                                        \
                 .pin = _pin,                                    \
                 .func_group = _func##_group,                    \
                 .nfunc = ARRAY_SIZE(_func##_group),             \
         }

In C file:

static const char *gpio1_group[] = {"GPIO1"};
static const char *gpio2_group[] = {"GPIO2"};

static const struct sky1_pin_desc sky1_pinctrl_s5_pads[] = {
        SKY_PINFUNCTION(PINCTRL_PIN(0, "GPIO1"), gpio1),
        SKY_PINFUNCTION(PINCTRL_PIN(1, "GPIO2"), gpio2),
		.......
};

What's your suggestion? Thanks

> 
> Yours,
> Linus Walleij

Best wishes
Gary


^ permalink raw reply	[flat|nested] 17+ messages in thread

* 回复: [v2 1/3] pinctrl: cix: Add pin-controller support for sky1
  2025-09-18  6:17         ` Gary Yang
@ 2025-09-25 10:34           ` Gary Yang
  2025-09-30 12:34           ` Linus Walleij
  1 sibling, 0 replies; 17+ messages in thread
From: Gary Yang @ 2025-09-25 10:34 UTC (permalink / raw)
  To: Linus Walleij
  Cc: robh@kernel.org, krzk+dt@kernel.org, conor+dt@kernel.org,
	linux-gpio@vger.kernel.org, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org, cix-kernel-upstream

Hi Linus,

> 
> New scheme with macros has verified ok. I just want to confirm with you
> before submit codes
> 
> > EXTERNAL EMAIL
> >
> > On Mon, Sep 15, 2025 at 9:09 AM Gary Yang <gary.yang@cixtech.com>
> wrote:
> >
> > > > Using a NULL func->name to terminate the array looks a bit dangerous.
> > >
> > > Checking whether this pointer is a null pointer is generally
> > > acceptable. A
> > name maps to a mux value.
> > > I think that it is safe. Of course, your suggestion is also a good
> > > idea. If you think this is not safe, we will change codes as your suggestions.
> >
> > It's OK just a suggestion. There are many ways to do this, first fix
> > other problems.
> >
> > There are things in the language and the kernel that can help you to
> > check boundaries of arrays such as these functions so you can't write
> > code that index out of range, e.g.
> >
> > +struct sky1_pin_desc {
> > +       const struct pinctrl_pin_desc pin;
> > +       const struct sky1_function_desc functions[4]; };
> > +
> > +struct sky1_pinctrl_soc_info {
> > +       const struct sky1_pin_desc *pins;
> > +       unsigned int npins;
> > +};
> >
> > It is possible to use a flexible array with the intrinsic __counted by() here, e.g.
> > instead of:
> >
> > struct sky1_pin_desc {
> >      const struct pinctrl_pin_desc pin;
> >      const struct sky1_function_desc functions[4];
> >
> > You can use:
> >
> > + size_t nfunctions;
> > + const struct sky1_function_desc functions[]
> > + __counted_by(nfunctions);
> >
> > If you grep counted_by in the kernel you find many other examples of
> > how we use this.
> >
> > But flexible arrays is a bit complicated and dangerous so maybe you
> > want to avoid it altogether. Also I'm not sure it works when you put
> > things containing a flexible array into another array... I never tried it.
> >
> > > > Then you can use nfuncs to iterate over the array of function
> > > > names, and define a macro like this:
> > > >
> > > > #define SKY_PINFUNCTION(_muxval, _functions, _nfunctions)   \
> > > > (struct sky1_function_desc) {                                  \
> > > >                 .muxval = (muxval),                        \
> > > >                 .functions = (_functions),                    \
> > > >                 .nfuncs = (_nfunctions),                  \
> > > >         }
> > > >
> > > > And then this:
> > > >
> > > > +static const struct sky1_pin_desc sky1_pinctrl_s5_pads[] = {
> > > > > +       {
> > > > > +               .pin = PINCTRL_PIN(0, "GPIO1"),
> > > > > +               .functions = {
> > > > > +                       [0] = {0, "GPIO1"},
> > > > > +               },
> > > > > +       },
> > > > > +       {
> > > > > +               .pin = PINCTRL_PIN(1, "GPIO2"),
> > > > > +               .functions = {
> > > > > +                       [0] = {0, "GPIO2"},
> > > > > +               },
> > > >
> > > > > +       },
> > > >
> > > > becomes
> > > >
> > > > static const struct sky1_pin_desc sky1_pinctrl_s5_pads[] = {
> > > >     SKY_PINFUNCTION(PINCTRL_PIN(0, "GPIO1"),  "GPIO1", 1),
> > > >     SKY_PINFUNCTION(PINCTRL_PIN(1, "GPIO2"),  "GPIO2", 1),
> > > >
> > > > I don't know about using the PINCTRL_PIN() macro here though,
> > > > can't you just put in 0, 1...?
> > > >
> > > > Anyway I think you get the idea.
> > > >
> > >
> > > First, let us review the struct sky1_pin_desc, it contains two
> > > members, one is
> > the struct pinctrl_pin_desc.
> > >
> > > struct pinctrl_pin_desc {
> > >         unsigned int number;
> > >         const char *name;
> > >         void *drv_data;
> > > };
> > >
> > > PINCTRL_PIN is used to initialize this struct in kernel. It locates
> > > in include/linux/pinctrl/pinctrl.h
> > >
> > > #define PINCTRL_PIN(a, b) { .number = a, .name = b }
> > >
> > > PINCTRL_PIN(0, "GPIO1") defines a pin, its number is 0, its name is
> "GPIO1".
> >
> > Ah I saw it wrong, sorry :(
> >
> > You're right about this of course.
> >
> > But I think you can still use a macro to define the long pin tables?
> > Albeit macros with flexible arguments is a bit hard to write.
> > Save it until everything else is working.
> >
> In header file:
> 
> struct sky1_pin_desc {
>         const struct pinctrl_pin_desc pin;
>         const char **func_group;
>         unsigned int nfunc;
> };
> 
> #define SKY_PINFUNCTION(_pin, _func)                            \
>  (struct sky1_pin_desc) {                                        \
>                  .pin = _pin,                                    \
>                  .func_group = _func##_group,                    \
>                  .nfunc = ARRAY_SIZE(_func##_group),             \
>          }
> 
> In C file:
> 
> static const char *gpio1_group[] = {"GPIO1"}; static const char *gpio2_group[]
> = {"GPIO2"};
> 
> static const struct sky1_pin_desc sky1_pinctrl_s5_pads[] = {
>         SKY_PINFUNCTION(PINCTRL_PIN(0, "GPIO1"), gpio1),
>         SKY_PINFUNCTION(PINCTRL_PIN(1, "GPIO2"), gpio2),
> 		.......
> };
> 
> What's your suggestion? Thanks
> 

Ping....

> >
> > Yours,
> > Linus Walleij
> 
Best wishes
Gary


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [v2 1/3] pinctrl: cix: Add pin-controller support for sky1
  2025-09-18  6:17         ` Gary Yang
  2025-09-25 10:34           ` Gary Yang
@ 2025-09-30 12:34           ` Linus Walleij
  2025-10-09 11:00             ` 回复: " Gary Yang
  1 sibling, 1 reply; 17+ messages in thread
From: Linus Walleij @ 2025-09-30 12:34 UTC (permalink / raw)
  To: Gary Yang
  Cc: robh@kernel.org, krzk+dt@kernel.org, conor+dt@kernel.org,
	linux-gpio@vger.kernel.org, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org, cix-kernel-upstream

Hi Gary,

thanks for your efforts!

Sorry for taking so much time to respond. I was coding.

On Thu, Sep 18, 2025 at 8:17 AM Gary Yang <gary.yang@cixtech.com> wrote:

> New scheme with macros has verified ok. I just want to confirm with you before submit codes

No need to confirm with me just post it!
Better one post too much than one too little.

> > But I think you can still use a macro to define the long pin tables?
> > Albeit macros with flexible arguments is a bit hard to write.
> > Save it until everything else is working.
> >
> In header file:
>
> struct sky1_pin_desc {
>         const struct pinctrl_pin_desc pin;
>         const char **func_group;
>         unsigned int nfunc;
> };
>
> #define SKY_PINFUNCTION(_pin, _func)                            \
>  (struct sky1_pin_desc) {                                        \
>                  .pin = _pin,                                    \
>                  .func_group = _func##_group,                    \
>                  .nfunc = ARRAY_SIZE(_func##_group),             \
>          }
>
> In C file:
>
> static const char *gpio1_group[] = {"GPIO1"};
> static const char *gpio2_group[] = {"GPIO2"};
>
> static const struct sky1_pin_desc sky1_pinctrl_s5_pads[] = {
>         SKY_PINFUNCTION(PINCTRL_PIN(0, "GPIO1"), gpio1),
>         SKY_PINFUNCTION(PINCTRL_PIN(1, "GPIO2"), gpio2),
>                 .......
> };
>
> What's your suggestion? Thanks

It's OK as-is if this is how you want to structure things!

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 17+ messages in thread

* 回复: [v2 1/3] pinctrl: cix: Add pin-controller support for sky1
  2025-09-30 12:34           ` Linus Walleij
@ 2025-10-09 11:00             ` Gary Yang
  0 siblings, 0 replies; 17+ messages in thread
From: Gary Yang @ 2025-10-09 11:00 UTC (permalink / raw)
  To: Linus Walleij
  Cc: robh@kernel.org, krzk+dt@kernel.org, conor+dt@kernel.org,
	linux-gpio@vger.kernel.org, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org, cix-kernel-upstream

Hi Linus:

I'm glad to receive your reply.

> EXTERNAL EMAIL
> 
> Hi Gary,
> 
> thanks for your efforts!
> 
> Sorry for taking so much time to respond. I was coding.
> 
> On Thu, Sep 18, 2025 at 8:17 AM Gary Yang <gary.yang@cixtech.com> wrote:
> 
> > New scheme with macros has verified ok. I just want to confirm with
> > you before submit codes
> 
> No need to confirm with me just post it!
> Better one post too much than one too little.
> 

Ok, We will post the next version as soon as possible.

> > > But I think you can still use a macro to define the long pin tables?
> > > Albeit macros with flexible arguments is a bit hard to write.
> > > Save it until everything else is working.
> > >
> > In header file:
> >
> > struct sky1_pin_desc {
> >         const struct pinctrl_pin_desc pin;
> >         const char **func_group;
> >         unsigned int nfunc;
> > };
> >
> > #define SKY_PINFUNCTION(_pin, _func)                            \
> >  (struct sky1_pin_desc) {                                        \
> >                  .pin = _pin,                                    \
> >                  .func_group = _func##_group,                    \
> >                  .nfunc = ARRAY_SIZE(_func##_group),             \
> >          }
> >
> > In C file:
> >
> > static const char *gpio1_group[] = {"GPIO1"}; static const char
> > *gpio2_group[] = {"GPIO2"};
> >
> > static const struct sky1_pin_desc sky1_pinctrl_s5_pads[] = {
> >         SKY_PINFUNCTION(PINCTRL_PIN(0, "GPIO1"), gpio1),
> >         SKY_PINFUNCTION(PINCTRL_PIN(1, "GPIO2"), gpio2),
> >                 .......
> > };
> >
> > What's your suggestion? Thanks
> 
> It's OK as-is if this is how you want to structure things!
> 

Thanks for your understanding. We will adopt this scheme in next version.

> Yours,
> Linus Walleij

Best wishes
Gary


^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2025-10-09 11:00 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-09-12  6:06 [v2 0/3] Add pinctrl support for sky1 Gary Yang
2025-09-12  6:06 ` [v2 1/3] pinctrl: cix: Add pin-controller " Gary Yang
2025-09-12 11:59   ` Linus Walleij
2025-09-15  7:09     ` 回复: " Gary Yang
2025-09-15  8:35       ` Linus Walleij
2025-09-17  2:19         ` 回复: " Gary Yang
2025-09-18  6:17         ` Gary Yang
2025-09-25 10:34           ` Gary Yang
2025-09-30 12:34           ` Linus Walleij
2025-10-09 11:00             ` 回复: " Gary Yang
2025-09-12  6:06 ` [v2 2/3] dt-bindings: pinctrl: Add cix,sky1-pinctrl Gary Yang
2025-09-12  7:39   ` Linus Walleij
2025-09-12 14:19   ` Rob Herring
2025-09-12 14:23   ` Rob Herring (Arm)
2025-09-12 15:23     ` 回复: " Gary Yang
2025-09-12  6:06 ` [v2 3/3] arm64: dts: cix: Add pinctrl nodes for sky1 Gary Yang
2025-09-12  7:45 ` [v2 0/3] Add pinctrl support " Linus Walleij

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).