162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Renesas RZ/V2M Pin Control and GPIO driver core
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Based on:
662306a36Sopenharmony_ci *   Renesas RZ/G2L Pin Control and GPIO driver core
762306a36Sopenharmony_ci *
862306a36Sopenharmony_ci * Copyright (C) 2022 Renesas Electronics Corporation.
962306a36Sopenharmony_ci */
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci#include <linux/bitfield.h>
1262306a36Sopenharmony_ci#include <linux/bitops.h>
1362306a36Sopenharmony_ci#include <linux/clk.h>
1462306a36Sopenharmony_ci#include <linux/gpio/driver.h>
1562306a36Sopenharmony_ci#include <linux/io.h>
1662306a36Sopenharmony_ci#include <linux/module.h>
1762306a36Sopenharmony_ci#include <linux/mutex.h>
1862306a36Sopenharmony_ci#include <linux/of.h>
1962306a36Sopenharmony_ci#include <linux/platform_device.h>
2062306a36Sopenharmony_ci#include <linux/spinlock.h>
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci#include <linux/pinctrl/consumer.h>
2362306a36Sopenharmony_ci#include <linux/pinctrl/pinconf-generic.h>
2462306a36Sopenharmony_ci#include <linux/pinctrl/pinconf.h>
2562306a36Sopenharmony_ci#include <linux/pinctrl/pinctrl.h>
2662306a36Sopenharmony_ci#include <linux/pinctrl/pinmux.h>
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci#include <dt-bindings/pinctrl/rzv2m-pinctrl.h>
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci#include "../core.h"
3162306a36Sopenharmony_ci#include "../pinconf.h"
3262306a36Sopenharmony_ci#include "../pinmux.h"
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci#define DRV_NAME	"pinctrl-rzv2m"
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci/*
3762306a36Sopenharmony_ci * Use 16 lower bits [15:0] for pin identifier
3862306a36Sopenharmony_ci * Use 16 higher bits [31:16] for pin mux function
3962306a36Sopenharmony_ci */
4062306a36Sopenharmony_ci#define MUX_PIN_ID_MASK		GENMASK(15, 0)
4162306a36Sopenharmony_ci#define MUX_FUNC_MASK		GENMASK(31, 16)
4262306a36Sopenharmony_ci#define MUX_FUNC(pinconf)	FIELD_GET(MUX_FUNC_MASK, (pinconf))
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci/* PIN capabilities */
4562306a36Sopenharmony_ci#define PIN_CFG_GRP_1_8V_2		1
4662306a36Sopenharmony_ci#define PIN_CFG_GRP_1_8V_3		2
4762306a36Sopenharmony_ci#define PIN_CFG_GRP_SWIO_1		3
4862306a36Sopenharmony_ci#define PIN_CFG_GRP_SWIO_2		4
4962306a36Sopenharmony_ci#define PIN_CFG_GRP_3_3V		5
5062306a36Sopenharmony_ci#define PIN_CFG_GRP_MASK		GENMASK(2, 0)
5162306a36Sopenharmony_ci#define PIN_CFG_BIAS			BIT(3)
5262306a36Sopenharmony_ci#define PIN_CFG_DRV			BIT(4)
5362306a36Sopenharmony_ci#define PIN_CFG_SLEW			BIT(5)
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci#define RZV2M_MPXED_PIN_FUNCS		(PIN_CFG_BIAS | \
5662306a36Sopenharmony_ci					 PIN_CFG_DRV | \
5762306a36Sopenharmony_ci					 PIN_CFG_SLEW)
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_ci/*
6062306a36Sopenharmony_ci * n indicates number of pins in the port, a is the register index
6162306a36Sopenharmony_ci * and f is pin configuration capabilities supported.
6262306a36Sopenharmony_ci */
6362306a36Sopenharmony_ci#define RZV2M_GPIO_PORT_PACK(n, a, f)	(((n) << 24) | ((a) << 16) | (f))
6462306a36Sopenharmony_ci#define RZV2M_GPIO_PORT_GET_PINCNT(x)	FIELD_GET(GENMASK(31, 24), (x))
6562306a36Sopenharmony_ci#define RZV2M_GPIO_PORT_GET_INDEX(x)	FIELD_GET(GENMASK(23, 16), (x))
6662306a36Sopenharmony_ci#define RZV2M_GPIO_PORT_GET_CFGS(x)	FIELD_GET(GENMASK(15, 0), (x))
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci#define RZV2M_DEDICATED_PORT_IDX	22
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci/*
7162306a36Sopenharmony_ci * BIT(31) indicates dedicated pin, b is the register bits (b * 16)
7262306a36Sopenharmony_ci * and f is the pin configuration capabilities supported.
7362306a36Sopenharmony_ci */
7462306a36Sopenharmony_ci#define RZV2M_SINGLE_PIN		BIT(31)
7562306a36Sopenharmony_ci#define RZV2M_SINGLE_PIN_PACK(b, f)	(RZV2M_SINGLE_PIN | \
7662306a36Sopenharmony_ci					 ((RZV2M_DEDICATED_PORT_IDX) << 24) | \
7762306a36Sopenharmony_ci					 ((b) << 16) | (f))
7862306a36Sopenharmony_ci#define RZV2M_SINGLE_PIN_GET_PORT(x)	FIELD_GET(GENMASK(30, 24), (x))
7962306a36Sopenharmony_ci#define RZV2M_SINGLE_PIN_GET_BIT(x)	FIELD_GET(GENMASK(23, 16), (x))
8062306a36Sopenharmony_ci#define RZV2M_SINGLE_PIN_GET_CFGS(x)	FIELD_GET(GENMASK(15, 0), (x))
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ci#define RZV2M_PIN_ID_TO_PORT(id)	((id) / RZV2M_PINS_PER_PORT)
8362306a36Sopenharmony_ci#define RZV2M_PIN_ID_TO_PIN(id)		((id) % RZV2M_PINS_PER_PORT)
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ci#define DO(n)		(0x00 + (n) * 0x40)
8662306a36Sopenharmony_ci#define OE(n)		(0x04 + (n) * 0x40)
8762306a36Sopenharmony_ci#define IE(n)		(0x08 + (n) * 0x40)
8862306a36Sopenharmony_ci#define PFSEL(n)	(0x10 + (n) * 0x40)
8962306a36Sopenharmony_ci#define DI(n)		(0x20 + (n) * 0x40)
9062306a36Sopenharmony_ci#define PUPD(n)		(0x24 + (n) * 0x40)
9162306a36Sopenharmony_ci#define DRV(n)		((n) < RZV2M_DEDICATED_PORT_IDX ? (0x28 + (n) * 0x40) \
9262306a36Sopenharmony_ci							: 0x590)
9362306a36Sopenharmony_ci#define SR(n)		((n) < RZV2M_DEDICATED_PORT_IDX ? (0x2c + (n) * 0x40) \
9462306a36Sopenharmony_ci							: 0x594)
9562306a36Sopenharmony_ci#define DI_MSK(n)	(0x30 + (n) * 0x40)
9662306a36Sopenharmony_ci#define EN_MSK(n)	(0x34 + (n) * 0x40)
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_ci#define PFC_MASK	0x07
9962306a36Sopenharmony_ci#define PUPD_MASK	0x03
10062306a36Sopenharmony_ci#define DRV_MASK	0x03
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_cistruct rzv2m_dedicated_configs {
10362306a36Sopenharmony_ci	const char *name;
10462306a36Sopenharmony_ci	u32 config;
10562306a36Sopenharmony_ci};
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_cistruct rzv2m_pinctrl_data {
10862306a36Sopenharmony_ci	const char * const *port_pins;
10962306a36Sopenharmony_ci	const u32 *port_pin_configs;
11062306a36Sopenharmony_ci	const struct rzv2m_dedicated_configs *dedicated_pins;
11162306a36Sopenharmony_ci	unsigned int n_port_pins;
11262306a36Sopenharmony_ci	unsigned int n_dedicated_pins;
11362306a36Sopenharmony_ci};
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_cistruct rzv2m_pinctrl {
11662306a36Sopenharmony_ci	struct pinctrl_dev		*pctl;
11762306a36Sopenharmony_ci	struct pinctrl_desc		desc;
11862306a36Sopenharmony_ci	struct pinctrl_pin_desc		*pins;
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ci	const struct rzv2m_pinctrl_data	*data;
12162306a36Sopenharmony_ci	void __iomem			*base;
12262306a36Sopenharmony_ci	struct device			*dev;
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_ci	struct gpio_chip		gpio_chip;
12562306a36Sopenharmony_ci	struct pinctrl_gpio_range	gpio_range;
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci	spinlock_t			lock; /* lock read/write registers */
12862306a36Sopenharmony_ci	struct mutex			mutex; /* serialize adding groups and functions */
12962306a36Sopenharmony_ci};
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_cistatic const unsigned int drv_1_8V_group2_uA[] = { 1800, 3800, 7800, 11000 };
13262306a36Sopenharmony_cistatic const unsigned int drv_1_8V_group3_uA[] = { 1600, 3200, 6400, 9600 };
13362306a36Sopenharmony_cistatic const unsigned int drv_SWIO_group2_3_3V_uA[] = { 9000, 11000, 13000, 18000 };
13462306a36Sopenharmony_cistatic const unsigned int drv_3_3V_group_uA[] = { 2000, 4000, 8000, 12000 };
13562306a36Sopenharmony_ci
13662306a36Sopenharmony_ci/* Helper for registers that have a write enable bit in the upper word */
13762306a36Sopenharmony_cistatic void rzv2m_writel_we(void __iomem *addr, u8 shift, u8 value)
13862306a36Sopenharmony_ci{
13962306a36Sopenharmony_ci	writel((BIT(16) | value) << shift, addr);
14062306a36Sopenharmony_ci}
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_cistatic void rzv2m_pinctrl_set_pfc_mode(struct rzv2m_pinctrl *pctrl,
14362306a36Sopenharmony_ci				       u8 port, u8 pin, u8 func)
14462306a36Sopenharmony_ci{
14562306a36Sopenharmony_ci	void __iomem *addr;
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_ci	/* Mask input/output */
14862306a36Sopenharmony_ci	rzv2m_writel_we(pctrl->base + DI_MSK(port), pin, 1);
14962306a36Sopenharmony_ci	rzv2m_writel_we(pctrl->base + EN_MSK(port), pin, 1);
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_ci	/* Select the function and set the write enable bits */
15262306a36Sopenharmony_ci	addr = pctrl->base + PFSEL(port) + (pin / 4) * 4;
15362306a36Sopenharmony_ci	writel(((PFC_MASK << 16) | func) << ((pin % 4) * 4), addr);
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_ci	/* Unmask input/output */
15662306a36Sopenharmony_ci	rzv2m_writel_we(pctrl->base + EN_MSK(port), pin, 0);
15762306a36Sopenharmony_ci	rzv2m_writel_we(pctrl->base + DI_MSK(port), pin, 0);
15862306a36Sopenharmony_ci};
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_cistatic int rzv2m_pinctrl_set_mux(struct pinctrl_dev *pctldev,
16162306a36Sopenharmony_ci				 unsigned int func_selector,
16262306a36Sopenharmony_ci				 unsigned int group_selector)
16362306a36Sopenharmony_ci{
16462306a36Sopenharmony_ci	struct rzv2m_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
16562306a36Sopenharmony_ci	struct function_desc *func;
16662306a36Sopenharmony_ci	unsigned int i, *psel_val;
16762306a36Sopenharmony_ci	struct group_desc *group;
16862306a36Sopenharmony_ci	int *pins;
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_ci	func = pinmux_generic_get_function(pctldev, func_selector);
17162306a36Sopenharmony_ci	if (!func)
17262306a36Sopenharmony_ci		return -EINVAL;
17362306a36Sopenharmony_ci	group = pinctrl_generic_get_group(pctldev, group_selector);
17462306a36Sopenharmony_ci	if (!group)
17562306a36Sopenharmony_ci		return -EINVAL;
17662306a36Sopenharmony_ci
17762306a36Sopenharmony_ci	psel_val = func->data;
17862306a36Sopenharmony_ci	pins = group->pins;
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_ci	for (i = 0; i < group->num_pins; i++) {
18162306a36Sopenharmony_ci		dev_dbg(pctrl->dev, "port:%u pin: %u PSEL:%u\n",
18262306a36Sopenharmony_ci			RZV2M_PIN_ID_TO_PORT(pins[i]), RZV2M_PIN_ID_TO_PIN(pins[i]),
18362306a36Sopenharmony_ci			psel_val[i]);
18462306a36Sopenharmony_ci		rzv2m_pinctrl_set_pfc_mode(pctrl, RZV2M_PIN_ID_TO_PORT(pins[i]),
18562306a36Sopenharmony_ci					   RZV2M_PIN_ID_TO_PIN(pins[i]), psel_val[i]);
18662306a36Sopenharmony_ci	}
18762306a36Sopenharmony_ci
18862306a36Sopenharmony_ci	return 0;
18962306a36Sopenharmony_ci};
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_cistatic int rzv2m_map_add_config(struct pinctrl_map *map,
19262306a36Sopenharmony_ci				const char *group_or_pin,
19362306a36Sopenharmony_ci				enum pinctrl_map_type type,
19462306a36Sopenharmony_ci				unsigned long *configs,
19562306a36Sopenharmony_ci				unsigned int num_configs)
19662306a36Sopenharmony_ci{
19762306a36Sopenharmony_ci	unsigned long *cfgs;
19862306a36Sopenharmony_ci
19962306a36Sopenharmony_ci	cfgs = kmemdup(configs, num_configs * sizeof(*cfgs),
20062306a36Sopenharmony_ci		       GFP_KERNEL);
20162306a36Sopenharmony_ci	if (!cfgs)
20262306a36Sopenharmony_ci		return -ENOMEM;
20362306a36Sopenharmony_ci
20462306a36Sopenharmony_ci	map->type = type;
20562306a36Sopenharmony_ci	map->data.configs.group_or_pin = group_or_pin;
20662306a36Sopenharmony_ci	map->data.configs.configs = cfgs;
20762306a36Sopenharmony_ci	map->data.configs.num_configs = num_configs;
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_ci	return 0;
21062306a36Sopenharmony_ci}
21162306a36Sopenharmony_ci
21262306a36Sopenharmony_cistatic int rzv2m_dt_subnode_to_map(struct pinctrl_dev *pctldev,
21362306a36Sopenharmony_ci				   struct device_node *np,
21462306a36Sopenharmony_ci				   struct device_node *parent,
21562306a36Sopenharmony_ci				   struct pinctrl_map **map,
21662306a36Sopenharmony_ci				   unsigned int *num_maps,
21762306a36Sopenharmony_ci				   unsigned int *index)
21862306a36Sopenharmony_ci{
21962306a36Sopenharmony_ci	struct rzv2m_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
22062306a36Sopenharmony_ci	struct pinctrl_map *maps = *map;
22162306a36Sopenharmony_ci	unsigned int nmaps = *num_maps;
22262306a36Sopenharmony_ci	unsigned long *configs = NULL;
22362306a36Sopenharmony_ci	unsigned int *pins, *psel_val;
22462306a36Sopenharmony_ci	unsigned int num_pinmux = 0;
22562306a36Sopenharmony_ci	unsigned int idx = *index;
22662306a36Sopenharmony_ci	unsigned int num_pins, i;
22762306a36Sopenharmony_ci	unsigned int num_configs;
22862306a36Sopenharmony_ci	struct property *pinmux;
22962306a36Sopenharmony_ci	struct property *prop;
23062306a36Sopenharmony_ci	int ret, gsel, fsel;
23162306a36Sopenharmony_ci	const char **pin_fn;
23262306a36Sopenharmony_ci	const char *name;
23362306a36Sopenharmony_ci	const char *pin;
23462306a36Sopenharmony_ci
23562306a36Sopenharmony_ci	pinmux = of_find_property(np, "pinmux", NULL);
23662306a36Sopenharmony_ci	if (pinmux)
23762306a36Sopenharmony_ci		num_pinmux = pinmux->length / sizeof(u32);
23862306a36Sopenharmony_ci
23962306a36Sopenharmony_ci	ret = of_property_count_strings(np, "pins");
24062306a36Sopenharmony_ci	if (ret == -EINVAL) {
24162306a36Sopenharmony_ci		num_pins = 0;
24262306a36Sopenharmony_ci	} else if (ret < 0) {
24362306a36Sopenharmony_ci		dev_err(pctrl->dev, "Invalid pins list in DT\n");
24462306a36Sopenharmony_ci		return ret;
24562306a36Sopenharmony_ci	} else {
24662306a36Sopenharmony_ci		num_pins = ret;
24762306a36Sopenharmony_ci	}
24862306a36Sopenharmony_ci
24962306a36Sopenharmony_ci	if (!num_pinmux && !num_pins)
25062306a36Sopenharmony_ci		return 0;
25162306a36Sopenharmony_ci
25262306a36Sopenharmony_ci	if (num_pinmux && num_pins) {
25362306a36Sopenharmony_ci		dev_err(pctrl->dev,
25462306a36Sopenharmony_ci			"DT node must contain either a pinmux or pins and not both\n");
25562306a36Sopenharmony_ci		return -EINVAL;
25662306a36Sopenharmony_ci	}
25762306a36Sopenharmony_ci
25862306a36Sopenharmony_ci	ret = pinconf_generic_parse_dt_config(np, NULL, &configs, &num_configs);
25962306a36Sopenharmony_ci	if (ret < 0)
26062306a36Sopenharmony_ci		return ret;
26162306a36Sopenharmony_ci
26262306a36Sopenharmony_ci	if (num_pins && !num_configs) {
26362306a36Sopenharmony_ci		dev_err(pctrl->dev, "DT node must contain a config\n");
26462306a36Sopenharmony_ci		ret = -ENODEV;
26562306a36Sopenharmony_ci		goto done;
26662306a36Sopenharmony_ci	}
26762306a36Sopenharmony_ci
26862306a36Sopenharmony_ci	if (num_pinmux)
26962306a36Sopenharmony_ci		nmaps += 1;
27062306a36Sopenharmony_ci
27162306a36Sopenharmony_ci	if (num_pins)
27262306a36Sopenharmony_ci		nmaps += num_pins;
27362306a36Sopenharmony_ci
27462306a36Sopenharmony_ci	maps = krealloc_array(maps, nmaps, sizeof(*maps), GFP_KERNEL);
27562306a36Sopenharmony_ci	if (!maps) {
27662306a36Sopenharmony_ci		ret = -ENOMEM;
27762306a36Sopenharmony_ci		goto done;
27862306a36Sopenharmony_ci	}
27962306a36Sopenharmony_ci
28062306a36Sopenharmony_ci	*map = maps;
28162306a36Sopenharmony_ci	*num_maps = nmaps;
28262306a36Sopenharmony_ci	if (num_pins) {
28362306a36Sopenharmony_ci		of_property_for_each_string(np, "pins", prop, pin) {
28462306a36Sopenharmony_ci			ret = rzv2m_map_add_config(&maps[idx], pin,
28562306a36Sopenharmony_ci						   PIN_MAP_TYPE_CONFIGS_PIN,
28662306a36Sopenharmony_ci						   configs, num_configs);
28762306a36Sopenharmony_ci			if (ret < 0)
28862306a36Sopenharmony_ci				goto done;
28962306a36Sopenharmony_ci
29062306a36Sopenharmony_ci			idx++;
29162306a36Sopenharmony_ci		}
29262306a36Sopenharmony_ci		ret = 0;
29362306a36Sopenharmony_ci		goto done;
29462306a36Sopenharmony_ci	}
29562306a36Sopenharmony_ci
29662306a36Sopenharmony_ci	pins = devm_kcalloc(pctrl->dev, num_pinmux, sizeof(*pins), GFP_KERNEL);
29762306a36Sopenharmony_ci	psel_val = devm_kcalloc(pctrl->dev, num_pinmux, sizeof(*psel_val),
29862306a36Sopenharmony_ci				GFP_KERNEL);
29962306a36Sopenharmony_ci	pin_fn = devm_kzalloc(pctrl->dev, sizeof(*pin_fn), GFP_KERNEL);
30062306a36Sopenharmony_ci	if (!pins || !psel_val || !pin_fn) {
30162306a36Sopenharmony_ci		ret = -ENOMEM;
30262306a36Sopenharmony_ci		goto done;
30362306a36Sopenharmony_ci	}
30462306a36Sopenharmony_ci
30562306a36Sopenharmony_ci	/* Collect pin locations and mux settings from DT properties */
30662306a36Sopenharmony_ci	for (i = 0; i < num_pinmux; ++i) {
30762306a36Sopenharmony_ci		u32 value;
30862306a36Sopenharmony_ci
30962306a36Sopenharmony_ci		ret = of_property_read_u32_index(np, "pinmux", i, &value);
31062306a36Sopenharmony_ci		if (ret)
31162306a36Sopenharmony_ci			goto done;
31262306a36Sopenharmony_ci		pins[i] = value & MUX_PIN_ID_MASK;
31362306a36Sopenharmony_ci		psel_val[i] = MUX_FUNC(value);
31462306a36Sopenharmony_ci	}
31562306a36Sopenharmony_ci
31662306a36Sopenharmony_ci	if (parent) {
31762306a36Sopenharmony_ci		name = devm_kasprintf(pctrl->dev, GFP_KERNEL, "%pOFn.%pOFn",
31862306a36Sopenharmony_ci				      parent, np);
31962306a36Sopenharmony_ci		if (!name) {
32062306a36Sopenharmony_ci			ret = -ENOMEM;
32162306a36Sopenharmony_ci			goto done;
32262306a36Sopenharmony_ci		}
32362306a36Sopenharmony_ci	} else {
32462306a36Sopenharmony_ci		name = np->name;
32562306a36Sopenharmony_ci	}
32662306a36Sopenharmony_ci
32762306a36Sopenharmony_ci	mutex_lock(&pctrl->mutex);
32862306a36Sopenharmony_ci
32962306a36Sopenharmony_ci	/* Register a single pin group listing all the pins we read from DT */
33062306a36Sopenharmony_ci	gsel = pinctrl_generic_add_group(pctldev, name, pins, num_pinmux, NULL);
33162306a36Sopenharmony_ci	if (gsel < 0) {
33262306a36Sopenharmony_ci		ret = gsel;
33362306a36Sopenharmony_ci		goto unlock;
33462306a36Sopenharmony_ci	}
33562306a36Sopenharmony_ci
33662306a36Sopenharmony_ci	/*
33762306a36Sopenharmony_ci	 * Register a single group function where the 'data' is an array PSEL
33862306a36Sopenharmony_ci	 * register values read from DT.
33962306a36Sopenharmony_ci	 */
34062306a36Sopenharmony_ci	pin_fn[0] = name;
34162306a36Sopenharmony_ci	fsel = pinmux_generic_add_function(pctldev, name, pin_fn, 1, psel_val);
34262306a36Sopenharmony_ci	if (fsel < 0) {
34362306a36Sopenharmony_ci		ret = fsel;
34462306a36Sopenharmony_ci		goto remove_group;
34562306a36Sopenharmony_ci	}
34662306a36Sopenharmony_ci
34762306a36Sopenharmony_ci	mutex_unlock(&pctrl->mutex);
34862306a36Sopenharmony_ci
34962306a36Sopenharmony_ci	maps[idx].type = PIN_MAP_TYPE_MUX_GROUP;
35062306a36Sopenharmony_ci	maps[idx].data.mux.group = name;
35162306a36Sopenharmony_ci	maps[idx].data.mux.function = name;
35262306a36Sopenharmony_ci	idx++;
35362306a36Sopenharmony_ci
35462306a36Sopenharmony_ci	dev_dbg(pctrl->dev, "Parsed %pOF with %d pins\n", np, num_pinmux);
35562306a36Sopenharmony_ci	ret = 0;
35662306a36Sopenharmony_ci	goto done;
35762306a36Sopenharmony_ci
35862306a36Sopenharmony_ciremove_group:
35962306a36Sopenharmony_ci	pinctrl_generic_remove_group(pctldev, gsel);
36062306a36Sopenharmony_ciunlock:
36162306a36Sopenharmony_ci	mutex_unlock(&pctrl->mutex);
36262306a36Sopenharmony_cidone:
36362306a36Sopenharmony_ci	*index = idx;
36462306a36Sopenharmony_ci	kfree(configs);
36562306a36Sopenharmony_ci	return ret;
36662306a36Sopenharmony_ci}
36762306a36Sopenharmony_ci
36862306a36Sopenharmony_cistatic void rzv2m_dt_free_map(struct pinctrl_dev *pctldev,
36962306a36Sopenharmony_ci			      struct pinctrl_map *map,
37062306a36Sopenharmony_ci			      unsigned int num_maps)
37162306a36Sopenharmony_ci{
37262306a36Sopenharmony_ci	unsigned int i;
37362306a36Sopenharmony_ci
37462306a36Sopenharmony_ci	if (!map)
37562306a36Sopenharmony_ci		return;
37662306a36Sopenharmony_ci
37762306a36Sopenharmony_ci	for (i = 0; i < num_maps; ++i) {
37862306a36Sopenharmony_ci		if (map[i].type == PIN_MAP_TYPE_CONFIGS_GROUP ||
37962306a36Sopenharmony_ci		    map[i].type == PIN_MAP_TYPE_CONFIGS_PIN)
38062306a36Sopenharmony_ci			kfree(map[i].data.configs.configs);
38162306a36Sopenharmony_ci	}
38262306a36Sopenharmony_ci	kfree(map);
38362306a36Sopenharmony_ci}
38462306a36Sopenharmony_ci
38562306a36Sopenharmony_cistatic int rzv2m_dt_node_to_map(struct pinctrl_dev *pctldev,
38662306a36Sopenharmony_ci				struct device_node *np,
38762306a36Sopenharmony_ci				struct pinctrl_map **map,
38862306a36Sopenharmony_ci				unsigned int *num_maps)
38962306a36Sopenharmony_ci{
39062306a36Sopenharmony_ci	struct rzv2m_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
39162306a36Sopenharmony_ci	struct device_node *child;
39262306a36Sopenharmony_ci	unsigned int index;
39362306a36Sopenharmony_ci	int ret;
39462306a36Sopenharmony_ci
39562306a36Sopenharmony_ci	*map = NULL;
39662306a36Sopenharmony_ci	*num_maps = 0;
39762306a36Sopenharmony_ci	index = 0;
39862306a36Sopenharmony_ci
39962306a36Sopenharmony_ci	for_each_child_of_node(np, child) {
40062306a36Sopenharmony_ci		ret = rzv2m_dt_subnode_to_map(pctldev, child, np, map,
40162306a36Sopenharmony_ci					      num_maps, &index);
40262306a36Sopenharmony_ci		if (ret < 0) {
40362306a36Sopenharmony_ci			of_node_put(child);
40462306a36Sopenharmony_ci			goto done;
40562306a36Sopenharmony_ci		}
40662306a36Sopenharmony_ci	}
40762306a36Sopenharmony_ci
40862306a36Sopenharmony_ci	if (*num_maps == 0) {
40962306a36Sopenharmony_ci		ret = rzv2m_dt_subnode_to_map(pctldev, np, NULL, map,
41062306a36Sopenharmony_ci					      num_maps, &index);
41162306a36Sopenharmony_ci		if (ret < 0)
41262306a36Sopenharmony_ci			goto done;
41362306a36Sopenharmony_ci	}
41462306a36Sopenharmony_ci
41562306a36Sopenharmony_ci	if (*num_maps)
41662306a36Sopenharmony_ci		return 0;
41762306a36Sopenharmony_ci
41862306a36Sopenharmony_ci	dev_err(pctrl->dev, "no mapping found in node %pOF\n", np);
41962306a36Sopenharmony_ci	ret = -EINVAL;
42062306a36Sopenharmony_ci
42162306a36Sopenharmony_cidone:
42262306a36Sopenharmony_ci	rzv2m_dt_free_map(pctldev, *map, *num_maps);
42362306a36Sopenharmony_ci
42462306a36Sopenharmony_ci	return ret;
42562306a36Sopenharmony_ci}
42662306a36Sopenharmony_ci
42762306a36Sopenharmony_cistatic int rzv2m_validate_gpio_pin(struct rzv2m_pinctrl *pctrl,
42862306a36Sopenharmony_ci				   u32 cfg, u32 port, u8 bit)
42962306a36Sopenharmony_ci{
43062306a36Sopenharmony_ci	u8 pincount = RZV2M_GPIO_PORT_GET_PINCNT(cfg);
43162306a36Sopenharmony_ci	u32 port_index = RZV2M_GPIO_PORT_GET_INDEX(cfg);
43262306a36Sopenharmony_ci	u32 data;
43362306a36Sopenharmony_ci
43462306a36Sopenharmony_ci	if (bit >= pincount || port >= pctrl->data->n_port_pins)
43562306a36Sopenharmony_ci		return -EINVAL;
43662306a36Sopenharmony_ci
43762306a36Sopenharmony_ci	data = pctrl->data->port_pin_configs[port];
43862306a36Sopenharmony_ci	if (port_index != RZV2M_GPIO_PORT_GET_INDEX(data))
43962306a36Sopenharmony_ci		return -EINVAL;
44062306a36Sopenharmony_ci
44162306a36Sopenharmony_ci	return 0;
44262306a36Sopenharmony_ci}
44362306a36Sopenharmony_ci
44462306a36Sopenharmony_cistatic void rzv2m_rmw_pin_config(struct rzv2m_pinctrl *pctrl, u32 offset,
44562306a36Sopenharmony_ci				 u8 shift, u32 mask, u32 val)
44662306a36Sopenharmony_ci{
44762306a36Sopenharmony_ci	void __iomem *addr = pctrl->base + offset;
44862306a36Sopenharmony_ci	unsigned long flags;
44962306a36Sopenharmony_ci	u32 reg;
45062306a36Sopenharmony_ci
45162306a36Sopenharmony_ci	spin_lock_irqsave(&pctrl->lock, flags);
45262306a36Sopenharmony_ci	reg = readl(addr) & ~(mask << shift);
45362306a36Sopenharmony_ci	writel(reg | (val << shift), addr);
45462306a36Sopenharmony_ci	spin_unlock_irqrestore(&pctrl->lock, flags);
45562306a36Sopenharmony_ci}
45662306a36Sopenharmony_ci
45762306a36Sopenharmony_cistatic int rzv2m_pinctrl_pinconf_get(struct pinctrl_dev *pctldev,
45862306a36Sopenharmony_ci				     unsigned int _pin,
45962306a36Sopenharmony_ci				     unsigned long *config)
46062306a36Sopenharmony_ci{
46162306a36Sopenharmony_ci	struct rzv2m_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
46262306a36Sopenharmony_ci	enum pin_config_param param = pinconf_to_config_param(*config);
46362306a36Sopenharmony_ci	const struct pinctrl_pin_desc *pin = &pctrl->desc.pins[_pin];
46462306a36Sopenharmony_ci	unsigned int *pin_data = pin->drv_data;
46562306a36Sopenharmony_ci	unsigned int arg = 0;
46662306a36Sopenharmony_ci	u32 port;
46762306a36Sopenharmony_ci	u32 cfg;
46862306a36Sopenharmony_ci	u8 bit;
46962306a36Sopenharmony_ci	u32 val;
47062306a36Sopenharmony_ci
47162306a36Sopenharmony_ci	if (!pin_data)
47262306a36Sopenharmony_ci		return -EINVAL;
47362306a36Sopenharmony_ci
47462306a36Sopenharmony_ci	if (*pin_data & RZV2M_SINGLE_PIN) {
47562306a36Sopenharmony_ci		port = RZV2M_SINGLE_PIN_GET_PORT(*pin_data);
47662306a36Sopenharmony_ci		cfg = RZV2M_SINGLE_PIN_GET_CFGS(*pin_data);
47762306a36Sopenharmony_ci		bit = RZV2M_SINGLE_PIN_GET_BIT(*pin_data);
47862306a36Sopenharmony_ci	} else {
47962306a36Sopenharmony_ci		cfg = RZV2M_GPIO_PORT_GET_CFGS(*pin_data);
48062306a36Sopenharmony_ci		port = RZV2M_PIN_ID_TO_PORT(_pin);
48162306a36Sopenharmony_ci		bit = RZV2M_PIN_ID_TO_PIN(_pin);
48262306a36Sopenharmony_ci
48362306a36Sopenharmony_ci		if (rzv2m_validate_gpio_pin(pctrl, *pin_data, RZV2M_PIN_ID_TO_PORT(_pin), bit))
48462306a36Sopenharmony_ci			return -EINVAL;
48562306a36Sopenharmony_ci	}
48662306a36Sopenharmony_ci
48762306a36Sopenharmony_ci	switch (param) {
48862306a36Sopenharmony_ci	case PIN_CONFIG_BIAS_DISABLE:
48962306a36Sopenharmony_ci	case PIN_CONFIG_BIAS_PULL_UP:
49062306a36Sopenharmony_ci	case PIN_CONFIG_BIAS_PULL_DOWN: {
49162306a36Sopenharmony_ci		enum pin_config_param bias;
49262306a36Sopenharmony_ci
49362306a36Sopenharmony_ci		if (!(cfg & PIN_CFG_BIAS))
49462306a36Sopenharmony_ci			return -EINVAL;
49562306a36Sopenharmony_ci
49662306a36Sopenharmony_ci		/* PUPD uses 2-bits per pin */
49762306a36Sopenharmony_ci		bit *= 2;
49862306a36Sopenharmony_ci
49962306a36Sopenharmony_ci		switch ((readl(pctrl->base + PUPD(port)) >> bit) & PUPD_MASK) {
50062306a36Sopenharmony_ci		case 0:
50162306a36Sopenharmony_ci			bias = PIN_CONFIG_BIAS_PULL_DOWN;
50262306a36Sopenharmony_ci			break;
50362306a36Sopenharmony_ci		case 2:
50462306a36Sopenharmony_ci			bias = PIN_CONFIG_BIAS_PULL_UP;
50562306a36Sopenharmony_ci			break;
50662306a36Sopenharmony_ci		default:
50762306a36Sopenharmony_ci			bias = PIN_CONFIG_BIAS_DISABLE;
50862306a36Sopenharmony_ci		}
50962306a36Sopenharmony_ci
51062306a36Sopenharmony_ci		if (bias != param)
51162306a36Sopenharmony_ci			return -EINVAL;
51262306a36Sopenharmony_ci		break;
51362306a36Sopenharmony_ci	}
51462306a36Sopenharmony_ci
51562306a36Sopenharmony_ci	case PIN_CONFIG_DRIVE_STRENGTH_UA:
51662306a36Sopenharmony_ci		if (!(cfg & PIN_CFG_DRV))
51762306a36Sopenharmony_ci			return -EINVAL;
51862306a36Sopenharmony_ci
51962306a36Sopenharmony_ci		/* DRV uses 2-bits per pin */
52062306a36Sopenharmony_ci		bit *= 2;
52162306a36Sopenharmony_ci
52262306a36Sopenharmony_ci		val = (readl(pctrl->base + DRV(port)) >> bit) & DRV_MASK;
52362306a36Sopenharmony_ci
52462306a36Sopenharmony_ci		switch (cfg & PIN_CFG_GRP_MASK) {
52562306a36Sopenharmony_ci		case PIN_CFG_GRP_1_8V_2:
52662306a36Sopenharmony_ci			arg = drv_1_8V_group2_uA[val];
52762306a36Sopenharmony_ci			break;
52862306a36Sopenharmony_ci		case PIN_CFG_GRP_1_8V_3:
52962306a36Sopenharmony_ci			arg = drv_1_8V_group3_uA[val];
53062306a36Sopenharmony_ci			break;
53162306a36Sopenharmony_ci		case PIN_CFG_GRP_SWIO_2:
53262306a36Sopenharmony_ci			arg = drv_SWIO_group2_3_3V_uA[val];
53362306a36Sopenharmony_ci			break;
53462306a36Sopenharmony_ci		case PIN_CFG_GRP_SWIO_1:
53562306a36Sopenharmony_ci		case PIN_CFG_GRP_3_3V:
53662306a36Sopenharmony_ci			arg = drv_3_3V_group_uA[val];
53762306a36Sopenharmony_ci			break;
53862306a36Sopenharmony_ci		default:
53962306a36Sopenharmony_ci			return -EINVAL;
54062306a36Sopenharmony_ci		}
54162306a36Sopenharmony_ci
54262306a36Sopenharmony_ci		break;
54362306a36Sopenharmony_ci
54462306a36Sopenharmony_ci	case PIN_CONFIG_SLEW_RATE:
54562306a36Sopenharmony_ci		if (!(cfg & PIN_CFG_SLEW))
54662306a36Sopenharmony_ci			return -EINVAL;
54762306a36Sopenharmony_ci
54862306a36Sopenharmony_ci		arg = readl(pctrl->base + SR(port)) & BIT(bit);
54962306a36Sopenharmony_ci		break;
55062306a36Sopenharmony_ci
55162306a36Sopenharmony_ci	default:
55262306a36Sopenharmony_ci		return -ENOTSUPP;
55362306a36Sopenharmony_ci	}
55462306a36Sopenharmony_ci
55562306a36Sopenharmony_ci	*config = pinconf_to_config_packed(param, arg);
55662306a36Sopenharmony_ci
55762306a36Sopenharmony_ci	return 0;
55862306a36Sopenharmony_ci};
55962306a36Sopenharmony_ci
56062306a36Sopenharmony_cistatic int rzv2m_pinctrl_pinconf_set(struct pinctrl_dev *pctldev,
56162306a36Sopenharmony_ci				     unsigned int _pin,
56262306a36Sopenharmony_ci				     unsigned long *_configs,
56362306a36Sopenharmony_ci				     unsigned int num_configs)
56462306a36Sopenharmony_ci{
56562306a36Sopenharmony_ci	struct rzv2m_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
56662306a36Sopenharmony_ci	const struct pinctrl_pin_desc *pin = &pctrl->desc.pins[_pin];
56762306a36Sopenharmony_ci	unsigned int *pin_data = pin->drv_data;
56862306a36Sopenharmony_ci	enum pin_config_param param;
56962306a36Sopenharmony_ci	u32 port;
57062306a36Sopenharmony_ci	unsigned int i;
57162306a36Sopenharmony_ci	u32 cfg;
57262306a36Sopenharmony_ci	u8 bit;
57362306a36Sopenharmony_ci	u32 val;
57462306a36Sopenharmony_ci
57562306a36Sopenharmony_ci	if (!pin_data)
57662306a36Sopenharmony_ci		return -EINVAL;
57762306a36Sopenharmony_ci
57862306a36Sopenharmony_ci	if (*pin_data & RZV2M_SINGLE_PIN) {
57962306a36Sopenharmony_ci		port = RZV2M_SINGLE_PIN_GET_PORT(*pin_data);
58062306a36Sopenharmony_ci		cfg = RZV2M_SINGLE_PIN_GET_CFGS(*pin_data);
58162306a36Sopenharmony_ci		bit = RZV2M_SINGLE_PIN_GET_BIT(*pin_data);
58262306a36Sopenharmony_ci	} else {
58362306a36Sopenharmony_ci		cfg = RZV2M_GPIO_PORT_GET_CFGS(*pin_data);
58462306a36Sopenharmony_ci		port = RZV2M_PIN_ID_TO_PORT(_pin);
58562306a36Sopenharmony_ci		bit = RZV2M_PIN_ID_TO_PIN(_pin);
58662306a36Sopenharmony_ci
58762306a36Sopenharmony_ci		if (rzv2m_validate_gpio_pin(pctrl, *pin_data, RZV2M_PIN_ID_TO_PORT(_pin), bit))
58862306a36Sopenharmony_ci			return -EINVAL;
58962306a36Sopenharmony_ci	}
59062306a36Sopenharmony_ci
59162306a36Sopenharmony_ci	for (i = 0; i < num_configs; i++) {
59262306a36Sopenharmony_ci		param = pinconf_to_config_param(_configs[i]);
59362306a36Sopenharmony_ci		switch (param) {
59462306a36Sopenharmony_ci		case PIN_CONFIG_BIAS_DISABLE:
59562306a36Sopenharmony_ci		case PIN_CONFIG_BIAS_PULL_UP:
59662306a36Sopenharmony_ci		case PIN_CONFIG_BIAS_PULL_DOWN:
59762306a36Sopenharmony_ci			if (!(cfg & PIN_CFG_BIAS))
59862306a36Sopenharmony_ci				return -EINVAL;
59962306a36Sopenharmony_ci
60062306a36Sopenharmony_ci			/* PUPD uses 2-bits per pin */
60162306a36Sopenharmony_ci			bit *= 2;
60262306a36Sopenharmony_ci
60362306a36Sopenharmony_ci			switch (param) {
60462306a36Sopenharmony_ci			case PIN_CONFIG_BIAS_PULL_DOWN:
60562306a36Sopenharmony_ci				val = 0;
60662306a36Sopenharmony_ci				break;
60762306a36Sopenharmony_ci			case PIN_CONFIG_BIAS_PULL_UP:
60862306a36Sopenharmony_ci				val = 2;
60962306a36Sopenharmony_ci				break;
61062306a36Sopenharmony_ci			default:
61162306a36Sopenharmony_ci				val = 1;
61262306a36Sopenharmony_ci			}
61362306a36Sopenharmony_ci
61462306a36Sopenharmony_ci			rzv2m_rmw_pin_config(pctrl, PUPD(port), bit, PUPD_MASK, val);
61562306a36Sopenharmony_ci			break;
61662306a36Sopenharmony_ci
61762306a36Sopenharmony_ci		case PIN_CONFIG_DRIVE_STRENGTH_UA: {
61862306a36Sopenharmony_ci			unsigned int arg = pinconf_to_config_argument(_configs[i]);
61962306a36Sopenharmony_ci			const unsigned int *drv_strengths;
62062306a36Sopenharmony_ci			unsigned int index;
62162306a36Sopenharmony_ci
62262306a36Sopenharmony_ci			if (!(cfg & PIN_CFG_DRV))
62362306a36Sopenharmony_ci				return -EINVAL;
62462306a36Sopenharmony_ci
62562306a36Sopenharmony_ci			switch (cfg & PIN_CFG_GRP_MASK) {
62662306a36Sopenharmony_ci			case PIN_CFG_GRP_1_8V_2:
62762306a36Sopenharmony_ci				drv_strengths = drv_1_8V_group2_uA;
62862306a36Sopenharmony_ci				break;
62962306a36Sopenharmony_ci			case PIN_CFG_GRP_1_8V_3:
63062306a36Sopenharmony_ci				drv_strengths = drv_1_8V_group3_uA;
63162306a36Sopenharmony_ci				break;
63262306a36Sopenharmony_ci			case PIN_CFG_GRP_SWIO_2:
63362306a36Sopenharmony_ci				drv_strengths = drv_SWIO_group2_3_3V_uA;
63462306a36Sopenharmony_ci				break;
63562306a36Sopenharmony_ci			case PIN_CFG_GRP_SWIO_1:
63662306a36Sopenharmony_ci			case PIN_CFG_GRP_3_3V:
63762306a36Sopenharmony_ci				drv_strengths = drv_3_3V_group_uA;
63862306a36Sopenharmony_ci				break;
63962306a36Sopenharmony_ci			default:
64062306a36Sopenharmony_ci				return -EINVAL;
64162306a36Sopenharmony_ci			}
64262306a36Sopenharmony_ci
64362306a36Sopenharmony_ci			for (index = 0; index < 4; index++) {
64462306a36Sopenharmony_ci				if (arg == drv_strengths[index])
64562306a36Sopenharmony_ci					break;
64662306a36Sopenharmony_ci			}
64762306a36Sopenharmony_ci			if (index >= 4)
64862306a36Sopenharmony_ci				return -EINVAL;
64962306a36Sopenharmony_ci
65062306a36Sopenharmony_ci			/* DRV uses 2-bits per pin */
65162306a36Sopenharmony_ci			bit *= 2;
65262306a36Sopenharmony_ci
65362306a36Sopenharmony_ci			rzv2m_rmw_pin_config(pctrl, DRV(port), bit, DRV_MASK, index);
65462306a36Sopenharmony_ci			break;
65562306a36Sopenharmony_ci		}
65662306a36Sopenharmony_ci
65762306a36Sopenharmony_ci		case PIN_CONFIG_SLEW_RATE: {
65862306a36Sopenharmony_ci			unsigned int arg = pinconf_to_config_argument(_configs[i]);
65962306a36Sopenharmony_ci
66062306a36Sopenharmony_ci			if (!(cfg & PIN_CFG_SLEW))
66162306a36Sopenharmony_ci				return -EINVAL;
66262306a36Sopenharmony_ci
66362306a36Sopenharmony_ci			rzv2m_writel_we(pctrl->base + SR(port), bit, !arg);
66462306a36Sopenharmony_ci			break;
66562306a36Sopenharmony_ci		}
66662306a36Sopenharmony_ci
66762306a36Sopenharmony_ci		default:
66862306a36Sopenharmony_ci			return -EOPNOTSUPP;
66962306a36Sopenharmony_ci		}
67062306a36Sopenharmony_ci	}
67162306a36Sopenharmony_ci
67262306a36Sopenharmony_ci	return 0;
67362306a36Sopenharmony_ci}
67462306a36Sopenharmony_ci
67562306a36Sopenharmony_cistatic int rzv2m_pinctrl_pinconf_group_set(struct pinctrl_dev *pctldev,
67662306a36Sopenharmony_ci					   unsigned int group,
67762306a36Sopenharmony_ci					   unsigned long *configs,
67862306a36Sopenharmony_ci					   unsigned int num_configs)
67962306a36Sopenharmony_ci{
68062306a36Sopenharmony_ci	const unsigned int *pins;
68162306a36Sopenharmony_ci	unsigned int i, npins;
68262306a36Sopenharmony_ci	int ret;
68362306a36Sopenharmony_ci
68462306a36Sopenharmony_ci	ret = pinctrl_generic_get_group_pins(pctldev, group, &pins, &npins);
68562306a36Sopenharmony_ci	if (ret)
68662306a36Sopenharmony_ci		return ret;
68762306a36Sopenharmony_ci
68862306a36Sopenharmony_ci	for (i = 0; i < npins; i++) {
68962306a36Sopenharmony_ci		ret = rzv2m_pinctrl_pinconf_set(pctldev, pins[i], configs,
69062306a36Sopenharmony_ci						num_configs);
69162306a36Sopenharmony_ci		if (ret)
69262306a36Sopenharmony_ci			return ret;
69362306a36Sopenharmony_ci	}
69462306a36Sopenharmony_ci
69562306a36Sopenharmony_ci	return 0;
69662306a36Sopenharmony_ci};
69762306a36Sopenharmony_ci
69862306a36Sopenharmony_cistatic int rzv2m_pinctrl_pinconf_group_get(struct pinctrl_dev *pctldev,
69962306a36Sopenharmony_ci					   unsigned int group,
70062306a36Sopenharmony_ci					   unsigned long *config)
70162306a36Sopenharmony_ci{
70262306a36Sopenharmony_ci	const unsigned int *pins;
70362306a36Sopenharmony_ci	unsigned int i, npins, prev_config = 0;
70462306a36Sopenharmony_ci	int ret;
70562306a36Sopenharmony_ci
70662306a36Sopenharmony_ci	ret = pinctrl_generic_get_group_pins(pctldev, group, &pins, &npins);
70762306a36Sopenharmony_ci	if (ret)
70862306a36Sopenharmony_ci		return ret;
70962306a36Sopenharmony_ci
71062306a36Sopenharmony_ci	for (i = 0; i < npins; i++) {
71162306a36Sopenharmony_ci		ret = rzv2m_pinctrl_pinconf_get(pctldev, pins[i], config);
71262306a36Sopenharmony_ci		if (ret)
71362306a36Sopenharmony_ci			return ret;
71462306a36Sopenharmony_ci
71562306a36Sopenharmony_ci		/* Check config matches previous pins */
71662306a36Sopenharmony_ci		if (i && prev_config != *config)
71762306a36Sopenharmony_ci			return -EOPNOTSUPP;
71862306a36Sopenharmony_ci
71962306a36Sopenharmony_ci		prev_config = *config;
72062306a36Sopenharmony_ci	}
72162306a36Sopenharmony_ci
72262306a36Sopenharmony_ci	return 0;
72362306a36Sopenharmony_ci};
72462306a36Sopenharmony_ci
72562306a36Sopenharmony_cistatic const struct pinctrl_ops rzv2m_pinctrl_pctlops = {
72662306a36Sopenharmony_ci	.get_groups_count = pinctrl_generic_get_group_count,
72762306a36Sopenharmony_ci	.get_group_name = pinctrl_generic_get_group_name,
72862306a36Sopenharmony_ci	.get_group_pins = pinctrl_generic_get_group_pins,
72962306a36Sopenharmony_ci	.dt_node_to_map = rzv2m_dt_node_to_map,
73062306a36Sopenharmony_ci	.dt_free_map = rzv2m_dt_free_map,
73162306a36Sopenharmony_ci};
73262306a36Sopenharmony_ci
73362306a36Sopenharmony_cistatic const struct pinmux_ops rzv2m_pinctrl_pmxops = {
73462306a36Sopenharmony_ci	.get_functions_count = pinmux_generic_get_function_count,
73562306a36Sopenharmony_ci	.get_function_name = pinmux_generic_get_function_name,
73662306a36Sopenharmony_ci	.get_function_groups = pinmux_generic_get_function_groups,
73762306a36Sopenharmony_ci	.set_mux = rzv2m_pinctrl_set_mux,
73862306a36Sopenharmony_ci	.strict = true,
73962306a36Sopenharmony_ci};
74062306a36Sopenharmony_ci
74162306a36Sopenharmony_cistatic const struct pinconf_ops rzv2m_pinctrl_confops = {
74262306a36Sopenharmony_ci	.is_generic = true,
74362306a36Sopenharmony_ci	.pin_config_get = rzv2m_pinctrl_pinconf_get,
74462306a36Sopenharmony_ci	.pin_config_set = rzv2m_pinctrl_pinconf_set,
74562306a36Sopenharmony_ci	.pin_config_group_set = rzv2m_pinctrl_pinconf_group_set,
74662306a36Sopenharmony_ci	.pin_config_group_get = rzv2m_pinctrl_pinconf_group_get,
74762306a36Sopenharmony_ci	.pin_config_config_dbg_show = pinconf_generic_dump_config,
74862306a36Sopenharmony_ci};
74962306a36Sopenharmony_ci
75062306a36Sopenharmony_cistatic int rzv2m_gpio_request(struct gpio_chip *chip, unsigned int offset)
75162306a36Sopenharmony_ci{
75262306a36Sopenharmony_ci	struct rzv2m_pinctrl *pctrl = gpiochip_get_data(chip);
75362306a36Sopenharmony_ci	u32 port = RZV2M_PIN_ID_TO_PORT(offset);
75462306a36Sopenharmony_ci	u8 bit = RZV2M_PIN_ID_TO_PIN(offset);
75562306a36Sopenharmony_ci	int ret;
75662306a36Sopenharmony_ci
75762306a36Sopenharmony_ci	ret = pinctrl_gpio_request(chip->base + offset);
75862306a36Sopenharmony_ci	if (ret)
75962306a36Sopenharmony_ci		return ret;
76062306a36Sopenharmony_ci
76162306a36Sopenharmony_ci	rzv2m_pinctrl_set_pfc_mode(pctrl, port, bit, 0);
76262306a36Sopenharmony_ci
76362306a36Sopenharmony_ci	return 0;
76462306a36Sopenharmony_ci}
76562306a36Sopenharmony_ci
76662306a36Sopenharmony_cistatic void rzv2m_gpio_set_direction(struct rzv2m_pinctrl *pctrl, u32 port,
76762306a36Sopenharmony_ci				     u8 bit, bool output)
76862306a36Sopenharmony_ci{
76962306a36Sopenharmony_ci	rzv2m_writel_we(pctrl->base + OE(port), bit, output);
77062306a36Sopenharmony_ci	rzv2m_writel_we(pctrl->base + IE(port), bit, !output);
77162306a36Sopenharmony_ci}
77262306a36Sopenharmony_ci
77362306a36Sopenharmony_cistatic int rzv2m_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
77462306a36Sopenharmony_ci{
77562306a36Sopenharmony_ci	struct rzv2m_pinctrl *pctrl = gpiochip_get_data(chip);
77662306a36Sopenharmony_ci	u32 port = RZV2M_PIN_ID_TO_PORT(offset);
77762306a36Sopenharmony_ci	u8 bit = RZV2M_PIN_ID_TO_PIN(offset);
77862306a36Sopenharmony_ci
77962306a36Sopenharmony_ci	if (!(readl(pctrl->base + IE(port)) & BIT(bit)))
78062306a36Sopenharmony_ci		return GPIO_LINE_DIRECTION_OUT;
78162306a36Sopenharmony_ci
78262306a36Sopenharmony_ci	return GPIO_LINE_DIRECTION_IN;
78362306a36Sopenharmony_ci}
78462306a36Sopenharmony_ci
78562306a36Sopenharmony_cistatic int rzv2m_gpio_direction_input(struct gpio_chip *chip,
78662306a36Sopenharmony_ci				      unsigned int offset)
78762306a36Sopenharmony_ci{
78862306a36Sopenharmony_ci	struct rzv2m_pinctrl *pctrl = gpiochip_get_data(chip);
78962306a36Sopenharmony_ci	u32 port = RZV2M_PIN_ID_TO_PORT(offset);
79062306a36Sopenharmony_ci	u8 bit = RZV2M_PIN_ID_TO_PIN(offset);
79162306a36Sopenharmony_ci
79262306a36Sopenharmony_ci	rzv2m_gpio_set_direction(pctrl, port, bit, false);
79362306a36Sopenharmony_ci
79462306a36Sopenharmony_ci	return 0;
79562306a36Sopenharmony_ci}
79662306a36Sopenharmony_ci
79762306a36Sopenharmony_cistatic void rzv2m_gpio_set(struct gpio_chip *chip, unsigned int offset,
79862306a36Sopenharmony_ci			   int value)
79962306a36Sopenharmony_ci{
80062306a36Sopenharmony_ci	struct rzv2m_pinctrl *pctrl = gpiochip_get_data(chip);
80162306a36Sopenharmony_ci	u32 port = RZV2M_PIN_ID_TO_PORT(offset);
80262306a36Sopenharmony_ci	u8 bit = RZV2M_PIN_ID_TO_PIN(offset);
80362306a36Sopenharmony_ci
80462306a36Sopenharmony_ci	rzv2m_writel_we(pctrl->base + DO(port), bit, !!value);
80562306a36Sopenharmony_ci}
80662306a36Sopenharmony_ci
80762306a36Sopenharmony_cistatic int rzv2m_gpio_direction_output(struct gpio_chip *chip,
80862306a36Sopenharmony_ci				       unsigned int offset, int value)
80962306a36Sopenharmony_ci{
81062306a36Sopenharmony_ci	struct rzv2m_pinctrl *pctrl = gpiochip_get_data(chip);
81162306a36Sopenharmony_ci	u32 port = RZV2M_PIN_ID_TO_PORT(offset);
81262306a36Sopenharmony_ci	u8 bit = RZV2M_PIN_ID_TO_PIN(offset);
81362306a36Sopenharmony_ci
81462306a36Sopenharmony_ci	rzv2m_gpio_set(chip, offset, value);
81562306a36Sopenharmony_ci	rzv2m_gpio_set_direction(pctrl, port, bit, true);
81662306a36Sopenharmony_ci
81762306a36Sopenharmony_ci	return 0;
81862306a36Sopenharmony_ci}
81962306a36Sopenharmony_ci
82062306a36Sopenharmony_cistatic int rzv2m_gpio_get(struct gpio_chip *chip, unsigned int offset)
82162306a36Sopenharmony_ci{
82262306a36Sopenharmony_ci	struct rzv2m_pinctrl *pctrl = gpiochip_get_data(chip);
82362306a36Sopenharmony_ci	u32 port = RZV2M_PIN_ID_TO_PORT(offset);
82462306a36Sopenharmony_ci	u8 bit = RZV2M_PIN_ID_TO_PIN(offset);
82562306a36Sopenharmony_ci	int direction = rzv2m_gpio_get_direction(chip, offset);
82662306a36Sopenharmony_ci
82762306a36Sopenharmony_ci	if (direction == GPIO_LINE_DIRECTION_IN)
82862306a36Sopenharmony_ci		return !!(readl(pctrl->base + DI(port)) & BIT(bit));
82962306a36Sopenharmony_ci	else
83062306a36Sopenharmony_ci		return !!(readl(pctrl->base + DO(port)) & BIT(bit));
83162306a36Sopenharmony_ci}
83262306a36Sopenharmony_ci
83362306a36Sopenharmony_cistatic void rzv2m_gpio_free(struct gpio_chip *chip, unsigned int offset)
83462306a36Sopenharmony_ci{
83562306a36Sopenharmony_ci	pinctrl_gpio_free(chip->base + offset);
83662306a36Sopenharmony_ci
83762306a36Sopenharmony_ci	/*
83862306a36Sopenharmony_ci	 * Set the GPIO as an input to ensure that the next GPIO request won't
83962306a36Sopenharmony_ci	 * drive the GPIO pin as an output.
84062306a36Sopenharmony_ci	 */
84162306a36Sopenharmony_ci	rzv2m_gpio_direction_input(chip, offset);
84262306a36Sopenharmony_ci}
84362306a36Sopenharmony_ci
84462306a36Sopenharmony_cistatic const char * const rzv2m_gpio_names[] = {
84562306a36Sopenharmony_ci	"P0_0", "P0_1", "P0_2", "P0_3", "P0_4", "P0_5", "P0_6", "P0_7",
84662306a36Sopenharmony_ci	"P0_8", "P0_9", "P0_10", "P0_11", "P0_12", "P0_13", "P0_14", "P0_15",
84762306a36Sopenharmony_ci	"P1_0", "P1_1", "P1_2", "P1_3", "P1_4", "P1_5", "P1_6", "P1_7",
84862306a36Sopenharmony_ci	"P1_8", "P1_9", "P1_10", "P1_11", "P1_12", "P1_13", "P1_14", "P1_15",
84962306a36Sopenharmony_ci	"P2_0", "P2_1", "P2_2", "P2_3", "P2_4", "P2_5", "P2_6", "P2_7",
85062306a36Sopenharmony_ci	"P2_8", "P2_9", "P2_10", "P2_11", "P2_12", "P2_13", "P2_14", "P2_15",
85162306a36Sopenharmony_ci	"P3_0", "P3_1", "P3_2", "P3_3", "P3_4", "P3_5", "P3_6", "P3_7",
85262306a36Sopenharmony_ci	"P3_8", "P3_9", "P3_10", "P3_11", "P3_12", "P3_13", "P3_14", "P3_15",
85362306a36Sopenharmony_ci	"P4_0", "P4_1", "P4_2", "P4_3", "P4_4", "P4_5", "P4_6", "P4_7",
85462306a36Sopenharmony_ci	"P4_8", "P4_9", "P4_10", "P4_11", "P4_12", "P4_13", "P4_14", "P4_15",
85562306a36Sopenharmony_ci	"P5_0", "P5_1", "P5_2", "P5_3", "P5_4", "P5_5", "P5_6", "P5_7",
85662306a36Sopenharmony_ci	"P5_8", "P5_9", "P5_10", "P5_11", "P5_12", "P5_13", "P5_14", "P5_15",
85762306a36Sopenharmony_ci	"P6_0", "P6_1", "P6_2", "P6_3", "P6_4", "P6_5", "P6_6", "P6_7",
85862306a36Sopenharmony_ci	"P6_8", "P6_9", "P6_10", "P6_11", "P6_12", "P6_13", "P6_14", "P6_15",
85962306a36Sopenharmony_ci	"P7_0", "P7_1", "P7_2", "P7_3", "P7_4", "P7_5", "P7_6", "P7_7",
86062306a36Sopenharmony_ci	"P7_8", "P7_9", "P7_10", "P7_11", "P7_12", "P7_13", "P7_14", "P7_15",
86162306a36Sopenharmony_ci	"P8_0", "P8_1", "P8_2", "P8_3", "P8_4", "P8_5", "P8_6", "P8_7",
86262306a36Sopenharmony_ci	"P8_8", "P8_9", "P8_10", "P8_11", "P8_12", "P8_13", "P8_14", "P8_15",
86362306a36Sopenharmony_ci	"P9_0", "P9_1", "P9_2", "P9_3", "P9_4", "P9_5", "P9_6", "P9_7",
86462306a36Sopenharmony_ci	"P9_8", "P9_9", "P9_10", "P9_11", "P9_12", "P9_13", "P9_14", "P9_15",
86562306a36Sopenharmony_ci	"P10_0", "P10_1", "P10_2", "P10_3", "P10_4", "P10_5", "P10_6", "P10_7",
86662306a36Sopenharmony_ci	"P10_8", "P10_9", "P10_10", "P10_11", "P10_12", "P10_13", "P10_14", "P10_15",
86762306a36Sopenharmony_ci	"P11_0", "P11_1", "P11_2", "P11_3", "P11_4", "P11_5", "P11_6", "P11_7",
86862306a36Sopenharmony_ci	"P11_8", "P11_9", "P11_10", "P11_11", "P11_12", "P11_13", "P11_14", "P11_15",
86962306a36Sopenharmony_ci	"P12_0", "P12_1", "P12_2", "P12_3", "P12_4", "P12_5", "P12_6", "P12_7",
87062306a36Sopenharmony_ci	"P12_8", "P12_9", "P12_10", "P12_11", "P12_12", "P12_13", "P12_14", "P12_15",
87162306a36Sopenharmony_ci	"P13_0", "P13_1", "P13_2", "P13_3", "P13_4", "P13_5", "P13_6", "P13_7",
87262306a36Sopenharmony_ci	"P13_8", "P13_9", "P13_10", "P13_11", "P13_12", "P13_13", "P13_14", "P13_15",
87362306a36Sopenharmony_ci	"P14_0", "P14_1", "P14_2", "P14_3", "P14_4", "P14_5", "P14_6", "P14_7",
87462306a36Sopenharmony_ci	"P14_8", "P14_9", "P14_10", "P14_11", "P14_12", "P14_13", "P14_14", "P14_15",
87562306a36Sopenharmony_ci	"P15_0", "P15_1", "P15_2", "P15_3", "P15_4", "P15_5", "P15_6", "P15_7",
87662306a36Sopenharmony_ci	"P15_8", "P15_9", "P15_10", "P15_11", "P15_12", "P15_13", "P15_14", "P15_15",
87762306a36Sopenharmony_ci	"P16_0", "P16_1", "P16_2", "P16_3", "P16_4", "P16_5", "P16_6", "P16_7",
87862306a36Sopenharmony_ci	"P16_8", "P16_9", "P16_10", "P16_11", "P16_12", "P16_13", "P16_14", "P16_15",
87962306a36Sopenharmony_ci	"P17_0", "P17_1", "P17_2", "P17_3", "P17_4", "P17_5", "P17_6", "P17_7",
88062306a36Sopenharmony_ci	"P17_8", "P17_9", "P17_10", "P17_11", "P17_12", "P17_13", "P17_14", "P17_15",
88162306a36Sopenharmony_ci	"P18_0", "P18_1", "P18_2", "P18_3", "P18_4", "P18_5", "P18_6", "P18_7",
88262306a36Sopenharmony_ci	"P18_8", "P18_9", "P18_10", "P18_11", "P18_12", "P18_13", "P18_14", "P18_15",
88362306a36Sopenharmony_ci	"P19_0", "P19_1", "P19_2", "P19_3", "P19_4", "P19_5", "P19_6", "P19_7",
88462306a36Sopenharmony_ci	"P19_8", "P19_9", "P19_10", "P19_11", "P19_12", "P19_13", "P19_14", "P19_15",
88562306a36Sopenharmony_ci	"P20_0", "P20_1", "P20_2", "P20_3", "P20_4", "P20_5", "P20_6", "P20_7",
88662306a36Sopenharmony_ci	"P20_8", "P20_9", "P20_10", "P20_11", "P20_12", "P20_13", "P20_14", "P20_15",
88762306a36Sopenharmony_ci	"P21_0", "P21_1", "P21_2", "P21_3", "P21_4", "P21_5", "P21_6", "P21_7",
88862306a36Sopenharmony_ci	"P21_8", "P21_9", "P21_10", "P21_11", "P21_12", "P21_13", "P21_14", "P21_15",
88962306a36Sopenharmony_ci};
89062306a36Sopenharmony_ci
89162306a36Sopenharmony_cistatic const u32 rzv2m_gpio_configs[] = {
89262306a36Sopenharmony_ci	RZV2M_GPIO_PORT_PACK(14, 0, PIN_CFG_GRP_SWIO_2 | RZV2M_MPXED_PIN_FUNCS),
89362306a36Sopenharmony_ci	RZV2M_GPIO_PORT_PACK(16, 1, PIN_CFG_GRP_SWIO_1 | RZV2M_MPXED_PIN_FUNCS),
89462306a36Sopenharmony_ci	RZV2M_GPIO_PORT_PACK(8,  2, PIN_CFG_GRP_1_8V_3 | RZV2M_MPXED_PIN_FUNCS),
89562306a36Sopenharmony_ci	RZV2M_GPIO_PORT_PACK(16, 3, PIN_CFG_GRP_SWIO_1 | RZV2M_MPXED_PIN_FUNCS),
89662306a36Sopenharmony_ci	RZV2M_GPIO_PORT_PACK(8,  4, PIN_CFG_GRP_SWIO_1 | RZV2M_MPXED_PIN_FUNCS),
89762306a36Sopenharmony_ci	RZV2M_GPIO_PORT_PACK(4,  5, PIN_CFG_GRP_1_8V_3 | RZV2M_MPXED_PIN_FUNCS),
89862306a36Sopenharmony_ci	RZV2M_GPIO_PORT_PACK(12, 6, PIN_CFG_GRP_SWIO_1 | RZV2M_MPXED_PIN_FUNCS),
89962306a36Sopenharmony_ci	RZV2M_GPIO_PORT_PACK(6,  7, PIN_CFG_GRP_SWIO_1 | RZV2M_MPXED_PIN_FUNCS),
90062306a36Sopenharmony_ci	RZV2M_GPIO_PORT_PACK(8,  8, PIN_CFG_GRP_SWIO_2 | RZV2M_MPXED_PIN_FUNCS),
90162306a36Sopenharmony_ci	RZV2M_GPIO_PORT_PACK(8,  9, PIN_CFG_GRP_SWIO_2 | RZV2M_MPXED_PIN_FUNCS),
90262306a36Sopenharmony_ci	RZV2M_GPIO_PORT_PACK(9,  10, PIN_CFG_GRP_SWIO_1 | RZV2M_MPXED_PIN_FUNCS),
90362306a36Sopenharmony_ci	RZV2M_GPIO_PORT_PACK(9,  11, PIN_CFG_GRP_SWIO_1 | RZV2M_MPXED_PIN_FUNCS),
90462306a36Sopenharmony_ci	RZV2M_GPIO_PORT_PACK(4,  12, PIN_CFG_GRP_3_3V | RZV2M_MPXED_PIN_FUNCS),
90562306a36Sopenharmony_ci	RZV2M_GPIO_PORT_PACK(12, 13, PIN_CFG_GRP_3_3V | RZV2M_MPXED_PIN_FUNCS),
90662306a36Sopenharmony_ci	RZV2M_GPIO_PORT_PACK(8,  14, PIN_CFG_GRP_3_3V | RZV2M_MPXED_PIN_FUNCS),
90762306a36Sopenharmony_ci	RZV2M_GPIO_PORT_PACK(16, 15, PIN_CFG_GRP_SWIO_2 | RZV2M_MPXED_PIN_FUNCS),
90862306a36Sopenharmony_ci	RZV2M_GPIO_PORT_PACK(14, 16, PIN_CFG_GRP_SWIO_2 | RZV2M_MPXED_PIN_FUNCS),
90962306a36Sopenharmony_ci	RZV2M_GPIO_PORT_PACK(1,  17, PIN_CFG_GRP_SWIO_2 | RZV2M_MPXED_PIN_FUNCS),
91062306a36Sopenharmony_ci	RZV2M_GPIO_PORT_PACK(0,  18, 0),
91162306a36Sopenharmony_ci	RZV2M_GPIO_PORT_PACK(0,  19, 0),
91262306a36Sopenharmony_ci	RZV2M_GPIO_PORT_PACK(3,  20, PIN_CFG_GRP_1_8V_2 | PIN_CFG_DRV),
91362306a36Sopenharmony_ci	RZV2M_GPIO_PORT_PACK(1,  21, PIN_CFG_GRP_SWIO_1 | PIN_CFG_DRV | PIN_CFG_SLEW),
91462306a36Sopenharmony_ci};
91562306a36Sopenharmony_ci
91662306a36Sopenharmony_cistatic const struct rzv2m_dedicated_configs rzv2m_dedicated_pins[] = {
91762306a36Sopenharmony_ci	{ "NAWPN", RZV2M_SINGLE_PIN_PACK(0,
91862306a36Sopenharmony_ci		(PIN_CFG_GRP_SWIO_2 | PIN_CFG_DRV | PIN_CFG_SLEW)) },
91962306a36Sopenharmony_ci	{ "IM0CLK", RZV2M_SINGLE_PIN_PACK(1,
92062306a36Sopenharmony_ci		(PIN_CFG_GRP_SWIO_1 | PIN_CFG_DRV | PIN_CFG_SLEW)) },
92162306a36Sopenharmony_ci	{ "IM1CLK", RZV2M_SINGLE_PIN_PACK(2,
92262306a36Sopenharmony_ci		(PIN_CFG_GRP_SWIO_1 | PIN_CFG_DRV | PIN_CFG_SLEW)) },
92362306a36Sopenharmony_ci	{ "DETDO", RZV2M_SINGLE_PIN_PACK(5,
92462306a36Sopenharmony_ci		(PIN_CFG_GRP_1_8V_3 | PIN_CFG_DRV | PIN_CFG_SLEW)) },
92562306a36Sopenharmony_ci	{ "DETMS", RZV2M_SINGLE_PIN_PACK(6,
92662306a36Sopenharmony_ci		(PIN_CFG_GRP_1_8V_3 | PIN_CFG_DRV | PIN_CFG_SLEW)) },
92762306a36Sopenharmony_ci	{ "PCRSTOUTB", RZV2M_SINGLE_PIN_PACK(12,
92862306a36Sopenharmony_ci		(PIN_CFG_GRP_3_3V | PIN_CFG_DRV | PIN_CFG_SLEW)) },
92962306a36Sopenharmony_ci	{ "USPWEN", RZV2M_SINGLE_PIN_PACK(14,
93062306a36Sopenharmony_ci		(PIN_CFG_GRP_3_3V | PIN_CFG_DRV | PIN_CFG_SLEW)) },
93162306a36Sopenharmony_ci};
93262306a36Sopenharmony_ci
93362306a36Sopenharmony_cistatic int rzv2m_gpio_register(struct rzv2m_pinctrl *pctrl)
93462306a36Sopenharmony_ci{
93562306a36Sopenharmony_ci	struct device_node *np = pctrl->dev->of_node;
93662306a36Sopenharmony_ci	struct gpio_chip *chip = &pctrl->gpio_chip;
93762306a36Sopenharmony_ci	const char *name = dev_name(pctrl->dev);
93862306a36Sopenharmony_ci	struct of_phandle_args of_args;
93962306a36Sopenharmony_ci	int ret;
94062306a36Sopenharmony_ci
94162306a36Sopenharmony_ci	ret = of_parse_phandle_with_fixed_args(np, "gpio-ranges", 3, 0, &of_args);
94262306a36Sopenharmony_ci	if (ret) {
94362306a36Sopenharmony_ci		dev_err(pctrl->dev, "Unable to parse gpio-ranges\n");
94462306a36Sopenharmony_ci		return ret;
94562306a36Sopenharmony_ci	}
94662306a36Sopenharmony_ci
94762306a36Sopenharmony_ci	if (of_args.args[0] != 0 || of_args.args[1] != 0 ||
94862306a36Sopenharmony_ci	    of_args.args[2] != pctrl->data->n_port_pins) {
94962306a36Sopenharmony_ci		dev_err(pctrl->dev, "gpio-ranges does not match selected SOC\n");
95062306a36Sopenharmony_ci		return -EINVAL;
95162306a36Sopenharmony_ci	}
95262306a36Sopenharmony_ci
95362306a36Sopenharmony_ci	chip->names = pctrl->data->port_pins;
95462306a36Sopenharmony_ci	chip->request = rzv2m_gpio_request;
95562306a36Sopenharmony_ci	chip->free = rzv2m_gpio_free;
95662306a36Sopenharmony_ci	chip->get_direction = rzv2m_gpio_get_direction;
95762306a36Sopenharmony_ci	chip->direction_input = rzv2m_gpio_direction_input;
95862306a36Sopenharmony_ci	chip->direction_output = rzv2m_gpio_direction_output;
95962306a36Sopenharmony_ci	chip->get = rzv2m_gpio_get;
96062306a36Sopenharmony_ci	chip->set = rzv2m_gpio_set;
96162306a36Sopenharmony_ci	chip->label = name;
96262306a36Sopenharmony_ci	chip->parent = pctrl->dev;
96362306a36Sopenharmony_ci	chip->owner = THIS_MODULE;
96462306a36Sopenharmony_ci	chip->base = -1;
96562306a36Sopenharmony_ci	chip->ngpio = of_args.args[2];
96662306a36Sopenharmony_ci
96762306a36Sopenharmony_ci	pctrl->gpio_range.id = 0;
96862306a36Sopenharmony_ci	pctrl->gpio_range.pin_base = 0;
96962306a36Sopenharmony_ci	pctrl->gpio_range.base = 0;
97062306a36Sopenharmony_ci	pctrl->gpio_range.npins = chip->ngpio;
97162306a36Sopenharmony_ci	pctrl->gpio_range.name = chip->label;
97262306a36Sopenharmony_ci	pctrl->gpio_range.gc = chip;
97362306a36Sopenharmony_ci	ret = devm_gpiochip_add_data(pctrl->dev, chip, pctrl);
97462306a36Sopenharmony_ci	if (ret) {
97562306a36Sopenharmony_ci		dev_err(pctrl->dev, "failed to add GPIO controller\n");
97662306a36Sopenharmony_ci		return ret;
97762306a36Sopenharmony_ci	}
97862306a36Sopenharmony_ci
97962306a36Sopenharmony_ci	dev_dbg(pctrl->dev, "Registered gpio controller\n");
98062306a36Sopenharmony_ci
98162306a36Sopenharmony_ci	return 0;
98262306a36Sopenharmony_ci}
98362306a36Sopenharmony_ci
98462306a36Sopenharmony_cistatic int rzv2m_pinctrl_register(struct rzv2m_pinctrl *pctrl)
98562306a36Sopenharmony_ci{
98662306a36Sopenharmony_ci	struct pinctrl_pin_desc *pins;
98762306a36Sopenharmony_ci	unsigned int i, j;
98862306a36Sopenharmony_ci	u32 *pin_data;
98962306a36Sopenharmony_ci	int ret;
99062306a36Sopenharmony_ci
99162306a36Sopenharmony_ci	pctrl->desc.name = DRV_NAME;
99262306a36Sopenharmony_ci	pctrl->desc.npins = pctrl->data->n_port_pins + pctrl->data->n_dedicated_pins;
99362306a36Sopenharmony_ci	pctrl->desc.pctlops = &rzv2m_pinctrl_pctlops;
99462306a36Sopenharmony_ci	pctrl->desc.pmxops = &rzv2m_pinctrl_pmxops;
99562306a36Sopenharmony_ci	pctrl->desc.confops = &rzv2m_pinctrl_confops;
99662306a36Sopenharmony_ci	pctrl->desc.owner = THIS_MODULE;
99762306a36Sopenharmony_ci
99862306a36Sopenharmony_ci	pins = devm_kcalloc(pctrl->dev, pctrl->desc.npins, sizeof(*pins), GFP_KERNEL);
99962306a36Sopenharmony_ci	if (!pins)
100062306a36Sopenharmony_ci		return -ENOMEM;
100162306a36Sopenharmony_ci
100262306a36Sopenharmony_ci	pin_data = devm_kcalloc(pctrl->dev, pctrl->desc.npins,
100362306a36Sopenharmony_ci				sizeof(*pin_data), GFP_KERNEL);
100462306a36Sopenharmony_ci	if (!pin_data)
100562306a36Sopenharmony_ci		return -ENOMEM;
100662306a36Sopenharmony_ci
100762306a36Sopenharmony_ci	pctrl->pins = pins;
100862306a36Sopenharmony_ci	pctrl->desc.pins = pins;
100962306a36Sopenharmony_ci
101062306a36Sopenharmony_ci	for (i = 0, j = 0; i < pctrl->data->n_port_pins; i++) {
101162306a36Sopenharmony_ci		pins[i].number = i;
101262306a36Sopenharmony_ci		pins[i].name = pctrl->data->port_pins[i];
101362306a36Sopenharmony_ci		if (i && !(i % RZV2M_PINS_PER_PORT))
101462306a36Sopenharmony_ci			j++;
101562306a36Sopenharmony_ci		pin_data[i] = pctrl->data->port_pin_configs[j];
101662306a36Sopenharmony_ci		pins[i].drv_data = &pin_data[i];
101762306a36Sopenharmony_ci	}
101862306a36Sopenharmony_ci
101962306a36Sopenharmony_ci	for (i = 0; i < pctrl->data->n_dedicated_pins; i++) {
102062306a36Sopenharmony_ci		unsigned int index = pctrl->data->n_port_pins + i;
102162306a36Sopenharmony_ci
102262306a36Sopenharmony_ci		pins[index].number = index;
102362306a36Sopenharmony_ci		pins[index].name = pctrl->data->dedicated_pins[i].name;
102462306a36Sopenharmony_ci		pin_data[index] = pctrl->data->dedicated_pins[i].config;
102562306a36Sopenharmony_ci		pins[index].drv_data = &pin_data[index];
102662306a36Sopenharmony_ci	}
102762306a36Sopenharmony_ci
102862306a36Sopenharmony_ci	ret = devm_pinctrl_register_and_init(pctrl->dev, &pctrl->desc, pctrl,
102962306a36Sopenharmony_ci					     &pctrl->pctl);
103062306a36Sopenharmony_ci	if (ret) {
103162306a36Sopenharmony_ci		dev_err(pctrl->dev, "pinctrl registration failed\n");
103262306a36Sopenharmony_ci		return ret;
103362306a36Sopenharmony_ci	}
103462306a36Sopenharmony_ci
103562306a36Sopenharmony_ci	ret = pinctrl_enable(pctrl->pctl);
103662306a36Sopenharmony_ci	if (ret) {
103762306a36Sopenharmony_ci		dev_err(pctrl->dev, "pinctrl enable failed\n");
103862306a36Sopenharmony_ci		return ret;
103962306a36Sopenharmony_ci	}
104062306a36Sopenharmony_ci
104162306a36Sopenharmony_ci	ret = rzv2m_gpio_register(pctrl);
104262306a36Sopenharmony_ci	if (ret) {
104362306a36Sopenharmony_ci		dev_err(pctrl->dev, "failed to add GPIO chip: %i\n", ret);
104462306a36Sopenharmony_ci		return ret;
104562306a36Sopenharmony_ci	}
104662306a36Sopenharmony_ci
104762306a36Sopenharmony_ci	return 0;
104862306a36Sopenharmony_ci}
104962306a36Sopenharmony_ci
105062306a36Sopenharmony_cistatic int rzv2m_pinctrl_probe(struct platform_device *pdev)
105162306a36Sopenharmony_ci{
105262306a36Sopenharmony_ci	struct rzv2m_pinctrl *pctrl;
105362306a36Sopenharmony_ci	struct clk *clk;
105462306a36Sopenharmony_ci	int ret;
105562306a36Sopenharmony_ci
105662306a36Sopenharmony_ci	pctrl = devm_kzalloc(&pdev->dev, sizeof(*pctrl), GFP_KERNEL);
105762306a36Sopenharmony_ci	if (!pctrl)
105862306a36Sopenharmony_ci		return -ENOMEM;
105962306a36Sopenharmony_ci
106062306a36Sopenharmony_ci	pctrl->dev = &pdev->dev;
106162306a36Sopenharmony_ci
106262306a36Sopenharmony_ci	pctrl->data = of_device_get_match_data(&pdev->dev);
106362306a36Sopenharmony_ci	if (!pctrl->data)
106462306a36Sopenharmony_ci		return -EINVAL;
106562306a36Sopenharmony_ci
106662306a36Sopenharmony_ci	pctrl->base = devm_platform_ioremap_resource(pdev, 0);
106762306a36Sopenharmony_ci	if (IS_ERR(pctrl->base))
106862306a36Sopenharmony_ci		return PTR_ERR(pctrl->base);
106962306a36Sopenharmony_ci
107062306a36Sopenharmony_ci	clk = devm_clk_get_enabled(pctrl->dev, NULL);
107162306a36Sopenharmony_ci	if (IS_ERR(clk))
107262306a36Sopenharmony_ci		return dev_err_probe(pctrl->dev, PTR_ERR(clk),
107362306a36Sopenharmony_ci				     "failed to enable GPIO clk\n");
107462306a36Sopenharmony_ci
107562306a36Sopenharmony_ci	spin_lock_init(&pctrl->lock);
107662306a36Sopenharmony_ci	mutex_init(&pctrl->mutex);
107762306a36Sopenharmony_ci
107862306a36Sopenharmony_ci	platform_set_drvdata(pdev, pctrl);
107962306a36Sopenharmony_ci
108062306a36Sopenharmony_ci	ret = rzv2m_pinctrl_register(pctrl);
108162306a36Sopenharmony_ci	if (ret)
108262306a36Sopenharmony_ci		return ret;
108362306a36Sopenharmony_ci
108462306a36Sopenharmony_ci	dev_info(pctrl->dev, "%s support registered\n", DRV_NAME);
108562306a36Sopenharmony_ci	return 0;
108662306a36Sopenharmony_ci}
108762306a36Sopenharmony_ci
108862306a36Sopenharmony_cistatic struct rzv2m_pinctrl_data r9a09g011_data = {
108962306a36Sopenharmony_ci	.port_pins = rzv2m_gpio_names,
109062306a36Sopenharmony_ci	.port_pin_configs = rzv2m_gpio_configs,
109162306a36Sopenharmony_ci	.dedicated_pins = rzv2m_dedicated_pins,
109262306a36Sopenharmony_ci	.n_port_pins = ARRAY_SIZE(rzv2m_gpio_configs) * RZV2M_PINS_PER_PORT,
109362306a36Sopenharmony_ci	.n_dedicated_pins = ARRAY_SIZE(rzv2m_dedicated_pins),
109462306a36Sopenharmony_ci};
109562306a36Sopenharmony_ci
109662306a36Sopenharmony_cistatic const struct of_device_id rzv2m_pinctrl_of_table[] = {
109762306a36Sopenharmony_ci	{
109862306a36Sopenharmony_ci		.compatible = "renesas,r9a09g011-pinctrl",
109962306a36Sopenharmony_ci		.data = &r9a09g011_data,
110062306a36Sopenharmony_ci	},
110162306a36Sopenharmony_ci	{ /* sentinel */ }
110262306a36Sopenharmony_ci};
110362306a36Sopenharmony_ci
110462306a36Sopenharmony_cistatic struct platform_driver rzv2m_pinctrl_driver = {
110562306a36Sopenharmony_ci	.driver = {
110662306a36Sopenharmony_ci		.name = DRV_NAME,
110762306a36Sopenharmony_ci		.of_match_table = of_match_ptr(rzv2m_pinctrl_of_table),
110862306a36Sopenharmony_ci	},
110962306a36Sopenharmony_ci	.probe = rzv2m_pinctrl_probe,
111062306a36Sopenharmony_ci};
111162306a36Sopenharmony_ci
111262306a36Sopenharmony_cistatic int __init rzv2m_pinctrl_init(void)
111362306a36Sopenharmony_ci{
111462306a36Sopenharmony_ci	return platform_driver_register(&rzv2m_pinctrl_driver);
111562306a36Sopenharmony_ci}
111662306a36Sopenharmony_cicore_initcall(rzv2m_pinctrl_init);
111762306a36Sopenharmony_ci
111862306a36Sopenharmony_ciMODULE_AUTHOR("Phil Edworthy <phil.edworthy@renesas.com>");
111962306a36Sopenharmony_ciMODULE_DESCRIPTION("Pin and gpio controller driver for RZ/V2M");
1120