summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-02-16 18:20:40 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2015-02-16 18:20:40 -0500
commit3c6847eaa3da59f3bbe15eb3004ddab41ae6a201 (patch)
tree9a33b100efeaa63fab23662eb0db42385b8d1f10
parent37507717de51a8332a34ee07fd88700be88df5bf (diff)
parent4fe7ffb7e17ca6ad9173b8de35f260c9c8fc2f79 (diff)
Merge branch 'irq-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull irqchip updates from Ingo Molnar: "Various irqchip driver updates, plus a genirq core update that allows the initial spreading of irqs amonst CPUs without having to do it from user-space" * 'irq-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: genirq: Fix null pointer reference in irq_set_affinity_hint() irqchip: gic: Allow interrupt level to be set for PPIs irqchip: mips-gic: Handle pending interrupts once in __gic_irq_dispatch() irqchip: Conexant CX92755 interrupts controller driver irqchip: Devicetree: document Conexant Digicolor irq binding irqchip: omap-intc: Remove unused legacy interface for omap2 irqchip: omap-intc: Fix support for dm814 and dm816 irqchip: mtk-sysirq: Get irq number from register resource size irqchip: renesas-intc-irqpin: r8a7779 IRLM setup support genirq: Set initial affinity in irq_set_affinity_hint()
-rw-r--r--Documentation/devicetree/bindings/arm/gic.txt8
-rw-r--r--Documentation/devicetree/bindings/interrupt-controller/digicolor-ic.txt21
-rw-r--r--Documentation/devicetree/bindings/interrupt-controller/renesas,intc-irqpin.txt5
-rw-r--r--Documentation/devicetree/bindings/interrupt-controller/ti,omap-intc-irq.txt28
-rw-r--r--drivers/irqchip/Makefile1
-rw-r--r--drivers/irqchip/irq-digicolor.c120
-rw-r--r--drivers/irqchip/irq-gic-common.c18
-rw-r--r--drivers/irqchip/irq-gic-common.h2
-rw-r--r--drivers/irqchip/irq-gic-v3.c8
-rw-r--r--drivers/irqchip/irq-gic.c9
-rw-r--r--drivers/irqchip/irq-hip04.c9
-rw-r--r--drivers/irqchip/irq-mips-gic.c44
-rw-r--r--drivers/irqchip/irq-mtk-sysirq.c18
-rw-r--r--drivers/irqchip/irq-omap-intc.c22
-rw-r--r--drivers/irqchip/irq-renesas-intc-irqpin.c50
-rw-r--r--include/linux/irqchip/irq-omap-intc.h2
-rw-r--r--kernel/irq/manage.c3
17 files changed, 296 insertions, 72 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/Documentation/devicetree/bindings/interrupt-controller/digicolor-ic.txt b/Documentation/devicetree/bindings/interrupt-controller/digicolor-ic.txt
new file mode 100644
index 000000000000..42d41ec84c7b
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/digicolor-ic.txt
@@ -0,0 +1,21 @@
1Conexant Digicolor Interrupt Controller
2
3Required properties:
4
5- compatible : should be "cnxt,cx92755-ic"
6- reg : Specifies base physical address and size of the interrupt controller
7 registers (IC) area
8- interrupt-controller : Identifies the node as an interrupt controller
9- #interrupt-cells : Specifies the number of cells needed to encode an
10 interrupt source. The value shall be 1.
11- syscon: A phandle to the syscon node describing UC registers
12
13Example:
14
15 intc: interrupt-controller@f0000040 {
16 compatible = "cnxt,cx92755-ic";
17 interrupt-controller;
18 #interrupt-cells = <1>;
19 reg = <0xf0000040 0x40>;
20 syscon = <&uc_regs>;
21 };
diff --git a/Documentation/devicetree/bindings/interrupt-controller/renesas,intc-irqpin.txt b/Documentation/devicetree/bindings/interrupt-controller/renesas,intc-irqpin.txt
index c73acd060093..4f7946ae8adc 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/renesas,intc-irqpin.txt
+++ b/Documentation/devicetree/bindings/interrupt-controller/renesas,intc-irqpin.txt
@@ -9,6 +9,11 @@ Required properties:
9 - "renesas,intc-irqpin-r8a7778" (R-Car M1A) 9 - "renesas,intc-irqpin-r8a7778" (R-Car M1A)
10 - "renesas,intc-irqpin-r8a7779" (R-Car H1) 10 - "renesas,intc-irqpin-r8a7779" (R-Car H1)
11 - "renesas,intc-irqpin-sh73a0" (SH-Mobile AG5) 11 - "renesas,intc-irqpin-sh73a0" (SH-Mobile AG5)
12
13- reg: Base address and length of each register bank used by the external
14 IRQ pins driven by the interrupt controller hardware module. The base
15 addresses, length and number of required register banks varies with soctype.
16
12- #interrupt-cells: has to be <2>: an interrupt index and flags, as defined in 17- #interrupt-cells: has to be <2>: an interrupt index and flags, as defined in
13 interrupts.txt in this directory 18 interrupts.txt in this directory
14 19
diff --git a/Documentation/devicetree/bindings/interrupt-controller/ti,omap-intc-irq.txt b/Documentation/devicetree/bindings/interrupt-controller/ti,omap-intc-irq.txt
new file mode 100644
index 000000000000..38ce5d037722
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/ti,omap-intc-irq.txt
@@ -0,0 +1,28 @@
1Omap2/3 intc controller
2
3On TI omap2 and 3 the intc interrupt controller can provide
496 or 128 IRQ signals to the ARM host depending on the SoC.
5
6Required Properties:
7- compatible: should be one of
8 "ti,omap2-intc"
9 "ti,omap3-intc"
10 "ti,dm814-intc"
11 "ti,dm816-intc"
12 "ti,am33xx-intc"
13
14- interrupt-controller : Identifies the node as an interrupt controller
15- #interrupt-cells : Specifies the number of cells needed to encode interrupt
16 source, should be 1 for intc
17- interrupts: interrupt reference to primary interrupt controller
18
19Please refer to interrupts.txt in this directory for details of the common
20Interrupt Controllers bindings used by client devices.
21
22Example:
23 intc: interrupt-controller@48200000 {
24 compatible = "ti,omap3-intc";
25 interrupt-controller;
26 #interrupt-cells = <1>;
27 reg = <0x48200000 0x1000>;
28 };
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index 9516a324be6d..42965d2476bb 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -42,3 +42,4 @@ obj-$(CONFIG_BRCMSTB_L2_IRQ) += irq-brcmstb-l2.o
42obj-$(CONFIG_KEYSTONE_IRQ) += irq-keystone.o 42obj-$(CONFIG_KEYSTONE_IRQ) += irq-keystone.o
43obj-$(CONFIG_MIPS_GIC) += irq-mips-gic.o 43obj-$(CONFIG_MIPS_GIC) += irq-mips-gic.o
44obj-$(CONFIG_ARCH_MEDIATEK) += irq-mtk-sysirq.o 44obj-$(CONFIG_ARCH_MEDIATEK) += irq-mtk-sysirq.o
45obj-$(CONFIG_ARCH_DIGICOLOR) += irq-digicolor.o
diff --git a/drivers/irqchip/irq-digicolor.c b/drivers/irqchip/irq-digicolor.c
new file mode 100644
index 000000000000..930a2a2fac7f
--- /dev/null
+++ b/drivers/irqchip/irq-digicolor.c
@@ -0,0 +1,120 @@
1/*
2 * Conexant Digicolor SoCs IRQ chip driver
3 *
4 * Author: Baruch Siach <baruch@tkos.co.il>
5 *
6 * Copyright (C) 2014 Paradox Innovation Ltd.
7 *
8 * This file is licensed under the terms of the GNU General Public
9 * License version 2. This program is licensed "as is" without any
10 * warranty of any kind, whether express or implied.
11 */
12
13#include <linux/io.h>
14#include <linux/irq.h>
15#include <linux/of.h>
16#include <linux/of_address.h>
17#include <linux/of_irq.h>
18#include <linux/mfd/syscon.h>
19#include <linux/regmap.h>
20
21#include <asm/exception.h>
22
23#include "irqchip.h"
24
25#define UC_IRQ_CONTROL 0x04
26
27#define IC_FLAG_CLEAR_LO 0x00
28#define IC_FLAG_CLEAR_XLO 0x04
29#define IC_INT0ENABLE_LO 0x10
30#define IC_INT0ENABLE_XLO 0x14
31#define IC_INT0STATUS_LO 0x18
32#define IC_INT0STATUS_XLO 0x1c
33
34static struct irq_domain *digicolor_irq_domain;
35
36static void __exception_irq_entry digicolor_handle_irq(struct pt_regs *regs)
37{
38 struct irq_domain_chip_generic *dgc = digicolor_irq_domain->gc;
39 struct irq_chip_generic *gc = dgc->gc[0];
40 u32 status, hwirq;
41
42 do {
43 status = irq_reg_readl(gc, IC_INT0STATUS_LO);
44 if (status) {
45 hwirq = ffs(status) - 1;
46 } else {
47 status = irq_reg_readl(gc, IC_INT0STATUS_XLO);
48 if (status)
49 hwirq = ffs(status) - 1 + 32;
50 else
51 return;
52 }
53
54 handle_domain_irq(digicolor_irq_domain, hwirq, regs);
55 } while (1);
56}
57
58static void digicolor_set_gc(void __iomem *reg_base, unsigned irq_base,
59 unsigned en_reg, unsigned ack_reg)
60{
61 struct irq_chip_generic *gc;
62
63 gc = irq_get_domain_generic_chip(digicolor_irq_domain, irq_base);
64 gc->reg_base = reg_base;
65 gc->chip_types[0].regs.ack = ack_reg;
66 gc->chip_types[0].regs.mask = en_reg;
67 gc->chip_types[0].chip.irq_ack = irq_gc_ack_set_bit;
68 gc->chip_types[0].chip.irq_mask = irq_gc_mask_clr_bit;
69 gc->chip_types[0].chip.irq_unmask = irq_gc_mask_set_bit;
70}
71
72static int __init digicolor_of_init(struct device_node *node,
73 struct device_node *parent)
74{
75 static void __iomem *reg_base;
76 unsigned int clr = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
77 struct regmap *ucregs;
78 int ret;
79
80 reg_base = of_iomap(node, 0);
81 if (!reg_base) {
82 pr_err("%s: unable to map IC registers\n", node->full_name);
83 return -ENXIO;
84 }
85
86 /* disable all interrupts */
87 writel(0, reg_base + IC_INT0ENABLE_LO);
88 writel(0, reg_base + IC_INT0ENABLE_XLO);
89
90 ucregs = syscon_regmap_lookup_by_phandle(node, "syscon");
91 if (IS_ERR(ucregs)) {
92 pr_err("%s: unable to map UC registers\n", node->full_name);
93 return PTR_ERR(ucregs);
94 }
95 /* channel 1, regular IRQs */
96 regmap_write(ucregs, UC_IRQ_CONTROL, 1);
97
98 digicolor_irq_domain =
99 irq_domain_add_linear(node, 64, &irq_generic_chip_ops, NULL);
100 if (!digicolor_irq_domain) {
101 pr_err("%s: unable to create IRQ domain\n", node->full_name);
102 return -ENOMEM;
103 }
104
105 ret = irq_alloc_domain_generic_chips(digicolor_irq_domain, 32, 1,
106 "digicolor_irq", handle_level_irq,
107 clr, 0, 0);
108 if (ret) {
109 pr_err("%s: unable to allocate IRQ gc\n", node->full_name);
110 return ret;
111 }
112
113 digicolor_set_gc(reg_base, 0, IC_INT0ENABLE_LO, IC_FLAG_CLEAR_LO);
114 digicolor_set_gc(reg_base, 32, IC_INT0ENABLE_XLO, IC_FLAG_CLEAR_XLO);
115
116 set_handle_irq(digicolor_handle_irq);
117
118 return 0;
119}
120IRQCHIP_DECLARE(conexant_digicolor_ic, "cnxt,cx92755-ic", digicolor_of_init);
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
24void gic_configure_irq(unsigned int irq, unsigned int type, 24int 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
68void __init gic_dist_config(void __iomem *base, int gic_irqs, 74void __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
23void gic_configure_irq(unsigned int irq, unsigned int type, 23int 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));
25void gic_dist_config(void __iomem *base, int gic_irqs, 25void 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 2ab290bec655..1c6dea2fbc34 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
257static u64 gic_mpidr_to_affinity(u64 mpidr) 257static 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
211static int gic_retrigger(struct irq_data *d) 214static 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
diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c
index 56b96c63dc4b..1daa7ca04577 100644
--- a/drivers/irqchip/irq-mips-gic.c
+++ b/drivers/irqchip/irq-mips-gic.c
@@ -235,9 +235,9 @@ int gic_get_c0_perfcount_int(void)
235 GIC_LOCAL_TO_HWIRQ(GIC_LOCAL_INT_PERFCTR)); 235 GIC_LOCAL_TO_HWIRQ(GIC_LOCAL_INT_PERFCTR));
236} 236}
237 237
238static unsigned int gic_get_int(void) 238static void gic_handle_shared_int(void)
239{ 239{
240 unsigned int i; 240 unsigned int i, intr, virq;
241 unsigned long *pcpu_mask; 241 unsigned long *pcpu_mask;
242 unsigned long pending_reg, intrmask_reg; 242 unsigned long pending_reg, intrmask_reg;
243 DECLARE_BITMAP(pending, GIC_MAX_INTRS); 243 DECLARE_BITMAP(pending, GIC_MAX_INTRS);
@@ -259,7 +259,16 @@ static unsigned int gic_get_int(void)
259 bitmap_and(pending, pending, intrmask, gic_shared_intrs); 259 bitmap_and(pending, pending, intrmask, gic_shared_intrs);
260 bitmap_and(pending, pending, pcpu_mask, gic_shared_intrs); 260 bitmap_and(pending, pending, pcpu_mask, gic_shared_intrs);
261 261
262 return find_first_bit(pending, gic_shared_intrs); 262 intr = find_first_bit(pending, gic_shared_intrs);
263 while (intr != gic_shared_intrs) {
264 virq = irq_linear_revmap(gic_irq_domain,
265 GIC_SHARED_TO_HWIRQ(intr));
266 do_IRQ(virq);
267
268 /* go to next pending bit */
269 bitmap_clear(pending, intr, 1);
270 intr = find_first_bit(pending, gic_shared_intrs);
271 }
263} 272}
264 273
265static void gic_mask_irq(struct irq_data *d) 274static void gic_mask_irq(struct irq_data *d)
@@ -386,16 +395,26 @@ static struct irq_chip gic_edge_irq_controller = {
386#endif 395#endif
387}; 396};
388 397
389static unsigned int gic_get_local_int(void) 398static void gic_handle_local_int(void)
390{ 399{
391 unsigned long pending, masked; 400 unsigned long pending, masked;
401 unsigned int intr, virq;
392 402
393 pending = gic_read(GIC_REG(VPE_LOCAL, GIC_VPE_PEND)); 403 pending = gic_read(GIC_REG(VPE_LOCAL, GIC_VPE_PEND));
394 masked = gic_read(GIC_REG(VPE_LOCAL, GIC_VPE_MASK)); 404 masked = gic_read(GIC_REG(VPE_LOCAL, GIC_VPE_MASK));
395 405
396 bitmap_and(&pending, &pending, &masked, GIC_NUM_LOCAL_INTRS); 406 bitmap_and(&pending, &pending, &masked, GIC_NUM_LOCAL_INTRS);
397 407
398 return find_first_bit(&pending, GIC_NUM_LOCAL_INTRS); 408 intr = find_first_bit(&pending, GIC_NUM_LOCAL_INTRS);
409 while (intr != GIC_NUM_LOCAL_INTRS) {
410 virq = irq_linear_revmap(gic_irq_domain,
411 GIC_LOCAL_TO_HWIRQ(intr));
412 do_IRQ(virq);
413
414 /* go to next pending bit */
415 bitmap_clear(&pending, intr, 1);
416 intr = find_first_bit(&pending, GIC_NUM_LOCAL_INTRS);
417 }
399} 418}
400 419
401static void gic_mask_local_irq(struct irq_data *d) 420static void gic_mask_local_irq(struct irq_data *d)
@@ -454,19 +473,8 @@ static struct irq_chip gic_all_vpes_local_irq_controller = {
454 473
455static void __gic_irq_dispatch(void) 474static void __gic_irq_dispatch(void)
456{ 475{
457 unsigned int intr, virq; 476 gic_handle_local_int();
458 477 gic_handle_shared_int();
459 while ((intr = gic_get_local_int()) != GIC_NUM_LOCAL_INTRS) {
460 virq = irq_linear_revmap(gic_irq_domain,
461 GIC_LOCAL_TO_HWIRQ(intr));
462 do_IRQ(virq);
463 }
464
465 while ((intr = gic_get_int()) != gic_shared_intrs) {
466 virq = irq_linear_revmap(gic_irq_domain,
467 GIC_SHARED_TO_HWIRQ(intr));
468 do_IRQ(virq);
469 }
470} 478}
471 479
472static void gic_irq_dispatch(unsigned int irq, struct irq_desc *desc) 480static void gic_irq_dispatch(unsigned int irq, struct irq_desc *desc)
diff --git a/drivers/irqchip/irq-mtk-sysirq.c b/drivers/irqchip/irq-mtk-sysirq.c
index 0b0d2c00a2df..eaf0a710e98a 100644
--- a/drivers/irqchip/irq-mtk-sysirq.c
+++ b/drivers/irqchip/irq-mtk-sysirq.c
@@ -23,8 +23,6 @@
23 23
24#include "irqchip.h" 24#include "irqchip.h"
25 25
26#define MT6577_SYS_INTPOL_NUM (224)
27
28struct mtk_sysirq_chip_data { 26struct mtk_sysirq_chip_data {
29 spinlock_t lock; 27 spinlock_t lock;
30 void __iomem *intpol_base; 28 void __iomem *intpol_base;
@@ -124,7 +122,8 @@ static int __init mtk_sysirq_of_init(struct device_node *node,
124{ 122{
125 struct irq_domain *domain, *domain_parent; 123 struct irq_domain *domain, *domain_parent;
126 struct mtk_sysirq_chip_data *chip_data; 124 struct mtk_sysirq_chip_data *chip_data;
127 int ret = 0; 125 int ret, size, intpol_num;
126 struct resource res;
128 127
129 domain_parent = irq_find_host(parent); 128 domain_parent = irq_find_host(parent);
130 if (!domain_parent) { 129 if (!domain_parent) {
@@ -132,19 +131,24 @@ static int __init mtk_sysirq_of_init(struct device_node *node,
132 return -EINVAL; 131 return -EINVAL;
133 } 132 }
134 133
134 ret = of_address_to_resource(node, 0, &res);
135 if (ret)
136 return ret;
137
135 chip_data = kzalloc(sizeof(*chip_data), GFP_KERNEL); 138 chip_data = kzalloc(sizeof(*chip_data), GFP_KERNEL);
136 if (!chip_data) 139 if (!chip_data)
137 return -ENOMEM; 140 return -ENOMEM;
138 141
139 chip_data->intpol_base = of_io_request_and_map(node, 0, "intpol"); 142 size = resource_size(&res);
140 if (IS_ERR(chip_data->intpol_base)) { 143 intpol_num = size * 8;
144 chip_data->intpol_base = ioremap(res.start, size);
145 if (!chip_data->intpol_base) {
141 pr_err("mtk_sysirq: unable to map sysirq register\n"); 146 pr_err("mtk_sysirq: unable to map sysirq register\n");
142 ret = PTR_ERR(chip_data->intpol_base); 147 ret = PTR_ERR(chip_data->intpol_base);
143 goto out_free; 148 goto out_free;
144 } 149 }
145 150
146 domain = irq_domain_add_hierarchy(domain_parent, 0, 151 domain = irq_domain_add_hierarchy(domain_parent, 0, intpol_num, node,
147 MT6577_SYS_INTPOL_NUM, node,
148 &sysirq_domain_ops, chip_data); 152 &sysirq_domain_ops, chip_data);
149 if (!domain) { 153 if (!domain) {
150 ret = -ENOMEM; 154 ret = -ENOMEM;
diff --git a/drivers/irqchip/irq-omap-intc.c b/drivers/irqchip/irq-omap-intc.c
index c03f140acbae..a569c6dbd1d1 100644
--- a/drivers/irqchip/irq-omap-intc.c
+++ b/drivers/irqchip/irq-omap-intc.c
@@ -364,14 +364,6 @@ out:
364 omap_ack_irq(NULL); 364 omap_ack_irq(NULL);
365} 365}
366 366
367void __init omap2_init_irq(void)
368{
369 omap_nr_irqs = 96;
370 omap_nr_pending = 3;
371 omap_init_irq(OMAP24XX_IC_BASE, NULL);
372 set_handle_irq(omap_intc_handle_irq);
373}
374
375void __init omap3_init_irq(void) 367void __init omap3_init_irq(void)
376{ 368{
377 omap_nr_irqs = 96; 369 omap_nr_irqs = 96;
@@ -380,14 +372,6 @@ void __init omap3_init_irq(void)
380 set_handle_irq(omap_intc_handle_irq); 372 set_handle_irq(omap_intc_handle_irq);
381} 373}
382 374
383void __init ti81xx_init_irq(void)
384{
385 omap_nr_irqs = 96;
386 omap_nr_pending = 4;
387 omap_init_irq(OMAP34XX_IC_BASE, NULL);
388 set_handle_irq(omap_intc_handle_irq);
389}
390
391static int __init intc_of_init(struct device_node *node, 375static int __init intc_of_init(struct device_node *node,
392 struct device_node *parent) 376 struct device_node *parent)
393{ 377{
@@ -399,7 +383,9 @@ static int __init intc_of_init(struct device_node *node,
399 if (WARN_ON(!node)) 383 if (WARN_ON(!node))
400 return -ENODEV; 384 return -ENODEV;
401 385
402 if (of_device_is_compatible(node, "ti,am33xx-intc")) { 386 if (of_device_is_compatible(node, "ti,dm814-intc") ||
387 of_device_is_compatible(node, "ti,dm816-intc") ||
388 of_device_is_compatible(node, "ti,am33xx-intc")) {
403 omap_nr_irqs = 128; 389 omap_nr_irqs = 128;
404 omap_nr_pending = 4; 390 omap_nr_pending = 4;
405 } 391 }
@@ -415,4 +401,6 @@ static int __init intc_of_init(struct device_node *node,
415 401
416IRQCHIP_DECLARE(omap2_intc, "ti,omap2-intc", intc_of_init); 402IRQCHIP_DECLARE(omap2_intc, "ti,omap2-intc", intc_of_init);
417IRQCHIP_DECLARE(omap3_intc, "ti,omap3-intc", intc_of_init); 403IRQCHIP_DECLARE(omap3_intc, "ti,omap3-intc", intc_of_init);
404IRQCHIP_DECLARE(dm814x_intc, "ti,dm814-intc", intc_of_init);
405IRQCHIP_DECLARE(dm816x_intc, "ti,dm816-intc", intc_of_init);
418IRQCHIP_DECLARE(am33xx_intc, "ti,am33xx-intc", intc_of_init); 406IRQCHIP_DECLARE(am33xx_intc, "ti,am33xx-intc", intc_of_init);
diff --git a/drivers/irqchip/irq-renesas-intc-irqpin.c b/drivers/irqchip/irq-renesas-intc-irqpin.c
index 078cac5e2d08..9a0767b9c89d 100644
--- a/drivers/irqchip/irq-renesas-intc-irqpin.c
+++ b/drivers/irqchip/irq-renesas-intc-irqpin.c
@@ -30,6 +30,7 @@
30#include <linux/err.h> 30#include <linux/err.h>
31#include <linux/slab.h> 31#include <linux/slab.h>
32#include <linux/module.h> 32#include <linux/module.h>
33#include <linux/of_device.h>
33#include <linux/platform_data/irq-renesas-intc-irqpin.h> 34#include <linux/platform_data/irq-renesas-intc-irqpin.h>
34#include <linux/pm_runtime.h> 35#include <linux/pm_runtime.h>
35 36
@@ -40,7 +41,9 @@
40#define INTC_IRQPIN_REG_SOURCE 2 /* INTREQnn */ 41#define INTC_IRQPIN_REG_SOURCE 2 /* INTREQnn */
41#define INTC_IRQPIN_REG_MASK 3 /* INTMSKnn */ 42#define INTC_IRQPIN_REG_MASK 3 /* INTMSKnn */
42#define INTC_IRQPIN_REG_CLEAR 4 /* INTMSKCLRnn */ 43#define INTC_IRQPIN_REG_CLEAR 4 /* INTMSKCLRnn */
43#define INTC_IRQPIN_REG_NR 5 44#define INTC_IRQPIN_REG_NR_MANDATORY 5
45#define INTC_IRQPIN_REG_IRLM 5 /* ICR0 with IRLM bit (optional) */
46#define INTC_IRQPIN_REG_NR 6
44 47
45/* INTC external IRQ PIN hardware register access: 48/* INTC external IRQ PIN hardware register access:
46 * 49 *
@@ -82,6 +85,10 @@ struct intc_irqpin_priv {
82 u8 shared_irq_mask; 85 u8 shared_irq_mask;
83}; 86};
84 87
88struct intc_irqpin_irlm_config {
89 unsigned int irlm_bit;
90};
91
85static unsigned long intc_irqpin_read32(void __iomem *iomem) 92static unsigned long intc_irqpin_read32(void __iomem *iomem)
86{ 93{
87 return ioread32(iomem); 94 return ioread32(iomem);
@@ -345,10 +352,23 @@ static struct irq_domain_ops intc_irqpin_irq_domain_ops = {
345 .xlate = irq_domain_xlate_twocell, 352 .xlate = irq_domain_xlate_twocell,
346}; 353};
347 354
355static const struct intc_irqpin_irlm_config intc_irqpin_irlm_r8a7779 = {
356 .irlm_bit = 23, /* ICR0.IRLM0 */
357};
358
359static const struct of_device_id intc_irqpin_dt_ids[] = {
360 { .compatible = "renesas,intc-irqpin", },
361 { .compatible = "renesas,intc-irqpin-r8a7779",
362 .data = &intc_irqpin_irlm_r8a7779 },
363 {},
364};
365MODULE_DEVICE_TABLE(of, intc_irqpin_dt_ids);
366
348static int intc_irqpin_probe(struct platform_device *pdev) 367static int intc_irqpin_probe(struct platform_device *pdev)
349{ 368{
350 struct device *dev = &pdev->dev; 369 struct device *dev = &pdev->dev;
351 struct renesas_intc_irqpin_config *pdata = dev->platform_data; 370 struct renesas_intc_irqpin_config *pdata = dev->platform_data;
371 const struct of_device_id *of_id;
352 struct intc_irqpin_priv *p; 372 struct intc_irqpin_priv *p;
353 struct intc_irqpin_iomem *i; 373 struct intc_irqpin_iomem *i;
354 struct resource *io[INTC_IRQPIN_REG_NR]; 374 struct resource *io[INTC_IRQPIN_REG_NR];
@@ -391,10 +411,11 @@ static int intc_irqpin_probe(struct platform_device *pdev)
391 pm_runtime_enable(dev); 411 pm_runtime_enable(dev);
392 pm_runtime_get_sync(dev); 412 pm_runtime_get_sync(dev);
393 413
394 /* get hold of manadatory IOMEM */ 414 /* get hold of register banks */
415 memset(io, 0, sizeof(io));
395 for (k = 0; k < INTC_IRQPIN_REG_NR; k++) { 416 for (k = 0; k < INTC_IRQPIN_REG_NR; k++) {
396 io[k] = platform_get_resource(pdev, IORESOURCE_MEM, k); 417 io[k] = platform_get_resource(pdev, IORESOURCE_MEM, k);
397 if (!io[k]) { 418 if (!io[k] && k < INTC_IRQPIN_REG_NR_MANDATORY) {
398 dev_err(dev, "not enough IOMEM resources\n"); 419 dev_err(dev, "not enough IOMEM resources\n");
399 ret = -EINVAL; 420 ret = -EINVAL;
400 goto err0; 421 goto err0;
@@ -422,6 +443,10 @@ static int intc_irqpin_probe(struct platform_device *pdev)
422 for (k = 0; k < INTC_IRQPIN_REG_NR; k++) { 443 for (k = 0; k < INTC_IRQPIN_REG_NR; k++) {
423 i = &p->iomem[k]; 444 i = &p->iomem[k];
424 445
446 /* handle optional registers */
447 if (!io[k])
448 continue;
449
425 switch (resource_size(io[k])) { 450 switch (resource_size(io[k])) {
426 case 1: 451 case 1:
427 i->width = 8; 452 i->width = 8;
@@ -448,6 +473,19 @@ static int intc_irqpin_probe(struct platform_device *pdev)
448 } 473 }
449 } 474 }
450 475
476 /* configure "individual IRQ mode" where needed */
477 of_id = of_match_device(intc_irqpin_dt_ids, dev);
478 if (of_id && of_id->data) {
479 const struct intc_irqpin_irlm_config *irlm_config = of_id->data;
480
481 if (io[INTC_IRQPIN_REG_IRLM])
482 intc_irqpin_read_modify_write(p, INTC_IRQPIN_REG_IRLM,
483 irlm_config->irlm_bit,
484 1, 1);
485 else
486 dev_warn(dev, "unable to select IRLM mode\n");
487 }
488
451 /* mask all interrupts using priority */ 489 /* mask all interrupts using priority */
452 for (k = 0; k < p->number_of_irqs; k++) 490 for (k = 0; k < p->number_of_irqs; k++)
453 intc_irqpin_mask_unmask_prio(p, k, 1); 491 intc_irqpin_mask_unmask_prio(p, k, 1);
@@ -550,12 +588,6 @@ static int intc_irqpin_remove(struct platform_device *pdev)
550 return 0; 588 return 0;
551} 589}
552 590
553static const struct of_device_id intc_irqpin_dt_ids[] = {
554 { .compatible = "renesas,intc-irqpin", },
555 {},
556};
557MODULE_DEVICE_TABLE(of, intc_irqpin_dt_ids);
558
559static struct platform_driver intc_irqpin_device_driver = { 591static struct platform_driver intc_irqpin_device_driver = {
560 .probe = intc_irqpin_probe, 592 .probe = intc_irqpin_probe,
561 .remove = intc_irqpin_remove, 593 .remove = intc_irqpin_remove,
diff --git a/include/linux/irqchip/irq-omap-intc.h b/include/linux/irqchip/irq-omap-intc.h
index e06b370cfc0d..2e3d1afeb674 100644
--- a/include/linux/irqchip/irq-omap-intc.h
+++ b/include/linux/irqchip/irq-omap-intc.h
@@ -18,9 +18,7 @@
18#ifndef __INCLUDE_LINUX_IRQCHIP_IRQ_OMAP_INTC_H 18#ifndef __INCLUDE_LINUX_IRQCHIP_IRQ_OMAP_INTC_H
19#define __INCLUDE_LINUX_IRQCHIP_IRQ_OMAP_INTC_H 19#define __INCLUDE_LINUX_IRQCHIP_IRQ_OMAP_INTC_H
20 20
21void omap2_init_irq(void);
22void omap3_init_irq(void); 21void omap3_init_irq(void);
23void ti81xx_init_irq(void);
24 22
25int omap_irq_pending(void); 23int omap_irq_pending(void);
26void omap_intc_save_context(void); 24void omap_intc_save_context(void);
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 80692373abd6..196a06fbc122 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -243,6 +243,9 @@ int irq_set_affinity_hint(unsigned int irq, const struct cpumask *m)
243 return -EINVAL; 243 return -EINVAL;
244 desc->affinity_hint = m; 244 desc->affinity_hint = m;
245 irq_put_desc_unlock(desc, flags); 245 irq_put_desc_unlock(desc, flags);
246 /* set the initial affinity to prevent every interrupt being on CPU0 */
247 if (m)
248 __irq_set_affinity(irq, m, false);
246 return 0; 249 return 0;
247} 250}
248EXPORT_SYMBOL_GPL(irq_set_affinity_hint); 251EXPORT_SYMBOL_GPL(irq_set_affinity_hint);