xref: /linux/drivers/pinctrl/renesas/pinctrl-rzt2h.c (revision ec2e0fb07d789976c601bec19ecced7a501c3705)
134d4d093SThierry Bultel // SPDX-License-Identifier: GPL-2.0
234d4d093SThierry Bultel /*
334d4d093SThierry Bultel  * Renesas RZ/T2H Pin Control and GPIO driver core
434d4d093SThierry Bultel  *
534d4d093SThierry Bultel  * Based on drivers/pinctrl/renesas/pinctrl-rzg2l.c
634d4d093SThierry Bultel  *
734d4d093SThierry Bultel  * Copyright (C) 2025 Renesas Electronics Corporation.
834d4d093SThierry Bultel  */
934d4d093SThierry Bultel 
1034d4d093SThierry Bultel #include <linux/bitfield.h>
1134d4d093SThierry Bultel #include <linux/bitops.h>
1234d4d093SThierry Bultel #include <linux/bits.h>
1334d4d093SThierry Bultel #include <linux/cleanup.h>
1434d4d093SThierry Bultel #include <linux/clk.h>
1534d4d093SThierry Bultel #include <linux/gpio/driver.h>
1634d4d093SThierry Bultel #include <linux/io.h>
1734d4d093SThierry Bultel #include <linux/ioport.h>
1834d4d093SThierry Bultel #include <linux/module.h>
1934d4d093SThierry Bultel #include <linux/mutex.h>
2034d4d093SThierry Bultel #include <linux/of_device.h>
2134d4d093SThierry Bultel #include <linux/platform_device.h>
2234d4d093SThierry Bultel #include <linux/pm_runtime.h>
2334d4d093SThierry Bultel #include <linux/spinlock.h>
2434d4d093SThierry Bultel #include <linux/types.h>
2534d4d093SThierry Bultel 
2634d4d093SThierry Bultel #include <linux/pinctrl/consumer.h>
2734d4d093SThierry Bultel #include <linux/pinctrl/pinconf-generic.h>
2834d4d093SThierry Bultel #include <linux/pinctrl/pinconf.h>
2934d4d093SThierry Bultel #include <linux/pinctrl/pinctrl.h>
3034d4d093SThierry Bultel #include <linux/pinctrl/pinmux.h>
3134d4d093SThierry Bultel 
3234d4d093SThierry Bultel #include <dt-bindings/pinctrl/renesas,r9a09g077-pinctrl.h>
3334d4d093SThierry Bultel 
3434d4d093SThierry Bultel #include "../core.h"
3534d4d093SThierry Bultel #include "../pinconf.h"
3634d4d093SThierry Bultel #include "../pinmux.h"
3734d4d093SThierry Bultel 
3834d4d093SThierry Bultel #define DRV_NAME	"pinctrl-rzt2h"
3934d4d093SThierry Bultel 
4034d4d093SThierry Bultel #define P(m)		(0x001 * (m))
4134d4d093SThierry Bultel #define PM(m)		(0x200 + 2 * (m))
4234d4d093SThierry Bultel #define PMC(m)		(0x400 + (m))
4334d4d093SThierry Bultel #define PFC(m)		(0x600 + 8 * (m))
4434d4d093SThierry Bultel #define PIN(m)		(0x800 + (m))
4534d4d093SThierry Bultel #define RSELP(m)	(0xc00 + (m))
4634d4d093SThierry Bultel 
4734d4d093SThierry Bultel #define PM_MASK			GENMASK(1, 0)
4834d4d093SThierry Bultel #define PM_PIN_MASK(pin)	(PM_MASK << ((pin) * 2))
4934d4d093SThierry Bultel #define PM_INPUT		BIT(0)
5034d4d093SThierry Bultel #define PM_OUTPUT		BIT(1)
5134d4d093SThierry Bultel 
5234d4d093SThierry Bultel #define PFC_MASK		GENMASK_ULL(5, 0)
5334d4d093SThierry Bultel #define PFC_PIN_MASK(pin)	(PFC_MASK << ((pin) * 8))
5434d4d093SThierry Bultel 
5534d4d093SThierry Bultel /*
5634d4d093SThierry Bultel  * Use 16 lower bits [15:0] for pin identifier
5734d4d093SThierry Bultel  * Use 8 higher bits [23:16] for pin mux function
5834d4d093SThierry Bultel  */
5934d4d093SThierry Bultel #define MUX_PIN_ID_MASK		GENMASK(15, 0)
6034d4d093SThierry Bultel #define MUX_FUNC_MASK		GENMASK(23, 16)
6134d4d093SThierry Bultel 
6234d4d093SThierry Bultel #define RZT2H_PIN_ID_TO_PORT(id)	((id) / RZT2H_PINS_PER_PORT)
6334d4d093SThierry Bultel #define RZT2H_PIN_ID_TO_PIN(id)		((id) % RZT2H_PINS_PER_PORT)
6434d4d093SThierry Bultel 
6534d4d093SThierry Bultel #define RZT2H_MAX_SAFETY_PORTS		12
6634d4d093SThierry Bultel 
6734d4d093SThierry Bultel struct rzt2h_pinctrl_data {
6834d4d093SThierry Bultel 	unsigned int n_port_pins;
6934d4d093SThierry Bultel 	const u8 *port_pin_configs;
7034d4d093SThierry Bultel 	unsigned int n_ports;
7134d4d093SThierry Bultel };
7234d4d093SThierry Bultel 
7334d4d093SThierry Bultel struct rzt2h_pinctrl {
7434d4d093SThierry Bultel 	struct pinctrl_dev		*pctl;
7534d4d093SThierry Bultel 	struct pinctrl_desc		desc;
7634d4d093SThierry Bultel 	struct pinctrl_pin_desc		*pins;
7734d4d093SThierry Bultel 	const struct rzt2h_pinctrl_data	*data;
7834d4d093SThierry Bultel 	void __iomem			*base0, *base1;
7934d4d093SThierry Bultel 	struct device			*dev;
8034d4d093SThierry Bultel 	struct gpio_chip		gpio_chip;
8134d4d093SThierry Bultel 	struct pinctrl_gpio_range	gpio_range;
8234d4d093SThierry Bultel 	spinlock_t			lock; /* lock read/write registers */
8334d4d093SThierry Bultel 	struct mutex			mutex; /* serialize adding groups and functions */
8434d4d093SThierry Bultel 	bool				safety_port_enabled;
8534d4d093SThierry Bultel };
8634d4d093SThierry Bultel 
8734d4d093SThierry Bultel #define RZT2H_GET_BASE(pctrl, port) \
8834d4d093SThierry Bultel 	((port) > RZT2H_MAX_SAFETY_PORTS ? (pctrl)->base0 : (pctrl)->base1)
8934d4d093SThierry Bultel 
9034d4d093SThierry Bultel #define RZT2H_PINCTRL_REG_ACCESS(size, type)						\
9134d4d093SThierry Bultel static inline void rzt2h_pinctrl_write##size(struct rzt2h_pinctrl *pctrl, u8 port,	\
9234d4d093SThierry Bultel 					     type val, unsigned int offset)		\
9334d4d093SThierry Bultel {											\
9434d4d093SThierry Bultel 	write##size(val, RZT2H_GET_BASE(pctrl, port) + offset);				\
9534d4d093SThierry Bultel }											\
9634d4d093SThierry Bultel static inline type rzt2h_pinctrl_read##size(struct rzt2h_pinctrl *pctrl, u8 port,	\
9734d4d093SThierry Bultel 					    unsigned int offset)			\
9834d4d093SThierry Bultel {											\
9934d4d093SThierry Bultel 	return read##size(RZT2H_GET_BASE(pctrl, port) + offset);			\
10034d4d093SThierry Bultel }
10134d4d093SThierry Bultel 
10234d4d093SThierry Bultel RZT2H_PINCTRL_REG_ACCESS(b, u8)
10334d4d093SThierry Bultel RZT2H_PINCTRL_REG_ACCESS(w, u16)
10434d4d093SThierry Bultel RZT2H_PINCTRL_REG_ACCESS(q, u64)
10534d4d093SThierry Bultel 
10634d4d093SThierry Bultel static int rzt2h_validate_pin(struct rzt2h_pinctrl *pctrl, unsigned int offset)
10734d4d093SThierry Bultel {
10834d4d093SThierry Bultel 	u8 port = RZT2H_PIN_ID_TO_PORT(offset);
10934d4d093SThierry Bultel 	u8 pin = RZT2H_PIN_ID_TO_PIN(offset);
11034d4d093SThierry Bultel 	u8 pincfg;
11134d4d093SThierry Bultel 
11234d4d093SThierry Bultel 	if (offset >= pctrl->data->n_port_pins || port >= pctrl->data->n_ports)
11334d4d093SThierry Bultel 		return -EINVAL;
11434d4d093SThierry Bultel 
11534d4d093SThierry Bultel 	if (!pctrl->safety_port_enabled && port <= RZT2H_MAX_SAFETY_PORTS)
11634d4d093SThierry Bultel 		return -EINVAL;
11734d4d093SThierry Bultel 
11834d4d093SThierry Bultel 	pincfg = pctrl->data->port_pin_configs[port];
11934d4d093SThierry Bultel 	return (pincfg & BIT(pin)) ? 0 : -EINVAL;
12034d4d093SThierry Bultel }
12134d4d093SThierry Bultel 
12234d4d093SThierry Bultel static void rzt2h_pinctrl_set_pfc_mode(struct rzt2h_pinctrl *pctrl,
12334d4d093SThierry Bultel 				       u8 port, u8 pin, u8 func)
12434d4d093SThierry Bultel {
12534d4d093SThierry Bultel 	u64 reg64;
12634d4d093SThierry Bultel 	u16 reg16;
12734d4d093SThierry Bultel 
12834d4d093SThierry Bultel 	guard(spinlock_irqsave)(&pctrl->lock);
12934d4d093SThierry Bultel 
13034d4d093SThierry Bultel 	/* Set pin to 'Non-use (Hi-Z input protection)'  */
13134d4d093SThierry Bultel 	reg16 = rzt2h_pinctrl_readw(pctrl, port, PM(port));
13234d4d093SThierry Bultel 	reg16 &= ~PM_PIN_MASK(pin);
13334d4d093SThierry Bultel 	rzt2h_pinctrl_writew(pctrl, port, reg16, PM(port));
13434d4d093SThierry Bultel 
13534d4d093SThierry Bultel 	/* Temporarily switch to GPIO mode with PMC register */
13634d4d093SThierry Bultel 	reg16 = rzt2h_pinctrl_readb(pctrl, port, PMC(port));
13734d4d093SThierry Bultel 	rzt2h_pinctrl_writeb(pctrl, port, reg16 & ~BIT(pin), PMC(port));
13834d4d093SThierry Bultel 
13934d4d093SThierry Bultel 	/* Select Pin function mode with PFC register */
14034d4d093SThierry Bultel 	reg64 = rzt2h_pinctrl_readq(pctrl, port, PFC(port));
14134d4d093SThierry Bultel 	reg64 &= ~PFC_PIN_MASK(pin);
14234d4d093SThierry Bultel 	rzt2h_pinctrl_writeq(pctrl, port, reg64 | ((u64)func << (pin * 8)), PFC(port));
14334d4d093SThierry Bultel 
14434d4d093SThierry Bultel 	/* Switch to Peripheral pin function with PMC register */
14534d4d093SThierry Bultel 	reg16 = rzt2h_pinctrl_readb(pctrl, port, PMC(port));
14634d4d093SThierry Bultel 	rzt2h_pinctrl_writeb(pctrl, port, reg16 | BIT(pin), PMC(port));
14734d4d093SThierry Bultel };
14834d4d093SThierry Bultel 
14934d4d093SThierry Bultel static int rzt2h_pinctrl_set_mux(struct pinctrl_dev *pctldev,
15034d4d093SThierry Bultel 				 unsigned int func_selector,
15134d4d093SThierry Bultel 				 unsigned int group_selector)
15234d4d093SThierry Bultel {
15334d4d093SThierry Bultel 	struct rzt2h_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
15434d4d093SThierry Bultel 	const struct function_desc *func;
15534d4d093SThierry Bultel 	struct group_desc *group;
15634d4d093SThierry Bultel 	const unsigned int *pins;
15734d4d093SThierry Bultel 	unsigned int i;
15834d4d093SThierry Bultel 	u8 *psel_val;
15934d4d093SThierry Bultel 	int ret;
16034d4d093SThierry Bultel 
16134d4d093SThierry Bultel 	func = pinmux_generic_get_function(pctldev, func_selector);
16234d4d093SThierry Bultel 	if (!func)
16334d4d093SThierry Bultel 		return -EINVAL;
16434d4d093SThierry Bultel 
16534d4d093SThierry Bultel 	group = pinctrl_generic_get_group(pctldev, group_selector);
16634d4d093SThierry Bultel 	if (!group)
16734d4d093SThierry Bultel 		return -EINVAL;
16834d4d093SThierry Bultel 
16934d4d093SThierry Bultel 	psel_val = func->data;
17034d4d093SThierry Bultel 	pins = group->grp.pins;
17134d4d093SThierry Bultel 
17234d4d093SThierry Bultel 	for (i = 0; i < group->grp.npins; i++) {
17334d4d093SThierry Bultel 		dev_dbg(pctrl->dev, "port:%u pin:%u PSEL:%u\n",
17434d4d093SThierry Bultel 			RZT2H_PIN_ID_TO_PORT(pins[i]), RZT2H_PIN_ID_TO_PIN(pins[i]),
17534d4d093SThierry Bultel 			psel_val[i]);
17634d4d093SThierry Bultel 		ret = rzt2h_validate_pin(pctrl, pins[i]);
17734d4d093SThierry Bultel 		if (ret)
17834d4d093SThierry Bultel 			return ret;
17934d4d093SThierry Bultel 
18034d4d093SThierry Bultel 		rzt2h_pinctrl_set_pfc_mode(pctrl, RZT2H_PIN_ID_TO_PORT(pins[i]),
18134d4d093SThierry Bultel 					   RZT2H_PIN_ID_TO_PIN(pins[i]), psel_val[i]);
18234d4d093SThierry Bultel 	}
18334d4d093SThierry Bultel 
18434d4d093SThierry Bultel 	return 0;
18534d4d093SThierry Bultel };
18634d4d093SThierry Bultel 
18734d4d093SThierry Bultel static int rzt2h_map_add_config(struct pinctrl_map *map,
18834d4d093SThierry Bultel 				const char *group_or_pin,
18934d4d093SThierry Bultel 				enum pinctrl_map_type type,
19034d4d093SThierry Bultel 				unsigned long *configs,
19134d4d093SThierry Bultel 				unsigned int num_configs)
19234d4d093SThierry Bultel {
19334d4d093SThierry Bultel 	unsigned long *cfgs;
19434d4d093SThierry Bultel 
19534d4d093SThierry Bultel 	cfgs = kmemdup_array(configs, num_configs, sizeof(*cfgs), GFP_KERNEL);
19634d4d093SThierry Bultel 	if (!cfgs)
19734d4d093SThierry Bultel 		return -ENOMEM;
19834d4d093SThierry Bultel 
19934d4d093SThierry Bultel 	map->type = type;
20034d4d093SThierry Bultel 	map->data.configs.group_or_pin = group_or_pin;
20134d4d093SThierry Bultel 	map->data.configs.configs = cfgs;
20234d4d093SThierry Bultel 	map->data.configs.num_configs = num_configs;
20334d4d093SThierry Bultel 
20434d4d093SThierry Bultel 	return 0;
20534d4d093SThierry Bultel }
20634d4d093SThierry Bultel 
20734d4d093SThierry Bultel static int rzt2h_dt_subnode_to_map(struct pinctrl_dev *pctldev,
20834d4d093SThierry Bultel 				   struct device_node *np,
20934d4d093SThierry Bultel 				   struct device_node *parent,
21034d4d093SThierry Bultel 				   struct pinctrl_map **map,
21134d4d093SThierry Bultel 				   unsigned int *num_maps,
21234d4d093SThierry Bultel 				   unsigned int *index)
21334d4d093SThierry Bultel {
21434d4d093SThierry Bultel 	struct rzt2h_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
21534d4d093SThierry Bultel 	struct pinctrl_map *maps = *map;
21634d4d093SThierry Bultel 	unsigned int nmaps = *num_maps;
21734d4d093SThierry Bultel 	unsigned long *configs = NULL;
21834d4d093SThierry Bultel 	unsigned int num_pinmux = 0;
21934d4d093SThierry Bultel 	unsigned int idx = *index;
22034d4d093SThierry Bultel 	unsigned int num_pins, i;
22134d4d093SThierry Bultel 	unsigned int num_configs;
22234d4d093SThierry Bultel 	struct property *pinmux;
22334d4d093SThierry Bultel 	struct property *prop;
22434d4d093SThierry Bultel 	int ret, gsel, fsel;
22534d4d093SThierry Bultel 	const char **pin_fn;
22634d4d093SThierry Bultel 	unsigned int *pins;
22734d4d093SThierry Bultel 	const char *name;
22834d4d093SThierry Bultel 	const char *pin;
22934d4d093SThierry Bultel 	u8 *psel_val;
23034d4d093SThierry Bultel 
23134d4d093SThierry Bultel 	pinmux = of_find_property(np, "pinmux", NULL);
23234d4d093SThierry Bultel 	if (pinmux)
23334d4d093SThierry Bultel 		num_pinmux = pinmux->length / sizeof(u32);
23434d4d093SThierry Bultel 
23534d4d093SThierry Bultel 	ret = of_property_count_strings(np, "pins");
23634d4d093SThierry Bultel 	if (ret == -EINVAL) {
23734d4d093SThierry Bultel 		num_pins = 0;
23834d4d093SThierry Bultel 	} else if (ret < 0) {
23934d4d093SThierry Bultel 		dev_err(pctrl->dev, "Invalid pins list in DT\n");
24034d4d093SThierry Bultel 		return ret;
24134d4d093SThierry Bultel 	} else {
24234d4d093SThierry Bultel 		num_pins = ret;
24334d4d093SThierry Bultel 	}
24434d4d093SThierry Bultel 
24534d4d093SThierry Bultel 	if (!num_pinmux && !num_pins)
24634d4d093SThierry Bultel 		return 0;
24734d4d093SThierry Bultel 
24834d4d093SThierry Bultel 	if (num_pinmux && num_pins) {
24934d4d093SThierry Bultel 		dev_err(pctrl->dev,
25034d4d093SThierry Bultel 			"DT node must contain either a pinmux or pins and not both\n");
25134d4d093SThierry Bultel 		return -EINVAL;
25234d4d093SThierry Bultel 	}
25334d4d093SThierry Bultel 
25434d4d093SThierry Bultel 	ret = pinconf_generic_parse_dt_config(np, pctldev, &configs, &num_configs);
25534d4d093SThierry Bultel 	if (ret < 0)
25634d4d093SThierry Bultel 		return ret;
25734d4d093SThierry Bultel 
25834d4d093SThierry Bultel 	if (num_pins && !num_configs) {
25934d4d093SThierry Bultel 		dev_err(pctrl->dev, "DT node must contain a config\n");
26034d4d093SThierry Bultel 		ret = -ENODEV;
26134d4d093SThierry Bultel 		goto done;
26234d4d093SThierry Bultel 	}
26334d4d093SThierry Bultel 
26434d4d093SThierry Bultel 	if (num_pinmux) {
26534d4d093SThierry Bultel 		nmaps += 1;
26634d4d093SThierry Bultel 		if (num_configs)
26734d4d093SThierry Bultel 			nmaps += 1;
26834d4d093SThierry Bultel 	}
26934d4d093SThierry Bultel 
27034d4d093SThierry Bultel 	if (num_pins)
27134d4d093SThierry Bultel 		nmaps += num_pins;
27234d4d093SThierry Bultel 
27334d4d093SThierry Bultel 	maps = krealloc_array(maps, nmaps, sizeof(*maps), GFP_KERNEL);
27434d4d093SThierry Bultel 	if (!maps) {
27534d4d093SThierry Bultel 		ret = -ENOMEM;
27634d4d093SThierry Bultel 		goto done;
27734d4d093SThierry Bultel 	}
27834d4d093SThierry Bultel 
27934d4d093SThierry Bultel 	*map = maps;
28034d4d093SThierry Bultel 	*num_maps = nmaps;
28134d4d093SThierry Bultel 	if (num_pins) {
28234d4d093SThierry Bultel 		of_property_for_each_string(np, "pins", prop, pin) {
28334d4d093SThierry Bultel 			ret = rzt2h_map_add_config(&maps[idx], pin,
28434d4d093SThierry Bultel 						   PIN_MAP_TYPE_CONFIGS_PIN,
28534d4d093SThierry Bultel 						   configs, num_configs);
28634d4d093SThierry Bultel 			if (ret < 0)
28734d4d093SThierry Bultel 				goto done;
28834d4d093SThierry Bultel 
28934d4d093SThierry Bultel 			idx++;
29034d4d093SThierry Bultel 		}
29134d4d093SThierry Bultel 		ret = 0;
29234d4d093SThierry Bultel 		goto done;
29334d4d093SThierry Bultel 	}
29434d4d093SThierry Bultel 
29534d4d093SThierry Bultel 	pins = devm_kcalloc(pctrl->dev, num_pinmux, sizeof(*pins), GFP_KERNEL);
29634d4d093SThierry Bultel 	psel_val = devm_kcalloc(pctrl->dev, num_pinmux, sizeof(*psel_val),
29734d4d093SThierry Bultel 				GFP_KERNEL);
29834d4d093SThierry Bultel 	pin_fn = devm_kzalloc(pctrl->dev, sizeof(*pin_fn), GFP_KERNEL);
29934d4d093SThierry Bultel 	if (!pins || !psel_val || !pin_fn) {
30034d4d093SThierry Bultel 		ret = -ENOMEM;
30134d4d093SThierry Bultel 		goto done;
30234d4d093SThierry Bultel 	}
30334d4d093SThierry Bultel 
30434d4d093SThierry Bultel 	/* Collect pin locations and mux settings from DT properties */
30534d4d093SThierry Bultel 	for (i = 0; i < num_pinmux; ++i) {
30634d4d093SThierry Bultel 		u32 value;
30734d4d093SThierry Bultel 
30834d4d093SThierry Bultel 		ret = of_property_read_u32_index(np, "pinmux", i, &value);
30934d4d093SThierry Bultel 		if (ret)
31034d4d093SThierry Bultel 			goto done;
31134d4d093SThierry Bultel 		pins[i] = FIELD_GET(MUX_PIN_ID_MASK, value);
31234d4d093SThierry Bultel 		psel_val[i] = FIELD_GET(MUX_FUNC_MASK, value);
31334d4d093SThierry Bultel 	}
31434d4d093SThierry Bultel 
31534d4d093SThierry Bultel 	if (parent) {
31634d4d093SThierry Bultel 		name = devm_kasprintf(pctrl->dev, GFP_KERNEL, "%pOFn.%pOFn",
31734d4d093SThierry Bultel 				      parent, np);
31834d4d093SThierry Bultel 		if (!name) {
31934d4d093SThierry Bultel 			ret = -ENOMEM;
32034d4d093SThierry Bultel 			goto done;
32134d4d093SThierry Bultel 		}
32234d4d093SThierry Bultel 	} else {
32334d4d093SThierry Bultel 		name = np->name;
32434d4d093SThierry Bultel 	}
32534d4d093SThierry Bultel 
32634d4d093SThierry Bultel 	if (num_configs) {
32734d4d093SThierry Bultel 		ret = rzt2h_map_add_config(&maps[idx], name,
32834d4d093SThierry Bultel 					   PIN_MAP_TYPE_CONFIGS_GROUP,
32934d4d093SThierry Bultel 					   configs, num_configs);
33034d4d093SThierry Bultel 		if (ret < 0)
33134d4d093SThierry Bultel 			goto done;
33234d4d093SThierry Bultel 
33334d4d093SThierry Bultel 		idx++;
33434d4d093SThierry Bultel 	}
33534d4d093SThierry Bultel 
33634d4d093SThierry Bultel 	scoped_guard(mutex, &pctrl->mutex) {
33734d4d093SThierry Bultel 		/* Register a single pin group listing all the pins we read from DT */
33834d4d093SThierry Bultel 		gsel = pinctrl_generic_add_group(pctldev, name, pins, num_pinmux, NULL);
33934d4d093SThierry Bultel 		if (gsel < 0) {
34034d4d093SThierry Bultel 			ret = gsel;
34134d4d093SThierry Bultel 			goto done;
34234d4d093SThierry Bultel 		}
34334d4d093SThierry Bultel 
34434d4d093SThierry Bultel 		/*
34534d4d093SThierry Bultel 		 * Register a single group function where the 'data' is an array PSEL
34634d4d093SThierry Bultel 		 * register values read from DT.
34734d4d093SThierry Bultel 		 */
34834d4d093SThierry Bultel 		pin_fn[0] = name;
34934d4d093SThierry Bultel 		fsel = pinmux_generic_add_function(pctldev, name, pin_fn, 1, psel_val);
35034d4d093SThierry Bultel 		if (fsel < 0) {
35134d4d093SThierry Bultel 			ret = fsel;
35234d4d093SThierry Bultel 			goto remove_group;
35334d4d093SThierry Bultel 		}
35434d4d093SThierry Bultel 	}
35534d4d093SThierry Bultel 
35634d4d093SThierry Bultel 	maps[idx].type = PIN_MAP_TYPE_MUX_GROUP;
35734d4d093SThierry Bultel 	maps[idx].data.mux.group = name;
35834d4d093SThierry Bultel 	maps[idx].data.mux.function = name;
35934d4d093SThierry Bultel 	idx++;
36034d4d093SThierry Bultel 
36134d4d093SThierry Bultel 	dev_dbg(pctrl->dev, "Parsed %pOF with %d pins\n", np, num_pinmux);
36234d4d093SThierry Bultel 	ret = 0;
36334d4d093SThierry Bultel 	goto done;
36434d4d093SThierry Bultel 
36534d4d093SThierry Bultel remove_group:
36634d4d093SThierry Bultel 	pinctrl_generic_remove_group(pctldev, gsel);
36734d4d093SThierry Bultel done:
36834d4d093SThierry Bultel 	*index = idx;
36934d4d093SThierry Bultel 	kfree(configs);
37034d4d093SThierry Bultel 	return ret;
37134d4d093SThierry Bultel }
37234d4d093SThierry Bultel 
37334d4d093SThierry Bultel static void rzt2h_dt_free_map(struct pinctrl_dev *pctldev,
37434d4d093SThierry Bultel 			      struct pinctrl_map *map,
37534d4d093SThierry Bultel 			      unsigned int num_maps)
37634d4d093SThierry Bultel {
37734d4d093SThierry Bultel 	unsigned int i;
37834d4d093SThierry Bultel 
37934d4d093SThierry Bultel 	if (!map)
38034d4d093SThierry Bultel 		return;
38134d4d093SThierry Bultel 
38234d4d093SThierry Bultel 	for (i = 0; i < num_maps; ++i) {
38334d4d093SThierry Bultel 		if (map[i].type == PIN_MAP_TYPE_CONFIGS_GROUP ||
38434d4d093SThierry Bultel 		    map[i].type == PIN_MAP_TYPE_CONFIGS_PIN)
38534d4d093SThierry Bultel 			kfree(map[i].data.configs.configs);
38634d4d093SThierry Bultel 	}
38734d4d093SThierry Bultel 	kfree(map);
38834d4d093SThierry Bultel }
38934d4d093SThierry Bultel 
39034d4d093SThierry Bultel static int rzt2h_dt_node_to_map(struct pinctrl_dev *pctldev,
39134d4d093SThierry Bultel 				struct device_node *np,
39234d4d093SThierry Bultel 				struct pinctrl_map **map,
39334d4d093SThierry Bultel 				unsigned int *num_maps)
39434d4d093SThierry Bultel {
39534d4d093SThierry Bultel 	struct rzt2h_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
39634d4d093SThierry Bultel 	unsigned int index;
39734d4d093SThierry Bultel 	int ret;
39834d4d093SThierry Bultel 
39934d4d093SThierry Bultel 	*map = NULL;
40034d4d093SThierry Bultel 	*num_maps = 0;
40134d4d093SThierry Bultel 	index = 0;
40234d4d093SThierry Bultel 
40334d4d093SThierry Bultel 	for_each_child_of_node_scoped(np, child) {
40434d4d093SThierry Bultel 		ret = rzt2h_dt_subnode_to_map(pctldev, child, np, map,
40534d4d093SThierry Bultel 					      num_maps, &index);
40634d4d093SThierry Bultel 		if (ret < 0)
40734d4d093SThierry Bultel 			goto done;
40834d4d093SThierry Bultel 	}
40934d4d093SThierry Bultel 
41034d4d093SThierry Bultel 	if (*num_maps == 0) {
41134d4d093SThierry Bultel 		ret = rzt2h_dt_subnode_to_map(pctldev, np, NULL, map,
41234d4d093SThierry Bultel 					      num_maps, &index);
41334d4d093SThierry Bultel 		if (ret < 0)
41434d4d093SThierry Bultel 			goto done;
41534d4d093SThierry Bultel 	}
41634d4d093SThierry Bultel 
41734d4d093SThierry Bultel 	if (*num_maps)
41834d4d093SThierry Bultel 		return 0;
41934d4d093SThierry Bultel 
42034d4d093SThierry Bultel 	dev_err(pctrl->dev, "no mapping found in node %pOF\n", np);
42134d4d093SThierry Bultel 	ret = -EINVAL;
42234d4d093SThierry Bultel 
42334d4d093SThierry Bultel done:
42434d4d093SThierry Bultel 	rzt2h_dt_free_map(pctldev, *map, *num_maps);
42534d4d093SThierry Bultel 	return ret;
42634d4d093SThierry Bultel }
42734d4d093SThierry Bultel 
42834d4d093SThierry Bultel static const struct pinctrl_ops rzt2h_pinctrl_pctlops = {
42934d4d093SThierry Bultel 	.get_groups_count = pinctrl_generic_get_group_count,
43034d4d093SThierry Bultel 	.get_group_name = pinctrl_generic_get_group_name,
43134d4d093SThierry Bultel 	.get_group_pins = pinctrl_generic_get_group_pins,
43234d4d093SThierry Bultel 	.dt_node_to_map = rzt2h_dt_node_to_map,
43334d4d093SThierry Bultel 	.dt_free_map = rzt2h_dt_free_map,
43434d4d093SThierry Bultel };
43534d4d093SThierry Bultel 
43634d4d093SThierry Bultel static const struct pinmux_ops rzt2h_pinctrl_pmxops = {
43734d4d093SThierry Bultel 	.get_functions_count = pinmux_generic_get_function_count,
43834d4d093SThierry Bultel 	.get_function_name = pinmux_generic_get_function_name,
43934d4d093SThierry Bultel 	.get_function_groups = pinmux_generic_get_function_groups,
44034d4d093SThierry Bultel 	.set_mux = rzt2h_pinctrl_set_mux,
44134d4d093SThierry Bultel 	.strict = true,
44234d4d093SThierry Bultel };
44334d4d093SThierry Bultel 
44434d4d093SThierry Bultel static int rzt2h_gpio_request(struct gpio_chip *chip, unsigned int offset)
44534d4d093SThierry Bultel {
44634d4d093SThierry Bultel 	struct rzt2h_pinctrl *pctrl = gpiochip_get_data(chip);
44734d4d093SThierry Bultel 	u8 port = RZT2H_PIN_ID_TO_PORT(offset);
44834d4d093SThierry Bultel 	u8 bit = RZT2H_PIN_ID_TO_PIN(offset);
44934d4d093SThierry Bultel 	int ret;
45034d4d093SThierry Bultel 	u8 reg;
45134d4d093SThierry Bultel 
45234d4d093SThierry Bultel 	ret = rzt2h_validate_pin(pctrl, offset);
45334d4d093SThierry Bultel 	if (ret)
45434d4d093SThierry Bultel 		return ret;
45534d4d093SThierry Bultel 
45634d4d093SThierry Bultel 	ret = pinctrl_gpio_request(chip, offset);
45734d4d093SThierry Bultel 	if (ret)
45834d4d093SThierry Bultel 		return ret;
45934d4d093SThierry Bultel 
46034d4d093SThierry Bultel 	guard(spinlock_irqsave)(&pctrl->lock);
46134d4d093SThierry Bultel 
46234d4d093SThierry Bultel 	/* Select GPIO mode in PMC Register */
46334d4d093SThierry Bultel 	reg = rzt2h_pinctrl_readb(pctrl, port, PMC(port));
46434d4d093SThierry Bultel 	reg &= ~BIT(bit);
46534d4d093SThierry Bultel 	rzt2h_pinctrl_writeb(pctrl, port, reg, PMC(port));
46634d4d093SThierry Bultel 
46734d4d093SThierry Bultel 	return 0;
46834d4d093SThierry Bultel }
46934d4d093SThierry Bultel 
47034d4d093SThierry Bultel static void rzt2h_gpio_set_direction(struct rzt2h_pinctrl *pctrl, u32 port,
47134d4d093SThierry Bultel 				     u8 bit, bool output)
47234d4d093SThierry Bultel {
47334d4d093SThierry Bultel 	u16 reg;
47434d4d093SThierry Bultel 
47534d4d093SThierry Bultel 	guard(spinlock_irqsave)(&pctrl->lock);
47634d4d093SThierry Bultel 
47734d4d093SThierry Bultel 	reg = rzt2h_pinctrl_readw(pctrl, port, PM(port));
47834d4d093SThierry Bultel 	reg &= ~PM_PIN_MASK(bit);
47934d4d093SThierry Bultel 
48034d4d093SThierry Bultel 	reg |= (output ? PM_OUTPUT : PM_INPUT) << (bit * 2);
48134d4d093SThierry Bultel 	rzt2h_pinctrl_writew(pctrl, port, reg, PM(port));
48234d4d093SThierry Bultel }
48334d4d093SThierry Bultel 
48434d4d093SThierry Bultel static int rzt2h_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
48534d4d093SThierry Bultel {
48634d4d093SThierry Bultel 	struct rzt2h_pinctrl *pctrl = gpiochip_get_data(chip);
48734d4d093SThierry Bultel 	u8 port = RZT2H_PIN_ID_TO_PORT(offset);
48834d4d093SThierry Bultel 	u8 bit = RZT2H_PIN_ID_TO_PIN(offset);
48934d4d093SThierry Bultel 	u16 reg;
49034d4d093SThierry Bultel 	int ret;
49134d4d093SThierry Bultel 
49234d4d093SThierry Bultel 	ret = rzt2h_validate_pin(pctrl, offset);
49334d4d093SThierry Bultel 	if (ret)
49434d4d093SThierry Bultel 		return ret;
49534d4d093SThierry Bultel 
49634d4d093SThierry Bultel 	if (rzt2h_pinctrl_readb(pctrl, port, PMC(port)) & BIT(bit))
49734d4d093SThierry Bultel 		return -EINVAL;
49834d4d093SThierry Bultel 
49934d4d093SThierry Bultel 	reg = rzt2h_pinctrl_readw(pctrl, port, PM(port));
50034d4d093SThierry Bultel 	reg = (reg >> (bit * 2)) & PM_MASK;
50134d4d093SThierry Bultel 	if (reg & PM_OUTPUT)
50234d4d093SThierry Bultel 		return GPIO_LINE_DIRECTION_OUT;
50334d4d093SThierry Bultel 	if (reg & PM_INPUT)
50434d4d093SThierry Bultel 		return GPIO_LINE_DIRECTION_IN;
50534d4d093SThierry Bultel 
50634d4d093SThierry Bultel 	return -EINVAL;
50734d4d093SThierry Bultel }
50834d4d093SThierry Bultel 
50934d4d093SThierry Bultel static int rzt2h_gpio_set(struct gpio_chip *chip, unsigned int offset,
51034d4d093SThierry Bultel 			  int value)
51134d4d093SThierry Bultel {
51234d4d093SThierry Bultel 	struct rzt2h_pinctrl *pctrl = gpiochip_get_data(chip);
51334d4d093SThierry Bultel 	u8 port = RZT2H_PIN_ID_TO_PORT(offset);
51434d4d093SThierry Bultel 	u8 bit = RZT2H_PIN_ID_TO_PIN(offset);
51534d4d093SThierry Bultel 	u8 reg;
51634d4d093SThierry Bultel 
51734d4d093SThierry Bultel 	guard(spinlock_irqsave)(&pctrl->lock);
51834d4d093SThierry Bultel 
51934d4d093SThierry Bultel 	reg = rzt2h_pinctrl_readb(pctrl, port, P(port));
52034d4d093SThierry Bultel 	if (value)
52134d4d093SThierry Bultel 		rzt2h_pinctrl_writeb(pctrl, port, reg | BIT(bit), P(port));
52234d4d093SThierry Bultel 	else
52334d4d093SThierry Bultel 		rzt2h_pinctrl_writeb(pctrl, port, reg & ~BIT(bit), P(port));
52434d4d093SThierry Bultel 
52534d4d093SThierry Bultel 	return 0;
52634d4d093SThierry Bultel }
52734d4d093SThierry Bultel 
52834d4d093SThierry Bultel static int rzt2h_gpio_get(struct gpio_chip *chip, unsigned int offset)
52934d4d093SThierry Bultel {
53034d4d093SThierry Bultel 	struct rzt2h_pinctrl *pctrl = gpiochip_get_data(chip);
53134d4d093SThierry Bultel 	u8 port = RZT2H_PIN_ID_TO_PORT(offset);
53234d4d093SThierry Bultel 	u8 bit = RZT2H_PIN_ID_TO_PIN(offset);
53334d4d093SThierry Bultel 	u16 reg;
53434d4d093SThierry Bultel 
53534d4d093SThierry Bultel 	reg = rzt2h_pinctrl_readw(pctrl, port, PM(port));
53634d4d093SThierry Bultel 	reg = (reg >> (bit * 2)) & PM_MASK;
53734d4d093SThierry Bultel 	if (reg & PM_INPUT)
53834d4d093SThierry Bultel 		return !!(rzt2h_pinctrl_readb(pctrl, port, PIN(port)) & BIT(bit));
53934d4d093SThierry Bultel 	if (reg & PM_OUTPUT)
54034d4d093SThierry Bultel 		return !!(rzt2h_pinctrl_readb(pctrl, port, P(port)) & BIT(bit));
54134d4d093SThierry Bultel 
54234d4d093SThierry Bultel 	return -EINVAL;
54334d4d093SThierry Bultel }
54434d4d093SThierry Bultel 
54534d4d093SThierry Bultel static int rzt2h_gpio_direction_input(struct gpio_chip *chip,
54634d4d093SThierry Bultel 				      unsigned int offset)
54734d4d093SThierry Bultel {
54834d4d093SThierry Bultel 	struct rzt2h_pinctrl *pctrl = gpiochip_get_data(chip);
54934d4d093SThierry Bultel 	u8 port = RZT2H_PIN_ID_TO_PORT(offset);
55034d4d093SThierry Bultel 	u8 bit = RZT2H_PIN_ID_TO_PIN(offset);
55134d4d093SThierry Bultel 
55234d4d093SThierry Bultel 	rzt2h_gpio_set_direction(pctrl, port, bit, false);
55334d4d093SThierry Bultel 
55434d4d093SThierry Bultel 	return 0;
55534d4d093SThierry Bultel }
55634d4d093SThierry Bultel 
55734d4d093SThierry Bultel static int rzt2h_gpio_direction_output(struct gpio_chip *chip,
55834d4d093SThierry Bultel 				       unsigned int offset, int value)
55934d4d093SThierry Bultel {
56034d4d093SThierry Bultel 	struct rzt2h_pinctrl *pctrl = gpiochip_get_data(chip);
56134d4d093SThierry Bultel 	u8 port = RZT2H_PIN_ID_TO_PORT(offset);
56234d4d093SThierry Bultel 	u8 bit = RZT2H_PIN_ID_TO_PIN(offset);
56334d4d093SThierry Bultel 
56434d4d093SThierry Bultel 	rzt2h_gpio_set(chip, offset, value);
56534d4d093SThierry Bultel 	rzt2h_gpio_set_direction(pctrl, port, bit, true);
56634d4d093SThierry Bultel 
56734d4d093SThierry Bultel 	return 0;
56834d4d093SThierry Bultel }
56934d4d093SThierry Bultel 
57034d4d093SThierry Bultel static void rzt2h_gpio_free(struct gpio_chip *chip, unsigned int offset)
57134d4d093SThierry Bultel {
57234d4d093SThierry Bultel 	pinctrl_gpio_free(chip, offset);
57334d4d093SThierry Bultel 
57434d4d093SThierry Bultel 	/*
57534d4d093SThierry Bultel 	 * Set the GPIO as an input to ensure that the next GPIO request won't
57634d4d093SThierry Bultel 	 * drive the GPIO pin as an output.
57734d4d093SThierry Bultel 	 */
57834d4d093SThierry Bultel 	rzt2h_gpio_direction_input(chip, offset);
57934d4d093SThierry Bultel }
58034d4d093SThierry Bultel 
58134d4d093SThierry Bultel static const char * const rzt2h_gpio_names[] = {
58234d4d093SThierry Bultel 	"P00_0", "P00_1", "P00_2", "P00_3", "P00_4", "P00_5", "P00_6", "P00_7",
58334d4d093SThierry Bultel 	"P01_0", "P01_1", "P01_2", "P01_3", "P01_4", "P01_5", "P01_6", "P01_7",
58434d4d093SThierry Bultel 	"P02_0", "P02_1", "P02_2", "P02_3", "P02_4", "P02_5", "P02_6", "P02_7",
58534d4d093SThierry Bultel 	"P03_0", "P03_1", "P03_2", "P03_3", "P03_4", "P03_5", "P03_6", "P03_7",
58634d4d093SThierry Bultel 	"P04_0", "P04_1", "P04_2", "P04_3", "P04_4", "P04_5", "P04_6", "P04_7",
58734d4d093SThierry Bultel 	"P05_0", "P05_1", "P05_2", "P05_3", "P05_4", "P05_5", "P05_6", "P05_7",
58834d4d093SThierry Bultel 	"P06_0", "P06_1", "P06_2", "P06_3", "P06_4", "P06_5", "P06_6", "P06_7",
58934d4d093SThierry Bultel 	"P07_0", "P07_1", "P07_2", "P07_3", "P07_4", "P07_5", "P07_6", "P07_7",
59034d4d093SThierry Bultel 	"P08_0", "P08_1", "P08_2", "P08_3", "P08_4", "P08_5", "P08_6", "P08_7",
59134d4d093SThierry Bultel 	"P09_0", "P09_1", "P09_2", "P09_3", "P09_4", "P09_5", "P09_6", "P09_7",
59234d4d093SThierry Bultel 	"P10_0", "P10_1", "P10_2", "P10_3", "P10_4", "P10_5", "P10_6", "P10_7",
59334d4d093SThierry Bultel 	"P11_0", "P11_1", "P11_2", "P11_3", "P11_4", "P11_5", "P11_6", "P11_7",
59434d4d093SThierry Bultel 	"P12_0", "P12_1", "P12_2", "P12_3", "P12_4", "P12_5", "P12_6", "P12_7",
59534d4d093SThierry Bultel 	"P13_0", "P13_1", "P13_2", "P13_3", "P13_4", "P13_5", "P13_6", "P13_7",
59634d4d093SThierry Bultel 	"P14_0", "P14_1", "P14_2", "P14_3", "P14_4", "P14_5", "P14_6", "P14_7",
59734d4d093SThierry Bultel 	"P15_0", "P15_1", "P15_2", "P15_3", "P15_4", "P15_5", "P15_6", "P15_7",
59834d4d093SThierry Bultel 	"P16_0", "P16_1", "P16_2", "P16_3", "P16_4", "P16_5", "P16_6", "P16_7",
59934d4d093SThierry Bultel 	"P17_0", "P17_1", "P17_2", "P17_3", "P17_4", "P17_5", "P17_6", "P17_7",
60034d4d093SThierry Bultel 	"P18_0", "P18_1", "P18_2", "P18_3", "P18_4", "P18_5", "P18_6", "P18_7",
60134d4d093SThierry Bultel 	"P19_0", "P19_1", "P19_2", "P19_3", "P19_4", "P19_5", "P19_6", "P19_7",
60234d4d093SThierry Bultel 	"P20_0", "P20_1", "P20_2", "P20_3", "P20_4", "P20_5", "P20_6", "P20_7",
60334d4d093SThierry Bultel 	"P21_0", "P21_1", "P21_2", "P21_3", "P21_4", "P21_5", "P21_6", "P21_7",
60434d4d093SThierry Bultel 	"P22_0", "P22_1", "P22_2", "P22_3", "P22_4", "P22_5", "P22_6", "P22_7",
60534d4d093SThierry Bultel 	"P23_0", "P23_1", "P23_2", "P23_3", "P23_4", "P23_5", "P23_6", "P23_7",
60634d4d093SThierry Bultel 	"P24_0", "P24_1", "P24_2", "P24_3", "P24_4", "P24_5", "P24_6", "P24_7",
60734d4d093SThierry Bultel 	"P25_0", "P25_1", "P25_2", "P25_3", "P25_4", "P25_5", "P25_6", "P25_7",
60834d4d093SThierry Bultel 	"P26_0", "P26_1", "P26_2", "P26_3", "P26_4", "P26_5", "P26_6", "P26_7",
60934d4d093SThierry Bultel 	"P27_0", "P27_1", "P27_2", "P27_3", "P27_4", "P27_5", "P27_6", "P27_7",
61034d4d093SThierry Bultel 	"P28_0", "P28_1", "P28_2", "P28_3", "P28_4", "P28_5", "P28_6", "P28_7",
61134d4d093SThierry Bultel 	"P29_0", "P29_1", "P29_2", "P29_3", "P29_4", "P29_5", "P29_6", "P29_7",
61234d4d093SThierry Bultel 	"P30_0", "P30_1", "P30_2", "P30_3", "P30_4", "P30_5", "P30_6", "P30_7",
61334d4d093SThierry Bultel 	"P31_0", "P31_1", "P31_2", "P31_3", "P31_4", "P31_5", "P31_6", "P31_7",
61434d4d093SThierry Bultel 	"P32_0", "P32_1", "P32_2", "P32_3", "P32_4", "P32_5", "P32_6", "P32_7",
61534d4d093SThierry Bultel 	"P33_0", "P33_1", "P33_2", "P33_3", "P33_4", "P33_5", "P33_6", "P33_7",
61634d4d093SThierry Bultel 	"P34_0", "P34_1", "P34_2", "P34_3", "P34_4", "P34_5", "P34_6", "P34_7",
61734d4d093SThierry Bultel 	"P35_0", "P35_1", "P35_2", "P35_3", "P35_4", "P35_5", "P35_6", "P35_7",
61834d4d093SThierry Bultel };
61934d4d093SThierry Bultel 
62034d4d093SThierry Bultel static int rzt2h_gpio_register(struct rzt2h_pinctrl *pctrl)
62134d4d093SThierry Bultel {
62234d4d093SThierry Bultel 	struct pinctrl_gpio_range *range = &pctrl->gpio_range;
62334d4d093SThierry Bultel 	struct gpio_chip *chip = &pctrl->gpio_chip;
62434d4d093SThierry Bultel 	struct device *dev = pctrl->dev;
62534d4d093SThierry Bultel 	struct of_phandle_args of_args;
62634d4d093SThierry Bultel 	int ret;
62734d4d093SThierry Bultel 
62834d4d093SThierry Bultel 	ret = of_parse_phandle_with_fixed_args(dev->of_node, "gpio-ranges", 3, 0, &of_args);
62934d4d093SThierry Bultel 	if (ret)
63034d4d093SThierry Bultel 		return dev_err_probe(dev, ret, "Unable to parse gpio-ranges\n");
63134d4d093SThierry Bultel 
63234d4d093SThierry Bultel 	if (of_args.args[0] != 0 || of_args.args[1] != 0 ||
63334d4d093SThierry Bultel 	    of_args.args[2] != pctrl->data->n_port_pins)
63434d4d093SThierry Bultel 		return dev_err_probe(dev, -EINVAL,
63534d4d093SThierry Bultel 				     "gpio-ranges does not match selected SOC\n");
63634d4d093SThierry Bultel 
63734d4d093SThierry Bultel 	chip->base = -1;
63834d4d093SThierry Bultel 	chip->parent = dev;
63934d4d093SThierry Bultel 	chip->owner = THIS_MODULE;
64034d4d093SThierry Bultel 	chip->ngpio = of_args.args[2];
64134d4d093SThierry Bultel 	chip->names = rzt2h_gpio_names;
64234d4d093SThierry Bultel 	chip->request = rzt2h_gpio_request;
64334d4d093SThierry Bultel 	chip->free = rzt2h_gpio_free;
64434d4d093SThierry Bultel 	chip->get_direction = rzt2h_gpio_get_direction;
64534d4d093SThierry Bultel 	chip->direction_input = rzt2h_gpio_direction_input;
64634d4d093SThierry Bultel 	chip->direction_output = rzt2h_gpio_direction_output;
64734d4d093SThierry Bultel 	chip->get = rzt2h_gpio_get;
64834d4d093SThierry Bultel 	chip->set = rzt2h_gpio_set;
64934d4d093SThierry Bultel 	chip->label = dev_name(dev);
65034d4d093SThierry Bultel 
65134d4d093SThierry Bultel 	range->id = 0;
65234d4d093SThierry Bultel 	range->pin_base = 0;
65334d4d093SThierry Bultel 	range->base = 0;
65434d4d093SThierry Bultel 	range->npins = chip->ngpio;
65534d4d093SThierry Bultel 	range->name = chip->label;
65634d4d093SThierry Bultel 	range->gc = chip;
65734d4d093SThierry Bultel 
65834d4d093SThierry Bultel 	ret = devm_gpiochip_add_data(dev, chip, pctrl);
65934d4d093SThierry Bultel 	if (ret)
66034d4d093SThierry Bultel 		return dev_err_probe(dev, ret, "gpiochip registration failed\n");
66134d4d093SThierry Bultel 
66234d4d093SThierry Bultel 	return ret;
66334d4d093SThierry Bultel }
66434d4d093SThierry Bultel 
66534d4d093SThierry Bultel static int rzt2h_pinctrl_register(struct rzt2h_pinctrl *pctrl)
66634d4d093SThierry Bultel {
66734d4d093SThierry Bultel 	struct pinctrl_desc *desc = &pctrl->desc;
66834d4d093SThierry Bultel 	struct device *dev = pctrl->dev;
66934d4d093SThierry Bultel 	struct pinctrl_pin_desc *pins;
67034d4d093SThierry Bultel 	unsigned int i, j;
67134d4d093SThierry Bultel 	int ret;
67234d4d093SThierry Bultel 
67334d4d093SThierry Bultel 	desc->name = DRV_NAME;
67434d4d093SThierry Bultel 	desc->npins = pctrl->data->n_port_pins;
67534d4d093SThierry Bultel 	desc->pctlops = &rzt2h_pinctrl_pctlops;
67634d4d093SThierry Bultel 	desc->pmxops = &rzt2h_pinctrl_pmxops;
67734d4d093SThierry Bultel 	desc->owner = THIS_MODULE;
67834d4d093SThierry Bultel 
67934d4d093SThierry Bultel 	pins = devm_kcalloc(dev, desc->npins, sizeof(*pins), GFP_KERNEL);
68034d4d093SThierry Bultel 	if (!pins)
68134d4d093SThierry Bultel 		return -ENOMEM;
68234d4d093SThierry Bultel 
68334d4d093SThierry Bultel 	pctrl->pins = pins;
68434d4d093SThierry Bultel 	desc->pins = pins;
68534d4d093SThierry Bultel 
68634d4d093SThierry Bultel 	for (i = 0, j = 0; i < pctrl->data->n_port_pins; i++) {
68734d4d093SThierry Bultel 		pins[i].number = i;
68834d4d093SThierry Bultel 		pins[i].name = rzt2h_gpio_names[i];
68934d4d093SThierry Bultel 		if (i && !(i % RZT2H_PINS_PER_PORT))
69034d4d093SThierry Bultel 			j++;
69134d4d093SThierry Bultel 	}
69234d4d093SThierry Bultel 
69334d4d093SThierry Bultel 	ret = devm_pinctrl_register_and_init(dev, desc, pctrl, &pctrl->pctl);
69434d4d093SThierry Bultel 	if (ret)
69534d4d093SThierry Bultel 		return dev_err_probe(dev, ret, "pinctrl registration failed\n");
69634d4d093SThierry Bultel 
69734d4d093SThierry Bultel 	ret = pinctrl_enable(pctrl->pctl);
69834d4d093SThierry Bultel 	if (ret)
69934d4d093SThierry Bultel 		return dev_err_probe(dev, ret, "pinctrl enable failed\n");
70034d4d093SThierry Bultel 
70134d4d093SThierry Bultel 	return rzt2h_gpio_register(pctrl);
70234d4d093SThierry Bultel }
70334d4d093SThierry Bultel 
70434d4d093SThierry Bultel static int rzt2h_pinctrl_cfg_regions(struct platform_device *pdev,
70534d4d093SThierry Bultel 				     struct rzt2h_pinctrl *pctrl)
70634d4d093SThierry Bultel {
70734d4d093SThierry Bultel 	struct resource *res;
70834d4d093SThierry Bultel 
70934d4d093SThierry Bultel 	pctrl->base0 = devm_platform_ioremap_resource_byname(pdev, "nsr");
71034d4d093SThierry Bultel 	if (IS_ERR(pctrl->base0))
71134d4d093SThierry Bultel 		return PTR_ERR(pctrl->base0);
71234d4d093SThierry Bultel 
71334d4d093SThierry Bultel 	/*
71434d4d093SThierry Bultel 	 * Open-coded instead of using devm_platform_ioremap_resource_byname()
71534d4d093SThierry Bultel 	 * because the "srs" region is optional.
71634d4d093SThierry Bultel 	 */
71734d4d093SThierry Bultel 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "srs");
71834d4d093SThierry Bultel 	if (res) {
71934d4d093SThierry Bultel 		u8 port;
72034d4d093SThierry Bultel 
72134d4d093SThierry Bultel 		pctrl->base1 = devm_ioremap_resource(&pdev->dev, res);
72234d4d093SThierry Bultel 		if (IS_ERR(pctrl->base1))
72334d4d093SThierry Bultel 			return PTR_ERR(pctrl->base1);
72434d4d093SThierry Bultel 
72534d4d093SThierry Bultel 		pctrl->safety_port_enabled = true;
72634d4d093SThierry Bultel 
72734d4d093SThierry Bultel 		/* Configure to select safety region 0x812c0xxx */
72834d4d093SThierry Bultel 		for (port = 0; port <= RZT2H_MAX_SAFETY_PORTS; port++)
72934d4d093SThierry Bultel 			writeb(0x0, pctrl->base1 + RSELP(port));
73034d4d093SThierry Bultel 	}
73134d4d093SThierry Bultel 
73234d4d093SThierry Bultel 	return 0;
73334d4d093SThierry Bultel }
73434d4d093SThierry Bultel 
73534d4d093SThierry Bultel static int rzt2h_pinctrl_probe(struct platform_device *pdev)
73634d4d093SThierry Bultel {
73734d4d093SThierry Bultel 	struct device *dev = &pdev->dev;
73834d4d093SThierry Bultel 	struct rzt2h_pinctrl *pctrl;
73934d4d093SThierry Bultel 	int ret;
74034d4d093SThierry Bultel 
74134d4d093SThierry Bultel 	pctrl = devm_kzalloc(dev, sizeof(*pctrl), GFP_KERNEL);
74234d4d093SThierry Bultel 	if (!pctrl)
74334d4d093SThierry Bultel 		return -ENOMEM;
74434d4d093SThierry Bultel 
74534d4d093SThierry Bultel 	pctrl->dev = dev;
74634d4d093SThierry Bultel 	pctrl->data = of_device_get_match_data(dev);
74734d4d093SThierry Bultel 
74834d4d093SThierry Bultel 	ret = rzt2h_pinctrl_cfg_regions(pdev, pctrl);
74934d4d093SThierry Bultel 	if (ret)
75034d4d093SThierry Bultel 		return ret;
75134d4d093SThierry Bultel 
75234d4d093SThierry Bultel 	spin_lock_init(&pctrl->lock);
75334d4d093SThierry Bultel 	mutex_init(&pctrl->mutex);
75434d4d093SThierry Bultel 	platform_set_drvdata(pdev, pctrl);
75534d4d093SThierry Bultel 
75634d4d093SThierry Bultel 	return rzt2h_pinctrl_register(pctrl);
75734d4d093SThierry Bultel }
75834d4d093SThierry Bultel 
75934d4d093SThierry Bultel static const u8 r9a09g077_gpio_configs[] = {
76034d4d093SThierry Bultel 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
76134d4d093SThierry Bultel 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
76234d4d093SThierry Bultel 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f,
76334d4d093SThierry Bultel };
76434d4d093SThierry Bultel 
765*d1d31e27SLad Prabhakar static const u8 r9a09g087_gpio_configs[] = {
766*d1d31e27SLad Prabhakar 	0x1f, 0xff, 0xff, 0x1f, 0x00, 0xfe, 0xff, 0x00, 0x7e, 0xf0, 0xff, 0x01,
767*d1d31e27SLad Prabhakar 	0xff, 0xff, 0xff, 0x00, 0xe0, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x01,
768*d1d31e27SLad Prabhakar 	0xe0, 0xff, 0xff, 0x7f, 0x00, 0xfe, 0xff, 0x7f, 0x00, 0xfc, 0x7f,
769*d1d31e27SLad Prabhakar };
770*d1d31e27SLad Prabhakar 
77134d4d093SThierry Bultel static struct rzt2h_pinctrl_data r9a09g077_data = {
77234d4d093SThierry Bultel 	.n_port_pins = ARRAY_SIZE(r9a09g077_gpio_configs) * RZT2H_PINS_PER_PORT,
77334d4d093SThierry Bultel 	.port_pin_configs = r9a09g077_gpio_configs,
77434d4d093SThierry Bultel 	.n_ports = ARRAY_SIZE(r9a09g077_gpio_configs),
77534d4d093SThierry Bultel };
77634d4d093SThierry Bultel 
777*d1d31e27SLad Prabhakar static struct rzt2h_pinctrl_data r9a09g087_data = {
778*d1d31e27SLad Prabhakar 	.n_port_pins = ARRAY_SIZE(r9a09g087_gpio_configs) * RZT2H_PINS_PER_PORT,
779*d1d31e27SLad Prabhakar 	.port_pin_configs = r9a09g087_gpio_configs,
780*d1d31e27SLad Prabhakar 	.n_ports = ARRAY_SIZE(r9a09g087_gpio_configs),
781*d1d31e27SLad Prabhakar };
782*d1d31e27SLad Prabhakar 
78334d4d093SThierry Bultel static const struct of_device_id rzt2h_pinctrl_of_table[] = {
78434d4d093SThierry Bultel 	{
78534d4d093SThierry Bultel 		.compatible = "renesas,r9a09g077-pinctrl",
78634d4d093SThierry Bultel 		.data = &r9a09g077_data,
78734d4d093SThierry Bultel 	},
788*d1d31e27SLad Prabhakar 	{
789*d1d31e27SLad Prabhakar 		.compatible = "renesas,r9a09g087-pinctrl",
790*d1d31e27SLad Prabhakar 		.data = &r9a09g087_data,
791*d1d31e27SLad Prabhakar 	},
79234d4d093SThierry Bultel 	{ /* sentinel */ }
79334d4d093SThierry Bultel };
79434d4d093SThierry Bultel 
79534d4d093SThierry Bultel static struct platform_driver rzt2h_pinctrl_driver = {
79634d4d093SThierry Bultel 	.driver = {
79734d4d093SThierry Bultel 		.name = DRV_NAME,
79834d4d093SThierry Bultel 		.of_match_table = of_match_ptr(rzt2h_pinctrl_of_table),
79934d4d093SThierry Bultel 		.suppress_bind_attrs = true,
80034d4d093SThierry Bultel 	},
80134d4d093SThierry Bultel 	.probe = rzt2h_pinctrl_probe,
80234d4d093SThierry Bultel };
80334d4d093SThierry Bultel 
80434d4d093SThierry Bultel static int __init rzt2h_pinctrl_init(void)
80534d4d093SThierry Bultel {
80634d4d093SThierry Bultel 	return platform_driver_register(&rzt2h_pinctrl_driver);
80734d4d093SThierry Bultel }
80834d4d093SThierry Bultel core_initcall(rzt2h_pinctrl_init);
80934d4d093SThierry Bultel 
81034d4d093SThierry Bultel MODULE_LICENSE("GPL");
81134d4d093SThierry Bultel MODULE_AUTHOR("Thierry Bultel <thierry.bultel.yh@bp.renesas.com>");
81234d4d093SThierry Bultel MODULE_AUTHOR("Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>");
81334d4d093SThierry Bultel MODULE_DESCRIPTION("Pin and gpio controller driver for the RZ/T2H family");
814