aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThierry Reding <treding@nvidia.com>2017-11-07 13:15:56 -0500
committerLinus Walleij <linus.walleij@linaro.org>2017-11-08 08:14:51 -0500
commit5b2b135a87fcfb2b27c3c192fd7c3b053f0c5fa2 (patch)
tree160e6bedcb617d63b02cb31f0fdf96cde39f2b42
parent1b95b4eb567aab1cafcdcb14c60a7dd9d56236a9 (diff)
gpio: Add Tegra186 support
Tegra186 has two GPIO controllers that are largely register compatible between one another but are completely different from the controller found on earlier generations. Signed-off-by: Thierry Reding <treding@nvidia.com> Acked-by: Grygorii Strashko <grygorii.strashko@ti.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
-rw-r--r--drivers/gpio/Kconfig9
-rw-r--r--drivers/gpio/Makefile1
-rw-r--r--drivers/gpio/gpio-tegra186.c623
3 files changed, 633 insertions, 0 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 9feb8e1ff2ff..4ed6a7967784 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -441,6 +441,15 @@ config GPIO_TEGRA
441 help 441 help
442 Say yes here to support GPIO pins on NVIDIA Tegra SoCs. 442 Say yes here to support GPIO pins on NVIDIA Tegra SoCs.
443 443
444config GPIO_TEGRA186
445 tristate "NVIDIA Tegra186 GPIO support"
446 default ARCH_TEGRA_186_SOC
447 depends on ARCH_TEGRA_186_SOC || COMPILE_TEST
448 depends on OF_GPIO
449 select GPIOLIB_IRQCHIP
450 help
451 Say yes here to support GPIO pins on NVIDIA Tegra186 SoCs.
452
444config GPIO_TS4800 453config GPIO_TS4800
445 tristate "TS-4800 DIO blocks and compatibles" 454 tristate "TS-4800 DIO blocks and compatibles"
446 depends on OF_GPIO 455 depends on OF_GPIO
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index ac4b7c34a668..120e79c0ebb2 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -114,6 +114,7 @@ obj-$(CONFIG_GPIO_SYSCON) += gpio-syscon.o
114obj-$(CONFIG_GPIO_TB10X) += gpio-tb10x.o 114obj-$(CONFIG_GPIO_TB10X) += gpio-tb10x.o
115obj-$(CONFIG_GPIO_TC3589X) += gpio-tc3589x.o 115obj-$(CONFIG_GPIO_TC3589X) += gpio-tc3589x.o
116obj-$(CONFIG_GPIO_TEGRA) += gpio-tegra.o 116obj-$(CONFIG_GPIO_TEGRA) += gpio-tegra.o
117obj-$(CONFIG_GPIO_TEGRA186) += gpio-tegra186.o
117obj-$(CONFIG_GPIO_THUNDERX) += gpio-thunderx.o 118obj-$(CONFIG_GPIO_THUNDERX) += gpio-thunderx.o
118obj-$(CONFIG_GPIO_TIMBERDALE) += gpio-timberdale.o 119obj-$(CONFIG_GPIO_TIMBERDALE) += gpio-timberdale.o
119obj-$(CONFIG_GPIO_PALMAS) += gpio-palmas.o 120obj-$(CONFIG_GPIO_PALMAS) += gpio-palmas.o
diff --git a/drivers/gpio/gpio-tegra186.c b/drivers/gpio/gpio-tegra186.c
new file mode 100644
index 000000000000..b55b5ca882c7
--- /dev/null
+++ b/drivers/gpio/gpio-tegra186.c
@@ -0,0 +1,623 @@
1/*
2 * Copyright (c) 2016-2017 NVIDIA Corporation
3 *
4 * 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 */
10
11#include <linux/gpio/driver.h>
12#include <linux/interrupt.h>
13#include <linux/irq.h>
14#include <linux/module.h>
15#include <linux/of_device.h>
16#include <linux/platform_device.h>
17
18#include <dt-bindings/gpio/tegra186-gpio.h>
19
20#define TEGRA186_GPIO_ENABLE_CONFIG 0x00
21#define TEGRA186_GPIO_ENABLE_CONFIG_ENABLE BIT(0)
22#define TEGRA186_GPIO_ENABLE_CONFIG_OUT BIT(1)
23#define TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_TYPE_NONE (0x0 << 2)
24#define TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_TYPE_LEVEL (0x1 << 2)
25#define TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_TYPE_SINGLE_EDGE (0x2 << 2)
26#define TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_TYPE_DOUBLE_EDGE (0x3 << 2)
27#define TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_TYPE_MASK (0x3 << 2)
28#define TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_LEVEL BIT(4)
29#define TEGRA186_GPIO_ENABLE_CONFIG_INTERRUPT BIT(6)
30
31#define TEGRA186_GPIO_DEBOUNCE_CONTROL 0x04
32#define TEGRA186_GPIO_DEBOUNCE_CONTROL_THRESHOLD(x) ((x) & 0xff)
33
34#define TEGRA186_GPIO_INPUT 0x08
35#define TEGRA186_GPIO_INPUT_HIGH BIT(0)
36
37#define TEGRA186_GPIO_OUTPUT_CONTROL 0x0c
38#define TEGRA186_GPIO_OUTPUT_CONTROL_FLOATED BIT(0)
39
40#define TEGRA186_GPIO_OUTPUT_VALUE 0x10
41#define TEGRA186_GPIO_OUTPUT_VALUE_HIGH BIT(0)
42
43#define TEGRA186_GPIO_INTERRUPT_CLEAR 0x14
44
45#define TEGRA186_GPIO_INTERRUPT_STATUS(x) (0x100 + (x) * 4)
46
47struct tegra_gpio_port {
48 const char *name;
49 unsigned int offset;
50 unsigned int pins;
51 unsigned int irq;
52};
53
54struct tegra_gpio_soc {
55 const struct tegra_gpio_port *ports;
56 unsigned int num_ports;
57 const char *name;
58};
59
60struct tegra_gpio {
61 struct gpio_chip gpio;
62 struct irq_chip intc;
63 unsigned int num_irq;
64 unsigned int *irq;
65
66 const struct tegra_gpio_soc *soc;
67
68 void __iomem *base;
69};
70
71static const struct tegra_gpio_port *
72tegra186_gpio_get_port(struct tegra_gpio *gpio, unsigned int *pin)
73{
74 unsigned int start = 0, i;
75
76 for (i = 0; i < gpio->soc->num_ports; i++) {
77 const struct tegra_gpio_port *port = &gpio->soc->ports[i];
78
79 if (*pin >= start && *pin < start + port->pins) {
80 *pin -= start;
81 return port;
82 }
83
84 start += port->pins;
85 }
86
87 return NULL;
88}
89
90static void __iomem *tegra186_gpio_get_base(struct tegra_gpio *gpio,
91 unsigned int pin)
92{
93 const struct tegra_gpio_port *port;
94
95 port = tegra186_gpio_get_port(gpio, &pin);
96 if (!port)
97 return NULL;
98
99 return gpio->base + port->offset + pin * 0x20;
100}
101
102static int tegra186_gpio_get_direction(struct gpio_chip *chip,
103 unsigned int offset)
104{
105 struct tegra_gpio *gpio = gpiochip_get_data(chip);
106 void __iomem *base;
107 u32 value;
108
109 base = tegra186_gpio_get_base(gpio, offset);
110 if (WARN_ON(base == NULL))
111 return -ENODEV;
112
113 value = readl(base + TEGRA186_GPIO_ENABLE_CONFIG);
114 if (value & TEGRA186_GPIO_ENABLE_CONFIG_OUT)
115 return 0;
116
117 return 1;
118}
119
120static int tegra186_gpio_direction_input(struct gpio_chip *chip,
121 unsigned int offset)
122{
123 struct tegra_gpio *gpio = gpiochip_get_data(chip);
124 void __iomem *base;
125 u32 value;
126
127 base = tegra186_gpio_get_base(gpio, offset);
128 if (WARN_ON(base == NULL))
129 return -ENODEV;
130
131 value = readl(base + TEGRA186_GPIO_OUTPUT_CONTROL);
132 value |= TEGRA186_GPIO_OUTPUT_CONTROL_FLOATED;
133 writel(value, base + TEGRA186_GPIO_OUTPUT_CONTROL);
134
135 value = readl(base + TEGRA186_GPIO_ENABLE_CONFIG);
136 value |= TEGRA186_GPIO_ENABLE_CONFIG_ENABLE;
137 value &= ~TEGRA186_GPIO_ENABLE_CONFIG_OUT;
138 writel(value, base + TEGRA186_GPIO_ENABLE_CONFIG);
139
140 return 0;
141}
142
143static int tegra186_gpio_direction_output(struct gpio_chip *chip,
144 unsigned int offset, int level)
145{
146 struct tegra_gpio *gpio = gpiochip_get_data(chip);
147 void __iomem *base;
148 u32 value;
149
150 /* configure output level first */
151 chip->set(chip, offset, level);
152
153 base = tegra186_gpio_get_base(gpio, offset);
154 if (WARN_ON(base == NULL))
155 return -EINVAL;
156
157 /* set the direction */
158 value = readl(base + TEGRA186_GPIO_OUTPUT_CONTROL);
159 value &= ~TEGRA186_GPIO_OUTPUT_CONTROL_FLOATED;
160 writel(value, base + TEGRA186_GPIO_OUTPUT_CONTROL);
161
162 value = readl(base + TEGRA186_GPIO_ENABLE_CONFIG);
163 value |= TEGRA186_GPIO_ENABLE_CONFIG_ENABLE;
164 value |= TEGRA186_GPIO_ENABLE_CONFIG_OUT;
165 writel(value, base + TEGRA186_GPIO_ENABLE_CONFIG);
166
167 return 0;
168}
169
170static int tegra186_gpio_get(struct gpio_chip *chip, unsigned int offset)
171{
172 struct tegra_gpio *gpio = gpiochip_get_data(chip);
173 void __iomem *base;
174 u32 value;
175
176 base = tegra186_gpio_get_base(gpio, offset);
177 if (WARN_ON(base == NULL))
178 return -ENODEV;
179
180 value = readl(base + TEGRA186_GPIO_ENABLE_CONFIG);
181 if (value & TEGRA186_GPIO_ENABLE_CONFIG_OUT)
182 value = readl(base + TEGRA186_GPIO_OUTPUT_VALUE);
183 else
184 value = readl(base + TEGRA186_GPIO_INPUT);
185
186 return value & BIT(0);
187}
188
189static void tegra186_gpio_set(struct gpio_chip *chip, unsigned int offset,
190 int level)
191{
192 struct tegra_gpio *gpio = gpiochip_get_data(chip);
193 void __iomem *base;
194 u32 value;
195
196 base = tegra186_gpio_get_base(gpio, offset);
197 if (WARN_ON(base == NULL))
198 return;
199
200 value = readl(base + TEGRA186_GPIO_OUTPUT_VALUE);
201 if (level == 0)
202 value &= ~TEGRA186_GPIO_OUTPUT_VALUE_HIGH;
203 else
204 value |= TEGRA186_GPIO_OUTPUT_VALUE_HIGH;
205
206 writel(value, base + TEGRA186_GPIO_OUTPUT_VALUE);
207}
208
209static int tegra186_gpio_of_xlate(struct gpio_chip *chip,
210 const struct of_phandle_args *spec,
211 u32 *flags)
212{
213 struct tegra_gpio *gpio = gpiochip_get_data(chip);
214 unsigned int port, pin, i, offset = 0;
215
216 if (WARN_ON(chip->of_gpio_n_cells < 2))
217 return -EINVAL;
218
219 if (WARN_ON(spec->args_count < chip->of_gpio_n_cells))
220 return -EINVAL;
221
222 port = spec->args[0] / 8;
223 pin = spec->args[0] % 8;
224
225 if (port >= gpio->soc->num_ports) {
226 dev_err(chip->parent, "invalid port number: %u\n", port);
227 return -EINVAL;
228 }
229
230 for (i = 0; i < port; i++)
231 offset += gpio->soc->ports[i].pins;
232
233 if (flags)
234 *flags = spec->args[1];
235
236 return offset + pin;
237}
238
239static void tegra186_irq_ack(struct irq_data *data)
240{
241 struct tegra_gpio *gpio = irq_data_get_irq_chip_data(data);
242 void __iomem *base;
243
244 base = tegra186_gpio_get_base(gpio, data->hwirq);
245 if (WARN_ON(base == NULL))
246 return;
247
248 writel(1, base + TEGRA186_GPIO_INTERRUPT_CLEAR);
249}
250
251static void tegra186_irq_mask(struct irq_data *data)
252{
253 struct tegra_gpio *gpio = irq_data_get_irq_chip_data(data);
254 void __iomem *base;
255 u32 value;
256
257 base = tegra186_gpio_get_base(gpio, data->hwirq);
258 if (WARN_ON(base == NULL))
259 return;
260
261 value = readl(base + TEGRA186_GPIO_ENABLE_CONFIG);
262 value &= ~TEGRA186_GPIO_ENABLE_CONFIG_INTERRUPT;
263 writel(value, base + TEGRA186_GPIO_ENABLE_CONFIG);
264}
265
266static void tegra186_irq_unmask(struct irq_data *data)
267{
268 struct tegra_gpio *gpio = irq_data_get_irq_chip_data(data);
269 void __iomem *base;
270 u32 value;
271
272 base = tegra186_gpio_get_base(gpio, data->hwirq);
273 if (WARN_ON(base == NULL))
274 return;
275
276 value = readl(base + TEGRA186_GPIO_ENABLE_CONFIG);
277 value |= TEGRA186_GPIO_ENABLE_CONFIG_INTERRUPT;
278 writel(value, base + TEGRA186_GPIO_ENABLE_CONFIG);
279}
280
281static int tegra186_irq_set_type(struct irq_data *data, unsigned int flow)
282{
283 struct tegra_gpio *gpio = irq_data_get_irq_chip_data(data);
284 void __iomem *base;
285 u32 value;
286
287 base = tegra186_gpio_get_base(gpio, data->hwirq);
288 if (WARN_ON(base == NULL))
289 return -ENODEV;
290
291 value = readl(base + TEGRA186_GPIO_ENABLE_CONFIG);
292 value &= ~TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_TYPE_MASK;
293 value &= ~TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_LEVEL;
294
295 switch (flow & IRQ_TYPE_SENSE_MASK) {
296 case IRQ_TYPE_NONE:
297 break;
298
299 case IRQ_TYPE_EDGE_RISING:
300 value |= TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_TYPE_SINGLE_EDGE;
301 value |= TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_LEVEL;
302 break;
303
304 case IRQ_TYPE_EDGE_FALLING:
305 value |= TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_TYPE_SINGLE_EDGE;
306 break;
307
308 case IRQ_TYPE_EDGE_BOTH:
309 value |= TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_TYPE_DOUBLE_EDGE;
310 break;
311
312 case IRQ_TYPE_LEVEL_HIGH:
313 value |= TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_TYPE_LEVEL;
314 value |= TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_LEVEL;
315 break;
316
317 case IRQ_TYPE_LEVEL_LOW:
318 value |= TEGRA186_GPIO_ENABLE_CONFIG_TRIGGER_TYPE_LEVEL;
319 break;
320
321 default:
322 return -EINVAL;
323 }
324
325 writel(value, base + TEGRA186_GPIO_ENABLE_CONFIG);
326
327 if ((flow & IRQ_TYPE_EDGE_BOTH) == 0)
328 irq_set_handler_locked(data, handle_level_irq);
329 else
330 irq_set_handler_locked(data, handle_edge_irq);
331
332 return 0;
333}
334
335static void tegra186_gpio_irq(struct irq_desc *desc)
336{
337 struct tegra_gpio *gpio = irq_desc_get_handler_data(desc);
338 struct irq_domain *domain = gpio->gpio.irq.domain;
339 struct irq_chip *chip = irq_desc_get_chip(desc);
340 unsigned int parent = irq_desc_get_irq(desc);
341 unsigned int i, offset = 0;
342
343 chained_irq_enter(chip, desc);
344
345 for (i = 0; i < gpio->soc->num_ports; i++) {
346 const struct tegra_gpio_port *port = &gpio->soc->ports[i];
347 void __iomem *base = gpio->base + port->offset;
348 unsigned int pin, irq;
349 unsigned long value;
350
351 /* skip ports that are not associated with this controller */
352 if (parent != gpio->irq[port->irq])
353 goto skip;
354
355 value = readl(base + TEGRA186_GPIO_INTERRUPT_STATUS(1));
356
357 for_each_set_bit(pin, &value, port->pins) {
358 irq = irq_find_mapping(domain, offset + pin);
359 if (WARN_ON(irq == 0))
360 continue;
361
362 generic_handle_irq(irq);
363 }
364
365skip:
366 offset += port->pins;
367 }
368
369 chained_irq_exit(chip, desc);
370}
371
372static int tegra186_gpio_irq_domain_xlate(struct irq_domain *domain,
373 struct device_node *np,
374 const u32 *spec, unsigned int size,
375 unsigned long *hwirq,
376 unsigned int *type)
377{
378 struct tegra_gpio *gpio = gpiochip_get_data(domain->host_data);
379 unsigned int port, pin, i, offset = 0;
380
381 if (size < 2)
382 return -EINVAL;
383
384 port = spec[0] / 8;
385 pin = spec[0] % 8;
386
387 if (port >= gpio->soc->num_ports) {
388 dev_err(gpio->gpio.parent, "invalid port number: %u\n", port);
389 return -EINVAL;
390 }
391
392 for (i = 0; i < port; i++)
393 offset += gpio->soc->ports[i].pins;
394
395 *type = spec[1] & IRQ_TYPE_SENSE_MASK;
396 *hwirq = offset + pin;
397
398 return 0;
399}
400
401static const struct irq_domain_ops tegra186_gpio_irq_domain_ops = {
402 .map = gpiochip_irq_map,
403 .unmap = gpiochip_irq_unmap,
404 .xlate = tegra186_gpio_irq_domain_xlate,
405};
406
407static struct lock_class_key tegra186_gpio_lock_class;
408
409static int tegra186_gpio_probe(struct platform_device *pdev)
410{
411 unsigned int i, j, offset;
412 struct gpio_irq_chip *irq;
413 struct tegra_gpio *gpio;
414 struct resource *res;
415 char **names;
416 int err;
417
418 gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
419 if (!gpio)
420 return -ENOMEM;
421
422 gpio->soc = of_device_get_match_data(&pdev->dev);
423
424 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "gpio");
425 gpio->base = devm_ioremap_resource(&pdev->dev, res);
426 if (IS_ERR(gpio->base))
427 return PTR_ERR(gpio->base);
428
429 err = platform_irq_count(pdev);
430 if (err < 0)
431 return err;
432
433 gpio->num_irq = err;
434
435 gpio->irq = devm_kcalloc(&pdev->dev, gpio->num_irq, sizeof(*gpio->irq),
436 GFP_KERNEL);
437 if (!gpio->irq)
438 return -ENOMEM;
439
440 for (i = 0; i < gpio->num_irq; i++) {
441 err = platform_get_irq(pdev, i);
442 if (err < 0)
443 return err;
444
445 gpio->irq[i] = err;
446 }
447
448 gpio->gpio.label = gpio->soc->name;
449 gpio->gpio.parent = &pdev->dev;
450
451 gpio->gpio.get_direction = tegra186_gpio_get_direction;
452 gpio->gpio.direction_input = tegra186_gpio_direction_input;
453 gpio->gpio.direction_output = tegra186_gpio_direction_output;
454 gpio->gpio.get = tegra186_gpio_get,
455 gpio->gpio.set = tegra186_gpio_set;
456
457 gpio->gpio.base = -1;
458
459 for (i = 0; i < gpio->soc->num_ports; i++)
460 gpio->gpio.ngpio += gpio->soc->ports[i].pins;
461
462 names = devm_kcalloc(gpio->gpio.parent, gpio->gpio.ngpio,
463 sizeof(*names), GFP_KERNEL);
464 if (!names)
465 return -ENOMEM;
466
467 for (i = 0, offset = 0; i < gpio->soc->num_ports; i++) {
468 const struct tegra_gpio_port *port = &gpio->soc->ports[i];
469 char *name;
470
471 for (j = 0; j < port->pins; j++) {
472 name = devm_kasprintf(gpio->gpio.parent, GFP_KERNEL,
473 "P%s.%02x", port->name, j);
474 if (!name)
475 return -ENOMEM;
476
477 names[offset + j] = name;
478 }
479
480 offset += port->pins;
481 }
482
483 gpio->gpio.names = (const char * const *)names;
484
485 gpio->gpio.of_node = pdev->dev.of_node;
486 gpio->gpio.of_gpio_n_cells = 2;
487 gpio->gpio.of_xlate = tegra186_gpio_of_xlate;
488
489 gpio->intc.name = pdev->dev.of_node->name;
490 gpio->intc.irq_ack = tegra186_irq_ack;
491 gpio->intc.irq_mask = tegra186_irq_mask;
492 gpio->intc.irq_unmask = tegra186_irq_unmask;
493 gpio->intc.irq_set_type = tegra186_irq_set_type;
494
495 irq = &gpio->gpio.irq;
496 irq->chip = &gpio->intc;
497 irq->domain_ops = &tegra186_gpio_irq_domain_ops;
498 irq->handler = handle_simple_irq;
499 irq->lock_key = &tegra186_gpio_lock_class;
500 irq->default_type = IRQ_TYPE_NONE;
501 irq->parent_handler = tegra186_gpio_irq;
502 irq->parent_handler_data = gpio;
503 irq->num_parents = gpio->num_irq;
504 irq->parents = gpio->irq;
505
506 irq->map = devm_kcalloc(&pdev->dev, gpio->gpio.ngpio,
507 sizeof(*irq->map), GFP_KERNEL);
508 if (!irq->map)
509 return -ENOMEM;
510
511 for (i = 0, offset = 0; i < gpio->soc->num_ports; i++) {
512 const struct tegra_gpio_port *port = &gpio->soc->ports[i];
513
514 for (j = 0; j < port->pins; j++)
515 irq->map[offset + j] = irq->parents[port->irq];
516
517 offset += port->pins;
518 }
519
520 platform_set_drvdata(pdev, gpio);
521
522 err = devm_gpiochip_add_data(&pdev->dev, &gpio->gpio, gpio);
523 if (err < 0)
524 return err;
525
526 return 0;
527}
528
529static int tegra186_gpio_remove(struct platform_device *pdev)
530{
531 return 0;
532}
533
534#define TEGRA_MAIN_GPIO_PORT(port, base, count, controller) \
535 [TEGRA_MAIN_GPIO_PORT_##port] = { \
536 .name = #port, \
537 .offset = base, \
538 .pins = count, \
539 .irq = controller, \
540 }
541
542static const struct tegra_gpio_port tegra186_main_ports[] = {
543 TEGRA_MAIN_GPIO_PORT( A, 0x2000, 7, 2),
544 TEGRA_MAIN_GPIO_PORT( B, 0x3000, 7, 3),
545 TEGRA_MAIN_GPIO_PORT( C, 0x3200, 7, 3),
546 TEGRA_MAIN_GPIO_PORT( D, 0x3400, 6, 3),
547 TEGRA_MAIN_GPIO_PORT( E, 0x2200, 8, 2),
548 TEGRA_MAIN_GPIO_PORT( F, 0x2400, 6, 2),
549 TEGRA_MAIN_GPIO_PORT( G, 0x4200, 6, 4),
550 TEGRA_MAIN_GPIO_PORT( H, 0x1000, 7, 1),
551 TEGRA_MAIN_GPIO_PORT( I, 0x0800, 8, 0),
552 TEGRA_MAIN_GPIO_PORT( J, 0x5000, 8, 5),
553 TEGRA_MAIN_GPIO_PORT( K, 0x5200, 1, 5),
554 TEGRA_MAIN_GPIO_PORT( L, 0x1200, 8, 1),
555 TEGRA_MAIN_GPIO_PORT( M, 0x5600, 6, 5),
556 TEGRA_MAIN_GPIO_PORT( N, 0x0000, 7, 0),
557 TEGRA_MAIN_GPIO_PORT( O, 0x0200, 4, 0),
558 TEGRA_MAIN_GPIO_PORT( P, 0x4000, 7, 4),
559 TEGRA_MAIN_GPIO_PORT( Q, 0x0400, 6, 0),
560 TEGRA_MAIN_GPIO_PORT( R, 0x0a00, 6, 0),
561 TEGRA_MAIN_GPIO_PORT( T, 0x0600, 4, 0),
562 TEGRA_MAIN_GPIO_PORT( X, 0x1400, 8, 1),
563 TEGRA_MAIN_GPIO_PORT( Y, 0x1600, 7, 1),
564 TEGRA_MAIN_GPIO_PORT(BB, 0x2600, 2, 2),
565 TEGRA_MAIN_GPIO_PORT(CC, 0x5400, 4, 5),
566};
567
568static const struct tegra_gpio_soc tegra186_main_soc = {
569 .num_ports = ARRAY_SIZE(tegra186_main_ports),
570 .ports = tegra186_main_ports,
571 .name = "tegra186-gpio",
572};
573
574#define TEGRA_AON_GPIO_PORT(port, base, count, controller) \
575 [TEGRA_AON_GPIO_PORT_##port] = { \
576 .name = #port, \
577 .offset = base, \
578 .pins = count, \
579 .irq = controller, \
580 }
581
582static const struct tegra_gpio_port tegra186_aon_ports[] = {
583 TEGRA_AON_GPIO_PORT( S, 0x0200, 5, 0),
584 TEGRA_AON_GPIO_PORT( U, 0x0400, 6, 0),
585 TEGRA_AON_GPIO_PORT( V, 0x0800, 8, 0),
586 TEGRA_AON_GPIO_PORT( W, 0x0a00, 8, 0),
587 TEGRA_AON_GPIO_PORT( Z, 0x0e00, 4, 0),
588 TEGRA_AON_GPIO_PORT(AA, 0x0c00, 8, 0),
589 TEGRA_AON_GPIO_PORT(EE, 0x0600, 3, 0),
590 TEGRA_AON_GPIO_PORT(FF, 0x0000, 5, 0),
591};
592
593static const struct tegra_gpio_soc tegra186_aon_soc = {
594 .num_ports = ARRAY_SIZE(tegra186_aon_ports),
595 .ports = tegra186_aon_ports,
596 .name = "tegra186-gpio-aon",
597};
598
599static const struct of_device_id tegra186_gpio_of_match[] = {
600 {
601 .compatible = "nvidia,tegra186-gpio",
602 .data = &tegra186_main_soc
603 }, {
604 .compatible = "nvidia,tegra186-gpio-aon",
605 .data = &tegra186_aon_soc
606 }, {
607 /* sentinel */
608 }
609};
610
611static struct platform_driver tegra186_gpio_driver = {
612 .driver = {
613 .name = "tegra186-gpio",
614 .of_match_table = tegra186_gpio_of_match,
615 },
616 .probe = tegra186_gpio_probe,
617 .remove = tegra186_gpio_remove,
618};
619module_platform_driver(tegra186_gpio_driver);
620
621MODULE_DESCRIPTION("NVIDIA Tegra186 GPIO controller driver");
622MODULE_AUTHOR("Thierry Reding <treding@nvidia.com>");
623MODULE_LICENSE("GPL v2");