aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/Kconfig1
-rw-r--r--arch/arm/boot/dts/kirkwood.dtsi27
-rw-r--r--arch/arm/mach-dove/irq.c58
-rw-r--r--arch/arm/mach-kirkwood/board-dt.c3
-rw-r--r--arch/arm/mach-kirkwood/irq.c38
-rw-r--r--arch/arm/mach-mv78xx0/irq.c22
-rw-r--r--arch/arm/mach-orion5x/irq.c22
-rw-r--r--arch/arm/plat-orion/gpio.c166
-rw-r--r--arch/arm/plat-orion/include/plat/gpio.h16
-rw-r--r--arch/arm/plat-orion/include/plat/irq.h3
-rw-r--r--arch/arm/plat-orion/irq.c40
11 files changed, 264 insertions, 132 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index a91009c61870..39bb94112a30 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1105,6 +1105,7 @@ config PLAT_ORION
1105 bool 1105 bool
1106 select CLKSRC_MMIO 1106 select CLKSRC_MMIO
1107 select GENERIC_IRQ_CHIP 1107 select GENERIC_IRQ_CHIP
1108 select IRQ_DOMAIN
1108 select COMMON_CLK 1109 select COMMON_CLK
1109 1110
1110config PLAT_PXA 1111config PLAT_PXA
diff --git a/arch/arm/boot/dts/kirkwood.dtsi b/arch/arm/boot/dts/kirkwood.dtsi
index f95dbc190ab6..cbaa7b6eb5da 100644
--- a/arch/arm/boot/dts/kirkwood.dtsi
+++ b/arch/arm/boot/dts/kirkwood.dtsi
@@ -2,6 +2,15 @@
2 2
3/ { 3/ {
4 compatible = "marvell,kirkwood"; 4 compatible = "marvell,kirkwood";
5 interrupt-parent = <&intc>;
6
7 intc: interrupt-controller {
8 compatible = "marvell,orion-intc", "marvell,intc";
9 interrupt-controller;
10 #interrupt-cells = <1>;
11 reg = <0xf1020204 0x04>,
12 <0xf1020214 0x04>;
13 };
5 14
6 ocp@f1000000 { 15 ocp@f1000000 {
7 compatible = "simple-bus"; 16 compatible = "simple-bus";
@@ -9,6 +18,24 @@
9 #address-cells = <1>; 18 #address-cells = <1>;
10 #size-cells = <1>; 19 #size-cells = <1>;
11 20
21 gpio0: gpio@10100 {
22 compatible = "marvell,orion-gpio";
23 #gpio-cells = <2>;
24 gpio-controller;
25 reg = <0x10100 0x40>;
26 ngpio = <32>;
27 interrupts = <35>, <36>, <37>, <38>;
28 };
29
30 gpio1: gpio@10140 {
31 compatible = "marvell,orion-gpio";
32 #gpio-cells = <2>;
33 gpio-controller;
34 reg = <0x10140 0x40>;
35 ngpio = <18>;
36 interrupts = <39>, <40>, <41>;
37 };
38
12 serial@12000 { 39 serial@12000 {
13 compatible = "ns16550a"; 40 compatible = "ns16550a";
14 reg = <0x12000 0x100>; 41 reg = <0x12000 0x100>;
diff --git a/arch/arm/mach-dove/irq.c b/arch/arm/mach-dove/irq.c
index f07fd16e0c9b..9bc97a5baaa8 100644
--- a/arch/arm/mach-dove/irq.c
+++ b/arch/arm/mach-dove/irq.c
@@ -20,22 +20,6 @@
20#include <mach/bridge-regs.h> 20#include <mach/bridge-regs.h>
21#include "common.h" 21#include "common.h"
22 22
23static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
24{
25 int irqoff;
26 BUG_ON(irq < IRQ_DOVE_GPIO_0_7 || irq > IRQ_DOVE_HIGH_GPIO);
27
28 irqoff = irq <= IRQ_DOVE_GPIO_16_23 ? irq - IRQ_DOVE_GPIO_0_7 :
29 3 + irq - IRQ_DOVE_GPIO_24_31;
30
31 orion_gpio_irq_handler(irqoff << 3);
32 if (irq == IRQ_DOVE_HIGH_GPIO) {
33 orion_gpio_irq_handler(40);
34 orion_gpio_irq_handler(48);
35 orion_gpio_irq_handler(56);
36 }
37}
38
39static void pmu_irq_mask(struct irq_data *d) 23static void pmu_irq_mask(struct irq_data *d)
40{ 24{
41 int pin = irq_to_pmu(d->irq); 25 int pin = irq_to_pmu(d->irq);
@@ -90,6 +74,27 @@ static void pmu_irq_handler(unsigned int irq, struct irq_desc *desc)
90 } 74 }
91} 75}
92 76
77static int __initdata gpio0_irqs[4] = {
78 IRQ_DOVE_GPIO_0_7,
79 IRQ_DOVE_GPIO_8_15,
80 IRQ_DOVE_GPIO_16_23,
81 IRQ_DOVE_GPIO_24_31,
82};
83
84static int __initdata gpio1_irqs[4] = {
85 IRQ_DOVE_HIGH_GPIO,
86 0,
87 0,
88 0,
89};
90
91static int __initdata gpio2_irqs[4] = {
92 0,
93 0,
94 0,
95 0,
96};
97
93void __init dove_init_irq(void) 98void __init dove_init_irq(void)
94{ 99{
95 int i; 100 int i;
@@ -100,19 +105,14 @@ void __init dove_init_irq(void)
100 /* 105 /*
101 * Initialize gpiolib for GPIOs 0-71. 106 * Initialize gpiolib for GPIOs 0-71.
102 */ 107 */
103 orion_gpio_init(0, 32, DOVE_GPIO_LO_VIRT_BASE, 0, 108 orion_gpio_init(NULL, 0, 32, (void __iomem *)DOVE_GPIO_LO_VIRT_BASE, 0,
104 IRQ_DOVE_GPIO_START); 109 IRQ_DOVE_GPIO_START, gpio0_irqs);
105 irq_set_chained_handler(IRQ_DOVE_GPIO_0_7, gpio_irq_handler); 110
106 irq_set_chained_handler(IRQ_DOVE_GPIO_8_15, gpio_irq_handler); 111 orion_gpio_init(NULL, 32, 32, (void __iomem *)DOVE_GPIO_HI_VIRT_BASE, 0,
107 irq_set_chained_handler(IRQ_DOVE_GPIO_16_23, gpio_irq_handler); 112 IRQ_DOVE_GPIO_START + 32, gpio1_irqs);
108 irq_set_chained_handler(IRQ_DOVE_GPIO_24_31, gpio_irq_handler); 113
109 114 orion_gpio_init(NULL, 64, 8, (void __iomem *)DOVE_GPIO2_VIRT_BASE, 0,
110 orion_gpio_init(32, 32, DOVE_GPIO_HI_VIRT_BASE, 0, 115 IRQ_DOVE_GPIO_START + 64, gpio2_irqs);
111 IRQ_DOVE_GPIO_START + 32);
112 irq_set_chained_handler(IRQ_DOVE_HIGH_GPIO, gpio_irq_handler);
113
114 orion_gpio_init(64, 8, DOVE_GPIO2_VIRT_BASE, 0,
115 IRQ_DOVE_GPIO_START + 64);
116 116
117 /* 117 /*
118 * Mask and clear PMU interrupts 118 * Mask and clear PMU interrupts
diff --git a/arch/arm/mach-kirkwood/board-dt.c b/arch/arm/mach-kirkwood/board-dt.c
index edc3f8a9d45e..27ac3d84016b 100644
--- a/arch/arm/mach-kirkwood/board-dt.c
+++ b/arch/arm/mach-kirkwood/board-dt.c
@@ -18,6 +18,7 @@
18#include <asm/mach/arch.h> 18#include <asm/mach/arch.h>
19#include <asm/mach/map.h> 19#include <asm/mach/map.h>
20#include <mach/bridge-regs.h> 20#include <mach/bridge-regs.h>
21#include <plat/irq.h>
21#include "common.h" 22#include "common.h"
22 23
23static struct of_device_id kirkwood_dt_match_table[] __initdata = { 24static struct of_device_id kirkwood_dt_match_table[] __initdata = {
@@ -84,7 +85,7 @@ DT_MACHINE_START(KIRKWOOD_DT, "Marvell Kirkwood (Flattened Device Tree)")
84 /* Maintainer: Jason Cooper <jason@lakedaemon.net> */ 85 /* Maintainer: Jason Cooper <jason@lakedaemon.net> */
85 .map_io = kirkwood_map_io, 86 .map_io = kirkwood_map_io,
86 .init_early = kirkwood_init_early, 87 .init_early = kirkwood_init_early,
87 .init_irq = kirkwood_init_irq, 88 .init_irq = orion_dt_init_irq,
88 .timer = &kirkwood_timer, 89 .timer = &kirkwood_timer,
89 .init_machine = kirkwood_dt_init, 90 .init_machine = kirkwood_dt_init,
90 .restart = kirkwood_restart, 91 .restart = kirkwood_restart,
diff --git a/arch/arm/mach-kirkwood/irq.c b/arch/arm/mach-kirkwood/irq.c
index c4c68e5b94f1..720063ffa19d 100644
--- a/arch/arm/mach-kirkwood/irq.c
+++ b/arch/arm/mach-kirkwood/irq.c
@@ -9,20 +9,23 @@
9 */ 9 */
10#include <linux/gpio.h> 10#include <linux/gpio.h>
11#include <linux/kernel.h> 11#include <linux/kernel.h>
12#include <linux/init.h>
13#include <linux/irq.h> 12#include <linux/irq.h>
14#include <linux/io.h>
15#include <mach/bridge-regs.h> 13#include <mach/bridge-regs.h>
16#include <plat/irq.h> 14#include <plat/irq.h>
17#include "common.h"
18 15
19static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc) 16static int __initdata gpio0_irqs[4] = {
20{ 17 IRQ_KIRKWOOD_GPIO_LOW_0_7,
21 BUG_ON(irq < IRQ_KIRKWOOD_GPIO_LOW_0_7); 18 IRQ_KIRKWOOD_GPIO_LOW_8_15,
22 BUG_ON(irq > IRQ_KIRKWOOD_GPIO_HIGH_16_23); 19 IRQ_KIRKWOOD_GPIO_LOW_16_23,
20 IRQ_KIRKWOOD_GPIO_LOW_24_31,
21};
23 22
24 orion_gpio_irq_handler((irq - IRQ_KIRKWOOD_GPIO_LOW_0_7) << 3); 23static int __initdata gpio1_irqs[4] = {
25} 24 IRQ_KIRKWOOD_GPIO_HIGH_0_7,
25 IRQ_KIRKWOOD_GPIO_HIGH_8_15,
26 IRQ_KIRKWOOD_GPIO_HIGH_16_23,
27 0,
28};
26 29
27void __init kirkwood_init_irq(void) 30void __init kirkwood_init_irq(void)
28{ 31{
@@ -32,17 +35,8 @@ void __init kirkwood_init_irq(void)
32 /* 35 /*
33 * Initialize gpiolib for GPIOs 0-49. 36 * Initialize gpiolib for GPIOs 0-49.
34 */ 37 */
35 orion_gpio_init(0, 32, GPIO_LOW_VIRT_BASE, 0, 38 orion_gpio_init(NULL, 0, 32, (void __iomem *)GPIO_LOW_VIRT_BASE, 0,
36 IRQ_KIRKWOOD_GPIO_START); 39 IRQ_KIRKWOOD_GPIO_START, gpio0_irqs);
37 irq_set_chained_handler(IRQ_KIRKWOOD_GPIO_LOW_0_7, gpio_irq_handler); 40 orion_gpio_init(NULL, 32, 18, (void __iomem *)GPIO_HIGH_VIRT_BASE, 0,
38 irq_set_chained_handler(IRQ_KIRKWOOD_GPIO_LOW_8_15, gpio_irq_handler); 41 IRQ_KIRKWOOD_GPIO_START + 32, gpio1_irqs);
39 irq_set_chained_handler(IRQ_KIRKWOOD_GPIO_LOW_16_23, gpio_irq_handler);
40 irq_set_chained_handler(IRQ_KIRKWOOD_GPIO_LOW_24_31, gpio_irq_handler);
41
42 orion_gpio_init(32, 18, GPIO_HIGH_VIRT_BASE, 0,
43 IRQ_KIRKWOOD_GPIO_START + 32);
44 irq_set_chained_handler(IRQ_KIRKWOOD_GPIO_HIGH_0_7, gpio_irq_handler);
45 irq_set_chained_handler(IRQ_KIRKWOOD_GPIO_HIGH_8_15, gpio_irq_handler);
46 irq_set_chained_handler(IRQ_KIRKWOOD_GPIO_HIGH_16_23,
47 gpio_irq_handler);
48} 42}
diff --git a/arch/arm/mach-mv78xx0/irq.c b/arch/arm/mach-mv78xx0/irq.c
index e421b701663b..eff9a750bbe2 100644
--- a/arch/arm/mach-mv78xx0/irq.c
+++ b/arch/arm/mach-mv78xx0/irq.c
@@ -9,19 +9,17 @@
9 */ 9 */
10#include <linux/gpio.h> 10#include <linux/gpio.h>
11#include <linux/kernel.h> 11#include <linux/kernel.h>
12#include <linux/init.h>
13#include <linux/pci.h>
14#include <linux/irq.h> 12#include <linux/irq.h>
15#include <mach/bridge-regs.h> 13#include <mach/bridge-regs.h>
16#include <plat/irq.h> 14#include <plat/irq.h>
17#include "common.h" 15#include "common.h"
18 16
19static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc) 17static int __initdata gpio0_irqs[4] = {
20{ 18 IRQ_MV78XX0_GPIO_0_7,
21 BUG_ON(irq < IRQ_MV78XX0_GPIO_0_7 || irq > IRQ_MV78XX0_GPIO_24_31); 19 IRQ_MV78XX0_GPIO_8_15,
22 20 IRQ_MV78XX0_GPIO_16_23,
23 orion_gpio_irq_handler((irq - IRQ_MV78XX0_GPIO_0_7) << 3); 21 IRQ_MV78XX0_GPIO_24_31,
24} 22};
25 23
26void __init mv78xx0_init_irq(void) 24void __init mv78xx0_init_irq(void)
27{ 25{
@@ -34,11 +32,7 @@ void __init mv78xx0_init_irq(void)
34 * registers for core #1 are at an offset of 0x18 from those of 32 * registers for core #1 are at an offset of 0x18 from those of
35 * core #0.) 33 * core #0.)
36 */ 34 */
37 orion_gpio_init(0, 32, GPIO_VIRT_BASE, 35 orion_gpio_init(NULL, 0, 32, (void __iomem *)GPIO_VIRT_BASE,
38 mv78xx0_core_index() ? 0x18 : 0, 36 mv78xx0_core_index() ? 0x18 : 0,
39 IRQ_MV78XX0_GPIO_START); 37 IRQ_MV78XX0_GPIO_START, gpio0_irqs);
40 irq_set_chained_handler(IRQ_MV78XX0_GPIO_0_7, gpio_irq_handler);
41 irq_set_chained_handler(IRQ_MV78XX0_GPIO_8_15, gpio_irq_handler);
42 irq_set_chained_handler(IRQ_MV78XX0_GPIO_16_23, gpio_irq_handler);
43 irq_set_chained_handler(IRQ_MV78XX0_GPIO_24_31, gpio_irq_handler);
44} 38}
diff --git a/arch/arm/mach-orion5x/irq.c b/arch/arm/mach-orion5x/irq.c
index b1b45fff776e..17da7091d310 100644
--- a/arch/arm/mach-orion5x/irq.c
+++ b/arch/arm/mach-orion5x/irq.c
@@ -11,19 +11,16 @@
11 */ 11 */
12#include <linux/gpio.h> 12#include <linux/gpio.h>
13#include <linux/kernel.h> 13#include <linux/kernel.h>
14#include <linux/init.h>
15#include <linux/irq.h> 14#include <linux/irq.h>
16#include <linux/io.h>
17#include <mach/bridge-regs.h> 15#include <mach/bridge-regs.h>
18#include <plat/irq.h> 16#include <plat/irq.h>
19#include "common.h"
20 17
21static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc) 18static int __initdata gpio0_irqs[4] = {
22{ 19 IRQ_ORION5X_GPIO_0_7,
23 BUG_ON(irq < IRQ_ORION5X_GPIO_0_7 || irq > IRQ_ORION5X_GPIO_24_31); 20 IRQ_ORION5X_GPIO_8_15,
24 21 IRQ_ORION5X_GPIO_16_23,
25 orion_gpio_irq_handler((irq - IRQ_ORION5X_GPIO_0_7) << 3); 22 IRQ_ORION5X_GPIO_24_31,
26} 23};
27 24
28void __init orion5x_init_irq(void) 25void __init orion5x_init_irq(void)
29{ 26{
@@ -32,9 +29,6 @@ void __init orion5x_init_irq(void)
32 /* 29 /*
33 * Initialize gpiolib for GPIOs 0-31. 30 * Initialize gpiolib for GPIOs 0-31.
34 */ 31 */
35 orion_gpio_init(0, 32, GPIO_VIRT_BASE, 0, IRQ_ORION5X_GPIO_START); 32 orion_gpio_init(NULL, 0, 32, (void __iomem *)GPIO_VIRT_BASE, 0,
36 irq_set_chained_handler(IRQ_ORION5X_GPIO_0_7, gpio_irq_handler); 33 IRQ_ORION5X_GPIO_START, gpio0_irqs);
37 irq_set_chained_handler(IRQ_ORION5X_GPIO_8_15, gpio_irq_handler);
38 irq_set_chained_handler(IRQ_ORION5X_GPIO_16_23, gpio_irq_handler);
39 irq_set_chained_handler(IRQ_ORION5X_GPIO_24_31, gpio_irq_handler);
40} 34}
diff --git a/arch/arm/plat-orion/gpio.c b/arch/arm/plat-orion/gpio.c
index af95af257301..dfda74fae6f2 100644
--- a/arch/arm/plat-orion/gpio.c
+++ b/arch/arm/plat-orion/gpio.c
@@ -8,15 +8,22 @@
8 * warranty of any kind, whether express or implied. 8 * warranty of any kind, whether express or implied.
9 */ 9 */
10 10
11#define DEBUG
12
11#include <linux/kernel.h> 13#include <linux/kernel.h>
12#include <linux/init.h> 14#include <linux/init.h>
13#include <linux/irq.h> 15#include <linux/irq.h>
16#include <linux/irqdomain.h>
14#include <linux/module.h> 17#include <linux/module.h>
15#include <linux/spinlock.h> 18#include <linux/spinlock.h>
16#include <linux/bitops.h> 19#include <linux/bitops.h>
17#include <linux/io.h> 20#include <linux/io.h>
18#include <linux/gpio.h> 21#include <linux/gpio.h>
19#include <linux/leds.h> 22#include <linux/leds.h>
23#include <linux/of.h>
24#include <linux/of_irq.h>
25#include <linux/of_address.h>
26#include <plat/gpio.h>
20 27
21/* 28/*
22 * GPIO unit register offsets. 29 * GPIO unit register offsets.
@@ -38,6 +45,7 @@ struct orion_gpio_chip {
38 unsigned long valid_output; 45 unsigned long valid_output;
39 int mask_offset; 46 int mask_offset;
40 int secondary_irq_base; 47 int secondary_irq_base;
48 struct irq_domain *domain;
41}; 49};
42 50
43static void __iomem *GPIO_OUT(struct orion_gpio_chip *ochip) 51static void __iomem *GPIO_OUT(struct orion_gpio_chip *ochip)
@@ -222,10 +230,10 @@ static int orion_gpio_to_irq(struct gpio_chip *chip, unsigned pin)
222 struct orion_gpio_chip *ochip = 230 struct orion_gpio_chip *ochip =
223 container_of(chip, struct orion_gpio_chip, chip); 231 container_of(chip, struct orion_gpio_chip, chip);
224 232
225 return ochip->secondary_irq_base + pin; 233 return irq_create_mapping(ochip->domain,
234 ochip->secondary_irq_base + pin);
226} 235}
227 236
228
229/* 237/*
230 * Orion-specific GPIO API extensions. 238 * Orion-specific GPIO API extensions.
231 */ 239 */
@@ -353,12 +361,10 @@ static int gpio_irq_set_type(struct irq_data *d, u32 type)
353 int pin; 361 int pin;
354 u32 u; 362 u32 u;
355 363
356 pin = d->irq - gc->irq_base; 364 pin = d->hwirq - ochip->secondary_irq_base;
357 365
358 u = readl(GPIO_IO_CONF(ochip)) & (1 << pin); 366 u = readl(GPIO_IO_CONF(ochip)) & (1 << pin);
359 if (!u) { 367 if (!u) {
360 printk(KERN_ERR "orion gpio_irq_set_type failed "
361 "(irq %d, pin %d).\n", d->irq, pin);
362 return -EINVAL; 368 return -EINVAL;
363 } 369 }
364 370
@@ -397,17 +403,53 @@ static int gpio_irq_set_type(struct irq_data *d, u32 type)
397 u &= ~(1 << pin); /* rising */ 403 u &= ~(1 << pin); /* rising */
398 writel(u, GPIO_IN_POL(ochip)); 404 writel(u, GPIO_IN_POL(ochip));
399 } 405 }
400
401 return 0; 406 return 0;
402} 407}
403 408
404void __init orion_gpio_init(int gpio_base, int ngpio, 409static void gpio_irq_handler(unsigned irq, struct irq_desc *desc)
405 u32 base, int mask_offset, int secondary_irq_base) 410{
411 struct orion_gpio_chip *ochip = irq_get_handler_data(irq);
412 u32 cause, type;
413 int i;
414
415 if (ochip == NULL)
416 return;
417
418 cause = readl(GPIO_DATA_IN(ochip)) & readl(GPIO_LEVEL_MASK(ochip));
419 cause |= readl(GPIO_EDGE_CAUSE(ochip)) & readl(GPIO_EDGE_MASK(ochip));
420
421 for (i = 0; i < ochip->chip.ngpio; i++) {
422 int irq;
423
424 irq = ochip->secondary_irq_base + i;
425
426 if (!(cause & (1 << i)))
427 continue;
428
429 type = irqd_get_trigger_type(irq_get_irq_data(irq));
430 if ((type & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) {
431 /* Swap polarity (race with GPIO line) */
432 u32 polarity;
433
434 polarity = readl(GPIO_IN_POL(ochip));
435 polarity ^= 1 << i;
436 writel(polarity, GPIO_IN_POL(ochip));
437 }
438 generic_handle_irq(irq);
439 }
440}
441
442void __init orion_gpio_init(struct device_node *np,
443 int gpio_base, int ngpio,
444 void __iomem *base, int mask_offset,
445 int secondary_irq_base,
446 int irqs[4])
406{ 447{
407 struct orion_gpio_chip *ochip; 448 struct orion_gpio_chip *ochip;
408 struct irq_chip_generic *gc; 449 struct irq_chip_generic *gc;
409 struct irq_chip_type *ct; 450 struct irq_chip_type *ct;
410 char gc_label[16]; 451 char gc_label[16];
452 int i;
411 453
412 if (orion_gpio_chip_count == ARRAY_SIZE(orion_gpio_chips)) 454 if (orion_gpio_chip_count == ARRAY_SIZE(orion_gpio_chips))
413 return; 455 return;
@@ -426,6 +468,10 @@ void __init orion_gpio_init(int gpio_base, int ngpio,
426 ochip->chip.base = gpio_base; 468 ochip->chip.base = gpio_base;
427 ochip->chip.ngpio = ngpio; 469 ochip->chip.ngpio = ngpio;
428 ochip->chip.can_sleep = 0; 470 ochip->chip.can_sleep = 0;
471#ifdef CONFIG_OF
472 ochip->chip.of_node = np;
473#endif
474
429 spin_lock_init(&ochip->lock); 475 spin_lock_init(&ochip->lock);
430 ochip->base = (void __iomem *)base; 476 ochip->base = (void __iomem *)base;
431 ochip->valid_input = 0; 477 ochip->valid_input = 0;
@@ -435,8 +481,6 @@ void __init orion_gpio_init(int gpio_base, int ngpio,
435 481
436 gpiochip_add(&ochip->chip); 482 gpiochip_add(&ochip->chip);
437 483
438 orion_gpio_chip_count++;
439
440 /* 484 /*
441 * Mask and clear GPIO interrupts. 485 * Mask and clear GPIO interrupts.
442 */ 486 */
@@ -444,16 +488,28 @@ void __init orion_gpio_init(int gpio_base, int ngpio,
444 writel(0, GPIO_EDGE_MASK(ochip)); 488 writel(0, GPIO_EDGE_MASK(ochip));
445 writel(0, GPIO_LEVEL_MASK(ochip)); 489 writel(0, GPIO_LEVEL_MASK(ochip));
446 490
447 gc = irq_alloc_generic_chip("orion_gpio_irq", 2, secondary_irq_base, 491 /* Setup the interrupt handlers. Each chip can have up to 4
492 * interrupt handlers, with each handler dealing with 8 GPIO
493 * pins. */
494
495 for (i = 0; i < 4; i++) {
496 if (irqs[i]) {
497 irq_set_handler_data(irqs[i], ochip);
498 irq_set_chained_handler(irqs[i], gpio_irq_handler);
499 }
500 }
501
502 gc = irq_alloc_generic_chip("orion_gpio_irq", 2,
503 secondary_irq_base,
448 ochip->base, handle_level_irq); 504 ochip->base, handle_level_irq);
449 gc->private = ochip; 505 gc->private = ochip;
450
451 ct = gc->chip_types; 506 ct = gc->chip_types;
452 ct->regs.mask = ochip->mask_offset + GPIO_LEVEL_MASK_OFF; 507 ct->regs.mask = ochip->mask_offset + GPIO_LEVEL_MASK_OFF;
453 ct->type = IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW; 508 ct->type = IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW;
454 ct->chip.irq_mask = irq_gc_mask_clr_bit; 509 ct->chip.irq_mask = irq_gc_mask_clr_bit;
455 ct->chip.irq_unmask = irq_gc_mask_set_bit; 510 ct->chip.irq_unmask = irq_gc_mask_set_bit;
456 ct->chip.irq_set_type = gpio_irq_set_type; 511 ct->chip.irq_set_type = gpio_irq_set_type;
512 ct->chip.name = ochip->chip.label;
457 513
458 ct++; 514 ct++;
459 ct->regs.mask = ochip->mask_offset + GPIO_EDGE_MASK_OFF; 515 ct->regs.mask = ochip->mask_offset + GPIO_EDGE_MASK_OFF;
@@ -464,41 +520,69 @@ void __init orion_gpio_init(int gpio_base, int ngpio,
464 ct->chip.irq_unmask = irq_gc_mask_set_bit; 520 ct->chip.irq_unmask = irq_gc_mask_set_bit;
465 ct->chip.irq_set_type = gpio_irq_set_type; 521 ct->chip.irq_set_type = gpio_irq_set_type;
466 ct->handler = handle_edge_irq; 522 ct->handler = handle_edge_irq;
523 ct->chip.name = ochip->chip.label;
467 524
468 irq_setup_generic_chip(gc, IRQ_MSK(ngpio), IRQ_GC_INIT_MASK_CACHE, 525 irq_setup_generic_chip(gc, IRQ_MSK(ngpio), IRQ_GC_INIT_MASK_CACHE,
469 IRQ_NOREQUEST, IRQ_LEVEL | IRQ_NOPROBE); 526 IRQ_NOREQUEST, IRQ_LEVEL | IRQ_NOPROBE);
470}
471 527
472void orion_gpio_irq_handler(int pinoff) 528 /* Setup irq domain on top of the generic chip. */
473{ 529 ochip->domain = irq_domain_add_legacy(np,
474 struct orion_gpio_chip *ochip; 530 ochip->chip.ngpio,
475 u32 cause, type; 531 ochip->secondary_irq_base,
476 int i; 532 ochip->secondary_irq_base,
477 533 &irq_domain_simple_ops,
478 ochip = orion_gpio_chip_find(pinoff); 534 ochip);
479 if (ochip == NULL) 535 if (!ochip->domain)
480 return; 536 panic("%s: couldn't allocate irq domain (DT).\n",
481 537 ochip->chip.label);
482 cause = readl(GPIO_DATA_IN(ochip)) & readl(GPIO_LEVEL_MASK(ochip));
483 cause |= readl(GPIO_EDGE_CAUSE(ochip)) & readl(GPIO_EDGE_MASK(ochip));
484
485 for (i = 0; i < ochip->chip.ngpio; i++) {
486 int irq;
487 538
488 irq = ochip->secondary_irq_base + i; 539 orion_gpio_chip_count++;
540}
489 541
490 if (!(cause & (1 << i))) 542#ifdef CONFIG_OF
491 continue; 543static void __init orion_gpio_of_init_one(struct device_node *np,
544 int irq_gpio_base)
545{
546 int ngpio, gpio_base, mask_offset;
547 void __iomem *base;
548 int ret, i;
549 int irqs[4];
550 int secondary_irq_base;
551
552 ret = of_property_read_u32(np, "ngpio", &ngpio);
553 if (ret)
554 goto out;
555 ret = of_property_read_u32(np, "mask-offset", &mask_offset);
556 if (ret == -EINVAL)
557 mask_offset = 0;
558 else
559 goto out;
560 base = of_iomap(np, 0);
561 if (!base)
562 goto out;
563
564 secondary_irq_base = irq_gpio_base + (32 * orion_gpio_chip_count);
565 gpio_base = 32 * orion_gpio_chip_count;
566
567 /* Get the interrupt numbers. Each chip can have up to 4
568 * interrupt handlers, with each handler dealing with 8 GPIO
569 * pins. */
570
571 for (i = 0; i < 4; i++)
572 irqs[i] = irq_of_parse_and_map(np, i);
573
574 orion_gpio_init(np, gpio_base, ngpio, base, mask_offset,
575 secondary_irq_base, irqs);
576 return;
577out:
578 pr_err("%s: %s: missing mandatory property\n", __func__, np->name);
579}
492 580
493 type = irqd_get_trigger_type(irq_get_irq_data(irq)); 581void __init orion_gpio_of_init(int irq_gpio_base)
494 if ((type & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) { 582{
495 /* Swap polarity (race with GPIO line) */ 583 struct device_node *np;
496 u32 polarity;
497 584
498 polarity = readl(GPIO_IN_POL(ochip)); 585 for_each_compatible_node(np, NULL, "marvell,orion-gpio")
499 polarity ^= 1 << i; 586 orion_gpio_of_init_one(np, irq_gpio_base);
500 writel(polarity, GPIO_IN_POL(ochip));
501 }
502 generic_handle_irq(irq);
503 }
504} 587}
588#endif
diff --git a/arch/arm/plat-orion/include/plat/gpio.h b/arch/arm/plat-orion/include/plat/gpio.h
index bec0c98ce41f..81c6fc8a7b28 100644
--- a/arch/arm/plat-orion/include/plat/gpio.h
+++ b/arch/arm/plat-orion/include/plat/gpio.h
@@ -13,7 +13,7 @@
13 13
14#include <linux/init.h> 14#include <linux/init.h>
15#include <linux/types.h> 15#include <linux/types.h>
16 16#include <linux/irqdomain.h>
17/* 17/*
18 * Orion-specific GPIO API extensions. 18 * Orion-specific GPIO API extensions.
19 */ 19 */
@@ -27,13 +27,11 @@ int orion_gpio_led_blink_set(unsigned gpio, int state,
27void orion_gpio_set_valid(unsigned pin, int mode); 27void orion_gpio_set_valid(unsigned pin, int mode);
28 28
29/* Initialize gpiolib. */ 29/* Initialize gpiolib. */
30void __init orion_gpio_init(int gpio_base, int ngpio, 30void __init orion_gpio_init(struct device_node *np,
31 u32 base, int mask_offset, int secondary_irq_base); 31 int gpio_base, int ngpio,
32 32 void __iomem *base, int mask_offset,
33/* 33 int secondary_irq_base,
34 * GPIO interrupt handling. 34 int irq[4]);
35 */
36void orion_gpio_irq_handler(int irqoff);
37
38 35
36void __init orion_gpio_of_init(int irq_gpio_base);
39#endif 37#endif
diff --git a/arch/arm/plat-orion/include/plat/irq.h b/arch/arm/plat-orion/include/plat/irq.h
index f05eeab94968..50547e417936 100644
--- a/arch/arm/plat-orion/include/plat/irq.h
+++ b/arch/arm/plat-orion/include/plat/irq.h
@@ -12,6 +12,5 @@
12#define __PLAT_IRQ_H 12#define __PLAT_IRQ_H
13 13
14void orion_irq_init(unsigned int irq_start, void __iomem *maskaddr); 14void orion_irq_init(unsigned int irq_start, void __iomem *maskaddr);
15 15void __init orion_dt_init_irq(void);
16
17#endif 16#endif
diff --git a/arch/arm/plat-orion/irq.c b/arch/arm/plat-orion/irq.c
index 2d5b9c1ef389..d751964def4c 100644
--- a/arch/arm/plat-orion/irq.c
+++ b/arch/arm/plat-orion/irq.c
@@ -11,8 +11,12 @@
11#include <linux/kernel.h> 11#include <linux/kernel.h>
12#include <linux/init.h> 12#include <linux/init.h>
13#include <linux/irq.h> 13#include <linux/irq.h>
14#include <linux/irqdomain.h>
14#include <linux/io.h> 15#include <linux/io.h>
16#include <linux/of_address.h>
17#include <linux/of_irq.h>
15#include <plat/irq.h> 18#include <plat/irq.h>
19#include <plat/gpio.h>
16 20
17void __init orion_irq_init(unsigned int irq_start, void __iomem *maskaddr) 21void __init orion_irq_init(unsigned int irq_start, void __iomem *maskaddr)
18{ 22{
@@ -32,3 +36,39 @@ void __init orion_irq_init(unsigned int irq_start, void __iomem *maskaddr)
32 irq_setup_generic_chip(gc, IRQ_MSK(32), IRQ_GC_INIT_MASK_CACHE, 36 irq_setup_generic_chip(gc, IRQ_MSK(32), IRQ_GC_INIT_MASK_CACHE,
33 IRQ_NOREQUEST, IRQ_LEVEL | IRQ_NOPROBE); 37 IRQ_NOREQUEST, IRQ_LEVEL | IRQ_NOPROBE);
34} 38}
39
40#ifdef CONFIG_OF
41static int __init orion_add_irq_domain(struct device_node *np,
42 struct device_node *interrupt_parent)
43{
44 int i = 0, irq_gpio;
45 void __iomem *base;
46
47 do {
48 base = of_iomap(np, i);
49 if (base) {
50 orion_irq_init(i * 32, base);
51 i++;
52 }
53 } while (base);
54
55 irq_domain_add_legacy(np, i * 32, 0, 0,
56 &irq_domain_simple_ops, NULL);
57
58 irq_gpio = i * 32;
59 orion_gpio_of_init(irq_gpio);
60
61 return 0;
62}
63
64static const struct of_device_id orion_irq_match[] = {
65 { .compatible = "marvell,orion-intc",
66 .data = orion_add_irq_domain, },
67 {},
68};
69
70void __init orion_dt_init_irq(void)
71{
72 of_irq_init(orion_irq_match);
73}
74#endif