diff options
Diffstat (limited to 'arch/arm/mach-davinci/gpio.c')
-rw-r--r-- | arch/arm/mach-davinci/gpio.c | 105 |
1 files changed, 99 insertions, 6 deletions
diff --git a/arch/arm/mach-davinci/gpio.c b/arch/arm/mach-davinci/gpio.c index 1b6532159c58..f6ea9db11f41 100644 --- a/arch/arm/mach-davinci/gpio.c +++ b/arch/arm/mach-davinci/gpio.c | |||
@@ -34,6 +34,7 @@ static DEFINE_SPINLOCK(gpio_lock); | |||
34 | struct davinci_gpio { | 34 | struct davinci_gpio { |
35 | struct gpio_chip chip; | 35 | struct gpio_chip chip; |
36 | struct gpio_controller *__iomem regs; | 36 | struct gpio_controller *__iomem regs; |
37 | int irq_base; | ||
37 | }; | 38 | }; |
38 | 39 | ||
39 | static struct davinci_gpio chips[DIV_ROUND_UP(DAVINCI_N_GPIO, 32)]; | 40 | static struct davinci_gpio chips[DIV_ROUND_UP(DAVINCI_N_GPIO, 32)]; |
@@ -161,8 +162,7 @@ pure_initcall(davinci_gpio_setup); | |||
161 | * used as output pins ... which is convenient for testing. | 162 | * used as output pins ... which is convenient for testing. |
162 | * | 163 | * |
163 | * NOTE: The first few GPIOs also have direct INTC hookups in addition | 164 | * NOTE: The first few GPIOs also have direct INTC hookups in addition |
164 | * to their GPIOBNK0 irq, with a bit less overhead but less flexibility | 165 | * to their GPIOBNK0 irq, with a bit less overhead. |
165 | * on triggering (e.g. no edge options). We don't try to use those. | ||
166 | * | 166 | * |
167 | * All those INTC hookups (direct, plus several IRQ banks) can also | 167 | * All those INTC hookups (direct, plus several IRQ banks) can also |
168 | * serve as EDMA event triggers. | 168 | * serve as EDMA event triggers. |
@@ -171,7 +171,7 @@ pure_initcall(davinci_gpio_setup); | |||
171 | static void gpio_irq_disable(unsigned irq) | 171 | static void gpio_irq_disable(unsigned irq) |
172 | { | 172 | { |
173 | struct gpio_controller *__iomem g = get_irq_chip_data(irq); | 173 | struct gpio_controller *__iomem g = get_irq_chip_data(irq); |
174 | u32 mask = __gpio_mask(irq_to_gpio(irq)); | 174 | u32 mask = (u32) get_irq_data(irq); |
175 | 175 | ||
176 | __raw_writel(mask, &g->clr_falling); | 176 | __raw_writel(mask, &g->clr_falling); |
177 | __raw_writel(mask, &g->clr_rising); | 177 | __raw_writel(mask, &g->clr_rising); |
@@ -180,7 +180,7 @@ static void gpio_irq_disable(unsigned irq) | |||
180 | static void gpio_irq_enable(unsigned irq) | 180 | static void gpio_irq_enable(unsigned irq) |
181 | { | 181 | { |
182 | struct gpio_controller *__iomem g = get_irq_chip_data(irq); | 182 | struct gpio_controller *__iomem g = get_irq_chip_data(irq); |
183 | u32 mask = __gpio_mask(irq_to_gpio(irq)); | 183 | u32 mask = (u32) get_irq_data(irq); |
184 | unsigned status = irq_desc[irq].status; | 184 | unsigned status = irq_desc[irq].status; |
185 | 185 | ||
186 | status &= IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING; | 186 | status &= IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING; |
@@ -196,7 +196,7 @@ static void gpio_irq_enable(unsigned irq) | |||
196 | static int gpio_irq_type(unsigned irq, unsigned trigger) | 196 | static int gpio_irq_type(unsigned irq, unsigned trigger) |
197 | { | 197 | { |
198 | struct gpio_controller *__iomem g = get_irq_chip_data(irq); | 198 | struct gpio_controller *__iomem g = get_irq_chip_data(irq); |
199 | u32 mask = __gpio_mask(irq_to_gpio(irq)); | 199 | u32 mask = (u32) get_irq_data(irq); |
200 | 200 | ||
201 | if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)) | 201 | if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)) |
202 | return -EINVAL; | 202 | return -EINVAL; |
@@ -260,6 +260,45 @@ gpio_irq_handler(unsigned irq, struct irq_desc *desc) | |||
260 | /* now it may re-trigger */ | 260 | /* now it may re-trigger */ |
261 | } | 261 | } |
262 | 262 | ||
263 | static int gpio_to_irq_banked(struct gpio_chip *chip, unsigned offset) | ||
264 | { | ||
265 | struct davinci_gpio *d = container_of(chip, struct davinci_gpio, chip); | ||
266 | |||
267 | if (d->irq_base >= 0) | ||
268 | return d->irq_base + offset; | ||
269 | else | ||
270 | return -ENODEV; | ||
271 | } | ||
272 | |||
273 | static int gpio_to_irq_unbanked(struct gpio_chip *chip, unsigned offset) | ||
274 | { | ||
275 | struct davinci_soc_info *soc_info = &davinci_soc_info; | ||
276 | |||
277 | /* NOTE: we assume for now that only irqs in the first gpio_chip | ||
278 | * can provide direct-mapped IRQs to AINTC (up to 32 GPIOs). | ||
279 | */ | ||
280 | if (offset < soc_info->gpio_unbanked) | ||
281 | return soc_info->gpio_irq + offset; | ||
282 | else | ||
283 | return -ENODEV; | ||
284 | } | ||
285 | |||
286 | static int gpio_irq_type_unbanked(unsigned irq, unsigned trigger) | ||
287 | { | ||
288 | struct gpio_controller *__iomem g = get_irq_chip_data(irq); | ||
289 | u32 mask = (u32) get_irq_data(irq); | ||
290 | |||
291 | if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)) | ||
292 | return -EINVAL; | ||
293 | |||
294 | __raw_writel(mask, (trigger & IRQ_TYPE_EDGE_FALLING) | ||
295 | ? &g->set_falling : &g->clr_falling); | ||
296 | __raw_writel(mask, (trigger & IRQ_TYPE_EDGE_RISING) | ||
297 | ? &g->set_rising : &g->clr_rising); | ||
298 | |||
299 | return 0; | ||
300 | } | ||
301 | |||
263 | /* | 302 | /* |
264 | * NOTE: for suspend/resume, probably best to make a platform_device with | 303 | * NOTE: for suspend/resume, probably best to make a platform_device with |
265 | * suspend_late/resume_resume calls hooking into results of the set_wake() | 304 | * suspend_late/resume_resume calls hooking into results of the set_wake() |
@@ -275,6 +314,7 @@ static int __init davinci_gpio_irq_setup(void) | |||
275 | u32 binten = 0; | 314 | u32 binten = 0; |
276 | unsigned ngpio, bank_irq; | 315 | unsigned ngpio, bank_irq; |
277 | struct davinci_soc_info *soc_info = &davinci_soc_info; | 316 | struct davinci_soc_info *soc_info = &davinci_soc_info; |
317 | struct gpio_controller *__iomem g; | ||
278 | 318 | ||
279 | ngpio = soc_info->gpio_num; | 319 | ngpio = soc_info->gpio_num; |
280 | 320 | ||
@@ -292,12 +332,63 @@ static int __init davinci_gpio_irq_setup(void) | |||
292 | } | 332 | } |
293 | clk_enable(clk); | 333 | clk_enable(clk); |
294 | 334 | ||
335 | /* Arrange gpio_to_irq() support, handling either direct IRQs or | ||
336 | * banked IRQs. Having GPIOs in the first GPIO bank use direct | ||
337 | * IRQs, while the others use banked IRQs, would need some setup | ||
338 | * tweaks to recognize hardware which can do that. | ||
339 | */ | ||
340 | for (gpio = 0, bank = 0; gpio < ngpio; bank++, gpio += 32) { | ||
341 | chips[bank].chip.to_irq = gpio_to_irq_banked; | ||
342 | chips[bank].irq_base = soc_info->gpio_unbanked | ||
343 | ? -EINVAL | ||
344 | : (soc_info->intc_irq_num + gpio); | ||
345 | } | ||
346 | |||
347 | /* | ||
348 | * AINTC can handle direct/unbanked IRQs for GPIOs, with the GPIO | ||
349 | * controller only handling trigger modes. We currently assume no | ||
350 | * IRQ mux conflicts; gpio_irq_type_unbanked() is only for GPIOs. | ||
351 | */ | ||
352 | if (soc_info->gpio_unbanked) { | ||
353 | static struct irq_chip gpio_irqchip_unbanked; | ||
354 | |||
355 | /* pass "bank 0" GPIO IRQs to AINTC */ | ||
356 | chips[0].chip.to_irq = gpio_to_irq_unbanked; | ||
357 | binten = BIT(0); | ||
358 | |||
359 | /* AINTC handles mask/unmask; GPIO handles triggering */ | ||
360 | irq = bank_irq; | ||
361 | gpio_irqchip_unbanked = *get_irq_desc_chip(irq_to_desc(irq)); | ||
362 | gpio_irqchip_unbanked.name = "GPIO-AINTC"; | ||
363 | gpio_irqchip_unbanked.set_type = gpio_irq_type_unbanked; | ||
364 | |||
365 | /* default trigger: both edges */ | ||
366 | g = gpio2controller(0); | ||
367 | __raw_writel(~0, &g->set_falling); | ||
368 | __raw_writel(~0, &g->set_rising); | ||
369 | |||
370 | /* set the direct IRQs up to use that irqchip */ | ||
371 | for (gpio = 0; gpio < soc_info->gpio_unbanked; gpio++, irq++) { | ||
372 | set_irq_chip(irq, &gpio_irqchip_unbanked); | ||
373 | set_irq_data(irq, (void *) __gpio_mask(gpio)); | ||
374 | set_irq_chip_data(irq, g); | ||
375 | irq_desc[irq].status |= IRQ_TYPE_EDGE_BOTH; | ||
376 | } | ||
377 | |||
378 | goto done; | ||
379 | } | ||
380 | |||
381 | /* | ||
382 | * Or, AINTC can handle IRQs for banks of 16 GPIO IRQs, which we | ||
383 | * then chain through our own handler. | ||
384 | */ | ||
295 | for (gpio = 0, irq = gpio_to_irq(0), bank = 0; | 385 | for (gpio = 0, irq = gpio_to_irq(0), bank = 0; |
296 | gpio < ngpio; | 386 | gpio < ngpio; |
297 | bank++, bank_irq++) { | 387 | bank++, bank_irq++) { |
298 | struct gpio_controller *__iomem g = gpio2controller(gpio); | ||
299 | unsigned i; | 388 | unsigned i; |
300 | 389 | ||
390 | /* disabled by default, enabled only as needed */ | ||
391 | g = gpio2controller(gpio); | ||
301 | __raw_writel(~0, &g->clr_falling); | 392 | __raw_writel(~0, &g->clr_falling); |
302 | __raw_writel(~0, &g->clr_rising); | 393 | __raw_writel(~0, &g->clr_rising); |
303 | 394 | ||
@@ -309,6 +400,7 @@ static int __init davinci_gpio_irq_setup(void) | |||
309 | for (i = 0; i < 16 && gpio < ngpio; i++, irq++, gpio++) { | 400 | for (i = 0; i < 16 && gpio < ngpio; i++, irq++, gpio++) { |
310 | set_irq_chip(irq, &gpio_irqchip); | 401 | set_irq_chip(irq, &gpio_irqchip); |
311 | set_irq_chip_data(irq, g); | 402 | set_irq_chip_data(irq, g); |
403 | set_irq_data(irq, (void *) __gpio_mask(gpio)); | ||
312 | set_irq_handler(irq, handle_simple_irq); | 404 | set_irq_handler(irq, handle_simple_irq); |
313 | set_irq_flags(irq, IRQF_VALID); | 405 | set_irq_flags(irq, IRQF_VALID); |
314 | } | 406 | } |
@@ -316,6 +408,7 @@ static int __init davinci_gpio_irq_setup(void) | |||
316 | binten |= BIT(bank); | 408 | binten |= BIT(bank); |
317 | } | 409 | } |
318 | 410 | ||
411 | done: | ||
319 | /* BINTEN -- per-bank interrupt enable. genirq would also let these | 412 | /* BINTEN -- per-bank interrupt enable. genirq would also let these |
320 | * bits be set/cleared dynamically. | 413 | * bits be set/cleared dynamically. |
321 | */ | 414 | */ |