aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/plat-omap
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/plat-omap')
-rw-r--r--arch/arm/plat-omap/gpio.c86
1 files changed, 61 insertions, 25 deletions
diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c
index b4d5b9e4bfce..d3c8ea7eecfd 100644
--- a/arch/arm/plat-omap/gpio.c
+++ b/arch/arm/plat-omap/gpio.c
@@ -174,7 +174,7 @@ static int gpio_bank_count;
174static inline struct gpio_bank *get_gpio_bank(int gpio) 174static inline struct gpio_bank *get_gpio_bank(int gpio)
175{ 175{
176#ifdef CONFIG_ARCH_OMAP15XX 176#ifdef CONFIG_ARCH_OMAP15XX
177 if (cpu_is_omap1510()) { 177 if (cpu_is_omap15xx()) {
178 if (OMAP_GPIO_IS_MPUIO(gpio)) 178 if (OMAP_GPIO_IS_MPUIO(gpio))
179 return &gpio_bank[0]; 179 return &gpio_bank[0];
180 return &gpio_bank[1]; 180 return &gpio_bank[1];
@@ -223,7 +223,7 @@ static inline int gpio_valid(int gpio)
223 return 0; 223 return 0;
224 } 224 }
225#ifdef CONFIG_ARCH_OMAP15XX 225#ifdef CONFIG_ARCH_OMAP15XX
226 if (cpu_is_omap1510() && gpio < 16) 226 if (cpu_is_omap15xx() && gpio < 16)
227 return 0; 227 return 0;
228#endif 228#endif
229#if defined(CONFIG_ARCH_OMAP16XX) 229#if defined(CONFIG_ARCH_OMAP16XX)
@@ -402,13 +402,13 @@ static inline void set_24xx_gpio_triggering(void __iomem *base, int gpio, int tr
402 u32 gpio_bit = 1 << gpio; 402 u32 gpio_bit = 1 << gpio;
403 403
404 MOD_REG_BIT(OMAP24XX_GPIO_LEVELDETECT0, gpio_bit, 404 MOD_REG_BIT(OMAP24XX_GPIO_LEVELDETECT0, gpio_bit,
405 trigger & IRQT_LOW); 405 trigger & __IRQT_LOWLVL);
406 MOD_REG_BIT(OMAP24XX_GPIO_LEVELDETECT1, gpio_bit, 406 MOD_REG_BIT(OMAP24XX_GPIO_LEVELDETECT1, gpio_bit,
407 trigger & IRQT_HIGH); 407 trigger & __IRQT_HIGHLVL);
408 MOD_REG_BIT(OMAP24XX_GPIO_RISINGDETECT, gpio_bit, 408 MOD_REG_BIT(OMAP24XX_GPIO_RISINGDETECT, gpio_bit,
409 trigger & IRQT_RISING); 409 trigger & __IRQT_RISEDGE);
410 MOD_REG_BIT(OMAP24XX_GPIO_FALLINGDETECT, gpio_bit, 410 MOD_REG_BIT(OMAP24XX_GPIO_FALLINGDETECT, gpio_bit,
411 trigger & IRQT_FALLING); 411 trigger & __IRQT_FALEDGE);
412 /* FIXME: Possibly do 'set_irq_handler(j, do_level_IRQ)' if only level 412 /* FIXME: Possibly do 'set_irq_handler(j, do_level_IRQ)' if only level
413 * triggering requested. */ 413 * triggering requested. */
414} 414}
@@ -422,9 +422,9 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger)
422 case METHOD_MPUIO: 422 case METHOD_MPUIO:
423 reg += OMAP_MPUIO_GPIO_INT_EDGE; 423 reg += OMAP_MPUIO_GPIO_INT_EDGE;
424 l = __raw_readl(reg); 424 l = __raw_readl(reg);
425 if (trigger == IRQT_RISING) 425 if (trigger & __IRQT_RISEDGE)
426 l |= 1 << gpio; 426 l |= 1 << gpio;
427 else if (trigger == IRQT_FALLING) 427 else if (trigger & __IRQT_FALEDGE)
428 l &= ~(1 << gpio); 428 l &= ~(1 << gpio);
429 else 429 else
430 goto bad; 430 goto bad;
@@ -432,9 +432,9 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger)
432 case METHOD_GPIO_1510: 432 case METHOD_GPIO_1510:
433 reg += OMAP1510_GPIO_INT_CONTROL; 433 reg += OMAP1510_GPIO_INT_CONTROL;
434 l = __raw_readl(reg); 434 l = __raw_readl(reg);
435 if (trigger == IRQT_RISING) 435 if (trigger & __IRQT_RISEDGE)
436 l |= 1 << gpio; 436 l |= 1 << gpio;
437 else if (trigger == IRQT_FALLING) 437 else if (trigger & __IRQT_FALEDGE)
438 l &= ~(1 << gpio); 438 l &= ~(1 << gpio);
439 else 439 else
440 goto bad; 440 goto bad;
@@ -446,20 +446,21 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger)
446 reg += OMAP1610_GPIO_EDGE_CTRL1; 446 reg += OMAP1610_GPIO_EDGE_CTRL1;
447 gpio &= 0x07; 447 gpio &= 0x07;
448 /* We allow only edge triggering, i.e. two lowest bits */ 448 /* We allow only edge triggering, i.e. two lowest bits */
449 if (trigger & ~IRQT_BOTHEDGE) 449 if (trigger & (__IRQT_LOWLVL | __IRQT_HIGHLVL))
450 BUG(); 450 BUG();
451 /* NOTE: knows __IRQT_{FAL,RIS}EDGE match OMAP hardware */
452 trigger &= 0x03;
453 l = __raw_readl(reg); 451 l = __raw_readl(reg);
454 l &= ~(3 << (gpio << 1)); 452 l &= ~(3 << (gpio << 1));
455 l |= trigger << (gpio << 1); 453 if (trigger & __IRQT_RISEDGE)
454 l |= 2 << (gpio << 1);
455 if (trigger & __IRQT_FALEDGE)
456 l |= 1 << (gpio << 1);
456 break; 457 break;
457 case METHOD_GPIO_730: 458 case METHOD_GPIO_730:
458 reg += OMAP730_GPIO_INT_CONTROL; 459 reg += OMAP730_GPIO_INT_CONTROL;
459 l = __raw_readl(reg); 460 l = __raw_readl(reg);
460 if (trigger == IRQT_RISING) 461 if (trigger & __IRQT_RISEDGE)
461 l |= 1 << gpio; 462 l |= 1 << gpio;
462 else if (trigger == IRQT_FALLING) 463 else if (trigger & __IRQT_FALEDGE)
463 l &= ~(1 << gpio); 464 l &= ~(1 << gpio);
464 else 465 else
465 goto bad; 466 goto bad;
@@ -491,7 +492,9 @@ static int gpio_irq_type(unsigned irq, unsigned type)
491 if (check_gpio(gpio) < 0) 492 if (check_gpio(gpio) < 0)
492 return -EINVAL; 493 return -EINVAL;
493 494
494 if (type & (__IRQT_LOWLVL|__IRQT_HIGHLVL|IRQT_PROBE)) 495 if (type & IRQT_PROBE)
496 return -EINVAL;
497 if (!cpu_is_omap24xx() && (type & (__IRQT_LOWLVL|__IRQT_HIGHLVL)))
495 return -EINVAL; 498 return -EINVAL;
496 499
497 bank = get_gpio_bank(gpio); 500 bank = get_gpio_bank(gpio);
@@ -755,13 +758,32 @@ static void gpio_irq_handler(unsigned int irq, struct irqdesc *desc,
755 if (bank->method == METHOD_GPIO_24XX) 758 if (bank->method == METHOD_GPIO_24XX)
756 isr_reg = bank->base + OMAP24XX_GPIO_IRQSTATUS1; 759 isr_reg = bank->base + OMAP24XX_GPIO_IRQSTATUS1;
757#endif 760#endif
758
759 while(1) { 761 while(1) {
760 isr = __raw_readl(isr_reg); 762 u32 isr_saved, level_mask = 0;
761 _enable_gpio_irqbank(bank, isr, 0); 763
762 _clear_gpio_irqbank(bank, isr); 764 isr_saved = isr = __raw_readl(isr_reg);
763 _enable_gpio_irqbank(bank, isr, 1); 765
764 desc->chip->unmask(irq); 766 if (cpu_is_omap15xx() && (bank->method == METHOD_MPUIO))
767 isr &= 0x0000ffff;
768
769 if (cpu_is_omap24xx())
770 level_mask =
771 __raw_readl(bank->base +
772 OMAP24XX_GPIO_LEVELDETECT0) |
773 __raw_readl(bank->base +
774 OMAP24XX_GPIO_LEVELDETECT1);
775
776 /* clear edge sensitive interrupts before handler(s) are
777 called so that we don't miss any interrupt occurred while
778 executing them */
779 _enable_gpio_irqbank(bank, isr_saved & ~level_mask, 0);
780 _clear_gpio_irqbank(bank, isr_saved & ~level_mask);
781 _enable_gpio_irqbank(bank, isr_saved & ~level_mask, 1);
782
783 /* if there is only edge sensitive GPIO pin interrupts
784 configured, we could unmask GPIO bank interrupt immediately */
785 if (!level_mask)
786 desc->chip->unmask(irq);
765 787
766 if (!isr) 788 if (!isr)
767 break; 789 break;
@@ -774,6 +796,20 @@ static void gpio_irq_handler(unsigned int irq, struct irqdesc *desc,
774 d = irq_desc + gpio_irq; 796 d = irq_desc + gpio_irq;
775 desc_handle_irq(gpio_irq, d, regs); 797 desc_handle_irq(gpio_irq, d, regs);
776 } 798 }
799
800 if (cpu_is_omap24xx()) {
801 /* clear level sensitive interrupts after handler(s) */
802 _enable_gpio_irqbank(bank, isr_saved & level_mask, 0);
803 _clear_gpio_irqbank(bank, isr_saved & level_mask);
804 _enable_gpio_irqbank(bank, isr_saved & level_mask, 1);
805 }
806
807 /* if bank has any level sensitive GPIO pin interrupt
808 configured, we must unmask the bank interrupt only after
809 handler(s) are executed in order to avoid spurious bank
810 interrupt */
811 if (level_mask)
812 desc->chip->unmask(irq);
777 } 813 }
778} 814}
779 815
@@ -848,7 +884,7 @@ static int __init _omap_gpio_init(void)
848 884
849 initialized = 1; 885 initialized = 1;
850 886
851 if (cpu_is_omap1510()) { 887 if (cpu_is_omap15xx()) {
852 gpio_ick = clk_get(NULL, "arm_gpio_ck"); 888 gpio_ick = clk_get(NULL, "arm_gpio_ck");
853 if (IS_ERR(gpio_ick)) 889 if (IS_ERR(gpio_ick))
854 printk("Could not get arm_gpio_ck\n"); 890 printk("Could not get arm_gpio_ck\n");
@@ -869,7 +905,7 @@ static int __init _omap_gpio_init(void)
869 } 905 }
870 906
871#ifdef CONFIG_ARCH_OMAP15XX 907#ifdef CONFIG_ARCH_OMAP15XX
872 if (cpu_is_omap1510()) { 908 if (cpu_is_omap15xx()) {
873 printk(KERN_INFO "OMAP1510 GPIO hardware\n"); 909 printk(KERN_INFO "OMAP1510 GPIO hardware\n");
874 gpio_bank_count = 2; 910 gpio_bank_count = 2;
875 gpio_bank = gpio_bank_1510; 911 gpio_bank = gpio_bank_1510;