diff options
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/Kconfig | 1 | ||||
-rw-r--r-- | arch/arm/boot/dts/kirkwood.dtsi | 27 | ||||
-rw-r--r-- | arch/arm/mach-dove/irq.c | 58 | ||||
-rw-r--r-- | arch/arm/mach-kirkwood/board-dt.c | 3 | ||||
-rw-r--r-- | arch/arm/mach-kirkwood/irq.c | 38 | ||||
-rw-r--r-- | arch/arm/mach-mv78xx0/irq.c | 22 | ||||
-rw-r--r-- | arch/arm/mach-orion5x/irq.c | 22 | ||||
-rw-r--r-- | arch/arm/plat-orion/gpio.c | 166 | ||||
-rw-r--r-- | arch/arm/plat-orion/include/plat/gpio.h | 16 | ||||
-rw-r--r-- | arch/arm/plat-orion/include/plat/irq.h | 3 | ||||
-rw-r--r-- | arch/arm/plat-orion/irq.c | 40 |
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 | ||
1110 | config PLAT_PXA | 1111 | config 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 | ||
23 | static 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 | |||
39 | static void pmu_irq_mask(struct irq_data *d) | 23 | static 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 | ||
77 | static 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 | |||
84 | static int __initdata gpio1_irqs[4] = { | ||
85 | IRQ_DOVE_HIGH_GPIO, | ||
86 | 0, | ||
87 | 0, | ||
88 | 0, | ||
89 | }; | ||
90 | |||
91 | static int __initdata gpio2_irqs[4] = { | ||
92 | 0, | ||
93 | 0, | ||
94 | 0, | ||
95 | 0, | ||
96 | }; | ||
97 | |||
93 | void __init dove_init_irq(void) | 98 | void __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 | ||
23 | static struct of_device_id kirkwood_dt_match_table[] __initdata = { | 24 | static 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 | ||
19 | static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc) | 16 | static 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); | 23 | static 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 | ||
27 | void __init kirkwood_init_irq(void) | 30 | void __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 | ||
19 | static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc) | 17 | static 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 | ||
26 | void __init mv78xx0_init_irq(void) | 24 | void __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 | ||
21 | static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc) | 18 | static 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 | ||
28 | void __init orion5x_init_irq(void) | 25 | void __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 | ||
43 | static void __iomem *GPIO_OUT(struct orion_gpio_chip *ochip) | 51 | static 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 | ||
404 | void __init orion_gpio_init(int gpio_base, int ngpio, | 409 | static 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 | |||
442 | void __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 | ||
472 | void 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; | 543 | static 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; | ||
577 | out: | ||
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)); | 581 | void __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, | |||
27 | void orion_gpio_set_valid(unsigned pin, int mode); | 27 | void orion_gpio_set_valid(unsigned pin, int mode); |
28 | 28 | ||
29 | /* Initialize gpiolib. */ | 29 | /* Initialize gpiolib. */ |
30 | void __init orion_gpio_init(int gpio_base, int ngpio, | 30 | void __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 | */ | ||
36 | void orion_gpio_irq_handler(int irqoff); | ||
37 | |||
38 | 35 | ||
36 | void __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 | ||
14 | void orion_irq_init(unsigned int irq_start, void __iomem *maskaddr); | 14 | void orion_irq_init(unsigned int irq_start, void __iomem *maskaddr); |
15 | 15 | void __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 | ||
17 | void __init orion_irq_init(unsigned int irq_start, void __iomem *maskaddr) | 21 | void __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 | ||
41 | static 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 | |||
64 | static const struct of_device_id orion_irq_match[] = { | ||
65 | { .compatible = "marvell,orion-intc", | ||
66 | .data = orion_add_irq_domain, }, | ||
67 | {}, | ||
68 | }; | ||
69 | |||
70 | void __init orion_dt_init_irq(void) | ||
71 | { | ||
72 | of_irq_init(orion_irq_match); | ||
73 | } | ||
74 | #endif | ||