summaryrefslogtreecommitdiff
path: root/arch/arm/mach-davinci/gpio.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-davinci/gpio.c')
-rw-r--r--arch/arm/mach-davinci/gpio.c63
1 files changed, 31 insertions, 32 deletions
diff --git a/arch/arm/mach-davinci/gpio.c b/arch/arm/mach-davinci/gpio.c
index 1aba41c6351e..1b6532159c58 100644
--- a/arch/arm/mach-davinci/gpio.c
+++ b/arch/arm/mach-davinci/gpio.c
@@ -23,6 +23,7 @@
#include <mach/cputype.h>
#include <mach/irqs.h>
#include <mach/hardware.h>
+#include <mach/common.h>
#include <mach/gpio.h>
#include <asm/mach/irq.h>
@@ -37,14 +38,13 @@ struct davinci_gpio {
static struct davinci_gpio chips[DIV_ROUND_UP(DAVINCI_N_GPIO, 32)];
-static unsigned __initdata ngpio;
-
/* create a non-inlined version */
static struct gpio_controller __iomem * __init gpio2controller(unsigned gpio)
{
return __gpio_to_controller(gpio);
}
+static int __init davinci_gpio_irq_setup(void);
/*--------------------------------------------------------------------------*/
@@ -115,23 +115,16 @@ davinci_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
static int __init davinci_gpio_setup(void)
{
int i, base;
+ unsigned ngpio;
+ struct davinci_soc_info *soc_info = &davinci_soc_info;
- /* The gpio banks conceptually expose a segmented bitmap,
+ /*
+ * The gpio banks conceptually expose a segmented bitmap,
* and "ngpio" is one more than the largest zero-based
* bit index that's valid.
*/
- if (cpu_is_davinci_dm355()) { /* or dm335() */
- ngpio = 104;
- } else if (cpu_is_davinci_dm644x()) { /* or dm337() */
- ngpio = 71;
- } else if (cpu_is_davinci_dm646x()) {
- /* NOTE: each bank has several "reserved" bits,
- * unusable as GPIOs. Only 33 of the GPIO numbers
- * are usable, and we're not rejecting the others.
- */
- ngpio = 43;
- } else {
- /* if cpu_is_davinci_dm643x() ngpio = 111 */
+ ngpio = soc_info->gpio_num;
+ if (ngpio == 0) {
pr_err("GPIO setup: how many GPIOs?\n");
return -EINVAL;
}
@@ -157,6 +150,7 @@ static int __init davinci_gpio_setup(void)
gpiochip_add(&chips[i].chip);
}
+ davinci_gpio_irq_setup();
return 0;
}
pure_initcall(davinci_gpio_setup);
@@ -187,10 +181,15 @@ static void gpio_irq_enable(unsigned irq)
{
struct gpio_controller *__iomem g = get_irq_chip_data(irq);
u32 mask = __gpio_mask(irq_to_gpio(irq));
+ unsigned status = irq_desc[irq].status;
+
+ status &= IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING;
+ if (!status)
+ status = IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING;
- if (irq_desc[irq].status & IRQ_TYPE_EDGE_FALLING)
+ if (status & IRQ_TYPE_EDGE_FALLING)
__raw_writel(mask, &g->set_falling);
- if (irq_desc[irq].status & IRQ_TYPE_EDGE_RISING)
+ if (status & IRQ_TYPE_EDGE_RISING)
__raw_writel(mask, &g->set_rising);
}
@@ -205,10 +204,13 @@ static int gpio_irq_type(unsigned irq, unsigned trigger)
irq_desc[irq].status &= ~IRQ_TYPE_SENSE_MASK;
irq_desc[irq].status |= trigger;
- __raw_writel(mask, (trigger & IRQ_TYPE_EDGE_FALLING)
- ? &g->set_falling : &g->clr_falling);
- __raw_writel(mask, (trigger & IRQ_TYPE_EDGE_RISING)
- ? &g->set_rising : &g->clr_rising);
+ /* don't enable the IRQ if it's currently disabled */
+ if (irq_desc[irq].depth == 0) {
+ __raw_writel(mask, (trigger & IRQ_TYPE_EDGE_FALLING)
+ ? &g->set_falling : &g->clr_falling);
+ __raw_writel(mask, (trigger & IRQ_TYPE_EDGE_RISING)
+ ? &g->set_rising : &g->clr_rising);
+ }
return 0;
}
@@ -230,6 +232,7 @@ gpio_irq_handler(unsigned irq, struct irq_desc *desc)
mask <<= 16;
/* temporarily mask (level sensitive) parent IRQ */
+ desc->chip->mask(irq);
desc->chip->ack(irq);
while (1) {
u32 status;
@@ -268,17 +271,15 @@ gpio_irq_handler(unsigned irq, struct irq_desc *desc)
static int __init davinci_gpio_irq_setup(void)
{
unsigned gpio, irq, bank;
- unsigned bank_irq;
struct clk *clk;
u32 binten = 0;
+ unsigned ngpio, bank_irq;
+ struct davinci_soc_info *soc_info = &davinci_soc_info;
+
+ ngpio = soc_info->gpio_num;
- if (cpu_is_davinci_dm355()) { /* or dm335() */
- bank_irq = IRQ_DM355_GPIOBNK0;
- } else if (cpu_is_davinci_dm644x()) {
- bank_irq = IRQ_GPIOBNK0;
- } else if (cpu_is_davinci_dm646x()) {
- bank_irq = IRQ_DM646X_GPIOBNK0;
- } else {
+ bank_irq = soc_info->gpio_irq;
+ if (bank_irq == 0) {
printk(KERN_ERR "Don't know first GPIO bank IRQ.\n");
return -EINVAL;
}
@@ -318,11 +319,9 @@ static int __init davinci_gpio_irq_setup(void)
/* BINTEN -- per-bank interrupt enable. genirq would also let these
* bits be set/cleared dynamically.
*/
- __raw_writel(binten, (void *__iomem)
- IO_ADDRESS(DAVINCI_GPIO_BASE + 0x08));
+ __raw_writel(binten, soc_info->gpio_base + 0x08);
printk(KERN_INFO "DaVinci: %d gpio irqs\n", irq - gpio_to_irq(0));
return 0;
}
-arch_initcall(davinci_gpio_irq_setup);