diff options
Diffstat (limited to 'arch/arm/mach-davinci/gpio.c')
| -rw-r--r-- | arch/arm/mach-davinci/gpio.c | 63 | 
1 files changed, 31 insertions, 32 deletions
diff --git a/arch/arm/mach-davinci/gpio.c b/arch/arm/mach-davinci/gpio.c index 1aba41c6351..1b6532159c5 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);  |