diff options
Diffstat (limited to 'arch/arm/plat-omap/gpio.c')
-rw-r--r-- | arch/arm/plat-omap/gpio.c | 127 |
1 files changed, 95 insertions, 32 deletions
diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c index 26b387c1242..9298bc0ab17 100644 --- a/arch/arm/plat-omap/gpio.c +++ b/arch/arm/plat-omap/gpio.c @@ -476,14 +476,12 @@ static void _set_gpio_dataout(struct gpio_bank *bank, int gpio, int enable) __raw_writel(l, reg); } -static int __omap_get_gpio_datain(int gpio) +static int _get_gpio_datain(struct gpio_bank *bank, int gpio) { - struct gpio_bank *bank; void __iomem *reg; if (check_gpio(gpio) < 0) return -EINVAL; - bank = get_gpio_bank(gpio); reg = bank->base; switch (bank->method) { #ifdef CONFIG_ARCH_OMAP1 @@ -524,6 +522,53 @@ static int __omap_get_gpio_datain(int gpio) & (1 << get_gpio_index(gpio))) != 0; } +static int _get_gpio_dataout(struct gpio_bank *bank, int gpio) +{ + void __iomem *reg; + + if (check_gpio(gpio) < 0) + return -EINVAL; + reg = bank->base; + + switch (bank->method) { +#ifdef CONFIG_ARCH_OMAP1 + case METHOD_MPUIO: + reg += OMAP_MPUIO_OUTPUT; + break; +#endif +#ifdef CONFIG_ARCH_OMAP15XX + case METHOD_GPIO_1510: + reg += OMAP1510_GPIO_DATA_OUTPUT; + break; +#endif +#ifdef CONFIG_ARCH_OMAP16XX + case METHOD_GPIO_1610: + reg += OMAP1610_GPIO_DATAOUT; + break; +#endif +#ifdef CONFIG_ARCH_OMAP730 + case METHOD_GPIO_730: + reg += OMAP730_GPIO_DATA_OUTPUT; + break; +#endif +#ifdef CONFIG_ARCH_OMAP850 + case METHOD_GPIO_850: + reg += OMAP850_GPIO_DATA_OUTPUT; + break; +#endif +#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \ + defined(CONFIG_ARCH_OMAP4) + case METHOD_GPIO_24XX: + reg += OMAP24XX_GPIO_DATAOUT; + break; +#endif + default: + return -EINVAL; + } + + return (__raw_readl(reg) & (1 << get_gpio_index(gpio))) != 0; +} + #define MOD_REG_BIT(reg, bit_mask, set) \ do { \ int l = __raw_readl(base + reg); \ @@ -1189,6 +1234,7 @@ static void gpio_mask_irq(unsigned int irq) struct gpio_bank *bank = get_irq_chip_data(irq); _set_gpio_irqenable(bank, gpio, 0); + _set_gpio_triggering(bank, get_gpio_index(gpio), IRQ_TYPE_NONE); } static void gpio_unmask_irq(unsigned int irq) @@ -1196,6 +1242,11 @@ static void gpio_unmask_irq(unsigned int irq) unsigned int gpio = irq - IH_GPIO_BASE; struct gpio_bank *bank = get_irq_chip_data(irq); unsigned int irq_mask = 1 << get_gpio_index(gpio); + struct irq_desc *desc = irq_to_desc(irq); + u32 trigger = desc->status & IRQ_TYPE_SENSE_MASK; + + if (trigger) + _set_gpio_triggering(bank, get_gpio_index(gpio), trigger); /* For level-triggered GPIOs, the clearing must be done after * the HW source is cleared, thus after the handler has run */ @@ -1350,9 +1401,49 @@ static int gpio_input(struct gpio_chip *chip, unsigned offset) return 0; } +static int gpio_is_input(struct gpio_bank *bank, int mask) +{ + void __iomem *reg = bank->base; + + switch (bank->method) { + case METHOD_MPUIO: + reg += OMAP_MPUIO_IO_CNTL; + break; + case METHOD_GPIO_1510: + reg += OMAP1510_GPIO_DIR_CONTROL; + break; + case METHOD_GPIO_1610: + reg += OMAP1610_GPIO_DIRECTION; + break; + case METHOD_GPIO_730: + reg += OMAP730_GPIO_DIR_CONTROL; + break; + case METHOD_GPIO_850: + reg += OMAP850_GPIO_DIR_CONTROL; + break; + case METHOD_GPIO_24XX: + reg += OMAP24XX_GPIO_OE; + break; + } + return __raw_readl(reg) & mask; +} + static int gpio_get(struct gpio_chip *chip, unsigned offset) { - return __omap_get_gpio_datain(chip->base + offset); + struct gpio_bank *bank; + void __iomem *reg; + int gpio; + u32 mask; + + gpio = chip->base + offset; + bank = get_gpio_bank(gpio); + reg = bank->base; + mask = 1 << get_gpio_index(gpio); + + if (gpio_is_input(bank, mask)) + return _get_gpio_datain(bank, gpio); + else + return _get_gpio_dataout(bank, gpio); } static int gpio_output(struct gpio_chip *chip, unsigned offset, int value) @@ -1886,34 +1977,6 @@ arch_initcall(omap_gpio_sysinit); #include <linux/debugfs.h> #include <linux/seq_file.h> -static int gpio_is_input(struct gpio_bank *bank, int mask) -{ - void __iomem *reg = bank->base; - - switch (bank->method) { - case METHOD_MPUIO: - reg += OMAP_MPUIO_IO_CNTL; - break; - case METHOD_GPIO_1510: - reg += OMAP1510_GPIO_DIR_CONTROL; - break; - case METHOD_GPIO_1610: - reg += OMAP1610_GPIO_DIRECTION; - break; - case METHOD_GPIO_730: - reg += OMAP730_GPIO_DIR_CONTROL; - break; - case METHOD_GPIO_850: - reg += OMAP850_GPIO_DIR_CONTROL; - break; - case METHOD_GPIO_24XX: - reg += OMAP24XX_GPIO_OE; - break; - } - return __raw_readl(reg) & mask; -} - - static int dbg_gpio_show(struct seq_file *s, void *unused) { unsigned i, j, gpio; |