diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2011-04-14 13:17:57 -0400 |
---|---|---|
committer | Nicolas Pitre <nico@fluxnic.net> | 2011-05-16 14:34:54 -0400 |
commit | e59347a1d15c0b1d9fdc510520f8fa78d7d19a5b (patch) | |
tree | 64930470ac9dbf427ab5b7ec6d2d290fbb61f373 /arch | |
parent | cfefd21e693dca791bf9ecfc9dd3794facad533c (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.c | 112 | ||||
-rw-r--r-- | arch/arm/plat-orion/include/plat/gpio.h | 1 | ||||
-rw-r--r-- | arch/arm/plat-orion/irq.c | 49 |
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 | ****************************************************************************/ |
324 | static 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 | |||
336 | static 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 | |||
353 | static 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 | ||
370 | static int gpio_irq_set_type(struct irq_data *d, u32 type) | 325 | static 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 | ||
428 | struct 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 | |||
436 | void __init orion_gpio_init(int gpio_base, int ngpio, | 381 | void __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 | ||
485 | void orion_gpio_irq_handler(int pinoff) | 445 | void 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 | */ |
42 | extern struct irq_chip orion_gpio_irq_chip; | ||
43 | void orion_gpio_irq_handler(int irqoff); | 42 | void 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 | ||
17 | static 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 | |||
27 | static 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 | |||
37 | static 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 | |||
44 | void __init orion_irq_init(unsigned int irq_start, void __iomem *maskaddr) | 17 | void __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 | } |