summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichal Wilczynski <m.wilczynski@samsung.com>2024-08-22 09:39:33 +0200
committerMichal Wilczynski <m.wilczynski@samsung.com>2024-08-22 13:53:38 +0200
commitbd58ea7ee669b5113fd7f8a8667b952e6fcea3fe (patch)
treed7f79f5060afed6ffe3641f043a0c5b1371b1069
parent592f3aea8a8b87f2689c1d6a1c03d493de2db533 (diff)
downloadlinux-riscv-bd58ea7ee669b5113fd7f8a8667b952e6fcea3fe.tar.gz
linux-riscv-bd58ea7ee669b5113fd7f8a8667b952e6fcea3fe.tar.bz2
linux-riscv-bd58ea7ee669b5113fd7f8a8667b952e6fcea3fe.zip
pinctrl: Add SpacemiT K1-X pinctrl drivers
Add custom SpacemiT K1-X pinctrl drivers. Ported from the vendor kernel [1]. [1] - https://github.com/BPI-SINOVOIP/pi-linux.git Change-Id: Ie7537d93bca98ce0ffcf366d49b1dc4fee490cd1 Signed-off-by: Michal Wilczynski <m.wilczynski@samsung.com>
-rw-r--r--drivers/pinctrl/Kconfig12
-rw-r--r--drivers/pinctrl/Makefile2
-rw-r--r--drivers/pinctrl/spacemit-pmic-pinctrl.c403
-rwxr-xr-xdrivers/pinctrl/spacemit/Kconfig15
-rwxr-xr-xdrivers/pinctrl/spacemit/Makefile2
-rwxr-xr-xdrivers/pinctrl/spacemit/pinctrl-spacemit.c582
-rwxr-xr-xdrivers/pinctrl/spacemit/pinctrl-spacemit.h104
-rw-r--r--include/dt-bindings/pinctrl/k1-x-pinctrl.h198
8 files changed, 1318 insertions, 0 deletions
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index 7dfb7190580e..95282fa1aeaf 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -403,6 +403,17 @@ config PINCTRL_RK805
help
This selects the pinctrl driver for RK805.
+config PINCTRL_SPACEMIT_PMIC
+ tristate "Pinctrl and GPIO driver for Spacemit PMIC"
+ depends on MFD_SPACEMIT_PMIC
+ select GPIOLIB
+ select PINMUX
+ select GENERIC_PINCTRL_GROUPS
+ select GENERIC_PINMUX_FUNCTIONS
+ select GENERIC_PINCONF
+ help
+ This selects the pinctrl driver for spacemit pmic.
+
config PINCTRL_ROCKCHIP
tristate "Rockchip gpio and pinctrl driver"
depends on ARCH_ROCKCHIP || COMPILE_TEST
@@ -533,5 +544,6 @@ source "drivers/pinctrl/ti/Kconfig"
source "drivers/pinctrl/uniphier/Kconfig"
source "drivers/pinctrl/visconti/Kconfig"
source "drivers/pinctrl/vt8500/Kconfig"
+source "drivers/pinctrl/spacemit/Kconfig"
endif
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index dd6cda270294..7394096d2b7e 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -79,3 +79,5 @@ obj-y += ti/
obj-$(CONFIG_PINCTRL_UNIPHIER) += uniphier/
obj-$(CONFIG_PINCTRL_VISCONTI) += visconti/
obj-$(CONFIG_ARCH_VT8500) += vt8500/
+obj-$(CONFIG_ARCH_SPACEMIT) += spacemit/
+obj-$(CONFIG_PINCTRL_SPACEMIT_PMIC) += spacemit-pmic-pinctrl.o \ No newline at end of file
diff --git a/drivers/pinctrl/spacemit-pmic-pinctrl.c b/drivers/pinctrl/spacemit-pmic-pinctrl.c
new file mode 100644
index 000000000000..2758936d56ef
--- /dev/null
+++ b/drivers/pinctrl/spacemit-pmic-pinctrl.c
@@ -0,0 +1,403 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Pinctrl driver for Spacemit PMIC
+ *
+ * Copyright (c) 2023, SPACEMIT Co., Ltd
+ *
+ */
+
+#include <linux/pinctrl/consumer.h>
+#include <linux/pinctrl/machine.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/gpio/driver.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+#include <linux/property.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/mfd/spacemit/spacemit_pmic.h>
+
+#include "core.h"
+#include "pinctrl-utils.h"
+#include "pinmux.h"
+
+SPM8821_PINMUX_DESC;
+SPM8821_PINFUNC_DESC;
+SPM8821_PIN_CINFIG_DESC;
+SPM8821_PINCTRL_MATCH_DATA;
+
+struct spacemit_pctl {
+ struct gpio_chip chip;
+ struct regmap *regmap;
+ struct pinctrl_dev *pctldev;
+ struct device *dev;
+ struct pinctrl_desc pinctrl_desc;
+ int funcdesc_nums, confdesc_nums;
+ const struct pin_func_desc *func_desc;
+ const struct pin_config_desc *config_desc;
+ const char *name;
+};
+
+static const struct pinctrl_ops spacemit_gpio_pinctrl_ops = {
+ .get_groups_count = pinctrl_generic_get_group_count,
+ .get_group_name = pinctrl_generic_get_group_name,
+ .get_group_pins = pinctrl_generic_get_group_pins,
+ .dt_node_to_map = pinconf_generic_dt_node_to_map_group,
+ .dt_free_map = pinconf_generic_dt_free_map,
+};
+
+static int spacemit_gpio_pinmux_set(struct pinctrl_dev *pctldev,
+ unsigned int function, unsigned int group)
+{
+ int i, ret;
+ struct spacemit_pctl *pctl = pinctrl_dev_get_drvdata(pctldev);
+ const char *funcname = pinmux_generic_get_function_name(pctldev, function);
+
+ /* get the target desc */
+ for (i = 0; i < pctl->funcdesc_nums; ++i) {
+ if (strcmp(funcname, pctl->func_desc[i].name) == 0 && group ==
+ pctl->func_desc[i].pin_id) {
+ /* set the first */
+ ret = regmap_update_bits(pctl->regmap,
+ pctl->func_desc[i].func_reg,
+ pctl->func_desc[i].func_mask,
+ pctl->func_desc[i].en_val
+ << (ffs(pctl->func_desc[i].func_mask) - 1));
+ if (ret) {
+ dev_err(pctl->dev, "set PIN%d, function:%s, failed\n", group, funcname);
+ return ret;
+ }
+
+ /* set the next if it have */
+ if (pctl->func_desc[i].ha_sub) {
+ ret = regmap_update_bits(pctl->regmap,
+ pctl->func_desc[i].sub_reg,
+ pctl->func_desc[i].sub_mask,
+ pctl->func_desc[i].sube_val
+ << (ffs(pctl->func_desc[i].sub_mask) - 1));
+ if (ret) {
+ dev_err(pctl->dev, "set PIN%d, function:%s, failed\n", group, funcname);
+ return ret;
+ }
+ }
+
+ break;
+ }
+ }
+
+ if (i >= pctl->funcdesc_nums) {
+ dev_err(pctl->dev, "Unsupported PIN%d, function:%s\n", group, funcname);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int spacemit_pmx_gpio_set_direction(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range,
+ unsigned int offset, bool input)
+{
+ int ret;
+ struct spacemit_pctl *pctl = pinctrl_dev_get_drvdata(pctldev);
+
+ if (strcmp(pctl->name, "spm8821") == 0)
+ /* when input == true, it means that we should set this pin
+ * as gpioin, so we should pass function(0) to set_mux
+ */
+ ret = spacemit_gpio_pinmux_set(pctldev, !input, offset);
+ else
+ return -EINVAL;
+
+ return ret;
+}
+
+static const struct pinmux_ops spacemit_gpio_pinmux_ops = {
+ .get_functions_count = pinmux_generic_get_function_count,
+ .get_function_name = pinmux_generic_get_function_name,
+ .get_function_groups = pinmux_generic_get_function_groups,
+ .set_mux = spacemit_gpio_pinmux_set,
+ .gpio_set_direction = spacemit_pmx_gpio_set_direction,
+ .strict = true,
+};
+
+static int spacemit_gpio_get(struct gpio_chip *chip, unsigned int offset)
+{
+ int ret;
+ unsigned int val;
+ struct spacemit_pctl *pctl = gpiochip_get_data(chip);
+
+ ret = regmap_read(pctl->regmap, pctl->config_desc[offset].input.reg, &val);
+ if (ret) {
+ dev_err(pctl->dev, "get PIN%d, direction failed\n", offset);
+ return ret;
+ }
+
+ val = val & pctl->config_desc[offset].input.msk;
+ val >>= ffs(pctl->config_desc[offset].input.msk) - 1;
+
+ return val;
+}
+
+static int spacemit_gpio_get_direction(struct gpio_chip *chip,
+ unsigned int offset)
+{
+ int i, ret;
+ unsigned int val, direction = 0;
+ struct spacemit_pctl *pctl = gpiochip_get_data(chip);
+
+ /* read the function set register */
+ for (i = 0; i < pctl->funcdesc_nums; ++i) {
+ if (offset == pctl->func_desc[i].pin_id) {
+ ret = regmap_read(pctl->regmap, pctl->func_desc[i].func_reg, &val);
+ if (ret) {
+ dev_err(pctl->dev, "get PIN%d, direction failed\n", offset);
+ return ret;
+ }
+
+ direction = val & pctl->func_desc[i].func_mask;
+ direction >>= ffs(pctl->func_desc[i].func_mask) - 1;
+
+ break;
+ }
+ }
+
+ if (strcmp(pctl->name, "spm8821") == 0)
+ return !direction;
+ else
+ return -EINVAL;
+}
+
+static void spacemit_gpio_set(struct gpio_chip *chip, unsigned int offset,
+ int value)
+{
+ int ret;
+ struct spacemit_pctl *pctl = gpiochip_get_data(chip);
+
+ ret = regmap_update_bits(pctl->regmap,
+ pctl->config_desc[offset].output.reg,
+ pctl->config_desc[offset].output.msk,
+ value ? pctl->config_desc[offset].output.msk : 0);
+ if (ret)
+ dev_err(pctl->dev, "set PIN%d, val:%d, failed\n", offset, value);
+}
+
+static int spacemit_gpio_input(struct gpio_chip *chip, unsigned int offset)
+{
+ /* set the gpio input */
+ return pinctrl_gpio_direction_input(chip->base + offset);
+}
+
+static int spacemit_gpio_output(struct gpio_chip *chip, unsigned int offset,
+ int value)
+{
+ /* set the gpio output */
+ return pinctrl_gpio_direction_input(chip->base + offset);
+}
+
+static int spacemit_pin_conf_get(struct pinctrl_dev *pctldev, unsigned int pin,
+ unsigned long *config)
+{
+ /* Do nothing by now */
+ return 0;
+}
+
+static int spacemit_pin_conf_set(struct pinctrl_dev *pctldev, unsigned int pin,
+ unsigned long *configs, unsigned int num_configs)
+{
+ unsigned int reg, msk, ret;
+ struct spacemit_pctl *pctl = pinctrl_dev_get_drvdata(pctldev);
+
+ while (num_configs) {
+ switch (pinconf_to_config_param(*configs)) {
+ case PIN_CONFIG_BIAS_DISABLE:
+ case PIN_CONFIG_BIAS_PULL_DOWN:
+ case PIN_CONFIG_BIAS_PULL_UP:
+ reg = pctl->config_desc[pin].pup.reg;
+ msk = pctl->config_desc[pin].pup.msk;
+ break;
+ case PIN_CONFIG_DRIVE_OPEN_DRAIN:
+ case PIN_CONFIG_DRIVE_PUSH_PULL:
+ case PIN_CONFIG_DRIVE_OPEN_SOURCE:
+ reg = pctl->config_desc[pin].od.reg;
+ msk = pctl->config_desc[pin].od.msk;
+ break;
+ case PIN_CONFIG_INPUT_DEBOUNCE:
+ reg = pctl->config_desc[pin].deb.reg;
+ msk = pctl->config_desc[pin].deb.timemsk;
+ break;
+ case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
+ reg = pctl->config_desc[pin].deb.reg;
+ msk = pctl->config_desc[pin].deb.en.msk;
+ break;
+ case PIN_CONFIG_OUTPUT:
+ reg = pctl->config_desc[pin].output.reg;
+ msk = pctl->config_desc[pin].output.msk;
+ break;
+ default:
+ return -ENOTSUPP;
+ }
+
+ ret = regmap_update_bits(pctl->regmap, reg, msk,
+ pinconf_to_config_argument(*configs)
+ << (ffs(msk) - 1));
+ if (ret) {
+ dev_err(pctl->dev, "set reg:%x, msk:%x failed\n", reg, msk);
+ return -EINVAL;
+ }
+ ++configs;
+ --num_configs;
+ }
+
+ return 0;
+}
+
+static int spacemit_pconf_group_set(struct pinctrl_dev *pctldev, unsigned group,
+ unsigned long *configs, unsigned num_configs)
+{
+ return spacemit_pin_conf_set(pctldev, group, configs, num_configs);
+}
+
+static int spacemit_pconf_group_get(struct pinctrl_dev *pctldev,
+ unsigned group,
+ unsigned long *config)
+{
+ return spacemit_pin_conf_get(pctldev, group, config);
+}
+
+static const struct pinconf_ops spacemit_gpio_pinconf_ops = {
+ .is_generic = true,
+ .pin_config_get = spacemit_pin_conf_get,
+ .pin_config_set = spacemit_pin_conf_set,
+ .pin_config_group_get = spacemit_pconf_group_get,
+ .pin_config_group_set = spacemit_pconf_group_set,
+};
+
+static const struct of_device_id spacemit_pmic_pinctrl_of_match[] = {
+ { .compatible = "pmic,pinctrl,spm8821", .data = (void *)&spm8821_pinctrl_match_data },
+ { },
+};
+MODULE_DEVICE_TABLE(of, spacemit_pmic_pinctrl_of_match);
+
+static int spacemit_pmic_pinctrl_probe(struct platform_device *pdev)
+{
+ int i, res;
+ struct spacemit_pctl *pctl;
+ unsigned int npins;
+ const char **pin_names;
+ unsigned int *pin_nums;
+ struct pinctrl_pin_desc *pins;
+ const struct of_device_id *of_id;
+ struct spacemit_pmic *pmic = dev_get_drvdata(pdev->dev.parent);
+ struct pinctrl_match_data *match_data;
+
+ of_id = of_match_device(spacemit_pmic_pinctrl_of_match, &pdev->dev);
+ if (!of_id) {
+ pr_err("Unable to match OF ID\n");
+ return -ENODEV;
+ }
+
+ match_data = (struct pinctrl_match_data *)of_id->data;
+
+ pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL);
+ if (!pctl)
+ return -ENOMEM;
+
+ pctl->name = match_data->name;
+ pctl->dev = &pdev->dev;
+ pctl->regmap = pmic->regmap;
+ pctl->func_desc = match_data->pinfunc_desc;
+ pctl->funcdesc_nums = match_data->nr_pin_fuc_desc;
+ pctl->config_desc = match_data->pinconf_desc;
+ pctl->confdesc_nums = match_data->nr_pin_conf_desc;
+ dev_set_drvdata(&pdev->dev, pctl);
+
+ if (of_property_read_u32(pdev->dev.of_node, "spacemit,npins", &npins))
+ return dev_err_probe(&pdev->dev, -EINVAL,
+ "spacemit,npins property not found\n");
+
+ pins = devm_kmalloc_array(&pdev->dev, npins, sizeof(pins[0]),
+ GFP_KERNEL);
+ pin_names = devm_kmalloc_array(&pdev->dev, npins, sizeof(pin_names[0]),
+ GFP_KERNEL);
+ pin_nums = devm_kmalloc_array(&pdev->dev, npins, sizeof(pin_nums[0]),
+ GFP_KERNEL);
+ if (!pins || !pin_names || !pin_nums)
+ return -ENOMEM;
+
+ for (i = 0; i < npins; i++) {
+ pins[i].number = i;
+ pins[i].name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "PIN%u", i);
+ pins[i].drv_data = pctl;
+ pin_names[i] = pins[i].name;
+ pin_nums[i] = i;
+ }
+
+ pctl->pinctrl_desc.name = dev_name(pctl->dev);
+ pctl->pinctrl_desc.pins = pins;
+ pctl->pinctrl_desc.npins = npins;
+ pctl->pinctrl_desc.pctlops = &spacemit_gpio_pinctrl_ops;
+ pctl->pinctrl_desc.pmxops = &spacemit_gpio_pinmux_ops;
+ pctl->pinctrl_desc.confops = &spacemit_gpio_pinconf_ops;
+
+ pctl->pctldev = devm_pinctrl_register(&pdev->dev, &pctl->pinctrl_desc, pctl);
+ if (IS_ERR(pctl->pctldev))
+ return dev_err_probe(&pdev->dev, PTR_ERR(pctl->pctldev),
+ "Failed to register pinctrl device.\n");
+
+ for (i = 0; i < npins; i++) {
+ res = pinctrl_generic_add_group(pctl->pctldev, pins[i].name,
+ pin_nums + i, 1, pctl);
+ if (res < 0)
+ return dev_err_probe(pctl->dev, res,
+ "Failed to register group");
+ }
+
+ for (i = 0; i < match_data->nr_pin_mux; ++i) {
+ res = pinmux_generic_add_function(pctl->pctldev, match_data->pinmux_funcs[i],
+ pin_names, npins, pctl);
+ if (res < 0)
+ return dev_err_probe(pctl->dev, res,
+ "Failed to register function.");
+ }
+
+ pctl->chip.base = -1;
+ pctl->chip.can_sleep = true;
+ pctl->chip.request = gpiochip_generic_request;
+ pctl->chip.free = gpiochip_generic_free;
+ pctl->chip.parent = &pdev->dev;
+ pctl->chip.label = dev_name(&pdev->dev);
+ pctl->chip.owner = THIS_MODULE;
+ pctl->chip.get = spacemit_gpio_get;
+ pctl->chip.get_direction = spacemit_gpio_get_direction;
+ pctl->chip.set = spacemit_gpio_set;
+ pctl->chip.direction_input = spacemit_gpio_input;
+ pctl->chip.direction_output = spacemit_gpio_output;
+
+ pctl->chip.ngpio = pctl->pinctrl_desc.npins;
+
+ res = devm_gpiochip_add_data(&pdev->dev, &pctl->chip, pctl);
+ if (res) {
+ dev_err(&pdev->dev, "Failed to register GPIO chip\n");
+ return res;
+ }
+
+ return 0;
+}
+
+static struct platform_driver spacemit_pmic_pinctrl_driver = {
+ .probe = spacemit_pmic_pinctrl_probe,
+ .driver = {
+ .name = "spacemit-pmic-pinctrl",
+ .of_match_table = spacemit_pmic_pinctrl_of_match,
+ },
+};
+module_platform_driver(spacemit_pmic_pinctrl_driver);
+
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/spacemit/Kconfig b/drivers/pinctrl/spacemit/Kconfig
new file mode 100755
index 000000000000..21ac69600e1e
--- /dev/null
+++ b/drivers/pinctrl/spacemit/Kconfig
@@ -0,0 +1,15 @@
+# SPDX-License-Identifier: GPL-2.0-only
+config PINCTRL_SPACEMIT
+ tristate
+ depends on OF
+ select GENERIC_PINCTRL_GROUPS
+ select GENERIC_PINMUX_FUNCTIONS
+ select GENERIC_PINCONF
+
+config PINCTRL_K1PRO
+ bool "Spacemit K1PRO pinctrl driver"
+ depends on OF
+ depends on SOC_SPACEMIT_K1_FPGA
+ select PINCTRL_SPACEMIT
+ help
+ Say Y here to enable the k1-pro pinctrl driver
diff --git a/drivers/pinctrl/spacemit/Makefile b/drivers/pinctrl/spacemit/Makefile
new file mode 100755
index 000000000000..0395ca400289
--- /dev/null
+++ b/drivers/pinctrl/spacemit/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_PINCTRL_SPACEMIT) += pinctrl-spacemit.o
+obj-$(CONFIG_PINCTRL_K1PRO) += pinctrl-k1pro.o \ No newline at end of file
diff --git a/drivers/pinctrl/spacemit/pinctrl-spacemit.c b/drivers/pinctrl/spacemit/pinctrl-spacemit.c
new file mode 100755
index 000000000000..cd3770d82b77
--- /dev/null
+++ b/drivers/pinctrl/spacemit/pinctrl-spacemit.c
@@ -0,0 +1,582 @@
+// SPDX-License-Identifier: GPL-2.0+
+//
+// Copyright (c) 2023, spacemit Corporation.
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/pinctrl/machine.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/reset.h>
+#include "../core.h"
+#include "pinctrl-spacemit.h"
+
+struct spacemit_pinctrl_data {
+ struct device *dev;
+ struct pinctrl_dev *pctl;
+ void __iomem *base;
+ struct reset_control *rstc;
+ struct spacemit_pinctrl_soc_data *soc;
+};
+
+static int spacemit_get_groups_count(struct pinctrl_dev *pctldev)
+{
+ struct spacemit_pinctrl_data *d = pinctrl_dev_get_drvdata(pctldev);
+
+ return d->soc->ngroups;
+}
+
+static const char *spacemit_get_group_name(struct pinctrl_dev *pctldev,
+ unsigned group)
+{
+ struct spacemit_pinctrl_data *d = pinctrl_dev_get_drvdata(pctldev);
+
+ if (group >= d->soc->ngroups)
+ return NULL;
+
+ return d->soc->groups[group].name;
+}
+
+static int spacemit_get_group_pins(struct pinctrl_dev *pctldev, unsigned group,
+ const unsigned **pins, unsigned *num_pins)
+{
+ struct spacemit_pinctrl_data *d = pinctrl_dev_get_drvdata(pctldev);
+
+ if (group >= d->soc->ngroups)
+ return -EINVAL;
+
+ *pins = d->soc->groups[group].pin_ids;
+ *num_pins = d->soc->groups[group].npins;
+
+ return 0;
+}
+
+static void spacemit_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
+ unsigned offset)
+{
+ seq_printf(s, " %s", dev_name(pctldev->dev));
+}
+
+static int spacemit_dt_node_to_map(struct pinctrl_dev *pctldev,
+ struct device_node *np,
+ struct pinctrl_map **map, unsigned *num_maps)
+{
+ struct spacemit_pinctrl_data *d = pinctrl_dev_get_drvdata(pctldev);
+ const struct spacemit_group *grp;
+ struct pinctrl_map *new_map;
+ struct device_node *parent;
+ int map_num = 1;
+ int i, j;
+
+ /*
+ * first find the group of this node and check if we need create
+ * config maps for pins
+ */
+ grp = NULL;
+ for (i = 0; i < d->soc->ngroups; i++) {
+ if (!strcmp(d->soc->groups[i].name, np->name)) {
+ grp = &d->soc->groups[i];
+ break;
+ }
+ }
+ if (!grp) {
+ dev_err(d->dev, "unable to find group for node %s\n",
+ np->name);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < grp->npins; i++)
+ map_num++;
+
+ new_map = kmalloc_array(map_num, sizeof(struct pinctrl_map),
+ GFP_KERNEL);
+ if (!new_map)
+ return -ENOMEM;
+
+ *map = new_map;
+ *num_maps = map_num;
+
+ /* create mux map */
+ parent = of_get_parent(np);
+ if (!parent) {
+ kfree(new_map);
+ return -EINVAL;
+ }
+ new_map[0].type = PIN_MAP_TYPE_MUX_GROUP;
+ new_map[0].data.mux.function = np->name;
+ new_map[0].data.mux.group = np->name;
+ of_node_put(parent);
+
+ /* create config map */
+ new_map++;
+ for (i = j = 0; i < grp->npins; i++) {
+ new_map[j].type = PIN_MAP_TYPE_CONFIGS_PIN;
+ new_map[j].data.configs.group_or_pin =
+ pin_get_name(pctldev, grp->pins[i].pin_id);
+ new_map[j].data.configs.configs = &grp->pins[i].config;
+ new_map[j].data.configs.num_configs = 1;
+ j++;
+ }
+
+ dev_dbg(pctldev->dev, "maps: function %s group %s num %d\n",
+ (*map)->data.mux.function, (*map)->data.mux.group, map_num);
+
+ return 0;
+}
+
+static void spacemit_dt_free_map(struct pinctrl_dev *pctldev,
+ struct pinctrl_map *map, unsigned num_maps)
+{
+ u32 i;
+
+ for (i = 0; i < num_maps; i++) {
+ if (map[i].type == PIN_MAP_TYPE_MUX_GROUP)
+ kfree(map[i].data.mux.group);
+ if (map[i].type == PIN_MAP_TYPE_CONFIGS_PIN)
+ kfree(map[i].data.configs.configs);
+ }
+
+ kfree(map);
+}
+
+static const struct pinctrl_ops spacemit_pinctrl_ops = {
+ .get_groups_count = spacemit_get_groups_count,
+ .get_group_name = spacemit_get_group_name,
+ .get_group_pins = spacemit_get_group_pins,
+ .pin_dbg_show = spacemit_pin_dbg_show,
+ .dt_node_to_map = spacemit_dt_node_to_map,
+ .dt_free_map = spacemit_dt_free_map,
+};
+
+static int spacemit_pinctrl_get_funcs_count(struct pinctrl_dev *pctldev)
+{
+ struct spacemit_pinctrl_data *d = pinctrl_dev_get_drvdata(pctldev);
+
+ return d->soc->nfunctions;
+}
+
+static const char *spacemit_pinctrl_get_func_name(struct pinctrl_dev *pctldev,
+ unsigned function)
+{
+ struct spacemit_pinctrl_data *d = pinctrl_dev_get_drvdata(pctldev);
+
+ return d->soc->functions[function].name;
+}
+
+static int spacemit_pinctrl_get_func_groups(struct pinctrl_dev *pctldev,
+ unsigned group,
+ const char * const **groups,
+ unsigned * const num_groups)
+{
+ struct spacemit_pinctrl_data *d = pinctrl_dev_get_drvdata(pctldev);
+
+ *groups = d->soc->functions[group].groups;
+ *num_groups = d->soc->functions[group].ngroups;
+
+ return 0;
+}
+
+static void spacemit_pinctrl_rmwl(u32 value, u32 mask, u8 shift, void __iomem *reg)
+{
+ u32 tmp;
+
+ tmp = readl(reg);
+ tmp &= ~(mask << shift);
+ tmp |= value << shift;
+ writel(tmp, reg);
+}
+
+static int spacemit_pinctrl_set_mux(struct pinctrl_dev *pctldev, unsigned selector,
+ unsigned group)
+{
+ struct spacemit_pinctrl_data *d = pinctrl_dev_get_drvdata(pctldev);
+ struct spacemit_group *g = &d->soc->groups[group];
+ void __iomem *reg;
+ u8 bank, shift, width;
+ u16 offset;
+ u32 i;
+
+ for (i = 0; i < g->npins; i++) {
+ bank = PINID_TO_BANK(g->pin_ids[i]);
+ offset = PINID_TO_PIN(g->pin_ids[i]);
+ reg = d->base + d->soc->regs->cfg;
+ reg += bank * d->soc->regs->reg_len + offset * 4;
+ shift = d->soc->pinconf->fs_shift;
+ width = d->soc->pinconf->fs_width;
+
+ dev_dbg(d->dev, "set mux: bank %d 0ffset %d val 0x%lx\n",
+ bank, offset, g->pins[i].muxsel);
+
+ spacemit_pinctrl_rmwl(g->pins[i].muxsel, GENMASK((width-1),0), shift, reg);
+ }
+
+ return 0;
+}
+
+static const struct pinmux_ops spacemit_pinmux_ops = {
+ .get_functions_count = spacemit_pinctrl_get_funcs_count,
+ .get_function_name = spacemit_pinctrl_get_func_name,
+ .get_function_groups = spacemit_pinctrl_get_func_groups,
+ .set_mux = spacemit_pinctrl_set_mux,
+};
+
+static int spacemit_pinconf_get(struct pinctrl_dev *pctldev,
+ unsigned pin, unsigned long *config)
+{
+ struct spacemit_pinctrl_data *d = pinctrl_dev_get_drvdata(pctldev);
+ u8 bank;
+ u16 offset = 0;
+ u64 reg = 0;
+
+ bank = PINID_TO_BANK(pin);
+ offset = PINID_TO_PIN(pin);
+ reg = (u64)(d->base + d->soc->regs->cfg);
+ reg += bank * d->soc->regs->reg_len + offset * 4;
+
+ *config = readl((void *)reg);
+ return 0;
+}
+
+static int spacemit_pinconf_set(struct pinctrl_dev *pctldev,
+ unsigned pin, unsigned long *configs,
+ unsigned num_configs)
+{
+ struct spacemit_pinctrl_data *d = pinctrl_dev_get_drvdata(pctldev);
+ struct spacemit_pinctrl_soc_data *soc = d->soc;
+ const struct spacemit_regs *regs = soc->regs;
+ const struct spacemit_pin_conf *pin_conf = soc->pinconf;
+ int i;
+ u8 bank;
+ u32 od, pull_en, pull, ds, st, rte;
+ u16 offset = 0;
+ u64 reg = 0;
+
+ dev_dbg(d->dev, "pinconf set pin %s\n",
+ pin_get_name(pctldev, pin));
+
+ bank = PINID_TO_BANK(pin);
+ offset = PINID_TO_PIN(pin);
+ reg = (u64)(d->base + regs->cfg);
+ reg += bank * regs->reg_len + offset * 4;
+
+ for (i = 0; i < num_configs; i++) {
+ volatile long config;
+
+ config = readl((void *)reg);
+
+ od = OD_DIS << pin_conf->od_shift;
+ pull_en = PE_EN << pin_conf->pe_shift;
+ pull = CONFIG_TO_PULL(configs[i]) << pin_conf->pull_shift;
+ ds = CONFIG_TO_DS(configs[i]) << pin_conf->ds_shift;
+ st = ST_DIS << pin_conf->st_shift;
+ rte = RTE_EN << pin_conf->rte_shift;
+
+ config |= (od | pull_en | pull | ds | st | rte);
+ writel(config, (void *)reg);
+ dev_dbg(d->dev, "write: bank %d 0ffset %d val 0x%lx\n",
+ bank, offset, config);
+ } /* for each config */
+
+ return 0;
+}
+
+static void spacemit_pinconf_dbg_show(struct pinctrl_dev *pctldev,
+ struct seq_file *s, unsigned pin)
+{
+ struct spacemit_pinctrl_data *d = pinctrl_dev_get_drvdata(pctldev);
+ u8 bank;
+ u16 offset = 0;
+ u64 reg = 0;
+
+ bank = PINID_TO_BANK(pin);
+ offset = PINID_TO_PIN(pin);
+ reg = (u64)(d->base + d->soc->regs->cfg);
+ reg += bank * d->soc->regs->reg_len + offset * 4;
+
+ seq_printf(s, "0x%lx", readl((void *)reg));
+}
+
+static void spacemit_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
+ struct seq_file *s, unsigned group)
+{
+ struct spacemit_pinctrl_data *d = pinctrl_dev_get_drvdata(pctldev);
+ struct spacemit_group *grp;
+ unsigned long config;
+ const char *name;
+ int i, ret;
+
+ if (group > d->soc->ngroups)
+ return;
+
+ seq_puts(s, "\n");
+ grp = &d->soc->groups[group];
+ for (i = 0; i < grp->npins; i++) {
+ struct spacemit_pin *pin = &grp->pins[i];
+
+ name = pin_get_name(pctldev, pin->pin_id);
+ ret = spacemit_pinconf_get(pctldev, pin->pin_id, &config);
+ if (ret)
+ return;
+ seq_printf(s, "%s: 0x%lx", name, config);
+ }
+}
+
+static const struct pinconf_ops spacemit_pinconf_ops = {
+ .pin_config_get = spacemit_pinconf_get,
+ .pin_config_set = spacemit_pinconf_set,
+ .pin_config_dbg_show = spacemit_pinconf_dbg_show,
+ .pin_config_group_dbg_show = spacemit_pinconf_group_dbg_show,
+};
+
+static struct pinctrl_desc spacemit_pinctrl_desc = {
+ .pctlops = &spacemit_pinctrl_ops,
+ .pmxops = &spacemit_pinmux_ops,
+ .confops = &spacemit_pinconf_ops,
+ .owner = THIS_MODULE,
+};
+
+static const char *get_pin_name_from_soc(struct spacemit_pinctrl_soc_data *soc,
+ const unsigned int pin_id)
+{
+ int i;
+
+ for (i = 0; i < soc->npins; i++) {
+ if (soc->pins[i].number == pin_id)
+ return soc->pins[i].name;
+ }
+
+ return NULL;
+}
+
+static int spacemit_pinctrl_parse_groups(struct device_node *np,
+ struct spacemit_group *grp,
+ struct spacemit_pinctrl_data *d,
+ u32 index)
+{
+ int size, i;
+ const __be32 *list;
+
+ dev_dbg(d->dev, "group(%d): %s\n", index, np->name);
+
+ /* Initialise group */
+ grp->name = np->name;
+
+ /*
+ * the binding format is spacemit,pins = <PIN MUX CONFIG>,
+ * do sanity check and calculate pins number
+ */
+ list = of_get_property(np, "spacemit,pins", &size);
+ if (!list) {
+ dev_err(d->dev, "no spacemit,pins property in node %s\n",
+ np->full_name);
+ return -EINVAL;
+ }
+
+ if (!size || size % SPACEMIT_PIN_SIZE) {
+ dev_err(d->dev, "Invalid spacemit,pins property in node %s\n",
+ np->full_name);
+ return -EINVAL;
+ }
+
+ grp->npins = size / SPACEMIT_PIN_SIZE;
+ grp->pins = devm_kcalloc(d->dev, grp->npins,
+ sizeof(struct spacemit_pin), GFP_KERNEL);
+ grp->pin_ids = devm_kcalloc(d->dev, grp->npins,
+ sizeof(unsigned int), GFP_KERNEL);
+ if (!grp->pins || !grp->pin_ids)
+ return -ENOMEM;
+
+ for (i = 0; i < grp->npins; i++) {
+ struct spacemit_pin *pin = &grp->pins[i];
+ u8 pull_val, driver_strength;
+
+ pin->pin_id = be32_to_cpu(*list++);
+ pin->muxsel = be32_to_cpu(*list++) & 0xF;
+ pull_val = be32_to_cpu(*list++) & 0x1;
+ driver_strength = be32_to_cpu(*list++) & 0xF;
+ pin->config = (pull_val << PULL_SHIFT) | (driver_strength << DS_SHIFT);
+ grp->pin_ids[i] = grp->pins[i].pin_id;
+
+ dev_dbg(d->dev, "%s: 0x%04x 0x%04lx",
+ get_pin_name_from_soc(d->soc, pin->pin_id), pin->muxsel, pin->config);
+ }
+
+ return 0;
+}
+
+static int spacemit_pinctrl_parse_functions(struct device_node *np,
+ struct spacemit_pinctrl_data *d)
+{
+ struct spacemit_pinctrl_soc_data *soc = d->soc;
+ struct device_node *child;
+ struct spacemit_function *f;
+ u32 i = 0, idxf = 0, idxg = 0;
+ const char *fn, *fnull = "";
+ int ret;
+
+ /* Count groups for each function */
+ fn = fnull;
+ f = &soc->functions[idxf];
+ for_each_child_of_node(np, child) {
+ if (strcmp(fn, child->name)) {
+ struct device_node *child2;
+
+ /*
+ * This reference is dropped by
+ * of_get_next_child(np, * child)
+ */
+ of_node_get(child);
+
+ /*
+ * The logic parsing the functions from dt currently
+ * doesn't handle if functions with the same name are
+ * not grouped together. Only the first contiguous
+ * cluster is usable for each function name. This is a
+ * bug that is not trivial to fix, but at least warn
+ * about it.
+ */
+ for (child2 = of_get_next_child(np, child);
+ child2 != NULL;
+ child2 = of_get_next_child(np, child2)) {
+ if (!strcmp(child2->name, fn))
+ dev_warn(d->dev,
+ "function nodes must be grouped by name (failed for: %s)",
+ fn);
+ }
+
+ f = &soc->functions[idxf++];
+ f->name = fn = child->name;
+ }
+ f->ngroups++;
+ dev_dbg(d->dev, "function(%d): %s\n", idxf-1, f->name);
+ }
+
+ /* Get groups for each function */
+ idxf = 0;
+ fn = fnull;
+ for_each_child_of_node(np, child) {
+ if (strcmp(fn, child->name)) {
+ f = &soc->functions[idxf++];
+ f->groups = devm_kcalloc(d->dev,
+ f->ngroups,
+ sizeof(*f->groups),
+ GFP_KERNEL);
+ if (!f->groups) {
+ of_node_put(child);
+ return -ENOMEM;
+ }
+ fn = child->name;
+ i = 0;
+ }
+
+ f->groups[i] = child->name;
+ ret = spacemit_pinctrl_parse_groups(child, &soc->groups[idxg++], d, i++);
+ if (ret) {
+ of_node_put(child);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static int spacemit_pinctrl_probe_dt(struct platform_device *pdev,
+ struct spacemit_pinctrl_data *d)
+{
+ struct spacemit_pinctrl_soc_data *soc = d->soc;
+ struct device_node *np = pdev->dev.of_node;
+ struct device_node *child;
+ const char *fn, *fnull = "";
+
+ if (!np)
+ return -ENODEV;
+
+ /* Count total functions and groups */
+ fn = fnull;
+ for_each_child_of_node(np, child) {
+ soc->ngroups++;
+ if (strcmp(fn, child->name)) {
+ fn = child->name;
+ soc->nfunctions++;
+ }
+ }
+
+ if (soc->nfunctions <= 0) {
+ dev_err(&pdev->dev, "It has no functions\n");
+ return -EINVAL;
+ }
+
+ soc->functions = devm_kcalloc(&pdev->dev, soc->nfunctions,
+ sizeof(struct spacemit_function),
+ GFP_KERNEL);
+ if (!soc->functions)
+ return -ENOMEM;
+
+ soc->groups = devm_kcalloc(&pdev->dev, soc->ngroups,
+ sizeof(struct spacemit_group),
+ GFP_KERNEL);
+ if (!soc->groups)
+ return -ENOMEM;
+
+ spacemit_pinctrl_parse_functions(np, d);
+
+ return 0;
+}
+
+int spacemit_pinctrl_probe(struct platform_device *pdev,
+ struct spacemit_pinctrl_soc_data *soc)
+{
+ struct spacemit_pinctrl_data *d;
+ struct resource *res;
+ int ret;
+
+ d = devm_kzalloc(&pdev->dev, sizeof(*d), GFP_KERNEL);
+ if (!d)
+ return -ENOMEM;
+
+ d->dev = &pdev->dev;
+ d->soc = soc;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ d->base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+ if (!d->base)
+ return -EADDRNOTAVAIL;
+
+ spacemit_pinctrl_desc.pins = d->soc->pins;
+ spacemit_pinctrl_desc.npins = d->soc->npins;
+ spacemit_pinctrl_desc.name = dev_name(&pdev->dev);
+
+ platform_set_drvdata(pdev, d);
+
+ d->rstc = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL);
+ if (IS_ERR(d->rstc)) {
+ ret = PTR_ERR(d->rstc);
+ dev_err(&pdev->dev, "failed to get reset.\n");
+ goto err;
+ }
+ reset_control_deassert(d->rstc);
+
+ ret = spacemit_pinctrl_probe_dt(pdev, d);
+ if (ret) {
+ dev_err(&pdev->dev, "dt probe failed: %d\n", ret);
+ goto err;
+ }
+
+ d->pctl = pinctrl_register(&spacemit_pinctrl_desc, &pdev->dev, d);
+ if (IS_ERR(d->pctl)) {
+ dev_err(&pdev->dev, "Couldn't register spacemit pinctrl driver\n");
+ ret = PTR_ERR(d->pctl);
+ goto err;
+ }
+
+ return 0;
+
+err:
+ iounmap(d->base);
+ return ret;
+} \ No newline at end of file
diff --git a/drivers/pinctrl/spacemit/pinctrl-spacemit.h b/drivers/pinctrl/spacemit/pinctrl-spacemit.h
new file mode 100755
index 000000000000..f937ab580528
--- /dev/null
+++ b/drivers/pinctrl/spacemit/pinctrl-spacemit.h
@@ -0,0 +1,104 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) 2023, spacemit Corporation.
+ */
+
+#ifndef __PINCTRL_SPACEMIT_H
+#define __PINCTRL_SPACEMIT_H
+
+#include <linux/platform_device.h>
+#include <linux/pinctrl/pinctrl.h>
+
+#define SPACEMIT_PINCTRL_PIN(pin) PINCTRL_PIN(pin, #pin)
+
+#define PINID_TO_BANK(p) ((p) >> 5)
+#define PINID_TO_PIN(p) ((p) % 32)
+
+/*
+ * pin config bit field definitions
+ * config format
+ * 0-3 driver_strength
+ * 4 pull
+ *
+ * od: open drain
+ * pe: pull enable
+ * st: schmit trigger
+ * rte: retention signal bus
+ *
+ * MSB of each field is presence bit for the config.
+ */
+#define OD_EN 1
+#define OD_DIS 0
+#define PE_EN 1
+#define PE_DIS 0
+#define ST_EN 1
+#define ST_DIS 0
+#define RTE_EN 1
+#define RTE_DIS 0
+
+#define DS_SHIFT 0
+#define PULL_SHIFT 4
+
+#define CONFIG_TO_DS(c) ((c) >> DS_SHIFT & 0xf)
+#define CONFIG_TO_PULL(c) ((c) >> PULL_SHIFT & 0x1)
+
+struct spacemit_function {
+ const char *name;
+ const char **groups;
+ unsigned ngroups;
+};
+
+/*
+ * Each pin represented in spacemit,pins consists:
+ * - u32 PIN_FUNC_ID
+ * - u32 pin muxsel
+ * - u32 pin pull_up/down
+ * - u32 pin driving strength
+ */
+#define SPACEMIT_PIN_SIZE 16
+
+struct spacemit_pin {
+ unsigned int pin_id;
+ u8 muxsel;
+ u8 pull;
+ unsigned long config;
+};
+
+struct spacemit_group {
+ const char *name;
+ unsigned npins;
+ unsigned *pin_ids;
+ struct spacemit_pin *pins;
+};
+
+struct spacemit_regs {
+ u16 cfg;
+ u16 reg_len;
+};
+
+struct spacemit_pin_conf {
+ u8 fs_shift;
+ u8 fs_width;
+ u8 od_shift;
+ u8 pe_shift;
+ u8 pull_shift;
+ u8 ds_shift;
+ u8 st_shift;
+ u8 rte_shift;
+};
+
+struct spacemit_pinctrl_soc_data {
+ const struct spacemit_regs *regs;
+ const struct spacemit_pin_conf *pinconf;
+ const struct pinctrl_pin_desc *pins;
+ unsigned npins;
+ struct spacemit_function *functions;
+ unsigned nfunctions;
+ struct spacemit_group *groups;
+ unsigned ngroups;
+};
+
+int spacemit_pinctrl_probe(struct platform_device *pdev,
+ struct spacemit_pinctrl_soc_data *soc);
+
+#endif /* __PINCTRL_SPACEMIT_H */
diff --git a/include/dt-bindings/pinctrl/k1-x-pinctrl.h b/include/dt-bindings/pinctrl/k1-x-pinctrl.h
new file mode 100644
index 000000000000..90d0ec2caf4a
--- /dev/null
+++ b/include/dt-bindings/pinctrl/k1-x-pinctrl.h
@@ -0,0 +1,198 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#ifndef __DT_BINDINGS_K1X_PINCTRL_H
+#define __DT_BINDINGS_K1X_PINCTRL_H
+
+/* pin offset */
+#define PINID(x) ((x) + 1)
+
+#define GPIO_00 PINID(0)
+#define GPIO_01 PINID(1)
+#define GPIO_02 PINID(2)
+#define GPIO_03 PINID(3)
+#define GPIO_04 PINID(4)
+#define GPIO_05 PINID(5)
+#define GPIO_06 PINID(6)
+#define GPIO_07 PINID(7)
+#define GPIO_08 PINID(8)
+#define GPIO_09 PINID(9)
+#define GPIO_10 PINID(10)
+#define GPIO_11 PINID(11)
+#define GPIO_12 PINID(12)
+#define GPIO_13 PINID(13)
+#define GPIO_14 PINID(14)
+#define GPIO_15 PINID(15)
+#define GPIO_16 PINID(16)
+#define GPIO_17 PINID(17)
+#define GPIO_18 PINID(18)
+#define GPIO_19 PINID(19)
+#define GPIO_20 PINID(20)
+#define GPIO_21 PINID(21)
+#define GPIO_22 PINID(22)
+#define GPIO_23 PINID(23)
+#define GPIO_24 PINID(24)
+#define GPIO_25 PINID(25)
+#define GPIO_26 PINID(26)
+#define GPIO_27 PINID(27)
+#define GPIO_28 PINID(28)
+#define GPIO_29 PINID(29)
+#define GPIO_30 PINID(30)
+#define GPIO_31 PINID(31)
+
+#define GPIO_32 PINID(32)
+#define GPIO_33 PINID(33)
+#define GPIO_34 PINID(34)
+#define GPIO_35 PINID(35)
+#define GPIO_36 PINID(36)
+#define GPIO_37 PINID(37)
+#define GPIO_38 PINID(38)
+#define GPIO_39 PINID(39)
+#define GPIO_40 PINID(40)
+#define GPIO_41 PINID(41)
+#define GPIO_42 PINID(42)
+#define GPIO_43 PINID(43)
+#define GPIO_44 PINID(44)
+#define GPIO_45 PINID(45)
+#define GPIO_46 PINID(46)
+#define GPIO_47 PINID(47)
+#define GPIO_48 PINID(48)
+#define GPIO_49 PINID(49)
+#define GPIO_50 PINID(50)
+#define GPIO_51 PINID(51)
+#define GPIO_52 PINID(52)
+#define GPIO_53 PINID(53)
+#define GPIO_54 PINID(54)
+#define GPIO_55 PINID(55)
+#define GPIO_56 PINID(56)
+#define GPIO_57 PINID(57)
+#define GPIO_58 PINID(58)
+#define GPIO_59 PINID(59)
+#define GPIO_60 PINID(60)
+#define GPIO_61 PINID(61)
+#define GPIO_62 PINID(62)
+#define GPIO_63 PINID(63)
+
+#define GPIO_64 PINID(64)
+#define GPIO_65 PINID(65)
+#define GPIO_66 PINID(66)
+#define GPIO_67 PINID(67)
+#define GPIO_68 PINID(68)
+#define GPIO_69 PINID(69)
+#define PRI_TDI PINID(70)
+#define PRI_TMS PINID(71)
+#define PRI_TCK PINID(72)
+#define PRI_TDO PINID(73)
+#define GPIO_74 PINID(74)
+#define GPIO_75 PINID(75)
+#define GPIO_76 PINID(76)
+#define GPIO_77 PINID(77)
+#define GPIO_78 PINID(78)
+#define GPIO_79 PINID(79)
+#define GPIO_80 PINID(80)
+#define GPIO_81 PINID(81)
+#define GPIO_82 PINID(82)
+#define GPIO_83 PINID(83)
+#define GPIO_84 PINID(84)
+#define GPIO_85 PINID(85)
+
+#define QSPI_DAT0 PINID(89)
+#define QSPI_DAT1 PINID(90)
+#define QSPI_DAT2 PINID(91)
+#define QSPI_DAT3 PINID(92)
+#define QSPI_CSI PINID(93)
+#define QSPI_CLK PINID(94)
+
+#define MMC1_DAT3 PINID(109)
+#define MMC1_DAT2 PINID(110)
+#define MMC1_DAT1 PINID(111)
+#define MMC1_DAT0 PINID(112)
+#define MMC1_CMD PINID(113)
+#define MMC1_CLK PINID(114)
+#define GPIO_110 PINID(115)
+#define PWR_SCL PINID(116)
+#define PWR_SDA PINID(117)
+#define VCXO_EN PINID(118)
+#define DVL0 PINID(119)
+#define DVL1 PINID(120)
+#define PMIC_INT_N PINID(121)
+#define GPIO_86 PINID(122)
+#define GPIO_87 PINID(123)
+#define GPIO_88 PINID(124)
+#define GPIO_89 PINID(125)
+#define GPIO_90 PINID(126)
+#define GPIO_91 PINID(127)
+#define GPIO_92 PINID(128)
+
+#define GPIO_111 PINID(130)
+#define GPIO_112 PINID(131)
+#define GPIO_113 PINID(132)
+#define GPIO_114 PINID(133)
+#define GPIO_115 PINID(134)
+#define GPIO_116 PINID(135)
+#define GPIO_117 PINID(136)
+#define GPIO_118 PINID(137)
+#define GPIO_119 PINID(138)
+#define GPIO_120 PINID(139)
+#define GPIO_121 PINID(140)
+#define GPIO_122 PINID(141)
+#define GPIO_123 PINID(142)
+#define GPIO_124 PINID(143)
+#define GPIO_125 PINID(144)
+#define GPIO_126 PINID(145)
+#define GPIO_127 PINID(146)
+
+/* pin mux */
+#define MUX_MODE0 0
+#define MUX_MODE1 1
+#define MUX_MODE2 2
+#define MUX_MODE3 3
+#define MUX_MODE4 4
+#define MUX_MODE5 5
+#define MUX_MODE6 6
+#define MUX_MODE7 7
+
+/* strong pull resistor */
+#define SPU_EN (1 << 3)
+
+/* edge detect */
+#define EDGE_NONE (1 << 6)
+#define EDGE_RISE (1 << 4)
+#define EDGE_FALL (1 << 5)
+#define EDGE_BOTH (3 << 4)
+
+/* slew rate output control */
+#define SLE_EN (1 << 7)
+
+/* schmitter trigger input threshhold */
+#define ST00 (0 << 8)
+#define ST01 (1 << 8)
+#define ST02 (2 << 8)
+#define ST03 (3 << 8)
+
+/* driver strength*/
+#define PAD_1V8_DS0 (0 << 11)
+#define PAD_1V8_DS1 (1 << 11)
+#define PAD_1V8_DS2 (2 << 11)
+#define PAD_1V8_DS3 (3 << 11)
+
+/*
+ * notice: !!!
+ * ds2 ---> bit10, ds1 ----> bit12, ds0 ----> bit11
+*/
+#define PAD_3V_DS0 (0 << 10) /* bit[12:10] 000 */
+#define PAD_3V_DS1 (2 << 10) /* bit[12:10] 010 */
+#define PAD_3V_DS2 (4 << 10) /* bit[12:10] 100 */
+#define PAD_3V_DS3 (6 << 10) /* bit[12:10] 110 */
+#define PAD_3V_DS4 (1 << 10) /* bit[12:10] 001 */
+#define PAD_3V_DS5 (3 << 10) /* bit[12:10] 011 */
+#define PAD_3V_DS6 (5 << 10) /* bit[12:10] 101 */
+#define PAD_3V_DS7 (7 << 10) /* bit[12:10] 111 */
+
+/* pull up/down */
+#define PULL_DIS (0 << 13) /* bit[15:13] 000 */
+#define PULL_UP (6 << 13) /* bit[15:13] 110 */
+#define PULL_DOWN (5 << 13) /* bit[15:13] 101 */
+
+#define K1X_PADCONF(pinid, conf, mux) ((pinid) * 4) (conf) (mux)
+
+#endif /* __DT_BINDINGS_K1PRO_PINCTRL_H */