diff options
author | Tony Lindgren <tony@atomide.com> | 2006-04-02 12:46:23 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2006-04-02 12:46:23 -0400 |
commit | 6e60e79a1d46eaa3369febc2f6c31e0acfaaae3f (patch) | |
tree | 38f59d144de2d3c61f21515647b6b066ed1477e2 | |
parent | 8d7f9f5037a09b8570d0c9e60a924ad2ba6fa7dd (diff) |
[ARM] 3429/1: ARM: OMAP: 4/8 Update GPIO
Patch from Tony Lindgren
Update OMAP GPIO code from linux-omap tree:
- Fix omap16xx edge control by Juha Yrjola
- Support for additional omap16xx trigger modes by Dirk Behme
- Fix edge detection by Tony Lindgren et al.
- Better support for omap15xx and omap310 by Andrej Zaborowski
- Fix omap15xx interrupt bug by Petukhov Nikolay
Signed-off-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-rw-r--r-- | arch/arm/plat-omap/gpio.c | 86 |
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; | |||
174 | static inline struct gpio_bank *get_gpio_bank(int gpio) | 174 | static 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; |