aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2011-04-14 13:17:57 -0400
committerNicolas Pitre <nico@fluxnic.net>2011-05-16 14:34:54 -0400
commite59347a1d15c0b1d9fdc510520f8fa78d7d19a5b (patch)
tree64930470ac9dbf427ab5b7ec6d2d290fbb61f373 /arch
parentcfefd21e693dca791bf9ecfc9dd3794facad533c (diff)
arm: orion: Use generic irq chip
The core interrupt chip is a straight forward conversion. The gpio chip is implemented with two instances of the irq_chip_type which can be switched with the irq_set_type function. That allows us to use the generic callbacks and avoids the conditionals in them. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Nicolas Pitre <nico@fluxnic.net>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/plat-orion/gpio.c112
-rw-r--r--arch/arm/plat-orion/include/plat/gpio.h1
-rw-r--r--arch/arm/plat-orion/irq.c49
3 files changed, 45 insertions, 117 deletions
diff --git a/arch/arm/plat-orion/gpio.c b/arch/arm/plat-orion/gpio.c
index a431a138f402..5b4fffab1eb4 100644
--- a/arch/arm/plat-orion/gpio.c
+++ b/arch/arm/plat-orion/gpio.c
@@ -321,59 +321,16 @@ EXPORT_SYMBOL(orion_gpio_set_blink);
321 * polarity LEVEL mask 321 * polarity LEVEL mask
322 * 322 *
323 ****************************************************************************/ 323 ****************************************************************************/
324static void gpio_irq_ack(struct irq_data *d)
325{
326 struct orion_gpio_chip *ochip = irq_data_get_irq_chip_data(d);
327 int type = irqd_get_trigger_type(d);
328
329 if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) {
330 int pin = d->irq - ochip->secondary_irq_base;
331
332 writel(~(1 << pin), GPIO_EDGE_CAUSE(ochip));
333 }
334}
335
336static void gpio_irq_mask(struct irq_data *d)
337{
338 struct orion_gpio_chip *ochip = irq_data_get_irq_chip_data(d);
339 int type = irqd_get_trigger_type(d);
340 void __iomem *reg;
341 int pin;
342
343 if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))
344 reg = GPIO_EDGE_MASK(ochip);
345 else
346 reg = GPIO_LEVEL_MASK(ochip);
347
348 pin = d->irq - ochip->secondary_irq_base;
349
350 writel(readl(reg) & ~(1 << pin), reg);
351}
352
353static void gpio_irq_unmask(struct irq_data *d)
354{
355 struct orion_gpio_chip *ochip = irq_data_get_irq_chip_data(d);
356 int type = irqd_get_trigger_type(d);
357 void __iomem *reg;
358 int pin;
359
360 if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))
361 reg = GPIO_EDGE_MASK(ochip);
362 else
363 reg = GPIO_LEVEL_MASK(ochip);
364
365 pin = d->irq - ochip->secondary_irq_base;
366
367 writel(readl(reg) | (1 << pin), reg);
368}
369 324
370static int gpio_irq_set_type(struct irq_data *d, u32 type) 325static int gpio_irq_set_type(struct irq_data *d, u32 type)
371{ 326{
372 struct orion_gpio_chip *ochip = irq_data_get_irq_chip_data(d); 327 struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
328 struct irq_chip_type *ct = irq_data_get_chip_type(d);
329 struct orion_gpio_chip *ochip = gc->private;
373 int pin; 330 int pin;
374 u32 u; 331 u32 u;
375 332
376 pin = d->irq - ochip->secondary_irq_base; 333 pin = d->irq - gc->irq_base;
377 334
378 u = readl(GPIO_IO_CONF(ochip)) & (1 << pin); 335 u = readl(GPIO_IO_CONF(ochip)) & (1 << pin);
379 if (!u) { 336 if (!u) {
@@ -382,18 +339,14 @@ static int gpio_irq_set_type(struct irq_data *d, u32 type)
382 return -EINVAL; 339 return -EINVAL;
383 } 340 }
384 341
385 /* 342 type &= IRQ_TYPE_SENSE_MASK;
386 * Set edge/level type. 343 if (type == IRQ_TYPE_NONE)
387 */
388 if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) {
389 __irq_set_handler_locked(d->irq, handle_edge_irq);
390 } else if (type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
391 __irq_set_handler_locked(d->irq, handle_level_irq);
392 } else {
393 printk(KERN_ERR "failed to set irq=%d (type=%d)\n",
394 d->irq, type);
395 return -EINVAL; 344 return -EINVAL;
396 } 345
346 /* Check if we need to change chip and handler */
347 if (!(ct->type & type))
348 if (irq_setup_alt_chip(d, type))
349 return -EINVAL;
397 350
398 /* 351 /*
399 * Configure interrupt polarity. 352 * Configure interrupt polarity.
@@ -425,19 +378,12 @@ static int gpio_irq_set_type(struct irq_data *d, u32 type)
425 return 0; 378 return 0;
426} 379}
427 380
428struct irq_chip orion_gpio_irq_chip = {
429 .name = "orion_gpio_irq",
430 .irq_ack = gpio_irq_ack,
431 .irq_mask = gpio_irq_mask,
432 .irq_unmask = gpio_irq_unmask,
433 .irq_set_type = gpio_irq_set_type,
434};
435
436void __init orion_gpio_init(int gpio_base, int ngpio, 381void __init orion_gpio_init(int gpio_base, int ngpio,
437 u32 base, int mask_offset, int secondary_irq_base) 382 u32 base, int mask_offset, int secondary_irq_base)
438{ 383{
439 struct orion_gpio_chip *ochip; 384 struct orion_gpio_chip *ochip;
440 int i; 385 struct irq_chip_generic *gc;
386 struct irq_chip_type *ct;
441 387
442 if (orion_gpio_chip_count == ARRAY_SIZE(orion_gpio_chips)) 388 if (orion_gpio_chip_count == ARRAY_SIZE(orion_gpio_chips))
443 return; 389 return;
@@ -471,15 +417,29 @@ void __init orion_gpio_init(int gpio_base, int ngpio,
471 writel(0, GPIO_EDGE_MASK(ochip)); 417 writel(0, GPIO_EDGE_MASK(ochip));
472 writel(0, GPIO_LEVEL_MASK(ochip)); 418 writel(0, GPIO_LEVEL_MASK(ochip));
473 419
474 for (i = 0; i < ngpio; i++) { 420 gc = irq_alloc_generic_chip("orion_gpio_irq", 2, secondary_irq_base,
475 unsigned int irq = secondary_irq_base + i; 421 ochip->base, handle_level_irq);
476 422 gc->private = ochip;
477 irq_set_chip_and_handler(irq, &orion_gpio_irq_chip, 423
478 handle_level_irq); 424 ct = gc->chip_types;
479 irq_set_chip_data(irq, ochip); 425 ct->regs.mask = ochip->mask_offset + GPIO_LEVEL_MASK_OFF;
480 irq_set_status_flags(irq, IRQ_LEVEL); 426 ct->type = IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW;
481 set_irq_flags(irq, IRQF_VALID); 427 ct->chip.irq_mask = irq_gc_mask_clr_bit;
482 } 428 ct->chip.irq_unmask = irq_gc_mask_set_bit;
429 ct->chip.irq_set_type = gpio_irq_set_type;
430
431 ct++;
432 ct->regs.mask = ochip->mask_offset + GPIO_EDGE_MASK_OFF;
433 ct->regs.ack = GPIO_EDGE_CAUSE_OFF;
434 ct->type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
435 ct->chip.irq_ack = irq_gc_ack;
436 ct->chip.irq_mask = irq_gc_mask_clr_bit;
437 ct->chip.irq_unmask = irq_gc_mask_set_bit;
438 ct->chip.irq_set_type = gpio_irq_set_type;
439 ct->handler = handle_edge_irq;
440
441 irq_setup_generic_chip(gc, IRQ_MSK(ngpio), IRQ_GC_INIT_MASK_CACHE,
442 IRQ_NOREQUEST, IRQ_LEVEL | IRQ_NOPROBE);
483} 443}
484 444
485void orion_gpio_irq_handler(int pinoff) 445void orion_gpio_irq_handler(int pinoff)
diff --git a/arch/arm/plat-orion/include/plat/gpio.h b/arch/arm/plat-orion/include/plat/gpio.h
index 5578b9803fc6..3075b9fdde83 100644
--- a/arch/arm/plat-orion/include/plat/gpio.h
+++ b/arch/arm/plat-orion/include/plat/gpio.h
@@ -39,7 +39,6 @@ void __init orion_gpio_init(int gpio_base, int ngpio,
39/* 39/*
40 * GPIO interrupt handling. 40 * GPIO interrupt handling.
41 */ 41 */
42extern struct irq_chip orion_gpio_irq_chip;
43void orion_gpio_irq_handler(int irqoff); 42void orion_gpio_irq_handler(int irqoff);
44 43
45 44
diff --git a/arch/arm/plat-orion/irq.c b/arch/arm/plat-orion/irq.c
index d8d638e09f8f..2d5b9c1ef389 100644
--- a/arch/arm/plat-orion/irq.c
+++ b/arch/arm/plat-orion/irq.c
@@ -14,52 +14,21 @@
14#include <linux/io.h> 14#include <linux/io.h>
15#include <plat/irq.h> 15#include <plat/irq.h>
16 16
17static void orion_irq_mask(struct irq_data *d)
18{
19 void __iomem *maskaddr = irq_data_get_irq_chip_data(d);
20 u32 mask;
21
22 mask = readl(maskaddr);
23 mask &= ~(1 << (d->irq & 31));
24 writel(mask, maskaddr);
25}
26
27static void orion_irq_unmask(struct irq_data *d)
28{
29 void __iomem *maskaddr = irq_data_get_irq_chip_data(d);
30 u32 mask;
31
32 mask = readl(maskaddr);
33 mask |= 1 << (d->irq & 31);
34 writel(mask, maskaddr);
35}
36
37static struct irq_chip orion_irq_chip = {
38 .name = "orion_irq",
39 .irq_mask = orion_irq_mask,
40 .irq_mask_ack = orion_irq_mask,
41 .irq_unmask = orion_irq_unmask,
42};
43
44void __init orion_irq_init(unsigned int irq_start, void __iomem *maskaddr) 17void __init orion_irq_init(unsigned int irq_start, void __iomem *maskaddr)
45{ 18{
46 unsigned int i; 19 struct irq_chip_generic *gc;
20 struct irq_chip_type *ct;
47 21
48 /* 22 /*
49 * Mask all interrupts initially. 23 * Mask all interrupts initially.
50 */ 24 */
51 writel(0, maskaddr); 25 writel(0, maskaddr);
52 26
53 /* 27 gc = irq_alloc_generic_chip("orion_irq", 1, irq_start, maskaddr,
54 * Register IRQ sources. 28 handle_level_irq);
55 */ 29 ct = gc->chip_types;
56 for (i = 0; i < 32; i++) { 30 ct->chip.irq_mask = irq_gc_mask_clr_bit;
57 unsigned int irq = irq_start + i; 31 ct->chip.irq_unmask = irq_gc_mask_set_bit;
58 32 irq_setup_generic_chip(gc, IRQ_MSK(32), IRQ_GC_INIT_MASK_CACHE,
59 irq_set_chip_and_handler(irq, &orion_irq_chip, 33 IRQ_NOREQUEST, IRQ_LEVEL | IRQ_NOPROBE);
60 handle_level_irq);
61 irq_set_chip_data(irq, maskaddr);
62 irq_set_status_flags(irq, IRQ_LEVEL);
63 set_irq_flags(irq, IRQF_VALID);
64 }
65} 34}