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