aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/plat-nomadik/gpio.c114
-rw-r--r--arch/arm/plat-nomadik/include/plat/gpio.h3
2 files changed, 100 insertions, 17 deletions
diff --git a/arch/arm/plat-nomadik/gpio.c b/arch/arm/plat-nomadik/gpio.c
index 45b1cf95e378..70620426ee55 100644
--- a/arch/arm/plat-nomadik/gpio.c
+++ b/arch/arm/plat-nomadik/gpio.c
@@ -50,6 +50,10 @@ struct nmk_gpio_chip {
50 /* Keep track of configured edges */ 50 /* Keep track of configured edges */
51 u32 edge_rising; 51 u32 edge_rising;
52 u32 edge_falling; 52 u32 edge_falling;
53 u32 real_wake;
54 u32 rwimsc;
55 u32 fwimsc;
56 u32 slpm;
53}; 57};
54 58
55static struct nmk_gpio_chip * 59static struct nmk_gpio_chip *
@@ -534,8 +538,20 @@ static void __nmk_gpio_irq_modify(struct nmk_gpio_chip *nmk_chip,
534 } 538 }
535} 539}
536 540
537static int nmk_gpio_irq_modify(struct irq_data *d, enum nmk_gpio_irq_type which, 541static void __nmk_gpio_set_wake(struct nmk_gpio_chip *nmk_chip,
538 bool enable) 542 int gpio, bool on)
543{
544#ifdef CONFIG_ARCH_U8500
545 if (cpu_is_u8500v2()) {
546 __nmk_gpio_set_slpm(nmk_chip, gpio - nmk_chip->chip.base,
547 on ? NMK_GPIO_SLPM_WAKEUP_ENABLE
548 : NMK_GPIO_SLPM_WAKEUP_DISABLE);
549 }
550#endif
551 __nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, on);
552}
553
554static int nmk_gpio_irq_maskunmask(struct irq_data *d, bool enable)
539{ 555{
540 int gpio; 556 int gpio;
541 struct nmk_gpio_chip *nmk_chip; 557 struct nmk_gpio_chip *nmk_chip;
@@ -548,45 +564,55 @@ static int nmk_gpio_irq_modify(struct irq_data *d, enum nmk_gpio_irq_type which,
548 if (!nmk_chip) 564 if (!nmk_chip)
549 return -EINVAL; 565 return -EINVAL;
550 566
551 spin_lock_irqsave(&nmk_chip->lock, flags); 567 spin_lock_irqsave(&nmk_gpio_slpm_lock, flags);
552 __nmk_gpio_irq_modify(nmk_chip, gpio, which, enable); 568 spin_lock(&nmk_chip->lock);
553 spin_unlock_irqrestore(&nmk_chip->lock, flags); 569
570 __nmk_gpio_irq_modify(nmk_chip, gpio, NORMAL, enable);
571
572 if (!(nmk_chip->real_wake & bitmask))
573 __nmk_gpio_set_wake(nmk_chip, gpio, enable);
574
575 spin_unlock(&nmk_chip->lock);
576 spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags);
554 577
555 return 0; 578 return 0;
556} 579}
557 580
558static void nmk_gpio_irq_mask(struct irq_data *d) 581static void nmk_gpio_irq_mask(struct irq_data *d)
559{ 582{
560 nmk_gpio_irq_modify(d, NORMAL, false); 583 nmk_gpio_irq_maskunmask(d, false);
561} 584}
562 585
563static void nmk_gpio_irq_unmask(struct irq_data *d) 586static void nmk_gpio_irq_unmask(struct irq_data *d)
564{ 587{
565 nmk_gpio_irq_modify(d, NORMAL, true); 588 nmk_gpio_irq_maskunmask(d, true);
566} 589}
567 590
568static int nmk_gpio_irq_set_wake(struct irq_data *d, unsigned int on) 591static int nmk_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
569{ 592{
593 struct irq_desc *desc = irq_to_desc(d->irq);
594 bool enabled = !(desc->status & IRQ_DISABLED);
570 struct nmk_gpio_chip *nmk_chip; 595 struct nmk_gpio_chip *nmk_chip;
571 unsigned long flags; 596 unsigned long flags;
597 u32 bitmask;
572 int gpio; 598 int gpio;
573 599
574 gpio = NOMADIK_IRQ_TO_GPIO(d->irq); 600 gpio = NOMADIK_IRQ_TO_GPIO(d->irq);
575 nmk_chip = irq_data_get_irq_chip_data(d); 601 nmk_chip = irq_data_get_irq_chip_data(d);
576 if (!nmk_chip) 602 if (!nmk_chip)
577 return -EINVAL; 603 return -EINVAL;
604 bitmask = nmk_gpio_get_bitmask(gpio);
578 605
579 spin_lock_irqsave(&nmk_gpio_slpm_lock, flags); 606 spin_lock_irqsave(&nmk_gpio_slpm_lock, flags);
580 spin_lock(&nmk_chip->lock); 607 spin_lock(&nmk_chip->lock);
581 608
582#ifdef CONFIG_ARCH_U8500 609 if (!enabled)
583 if (cpu_is_u8500v2()) { 610 __nmk_gpio_set_wake(nmk_chip, gpio, on);
584 __nmk_gpio_set_slpm(nmk_chip, gpio - nmk_chip->chip.base, 611
585 on ? NMK_GPIO_SLPM_WAKEUP_ENABLE 612 if (on)
586 : NMK_GPIO_SLPM_WAKEUP_DISABLE); 613 nmk_chip->real_wake |= bitmask;
587 } 614 else
588#endif 615 nmk_chip->real_wake &= ~bitmask;
589 __nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, on);
590 616
591 spin_unlock(&nmk_chip->lock); 617 spin_unlock(&nmk_chip->lock);
592 spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags); 618 spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags);
@@ -620,7 +646,7 @@ static int nmk_gpio_irq_set_type(struct irq_data *d, unsigned int type)
620 if (enabled) 646 if (enabled)
621 __nmk_gpio_irq_modify(nmk_chip, gpio, NORMAL, false); 647 __nmk_gpio_irq_modify(nmk_chip, gpio, NORMAL, false);
622 648
623 if (wake) 649 if (enabled || wake)
624 __nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, false); 650 __nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, false);
625 651
626 nmk_chip->edge_rising &= ~bitmask; 652 nmk_chip->edge_rising &= ~bitmask;
@@ -634,7 +660,7 @@ static int nmk_gpio_irq_set_type(struct irq_data *d, unsigned int type)
634 if (enabled) 660 if (enabled)
635 __nmk_gpio_irq_modify(nmk_chip, gpio, NORMAL, true); 661 __nmk_gpio_irq_modify(nmk_chip, gpio, NORMAL, true);
636 662
637 if (wake) 663 if (enabled || wake)
638 __nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, true); 664 __nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, true);
639 665
640 spin_unlock_irqrestore(&nmk_chip->lock, flags); 666 spin_unlock_irqrestore(&nmk_chip->lock, flags);
@@ -870,6 +896,60 @@ static struct gpio_chip nmk_gpio_template = {
870 .can_sleep = 0, 896 .can_sleep = 0,
871}; 897};
872 898
899/*
900 * Called from the suspend/resume path to only keep the real wakeup interrupts
901 * (those that have had set_irq_wake() called on them) as wakeup interrupts,
902 * and not the rest of the interrupts which we needed to have as wakeups for
903 * cpuidle.
904 *
905 * PM ops are not used since this needs to be done at the end, after all the
906 * other drivers are done with their suspend callbacks.
907 */
908void nmk_gpio_wakeups_suspend(void)
909{
910 int i;
911
912 for (i = 0; i < NUM_BANKS; i++) {
913 struct nmk_gpio_chip *chip = nmk_gpio_chips[i];
914
915 if (!chip)
916 break;
917
918 chip->rwimsc = readl(chip->addr + NMK_GPIO_RWIMSC);
919 chip->fwimsc = readl(chip->addr + NMK_GPIO_FWIMSC);
920
921 writel(chip->rwimsc & chip->real_wake,
922 chip->addr + NMK_GPIO_RWIMSC);
923 writel(chip->fwimsc & chip->real_wake,
924 chip->addr + NMK_GPIO_FWIMSC);
925
926 if (cpu_is_u8500v2()) {
927 chip->slpm = readl(chip->addr + NMK_GPIO_SLPC);
928
929 /* 0 -> wakeup enable */
930 writel(~chip->real_wake, chip->addr + NMK_GPIO_SLPC);
931 }
932 }
933}
934
935void nmk_gpio_wakeups_resume(void)
936{
937 int i;
938
939 for (i = 0; i < NUM_BANKS; i++) {
940 struct nmk_gpio_chip *chip = nmk_gpio_chips[i];
941
942 if (!chip)
943 break;
944
945 writel(chip->rwimsc, chip->addr + NMK_GPIO_RWIMSC);
946 writel(chip->fwimsc, chip->addr + NMK_GPIO_FWIMSC);
947
948 if (cpu_is_u8500v2())
949 writel(chip->slpm, chip->addr + NMK_GPIO_SLPC);
950 }
951}
952
873static int __devinit nmk_gpio_probe(struct platform_device *dev) 953static int __devinit nmk_gpio_probe(struct platform_device *dev)
874{ 954{
875 struct nmk_gpio_platform_data *pdata = dev->dev.platform_data; 955 struct nmk_gpio_platform_data *pdata = dev->dev.platform_data;
diff --git a/arch/arm/plat-nomadik/include/plat/gpio.h b/arch/arm/plat-nomadik/include/plat/gpio.h
index e3a4837e86f4..1b9f6f0843d1 100644
--- a/arch/arm/plat-nomadik/include/plat/gpio.h
+++ b/arch/arm/plat-nomadik/include/plat/gpio.h
@@ -75,6 +75,9 @@ extern int nmk_gpio_set_pull(int gpio, enum nmk_gpio_pull pull);
75extern int nmk_gpio_set_mode(int gpio, int gpio_mode); 75extern int nmk_gpio_set_mode(int gpio, int gpio_mode);
76extern int nmk_gpio_get_mode(int gpio); 76extern int nmk_gpio_get_mode(int gpio);
77 77
78extern void nmk_gpio_wakeups_suspend(void);
79extern void nmk_gpio_wakeups_resume(void);
80
78/* 81/*
79 * Platform data to register a block: only the initial gpio/irq number. 82 * Platform data to register a block: only the initial gpio/irq number.
80 */ 83 */