From df4aab46a8256ac0f0c2701b3fe23b7dd05e6b48 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Mon, 4 May 2009 13:14:27 -0700 Subject: davinci: gpio irq enable tweaks Fix two IRQ triggering bugs affecting GPIO IRQs: - Make sure enabling with IRQ_TYPE_NONE ("default, unspecified") isn't a NOP ... default to both edges, at least one must work. - As noted by Kevin Hilman, setting the irq trigger type for a banked gpio interrupt shouldn't enable irqs that are disabled. Since GPIO IRQs haven't been used much yet, it's not clear these bugs could have affected anything. The few current users don't seem to have been obviously suffering from these issues. Signed-off-by: David Brownell Signed-off-by: Kevin Hilman --- arch/arm/mach-davinci/gpio.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'arch/arm/mach-davinci/gpio.c') diff --git a/arch/arm/mach-davinci/gpio.c b/arch/arm/mach-davinci/gpio.c index 1aba41c6351..34ba4ceda34 100644 --- a/arch/arm/mach-davinci/gpio.c +++ b/arch/arm/mach-davinci/gpio.c @@ -187,10 +187,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; - if (irq_desc[irq].status & IRQ_TYPE_EDGE_FALLING) + status &= IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING; + if (!status) + status = IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING; + + 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 +210,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; } -- cgit v1.2.3 From dc75602628472d7fbc4cb43f010bf0257e95ab71 Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Mon, 11 May 2009 11:04:53 -0700 Subject: davinci: fixups for banked GPIO interrupt handling This patch seems to get me much more reliable performance using the GPIO banked interrupts on dm355 for the dm9000 driver. Changes include: - init GPIO handling along with normal GPIO init - mask the level-sensitive bank IRQ during handling Signed-off-by: Kevin Hilman --- arch/arm/mach-davinci/gpio.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'arch/arm/mach-davinci/gpio.c') diff --git a/arch/arm/mach-davinci/gpio.c b/arch/arm/mach-davinci/gpio.c index 34ba4ceda34..40327b557d7 100644 --- a/arch/arm/mach-davinci/gpio.c +++ b/arch/arm/mach-davinci/gpio.c @@ -45,6 +45,7 @@ static struct gpio_controller __iomem * __init gpio2controller(unsigned gpio) return __gpio_to_controller(gpio); } +static int __init davinci_gpio_irq_setup(void); /*--------------------------------------------------------------------------*/ @@ -157,6 +158,7 @@ static int __init davinci_gpio_setup(void) gpiochip_add(&chips[i].chip); } + davinci_gpio_irq_setup(); return 0; } pure_initcall(davinci_gpio_setup); @@ -238,6 +240,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; @@ -333,4 +336,3 @@ static int __init davinci_gpio_irq_setup(void) return 0; } -arch_initcall(davinci_gpio_irq_setup); -- cgit v1.2.3 From a994955cc091a8a51b7d7412174d9cf6de04d26b Mon Sep 17 00:00:00 2001 From: "Mark A. Greer" Date: Wed, 15 Apr 2009 12:40:35 -0700 Subject: davinci: Make GPIO code more generic The current gpio code needs to know the number of gpio irqs there are and what the bank irq number is. To determine those values, it checks the SoC type. It also assumes that the base address and the number of irqs the interrupt controller uses is fixed. To clean up the SoC checks and make it support different base addresses and interrupt controllers, have the SoC-specific code set those values in the soc_info structure and have the gpio code reference them there. Signed-off-by: Mark A. Greer Signed-off-by: Kevin Hilman --- arch/arm/mach-davinci/gpio.c | 39 ++++++++++++++------------------------- 1 file changed, 14 insertions(+), 25 deletions(-) (limited to 'arch/arm/mach-davinci/gpio.c') diff --git a/arch/arm/mach-davinci/gpio.c b/arch/arm/mach-davinci/gpio.c index 40327b557d7..1b6532159c5 100644 --- a/arch/arm/mach-davinci/gpio.c +++ b/arch/arm/mach-davinci/gpio.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -37,8 +38,6 @@ 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) { @@ -116,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; } @@ -279,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; } @@ -329,8 +319,7 @@ 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)); -- cgit v1.2.3