Lad Prabhakar | c4c4637 | 2021-07-27 12:23:26 +0100 | [diff] [blame] | 1 | // SPDX-License-Identifier: GPL-2.0 |
| 2 | /* |
| 3 | * Renesas RZ/G2L Pin Control and GPIO driver core |
| 4 | * |
| 5 | * Copyright (C) 2021 Renesas Electronics Corporation. |
| 6 | */ |
| 7 | |
| 8 | #include <linux/bitops.h> |
| 9 | #include <linux/clk.h> |
| 10 | #include <linux/gpio/driver.h> |
| 11 | #include <linux/io.h> |
| 12 | #include <linux/module.h> |
| 13 | #include <linux/of_device.h> |
| 14 | #include <linux/pinctrl/pinconf-generic.h> |
| 15 | #include <linux/pinctrl/pinconf.h> |
| 16 | #include <linux/pinctrl/pinctrl.h> |
| 17 | #include <linux/pinctrl/pinmux.h> |
| 18 | #include <linux/spinlock.h> |
| 19 | |
| 20 | #include <dt-bindings/pinctrl/rzg2l-pinctrl.h> |
| 21 | |
| 22 | #include "../core.h" |
| 23 | #include "../pinconf.h" |
| 24 | #include "../pinmux.h" |
| 25 | |
| 26 | #define DRV_NAME "pinctrl-rzg2l" |
| 27 | |
| 28 | /* |
| 29 | * Use 16 lower bits [15:0] for pin identifier |
| 30 | * Use 16 higher bits [31:16] for pin mux function |
| 31 | */ |
| 32 | #define MUX_PIN_ID_MASK GENMASK(15, 0) |
| 33 | #define MUX_FUNC_MASK GENMASK(31, 16) |
| 34 | #define MUX_FUNC_OFFS 16 |
| 35 | #define MUX_FUNC(pinconf) (((pinconf) & MUX_FUNC_MASK) >> MUX_FUNC_OFFS) |
| 36 | |
| 37 | /* PIN capabilities */ |
Lad Prabhakar | adb613f | 2021-11-10 22:46:22 +0000 | [diff] [blame] | 38 | #define PIN_CFG_IOLH_A BIT(0) |
| 39 | #define PIN_CFG_IOLH_B BIT(1) |
| 40 | #define PIN_CFG_SR BIT(2) |
| 41 | #define PIN_CFG_IEN BIT(3) |
| 42 | #define PIN_CFG_PUPD BIT(4) |
| 43 | #define PIN_CFG_IO_VMC_SD0 BIT(5) |
| 44 | #define PIN_CFG_IO_VMC_SD1 BIT(6) |
| 45 | #define PIN_CFG_IO_VMC_QSPI BIT(7) |
| 46 | #define PIN_CFG_IO_VMC_ETH0 BIT(8) |
| 47 | #define PIN_CFG_IO_VMC_ETH1 BIT(9) |
| 48 | #define PIN_CFG_FILONOFF BIT(10) |
| 49 | #define PIN_CFG_FILNUM BIT(11) |
| 50 | #define PIN_CFG_FILCLKSEL BIT(12) |
Lad Prabhakar | c4c4637 | 2021-07-27 12:23:26 +0100 | [diff] [blame] | 51 | |
Lad Prabhakar | adb613f | 2021-11-10 22:46:22 +0000 | [diff] [blame] | 52 | #define RZG2L_MPXED_PIN_FUNCS (PIN_CFG_IOLH_A | \ |
Lad Prabhakar | c4c4637 | 2021-07-27 12:23:26 +0100 | [diff] [blame] | 53 | PIN_CFG_SR | \ |
| 54 | PIN_CFG_PUPD | \ |
| 55 | PIN_CFG_FILONOFF | \ |
| 56 | PIN_CFG_FILNUM | \ |
| 57 | PIN_CFG_FILCLKSEL) |
| 58 | |
| 59 | #define RZG2L_MPXED_ETH_PIN_FUNCS(x) ((x) | \ |
| 60 | PIN_CFG_FILONOFF | \ |
| 61 | PIN_CFG_FILNUM | \ |
| 62 | PIN_CFG_FILCLKSEL) |
| 63 | |
| 64 | /* |
| 65 | * n indicates number of pins in the port, a is the register index |
| 66 | * and f is pin configuration capabilities supported. |
| 67 | */ |
| 68 | #define RZG2L_GPIO_PORT_PACK(n, a, f) (((n) << 28) | ((a) << 20) | (f)) |
| 69 | #define RZG2L_GPIO_PORT_GET_PINCNT(x) (((x) & GENMASK(30, 28)) >> 28) |
| 70 | #define RZG2L_GPIO_PORT_GET_INDEX(x) (((x) & GENMASK(26, 20)) >> 20) |
| 71 | #define RZG2L_GPIO_PORT_GET_CFGS(x) ((x) & GENMASK(19, 0)) |
| 72 | |
| 73 | /* |
| 74 | * BIT(31) indicates dedicated pin, p is the register index while |
| 75 | * referencing to SR/IEN/IOLH/FILxx registers, b is the register bits |
| 76 | * (b * 8) and f is the pin configuration capabilities supported. |
| 77 | */ |
| 78 | #define RZG2L_SINGLE_PIN BIT(31) |
| 79 | #define RZG2L_SINGLE_PIN_PACK(p, b, f) (RZG2L_SINGLE_PIN | \ |
| 80 | ((p) << 24) | ((b) << 20) | (f)) |
Lad Prabhakar | c76629a | 2021-11-10 22:46:18 +0000 | [diff] [blame] | 81 | #define RZG2L_SINGLE_PIN_GET_PORT_OFFSET(x) (((x) & GENMASK(30, 24)) >> 24) |
Lad Prabhakar | c4c4637 | 2021-07-27 12:23:26 +0100 | [diff] [blame] | 82 | #define RZG2L_SINGLE_PIN_GET_BIT(x) (((x) & GENMASK(22, 20)) >> 20) |
| 83 | #define RZG2L_SINGLE_PIN_GET_CFGS(x) ((x) & GENMASK(19, 0)) |
| 84 | |
| 85 | #define P(n) (0x0000 + 0x10 + (n)) |
| 86 | #define PM(n) (0x0100 + 0x20 + (n) * 2) |
| 87 | #define PMC(n) (0x0200 + 0x10 + (n)) |
| 88 | #define PFC(n) (0x0400 + 0x40 + (n) * 4) |
| 89 | #define PIN(n) (0x0800 + 0x10 + (n)) |
Lad Prabhakar | adb613f | 2021-11-10 22:46:22 +0000 | [diff] [blame] | 90 | #define IOLH(n) (0x1000 + (n) * 8) |
Lad Prabhakar | c4c4637 | 2021-07-27 12:23:26 +0100 | [diff] [blame] | 91 | #define IEN(n) (0x1800 + (n) * 8) |
| 92 | #define PWPR (0x3014) |
| 93 | #define SD_CH(n) (0x3000 + (n) * 4) |
| 94 | #define QSPI (0x3008) |
| 95 | |
| 96 | #define PVDD_1800 1 /* I/O domain voltage <= 1.8V */ |
| 97 | #define PVDD_3300 0 /* I/O domain voltage >= 3.3V */ |
| 98 | |
| 99 | #define PWPR_B0WI BIT(7) /* Bit Write Disable */ |
| 100 | #define PWPR_PFCWE BIT(6) /* PFC Register Write Enable */ |
| 101 | |
| 102 | #define PM_MASK 0x03 |
| 103 | #define PVDD_MASK 0x01 |
| 104 | #define PFC_MASK 0x07 |
| 105 | #define IEN_MASK 0x01 |
Lad Prabhakar | adb613f | 2021-11-10 22:46:22 +0000 | [diff] [blame] | 106 | #define IOLH_MASK 0x03 |
Lad Prabhakar | c4c4637 | 2021-07-27 12:23:26 +0100 | [diff] [blame] | 107 | |
| 108 | #define PM_INPUT 0x1 |
| 109 | #define PM_OUTPUT 0x2 |
| 110 | |
| 111 | #define RZG2L_PIN_ID_TO_PORT(id) ((id) / RZG2L_PINS_PER_PORT) |
Lad Prabhakar | 7f13a42 | 2021-11-10 22:46:20 +0000 | [diff] [blame] | 112 | #define RZG2L_PIN_ID_TO_PORT_OFFSET(id) (RZG2L_PIN_ID_TO_PORT(id) + 0x10) |
Lad Prabhakar | c4c4637 | 2021-07-27 12:23:26 +0100 | [diff] [blame] | 113 | #define RZG2L_PIN_ID_TO_PIN(id) ((id) % RZG2L_PINS_PER_PORT) |
| 114 | |
| 115 | struct rzg2l_dedicated_configs { |
| 116 | const char *name; |
| 117 | u32 config; |
| 118 | }; |
| 119 | |
| 120 | struct rzg2l_pinctrl_data { |
| 121 | const char * const *port_pins; |
| 122 | const u32 *port_pin_configs; |
| 123 | struct rzg2l_dedicated_configs *dedicated_pins; |
| 124 | unsigned int n_port_pins; |
| 125 | unsigned int n_dedicated_pins; |
| 126 | }; |
| 127 | |
| 128 | struct rzg2l_pinctrl { |
| 129 | struct pinctrl_dev *pctl; |
| 130 | struct pinctrl_desc desc; |
| 131 | struct pinctrl_pin_desc *pins; |
| 132 | |
| 133 | const struct rzg2l_pinctrl_data *data; |
| 134 | void __iomem *base; |
| 135 | struct device *dev; |
| 136 | struct clk *clk; |
| 137 | |
| 138 | struct gpio_chip gpio_chip; |
| 139 | struct pinctrl_gpio_range gpio_range; |
| 140 | |
| 141 | spinlock_t lock; |
| 142 | }; |
| 143 | |
Lad Prabhakar | adb613f | 2021-11-10 22:46:22 +0000 | [diff] [blame] | 144 | static const unsigned int iolh_groupa_mA[] = { 2, 4, 8, 12 }; |
| 145 | static const unsigned int iolh_groupb_oi[] = { 100, 66, 50, 33 }; |
| 146 | |
Lad Prabhakar | c4c4637 | 2021-07-27 12:23:26 +0100 | [diff] [blame] | 147 | static void rzg2l_pinctrl_set_pfc_mode(struct rzg2l_pinctrl *pctrl, |
| 148 | u8 port, u8 pin, u8 func) |
| 149 | { |
| 150 | unsigned long flags; |
| 151 | u32 reg; |
| 152 | |
| 153 | spin_lock_irqsave(&pctrl->lock, flags); |
| 154 | |
| 155 | /* Set pin to 'Non-use (Hi-Z input protection)' */ |
| 156 | reg = readw(pctrl->base + PM(port)); |
| 157 | reg &= ~(PM_MASK << (pin * 2)); |
| 158 | writew(reg, pctrl->base + PM(port)); |
| 159 | |
| 160 | /* Temporarily switch to GPIO mode with PMC register */ |
| 161 | reg = readb(pctrl->base + PMC(port)); |
| 162 | writeb(reg & ~BIT(pin), pctrl->base + PMC(port)); |
| 163 | |
| 164 | /* Set the PWPR register to allow PFC register to write */ |
| 165 | writel(0x0, pctrl->base + PWPR); /* B0WI=0, PFCWE=0 */ |
| 166 | writel(PWPR_PFCWE, pctrl->base + PWPR); /* B0WI=0, PFCWE=1 */ |
| 167 | |
| 168 | /* Select Pin function mode with PFC register */ |
| 169 | reg = readl(pctrl->base + PFC(port)); |
| 170 | reg &= ~(PFC_MASK << (pin * 4)); |
| 171 | writel(reg | (func << (pin * 4)), pctrl->base + PFC(port)); |
| 172 | |
| 173 | /* Set the PWPR register to be write-protected */ |
| 174 | writel(0x0, pctrl->base + PWPR); /* B0WI=0, PFCWE=0 */ |
| 175 | writel(PWPR_B0WI, pctrl->base + PWPR); /* B0WI=1, PFCWE=0 */ |
| 176 | |
| 177 | /* Switch to Peripheral pin function with PMC register */ |
| 178 | reg = readb(pctrl->base + PMC(port)); |
| 179 | writeb(reg | BIT(pin), pctrl->base + PMC(port)); |
| 180 | |
| 181 | spin_unlock_irqrestore(&pctrl->lock, flags); |
| 182 | }; |
| 183 | |
| 184 | static int rzg2l_pinctrl_set_mux(struct pinctrl_dev *pctldev, |
| 185 | unsigned int func_selector, |
| 186 | unsigned int group_selector) |
| 187 | { |
| 188 | struct rzg2l_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); |
| 189 | struct function_desc *func; |
| 190 | unsigned int i, *psel_val; |
| 191 | struct group_desc *group; |
| 192 | int *pins; |
| 193 | |
| 194 | func = pinmux_generic_get_function(pctldev, func_selector); |
| 195 | if (!func) |
| 196 | return -EINVAL; |
| 197 | group = pinctrl_generic_get_group(pctldev, group_selector); |
| 198 | if (!group) |
| 199 | return -EINVAL; |
| 200 | |
| 201 | psel_val = func->data; |
| 202 | pins = group->pins; |
| 203 | |
| 204 | for (i = 0; i < group->num_pins; i++) { |
| 205 | dev_dbg(pctrl->dev, "port:%u pin: %u PSEL:%u\n", |
| 206 | RZG2L_PIN_ID_TO_PORT(pins[i]), RZG2L_PIN_ID_TO_PIN(pins[i]), |
| 207 | psel_val[i]); |
| 208 | rzg2l_pinctrl_set_pfc_mode(pctrl, RZG2L_PIN_ID_TO_PORT(pins[i]), |
| 209 | RZG2L_PIN_ID_TO_PIN(pins[i]), psel_val[i]); |
| 210 | } |
| 211 | |
| 212 | return 0; |
| 213 | }; |
| 214 | |
| 215 | static int rzg2l_map_add_config(struct pinctrl_map *map, |
| 216 | const char *group_or_pin, |
| 217 | enum pinctrl_map_type type, |
| 218 | unsigned long *configs, |
| 219 | unsigned int num_configs) |
| 220 | { |
| 221 | unsigned long *cfgs; |
| 222 | |
| 223 | cfgs = kmemdup(configs, num_configs * sizeof(*cfgs), |
| 224 | GFP_KERNEL); |
| 225 | if (!cfgs) |
| 226 | return -ENOMEM; |
| 227 | |
| 228 | map->type = type; |
| 229 | map->data.configs.group_or_pin = group_or_pin; |
| 230 | map->data.configs.configs = cfgs; |
| 231 | map->data.configs.num_configs = num_configs; |
| 232 | |
| 233 | return 0; |
| 234 | } |
| 235 | |
| 236 | static int rzg2l_dt_subnode_to_map(struct pinctrl_dev *pctldev, |
| 237 | struct device_node *np, |
| 238 | struct pinctrl_map **map, |
| 239 | unsigned int *num_maps, |
| 240 | unsigned int *index) |
| 241 | { |
| 242 | struct rzg2l_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); |
| 243 | struct pinctrl_map *maps = *map; |
| 244 | unsigned int nmaps = *num_maps; |
| 245 | unsigned long *configs = NULL; |
| 246 | unsigned int *pins, *psel_val; |
| 247 | unsigned int num_pinmux = 0; |
| 248 | unsigned int idx = *index; |
| 249 | unsigned int num_pins, i; |
| 250 | unsigned int num_configs; |
| 251 | struct property *pinmux; |
| 252 | struct property *prop; |
| 253 | int ret, gsel, fsel; |
| 254 | const char **pin_fn; |
| 255 | const char *pin; |
| 256 | |
| 257 | pinmux = of_find_property(np, "pinmux", NULL); |
| 258 | if (pinmux) |
| 259 | num_pinmux = pinmux->length / sizeof(u32); |
| 260 | |
| 261 | ret = of_property_count_strings(np, "pins"); |
| 262 | if (ret == -EINVAL) { |
| 263 | num_pins = 0; |
| 264 | } else if (ret < 0) { |
| 265 | dev_err(pctrl->dev, "Invalid pins list in DT\n"); |
| 266 | return ret; |
| 267 | } else { |
| 268 | num_pins = ret; |
| 269 | } |
| 270 | |
| 271 | if (!num_pinmux && !num_pins) |
| 272 | return 0; |
| 273 | |
| 274 | if (num_pinmux && num_pins) { |
| 275 | dev_err(pctrl->dev, |
| 276 | "DT node must contain either a pinmux or pins and not both\n"); |
| 277 | return -EINVAL; |
| 278 | } |
| 279 | |
| 280 | ret = pinconf_generic_parse_dt_config(np, NULL, &configs, &num_configs); |
| 281 | if (ret < 0) |
| 282 | return ret; |
| 283 | |
| 284 | if (num_pins && !num_configs) { |
| 285 | dev_err(pctrl->dev, "DT node must contain a config\n"); |
| 286 | ret = -ENODEV; |
| 287 | goto done; |
| 288 | } |
| 289 | |
| 290 | if (num_pinmux) |
| 291 | nmaps += 1; |
| 292 | |
| 293 | if (num_pins) |
| 294 | nmaps += num_pins; |
| 295 | |
| 296 | maps = krealloc_array(maps, nmaps, sizeof(*maps), GFP_KERNEL); |
| 297 | if (!maps) { |
| 298 | ret = -ENOMEM; |
| 299 | goto done; |
| 300 | } |
| 301 | |
| 302 | *map = maps; |
| 303 | *num_maps = nmaps; |
| 304 | if (num_pins) { |
| 305 | of_property_for_each_string(np, "pins", prop, pin) { |
| 306 | ret = rzg2l_map_add_config(&maps[idx], pin, |
| 307 | PIN_MAP_TYPE_CONFIGS_PIN, |
| 308 | configs, num_configs); |
| 309 | if (ret < 0) |
| 310 | goto done; |
| 311 | |
| 312 | idx++; |
| 313 | } |
| 314 | ret = 0; |
| 315 | goto done; |
| 316 | } |
| 317 | |
| 318 | pins = devm_kcalloc(pctrl->dev, num_pinmux, sizeof(*pins), GFP_KERNEL); |
| 319 | psel_val = devm_kcalloc(pctrl->dev, num_pinmux, sizeof(*psel_val), |
| 320 | GFP_KERNEL); |
| 321 | pin_fn = devm_kzalloc(pctrl->dev, sizeof(*pin_fn), GFP_KERNEL); |
| 322 | if (!pins || !psel_val || !pin_fn) { |
| 323 | ret = -ENOMEM; |
| 324 | goto done; |
| 325 | } |
| 326 | |
| 327 | /* Collect pin locations and mux settings from DT properties */ |
| 328 | for (i = 0; i < num_pinmux; ++i) { |
| 329 | u32 value; |
| 330 | |
| 331 | ret = of_property_read_u32_index(np, "pinmux", i, &value); |
| 332 | if (ret) |
| 333 | goto done; |
| 334 | pins[i] = value & MUX_PIN_ID_MASK; |
| 335 | psel_val[i] = MUX_FUNC(value); |
| 336 | } |
| 337 | |
| 338 | /* Register a single pin group listing all the pins we read from DT */ |
| 339 | gsel = pinctrl_generic_add_group(pctldev, np->name, pins, num_pinmux, NULL); |
| 340 | if (gsel < 0) { |
| 341 | ret = gsel; |
| 342 | goto done; |
| 343 | } |
| 344 | |
| 345 | /* |
| 346 | * Register a single group function where the 'data' is an array PSEL |
| 347 | * register values read from DT. |
| 348 | */ |
| 349 | pin_fn[0] = np->name; |
| 350 | fsel = pinmux_generic_add_function(pctldev, np->name, pin_fn, 1, |
| 351 | psel_val); |
| 352 | if (fsel < 0) { |
| 353 | ret = fsel; |
| 354 | goto remove_group; |
| 355 | } |
| 356 | |
| 357 | maps[idx].type = PIN_MAP_TYPE_MUX_GROUP; |
| 358 | maps[idx].data.mux.group = np->name; |
| 359 | maps[idx].data.mux.function = np->name; |
| 360 | idx++; |
| 361 | |
| 362 | dev_dbg(pctrl->dev, "Parsed %pOF with %d pins\n", np, num_pinmux); |
| 363 | ret = 0; |
| 364 | goto done; |
| 365 | |
| 366 | remove_group: |
| 367 | pinctrl_generic_remove_group(pctldev, gsel); |
| 368 | done: |
| 369 | *index = idx; |
| 370 | kfree(configs); |
| 371 | return ret; |
| 372 | } |
| 373 | |
| 374 | static void rzg2l_dt_free_map(struct pinctrl_dev *pctldev, |
| 375 | struct pinctrl_map *map, |
| 376 | unsigned int num_maps) |
| 377 | { |
| 378 | unsigned int i; |
| 379 | |
| 380 | if (!map) |
| 381 | return; |
| 382 | |
| 383 | for (i = 0; i < num_maps; ++i) { |
| 384 | if (map[i].type == PIN_MAP_TYPE_CONFIGS_GROUP || |
| 385 | map[i].type == PIN_MAP_TYPE_CONFIGS_PIN) |
| 386 | kfree(map[i].data.configs.configs); |
| 387 | } |
| 388 | kfree(map); |
| 389 | } |
| 390 | |
| 391 | static int rzg2l_dt_node_to_map(struct pinctrl_dev *pctldev, |
| 392 | struct device_node *np, |
| 393 | struct pinctrl_map **map, |
| 394 | unsigned int *num_maps) |
| 395 | { |
| 396 | struct rzg2l_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); |
| 397 | struct device_node *child; |
| 398 | unsigned int index; |
| 399 | int ret; |
| 400 | |
| 401 | *map = NULL; |
| 402 | *num_maps = 0; |
| 403 | index = 0; |
| 404 | |
| 405 | for_each_child_of_node(np, child) { |
| 406 | ret = rzg2l_dt_subnode_to_map(pctldev, child, map, |
| 407 | num_maps, &index); |
| 408 | if (ret < 0) { |
| 409 | of_node_put(child); |
| 410 | goto done; |
| 411 | } |
| 412 | } |
| 413 | |
| 414 | if (*num_maps == 0) { |
| 415 | ret = rzg2l_dt_subnode_to_map(pctldev, np, map, |
| 416 | num_maps, &index); |
| 417 | if (ret < 0) |
| 418 | goto done; |
| 419 | } |
| 420 | |
| 421 | if (*num_maps) |
| 422 | return 0; |
| 423 | |
| 424 | dev_err(pctrl->dev, "no mapping found in node %pOF\n", np); |
| 425 | ret = -EINVAL; |
| 426 | |
| 427 | done: |
| 428 | if (ret < 0) |
| 429 | rzg2l_dt_free_map(pctldev, *map, *num_maps); |
| 430 | |
| 431 | return ret; |
| 432 | } |
| 433 | |
Lad Prabhakar | 7f13a42 | 2021-11-10 22:46:20 +0000 | [diff] [blame] | 434 | static int rzg2l_validate_gpio_pin(struct rzg2l_pinctrl *pctrl, |
| 435 | u32 cfg, u32 port, u8 bit) |
| 436 | { |
| 437 | u8 pincount = RZG2L_GPIO_PORT_GET_PINCNT(cfg); |
| 438 | u32 port_index = RZG2L_GPIO_PORT_GET_INDEX(cfg); |
| 439 | u32 data; |
| 440 | |
| 441 | if (bit >= pincount || port >= pctrl->data->n_port_pins) |
| 442 | return -EINVAL; |
| 443 | |
| 444 | data = pctrl->data->port_pin_configs[port]; |
| 445 | if (port_index != RZG2L_GPIO_PORT_GET_INDEX(data)) |
| 446 | return -EINVAL; |
| 447 | |
| 448 | return 0; |
| 449 | } |
| 450 | |
Lad Prabhakar | d118999 | 2021-11-10 22:46:19 +0000 | [diff] [blame] | 451 | static u32 rzg2l_read_pin_config(struct rzg2l_pinctrl *pctrl, u32 offset, |
| 452 | u8 bit, u32 mask) |
| 453 | { |
| 454 | void __iomem *addr = pctrl->base + offset; |
| 455 | |
| 456 | /* handle _L/_H for 32-bit register read/write */ |
| 457 | if (bit >= 4) { |
| 458 | bit -= 4; |
| 459 | addr += 4; |
| 460 | } |
| 461 | |
| 462 | return (readl(addr) >> (bit * 8)) & mask; |
| 463 | } |
| 464 | |
| 465 | static void rzg2l_rmw_pin_config(struct rzg2l_pinctrl *pctrl, u32 offset, |
| 466 | u8 bit, u32 mask, u32 val) |
| 467 | { |
| 468 | void __iomem *addr = pctrl->base + offset; |
| 469 | unsigned long flags; |
| 470 | u32 reg; |
| 471 | |
| 472 | /* handle _L/_H for 32-bit register read/write */ |
| 473 | if (bit >= 4) { |
| 474 | bit -= 4; |
| 475 | addr += 4; |
| 476 | } |
| 477 | |
| 478 | spin_lock_irqsave(&pctrl->lock, flags); |
| 479 | reg = readl(addr) & ~(mask << (bit * 8)); |
| 480 | writel(reg | (val << (bit * 8)), addr); |
| 481 | spin_unlock_irqrestore(&pctrl->lock, flags); |
| 482 | } |
| 483 | |
Lad Prabhakar | c4c4637 | 2021-07-27 12:23:26 +0100 | [diff] [blame] | 484 | static int rzg2l_pinctrl_pinconf_get(struct pinctrl_dev *pctldev, |
| 485 | unsigned int _pin, |
| 486 | unsigned long *config) |
| 487 | { |
| 488 | struct rzg2l_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); |
| 489 | enum pin_config_param param = pinconf_to_config_param(*config); |
| 490 | const struct pinctrl_pin_desc *pin = &pctrl->desc.pins[_pin]; |
| 491 | unsigned int *pin_data = pin->drv_data; |
| 492 | unsigned int arg = 0; |
| 493 | unsigned long flags; |
| 494 | void __iomem *addr; |
Lad Prabhakar | 7f13a42 | 2021-11-10 22:46:20 +0000 | [diff] [blame] | 495 | u32 port_offset; |
Lad Prabhakar | c4c4637 | 2021-07-27 12:23:26 +0100 | [diff] [blame] | 496 | u32 cfg = 0; |
| 497 | u8 bit = 0; |
| 498 | |
| 499 | if (!pin_data) |
| 500 | return -EINVAL; |
| 501 | |
| 502 | if (*pin_data & RZG2L_SINGLE_PIN) { |
Lad Prabhakar | c76629a | 2021-11-10 22:46:18 +0000 | [diff] [blame] | 503 | port_offset = RZG2L_SINGLE_PIN_GET_PORT_OFFSET(*pin_data); |
Lad Prabhakar | c4c4637 | 2021-07-27 12:23:26 +0100 | [diff] [blame] | 504 | cfg = RZG2L_SINGLE_PIN_GET_CFGS(*pin_data); |
| 505 | bit = RZG2L_SINGLE_PIN_GET_BIT(*pin_data); |
Lad Prabhakar | 7f13a42 | 2021-11-10 22:46:20 +0000 | [diff] [blame] | 506 | } else { |
| 507 | cfg = RZG2L_GPIO_PORT_GET_CFGS(*pin_data); |
| 508 | port_offset = RZG2L_PIN_ID_TO_PORT_OFFSET(_pin); |
| 509 | bit = RZG2L_PIN_ID_TO_PIN(_pin); |
| 510 | |
| 511 | if (rzg2l_validate_gpio_pin(pctrl, *pin_data, RZG2L_PIN_ID_TO_PORT(_pin), bit)) |
| 512 | return -EINVAL; |
Lad Prabhakar | c4c4637 | 2021-07-27 12:23:26 +0100 | [diff] [blame] | 513 | } |
| 514 | |
| 515 | switch (param) { |
| 516 | case PIN_CONFIG_INPUT_ENABLE: |
| 517 | if (!(cfg & PIN_CFG_IEN)) |
| 518 | return -EINVAL; |
Lad Prabhakar | d118999 | 2021-11-10 22:46:19 +0000 | [diff] [blame] | 519 | arg = rzg2l_read_pin_config(pctrl, IEN(port_offset), bit, IEN_MASK); |
Lad Prabhakar | c4c4637 | 2021-07-27 12:23:26 +0100 | [diff] [blame] | 520 | break; |
| 521 | |
| 522 | case PIN_CONFIG_POWER_SOURCE: { |
| 523 | u32 pwr_reg = 0x0; |
| 524 | |
Lad Prabhakar | 22972a2 | 2021-11-10 22:46:21 +0000 | [diff] [blame] | 525 | if (cfg & PIN_CFG_IO_VMC_SD0) |
Lad Prabhakar | c4c4637 | 2021-07-27 12:23:26 +0100 | [diff] [blame] | 526 | pwr_reg = SD_CH(0); |
Lad Prabhakar | 22972a2 | 2021-11-10 22:46:21 +0000 | [diff] [blame] | 527 | else if (cfg & PIN_CFG_IO_VMC_SD1) |
Lad Prabhakar | c4c4637 | 2021-07-27 12:23:26 +0100 | [diff] [blame] | 528 | pwr_reg = SD_CH(1); |
Lad Prabhakar | 22972a2 | 2021-11-10 22:46:21 +0000 | [diff] [blame] | 529 | else if (cfg & PIN_CFG_IO_VMC_QSPI) |
Lad Prabhakar | c4c4637 | 2021-07-27 12:23:26 +0100 | [diff] [blame] | 530 | pwr_reg = QSPI; |
| 531 | else |
| 532 | return -EINVAL; |
| 533 | |
| 534 | spin_lock_irqsave(&pctrl->lock, flags); |
| 535 | addr = pctrl->base + pwr_reg; |
| 536 | arg = (readl(addr) & PVDD_MASK) ? 1800 : 3300; |
| 537 | spin_unlock_irqrestore(&pctrl->lock, flags); |
| 538 | break; |
| 539 | } |
| 540 | |
Lad Prabhakar | adb613f | 2021-11-10 22:46:22 +0000 | [diff] [blame] | 541 | case PIN_CONFIG_DRIVE_STRENGTH: { |
| 542 | unsigned int index; |
| 543 | |
| 544 | if (!(cfg & PIN_CFG_IOLH_A)) |
| 545 | return -EINVAL; |
| 546 | |
| 547 | index = rzg2l_read_pin_config(pctrl, IOLH(port_offset), bit, IOLH_MASK); |
| 548 | arg = iolh_groupa_mA[index]; |
| 549 | break; |
| 550 | } |
| 551 | |
| 552 | case PIN_CONFIG_OUTPUT_IMPEDANCE_OHMS: { |
| 553 | unsigned int index; |
| 554 | |
| 555 | if (!(cfg & PIN_CFG_IOLH_B)) |
| 556 | return -EINVAL; |
| 557 | |
| 558 | index = rzg2l_read_pin_config(pctrl, IOLH(port_offset), bit, IOLH_MASK); |
| 559 | arg = iolh_groupb_oi[index]; |
| 560 | break; |
| 561 | } |
| 562 | |
Lad Prabhakar | c4c4637 | 2021-07-27 12:23:26 +0100 | [diff] [blame] | 563 | default: |
| 564 | return -ENOTSUPP; |
| 565 | } |
| 566 | |
| 567 | *config = pinconf_to_config_packed(param, arg); |
| 568 | |
| 569 | return 0; |
| 570 | }; |
| 571 | |
| 572 | static int rzg2l_pinctrl_pinconf_set(struct pinctrl_dev *pctldev, |
| 573 | unsigned int _pin, |
| 574 | unsigned long *_configs, |
| 575 | unsigned int num_configs) |
| 576 | { |
| 577 | struct rzg2l_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); |
| 578 | const struct pinctrl_pin_desc *pin = &pctrl->desc.pins[_pin]; |
| 579 | unsigned int *pin_data = pin->drv_data; |
| 580 | enum pin_config_param param; |
| 581 | unsigned long flags; |
| 582 | void __iomem *addr; |
Lad Prabhakar | 7f13a42 | 2021-11-10 22:46:20 +0000 | [diff] [blame] | 583 | u32 port_offset; |
Lad Prabhakar | c4c4637 | 2021-07-27 12:23:26 +0100 | [diff] [blame] | 584 | unsigned int i; |
| 585 | u32 cfg = 0; |
| 586 | u8 bit = 0; |
| 587 | |
| 588 | if (!pin_data) |
| 589 | return -EINVAL; |
| 590 | |
| 591 | if (*pin_data & RZG2L_SINGLE_PIN) { |
Lad Prabhakar | c76629a | 2021-11-10 22:46:18 +0000 | [diff] [blame] | 592 | port_offset = RZG2L_SINGLE_PIN_GET_PORT_OFFSET(*pin_data); |
Lad Prabhakar | c4c4637 | 2021-07-27 12:23:26 +0100 | [diff] [blame] | 593 | cfg = RZG2L_SINGLE_PIN_GET_CFGS(*pin_data); |
| 594 | bit = RZG2L_SINGLE_PIN_GET_BIT(*pin_data); |
Lad Prabhakar | 7f13a42 | 2021-11-10 22:46:20 +0000 | [diff] [blame] | 595 | } else { |
| 596 | cfg = RZG2L_GPIO_PORT_GET_CFGS(*pin_data); |
| 597 | port_offset = RZG2L_PIN_ID_TO_PORT_OFFSET(_pin); |
| 598 | bit = RZG2L_PIN_ID_TO_PIN(_pin); |
| 599 | |
| 600 | if (rzg2l_validate_gpio_pin(pctrl, *pin_data, RZG2L_PIN_ID_TO_PORT(_pin), bit)) |
| 601 | return -EINVAL; |
Lad Prabhakar | c4c4637 | 2021-07-27 12:23:26 +0100 | [diff] [blame] | 602 | } |
| 603 | |
| 604 | for (i = 0; i < num_configs; i++) { |
| 605 | param = pinconf_to_config_param(_configs[i]); |
| 606 | switch (param) { |
| 607 | case PIN_CONFIG_INPUT_ENABLE: { |
| 608 | unsigned int arg = |
| 609 | pinconf_to_config_argument(_configs[i]); |
| 610 | |
| 611 | if (!(cfg & PIN_CFG_IEN)) |
| 612 | return -EINVAL; |
| 613 | |
Lad Prabhakar | d118999 | 2021-11-10 22:46:19 +0000 | [diff] [blame] | 614 | rzg2l_rmw_pin_config(pctrl, IEN(port_offset), bit, IEN_MASK, !!arg); |
Lad Prabhakar | c4c4637 | 2021-07-27 12:23:26 +0100 | [diff] [blame] | 615 | break; |
| 616 | } |
| 617 | |
| 618 | case PIN_CONFIG_POWER_SOURCE: { |
| 619 | unsigned int mV = pinconf_to_config_argument(_configs[i]); |
| 620 | u32 pwr_reg = 0x0; |
| 621 | |
| 622 | if (mV != 1800 && mV != 3300) |
| 623 | return -EINVAL; |
| 624 | |
Lad Prabhakar | 22972a2 | 2021-11-10 22:46:21 +0000 | [diff] [blame] | 625 | if (cfg & PIN_CFG_IO_VMC_SD0) |
Lad Prabhakar | c4c4637 | 2021-07-27 12:23:26 +0100 | [diff] [blame] | 626 | pwr_reg = SD_CH(0); |
Lad Prabhakar | 22972a2 | 2021-11-10 22:46:21 +0000 | [diff] [blame] | 627 | else if (cfg & PIN_CFG_IO_VMC_SD1) |
Lad Prabhakar | c4c4637 | 2021-07-27 12:23:26 +0100 | [diff] [blame] | 628 | pwr_reg = SD_CH(1); |
Lad Prabhakar | 22972a2 | 2021-11-10 22:46:21 +0000 | [diff] [blame] | 629 | else if (cfg & PIN_CFG_IO_VMC_QSPI) |
Lad Prabhakar | c4c4637 | 2021-07-27 12:23:26 +0100 | [diff] [blame] | 630 | pwr_reg = QSPI; |
| 631 | else |
| 632 | return -EINVAL; |
| 633 | |
| 634 | addr = pctrl->base + pwr_reg; |
| 635 | spin_lock_irqsave(&pctrl->lock, flags); |
| 636 | writel((mV == 1800) ? PVDD_1800 : PVDD_3300, addr); |
| 637 | spin_unlock_irqrestore(&pctrl->lock, flags); |
| 638 | break; |
| 639 | } |
Lad Prabhakar | adb613f | 2021-11-10 22:46:22 +0000 | [diff] [blame] | 640 | |
| 641 | case PIN_CONFIG_DRIVE_STRENGTH: { |
| 642 | unsigned int arg = pinconf_to_config_argument(_configs[i]); |
| 643 | unsigned int index; |
| 644 | |
| 645 | if (!(cfg & PIN_CFG_IOLH_A)) |
| 646 | return -EINVAL; |
| 647 | |
| 648 | for (index = 0; index < ARRAY_SIZE(iolh_groupa_mA); index++) { |
| 649 | if (arg == iolh_groupa_mA[index]) |
| 650 | break; |
| 651 | } |
| 652 | if (index >= ARRAY_SIZE(iolh_groupa_mA)) |
| 653 | return -EINVAL; |
| 654 | |
| 655 | rzg2l_rmw_pin_config(pctrl, IOLH(port_offset), bit, IOLH_MASK, index); |
| 656 | break; |
| 657 | } |
| 658 | |
| 659 | case PIN_CONFIG_OUTPUT_IMPEDANCE_OHMS: { |
| 660 | unsigned int arg = pinconf_to_config_argument(_configs[i]); |
| 661 | unsigned int index; |
| 662 | |
| 663 | if (!(cfg & PIN_CFG_IOLH_B)) |
| 664 | return -EINVAL; |
| 665 | |
| 666 | for (index = 0; index < ARRAY_SIZE(iolh_groupb_oi); index++) { |
| 667 | if (arg == iolh_groupb_oi[index]) |
| 668 | break; |
| 669 | } |
| 670 | if (index >= ARRAY_SIZE(iolh_groupb_oi)) |
| 671 | return -EINVAL; |
| 672 | |
| 673 | rzg2l_rmw_pin_config(pctrl, IOLH(port_offset), bit, IOLH_MASK, index); |
| 674 | break; |
| 675 | } |
| 676 | |
Lad Prabhakar | c4c4637 | 2021-07-27 12:23:26 +0100 | [diff] [blame] | 677 | default: |
| 678 | return -EOPNOTSUPP; |
| 679 | } |
| 680 | } |
| 681 | |
| 682 | return 0; |
| 683 | } |
| 684 | |
| 685 | static int rzg2l_pinctrl_pinconf_group_set(struct pinctrl_dev *pctldev, |
| 686 | unsigned int group, |
| 687 | unsigned long *configs, |
| 688 | unsigned int num_configs) |
| 689 | { |
| 690 | const unsigned int *pins; |
| 691 | unsigned int i, npins; |
| 692 | int ret; |
| 693 | |
| 694 | ret = pinctrl_generic_get_group_pins(pctldev, group, &pins, &npins); |
| 695 | if (ret) |
| 696 | return ret; |
| 697 | |
| 698 | for (i = 0; i < npins; i++) { |
| 699 | ret = rzg2l_pinctrl_pinconf_set(pctldev, pins[i], configs, |
| 700 | num_configs); |
| 701 | if (ret) |
| 702 | return ret; |
| 703 | } |
| 704 | |
| 705 | return 0; |
| 706 | }; |
| 707 | |
| 708 | static int rzg2l_pinctrl_pinconf_group_get(struct pinctrl_dev *pctldev, |
| 709 | unsigned int group, |
| 710 | unsigned long *config) |
| 711 | { |
| 712 | const unsigned int *pins; |
| 713 | unsigned int i, npins, prev_config = 0; |
| 714 | int ret; |
| 715 | |
| 716 | ret = pinctrl_generic_get_group_pins(pctldev, group, &pins, &npins); |
| 717 | if (ret) |
| 718 | return ret; |
| 719 | |
| 720 | for (i = 0; i < npins; i++) { |
| 721 | ret = rzg2l_pinctrl_pinconf_get(pctldev, pins[i], config); |
| 722 | if (ret) |
| 723 | return ret; |
| 724 | |
| 725 | /* Check config matching between to pin */ |
| 726 | if (i && prev_config != *config) |
| 727 | return -EOPNOTSUPP; |
| 728 | |
| 729 | prev_config = *config; |
| 730 | } |
| 731 | |
| 732 | return 0; |
| 733 | }; |
| 734 | |
| 735 | static const struct pinctrl_ops rzg2l_pinctrl_pctlops = { |
| 736 | .get_groups_count = pinctrl_generic_get_group_count, |
| 737 | .get_group_name = pinctrl_generic_get_group_name, |
| 738 | .get_group_pins = pinctrl_generic_get_group_pins, |
| 739 | .dt_node_to_map = rzg2l_dt_node_to_map, |
| 740 | .dt_free_map = rzg2l_dt_free_map, |
| 741 | }; |
| 742 | |
| 743 | static const struct pinmux_ops rzg2l_pinctrl_pmxops = { |
| 744 | .get_functions_count = pinmux_generic_get_function_count, |
| 745 | .get_function_name = pinmux_generic_get_function_name, |
| 746 | .get_function_groups = pinmux_generic_get_function_groups, |
| 747 | .set_mux = rzg2l_pinctrl_set_mux, |
| 748 | .strict = true, |
| 749 | }; |
| 750 | |
| 751 | static const struct pinconf_ops rzg2l_pinctrl_confops = { |
| 752 | .is_generic = true, |
| 753 | .pin_config_get = rzg2l_pinctrl_pinconf_get, |
| 754 | .pin_config_set = rzg2l_pinctrl_pinconf_set, |
| 755 | .pin_config_group_set = rzg2l_pinctrl_pinconf_group_set, |
| 756 | .pin_config_group_get = rzg2l_pinctrl_pinconf_group_get, |
| 757 | .pin_config_config_dbg_show = pinconf_generic_dump_config, |
| 758 | }; |
| 759 | |
| 760 | static int rzg2l_gpio_request(struct gpio_chip *chip, unsigned int offset) |
| 761 | { |
| 762 | struct rzg2l_pinctrl *pctrl = gpiochip_get_data(chip); |
| 763 | u32 port = RZG2L_PIN_ID_TO_PORT(offset); |
| 764 | u8 bit = RZG2L_PIN_ID_TO_PIN(offset); |
| 765 | unsigned long flags; |
| 766 | u8 reg8; |
| 767 | int ret; |
| 768 | |
| 769 | ret = pinctrl_gpio_request(chip->base + offset); |
| 770 | if (ret) |
| 771 | return ret; |
| 772 | |
| 773 | spin_lock_irqsave(&pctrl->lock, flags); |
| 774 | |
| 775 | /* Select GPIO mode in PMC Register */ |
| 776 | reg8 = readb(pctrl->base + PMC(port)); |
| 777 | reg8 &= ~BIT(bit); |
| 778 | writeb(reg8, pctrl->base + PMC(port)); |
| 779 | |
| 780 | spin_unlock_irqrestore(&pctrl->lock, flags); |
| 781 | |
| 782 | return 0; |
| 783 | } |
| 784 | |
| 785 | static void rzg2l_gpio_set_direction(struct rzg2l_pinctrl *pctrl, u32 port, |
| 786 | u8 bit, bool output) |
| 787 | { |
| 788 | unsigned long flags; |
| 789 | u16 reg16; |
| 790 | |
| 791 | spin_lock_irqsave(&pctrl->lock, flags); |
| 792 | |
| 793 | reg16 = readw(pctrl->base + PM(port)); |
| 794 | reg16 &= ~(PM_MASK << (bit * 2)); |
| 795 | |
| 796 | reg16 |= (output ? PM_OUTPUT : PM_INPUT) << (bit * 2); |
| 797 | writew(reg16, pctrl->base + PM(port)); |
| 798 | |
| 799 | spin_unlock_irqrestore(&pctrl->lock, flags); |
| 800 | } |
| 801 | |
| 802 | static int rzg2l_gpio_get_direction(struct gpio_chip *chip, unsigned int offset) |
| 803 | { |
| 804 | struct rzg2l_pinctrl *pctrl = gpiochip_get_data(chip); |
| 805 | u32 port = RZG2L_PIN_ID_TO_PORT(offset); |
| 806 | u8 bit = RZG2L_PIN_ID_TO_PIN(offset); |
| 807 | |
| 808 | if (!(readb(pctrl->base + PMC(port)) & BIT(bit))) { |
| 809 | u16 reg16; |
| 810 | |
| 811 | reg16 = readw(pctrl->base + PM(port)); |
| 812 | reg16 = (reg16 >> (bit * 2)) & PM_MASK; |
| 813 | if (reg16 == PM_OUTPUT) |
| 814 | return GPIO_LINE_DIRECTION_OUT; |
| 815 | } |
| 816 | |
| 817 | return GPIO_LINE_DIRECTION_IN; |
| 818 | } |
| 819 | |
| 820 | static int rzg2l_gpio_direction_input(struct gpio_chip *chip, |
| 821 | unsigned int offset) |
| 822 | { |
| 823 | struct rzg2l_pinctrl *pctrl = gpiochip_get_data(chip); |
| 824 | u32 port = RZG2L_PIN_ID_TO_PORT(offset); |
| 825 | u8 bit = RZG2L_PIN_ID_TO_PIN(offset); |
| 826 | |
| 827 | rzg2l_gpio_set_direction(pctrl, port, bit, false); |
| 828 | |
| 829 | return 0; |
| 830 | } |
| 831 | |
| 832 | static void rzg2l_gpio_set(struct gpio_chip *chip, unsigned int offset, |
| 833 | int value) |
| 834 | { |
| 835 | struct rzg2l_pinctrl *pctrl = gpiochip_get_data(chip); |
| 836 | u32 port = RZG2L_PIN_ID_TO_PORT(offset); |
| 837 | u8 bit = RZG2L_PIN_ID_TO_PIN(offset); |
| 838 | unsigned long flags; |
| 839 | u8 reg8; |
| 840 | |
| 841 | spin_lock_irqsave(&pctrl->lock, flags); |
| 842 | |
| 843 | reg8 = readb(pctrl->base + P(port)); |
| 844 | |
| 845 | if (value) |
| 846 | writeb(reg8 | BIT(bit), pctrl->base + P(port)); |
| 847 | else |
| 848 | writeb(reg8 & ~BIT(bit), pctrl->base + P(port)); |
| 849 | |
| 850 | spin_unlock_irqrestore(&pctrl->lock, flags); |
| 851 | } |
| 852 | |
| 853 | static int rzg2l_gpio_direction_output(struct gpio_chip *chip, |
| 854 | unsigned int offset, int value) |
| 855 | { |
| 856 | struct rzg2l_pinctrl *pctrl = gpiochip_get_data(chip); |
| 857 | u32 port = RZG2L_PIN_ID_TO_PORT(offset); |
| 858 | u8 bit = RZG2L_PIN_ID_TO_PIN(offset); |
| 859 | |
| 860 | rzg2l_gpio_set(chip, offset, value); |
| 861 | rzg2l_gpio_set_direction(pctrl, port, bit, true); |
| 862 | |
| 863 | return 0; |
| 864 | } |
| 865 | |
| 866 | static int rzg2l_gpio_get(struct gpio_chip *chip, unsigned int offset) |
| 867 | { |
| 868 | struct rzg2l_pinctrl *pctrl = gpiochip_get_data(chip); |
| 869 | u32 port = RZG2L_PIN_ID_TO_PORT(offset); |
| 870 | u8 bit = RZG2L_PIN_ID_TO_PIN(offset); |
| 871 | u16 reg16; |
| 872 | |
| 873 | reg16 = readw(pctrl->base + PM(port)); |
| 874 | reg16 = (reg16 >> (bit * 2)) & PM_MASK; |
| 875 | |
| 876 | if (reg16 == PM_INPUT) |
| 877 | return !!(readb(pctrl->base + PIN(port)) & BIT(bit)); |
| 878 | else if (reg16 == PM_OUTPUT) |
| 879 | return !!(readb(pctrl->base + P(port)) & BIT(bit)); |
| 880 | else |
| 881 | return -EINVAL; |
| 882 | } |
| 883 | |
| 884 | static void rzg2l_gpio_free(struct gpio_chip *chip, unsigned int offset) |
| 885 | { |
| 886 | pinctrl_gpio_free(chip->base + offset); |
| 887 | |
| 888 | /* |
| 889 | * Set the GPIO as an input to ensure that the next GPIO request won't |
| 890 | * drive the GPIO pin as an output. |
| 891 | */ |
| 892 | rzg2l_gpio_direction_input(chip, offset); |
| 893 | } |
| 894 | |
| 895 | static const char * const rzg2l_gpio_names[] = { |
| 896 | "P0_0", "P0_1", "P0_2", "P0_3", "P0_4", "P0_5", "P0_6", "P0_7", |
| 897 | "P1_0", "P1_1", "P1_2", "P1_3", "P1_4", "P1_5", "P1_6", "P1_7", |
| 898 | "P2_0", "P2_1", "P2_2", "P2_3", "P2_4", "P2_5", "P2_6", "P2_7", |
| 899 | "P3_0", "P3_1", "P3_2", "P3_3", "P3_4", "P3_5", "P3_6", "P3_7", |
| 900 | "P4_0", "P4_1", "P4_2", "P4_3", "P4_4", "P4_5", "P4_6", "P4_7", |
| 901 | "P5_0", "P5_1", "P5_2", "P5_3", "P5_4", "P5_5", "P5_6", "P5_7", |
| 902 | "P6_0", "P6_1", "P6_2", "P6_3", "P6_4", "P6_5", "P6_6", "P6_7", |
| 903 | "P7_0", "P7_1", "P7_2", "P7_3", "P7_4", "P7_5", "P7_6", "P7_7", |
| 904 | "P8_0", "P8_1", "P8_2", "P8_3", "P8_4", "P8_5", "P8_6", "P8_7", |
| 905 | "P9_0", "P9_1", "P9_2", "P9_3", "P9_4", "P9_5", "P9_6", "P9_7", |
| 906 | "P10_0", "P10_1", "P10_2", "P10_3", "P10_4", "P10_5", "P10_6", "P10_7", |
| 907 | "P11_0", "P11_1", "P11_2", "P11_3", "P11_4", "P11_5", "P11_6", "P11_7", |
| 908 | "P12_0", "P12_1", "P12_2", "P12_3", "P12_4", "P12_5", "P12_6", "P12_7", |
| 909 | "P13_0", "P13_1", "P13_2", "P13_3", "P13_4", "P13_5", "P13_6", "P13_7", |
| 910 | "P14_0", "P14_1", "P14_2", "P14_3", "P14_4", "P14_5", "P14_6", "P14_7", |
| 911 | "P15_0", "P15_1", "P15_2", "P15_3", "P15_4", "P15_5", "P15_6", "P15_7", |
| 912 | "P16_0", "P16_1", "P16_2", "P16_3", "P16_4", "P16_5", "P16_6", "P16_7", |
| 913 | "P17_0", "P17_1", "P17_2", "P17_3", "P17_4", "P17_5", "P17_6", "P17_7", |
| 914 | "P18_0", "P18_1", "P18_2", "P18_3", "P18_4", "P18_5", "P18_6", "P18_7", |
| 915 | "P19_0", "P19_1", "P19_2", "P19_3", "P19_4", "P19_5", "P19_6", "P19_7", |
| 916 | "P20_0", "P20_1", "P20_2", "P20_3", "P20_4", "P20_5", "P20_6", "P20_7", |
| 917 | "P21_0", "P21_1", "P21_2", "P21_3", "P21_4", "P21_5", "P21_6", "P21_7", |
| 918 | "P22_0", "P22_1", "P22_2", "P22_3", "P22_4", "P22_5", "P22_6", "P22_7", |
| 919 | "P23_0", "P23_1", "P23_2", "P23_3", "P23_4", "P23_5", "P23_6", "P23_7", |
| 920 | "P24_0", "P24_1", "P24_2", "P24_3", "P24_4", "P24_5", "P24_6", "P24_7", |
| 921 | "P25_0", "P25_1", "P25_2", "P25_3", "P25_4", "P25_5", "P25_6", "P25_7", |
| 922 | "P26_0", "P26_1", "P26_2", "P26_3", "P26_4", "P26_5", "P26_6", "P26_7", |
| 923 | "P27_0", "P27_1", "P27_2", "P27_3", "P27_4", "P27_5", "P27_6", "P27_7", |
| 924 | "P28_0", "P28_1", "P28_2", "P28_3", "P28_4", "P28_5", "P28_6", "P28_7", |
| 925 | "P29_0", "P29_1", "P29_2", "P29_3", "P29_4", "P29_5", "P29_6", "P29_7", |
| 926 | "P30_0", "P30_1", "P30_2", "P30_3", "P30_4", "P30_5", "P30_6", "P30_7", |
| 927 | "P31_0", "P31_1", "P31_2", "P31_3", "P31_4", "P31_5", "P31_6", "P31_7", |
| 928 | "P32_0", "P32_1", "P32_2", "P32_3", "P32_4", "P32_5", "P32_6", "P32_7", |
| 929 | "P33_0", "P33_1", "P33_2", "P33_3", "P33_4", "P33_5", "P33_6", "P33_7", |
| 930 | "P34_0", "P34_1", "P34_2", "P34_3", "P34_4", "P34_5", "P34_6", "P34_7", |
| 931 | "P35_0", "P35_1", "P35_2", "P35_3", "P35_4", "P35_5", "P35_6", "P35_7", |
| 932 | "P36_0", "P36_1", "P36_2", "P36_3", "P36_4", "P36_5", "P36_6", "P36_7", |
| 933 | "P37_0", "P37_1", "P37_2", "P37_3", "P37_4", "P37_5", "P37_6", "P37_7", |
| 934 | "P38_0", "P38_1", "P38_2", "P38_3", "P38_4", "P38_5", "P38_6", "P38_7", |
| 935 | "P39_0", "P39_1", "P39_2", "P39_3", "P39_4", "P39_5", "P39_6", "P39_7", |
| 936 | "P40_0", "P40_1", "P40_2", "P40_3", "P40_4", "P40_5", "P40_6", "P40_7", |
| 937 | "P41_0", "P41_1", "P41_2", "P41_3", "P41_4", "P41_5", "P41_6", "P41_7", |
| 938 | "P42_0", "P42_1", "P42_2", "P42_3", "P42_4", "P42_5", "P42_6", "P42_7", |
| 939 | "P43_0", "P43_1", "P43_2", "P43_3", "P43_4", "P43_5", "P43_6", "P43_7", |
| 940 | "P44_0", "P44_1", "P44_2", "P44_3", "P44_4", "P44_5", "P44_6", "P44_7", |
| 941 | "P45_0", "P45_1", "P45_2", "P45_3", "P45_4", "P45_5", "P45_6", "P45_7", |
| 942 | "P46_0", "P46_1", "P46_2", "P46_3", "P46_4", "P46_5", "P46_6", "P46_7", |
| 943 | "P47_0", "P47_1", "P47_2", "P47_3", "P47_4", "P47_5", "P47_6", "P47_7", |
| 944 | "P48_0", "P48_1", "P48_2", "P48_3", "P48_4", "P48_5", "P48_6", "P48_7", |
| 945 | }; |
| 946 | |
| 947 | static const u32 rzg2l_gpio_configs[] = { |
| 948 | RZG2L_GPIO_PORT_PACK(2, 0x10, RZG2L_MPXED_PIN_FUNCS), |
| 949 | RZG2L_GPIO_PORT_PACK(2, 0x11, RZG2L_MPXED_PIN_FUNCS), |
| 950 | RZG2L_GPIO_PORT_PACK(2, 0x12, RZG2L_MPXED_PIN_FUNCS), |
| 951 | RZG2L_GPIO_PORT_PACK(2, 0x13, RZG2L_MPXED_PIN_FUNCS), |
| 952 | RZG2L_GPIO_PORT_PACK(2, 0x14, RZG2L_MPXED_PIN_FUNCS), |
| 953 | RZG2L_GPIO_PORT_PACK(3, 0x15, RZG2L_MPXED_PIN_FUNCS), |
| 954 | RZG2L_GPIO_PORT_PACK(2, 0x16, RZG2L_MPXED_PIN_FUNCS), |
| 955 | RZG2L_GPIO_PORT_PACK(3, 0x17, RZG2L_MPXED_PIN_FUNCS), |
| 956 | RZG2L_GPIO_PORT_PACK(3, 0x18, RZG2L_MPXED_PIN_FUNCS), |
| 957 | RZG2L_GPIO_PORT_PACK(2, 0x19, RZG2L_MPXED_PIN_FUNCS), |
| 958 | RZG2L_GPIO_PORT_PACK(2, 0x1a, RZG2L_MPXED_PIN_FUNCS), |
| 959 | RZG2L_GPIO_PORT_PACK(2, 0x1b, RZG2L_MPXED_PIN_FUNCS), |
| 960 | RZG2L_GPIO_PORT_PACK(2, 0x1c, RZG2L_MPXED_PIN_FUNCS), |
| 961 | RZG2L_GPIO_PORT_PACK(3, 0x1d, RZG2L_MPXED_PIN_FUNCS), |
| 962 | RZG2L_GPIO_PORT_PACK(2, 0x1e, RZG2L_MPXED_PIN_FUNCS), |
| 963 | RZG2L_GPIO_PORT_PACK(2, 0x1f, RZG2L_MPXED_PIN_FUNCS), |
| 964 | RZG2L_GPIO_PORT_PACK(2, 0x20, RZG2L_MPXED_PIN_FUNCS), |
Biju Das | fcfb631 | 2021-09-22 08:41:40 +0100 | [diff] [blame] | 965 | RZG2L_GPIO_PORT_PACK(3, 0x21, RZG2L_MPXED_PIN_FUNCS), |
Lad Prabhakar | c4c4637 | 2021-07-27 12:23:26 +0100 | [diff] [blame] | 966 | RZG2L_GPIO_PORT_PACK(2, 0x22, RZG2L_MPXED_PIN_FUNCS), |
| 967 | RZG2L_GPIO_PORT_PACK(2, 0x23, RZG2L_MPXED_PIN_FUNCS), |
Lad Prabhakar | 22972a2 | 2021-11-10 22:46:21 +0000 | [diff] [blame] | 968 | RZG2L_GPIO_PORT_PACK(3, 0x24, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH0)), |
| 969 | RZG2L_GPIO_PORT_PACK(2, 0x25, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH0)), |
| 970 | RZG2L_GPIO_PORT_PACK(2, 0x26, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH0)), |
| 971 | RZG2L_GPIO_PORT_PACK(2, 0x27, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH0)), |
| 972 | RZG2L_GPIO_PORT_PACK(2, 0x28, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH0)), |
| 973 | RZG2L_GPIO_PORT_PACK(2, 0x29, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH0)), |
| 974 | RZG2L_GPIO_PORT_PACK(2, 0x2a, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH0)), |
| 975 | RZG2L_GPIO_PORT_PACK(2, 0x2b, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH0)), |
| 976 | RZG2L_GPIO_PORT_PACK(2, 0x2c, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH0)), |
| 977 | RZG2L_GPIO_PORT_PACK(2, 0x2d, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH1)), |
| 978 | RZG2L_GPIO_PORT_PACK(2, 0x2e, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH1)), |
| 979 | RZG2L_GPIO_PORT_PACK(2, 0x2f, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH1)), |
| 980 | RZG2L_GPIO_PORT_PACK(2, 0x30, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH1)), |
| 981 | RZG2L_GPIO_PORT_PACK(2, 0x31, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH1)), |
| 982 | RZG2L_GPIO_PORT_PACK(2, 0x32, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH1)), |
| 983 | RZG2L_GPIO_PORT_PACK(2, 0x33, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH1)), |
| 984 | RZG2L_GPIO_PORT_PACK(2, 0x34, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH1)), |
| 985 | RZG2L_GPIO_PORT_PACK(3, 0x35, RZG2L_MPXED_ETH_PIN_FUNCS(PIN_CFG_IO_VMC_ETH1)), |
Lad Prabhakar | c4c4637 | 2021-07-27 12:23:26 +0100 | [diff] [blame] | 986 | RZG2L_GPIO_PORT_PACK(2, 0x36, RZG2L_MPXED_PIN_FUNCS), |
| 987 | RZG2L_GPIO_PORT_PACK(3, 0x37, RZG2L_MPXED_PIN_FUNCS), |
| 988 | RZG2L_GPIO_PORT_PACK(3, 0x38, RZG2L_MPXED_PIN_FUNCS), |
| 989 | RZG2L_GPIO_PORT_PACK(2, 0x39, RZG2L_MPXED_PIN_FUNCS), |
| 990 | RZG2L_GPIO_PORT_PACK(5, 0x3a, RZG2L_MPXED_PIN_FUNCS), |
| 991 | RZG2L_GPIO_PORT_PACK(4, 0x3b, RZG2L_MPXED_PIN_FUNCS), |
| 992 | RZG2L_GPIO_PORT_PACK(4, 0x3c, RZG2L_MPXED_PIN_FUNCS), |
| 993 | RZG2L_GPIO_PORT_PACK(4, 0x3d, RZG2L_MPXED_PIN_FUNCS), |
| 994 | RZG2L_GPIO_PORT_PACK(4, 0x3e, RZG2L_MPXED_PIN_FUNCS), |
| 995 | RZG2L_GPIO_PORT_PACK(4, 0x3f, RZG2L_MPXED_PIN_FUNCS), |
| 996 | RZG2L_GPIO_PORT_PACK(5, 0x40, RZG2L_MPXED_PIN_FUNCS), |
| 997 | }; |
| 998 | |
| 999 | static struct rzg2l_dedicated_configs rzg2l_dedicated_pins[] = { |
| 1000 | { "NMI", RZG2L_SINGLE_PIN_PACK(0x1, 0, |
| 1001 | (PIN_CFG_FILONOFF | PIN_CFG_FILNUM | PIN_CFG_FILCLKSEL)) }, |
| 1002 | { "TMS/SWDIO", RZG2L_SINGLE_PIN_PACK(0x2, 0, |
Lad Prabhakar | adb613f | 2021-11-10 22:46:22 +0000 | [diff] [blame] | 1003 | (PIN_CFG_SR | PIN_CFG_IOLH_A | PIN_CFG_IEN)) }, |
Lad Prabhakar | c4c4637 | 2021-07-27 12:23:26 +0100 | [diff] [blame] | 1004 | { "TDO", RZG2L_SINGLE_PIN_PACK(0x3, 0, |
Lad Prabhakar | adb613f | 2021-11-10 22:46:22 +0000 | [diff] [blame] | 1005 | (PIN_CFG_IOLH_A | PIN_CFG_SR | PIN_CFG_IEN)) }, |
Lad Prabhakar | c4c4637 | 2021-07-27 12:23:26 +0100 | [diff] [blame] | 1006 | { "AUDIO_CLK1", RZG2L_SINGLE_PIN_PACK(0x4, 0, PIN_CFG_IEN) }, |
| 1007 | { "AUDIO_CLK2", RZG2L_SINGLE_PIN_PACK(0x4, 1, PIN_CFG_IEN) }, |
| 1008 | { "SD0_CLK", RZG2L_SINGLE_PIN_PACK(0x6, 0, |
Lad Prabhakar | adb613f | 2021-11-10 22:46:22 +0000 | [diff] [blame] | 1009 | (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_SD0)) }, |
Lad Prabhakar | c4c4637 | 2021-07-27 12:23:26 +0100 | [diff] [blame] | 1010 | { "SD0_CMD", RZG2L_SINGLE_PIN_PACK(0x6, 1, |
Lad Prabhakar | adb613f | 2021-11-10 22:46:22 +0000 | [diff] [blame] | 1011 | (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD0)) }, |
Lad Prabhakar | c4c4637 | 2021-07-27 12:23:26 +0100 | [diff] [blame] | 1012 | { "SD0_RST#", RZG2L_SINGLE_PIN_PACK(0x6, 2, |
Lad Prabhakar | adb613f | 2021-11-10 22:46:22 +0000 | [diff] [blame] | 1013 | (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_SD0)) }, |
Lad Prabhakar | c4c4637 | 2021-07-27 12:23:26 +0100 | [diff] [blame] | 1014 | { "SD0_DATA0", RZG2L_SINGLE_PIN_PACK(0x7, 0, |
Lad Prabhakar | adb613f | 2021-11-10 22:46:22 +0000 | [diff] [blame] | 1015 | (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD0)) }, |
Lad Prabhakar | c4c4637 | 2021-07-27 12:23:26 +0100 | [diff] [blame] | 1016 | { "SD0_DATA1", RZG2L_SINGLE_PIN_PACK(0x7, 1, |
Lad Prabhakar | adb613f | 2021-11-10 22:46:22 +0000 | [diff] [blame] | 1017 | (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD0)) }, |
Lad Prabhakar | c4c4637 | 2021-07-27 12:23:26 +0100 | [diff] [blame] | 1018 | { "SD0_DATA2", RZG2L_SINGLE_PIN_PACK(0x7, 2, |
Lad Prabhakar | adb613f | 2021-11-10 22:46:22 +0000 | [diff] [blame] | 1019 | (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD0)) }, |
Lad Prabhakar | c4c4637 | 2021-07-27 12:23:26 +0100 | [diff] [blame] | 1020 | { "SD0_DATA3", RZG2L_SINGLE_PIN_PACK(0x7, 3, |
Lad Prabhakar | adb613f | 2021-11-10 22:46:22 +0000 | [diff] [blame] | 1021 | (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD0)) }, |
Lad Prabhakar | c4c4637 | 2021-07-27 12:23:26 +0100 | [diff] [blame] | 1022 | { "SD0_DATA4", RZG2L_SINGLE_PIN_PACK(0x7, 4, |
Lad Prabhakar | adb613f | 2021-11-10 22:46:22 +0000 | [diff] [blame] | 1023 | (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD0)) }, |
Lad Prabhakar | c4c4637 | 2021-07-27 12:23:26 +0100 | [diff] [blame] | 1024 | { "SD0_DATA5", RZG2L_SINGLE_PIN_PACK(0x7, 5, |
Lad Prabhakar | adb613f | 2021-11-10 22:46:22 +0000 | [diff] [blame] | 1025 | (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD0)) }, |
Lad Prabhakar | c4c4637 | 2021-07-27 12:23:26 +0100 | [diff] [blame] | 1026 | { "SD0_DATA6", RZG2L_SINGLE_PIN_PACK(0x7, 6, |
Lad Prabhakar | adb613f | 2021-11-10 22:46:22 +0000 | [diff] [blame] | 1027 | (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD0)) }, |
Lad Prabhakar | c4c4637 | 2021-07-27 12:23:26 +0100 | [diff] [blame] | 1028 | { "SD0_DATA7", RZG2L_SINGLE_PIN_PACK(0x7, 7, |
Lad Prabhakar | adb613f | 2021-11-10 22:46:22 +0000 | [diff] [blame] | 1029 | (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD0)) }, |
Lad Prabhakar | c4c4637 | 2021-07-27 12:23:26 +0100 | [diff] [blame] | 1030 | { "SD1_CLK", RZG2L_SINGLE_PIN_PACK(0x8, 0, |
Lad Prabhakar | adb613f | 2021-11-10 22:46:22 +0000 | [diff] [blame] | 1031 | (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_SD1)) }, |
Lad Prabhakar | c4c4637 | 2021-07-27 12:23:26 +0100 | [diff] [blame] | 1032 | { "SD1_CMD", RZG2L_SINGLE_PIN_PACK(0x8, 1, |
Lad Prabhakar | adb613f | 2021-11-10 22:46:22 +0000 | [diff] [blame] | 1033 | (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD1)) }, |
Lad Prabhakar | c4c4637 | 2021-07-27 12:23:26 +0100 | [diff] [blame] | 1034 | { "SD1_DATA0", RZG2L_SINGLE_PIN_PACK(0x9, 0, |
Lad Prabhakar | adb613f | 2021-11-10 22:46:22 +0000 | [diff] [blame] | 1035 | (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD1)) }, |
Lad Prabhakar | c4c4637 | 2021-07-27 12:23:26 +0100 | [diff] [blame] | 1036 | { "SD1_DATA1", RZG2L_SINGLE_PIN_PACK(0x9, 1, |
Lad Prabhakar | adb613f | 2021-11-10 22:46:22 +0000 | [diff] [blame] | 1037 | (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD1)) }, |
Lad Prabhakar | c4c4637 | 2021-07-27 12:23:26 +0100 | [diff] [blame] | 1038 | { "SD1_DATA2", RZG2L_SINGLE_PIN_PACK(0x9, 2, |
Lad Prabhakar | adb613f | 2021-11-10 22:46:22 +0000 | [diff] [blame] | 1039 | (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD1)) }, |
Lad Prabhakar | c4c4637 | 2021-07-27 12:23:26 +0100 | [diff] [blame] | 1040 | { "SD1_DATA3", RZG2L_SINGLE_PIN_PACK(0x9, 3, |
Lad Prabhakar | adb613f | 2021-11-10 22:46:22 +0000 | [diff] [blame] | 1041 | (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IEN | PIN_CFG_IO_VMC_SD1)) }, |
Lad Prabhakar | c4c4637 | 2021-07-27 12:23:26 +0100 | [diff] [blame] | 1042 | { "QSPI0_SPCLK", RZG2L_SINGLE_PIN_PACK(0xa, 0, |
Lad Prabhakar | adb613f | 2021-11-10 22:46:22 +0000 | [diff] [blame] | 1043 | (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) }, |
Lad Prabhakar | c4c4637 | 2021-07-27 12:23:26 +0100 | [diff] [blame] | 1044 | { "QSPI0_IO0", RZG2L_SINGLE_PIN_PACK(0xa, 1, |
Lad Prabhakar | adb613f | 2021-11-10 22:46:22 +0000 | [diff] [blame] | 1045 | (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) }, |
Lad Prabhakar | c4c4637 | 2021-07-27 12:23:26 +0100 | [diff] [blame] | 1046 | { "QSPI0_IO1", RZG2L_SINGLE_PIN_PACK(0xa, 2, |
Lad Prabhakar | adb613f | 2021-11-10 22:46:22 +0000 | [diff] [blame] | 1047 | (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) }, |
Lad Prabhakar | c4c4637 | 2021-07-27 12:23:26 +0100 | [diff] [blame] | 1048 | { "QSPI0_IO2", RZG2L_SINGLE_PIN_PACK(0xa, 3, |
Lad Prabhakar | adb613f | 2021-11-10 22:46:22 +0000 | [diff] [blame] | 1049 | (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) }, |
Lad Prabhakar | c4c4637 | 2021-07-27 12:23:26 +0100 | [diff] [blame] | 1050 | { "QSPI0_IO3", RZG2L_SINGLE_PIN_PACK(0xa, 4, |
Lad Prabhakar | adb613f | 2021-11-10 22:46:22 +0000 | [diff] [blame] | 1051 | (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) }, |
Lad Prabhakar | c4c4637 | 2021-07-27 12:23:26 +0100 | [diff] [blame] | 1052 | { "QSPI0_SSL", RZG2L_SINGLE_PIN_PACK(0xa, 5, |
Lad Prabhakar | adb613f | 2021-11-10 22:46:22 +0000 | [diff] [blame] | 1053 | (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) }, |
Lad Prabhakar | c4c4637 | 2021-07-27 12:23:26 +0100 | [diff] [blame] | 1054 | { "QSPI1_SPCLK", RZG2L_SINGLE_PIN_PACK(0xb, 0, |
Lad Prabhakar | adb613f | 2021-11-10 22:46:22 +0000 | [diff] [blame] | 1055 | (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) }, |
Lad Prabhakar | c4c4637 | 2021-07-27 12:23:26 +0100 | [diff] [blame] | 1056 | { "QSPI1_IO0", RZG2L_SINGLE_PIN_PACK(0xb, 1, |
Lad Prabhakar | adb613f | 2021-11-10 22:46:22 +0000 | [diff] [blame] | 1057 | (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) }, |
Lad Prabhakar | c4c4637 | 2021-07-27 12:23:26 +0100 | [diff] [blame] | 1058 | { "QSPI1_IO1", RZG2L_SINGLE_PIN_PACK(0xb, 2, |
Lad Prabhakar | adb613f | 2021-11-10 22:46:22 +0000 | [diff] [blame] | 1059 | (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) }, |
Lad Prabhakar | c4c4637 | 2021-07-27 12:23:26 +0100 | [diff] [blame] | 1060 | { "QSPI1_IO2", RZG2L_SINGLE_PIN_PACK(0xb, 3, |
Lad Prabhakar | adb613f | 2021-11-10 22:46:22 +0000 | [diff] [blame] | 1061 | (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) }, |
Lad Prabhakar | c4c4637 | 2021-07-27 12:23:26 +0100 | [diff] [blame] | 1062 | { "QSPI1_IO3", RZG2L_SINGLE_PIN_PACK(0xb, 4, |
Lad Prabhakar | adb613f | 2021-11-10 22:46:22 +0000 | [diff] [blame] | 1063 | (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) }, |
Lad Prabhakar | c4c4637 | 2021-07-27 12:23:26 +0100 | [diff] [blame] | 1064 | { "QSPI1_SSL", RZG2L_SINGLE_PIN_PACK(0xb, 5, |
Lad Prabhakar | adb613f | 2021-11-10 22:46:22 +0000 | [diff] [blame] | 1065 | (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) }, |
Lad Prabhakar | c4c4637 | 2021-07-27 12:23:26 +0100 | [diff] [blame] | 1066 | { "QSPI_RESET#", RZG2L_SINGLE_PIN_PACK(0xc, 0, |
Lad Prabhakar | adb613f | 2021-11-10 22:46:22 +0000 | [diff] [blame] | 1067 | (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) }, |
Lad Prabhakar | c4c4637 | 2021-07-27 12:23:26 +0100 | [diff] [blame] | 1068 | { "QSPI_WP#", RZG2L_SINGLE_PIN_PACK(0xc, 1, |
Lad Prabhakar | adb613f | 2021-11-10 22:46:22 +0000 | [diff] [blame] | 1069 | (PIN_CFG_IOLH_B | PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) }, |
Lad Prabhakar | 22972a2 | 2021-11-10 22:46:21 +0000 | [diff] [blame] | 1070 | { "QSPI_INT#", RZG2L_SINGLE_PIN_PACK(0xc, 2, (PIN_CFG_SR | PIN_CFG_IO_VMC_QSPI)) }, |
Lad Prabhakar | adb613f | 2021-11-10 22:46:22 +0000 | [diff] [blame] | 1071 | { "WDTOVF_PERROUT#", RZG2L_SINGLE_PIN_PACK(0xd, 0, (PIN_CFG_IOLH_A | PIN_CFG_SR)) }, |
Lad Prabhakar | c4c4637 | 2021-07-27 12:23:26 +0100 | [diff] [blame] | 1072 | { "RIIC0_SDA", RZG2L_SINGLE_PIN_PACK(0xe, 0, PIN_CFG_IEN) }, |
| 1073 | { "RIIC0_SCL", RZG2L_SINGLE_PIN_PACK(0xe, 1, PIN_CFG_IEN) }, |
| 1074 | { "RIIC1_SDA", RZG2L_SINGLE_PIN_PACK(0xe, 2, PIN_CFG_IEN) }, |
| 1075 | { "RIIC1_SCL", RZG2L_SINGLE_PIN_PACK(0xe, 3, PIN_CFG_IEN) }, |
| 1076 | }; |
| 1077 | |
| 1078 | static int rzg2l_gpio_register(struct rzg2l_pinctrl *pctrl) |
| 1079 | { |
| 1080 | struct device_node *np = pctrl->dev->of_node; |
| 1081 | struct gpio_chip *chip = &pctrl->gpio_chip; |
| 1082 | const char *name = dev_name(pctrl->dev); |
| 1083 | struct of_phandle_args of_args; |
| 1084 | int ret; |
| 1085 | |
| 1086 | ret = of_parse_phandle_with_fixed_args(np, "gpio-ranges", 3, 0, &of_args); |
| 1087 | if (ret) { |
| 1088 | dev_err(pctrl->dev, "Unable to parse gpio-ranges\n"); |
| 1089 | return ret; |
| 1090 | } |
| 1091 | |
| 1092 | if (of_args.args[0] != 0 || of_args.args[1] != 0 || |
| 1093 | of_args.args[2] != ARRAY_SIZE(rzg2l_gpio_names)) { |
| 1094 | dev_err(pctrl->dev, "gpio-ranges does not match selected SOC\n"); |
| 1095 | return -EINVAL; |
| 1096 | } |
| 1097 | |
| 1098 | chip->names = rzg2l_gpio_names; |
| 1099 | chip->request = rzg2l_gpio_request; |
| 1100 | chip->free = rzg2l_gpio_free; |
| 1101 | chip->get_direction = rzg2l_gpio_get_direction; |
| 1102 | chip->direction_input = rzg2l_gpio_direction_input; |
| 1103 | chip->direction_output = rzg2l_gpio_direction_output; |
| 1104 | chip->get = rzg2l_gpio_get; |
| 1105 | chip->set = rzg2l_gpio_set; |
| 1106 | chip->label = name; |
| 1107 | chip->parent = pctrl->dev; |
| 1108 | chip->owner = THIS_MODULE; |
| 1109 | chip->base = -1; |
| 1110 | chip->ngpio = of_args.args[2]; |
| 1111 | |
| 1112 | pctrl->gpio_range.id = 0; |
| 1113 | pctrl->gpio_range.pin_base = 0; |
| 1114 | pctrl->gpio_range.base = 0; |
| 1115 | pctrl->gpio_range.npins = chip->ngpio; |
| 1116 | pctrl->gpio_range.name = chip->label; |
| 1117 | pctrl->gpio_range.gc = chip; |
| 1118 | ret = devm_gpiochip_add_data(pctrl->dev, chip, pctrl); |
| 1119 | if (ret) { |
| 1120 | dev_err(pctrl->dev, "failed to add GPIO controller\n"); |
| 1121 | return ret; |
| 1122 | } |
| 1123 | |
| 1124 | dev_dbg(pctrl->dev, "Registered gpio controller\n"); |
| 1125 | |
| 1126 | return 0; |
| 1127 | } |
| 1128 | |
| 1129 | static int rzg2l_pinctrl_register(struct rzg2l_pinctrl *pctrl) |
| 1130 | { |
| 1131 | struct pinctrl_pin_desc *pins; |
| 1132 | unsigned int i, j; |
| 1133 | u32 *pin_data; |
| 1134 | int ret; |
| 1135 | |
| 1136 | pctrl->desc.name = DRV_NAME; |
| 1137 | pctrl->desc.npins = pctrl->data->n_port_pins + pctrl->data->n_dedicated_pins; |
| 1138 | pctrl->desc.pctlops = &rzg2l_pinctrl_pctlops; |
| 1139 | pctrl->desc.pmxops = &rzg2l_pinctrl_pmxops; |
| 1140 | pctrl->desc.confops = &rzg2l_pinctrl_confops; |
| 1141 | pctrl->desc.owner = THIS_MODULE; |
| 1142 | |
| 1143 | pins = devm_kcalloc(pctrl->dev, pctrl->desc.npins, sizeof(*pins), GFP_KERNEL); |
| 1144 | if (!pins) |
| 1145 | return -ENOMEM; |
| 1146 | |
| 1147 | pin_data = devm_kcalloc(pctrl->dev, pctrl->desc.npins, |
| 1148 | sizeof(*pin_data), GFP_KERNEL); |
| 1149 | if (!pin_data) |
| 1150 | return -ENOMEM; |
| 1151 | |
| 1152 | pctrl->pins = pins; |
| 1153 | pctrl->desc.pins = pins; |
| 1154 | |
| 1155 | for (i = 0, j = 0; i < pctrl->data->n_port_pins; i++) { |
| 1156 | pins[i].number = i; |
| 1157 | pins[i].name = pctrl->data->port_pins[i]; |
| 1158 | if (i && !(i % RZG2L_PINS_PER_PORT)) |
| 1159 | j++; |
| 1160 | pin_data[i] = pctrl->data->port_pin_configs[j]; |
| 1161 | pins[i].drv_data = &pin_data[i]; |
| 1162 | } |
| 1163 | |
| 1164 | for (i = 0; i < pctrl->data->n_dedicated_pins; i++) { |
| 1165 | unsigned int index = pctrl->data->n_port_pins + i; |
| 1166 | |
| 1167 | pins[index].number = index; |
| 1168 | pins[index].name = pctrl->data->dedicated_pins[i].name; |
| 1169 | pin_data[index] = pctrl->data->dedicated_pins[i].config; |
| 1170 | pins[index].drv_data = &pin_data[index]; |
| 1171 | } |
| 1172 | |
| 1173 | ret = devm_pinctrl_register_and_init(pctrl->dev, &pctrl->desc, pctrl, |
| 1174 | &pctrl->pctl); |
| 1175 | if (ret) { |
| 1176 | dev_err(pctrl->dev, "pinctrl registration failed\n"); |
| 1177 | return ret; |
| 1178 | } |
| 1179 | |
| 1180 | ret = pinctrl_enable(pctrl->pctl); |
| 1181 | if (ret) { |
| 1182 | dev_err(pctrl->dev, "pinctrl enable failed\n"); |
| 1183 | return ret; |
| 1184 | } |
| 1185 | |
| 1186 | ret = rzg2l_gpio_register(pctrl); |
| 1187 | if (ret) { |
| 1188 | dev_err(pctrl->dev, "failed to add GPIO chip: %i\n", ret); |
| 1189 | return ret; |
| 1190 | } |
| 1191 | |
| 1192 | return 0; |
| 1193 | } |
| 1194 | |
| 1195 | static void rzg2l_pinctrl_clk_disable(void *data) |
| 1196 | { |
| 1197 | clk_disable_unprepare(data); |
| 1198 | } |
| 1199 | |
| 1200 | static int rzg2l_pinctrl_probe(struct platform_device *pdev) |
| 1201 | { |
| 1202 | struct rzg2l_pinctrl *pctrl; |
| 1203 | int ret; |
| 1204 | |
| 1205 | pctrl = devm_kzalloc(&pdev->dev, sizeof(*pctrl), GFP_KERNEL); |
| 1206 | if (!pctrl) |
| 1207 | return -ENOMEM; |
| 1208 | |
| 1209 | pctrl->dev = &pdev->dev; |
| 1210 | |
| 1211 | pctrl->data = of_device_get_match_data(&pdev->dev); |
| 1212 | if (!pctrl->data) |
| 1213 | return -EINVAL; |
| 1214 | |
| 1215 | pctrl->base = devm_platform_ioremap_resource(pdev, 0); |
| 1216 | if (IS_ERR(pctrl->base)) |
| 1217 | return PTR_ERR(pctrl->base); |
| 1218 | |
| 1219 | pctrl->clk = devm_clk_get(pctrl->dev, NULL); |
| 1220 | if (IS_ERR(pctrl->clk)) { |
| 1221 | ret = PTR_ERR(pctrl->clk); |
| 1222 | dev_err(pctrl->dev, "failed to get GPIO clk : %i\n", ret); |
| 1223 | return ret; |
| 1224 | } |
| 1225 | |
| 1226 | spin_lock_init(&pctrl->lock); |
| 1227 | |
| 1228 | platform_set_drvdata(pdev, pctrl); |
| 1229 | |
| 1230 | ret = clk_prepare_enable(pctrl->clk); |
| 1231 | if (ret) { |
| 1232 | dev_err(pctrl->dev, "failed to enable GPIO clk: %i\n", ret); |
| 1233 | return ret; |
| 1234 | } |
| 1235 | |
| 1236 | ret = devm_add_action_or_reset(&pdev->dev, rzg2l_pinctrl_clk_disable, |
| 1237 | pctrl->clk); |
| 1238 | if (ret) { |
| 1239 | dev_err(pctrl->dev, |
| 1240 | "failed to register GPIO clk disable action, %i\n", |
| 1241 | ret); |
| 1242 | return ret; |
| 1243 | } |
| 1244 | |
| 1245 | ret = rzg2l_pinctrl_register(pctrl); |
| 1246 | if (ret) |
| 1247 | return ret; |
| 1248 | |
| 1249 | dev_info(pctrl->dev, "%s support registered\n", DRV_NAME); |
| 1250 | return 0; |
| 1251 | } |
| 1252 | |
| 1253 | static struct rzg2l_pinctrl_data r9a07g044_data = { |
| 1254 | .port_pins = rzg2l_gpio_names, |
| 1255 | .port_pin_configs = rzg2l_gpio_configs, |
| 1256 | .dedicated_pins = rzg2l_dedicated_pins, |
| 1257 | .n_port_pins = ARRAY_SIZE(rzg2l_gpio_names), |
| 1258 | .n_dedicated_pins = ARRAY_SIZE(rzg2l_dedicated_pins), |
| 1259 | }; |
| 1260 | |
| 1261 | static const struct of_device_id rzg2l_pinctrl_of_table[] = { |
| 1262 | { |
| 1263 | .compatible = "renesas,r9a07g044-pinctrl", |
| 1264 | .data = &r9a07g044_data, |
| 1265 | }, |
| 1266 | { /* sentinel */ } |
| 1267 | }; |
| 1268 | |
| 1269 | static struct platform_driver rzg2l_pinctrl_driver = { |
| 1270 | .driver = { |
| 1271 | .name = DRV_NAME, |
| 1272 | .of_match_table = of_match_ptr(rzg2l_pinctrl_of_table), |
| 1273 | }, |
| 1274 | .probe = rzg2l_pinctrl_probe, |
| 1275 | }; |
| 1276 | |
| 1277 | static int __init rzg2l_pinctrl_init(void) |
| 1278 | { |
| 1279 | return platform_driver_register(&rzg2l_pinctrl_driver); |
| 1280 | } |
| 1281 | core_initcall(rzg2l_pinctrl_init); |
| 1282 | |
| 1283 | MODULE_AUTHOR("Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>"); |
| 1284 | MODULE_DESCRIPTION("Pin and gpio controller driver for RZ/G2L family"); |
| 1285 | MODULE_LICENSE("GPL v2"); |