aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorRabin Vincent <rabin.vincent@stericsson.com>2010-10-14 01:08:03 -0400
committerLinus Walleij <linus.walleij@linaro.org>2011-03-14 09:05:15 -0400
commit33b744b35189baaa260f526cf117392095331843 (patch)
tree009bb385065b80e385cc040c998bc08280c38343 /arch
parentc84c7c08e320acfd10a0b7e55dbb0bc819b6d284 (diff)
plat-nomadik: support secondary GPIO interrupts
When GPIOs wake up the system from sleep mode, the normal GPIO interrupt handler does not hit and the normal interrupt status register does not contain the status. Instead the secondary GPIO handler does, and the interrupt status needs to be retrieved from the wakeup status saved by the suspend/resume code. Signed-off-by: Rabin Vincent <rabin.vincent@stericsson.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/plat-nomadik/gpio.c51
-rw-r--r--arch/arm/plat-nomadik/include/plat/gpio.h1
2 files changed, 46 insertions, 6 deletions
diff --git a/arch/arm/plat-nomadik/gpio.c b/arch/arm/plat-nomadik/gpio.c
index 46f1af869b7f..971e5d3798e4 100644
--- a/arch/arm/plat-nomadik/gpio.c
+++ b/arch/arm/plat-nomadik/gpio.c
@@ -39,7 +39,10 @@ struct nmk_gpio_chip {
39 struct gpio_chip chip; 39 struct gpio_chip chip;
40 void __iomem *addr; 40 void __iomem *addr;
41 struct clk *clk; 41 struct clk *clk;
42 unsigned int bank;
42 unsigned int parent_irq; 43 unsigned int parent_irq;
44 unsigned int secondary_parent_irq;
45 u32 (*get_secondary_status)(unsigned int bank);
43 spinlock_t lock; 46 spinlock_t lock;
44 /* Keep track of configured edges */ 47 /* Keep track of configured edges */
45 u32 edge_rising; 48 u32 edge_rising;
@@ -514,12 +517,11 @@ static struct irq_chip nmk_gpio_irq_chip = {
514 .irq_set_wake = nmk_gpio_irq_set_wake, 517 .irq_set_wake = nmk_gpio_irq_set_wake,
515}; 518};
516 519
517static void nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) 520static void __nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc,
521 u32 status)
518{ 522{
519 struct nmk_gpio_chip *nmk_chip; 523 struct nmk_gpio_chip *nmk_chip;
520 struct irq_chip *host_chip = get_irq_chip(irq); 524 struct irq_chip *host_chip = get_irq_chip(irq);
521 unsigned int gpio_irq;
522 u32 pending;
523 unsigned int first_irq; 525 unsigned int first_irq;
524 526
525 if (host_chip->irq_mask_ack) 527 if (host_chip->irq_mask_ack)
@@ -532,14 +534,33 @@ static void nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
532 534
533 nmk_chip = get_irq_data(irq); 535 nmk_chip = get_irq_data(irq);
534 first_irq = NOMADIK_GPIO_TO_IRQ(nmk_chip->chip.base); 536 first_irq = NOMADIK_GPIO_TO_IRQ(nmk_chip->chip.base);
535 while ( (pending = readl(nmk_chip->addr + NMK_GPIO_IS)) ) { 537 while (status) {
536 gpio_irq = first_irq + __ffs(pending); 538 int bit = __ffs(status);
537 generic_handle_irq(gpio_irq); 539
540 generic_handle_irq(first_irq + bit);
541 status &= ~BIT(bit);
538 } 542 }
539 543
540 host_chip->irq_unmask(&desc->irq_data); 544 host_chip->irq_unmask(&desc->irq_data);
541} 545}
542 546
547static void nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
548{
549 struct nmk_gpio_chip *nmk_chip = get_irq_data(irq);
550 u32 status = readl(nmk_chip->addr + NMK_GPIO_IS);
551
552 __nmk_gpio_irq_handler(irq, desc, status);
553}
554
555static void nmk_gpio_secondary_irq_handler(unsigned int irq,
556 struct irq_desc *desc)
557{
558 struct nmk_gpio_chip *nmk_chip = get_irq_data(irq);
559 u32 status = nmk_chip->get_secondary_status(nmk_chip->bank);
560
561 __nmk_gpio_irq_handler(irq, desc, status);
562}
563
543static int nmk_gpio_init_irq(struct nmk_gpio_chip *nmk_chip) 564static int nmk_gpio_init_irq(struct nmk_gpio_chip *nmk_chip)
544{ 565{
545 unsigned int first_irq; 566 unsigned int first_irq;
@@ -553,8 +574,16 @@ static int nmk_gpio_init_irq(struct nmk_gpio_chip *nmk_chip)
553 set_irq_chip_data(i, nmk_chip); 574 set_irq_chip_data(i, nmk_chip);
554 set_irq_type(i, IRQ_TYPE_EDGE_FALLING); 575 set_irq_type(i, IRQ_TYPE_EDGE_FALLING);
555 } 576 }
577
556 set_irq_chained_handler(nmk_chip->parent_irq, nmk_gpio_irq_handler); 578 set_irq_chained_handler(nmk_chip->parent_irq, nmk_gpio_irq_handler);
557 set_irq_data(nmk_chip->parent_irq, nmk_chip); 579 set_irq_data(nmk_chip->parent_irq, nmk_chip);
580
581 if (nmk_chip->secondary_parent_irq >= 0) {
582 set_irq_chained_handler(nmk_chip->secondary_parent_irq,
583 nmk_gpio_secondary_irq_handler);
584 set_irq_data(nmk_chip->secondary_parent_irq, nmk_chip);
585 }
586
558 return 0; 587 return 0;
559} 588}
560 589
@@ -714,6 +743,7 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev)
714 struct gpio_chip *chip; 743 struct gpio_chip *chip;
715 struct resource *res; 744 struct resource *res;
716 struct clk *clk; 745 struct clk *clk;
746 int secondary_irq;
717 int irq; 747 int irq;
718 int ret; 748 int ret;
719 749
@@ -732,6 +762,12 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev)
732 goto out; 762 goto out;
733 } 763 }
734 764
765 secondary_irq = platform_get_irq(dev, 1);
766 if (secondary_irq >= 0 && !pdata->get_secondary_status) {
767 ret = -EINVAL;
768 goto out;
769 }
770
735 if (request_mem_region(res->start, resource_size(res), 771 if (request_mem_region(res->start, resource_size(res),
736 dev_name(&dev->dev)) == NULL) { 772 dev_name(&dev->dev)) == NULL) {
737 ret = -EBUSY; 773 ret = -EBUSY;
@@ -755,10 +791,13 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev)
755 * The virt address in nmk_chip->addr is in the nomadik register space, 791 * The virt address in nmk_chip->addr is in the nomadik register space,
756 * so we can simply convert the resource address, without remapping 792 * so we can simply convert the resource address, without remapping
757 */ 793 */
794 nmk_chip->bank = dev->id;
758 nmk_chip->clk = clk; 795 nmk_chip->clk = clk;
759 nmk_chip->addr = io_p2v(res->start); 796 nmk_chip->addr = io_p2v(res->start);
760 nmk_chip->chip = nmk_gpio_template; 797 nmk_chip->chip = nmk_gpio_template;
761 nmk_chip->parent_irq = irq; 798 nmk_chip->parent_irq = irq;
799 nmk_chip->secondary_parent_irq = secondary_irq;
800 nmk_chip->get_secondary_status = pdata->get_secondary_status;
762 spin_lock_init(&nmk_chip->lock); 801 spin_lock_init(&nmk_chip->lock);
763 802
764 chip = &nmk_chip->chip; 803 chip = &nmk_chip->chip;
diff --git a/arch/arm/plat-nomadik/include/plat/gpio.h b/arch/arm/plat-nomadik/include/plat/gpio.h
index d745f3ac0a61..d108a326a0ab 100644
--- a/arch/arm/plat-nomadik/include/plat/gpio.h
+++ b/arch/arm/plat-nomadik/include/plat/gpio.h
@@ -83,6 +83,7 @@ struct nmk_gpio_platform_data {
83 int first_gpio; 83 int first_gpio;
84 int first_irq; 84 int first_irq;
85 int num_gpio; 85 int num_gpio;
86 u32 (*get_secondary_status)(unsigned int bank);
86}; 87};
87 88
88#endif /* __ASM_PLAT_GPIO_H */ 89#endif /* __ASM_PLAT_GPIO_H */