.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * Copyright (c) 2016-2017 NVIDIA Corporation |
---|
3 | 4 | * |
---|
4 | 5 | * Author: Thierry Reding <treding@nvidia.com> |
---|
5 | | - * |
---|
6 | | - * This software is licensed under the terms of the GNU General Public |
---|
7 | | - * License version 2, as published by the Free Software Foundation, and |
---|
8 | | - * may be copied, distributed, and modified under those terms. |
---|
9 | 6 | */ |
---|
10 | 7 | |
---|
11 | 8 | #include <linux/gpio/driver.h> |
---|
.. | .. |
---|
18 | 15 | #include <dt-bindings/gpio/tegra186-gpio.h> |
---|
19 | 16 | #include <dt-bindings/gpio/tegra194-gpio.h> |
---|
20 | 17 | |
---|
| 18 | +/* security registers */ |
---|
| 19 | +#define TEGRA186_GPIO_CTL_SCR 0x0c |
---|
| 20 | +#define TEGRA186_GPIO_CTL_SCR_SEC_WEN BIT(28) |
---|
| 21 | +#define TEGRA186_GPIO_CTL_SCR_SEC_REN BIT(27) |
---|
| 22 | + |
---|
| 23 | +#define TEGRA186_GPIO_INT_ROUTE_MAPPING(p, x) (0x14 + (p) * 0x20 + (x) * 4) |
---|
| 24 | + |
---|
| 25 | +/* control registers */ |
---|
21 | 26 | #define TEGRA186_GPIO_ENABLE_CONFIG 0x00 |
---|
22 | 27 | #define TEGRA186_GPIO_ENABLE_CONFIG_ENABLE BIT(0) |
---|
23 | 28 | #define TEGRA186_GPIO_ENABLE_CONFIG_OUT BIT(1) |
---|
.. | .. |
---|
27 | 32 | #define TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_TYPE_DOUBLE_EDGE (0x3 << 2) |
---|
28 | 33 | #define TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_TYPE_MASK (0x3 << 2) |
---|
29 | 34 | #define TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_LEVEL BIT(4) |
---|
| 35 | +#define TEGRA186_GPIO_ENABLE_CONFIG_DEBOUNCE BIT(5) |
---|
30 | 36 | #define TEGRA186_GPIO_ENABLE_CONFIG_INTERRUPT BIT(6) |
---|
31 | 37 | |
---|
32 | 38 | #define TEGRA186_GPIO_DEBOUNCE_CONTROL 0x04 |
---|
.. | .. |
---|
47 | 53 | |
---|
48 | 54 | struct tegra_gpio_port { |
---|
49 | 55 | const char *name; |
---|
50 | | - unsigned int offset; |
---|
| 56 | + unsigned int bank; |
---|
| 57 | + unsigned int port; |
---|
51 | 58 | unsigned int pins; |
---|
52 | | - unsigned int irq; |
---|
| 59 | +}; |
---|
| 60 | + |
---|
| 61 | +struct tegra186_pin_range { |
---|
| 62 | + unsigned int offset; |
---|
| 63 | + const char *group; |
---|
53 | 64 | }; |
---|
54 | 65 | |
---|
55 | 66 | struct tegra_gpio_soc { |
---|
56 | 67 | const struct tegra_gpio_port *ports; |
---|
57 | 68 | unsigned int num_ports; |
---|
58 | 69 | const char *name; |
---|
| 70 | + unsigned int instance; |
---|
| 71 | + |
---|
| 72 | + const struct tegra186_pin_range *pin_ranges; |
---|
| 73 | + unsigned int num_pin_ranges; |
---|
| 74 | + const char *pinmux; |
---|
59 | 75 | }; |
---|
60 | 76 | |
---|
61 | 77 | struct tegra_gpio { |
---|
.. | .. |
---|
66 | 82 | |
---|
67 | 83 | const struct tegra_gpio_soc *soc; |
---|
68 | 84 | |
---|
| 85 | + void __iomem *secure; |
---|
69 | 86 | void __iomem *base; |
---|
70 | 87 | }; |
---|
71 | 88 | |
---|
.. | .. |
---|
92 | 109 | unsigned int pin) |
---|
93 | 110 | { |
---|
94 | 111 | const struct tegra_gpio_port *port; |
---|
| 112 | + unsigned int offset; |
---|
95 | 113 | |
---|
96 | 114 | port = tegra186_gpio_get_port(gpio, &pin); |
---|
97 | 115 | if (!port) |
---|
98 | 116 | return NULL; |
---|
99 | 117 | |
---|
100 | | - return gpio->base + port->offset + pin * 0x20; |
---|
| 118 | + offset = port->bank * 0x1000 + port->port * 0x200; |
---|
| 119 | + |
---|
| 120 | + return gpio->base + offset + pin * 0x20; |
---|
101 | 121 | } |
---|
102 | 122 | |
---|
103 | 123 | static int tegra186_gpio_get_direction(struct gpio_chip *chip, |
---|
.. | .. |
---|
113 | 133 | |
---|
114 | 134 | value = readl(base + TEGRA186_GPIO_ENABLE_CONFIG); |
---|
115 | 135 | if (value & TEGRA186_GPIO_ENABLE_CONFIG_OUT) |
---|
116 | | - return 0; |
---|
| 136 | + return GPIO_LINE_DIRECTION_OUT; |
---|
117 | 137 | |
---|
118 | | - return 1; |
---|
| 138 | + return GPIO_LINE_DIRECTION_IN; |
---|
119 | 139 | } |
---|
120 | 140 | |
---|
121 | 141 | static int tegra186_gpio_direction_input(struct gpio_chip *chip, |
---|
.. | .. |
---|
207 | 227 | writel(value, base + TEGRA186_GPIO_OUTPUT_VALUE); |
---|
208 | 228 | } |
---|
209 | 229 | |
---|
| 230 | +static int tegra186_gpio_set_config(struct gpio_chip *chip, |
---|
| 231 | + unsigned int offset, |
---|
| 232 | + unsigned long config) |
---|
| 233 | +{ |
---|
| 234 | + struct tegra_gpio *gpio = gpiochip_get_data(chip); |
---|
| 235 | + u32 debounce, value; |
---|
| 236 | + void __iomem *base; |
---|
| 237 | + |
---|
| 238 | + base = tegra186_gpio_get_base(gpio, offset); |
---|
| 239 | + if (base == NULL) |
---|
| 240 | + return -ENXIO; |
---|
| 241 | + |
---|
| 242 | + if (pinconf_to_config_param(config) != PIN_CONFIG_INPUT_DEBOUNCE) |
---|
| 243 | + return -ENOTSUPP; |
---|
| 244 | + |
---|
| 245 | + debounce = pinconf_to_config_argument(config); |
---|
| 246 | + |
---|
| 247 | + /* |
---|
| 248 | + * The Tegra186 GPIO controller supports a maximum of 255 ms debounce |
---|
| 249 | + * time. |
---|
| 250 | + */ |
---|
| 251 | + if (debounce > 255000) |
---|
| 252 | + return -EINVAL; |
---|
| 253 | + |
---|
| 254 | + debounce = DIV_ROUND_UP(debounce, USEC_PER_MSEC); |
---|
| 255 | + |
---|
| 256 | + value = TEGRA186_GPIO_DEBOUNCE_CONTROL_THRESHOLD(debounce); |
---|
| 257 | + writel(value, base + TEGRA186_GPIO_DEBOUNCE_CONTROL); |
---|
| 258 | + |
---|
| 259 | + value = readl(base + TEGRA186_GPIO_ENABLE_CONFIG); |
---|
| 260 | + value |= TEGRA186_GPIO_ENABLE_CONFIG_DEBOUNCE; |
---|
| 261 | + writel(value, base + TEGRA186_GPIO_ENABLE_CONFIG); |
---|
| 262 | + |
---|
| 263 | + return 0; |
---|
| 264 | +} |
---|
| 265 | + |
---|
| 266 | +static int tegra186_gpio_add_pin_ranges(struct gpio_chip *chip) |
---|
| 267 | +{ |
---|
| 268 | + struct tegra_gpio *gpio = gpiochip_get_data(chip); |
---|
| 269 | + struct pinctrl_dev *pctldev; |
---|
| 270 | + struct device_node *np; |
---|
| 271 | + unsigned int i, j; |
---|
| 272 | + int err; |
---|
| 273 | + |
---|
| 274 | + if (!gpio->soc->pinmux || gpio->soc->num_pin_ranges == 0) |
---|
| 275 | + return 0; |
---|
| 276 | + |
---|
| 277 | + np = of_find_compatible_node(NULL, NULL, gpio->soc->pinmux); |
---|
| 278 | + if (!np) |
---|
| 279 | + return -ENODEV; |
---|
| 280 | + |
---|
| 281 | + pctldev = of_pinctrl_get(np); |
---|
| 282 | + of_node_put(np); |
---|
| 283 | + if (!pctldev) |
---|
| 284 | + return -EPROBE_DEFER; |
---|
| 285 | + |
---|
| 286 | + for (i = 0; i < gpio->soc->num_pin_ranges; i++) { |
---|
| 287 | + unsigned int pin = gpio->soc->pin_ranges[i].offset, port; |
---|
| 288 | + const char *group = gpio->soc->pin_ranges[i].group; |
---|
| 289 | + |
---|
| 290 | + port = pin / 8; |
---|
| 291 | + pin = pin % 8; |
---|
| 292 | + |
---|
| 293 | + if (port >= gpio->soc->num_ports) { |
---|
| 294 | + dev_warn(chip->parent, "invalid port %u for %s\n", |
---|
| 295 | + port, group); |
---|
| 296 | + continue; |
---|
| 297 | + } |
---|
| 298 | + |
---|
| 299 | + for (j = 0; j < port; j++) |
---|
| 300 | + pin += gpio->soc->ports[j].pins; |
---|
| 301 | + |
---|
| 302 | + err = gpiochip_add_pingroup_range(chip, pctldev, pin, group); |
---|
| 303 | + if (err < 0) |
---|
| 304 | + return err; |
---|
| 305 | + } |
---|
| 306 | + |
---|
| 307 | + return 0; |
---|
| 308 | +} |
---|
| 309 | + |
---|
210 | 310 | static int tegra186_gpio_of_xlate(struct gpio_chip *chip, |
---|
211 | 311 | const struct of_phandle_args *spec, |
---|
212 | 312 | u32 *flags) |
---|
.. | .. |
---|
284 | 384 | writel(value, base + TEGRA186_GPIO_ENABLE_CONFIG); |
---|
285 | 385 | } |
---|
286 | 386 | |
---|
287 | | -static int tegra186_irq_set_type(struct irq_data *data, unsigned int flow) |
---|
| 387 | +static int tegra186_irq_set_type(struct irq_data *data, unsigned int type) |
---|
288 | 388 | { |
---|
289 | 389 | struct gpio_chip *gc = irq_data_get_irq_chip_data(data); |
---|
290 | 390 | struct tegra_gpio *gpio = to_tegra_gpio(gc); |
---|
.. | .. |
---|
299 | 399 | value &= ~TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_TYPE_MASK; |
---|
300 | 400 | value &= ~TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_LEVEL; |
---|
301 | 401 | |
---|
302 | | - switch (flow & IRQ_TYPE_SENSE_MASK) { |
---|
| 402 | + switch (type & IRQ_TYPE_SENSE_MASK) { |
---|
303 | 403 | case IRQ_TYPE_NONE: |
---|
304 | 404 | break; |
---|
305 | 405 | |
---|
.. | .. |
---|
331 | 431 | |
---|
332 | 432 | writel(value, base + TEGRA186_GPIO_ENABLE_CONFIG); |
---|
333 | 433 | |
---|
334 | | - if ((flow & IRQ_TYPE_EDGE_BOTH) == 0) |
---|
| 434 | + if ((type & IRQ_TYPE_EDGE_BOTH) == 0) |
---|
335 | 435 | irq_set_handler_locked(data, handle_level_irq); |
---|
336 | 436 | else |
---|
337 | 437 | irq_set_handler_locked(data, handle_edge_irq); |
---|
| 438 | + |
---|
| 439 | + if (data->parent_data) |
---|
| 440 | + return irq_chip_set_type_parent(data, type); |
---|
| 441 | + |
---|
| 442 | + return 0; |
---|
| 443 | +} |
---|
| 444 | + |
---|
| 445 | +static int tegra186_irq_set_wake(struct irq_data *data, unsigned int on) |
---|
| 446 | +{ |
---|
| 447 | + if (data->parent_data) |
---|
| 448 | + return irq_chip_set_wake_parent(data, on); |
---|
338 | 449 | |
---|
339 | 450 | return 0; |
---|
340 | 451 | } |
---|
.. | .. |
---|
351 | 462 | |
---|
352 | 463 | for (i = 0; i < gpio->soc->num_ports; i++) { |
---|
353 | 464 | const struct tegra_gpio_port *port = &gpio->soc->ports[i]; |
---|
354 | | - void __iomem *base = gpio->base + port->offset; |
---|
355 | 465 | unsigned int pin, irq; |
---|
356 | 466 | unsigned long value; |
---|
| 467 | + void __iomem *base; |
---|
357 | 468 | |
---|
358 | | - /* skip ports that are not associated with this controller */ |
---|
359 | | - if (parent != gpio->irq[port->irq]) |
---|
| 469 | + base = gpio->base + port->bank * 0x1000 + port->port * 0x200; |
---|
| 470 | + |
---|
| 471 | + /* skip ports that are not associated with this bank */ |
---|
| 472 | + if (parent != gpio->irq[port->bank]) |
---|
360 | 473 | goto skip; |
---|
361 | 474 | |
---|
362 | 475 | value = readl(base + TEGRA186_GPIO_INTERRUPT_STATUS(1)); |
---|
.. | .. |
---|
376 | 489 | chained_irq_exit(chip, desc); |
---|
377 | 490 | } |
---|
378 | 491 | |
---|
379 | | -static int tegra186_gpio_irq_domain_xlate(struct irq_domain *domain, |
---|
380 | | - struct device_node *np, |
---|
381 | | - const u32 *spec, unsigned int size, |
---|
382 | | - unsigned long *hwirq, |
---|
383 | | - unsigned int *type) |
---|
| 492 | +static int tegra186_gpio_irq_domain_translate(struct irq_domain *domain, |
---|
| 493 | + struct irq_fwspec *fwspec, |
---|
| 494 | + unsigned long *hwirq, |
---|
| 495 | + unsigned int *type) |
---|
384 | 496 | { |
---|
385 | 497 | struct tegra_gpio *gpio = gpiochip_get_data(domain->host_data); |
---|
386 | 498 | unsigned int port, pin, i, offset = 0; |
---|
387 | 499 | |
---|
388 | | - if (size < 2) |
---|
| 500 | + if (WARN_ON(gpio->gpio.of_gpio_n_cells < 2)) |
---|
389 | 501 | return -EINVAL; |
---|
390 | 502 | |
---|
391 | | - port = spec[0] / 8; |
---|
392 | | - pin = spec[0] % 8; |
---|
393 | | - |
---|
394 | | - if (port >= gpio->soc->num_ports) { |
---|
395 | | - dev_err(gpio->gpio.parent, "invalid port number: %u\n", port); |
---|
| 503 | + if (WARN_ON(fwspec->param_count < gpio->gpio.of_gpio_n_cells)) |
---|
396 | 504 | return -EINVAL; |
---|
397 | | - } |
---|
| 505 | + |
---|
| 506 | + port = fwspec->param[0] / 8; |
---|
| 507 | + pin = fwspec->param[0] % 8; |
---|
| 508 | + |
---|
| 509 | + if (port >= gpio->soc->num_ports) |
---|
| 510 | + return -EINVAL; |
---|
398 | 511 | |
---|
399 | 512 | for (i = 0; i < port; i++) |
---|
400 | 513 | offset += gpio->soc->ports[i].pins; |
---|
401 | 514 | |
---|
402 | | - *type = spec[1] & IRQ_TYPE_SENSE_MASK; |
---|
| 515 | + *type = fwspec->param[1] & IRQ_TYPE_SENSE_MASK; |
---|
403 | 516 | *hwirq = offset + pin; |
---|
404 | 517 | |
---|
405 | 518 | return 0; |
---|
406 | 519 | } |
---|
407 | 520 | |
---|
408 | | -static const struct irq_domain_ops tegra186_gpio_irq_domain_ops = { |
---|
409 | | - .map = gpiochip_irq_map, |
---|
410 | | - .unmap = gpiochip_irq_unmap, |
---|
411 | | - .xlate = tegra186_gpio_irq_domain_xlate, |
---|
| 521 | +static void *tegra186_gpio_populate_parent_fwspec(struct gpio_chip *chip, |
---|
| 522 | + unsigned int parent_hwirq, |
---|
| 523 | + unsigned int parent_type) |
---|
| 524 | +{ |
---|
| 525 | + struct tegra_gpio *gpio = gpiochip_get_data(chip); |
---|
| 526 | + struct irq_fwspec *fwspec; |
---|
| 527 | + |
---|
| 528 | + fwspec = kmalloc(sizeof(*fwspec), GFP_KERNEL); |
---|
| 529 | + if (!fwspec) |
---|
| 530 | + return NULL; |
---|
| 531 | + |
---|
| 532 | + fwspec->fwnode = chip->irq.parent_domain->fwnode; |
---|
| 533 | + fwspec->param_count = 3; |
---|
| 534 | + fwspec->param[0] = gpio->soc->instance; |
---|
| 535 | + fwspec->param[1] = parent_hwirq; |
---|
| 536 | + fwspec->param[2] = parent_type; |
---|
| 537 | + |
---|
| 538 | + return fwspec; |
---|
| 539 | +} |
---|
| 540 | + |
---|
| 541 | +static int tegra186_gpio_child_to_parent_hwirq(struct gpio_chip *chip, |
---|
| 542 | + unsigned int hwirq, |
---|
| 543 | + unsigned int type, |
---|
| 544 | + unsigned int *parent_hwirq, |
---|
| 545 | + unsigned int *parent_type) |
---|
| 546 | +{ |
---|
| 547 | + *parent_hwirq = chip->irq.child_offset_to_irq(chip, hwirq); |
---|
| 548 | + *parent_type = type; |
---|
| 549 | + |
---|
| 550 | + return 0; |
---|
| 551 | +} |
---|
| 552 | + |
---|
| 553 | +static unsigned int tegra186_gpio_child_offset_to_irq(struct gpio_chip *chip, |
---|
| 554 | + unsigned int offset) |
---|
| 555 | +{ |
---|
| 556 | + struct tegra_gpio *gpio = gpiochip_get_data(chip); |
---|
| 557 | + unsigned int i; |
---|
| 558 | + |
---|
| 559 | + for (i = 0; i < gpio->soc->num_ports; i++) { |
---|
| 560 | + if (offset < gpio->soc->ports[i].pins) |
---|
| 561 | + break; |
---|
| 562 | + |
---|
| 563 | + offset -= gpio->soc->ports[i].pins; |
---|
| 564 | + } |
---|
| 565 | + |
---|
| 566 | + return offset + i * 8; |
---|
| 567 | +} |
---|
| 568 | + |
---|
| 569 | +static const struct of_device_id tegra186_pmc_of_match[] = { |
---|
| 570 | + { .compatible = "nvidia,tegra186-pmc" }, |
---|
| 571 | + { .compatible = "nvidia,tegra194-pmc" }, |
---|
| 572 | + { /* sentinel */ } |
---|
412 | 573 | }; |
---|
| 574 | + |
---|
| 575 | +static void tegra186_gpio_init_route_mapping(struct tegra_gpio *gpio) |
---|
| 576 | +{ |
---|
| 577 | + unsigned int i, j; |
---|
| 578 | + u32 value; |
---|
| 579 | + |
---|
| 580 | + for (i = 0; i < gpio->soc->num_ports; i++) { |
---|
| 581 | + const struct tegra_gpio_port *port = &gpio->soc->ports[i]; |
---|
| 582 | + unsigned int offset, p = port->port; |
---|
| 583 | + void __iomem *base; |
---|
| 584 | + |
---|
| 585 | + base = gpio->secure + port->bank * 0x1000 + 0x800; |
---|
| 586 | + |
---|
| 587 | + value = readl(base + TEGRA186_GPIO_CTL_SCR); |
---|
| 588 | + |
---|
| 589 | + /* |
---|
| 590 | + * For controllers that haven't been locked down yet, make |
---|
| 591 | + * sure to program the default interrupt route mapping. |
---|
| 592 | + */ |
---|
| 593 | + if ((value & TEGRA186_GPIO_CTL_SCR_SEC_REN) == 0 && |
---|
| 594 | + (value & TEGRA186_GPIO_CTL_SCR_SEC_WEN) == 0) { |
---|
| 595 | + for (j = 0; j < 8; j++) { |
---|
| 596 | + offset = TEGRA186_GPIO_INT_ROUTE_MAPPING(p, j); |
---|
| 597 | + |
---|
| 598 | + value = readl(base + offset); |
---|
| 599 | + value = BIT(port->pins) - 1; |
---|
| 600 | + writel(value, base + offset); |
---|
| 601 | + } |
---|
| 602 | + } |
---|
| 603 | + } |
---|
| 604 | +} |
---|
413 | 605 | |
---|
414 | 606 | static int tegra186_gpio_probe(struct platform_device *pdev) |
---|
415 | 607 | { |
---|
416 | 608 | unsigned int i, j, offset; |
---|
417 | 609 | struct gpio_irq_chip *irq; |
---|
418 | 610 | struct tegra_gpio *gpio; |
---|
419 | | - struct resource *res; |
---|
| 611 | + struct device_node *np; |
---|
420 | 612 | char **names; |
---|
421 | 613 | int err; |
---|
422 | 614 | |
---|
.. | .. |
---|
426 | 618 | |
---|
427 | 619 | gpio->soc = of_device_get_match_data(&pdev->dev); |
---|
428 | 620 | |
---|
429 | | - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "gpio"); |
---|
430 | | - gpio->base = devm_ioremap_resource(&pdev->dev, res); |
---|
| 621 | + gpio->secure = devm_platform_ioremap_resource_byname(pdev, "security"); |
---|
| 622 | + if (IS_ERR(gpio->secure)) |
---|
| 623 | + return PTR_ERR(gpio->secure); |
---|
| 624 | + |
---|
| 625 | + gpio->base = devm_platform_ioremap_resource_byname(pdev, "gpio"); |
---|
431 | 626 | if (IS_ERR(gpio->base)) |
---|
432 | 627 | return PTR_ERR(gpio->base); |
---|
433 | 628 | |
---|
.. | .. |
---|
453 | 648 | gpio->gpio.label = gpio->soc->name; |
---|
454 | 649 | gpio->gpio.parent = &pdev->dev; |
---|
455 | 650 | |
---|
| 651 | + gpio->gpio.request = gpiochip_generic_request; |
---|
| 652 | + gpio->gpio.free = gpiochip_generic_free; |
---|
456 | 653 | gpio->gpio.get_direction = tegra186_gpio_get_direction; |
---|
457 | 654 | gpio->gpio.direction_input = tegra186_gpio_direction_input; |
---|
458 | 655 | gpio->gpio.direction_output = tegra186_gpio_direction_output; |
---|
459 | 656 | gpio->gpio.get = tegra186_gpio_get, |
---|
460 | 657 | gpio->gpio.set = tegra186_gpio_set; |
---|
| 658 | + gpio->gpio.set_config = tegra186_gpio_set_config; |
---|
| 659 | + gpio->gpio.add_pin_ranges = tegra186_gpio_add_pin_ranges; |
---|
461 | 660 | |
---|
462 | 661 | gpio->gpio.base = -1; |
---|
463 | 662 | |
---|
.. | .. |
---|
496 | 695 | gpio->intc.irq_mask = tegra186_irq_mask; |
---|
497 | 696 | gpio->intc.irq_unmask = tegra186_irq_unmask; |
---|
498 | 697 | gpio->intc.irq_set_type = tegra186_irq_set_type; |
---|
| 698 | + gpio->intc.irq_set_wake = tegra186_irq_set_wake; |
---|
499 | 699 | |
---|
500 | 700 | irq = &gpio->gpio.irq; |
---|
501 | 701 | irq->chip = &gpio->intc; |
---|
502 | | - irq->domain_ops = &tegra186_gpio_irq_domain_ops; |
---|
| 702 | + irq->fwnode = of_node_to_fwnode(pdev->dev.of_node); |
---|
| 703 | + irq->child_to_parent_hwirq = tegra186_gpio_child_to_parent_hwirq; |
---|
| 704 | + irq->populate_parent_alloc_arg = tegra186_gpio_populate_parent_fwspec; |
---|
| 705 | + irq->child_offset_to_irq = tegra186_gpio_child_offset_to_irq; |
---|
| 706 | + irq->child_irq_domain_ops.translate = tegra186_gpio_irq_domain_translate; |
---|
503 | 707 | irq->handler = handle_simple_irq; |
---|
504 | 708 | irq->default_type = IRQ_TYPE_NONE; |
---|
505 | 709 | irq->parent_handler = tegra186_gpio_irq; |
---|
506 | 710 | irq->parent_handler_data = gpio; |
---|
507 | 711 | irq->num_parents = gpio->num_irq; |
---|
508 | 712 | irq->parents = gpio->irq; |
---|
| 713 | + |
---|
| 714 | + np = of_find_matching_node(NULL, tegra186_pmc_of_match); |
---|
| 715 | + if (np) { |
---|
| 716 | + irq->parent_domain = irq_find_host(np); |
---|
| 717 | + of_node_put(np); |
---|
| 718 | + |
---|
| 719 | + if (!irq->parent_domain) |
---|
| 720 | + return -EPROBE_DEFER; |
---|
| 721 | + } |
---|
| 722 | + |
---|
| 723 | + tegra186_gpio_init_route_mapping(gpio); |
---|
509 | 724 | |
---|
510 | 725 | irq->map = devm_kcalloc(&pdev->dev, gpio->gpio.ngpio, |
---|
511 | 726 | sizeof(*irq->map), GFP_KERNEL); |
---|
.. | .. |
---|
516 | 731 | const struct tegra_gpio_port *port = &gpio->soc->ports[i]; |
---|
517 | 732 | |
---|
518 | 733 | for (j = 0; j < port->pins; j++) |
---|
519 | | - irq->map[offset + j] = irq->parents[port->irq]; |
---|
| 734 | + irq->map[offset + j] = irq->parents[port->bank]; |
---|
520 | 735 | |
---|
521 | 736 | offset += port->pins; |
---|
522 | 737 | } |
---|
.. | .. |
---|
535 | 750 | return 0; |
---|
536 | 751 | } |
---|
537 | 752 | |
---|
538 | | -#define TEGRA_MAIN_GPIO_PORT(port, base, count, controller) \ |
---|
539 | | - [TEGRA_MAIN_GPIO_PORT_##port] = { \ |
---|
540 | | - .name = #port, \ |
---|
541 | | - .offset = base, \ |
---|
542 | | - .pins = count, \ |
---|
543 | | - .irq = controller, \ |
---|
| 753 | +#define TEGRA186_MAIN_GPIO_PORT(_name, _bank, _port, _pins) \ |
---|
| 754 | + [TEGRA186_MAIN_GPIO_PORT_##_name] = { \ |
---|
| 755 | + .name = #_name, \ |
---|
| 756 | + .bank = _bank, \ |
---|
| 757 | + .port = _port, \ |
---|
| 758 | + .pins = _pins, \ |
---|
544 | 759 | } |
---|
545 | 760 | |
---|
546 | 761 | static const struct tegra_gpio_port tegra186_main_ports[] = { |
---|
547 | | - TEGRA_MAIN_GPIO_PORT( A, 0x2000, 7, 2), |
---|
548 | | - TEGRA_MAIN_GPIO_PORT( B, 0x3000, 7, 3), |
---|
549 | | - TEGRA_MAIN_GPIO_PORT( C, 0x3200, 7, 3), |
---|
550 | | - TEGRA_MAIN_GPIO_PORT( D, 0x3400, 6, 3), |
---|
551 | | - TEGRA_MAIN_GPIO_PORT( E, 0x2200, 8, 2), |
---|
552 | | - TEGRA_MAIN_GPIO_PORT( F, 0x2400, 6, 2), |
---|
553 | | - TEGRA_MAIN_GPIO_PORT( G, 0x4200, 6, 4), |
---|
554 | | - TEGRA_MAIN_GPIO_PORT( H, 0x1000, 7, 1), |
---|
555 | | - TEGRA_MAIN_GPIO_PORT( I, 0x0800, 8, 0), |
---|
556 | | - TEGRA_MAIN_GPIO_PORT( J, 0x5000, 8, 5), |
---|
557 | | - TEGRA_MAIN_GPIO_PORT( K, 0x5200, 1, 5), |
---|
558 | | - TEGRA_MAIN_GPIO_PORT( L, 0x1200, 8, 1), |
---|
559 | | - TEGRA_MAIN_GPIO_PORT( M, 0x5600, 6, 5), |
---|
560 | | - TEGRA_MAIN_GPIO_PORT( N, 0x0000, 7, 0), |
---|
561 | | - TEGRA_MAIN_GPIO_PORT( O, 0x0200, 4, 0), |
---|
562 | | - TEGRA_MAIN_GPIO_PORT( P, 0x4000, 7, 4), |
---|
563 | | - TEGRA_MAIN_GPIO_PORT( Q, 0x0400, 6, 0), |
---|
564 | | - TEGRA_MAIN_GPIO_PORT( R, 0x0a00, 6, 0), |
---|
565 | | - TEGRA_MAIN_GPIO_PORT( T, 0x0600, 4, 0), |
---|
566 | | - TEGRA_MAIN_GPIO_PORT( X, 0x1400, 8, 1), |
---|
567 | | - TEGRA_MAIN_GPIO_PORT( Y, 0x1600, 7, 1), |
---|
568 | | - TEGRA_MAIN_GPIO_PORT(BB, 0x2600, 2, 2), |
---|
569 | | - TEGRA_MAIN_GPIO_PORT(CC, 0x5400, 4, 5), |
---|
| 762 | + TEGRA186_MAIN_GPIO_PORT( A, 2, 0, 7), |
---|
| 763 | + TEGRA186_MAIN_GPIO_PORT( B, 3, 0, 7), |
---|
| 764 | + TEGRA186_MAIN_GPIO_PORT( C, 3, 1, 7), |
---|
| 765 | + TEGRA186_MAIN_GPIO_PORT( D, 3, 2, 6), |
---|
| 766 | + TEGRA186_MAIN_GPIO_PORT( E, 2, 1, 8), |
---|
| 767 | + TEGRA186_MAIN_GPIO_PORT( F, 2, 2, 6), |
---|
| 768 | + TEGRA186_MAIN_GPIO_PORT( G, 4, 1, 6), |
---|
| 769 | + TEGRA186_MAIN_GPIO_PORT( H, 1, 0, 7), |
---|
| 770 | + TEGRA186_MAIN_GPIO_PORT( I, 0, 4, 8), |
---|
| 771 | + TEGRA186_MAIN_GPIO_PORT( J, 5, 0, 8), |
---|
| 772 | + TEGRA186_MAIN_GPIO_PORT( K, 5, 1, 1), |
---|
| 773 | + TEGRA186_MAIN_GPIO_PORT( L, 1, 1, 8), |
---|
| 774 | + TEGRA186_MAIN_GPIO_PORT( M, 5, 3, 6), |
---|
| 775 | + TEGRA186_MAIN_GPIO_PORT( N, 0, 0, 7), |
---|
| 776 | + TEGRA186_MAIN_GPIO_PORT( O, 0, 1, 4), |
---|
| 777 | + TEGRA186_MAIN_GPIO_PORT( P, 4, 0, 7), |
---|
| 778 | + TEGRA186_MAIN_GPIO_PORT( Q, 0, 2, 6), |
---|
| 779 | + TEGRA186_MAIN_GPIO_PORT( R, 0, 5, 6), |
---|
| 780 | + TEGRA186_MAIN_GPIO_PORT( T, 0, 3, 4), |
---|
| 781 | + TEGRA186_MAIN_GPIO_PORT( X, 1, 2, 8), |
---|
| 782 | + TEGRA186_MAIN_GPIO_PORT( Y, 1, 3, 7), |
---|
| 783 | + TEGRA186_MAIN_GPIO_PORT(BB, 2, 3, 2), |
---|
| 784 | + TEGRA186_MAIN_GPIO_PORT(CC, 5, 2, 4), |
---|
570 | 785 | }; |
---|
571 | 786 | |
---|
572 | 787 | static const struct tegra_gpio_soc tegra186_main_soc = { |
---|
573 | 788 | .num_ports = ARRAY_SIZE(tegra186_main_ports), |
---|
574 | 789 | .ports = tegra186_main_ports, |
---|
575 | 790 | .name = "tegra186-gpio", |
---|
| 791 | + .instance = 0, |
---|
576 | 792 | }; |
---|
577 | 793 | |
---|
578 | | -#define TEGRA_AON_GPIO_PORT(port, base, count, controller) \ |
---|
579 | | - [TEGRA_AON_GPIO_PORT_##port] = { \ |
---|
580 | | - .name = #port, \ |
---|
581 | | - .offset = base, \ |
---|
582 | | - .pins = count, \ |
---|
583 | | - .irq = controller, \ |
---|
| 794 | +#define TEGRA186_AON_GPIO_PORT(_name, _bank, _port, _pins) \ |
---|
| 795 | + [TEGRA186_AON_GPIO_PORT_##_name] = { \ |
---|
| 796 | + .name = #_name, \ |
---|
| 797 | + .bank = _bank, \ |
---|
| 798 | + .port = _port, \ |
---|
| 799 | + .pins = _pins, \ |
---|
584 | 800 | } |
---|
585 | 801 | |
---|
586 | 802 | static const struct tegra_gpio_port tegra186_aon_ports[] = { |
---|
587 | | - TEGRA_AON_GPIO_PORT( S, 0x0200, 5, 0), |
---|
588 | | - TEGRA_AON_GPIO_PORT( U, 0x0400, 6, 0), |
---|
589 | | - TEGRA_AON_GPIO_PORT( V, 0x0800, 8, 0), |
---|
590 | | - TEGRA_AON_GPIO_PORT( W, 0x0a00, 8, 0), |
---|
591 | | - TEGRA_AON_GPIO_PORT( Z, 0x0e00, 4, 0), |
---|
592 | | - TEGRA_AON_GPIO_PORT(AA, 0x0c00, 8, 0), |
---|
593 | | - TEGRA_AON_GPIO_PORT(EE, 0x0600, 3, 0), |
---|
594 | | - TEGRA_AON_GPIO_PORT(FF, 0x0000, 5, 0), |
---|
| 803 | + TEGRA186_AON_GPIO_PORT( S, 0, 1, 5), |
---|
| 804 | + TEGRA186_AON_GPIO_PORT( U, 0, 2, 6), |
---|
| 805 | + TEGRA186_AON_GPIO_PORT( V, 0, 4, 8), |
---|
| 806 | + TEGRA186_AON_GPIO_PORT( W, 0, 5, 8), |
---|
| 807 | + TEGRA186_AON_GPIO_PORT( Z, 0, 7, 4), |
---|
| 808 | + TEGRA186_AON_GPIO_PORT(AA, 0, 6, 8), |
---|
| 809 | + TEGRA186_AON_GPIO_PORT(EE, 0, 3, 3), |
---|
| 810 | + TEGRA186_AON_GPIO_PORT(FF, 0, 0, 5), |
---|
595 | 811 | }; |
---|
596 | 812 | |
---|
597 | 813 | static const struct tegra_gpio_soc tegra186_aon_soc = { |
---|
598 | 814 | .num_ports = ARRAY_SIZE(tegra186_aon_ports), |
---|
599 | 815 | .ports = tegra186_aon_ports, |
---|
600 | 816 | .name = "tegra186-gpio-aon", |
---|
| 817 | + .instance = 1, |
---|
601 | 818 | }; |
---|
602 | 819 | |
---|
603 | | -#define TEGRA194_MAIN_GPIO_PORT(port, base, count, controller) \ |
---|
604 | | - [TEGRA194_MAIN_GPIO_PORT_##port] = { \ |
---|
605 | | - .name = #port, \ |
---|
606 | | - .offset = base, \ |
---|
607 | | - .pins = count, \ |
---|
608 | | - .irq = controller, \ |
---|
| 820 | +#define TEGRA194_MAIN_GPIO_PORT(_name, _bank, _port, _pins) \ |
---|
| 821 | + [TEGRA194_MAIN_GPIO_PORT_##_name] = { \ |
---|
| 822 | + .name = #_name, \ |
---|
| 823 | + .bank = _bank, \ |
---|
| 824 | + .port = _port, \ |
---|
| 825 | + .pins = _pins, \ |
---|
609 | 826 | } |
---|
610 | 827 | |
---|
611 | 828 | static const struct tegra_gpio_port tegra194_main_ports[] = { |
---|
612 | | - TEGRA194_MAIN_GPIO_PORT( A, 0x1400, 8, 1), |
---|
613 | | - TEGRA194_MAIN_GPIO_PORT( B, 0x4e00, 2, 4), |
---|
614 | | - TEGRA194_MAIN_GPIO_PORT( C, 0x4600, 8, 4), |
---|
615 | | - TEGRA194_MAIN_GPIO_PORT( D, 0x4800, 4, 4), |
---|
616 | | - TEGRA194_MAIN_GPIO_PORT( E, 0x4a00, 8, 4), |
---|
617 | | - TEGRA194_MAIN_GPIO_PORT( F, 0x4c00, 6, 4), |
---|
618 | | - TEGRA194_MAIN_GPIO_PORT( G, 0x4000, 8, 4), |
---|
619 | | - TEGRA194_MAIN_GPIO_PORT( H, 0x4200, 8, 4), |
---|
620 | | - TEGRA194_MAIN_GPIO_PORT( I, 0x4400, 5, 4), |
---|
621 | | - TEGRA194_MAIN_GPIO_PORT( J, 0x5200, 6, 5), |
---|
622 | | - TEGRA194_MAIN_GPIO_PORT( K, 0x3000, 8, 3), |
---|
623 | | - TEGRA194_MAIN_GPIO_PORT( L, 0x3200, 4, 3), |
---|
624 | | - TEGRA194_MAIN_GPIO_PORT( M, 0x2600, 8, 2), |
---|
625 | | - TEGRA194_MAIN_GPIO_PORT( N, 0x2800, 3, 2), |
---|
626 | | - TEGRA194_MAIN_GPIO_PORT( O, 0x5000, 6, 5), |
---|
627 | | - TEGRA194_MAIN_GPIO_PORT( P, 0x2a00, 8, 2), |
---|
628 | | - TEGRA194_MAIN_GPIO_PORT( Q, 0x2c00, 8, 2), |
---|
629 | | - TEGRA194_MAIN_GPIO_PORT( R, 0x2e00, 6, 2), |
---|
630 | | - TEGRA194_MAIN_GPIO_PORT( S, 0x3600, 8, 3), |
---|
631 | | - TEGRA194_MAIN_GPIO_PORT( T, 0x3800, 8, 3), |
---|
632 | | - TEGRA194_MAIN_GPIO_PORT( U, 0x3a00, 1, 3), |
---|
633 | | - TEGRA194_MAIN_GPIO_PORT( V, 0x1000, 8, 1), |
---|
634 | | - TEGRA194_MAIN_GPIO_PORT( W, 0x1200, 2, 1), |
---|
635 | | - TEGRA194_MAIN_GPIO_PORT( X, 0x2000, 8, 2), |
---|
636 | | - TEGRA194_MAIN_GPIO_PORT( Y, 0x2200, 8, 2), |
---|
637 | | - TEGRA194_MAIN_GPIO_PORT( Z, 0x2400, 8, 2), |
---|
638 | | - TEGRA194_MAIN_GPIO_PORT(FF, 0x3400, 2, 3), |
---|
639 | | - TEGRA194_MAIN_GPIO_PORT(GG, 0x0000, 2, 0) |
---|
| 829 | + TEGRA194_MAIN_GPIO_PORT( A, 1, 2, 8), |
---|
| 830 | + TEGRA194_MAIN_GPIO_PORT( B, 4, 7, 2), |
---|
| 831 | + TEGRA194_MAIN_GPIO_PORT( C, 4, 3, 8), |
---|
| 832 | + TEGRA194_MAIN_GPIO_PORT( D, 4, 4, 4), |
---|
| 833 | + TEGRA194_MAIN_GPIO_PORT( E, 4, 5, 8), |
---|
| 834 | + TEGRA194_MAIN_GPIO_PORT( F, 4, 6, 6), |
---|
| 835 | + TEGRA194_MAIN_GPIO_PORT( G, 4, 0, 8), |
---|
| 836 | + TEGRA194_MAIN_GPIO_PORT( H, 4, 1, 8), |
---|
| 837 | + TEGRA194_MAIN_GPIO_PORT( I, 4, 2, 5), |
---|
| 838 | + TEGRA194_MAIN_GPIO_PORT( J, 5, 1, 6), |
---|
| 839 | + TEGRA194_MAIN_GPIO_PORT( K, 3, 0, 8), |
---|
| 840 | + TEGRA194_MAIN_GPIO_PORT( L, 3, 1, 4), |
---|
| 841 | + TEGRA194_MAIN_GPIO_PORT( M, 2, 3, 8), |
---|
| 842 | + TEGRA194_MAIN_GPIO_PORT( N, 2, 4, 3), |
---|
| 843 | + TEGRA194_MAIN_GPIO_PORT( O, 5, 0, 6), |
---|
| 844 | + TEGRA194_MAIN_GPIO_PORT( P, 2, 5, 8), |
---|
| 845 | + TEGRA194_MAIN_GPIO_PORT( Q, 2, 6, 8), |
---|
| 846 | + TEGRA194_MAIN_GPIO_PORT( R, 2, 7, 6), |
---|
| 847 | + TEGRA194_MAIN_GPIO_PORT( S, 3, 3, 8), |
---|
| 848 | + TEGRA194_MAIN_GPIO_PORT( T, 3, 4, 8), |
---|
| 849 | + TEGRA194_MAIN_GPIO_PORT( U, 3, 5, 1), |
---|
| 850 | + TEGRA194_MAIN_GPIO_PORT( V, 1, 0, 8), |
---|
| 851 | + TEGRA194_MAIN_GPIO_PORT( W, 1, 1, 2), |
---|
| 852 | + TEGRA194_MAIN_GPIO_PORT( X, 2, 0, 8), |
---|
| 853 | + TEGRA194_MAIN_GPIO_PORT( Y, 2, 1, 8), |
---|
| 854 | + TEGRA194_MAIN_GPIO_PORT( Z, 2, 2, 8), |
---|
| 855 | + TEGRA194_MAIN_GPIO_PORT(FF, 3, 2, 2), |
---|
| 856 | + TEGRA194_MAIN_GPIO_PORT(GG, 0, 0, 2) |
---|
| 857 | +}; |
---|
| 858 | + |
---|
| 859 | +static const struct tegra186_pin_range tegra194_main_pin_ranges[] = { |
---|
| 860 | + { TEGRA194_MAIN_GPIO(GG, 0), "pex_l5_clkreq_n_pgg0" }, |
---|
| 861 | + { TEGRA194_MAIN_GPIO(GG, 1), "pex_l5_rst_n_pgg1" }, |
---|
640 | 862 | }; |
---|
641 | 863 | |
---|
642 | 864 | static const struct tegra_gpio_soc tegra194_main_soc = { |
---|
643 | 865 | .num_ports = ARRAY_SIZE(tegra194_main_ports), |
---|
644 | 866 | .ports = tegra194_main_ports, |
---|
645 | 867 | .name = "tegra194-gpio", |
---|
| 868 | + .instance = 0, |
---|
| 869 | + .num_pin_ranges = ARRAY_SIZE(tegra194_main_pin_ranges), |
---|
| 870 | + .pin_ranges = tegra194_main_pin_ranges, |
---|
| 871 | + .pinmux = "nvidia,tegra194-pinmux", |
---|
646 | 872 | }; |
---|
647 | 873 | |
---|
648 | | -#define TEGRA194_AON_GPIO_PORT(port, base, count, controller) \ |
---|
649 | | - [TEGRA194_AON_GPIO_PORT_##port] = { \ |
---|
650 | | - .name = #port, \ |
---|
651 | | - .offset = base, \ |
---|
652 | | - .pins = count, \ |
---|
653 | | - .irq = controller, \ |
---|
| 874 | +#define TEGRA194_AON_GPIO_PORT(_name, _bank, _port, _pins) \ |
---|
| 875 | + [TEGRA194_AON_GPIO_PORT_##_name] = { \ |
---|
| 876 | + .name = #_name, \ |
---|
| 877 | + .bank = _bank, \ |
---|
| 878 | + .port = _port, \ |
---|
| 879 | + .pins = _pins, \ |
---|
654 | 880 | } |
---|
655 | 881 | |
---|
656 | 882 | static const struct tegra_gpio_port tegra194_aon_ports[] = { |
---|
657 | | - TEGRA194_AON_GPIO_PORT(AA, 0x0600, 8, 0), |
---|
658 | | - TEGRA194_AON_GPIO_PORT(BB, 0x0800, 4, 0), |
---|
659 | | - TEGRA194_AON_GPIO_PORT(CC, 0x0200, 8, 0), |
---|
660 | | - TEGRA194_AON_GPIO_PORT(DD, 0x0400, 3, 0), |
---|
661 | | - TEGRA194_AON_GPIO_PORT(EE, 0x0000, 7, 0) |
---|
| 883 | + TEGRA194_AON_GPIO_PORT(AA, 0, 3, 8), |
---|
| 884 | + TEGRA194_AON_GPIO_PORT(BB, 0, 4, 4), |
---|
| 885 | + TEGRA194_AON_GPIO_PORT(CC, 0, 1, 8), |
---|
| 886 | + TEGRA194_AON_GPIO_PORT(DD, 0, 2, 3), |
---|
| 887 | + TEGRA194_AON_GPIO_PORT(EE, 0, 0, 7) |
---|
662 | 888 | }; |
---|
663 | 889 | |
---|
664 | 890 | static const struct tegra_gpio_soc tegra194_aon_soc = { |
---|
665 | 891 | .num_ports = ARRAY_SIZE(tegra194_aon_ports), |
---|
666 | 892 | .ports = tegra194_aon_ports, |
---|
667 | 893 | .name = "tegra194-gpio-aon", |
---|
| 894 | + .instance = 1, |
---|
668 | 895 | }; |
---|
669 | 896 | |
---|
670 | 897 | static const struct of_device_id tegra186_gpio_of_match[] = { |
---|
.. | .. |
---|
684 | 911 | /* sentinel */ |
---|
685 | 912 | } |
---|
686 | 913 | }; |
---|
| 914 | +MODULE_DEVICE_TABLE(of, tegra186_gpio_of_match); |
---|
687 | 915 | |
---|
688 | 916 | static struct platform_driver tegra186_gpio_driver = { |
---|
689 | 917 | .driver = { |
---|