diff options
-rw-r--r-- | Documentation/devicetree/bindings/arm/gic.txt | 8 | ||||
-rw-r--r-- | drivers/irqchip/irq-gic-common.c | 18 | ||||
-rw-r--r-- | drivers/irqchip/irq-gic-common.h | 2 | ||||
-rw-r--r-- | drivers/irqchip/irq-gic-v3.c | 8 | ||||
-rw-r--r-- | drivers/irqchip/irq-gic.c | 9 | ||||
-rw-r--r-- | drivers/irqchip/irq-hip04.c | 9 |
6 files changed, 35 insertions, 19 deletions
diff --git a/Documentation/devicetree/bindings/arm/gic.txt b/Documentation/devicetree/bindings/arm/gic.txt index 8112d0c3675a..c97484b73e72 100644 --- a/Documentation/devicetree/bindings/arm/gic.txt +++ b/Documentation/devicetree/bindings/arm/gic.txt | |||
@@ -32,12 +32,16 @@ Main node required properties: | |||
32 | The 3rd cell is the flags, encoded as follows: | 32 | The 3rd cell is the flags, encoded as follows: |
33 | bits[3:0] trigger type and level flags. | 33 | bits[3:0] trigger type and level flags. |
34 | 1 = low-to-high edge triggered | 34 | 1 = low-to-high edge triggered |
35 | 2 = high-to-low edge triggered | 35 | 2 = high-to-low edge triggered (invalid for SPIs) |
36 | 4 = active high level-sensitive | 36 | 4 = active high level-sensitive |
37 | 8 = active low level-sensitive | 37 | 8 = active low level-sensitive (invalid for SPIs). |
38 | bits[15:8] PPI interrupt cpu mask. Each bit corresponds to each of | 38 | bits[15:8] PPI interrupt cpu mask. Each bit corresponds to each of |
39 | the 8 possible cpus attached to the GIC. A bit set to '1' indicated | 39 | the 8 possible cpus attached to the GIC. A bit set to '1' indicated |
40 | the interrupt is wired to that CPU. Only valid for PPI interrupts. | 40 | the interrupt is wired to that CPU. Only valid for PPI interrupts. |
41 | Also note that the configurability of PPI interrupts is IMPLEMENTATION | ||
42 | DEFINED and as such not guaranteed to be present (most SoC available | ||
43 | in 2014 seem to ignore the setting of this flag and use the hardware | ||
44 | default value). | ||
41 | 45 | ||
42 | - reg : Specifies base physical address(s) and size of the GIC registers. The | 46 | - reg : Specifies base physical address(s) and size of the GIC registers. The |
43 | first region is the GIC distributor register base and size. The 2nd region is | 47 | first region is the GIC distributor register base and size. The 2nd region is |
diff --git a/drivers/irqchip/irq-gic-common.c b/drivers/irqchip/irq-gic-common.c index 61541ff24397..ad96ebb0c7ab 100644 --- a/drivers/irqchip/irq-gic-common.c +++ b/drivers/irqchip/irq-gic-common.c | |||
@@ -21,7 +21,7 @@ | |||
21 | 21 | ||
22 | #include "irq-gic-common.h" | 22 | #include "irq-gic-common.h" |
23 | 23 | ||
24 | void gic_configure_irq(unsigned int irq, unsigned int type, | 24 | int gic_configure_irq(unsigned int irq, unsigned int type, |
25 | void __iomem *base, void (*sync_access)(void)) | 25 | void __iomem *base, void (*sync_access)(void)) |
26 | { | 26 | { |
27 | u32 enablemask = 1 << (irq % 32); | 27 | u32 enablemask = 1 << (irq % 32); |
@@ -29,16 +29,17 @@ void gic_configure_irq(unsigned int irq, unsigned int type, | |||
29 | u32 confmask = 0x2 << ((irq % 16) * 2); | 29 | u32 confmask = 0x2 << ((irq % 16) * 2); |
30 | u32 confoff = (irq / 16) * 4; | 30 | u32 confoff = (irq / 16) * 4; |
31 | bool enabled = false; | 31 | bool enabled = false; |
32 | u32 val; | 32 | u32 val, oldval; |
33 | int ret = 0; | ||
33 | 34 | ||
34 | /* | 35 | /* |
35 | * Read current configuration register, and insert the config | 36 | * Read current configuration register, and insert the config |
36 | * for "irq", depending on "type". | 37 | * for "irq", depending on "type". |
37 | */ | 38 | */ |
38 | val = readl_relaxed(base + GIC_DIST_CONFIG + confoff); | 39 | val = oldval = readl_relaxed(base + GIC_DIST_CONFIG + confoff); |
39 | if (type == IRQ_TYPE_LEVEL_HIGH) | 40 | if (type & IRQ_TYPE_LEVEL_MASK) |
40 | val &= ~confmask; | 41 | val &= ~confmask; |
41 | else if (type == IRQ_TYPE_EDGE_RISING) | 42 | else if (type & IRQ_TYPE_EDGE_BOTH) |
42 | val |= confmask; | 43 | val |= confmask; |
43 | 44 | ||
44 | /* | 45 | /* |
@@ -54,15 +55,20 @@ void gic_configure_irq(unsigned int irq, unsigned int type, | |||
54 | 55 | ||
55 | /* | 56 | /* |
56 | * Write back the new configuration, and possibly re-enable | 57 | * Write back the new configuration, and possibly re-enable |
57 | * the interrupt. | 58 | * the interrupt. If we tried to write a new configuration and failed, |
59 | * return an error. | ||
58 | */ | 60 | */ |
59 | writel_relaxed(val, base + GIC_DIST_CONFIG + confoff); | 61 | writel_relaxed(val, base + GIC_DIST_CONFIG + confoff); |
62 | if (readl_relaxed(base + GIC_DIST_CONFIG + confoff) != val && val != oldval) | ||
63 | ret = -EINVAL; | ||
60 | 64 | ||
61 | if (enabled) | 65 | if (enabled) |
62 | writel_relaxed(enablemask, base + GIC_DIST_ENABLE_SET + enableoff); | 66 | writel_relaxed(enablemask, base + GIC_DIST_ENABLE_SET + enableoff); |
63 | 67 | ||
64 | if (sync_access) | 68 | if (sync_access) |
65 | sync_access(); | 69 | sync_access(); |
70 | |||
71 | return ret; | ||
66 | } | 72 | } |
67 | 73 | ||
68 | void __init gic_dist_config(void __iomem *base, int gic_irqs, | 74 | void __init gic_dist_config(void __iomem *base, int gic_irqs, |
diff --git a/drivers/irqchip/irq-gic-common.h b/drivers/irqchip/irq-gic-common.h index b41f02481c3a..35a9884778bd 100644 --- a/drivers/irqchip/irq-gic-common.h +++ b/drivers/irqchip/irq-gic-common.h | |||
@@ -20,7 +20,7 @@ | |||
20 | #include <linux/of.h> | 20 | #include <linux/of.h> |
21 | #include <linux/irqdomain.h> | 21 | #include <linux/irqdomain.h> |
22 | 22 | ||
23 | void gic_configure_irq(unsigned int irq, unsigned int type, | 23 | int gic_configure_irq(unsigned int irq, unsigned int type, |
24 | void __iomem *base, void (*sync_access)(void)); | 24 | void __iomem *base, void (*sync_access)(void)); |
25 | void gic_dist_config(void __iomem *base, int gic_irqs, | 25 | void gic_dist_config(void __iomem *base, int gic_irqs, |
26 | void (*sync_access)(void)); | 26 | void (*sync_access)(void)); |
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c index 1a146ccee701..6e508038f31b 100644 --- a/drivers/irqchip/irq-gic-v3.c +++ b/drivers/irqchip/irq-gic-v3.c | |||
@@ -238,7 +238,9 @@ static int gic_set_type(struct irq_data *d, unsigned int type) | |||
238 | if (irq < 16) | 238 | if (irq < 16) |
239 | return -EINVAL; | 239 | return -EINVAL; |
240 | 240 | ||
241 | if (type != IRQ_TYPE_LEVEL_HIGH && type != IRQ_TYPE_EDGE_RISING) | 241 | /* SPIs have restrictions on the supported types */ |
242 | if (irq >= 32 && type != IRQ_TYPE_LEVEL_HIGH && | ||
243 | type != IRQ_TYPE_EDGE_RISING) | ||
242 | return -EINVAL; | 244 | return -EINVAL; |
243 | 245 | ||
244 | if (gic_irq_in_rdist(d)) { | 246 | if (gic_irq_in_rdist(d)) { |
@@ -249,9 +251,7 @@ static int gic_set_type(struct irq_data *d, unsigned int type) | |||
249 | rwp_wait = gic_dist_wait_for_rwp; | 251 | rwp_wait = gic_dist_wait_for_rwp; |
250 | } | 252 | } |
251 | 253 | ||
252 | gic_configure_irq(irq, type, base, rwp_wait); | 254 | return gic_configure_irq(irq, type, base, rwp_wait); |
253 | |||
254 | return 0; | ||
255 | } | 255 | } |
256 | 256 | ||
257 | static u64 gic_mpidr_to_affinity(u64 mpidr) | 257 | static u64 gic_mpidr_to_affinity(u64 mpidr) |
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c index d617ee5a3d8a..4634cf7d0ec3 100644 --- a/drivers/irqchip/irq-gic.c +++ b/drivers/irqchip/irq-gic.c | |||
@@ -188,12 +188,15 @@ static int gic_set_type(struct irq_data *d, unsigned int type) | |||
188 | { | 188 | { |
189 | void __iomem *base = gic_dist_base(d); | 189 | void __iomem *base = gic_dist_base(d); |
190 | unsigned int gicirq = gic_irq(d); | 190 | unsigned int gicirq = gic_irq(d); |
191 | int ret; | ||
191 | 192 | ||
192 | /* Interrupt configuration for SGIs can't be changed */ | 193 | /* Interrupt configuration for SGIs can't be changed */ |
193 | if (gicirq < 16) | 194 | if (gicirq < 16) |
194 | return -EINVAL; | 195 | return -EINVAL; |
195 | 196 | ||
196 | if (type != IRQ_TYPE_LEVEL_HIGH && type != IRQ_TYPE_EDGE_RISING) | 197 | /* SPIs have restrictions on the supported types */ |
198 | if (gicirq >= 32 && type != IRQ_TYPE_LEVEL_HIGH && | ||
199 | type != IRQ_TYPE_EDGE_RISING) | ||
197 | return -EINVAL; | 200 | return -EINVAL; |
198 | 201 | ||
199 | raw_spin_lock(&irq_controller_lock); | 202 | raw_spin_lock(&irq_controller_lock); |
@@ -201,11 +204,11 @@ static int gic_set_type(struct irq_data *d, unsigned int type) | |||
201 | if (gic_arch_extn.irq_set_type) | 204 | if (gic_arch_extn.irq_set_type) |
202 | gic_arch_extn.irq_set_type(d, type); | 205 | gic_arch_extn.irq_set_type(d, type); |
203 | 206 | ||
204 | gic_configure_irq(gicirq, type, base, NULL); | 207 | ret = gic_configure_irq(gicirq, type, base, NULL); |
205 | 208 | ||
206 | raw_spin_unlock(&irq_controller_lock); | 209 | raw_spin_unlock(&irq_controller_lock); |
207 | 210 | ||
208 | return 0; | 211 | return ret; |
209 | } | 212 | } |
210 | 213 | ||
211 | static int gic_retrigger(struct irq_data *d) | 214 | static int gic_retrigger(struct irq_data *d) |
diff --git a/drivers/irqchip/irq-hip04.c b/drivers/irqchip/irq-hip04.c index 6bc2deb73d53..7d6ffb5de84f 100644 --- a/drivers/irqchip/irq-hip04.c +++ b/drivers/irqchip/irq-hip04.c | |||
@@ -120,21 +120,24 @@ static int hip04_irq_set_type(struct irq_data *d, unsigned int type) | |||
120 | { | 120 | { |
121 | void __iomem *base = hip04_dist_base(d); | 121 | void __iomem *base = hip04_dist_base(d); |
122 | unsigned int irq = hip04_irq(d); | 122 | unsigned int irq = hip04_irq(d); |
123 | int ret; | ||
123 | 124 | ||
124 | /* Interrupt configuration for SGIs can't be changed */ | 125 | /* Interrupt configuration for SGIs can't be changed */ |
125 | if (irq < 16) | 126 | if (irq < 16) |
126 | return -EINVAL; | 127 | return -EINVAL; |
127 | 128 | ||
128 | if (type != IRQ_TYPE_LEVEL_HIGH && type != IRQ_TYPE_EDGE_RISING) | 129 | /* SPIs have restrictions on the supported types */ |
130 | if (irq >= 32 && type != IRQ_TYPE_LEVEL_HIGH && | ||
131 | type != IRQ_TYPE_EDGE_RISING) | ||
129 | return -EINVAL; | 132 | return -EINVAL; |
130 | 133 | ||
131 | raw_spin_lock(&irq_controller_lock); | 134 | raw_spin_lock(&irq_controller_lock); |
132 | 135 | ||
133 | gic_configure_irq(irq, type, base, NULL); | 136 | ret = gic_configure_irq(irq, type, base, NULL); |
134 | 137 | ||
135 | raw_spin_unlock(&irq_controller_lock); | 138 | raw_spin_unlock(&irq_controller_lock); |
136 | 139 | ||
137 | return 0; | 140 | return ret; |
138 | } | 141 | } |
139 | 142 | ||
140 | #ifdef CONFIG_SMP | 143 | #ifdef CONFIG_SMP |