diff options
author | Haojian Zhuang <haojian.zhuang@gmail.com> | 2012-04-13 03:15:45 -0400 |
---|---|---|
committer | Haojian Zhuang <haojian.zhuang@gmail.com> | 2012-05-05 04:36:47 -0400 |
commit | 7a4d5079baf205f39efa0d9a1b273812c15a93aa (patch) | |
tree | 25cb94c3b212f83f3bcafc85e7ca87152baa7fb8 /drivers/gpio/gpio-pxa.c | |
parent | c68ef2b5921cf26225533c8ed109386578060a98 (diff) |
gpio: pxa: parse gpio from DTS file
Parse GPIO numbers from DTS file. Allocate interrupt according to
GPIO numbers.
Signed-off-by: Haojian Zhuang <haojian.zhuang@gmail.com>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Diffstat (limited to 'drivers/gpio/gpio-pxa.c')
-rw-r--r-- | drivers/gpio/gpio-pxa.c | 116 |
1 files changed, 98 insertions, 18 deletions
diff --git a/drivers/gpio/gpio-pxa.c b/drivers/gpio/gpio-pxa.c index fc3ace3fd4cb..58a6a63a6ece 100644 --- a/drivers/gpio/gpio-pxa.c +++ b/drivers/gpio/gpio-pxa.c | |||
@@ -11,13 +11,17 @@ | |||
11 | * it under the terms of the GNU General Public License version 2 as | 11 | * it under the terms of the GNU General Public License version 2 as |
12 | * published by the Free Software Foundation. | 12 | * published by the Free Software Foundation. |
13 | */ | 13 | */ |
14 | #include <linux/module.h> | ||
14 | #include <linux/clk.h> | 15 | #include <linux/clk.h> |
15 | #include <linux/err.h> | 16 | #include <linux/err.h> |
16 | #include <linux/gpio.h> | 17 | #include <linux/gpio.h> |
17 | #include <linux/gpio-pxa.h> | 18 | #include <linux/gpio-pxa.h> |
18 | #include <linux/init.h> | 19 | #include <linux/init.h> |
19 | #include <linux/irq.h> | 20 | #include <linux/irq.h> |
21 | #include <linux/irqdomain.h> | ||
20 | #include <linux/io.h> | 22 | #include <linux/io.h> |
23 | #include <linux/of.h> | ||
24 | #include <linux/of_device.h> | ||
21 | #include <linux/platform_device.h> | 25 | #include <linux/platform_device.h> |
22 | #include <linux/syscore_ops.h> | 26 | #include <linux/syscore_ops.h> |
23 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
@@ -56,6 +60,10 @@ | |||
56 | 60 | ||
57 | int pxa_last_gpio; | 61 | int pxa_last_gpio; |
58 | 62 | ||
63 | #ifdef CONFIG_OF | ||
64 | static struct irq_domain *domain; | ||
65 | #endif | ||
66 | |||
59 | struct pxa_gpio_chip { | 67 | struct pxa_gpio_chip { |
60 | struct gpio_chip chip; | 68 | struct gpio_chip chip; |
61 | void __iomem *regbase; | 69 | void __iomem *regbase; |
@@ -81,7 +89,6 @@ enum { | |||
81 | PXA3XX_GPIO, | 89 | PXA3XX_GPIO, |
82 | PXA93X_GPIO, | 90 | PXA93X_GPIO, |
83 | MMP_GPIO = 0x10, | 91 | MMP_GPIO = 0x10, |
84 | MMP2_GPIO, | ||
85 | }; | 92 | }; |
86 | 93 | ||
87 | static DEFINE_SPINLOCK(gpio_lock); | 94 | static DEFINE_SPINLOCK(gpio_lock); |
@@ -475,22 +482,92 @@ static int pxa_gpio_nums(void) | |||
475 | gpio_type = MMP_GPIO; | 482 | gpio_type = MMP_GPIO; |
476 | } else if (cpu_is_mmp2()) { | 483 | } else if (cpu_is_mmp2()) { |
477 | count = 191; | 484 | count = 191; |
478 | gpio_type = MMP2_GPIO; | 485 | gpio_type = MMP_GPIO; |
479 | } | 486 | } |
480 | #endif /* CONFIG_ARCH_MMP */ | 487 | #endif /* CONFIG_ARCH_MMP */ |
481 | return count; | 488 | return count; |
482 | } | 489 | } |
483 | 490 | ||
491 | static struct of_device_id pxa_gpio_dt_ids[] = { | ||
492 | { .compatible = "mrvl,pxa-gpio" }, | ||
493 | { .compatible = "mrvl,mmp-gpio", .data = (void *)MMP_GPIO }, | ||
494 | {} | ||
495 | }; | ||
496 | |||
497 | static int pxa_irq_domain_map(struct irq_domain *d, unsigned int irq, | ||
498 | irq_hw_number_t hw) | ||
499 | { | ||
500 | irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip, | ||
501 | handle_edge_irq); | ||
502 | set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); | ||
503 | return 0; | ||
504 | } | ||
505 | |||
506 | const struct irq_domain_ops pxa_irq_domain_ops = { | ||
507 | .map = pxa_irq_domain_map, | ||
508 | }; | ||
509 | |||
510 | #ifdef CONFIG_OF | ||
511 | static int __devinit pxa_gpio_probe_dt(struct platform_device *pdev) | ||
512 | { | ||
513 | int ret, nr_banks, nr_gpios, irq_base; | ||
514 | struct device_node *prev, *next, *np = pdev->dev.of_node; | ||
515 | const struct of_device_id *of_id = | ||
516 | of_match_device(pxa_gpio_dt_ids, &pdev->dev); | ||
517 | |||
518 | if (!of_id) { | ||
519 | dev_err(&pdev->dev, "Failed to find gpio controller\n"); | ||
520 | return -EFAULT; | ||
521 | } | ||
522 | gpio_type = (int)of_id->data; | ||
523 | |||
524 | next = of_get_next_child(np, NULL); | ||
525 | prev = next; | ||
526 | if (!next) { | ||
527 | dev_err(&pdev->dev, "Failed to find child gpio node\n"); | ||
528 | ret = -EINVAL; | ||
529 | goto err; | ||
530 | } | ||
531 | for (nr_banks = 1; ; nr_banks++) { | ||
532 | next = of_get_next_child(np, prev); | ||
533 | if (!next) | ||
534 | break; | ||
535 | prev = next; | ||
536 | } | ||
537 | of_node_put(prev); | ||
538 | nr_gpios = nr_banks << 5; | ||
539 | pxa_last_gpio = nr_gpios - 1; | ||
540 | |||
541 | irq_base = irq_alloc_descs(-1, 0, nr_gpios, 0); | ||
542 | if (irq_base < 0) { | ||
543 | dev_err(&pdev->dev, "Failed to allocate IRQ numbers\n"); | ||
544 | goto err; | ||
545 | } | ||
546 | domain = irq_domain_add_legacy(np, nr_gpios, irq_base, 0, | ||
547 | &pxa_irq_domain_ops, NULL); | ||
548 | return 0; | ||
549 | err: | ||
550 | iounmap(gpio_reg_base); | ||
551 | return ret; | ||
552 | } | ||
553 | #else | ||
554 | #define pxa_gpio_probe_dt(pdev) (-1) | ||
555 | #endif | ||
556 | |||
484 | static int __devinit pxa_gpio_probe(struct platform_device *pdev) | 557 | static int __devinit pxa_gpio_probe(struct platform_device *pdev) |
485 | { | 558 | { |
486 | struct pxa_gpio_chip *c; | 559 | struct pxa_gpio_chip *c; |
487 | struct resource *res; | 560 | struct resource *res; |
488 | struct clk *clk; | 561 | struct clk *clk; |
489 | struct pxa_gpio_platform_data *info; | 562 | struct pxa_gpio_platform_data *info; |
490 | int gpio, irq, ret; | 563 | int gpio, irq, ret, use_of = 0; |
491 | int irq0 = 0, irq1 = 0, irq_mux, gpio_offset = 0; | 564 | int irq0 = 0, irq1 = 0, irq_mux, gpio_offset = 0; |
492 | 565 | ||
493 | pxa_last_gpio = pxa_gpio_nums(); | 566 | ret = pxa_gpio_probe_dt(pdev); |
567 | if (ret < 0) | ||
568 | pxa_last_gpio = pxa_gpio_nums(); | ||
569 | else | ||
570 | use_of = 1; | ||
494 | if (!pxa_last_gpio) | 571 | if (!pxa_last_gpio) |
495 | return -EINVAL; | 572 | return -EINVAL; |
496 | 573 | ||
@@ -545,25 +622,27 @@ static int __devinit pxa_gpio_probe(struct platform_device *pdev) | |||
545 | writel_relaxed(~0, c->regbase + ED_MASK_OFFSET); | 622 | writel_relaxed(~0, c->regbase + ED_MASK_OFFSET); |
546 | } | 623 | } |
547 | 624 | ||
625 | if (!use_of) { | ||
548 | #ifdef CONFIG_ARCH_PXA | 626 | #ifdef CONFIG_ARCH_PXA |
549 | irq = gpio_to_irq(0); | 627 | irq = gpio_to_irq(0); |
550 | irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip, | 628 | irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip, |
551 | handle_edge_irq); | 629 | handle_edge_irq); |
552 | set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); | 630 | set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); |
553 | irq_set_chained_handler(IRQ_GPIO0, pxa_gpio_demux_handler); | 631 | irq_set_chained_handler(IRQ_GPIO0, pxa_gpio_demux_handler); |
554 | |||
555 | irq = gpio_to_irq(1); | ||
556 | irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip, | ||
557 | handle_edge_irq); | ||
558 | set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); | ||
559 | irq_set_chained_handler(IRQ_GPIO1, pxa_gpio_demux_handler); | ||
560 | #endif | ||
561 | 632 | ||
562 | for (irq = gpio_to_irq(gpio_offset); | 633 | irq = gpio_to_irq(1); |
563 | irq <= gpio_to_irq(pxa_last_gpio); irq++) { | ||
564 | irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip, | 634 | irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip, |
565 | handle_edge_irq); | 635 | handle_edge_irq); |
566 | set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); | 636 | set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); |
637 | irq_set_chained_handler(IRQ_GPIO1, pxa_gpio_demux_handler); | ||
638 | #endif | ||
639 | |||
640 | for (irq = gpio_to_irq(gpio_offset); | ||
641 | irq <= gpio_to_irq(pxa_last_gpio); irq++) { | ||
642 | irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip, | ||
643 | handle_edge_irq); | ||
644 | set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); | ||
645 | } | ||
567 | } | 646 | } |
568 | 647 | ||
569 | irq_set_chained_handler(irq_mux, pxa_gpio_demux_handler); | 648 | irq_set_chained_handler(irq_mux, pxa_gpio_demux_handler); |
@@ -574,6 +653,7 @@ static struct platform_driver pxa_gpio_driver = { | |||
574 | .probe = pxa_gpio_probe, | 653 | .probe = pxa_gpio_probe, |
575 | .driver = { | 654 | .driver = { |
576 | .name = "pxa-gpio", | 655 | .name = "pxa-gpio", |
656 | .of_match_table = pxa_gpio_dt_ids, | ||
577 | }, | 657 | }, |
578 | }; | 658 | }; |
579 | 659 | ||