X-Git-Url: http://pilppa.org/gitweb/?a=blobdiff_plain;f=arch%2Farm%2Fplat-omap%2Fgpio.c;h=33305e3fd416e4fedee5df770293680ee12eb0d6;hb=ee4645b252977cafe56c1e3b45a6abc542bd573a;hp=8679fbca6bbec4ec3d5e5561b92c633cf1e6f298;hpb=a02efb906d12c9d4eb2ab7c59049ba9545e5412d;p=linux-2.6-omap-h63xx.git diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c index 8679fbca6bb..798a8cd811a 100644 --- a/arch/arm/plat-omap/gpio.c +++ b/arch/arm/plat-omap/gpio.c @@ -101,6 +101,7 @@ #define OMAP24XX_GPIO_IRQSTATUS2 0x0028 #define OMAP24XX_GPIO_IRQENABLE2 0x002c #define OMAP24XX_GPIO_IRQENABLE1 0x001c +#define OMAP24XX_GPIO_WAKE_EN 0x0020 #define OMAP24XX_GPIO_CTRL 0x0030 #define OMAP24XX_GPIO_OE 0x0034 #define OMAP24XX_GPIO_DATAIN 0x0038 @@ -151,6 +152,7 @@ struct gpio_bank { u32 level_mask; spinlock_t lock; struct gpio_chip chip; + struct clk *dbck; }; #define METHOD_MPUIO 0 @@ -243,6 +245,8 @@ static inline struct gpio_bank *get_gpio_bank(int gpio) return &gpio_bank[gpio >> 5]; if (cpu_is_omap34xx()) return &gpio_bank[gpio >> 5]; + BUG(); + return NULL; } static inline int get_gpio_index(int gpio) @@ -331,19 +335,6 @@ static void _set_gpio_direction(struct gpio_bank *bank, int gpio, int is_input) __raw_writel(l, reg); } -void omap_set_gpio_direction(int gpio, int is_input) -{ - struct gpio_bank *bank; - unsigned long flags; - - if (check_gpio(gpio) < 0) - return; - bank = get_gpio_bank(gpio); - spin_lock_irqsave(&bank->lock, flags); - _set_gpio_direction(bank, get_gpio_index(gpio), is_input); - spin_unlock_irqrestore(&bank->lock, flags); -} - static void _set_gpio_dataout(struct gpio_bank *bank, int gpio, int enable) { void __iomem *reg = bank->base; @@ -405,20 +396,7 @@ static void _set_gpio_dataout(struct gpio_bank *bank, int gpio, int enable) __raw_writel(l, reg); } -void omap_set_gpio_dataout(int gpio, int enable) -{ - struct gpio_bank *bank; - unsigned long flags; - - if (check_gpio(gpio) < 0) - return; - bank = get_gpio_bank(gpio); - spin_lock_irqsave(&bank->lock, flags); - _set_gpio_dataout(bank, get_gpio_index(gpio), enable); - spin_unlock_irqrestore(&bank->lock, flags); -} - -int omap_get_gpio_datain(int gpio) +static int __omap_get_gpio_datain(int gpio) { struct gpio_bank *bank; void __iomem *reg; @@ -472,6 +450,7 @@ void omap_set_gpio_debounce(int gpio, int enable) { struct gpio_bank *bank; void __iomem *reg; + unsigned long flags; u32 val, l = 1 << get_gpio_index(gpio); if (cpu_class_is_omap1()) @@ -479,16 +458,28 @@ void omap_set_gpio_debounce(int gpio, int enable) bank = get_gpio_bank(gpio); reg = bank->base; - reg += OMAP24XX_GPIO_DEBOUNCE_EN; + + spin_lock_irqsave(&bank->lock, flags); val = __raw_readl(reg); - if (enable) + if (enable && !(val & l)) val |= l; - else + else if (!enable && (val & l)) val &= ~l; + else + goto done; + + if (cpu_is_omap34xx()) { + if (enable) + clk_enable(bank->dbck); + else + clk_disable(bank->dbck); + } __raw_writel(val, reg); +done: + spin_unlock_irqrestore(&bank->lock, flags); } EXPORT_SYMBOL(omap_set_gpio_debounce); @@ -846,13 +837,10 @@ static int _set_gpio_wakeup(struct gpio_bank *bank, int gpio, int enable) case METHOD_MPUIO: case METHOD_GPIO_1610: spin_lock_irqsave(&bank->lock, flags); - if (enable) { + if (enable) bank->suspend_wakeup |= (1 << gpio); - enable_irq_wake(bank->irq); - } else { - disable_irq_wake(bank->irq); + else bank->suspend_wakeup &= ~(1 << gpio); - } spin_unlock_irqrestore(&bank->lock, flags); return 0; #endif @@ -865,13 +853,10 @@ static int _set_gpio_wakeup(struct gpio_bank *bank, int gpio, int enable) return -EINVAL; } spin_lock_irqsave(&bank->lock, flags); - if (enable) { + if (enable) bank->suspend_wakeup |= (1 << gpio); - enable_irq_wake(bank->irq); - } else { - disable_irq_wake(bank->irq); + else bank->suspend_wakeup &= ~(1 << gpio); - } spin_unlock_irqrestore(&bank->lock, flags); return 0; #endif @@ -905,26 +890,17 @@ static int gpio_wake_enable(unsigned int irq, unsigned int enable) return retval; } -int omap_request_gpio(int gpio) +static int omap_gpio_request(struct gpio_chip *chip, unsigned offset) { - struct gpio_bank *bank; + struct gpio_bank *bank = container_of(chip, struct gpio_bank, chip); unsigned long flags; - int status; - - if (check_gpio(gpio) < 0) - return -EINVAL; - - status = gpio_request(gpio, NULL); - if (status < 0) - return status; - bank = get_gpio_bank(gpio); spin_lock_irqsave(&bank->lock, flags); /* Set trigger to none. You need to enable the desired trigger with * request_irq() or set_irq_type(). */ - _set_gpio_triggering(bank, get_gpio_index(gpio), IRQ_TYPE_NONE); + _set_gpio_triggering(bank, offset, IRQ_TYPE_NONE); #ifdef CONFIG_ARCH_OMAP15XX if (bank->method == METHOD_GPIO_1510) { @@ -932,7 +908,7 @@ int omap_request_gpio(int gpio) /* Claim the pin for MPU */ reg = bank->base + OMAP1510_GPIO_PIN_CONTROL; - __raw_writel(__raw_readl(reg) | (1 << get_gpio_index(gpio)), reg); + __raw_writel(__raw_readl(reg) | (1 << offset), reg); } #endif spin_unlock_irqrestore(&bank->lock, flags); @@ -940,39 +916,28 @@ int omap_request_gpio(int gpio) return 0; } -void omap_free_gpio(int gpio) +static void omap_gpio_free(struct gpio_chip *chip, unsigned offset) { - struct gpio_bank *bank; + struct gpio_bank *bank = container_of(chip, struct gpio_bank, chip); unsigned long flags; - if (check_gpio(gpio) < 0) - return; - bank = get_gpio_bank(gpio); spin_lock_irqsave(&bank->lock, flags); - if (unlikely(!gpiochip_is_requested(&bank->chip, - get_gpio_index(gpio)))) { - spin_unlock_irqrestore(&bank->lock, flags); - printk(KERN_ERR "omap-gpio: GPIO %d wasn't reserved!\n", gpio); - dump_stack(); - return; - } #ifdef CONFIG_ARCH_OMAP16XX if (bank->method == METHOD_GPIO_1610) { /* Disable wake-up during idle for dynamic tick */ void __iomem *reg = bank->base + OMAP1610_GPIO_CLEAR_WAKEUPENA; - __raw_writel(1 << get_gpio_index(gpio), reg); + __raw_writel(1 << offset, reg); } #endif #if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) if (bank->method == METHOD_GPIO_24XX) { /* Disable wake-up during idle for dynamic tick */ void __iomem *reg = bank->base + OMAP24XX_GPIO_CLEARWKUENA; - __raw_writel(1 << get_gpio_index(gpio), reg); + __raw_writel(1 << offset, reg); } #endif - _reset_gpio(bank, gpio); + _reset_gpio(bank, bank->chip.base + offset); spin_unlock_irqrestore(&bank->lock, flags); - gpio_free(gpio); } /* @@ -1251,7 +1216,7 @@ static int gpio_input(struct gpio_chip *chip, unsigned offset) static int gpio_get(struct gpio_chip *chip, unsigned offset) { - return omap_get_gpio_datain(chip->base + offset); + return __omap_get_gpio_datain(chip->base + offset); } static int gpio_output(struct gpio_chip *chip, unsigned offset, int value) @@ -1278,6 +1243,14 @@ static void gpio_set(struct gpio_chip *chip, unsigned offset, int value) spin_unlock_irqrestore(&bank->lock, flags); } +static int gpio_2irq(struct gpio_chip *chip, unsigned offset) +{ + struct gpio_bank *bank; + + bank = container_of(chip, struct gpio_bank, chip); + return bank->virtual_irq_start + offset; +} + /*---------------------------------------------------------------------*/ static int initialized; @@ -1295,7 +1268,6 @@ static struct clk * gpio5_fck; #endif #if defined(CONFIG_ARCH_OMAP3) -static struct clk *gpio_fclks[OMAP34XX_NR_GPIOS]; static struct clk *gpio_iclks[OMAP34XX_NR_GPIOS]; #endif @@ -1309,9 +1281,7 @@ static int __init _omap_gpio_init(void) int i; int gpio = 0; struct gpio_bank *bank; -#if defined(CONFIG_ARCH_OMAP3) char clk_name[11]; -#endif initialized = 1; @@ -1366,12 +1336,6 @@ static int __init _omap_gpio_init(void) printk(KERN_ERR "Could not get %s\n", clk_name); else clk_enable(gpio_iclks[i]); - sprintf(clk_name, "gpio%d_fck", i + 1); - gpio_fclks[i] = clk_get(NULL, clk_name); - if (IS_ERR(gpio_fclks[i])) - printk(KERN_ERR "Could not get %s\n", clk_name); - else - clk_enable(gpio_fclks[i]); } } #endif @@ -1478,10 +1442,13 @@ static int __init _omap_gpio_init(void) /* REVISIT eventually switch from OMAP-specific gpio structs * over to the generic ones */ + bank->chip.request = omap_gpio_request; + bank->chip.free = omap_gpio_free; bank->chip.direction_input = gpio_input; bank->chip.get = gpio_get; bank->chip.direction_output = gpio_output; bank->chip.set = gpio_set; + bank->chip.to_irq = gpio_2irq; if (bank_is_mpuio(bank)) { bank->chip.label = "mpuio"; #ifdef CONFIG_ARCH_OMAP16XX @@ -1510,6 +1477,13 @@ static int __init _omap_gpio_init(void) } set_irq_chained_handler(bank->irq, gpio_irq_handler); set_irq_data(bank->irq, bank); + + if (cpu_is_omap34xx()) { + sprintf(clk_name, "gpio%d_dbck", i + 1); + bank->dbck = clk_get(NULL, clk_name); + if (IS_ERR(bank->dbck)) + printk(KERN_ERR "Could not get %s\n", clk_name); + } } /* Enable system clock for GPIO module. @@ -1551,7 +1525,7 @@ static int omap_gpio_suspend(struct sys_device *dev, pm_message_t mesg) #endif #if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) case METHOD_GPIO_24XX: - wake_status = bank->base + OMAP24XX_GPIO_SETWKUENA; + wake_status = bank->base + OMAP24XX_GPIO_WAKE_EN; wake_clear = bank->base + OMAP24XX_GPIO_CLEARWKUENA; wake_set = bank->base + OMAP24XX_GPIO_SETWKUENA; break; @@ -1574,7 +1548,7 @@ static int omap_gpio_resume(struct sys_device *dev) { int i; - if (!cpu_is_omap24xx() && !cpu_is_omap16xx()) + if (!cpu_class_is_omap2() && !cpu_is_omap16xx()) return 0; for (i = 0; i < gpio_bank_count; i++) { @@ -1738,12 +1712,6 @@ static int __init omap_gpio_sysinit(void) return ret; } -EXPORT_SYMBOL(omap_request_gpio); -EXPORT_SYMBOL(omap_free_gpio); -EXPORT_SYMBOL(omap_set_gpio_direction); -EXPORT_SYMBOL(omap_set_gpio_dataout); -EXPORT_SYMBOL(omap_get_gpio_datain); - arch_initcall(omap_gpio_sysinit); @@ -1800,14 +1768,14 @@ static int dbg_gpio_show(struct seq_file *s, void *unused) continue; irq = bank->virtual_irq_start + j; - value = omap_get_gpio_datain(gpio); + value = gpio_get_value(gpio); is_in = gpio_is_input(bank, mask); if (bank_is_mpuio(bank)) seq_printf(s, "MPUIO %2d ", j); else seq_printf(s, "GPIO %3d ", gpio); - seq_printf(s, "(%10s): %s %s", + seq_printf(s, "(%-20.20s): %s %s", label, is_in ? "in " : "out", value ? "hi" : "lo"); @@ -1815,6 +1783,8 @@ static int dbg_gpio_show(struct seq_file *s, void *unused) /* FIXME for at least omap2, show pullup/pulldown state */ irqstat = irq_desc[irq].status; +#if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP24XX) || \ + defined(CONFIG_ARCH_OMAP34XX) if (is_in && ((bank->suspend_wakeup & mask) || irqstat & IRQ_TYPE_SENSE_MASK)) { char *trigger = NULL; @@ -1844,6 +1814,7 @@ static int dbg_gpio_show(struct seq_file *s, void *unused) (bank->suspend_wakeup & mask) ? " wakeup" : ""); } +#endif seq_printf(s, "\n"); }