aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShiraz Hashim <shiraz.hashim@st.com>2012-08-03 06:03:10 -0400
committerViresh Kumar <viresh.kumar@linaro.org>2012-11-26 06:25:32 -0500
commit80515a5a2e3c35e2994105f19af27650e8a16c51 (patch)
treeb117ab7aa811d0da139fc03aa4f906cbc5b560cb
parent300a6856324a56955ab909e1dca93dabb8464c8a (diff)
ARM: SPEAr3xx: shirq: simplify and move the shared irq multiplexor to DT
SPEAr3xx architecture includes shared/multiplexed irqs for certain set of devices. The multiplexor provides a single interrupt to parent interrupt controller (VIC) on behalf of a group of devices. There can be multiple groups available on SPEAr3xx variants but not exceeding 4. The number of devices in a group can differ, further they may share same set of status/mask registers spanning across different bit masks. Also in some cases the group may not have enable or other registers. This makes software little complex. Present implementation was non-DT and had few complex data structures to decipher banks, number of irqs supported, mask and registers involved. This patch simplifies the overall design and convert it in to DT. It also removes all registration from individual SoC files and bring them in to common shirq.c. Also updated the corresponding documentation for DT binding of shirq. Signed-off-by: Shiraz Hashim <shiraz.hashim@st.com> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
-rw-r--r--Documentation/devicetree/bindings/arm/spear/shirq.txt48
-rw-r--r--arch/arm/mach-spear3xx/include/mach/irqs.h10
-rw-r--r--arch/arm/mach-spear3xx/spear300.c103
-rw-r--r--arch/arm/mach-spear3xx/spear310.c202
-rw-r--r--arch/arm/mach-spear3xx/spear320.c204
-rw-r--r--arch/arm/mach-spear3xx/spear3xx.c4
-rw-r--r--arch/arm/plat-spear/include/plat/shirq.h39
-rw-r--r--arch/arm/plat-spear/shirq.c297
8 files changed, 316 insertions, 591 deletions
diff --git a/Documentation/devicetree/bindings/arm/spear/shirq.txt b/Documentation/devicetree/bindings/arm/spear/shirq.txt
new file mode 100644
index 00000000000..13fbb8866bd
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/spear/shirq.txt
@@ -0,0 +1,48 @@
1* SPEAr Shared IRQ layer (shirq)
2
3SPEAr3xx architecture includes shared/multiplexed irqs for certain set
4of devices. The multiplexor provides a single interrupt to parent
5interrupt controller (VIC) on behalf of a group of devices.
6
7There can be multiple groups available on SPEAr3xx variants but not
8exceeding 4. The number of devices in a group can differ, further they
9may share same set of status/mask registers spanning across different
10bit masks. Also in some cases the group may not have enable or other
11registers. This makes software little complex.
12
13A single node in the device tree is used to describe the shared
14interrupt multiplexor (one node for all groups). A group in the
15interrupt controller shares config/control registers with other groups.
16For example, a 32-bit interrupt enable/disable config register can
17accommodate upto 4 interrupt groups.
18
19Required properties:
20 - compatible: should be, either of
21 - "st,spear300-shirq"
22 - "st,spear310-shirq"
23 - "st,spear320-shirq"
24 - interrupt-controller: Identifies the node as an interrupt controller.
25 - #interrupt-cells: should be <1> which basically contains the offset
26 (starting from 0) of interrupts for all the groups.
27 - reg: Base address and size of shirq registers.
28 - interrupts: The list of interrupts generated by the groups which are
29 then connected to a parent interrupt controller. Each group is
30 associated with one of the interrupts, hence number of interrupts (to
31 parent) is equal to number of groups. The format of the interrupt
32 specifier depends in the interrupt parent controller.
33
34 Optional properties:
35 - interrupt-parent: pHandle of the parent interrupt controller, if not
36 inherited from the parent node.
37
38Example:
39
40The following is an example from the SPEAr320 SoC dtsi file.
41
42shirq: interrupt-controller@0xb3000000 {
43 compatible = "st,spear320-shirq";
44 reg = <0xb3000000 0x1000>;
45 interrupts = <28 29 30 1>;
46 #interrupt-cells = <1>;
47 interrupt-controller;
48};
diff --git a/arch/arm/mach-spear3xx/include/mach/irqs.h b/arch/arm/mach-spear3xx/include/mach/irqs.h
index 803de76f5f3..f95e5b2b668 100644
--- a/arch/arm/mach-spear3xx/include/mach/irqs.h
+++ b/arch/arm/mach-spear3xx/include/mach/irqs.h
@@ -14,14 +14,6 @@
14#ifndef __MACH_IRQS_H 14#ifndef __MACH_IRQS_H
15#define __MACH_IRQS_H 15#define __MACH_IRQS_H
16 16
17/* FIXME: probe all these from DT */ 17#define NR_IRQS 256
18#define SPEAR3XX_IRQ_INTRCOMM_RAS_ARM 1
19#define SPEAR3XX_IRQ_GEN_RAS_1 28
20#define SPEAR3XX_IRQ_GEN_RAS_2 29
21#define SPEAR3XX_IRQ_GEN_RAS_3 30
22#define SPEAR3XX_IRQ_VIC_END 32
23#define SPEAR3XX_VIRQ_START SPEAR3XX_IRQ_VIC_END
24
25#define NR_IRQS 160
26 18
27#endif /* __MACH_IRQS_H */ 19#endif /* __MACH_IRQS_H */
diff --git a/arch/arm/mach-spear3xx/spear300.c b/arch/arm/mach-spear3xx/spear300.c
index 6ec30054996..a69cbfdb07e 100644
--- a/arch/arm/mach-spear3xx/spear300.c
+++ b/arch/arm/mach-spear3xx/spear300.c
@@ -17,102 +17,9 @@
17#include <linux/of_platform.h> 17#include <linux/of_platform.h>
18#include <asm/hardware/vic.h> 18#include <asm/hardware/vic.h>
19#include <asm/mach/arch.h> 19#include <asm/mach/arch.h>
20#include <plat/shirq.h>
21#include <mach/generic.h> 20#include <mach/generic.h>
22#include <mach/spear.h> 21#include <mach/spear.h>
23 22
24/* Base address of various IPs */
25#define SPEAR300_TELECOM_BASE UL(0x50000000)
26
27/* Interrupt registers offsets and masks */
28#define SPEAR300_INT_ENB_MASK_REG 0x54
29#define SPEAR300_INT_STS_MASK_REG 0x58
30#define SPEAR300_IT_PERS_S_IRQ_MASK (1 << 0)
31#define SPEAR300_IT_CHANGE_S_IRQ_MASK (1 << 1)
32#define SPEAR300_I2S_IRQ_MASK (1 << 2)
33#define SPEAR300_TDM_IRQ_MASK (1 << 3)
34#define SPEAR300_CAMERA_L_IRQ_MASK (1 << 4)
35#define SPEAR300_CAMERA_F_IRQ_MASK (1 << 5)
36#define SPEAR300_CAMERA_V_IRQ_MASK (1 << 6)
37#define SPEAR300_KEYBOARD_IRQ_MASK (1 << 7)
38#define SPEAR300_GPIO1_IRQ_MASK (1 << 8)
39
40#define SPEAR300_SHIRQ_RAS1_MASK 0x1FF
41
42#define SPEAR300_SOC_CONFIG_BASE UL(0x99000000)
43
44
45/* SPEAr300 Virtual irq definitions */
46/* IRQs sharing IRQ_GEN_RAS_1 */
47#define SPEAR300_VIRQ_IT_PERS_S (SPEAR3XX_VIRQ_START + 0)
48#define SPEAR300_VIRQ_IT_CHANGE_S (SPEAR3XX_VIRQ_START + 1)
49#define SPEAR300_VIRQ_I2S (SPEAR3XX_VIRQ_START + 2)
50#define SPEAR300_VIRQ_TDM (SPEAR3XX_VIRQ_START + 3)
51#define SPEAR300_VIRQ_CAMERA_L (SPEAR3XX_VIRQ_START + 4)
52#define SPEAR300_VIRQ_CAMERA_F (SPEAR3XX_VIRQ_START + 5)
53#define SPEAR300_VIRQ_CAMERA_V (SPEAR3XX_VIRQ_START + 6)
54#define SPEAR300_VIRQ_KEYBOARD (SPEAR3XX_VIRQ_START + 7)
55#define SPEAR300_VIRQ_GPIO1 (SPEAR3XX_VIRQ_START + 8)
56
57/* IRQs sharing IRQ_GEN_RAS_3 */
58#define SPEAR300_IRQ_CLCD SPEAR3XX_IRQ_GEN_RAS_3
59
60/* IRQs sharing IRQ_INTRCOMM_RAS_ARM */
61#define SPEAR300_IRQ_SDHCI SPEAR3XX_IRQ_INTRCOMM_RAS_ARM
62
63/* spear3xx shared irq */
64static struct shirq_dev_config shirq_ras1_config[] = {
65 {
66 .virq = SPEAR300_VIRQ_IT_PERS_S,
67 .enb_mask = SPEAR300_IT_PERS_S_IRQ_MASK,
68 .status_mask = SPEAR300_IT_PERS_S_IRQ_MASK,
69 }, {
70 .virq = SPEAR300_VIRQ_IT_CHANGE_S,
71 .enb_mask = SPEAR300_IT_CHANGE_S_IRQ_MASK,
72 .status_mask = SPEAR300_IT_CHANGE_S_IRQ_MASK,
73 }, {
74 .virq = SPEAR300_VIRQ_I2S,
75 .enb_mask = SPEAR300_I2S_IRQ_MASK,
76 .status_mask = SPEAR300_I2S_IRQ_MASK,
77 }, {
78 .virq = SPEAR300_VIRQ_TDM,
79 .enb_mask = SPEAR300_TDM_IRQ_MASK,
80 .status_mask = SPEAR300_TDM_IRQ_MASK,
81 }, {
82 .virq = SPEAR300_VIRQ_CAMERA_L,
83 .enb_mask = SPEAR300_CAMERA_L_IRQ_MASK,
84 .status_mask = SPEAR300_CAMERA_L_IRQ_MASK,
85 }, {
86 .virq = SPEAR300_VIRQ_CAMERA_F,
87 .enb_mask = SPEAR300_CAMERA_F_IRQ_MASK,
88 .status_mask = SPEAR300_CAMERA_F_IRQ_MASK,
89 }, {
90 .virq = SPEAR300_VIRQ_CAMERA_V,
91 .enb_mask = SPEAR300_CAMERA_V_IRQ_MASK,
92 .status_mask = SPEAR300_CAMERA_V_IRQ_MASK,
93 }, {
94 .virq = SPEAR300_VIRQ_KEYBOARD,
95 .enb_mask = SPEAR300_KEYBOARD_IRQ_MASK,
96 .status_mask = SPEAR300_KEYBOARD_IRQ_MASK,
97 }, {
98 .virq = SPEAR300_VIRQ_GPIO1,
99 .enb_mask = SPEAR300_GPIO1_IRQ_MASK,
100 .status_mask = SPEAR300_GPIO1_IRQ_MASK,
101 },
102};
103
104static struct spear_shirq shirq_ras1 = {
105 .irq = SPEAR3XX_IRQ_GEN_RAS_1,
106 .dev_config = shirq_ras1_config,
107 .dev_count = ARRAY_SIZE(shirq_ras1_config),
108 .regs = {
109 .enb_reg = SPEAR300_INT_ENB_MASK_REG,
110 .status_reg = SPEAR300_INT_STS_MASK_REG,
111 .status_reg_mask = SPEAR300_SHIRQ_RAS1_MASK,
112 .clear_reg = -1,
113 },
114};
115
116/* DMAC platform data's slave info */ 23/* DMAC platform data's slave info */
117struct pl08x_channel_data spear300_dma_info[] = { 24struct pl08x_channel_data spear300_dma_info[] = {
118 { 25 {
@@ -285,21 +192,11 @@ static struct of_dev_auxdata spear300_auxdata_lookup[] __initdata = {
285 192
286static void __init spear300_dt_init(void) 193static void __init spear300_dt_init(void)
287{ 194{
288 int ret;
289
290 pl080_plat_data.slave_channels = spear300_dma_info; 195 pl080_plat_data.slave_channels = spear300_dma_info;
291 pl080_plat_data.num_slave_channels = ARRAY_SIZE(spear300_dma_info); 196 pl080_plat_data.num_slave_channels = ARRAY_SIZE(spear300_dma_info);
292 197
293 of_platform_populate(NULL, of_default_bus_match_table, 198 of_platform_populate(NULL, of_default_bus_match_table,
294 spear300_auxdata_lookup, NULL); 199 spear300_auxdata_lookup, NULL);
295
296 /* shared irq registration */
297 shirq_ras1.regs.base = ioremap(SPEAR300_TELECOM_BASE, SZ_4K);
298 if (shirq_ras1.regs.base) {
299 ret = spear_shirq_register(&shirq_ras1);
300 if (ret)
301 pr_err("Error registering Shared IRQ\n");
302 }
303} 200}
304 201
305static const char * const spear300_dt_board_compat[] = { 202static const char * const spear300_dt_board_compat[] = {
diff --git a/arch/arm/mach-spear3xx/spear310.c b/arch/arm/mach-spear3xx/spear310.c
index 1d0e435b904..b963ebb10b5 100644
--- a/arch/arm/mach-spear3xx/spear310.c
+++ b/arch/arm/mach-spear3xx/spear310.c
@@ -18,7 +18,6 @@
18#include <linux/of_platform.h> 18#include <linux/of_platform.h>
19#include <asm/hardware/vic.h> 19#include <asm/hardware/vic.h>
20#include <asm/mach/arch.h> 20#include <asm/mach/arch.h>
21#include <plat/shirq.h>
22#include <mach/generic.h> 21#include <mach/generic.h>
23#include <mach/spear.h> 22#include <mach/spear.h>
24 23
@@ -27,176 +26,6 @@
27#define SPEAR310_UART3_BASE UL(0xB2100000) 26#define SPEAR310_UART3_BASE UL(0xB2100000)
28#define SPEAR310_UART4_BASE UL(0xB2180000) 27#define SPEAR310_UART4_BASE UL(0xB2180000)
29#define SPEAR310_UART5_BASE UL(0xB2200000) 28#define SPEAR310_UART5_BASE UL(0xB2200000)
30#define SPEAR310_SOC_CONFIG_BASE UL(0xB4000000)
31
32/* Interrupt registers offsets and masks */
33#define SPEAR310_INT_STS_MASK_REG 0x04
34#define SPEAR310_SMII0_IRQ_MASK (1 << 0)
35#define SPEAR310_SMII1_IRQ_MASK (1 << 1)
36#define SPEAR310_SMII2_IRQ_MASK (1 << 2)
37#define SPEAR310_SMII3_IRQ_MASK (1 << 3)
38#define SPEAR310_WAKEUP_SMII0_IRQ_MASK (1 << 4)
39#define SPEAR310_WAKEUP_SMII1_IRQ_MASK (1 << 5)
40#define SPEAR310_WAKEUP_SMII2_IRQ_MASK (1 << 6)
41#define SPEAR310_WAKEUP_SMII3_IRQ_MASK (1 << 7)
42#define SPEAR310_UART1_IRQ_MASK (1 << 8)
43#define SPEAR310_UART2_IRQ_MASK (1 << 9)
44#define SPEAR310_UART3_IRQ_MASK (1 << 10)
45#define SPEAR310_UART4_IRQ_MASK (1 << 11)
46#define SPEAR310_UART5_IRQ_MASK (1 << 12)
47#define SPEAR310_EMI_IRQ_MASK (1 << 13)
48#define SPEAR310_TDM_HDLC_IRQ_MASK (1 << 14)
49#define SPEAR310_RS485_0_IRQ_MASK (1 << 15)
50#define SPEAR310_RS485_1_IRQ_MASK (1 << 16)
51
52#define SPEAR310_SHIRQ_RAS1_MASK 0x000FF
53#define SPEAR310_SHIRQ_RAS2_MASK 0x01F00
54#define SPEAR310_SHIRQ_RAS3_MASK 0x02000
55#define SPEAR310_SHIRQ_INTRCOMM_RAS_MASK 0x1C000
56
57/* SPEAr310 Virtual irq definitions */
58/* IRQs sharing IRQ_GEN_RAS_1 */
59#define SPEAR310_VIRQ_SMII0 (SPEAR3XX_VIRQ_START + 0)
60#define SPEAR310_VIRQ_SMII1 (SPEAR3XX_VIRQ_START + 1)
61#define SPEAR310_VIRQ_SMII2 (SPEAR3XX_VIRQ_START + 2)
62#define SPEAR310_VIRQ_SMII3 (SPEAR3XX_VIRQ_START + 3)
63#define SPEAR310_VIRQ_WAKEUP_SMII0 (SPEAR3XX_VIRQ_START + 4)
64#define SPEAR310_VIRQ_WAKEUP_SMII1 (SPEAR3XX_VIRQ_START + 5)
65#define SPEAR310_VIRQ_WAKEUP_SMII2 (SPEAR3XX_VIRQ_START + 6)
66#define SPEAR310_VIRQ_WAKEUP_SMII3 (SPEAR3XX_VIRQ_START + 7)
67
68/* IRQs sharing IRQ_GEN_RAS_2 */
69#define SPEAR310_VIRQ_UART1 (SPEAR3XX_VIRQ_START + 8)
70#define SPEAR310_VIRQ_UART2 (SPEAR3XX_VIRQ_START + 9)
71#define SPEAR310_VIRQ_UART3 (SPEAR3XX_VIRQ_START + 10)
72#define SPEAR310_VIRQ_UART4 (SPEAR3XX_VIRQ_START + 11)
73#define SPEAR310_VIRQ_UART5 (SPEAR3XX_VIRQ_START + 12)
74
75/* IRQs sharing IRQ_GEN_RAS_3 */
76#define SPEAR310_VIRQ_EMI (SPEAR3XX_VIRQ_START + 13)
77#define SPEAR310_VIRQ_PLGPIO (SPEAR3XX_VIRQ_START + 14)
78
79/* IRQs sharing IRQ_INTRCOMM_RAS_ARM */
80#define SPEAR310_VIRQ_TDM_HDLC (SPEAR3XX_VIRQ_START + 15)
81#define SPEAR310_VIRQ_RS485_0 (SPEAR3XX_VIRQ_START + 16)
82#define SPEAR310_VIRQ_RS485_1 (SPEAR3XX_VIRQ_START + 17)
83
84
85/* spear3xx shared irq */
86static struct shirq_dev_config shirq_ras1_config[] = {
87 {
88 .virq = SPEAR310_VIRQ_SMII0,
89 .status_mask = SPEAR310_SMII0_IRQ_MASK,
90 }, {
91 .virq = SPEAR310_VIRQ_SMII1,
92 .status_mask = SPEAR310_SMII1_IRQ_MASK,
93 }, {
94 .virq = SPEAR310_VIRQ_SMII2,
95 .status_mask = SPEAR310_SMII2_IRQ_MASK,
96 }, {
97 .virq = SPEAR310_VIRQ_SMII3,
98 .status_mask = SPEAR310_SMII3_IRQ_MASK,
99 }, {
100 .virq = SPEAR310_VIRQ_WAKEUP_SMII0,
101 .status_mask = SPEAR310_WAKEUP_SMII0_IRQ_MASK,
102 }, {
103 .virq = SPEAR310_VIRQ_WAKEUP_SMII1,
104 .status_mask = SPEAR310_WAKEUP_SMII1_IRQ_MASK,
105 }, {
106 .virq = SPEAR310_VIRQ_WAKEUP_SMII2,
107 .status_mask = SPEAR310_WAKEUP_SMII2_IRQ_MASK,
108 }, {
109 .virq = SPEAR310_VIRQ_WAKEUP_SMII3,
110 .status_mask = SPEAR310_WAKEUP_SMII3_IRQ_MASK,
111 },
112};
113
114static struct spear_shirq shirq_ras1 = {
115 .irq = SPEAR3XX_IRQ_GEN_RAS_1,
116 .dev_config = shirq_ras1_config,
117 .dev_count = ARRAY_SIZE(shirq_ras1_config),
118 .regs = {
119 .enb_reg = -1,
120 .status_reg = SPEAR310_INT_STS_MASK_REG,
121 .status_reg_mask = SPEAR310_SHIRQ_RAS1_MASK,
122 .clear_reg = -1,
123 },
124};
125
126static struct shirq_dev_config shirq_ras2_config[] = {
127 {
128 .virq = SPEAR310_VIRQ_UART1,
129 .status_mask = SPEAR310_UART1_IRQ_MASK,
130 }, {
131 .virq = SPEAR310_VIRQ_UART2,
132 .status_mask = SPEAR310_UART2_IRQ_MASK,
133 }, {
134 .virq = SPEAR310_VIRQ_UART3,
135 .status_mask = SPEAR310_UART3_IRQ_MASK,
136 }, {
137 .virq = SPEAR310_VIRQ_UART4,
138 .status_mask = SPEAR310_UART4_IRQ_MASK,
139 }, {
140 .virq = SPEAR310_VIRQ_UART5,
141 .status_mask = SPEAR310_UART5_IRQ_MASK,
142 },
143};
144
145static struct spear_shirq shirq_ras2 = {
146 .irq = SPEAR3XX_IRQ_GEN_RAS_2,
147 .dev_config = shirq_ras2_config,
148 .dev_count = ARRAY_SIZE(shirq_ras2_config),
149 .regs = {
150 .enb_reg = -1,
151 .status_reg = SPEAR310_INT_STS_MASK_REG,
152 .status_reg_mask = SPEAR310_SHIRQ_RAS2_MASK,
153 .clear_reg = -1,
154 },
155};
156
157static struct shirq_dev_config shirq_ras3_config[] = {
158 {
159 .virq = SPEAR310_VIRQ_EMI,
160 .status_mask = SPEAR310_EMI_IRQ_MASK,
161 },
162};
163
164static struct spear_shirq shirq_ras3 = {
165 .irq = SPEAR3XX_IRQ_GEN_RAS_3,
166 .dev_config = shirq_ras3_config,
167 .dev_count = ARRAY_SIZE(shirq_ras3_config),
168 .regs = {
169 .enb_reg = -1,
170 .status_reg = SPEAR310_INT_STS_MASK_REG,
171 .status_reg_mask = SPEAR310_SHIRQ_RAS3_MASK,
172 .clear_reg = -1,
173 },
174};
175
176static struct shirq_dev_config shirq_intrcomm_ras_config[] = {
177 {
178 .virq = SPEAR310_VIRQ_TDM_HDLC,
179 .status_mask = SPEAR310_TDM_HDLC_IRQ_MASK,
180 }, {
181 .virq = SPEAR310_VIRQ_RS485_0,
182 .status_mask = SPEAR310_RS485_0_IRQ_MASK,
183 }, {
184 .virq = SPEAR310_VIRQ_RS485_1,
185 .status_mask = SPEAR310_RS485_1_IRQ_MASK,
186 },
187};
188
189static struct spear_shirq shirq_intrcomm_ras = {
190 .irq = SPEAR3XX_IRQ_INTRCOMM_RAS_ARM,
191 .dev_config = shirq_intrcomm_ras_config,
192 .dev_count = ARRAY_SIZE(shirq_intrcomm_ras_config),
193 .regs = {
194 .enb_reg = -1,
195 .status_reg = SPEAR310_INT_STS_MASK_REG,
196 .status_reg_mask = SPEAR310_SHIRQ_INTRCOMM_RAS_MASK,
197 .clear_reg = -1,
198 },
199};
200 29
201/* DMAC platform data's slave info */ 30/* DMAC platform data's slave info */
202struct pl08x_channel_data spear310_dma_info[] = { 31struct pl08x_channel_data spear310_dma_info[] = {
@@ -405,42 +234,11 @@ static struct of_dev_auxdata spear310_auxdata_lookup[] __initdata = {
405 234
406static void __init spear310_dt_init(void) 235static void __init spear310_dt_init(void)
407{ 236{
408 void __iomem *base;
409 int ret;
410
411 pl080_plat_data.slave_channels = spear310_dma_info; 237 pl080_plat_data.slave_channels = spear310_dma_info;
412 pl080_plat_data.num_slave_channels = ARRAY_SIZE(spear310_dma_info); 238 pl080_plat_data.num_slave_channels = ARRAY_SIZE(spear310_dma_info);
413 239
414 of_platform_populate(NULL, of_default_bus_match_table, 240 of_platform_populate(NULL, of_default_bus_match_table,
415 spear310_auxdata_lookup, NULL); 241 spear310_auxdata_lookup, NULL);
416
417 /* shared irq registration */
418 base = ioremap(SPEAR310_SOC_CONFIG_BASE, SZ_4K);
419 if (base) {
420 /* shirq 1 */
421 shirq_ras1.regs.base = base;
422 ret = spear_shirq_register(&shirq_ras1);
423 if (ret)
424 pr_err("Error registering Shared IRQ 1\n");
425
426 /* shirq 2 */
427 shirq_ras2.regs.base = base;
428 ret = spear_shirq_register(&shirq_ras2);
429 if (ret)
430 pr_err("Error registering Shared IRQ 2\n");
431
432 /* shirq 3 */
433 shirq_ras3.regs.base = base;
434 ret = spear_shirq_register(&shirq_ras3);
435 if (ret)
436 pr_err("Error registering Shared IRQ 3\n");
437
438 /* shirq 4 */
439 shirq_intrcomm_ras.regs.base = base;
440 ret = spear_shirq_register(&shirq_intrcomm_ras);
441 if (ret)
442 pr_err("Error registering Shared IRQ 4\n");
443 }
444} 242}
445 243
446static const char * const spear310_dt_board_compat[] = { 244static const char * const spear310_dt_board_compat[] = {
diff --git a/arch/arm/mach-spear3xx/spear320.c b/arch/arm/mach-spear3xx/spear320.c
index fd823c62457..707504b84e0 100644
--- a/arch/arm/mach-spear3xx/spear320.c
+++ b/arch/arm/mach-spear3xx/spear320.c
@@ -19,7 +19,6 @@
19#include <linux/of_platform.h> 19#include <linux/of_platform.h>
20#include <asm/hardware/vic.h> 20#include <asm/hardware/vic.h>
21#include <asm/mach/arch.h> 21#include <asm/mach/arch.h>
22#include <plat/shirq.h>
23#include <mach/generic.h> 22#include <mach/generic.h>
24#include <mach/spear.h> 23#include <mach/spear.h>
25 24
@@ -28,184 +27,6 @@
28#define SPEAR320_SSP0_BASE UL(0xA5000000) 27#define SPEAR320_SSP0_BASE UL(0xA5000000)
29#define SPEAR320_SSP1_BASE UL(0xA6000000) 28#define SPEAR320_SSP1_BASE UL(0xA6000000)
30 29
31/* Interrupt registers offsets and masks */
32#define SPEAR320_INT_STS_MASK_REG 0x04
33#define SPEAR320_INT_CLR_MASK_REG 0x04
34#define SPEAR320_INT_ENB_MASK_REG 0x08
35#define SPEAR320_GPIO_IRQ_MASK (1 << 0)
36#define SPEAR320_I2S_PLAY_IRQ_MASK (1 << 1)
37#define SPEAR320_I2S_REC_IRQ_MASK (1 << 2)
38#define SPEAR320_EMI_IRQ_MASK (1 << 7)
39#define SPEAR320_CLCD_IRQ_MASK (1 << 8)
40#define SPEAR320_SPP_IRQ_MASK (1 << 9)
41#define SPEAR320_SDHCI_IRQ_MASK (1 << 10)
42#define SPEAR320_CAN_U_IRQ_MASK (1 << 11)
43#define SPEAR320_CAN_L_IRQ_MASK (1 << 12)
44#define SPEAR320_UART1_IRQ_MASK (1 << 13)
45#define SPEAR320_UART2_IRQ_MASK (1 << 14)
46#define SPEAR320_SSP1_IRQ_MASK (1 << 15)
47#define SPEAR320_SSP2_IRQ_MASK (1 << 16)
48#define SPEAR320_SMII0_IRQ_MASK (1 << 17)
49#define SPEAR320_MII1_SMII1_IRQ_MASK (1 << 18)
50#define SPEAR320_WAKEUP_SMII0_IRQ_MASK (1 << 19)
51#define SPEAR320_WAKEUP_MII1_SMII1_IRQ_MASK (1 << 20)
52#define SPEAR320_I2C1_IRQ_MASK (1 << 21)
53
54#define SPEAR320_SHIRQ_RAS1_MASK 0x000380
55#define SPEAR320_SHIRQ_RAS3_MASK 0x000007
56#define SPEAR320_SHIRQ_INTRCOMM_RAS_MASK 0x3FF800
57
58/* SPEAr320 Virtual irq definitions */
59/* IRQs sharing IRQ_GEN_RAS_1 */
60#define SPEAR320_VIRQ_EMI (SPEAR3XX_VIRQ_START + 0)
61#define SPEAR320_VIRQ_CLCD (SPEAR3XX_VIRQ_START + 1)
62#define SPEAR320_VIRQ_SPP (SPEAR3XX_VIRQ_START + 2)
63
64/* IRQs sharing IRQ_GEN_RAS_2 */
65#define SPEAR320_IRQ_SDHCI SPEAR3XX_IRQ_GEN_RAS_2
66
67/* IRQs sharing IRQ_GEN_RAS_3 */
68#define SPEAR320_VIRQ_PLGPIO (SPEAR3XX_VIRQ_START + 3)
69#define SPEAR320_VIRQ_I2S_PLAY (SPEAR3XX_VIRQ_START + 4)
70#define SPEAR320_VIRQ_I2S_REC (SPEAR3XX_VIRQ_START + 5)
71
72/* IRQs sharing IRQ_INTRCOMM_RAS_ARM */
73#define SPEAR320_VIRQ_CANU (SPEAR3XX_VIRQ_START + 6)
74#define SPEAR320_VIRQ_CANL (SPEAR3XX_VIRQ_START + 7)
75#define SPEAR320_VIRQ_UART1 (SPEAR3XX_VIRQ_START + 8)
76#define SPEAR320_VIRQ_UART2 (SPEAR3XX_VIRQ_START + 9)
77#define SPEAR320_VIRQ_SSP1 (SPEAR3XX_VIRQ_START + 10)
78#define SPEAR320_VIRQ_SSP2 (SPEAR3XX_VIRQ_START + 11)
79#define SPEAR320_VIRQ_SMII0 (SPEAR3XX_VIRQ_START + 12)
80#define SPEAR320_VIRQ_MII1_SMII1 (SPEAR3XX_VIRQ_START + 13)
81#define SPEAR320_VIRQ_WAKEUP_SMII0 (SPEAR3XX_VIRQ_START + 14)
82#define SPEAR320_VIRQ_WAKEUP_MII1_SMII1 (SPEAR3XX_VIRQ_START + 15)
83#define SPEAR320_VIRQ_I2C1 (SPEAR3XX_VIRQ_START + 16)
84
85/* spear3xx shared irq */
86static struct shirq_dev_config shirq_ras1_config[] = {
87 {
88 .virq = SPEAR320_VIRQ_EMI,
89 .status_mask = SPEAR320_EMI_IRQ_MASK,
90 .clear_mask = SPEAR320_EMI_IRQ_MASK,
91 }, {
92 .virq = SPEAR320_VIRQ_CLCD,
93 .status_mask = SPEAR320_CLCD_IRQ_MASK,
94 .clear_mask = SPEAR320_CLCD_IRQ_MASK,
95 }, {
96 .virq = SPEAR320_VIRQ_SPP,
97 .status_mask = SPEAR320_SPP_IRQ_MASK,
98 .clear_mask = SPEAR320_SPP_IRQ_MASK,
99 },
100};
101
102static struct spear_shirq shirq_ras1 = {
103 .irq = SPEAR3XX_IRQ_GEN_RAS_1,
104 .dev_config = shirq_ras1_config,
105 .dev_count = ARRAY_SIZE(shirq_ras1_config),
106 .regs = {
107 .enb_reg = -1,
108 .status_reg = SPEAR320_INT_STS_MASK_REG,
109 .status_reg_mask = SPEAR320_SHIRQ_RAS1_MASK,
110 .clear_reg = SPEAR320_INT_CLR_MASK_REG,
111 .reset_to_clear = 1,
112 },
113};
114
115static struct shirq_dev_config shirq_ras3_config[] = {
116 {
117 .virq = SPEAR320_VIRQ_PLGPIO,
118 .enb_mask = SPEAR320_GPIO_IRQ_MASK,
119 .status_mask = SPEAR320_GPIO_IRQ_MASK,
120 .clear_mask = SPEAR320_GPIO_IRQ_MASK,
121 }, {
122 .virq = SPEAR320_VIRQ_I2S_PLAY,
123 .enb_mask = SPEAR320_I2S_PLAY_IRQ_MASK,
124 .status_mask = SPEAR320_I2S_PLAY_IRQ_MASK,
125 .clear_mask = SPEAR320_I2S_PLAY_IRQ_MASK,
126 }, {
127 .virq = SPEAR320_VIRQ_I2S_REC,
128 .enb_mask = SPEAR320_I2S_REC_IRQ_MASK,
129 .status_mask = SPEAR320_I2S_REC_IRQ_MASK,
130 .clear_mask = SPEAR320_I2S_REC_IRQ_MASK,
131 },
132};
133
134static struct spear_shirq shirq_ras3 = {
135 .irq = SPEAR3XX_IRQ_GEN_RAS_3,
136 .dev_config = shirq_ras3_config,
137 .dev_count = ARRAY_SIZE(shirq_ras3_config),
138 .regs = {
139 .enb_reg = SPEAR320_INT_ENB_MASK_REG,
140 .reset_to_enb = 1,
141 .status_reg = SPEAR320_INT_STS_MASK_REG,
142 .status_reg_mask = SPEAR320_SHIRQ_RAS3_MASK,
143 .clear_reg = SPEAR320_INT_CLR_MASK_REG,
144 .reset_to_clear = 1,
145 },
146};
147
148static struct shirq_dev_config shirq_intrcomm_ras_config[] = {
149 {
150 .virq = SPEAR320_VIRQ_CANU,
151 .status_mask = SPEAR320_CAN_U_IRQ_MASK,
152 .clear_mask = SPEAR320_CAN_U_IRQ_MASK,
153 }, {
154 .virq = SPEAR320_VIRQ_CANL,
155 .status_mask = SPEAR320_CAN_L_IRQ_MASK,
156 .clear_mask = SPEAR320_CAN_L_IRQ_MASK,
157 }, {
158 .virq = SPEAR320_VIRQ_UART1,
159 .status_mask = SPEAR320_UART1_IRQ_MASK,
160 .clear_mask = SPEAR320_UART1_IRQ_MASK,
161 }, {
162 .virq = SPEAR320_VIRQ_UART2,
163 .status_mask = SPEAR320_UART2_IRQ_MASK,
164 .clear_mask = SPEAR320_UART2_IRQ_MASK,
165 }, {
166 .virq = SPEAR320_VIRQ_SSP1,
167 .status_mask = SPEAR320_SSP1_IRQ_MASK,
168 .clear_mask = SPEAR320_SSP1_IRQ_MASK,
169 }, {
170 .virq = SPEAR320_VIRQ_SSP2,
171 .status_mask = SPEAR320_SSP2_IRQ_MASK,
172 .clear_mask = SPEAR320_SSP2_IRQ_MASK,
173 }, {
174 .virq = SPEAR320_VIRQ_SMII0,
175 .status_mask = SPEAR320_SMII0_IRQ_MASK,
176 .clear_mask = SPEAR320_SMII0_IRQ_MASK,
177 }, {
178 .virq = SPEAR320_VIRQ_MII1_SMII1,
179 .status_mask = SPEAR320_MII1_SMII1_IRQ_MASK,
180 .clear_mask = SPEAR320_MII1_SMII1_IRQ_MASK,
181 }, {
182 .virq = SPEAR320_VIRQ_WAKEUP_SMII0,
183 .status_mask = SPEAR320_WAKEUP_SMII0_IRQ_MASK,
184 .clear_mask = SPEAR320_WAKEUP_SMII0_IRQ_MASK,
185 }, {
186 .virq = SPEAR320_VIRQ_WAKEUP_MII1_SMII1,
187 .status_mask = SPEAR320_WAKEUP_MII1_SMII1_IRQ_MASK,
188 .clear_mask = SPEAR320_WAKEUP_MII1_SMII1_IRQ_MASK,
189 }, {
190 .virq = SPEAR320_VIRQ_I2C1,
191 .status_mask = SPEAR320_I2C1_IRQ_MASK,
192 .clear_mask = SPEAR320_I2C1_IRQ_MASK,
193 },
194};
195
196static struct spear_shirq shirq_intrcomm_ras = {
197 .irq = SPEAR3XX_IRQ_INTRCOMM_RAS_ARM,
198 .dev_config = shirq_intrcomm_ras_config,
199 .dev_count = ARRAY_SIZE(shirq_intrcomm_ras_config),
200 .regs = {
201 .enb_reg = -1,
202 .status_reg = SPEAR320_INT_STS_MASK_REG,
203 .status_reg_mask = SPEAR320_SHIRQ_INTRCOMM_RAS_MASK,
204 .clear_reg = SPEAR320_INT_CLR_MASK_REG,
205 .reset_to_clear = 1,
206 },
207};
208
209/* DMAC platform data's slave info */ 30/* DMAC platform data's slave info */
210struct pl08x_channel_data spear320_dma_info[] = { 31struct pl08x_channel_data spear320_dma_info[] = {
211 { 32 {
@@ -416,36 +237,11 @@ static struct of_dev_auxdata spear320_auxdata_lookup[] __initdata = {
416 237
417static void __init spear320_dt_init(void) 238static void __init spear320_dt_init(void)
418{ 239{
419 void __iomem *base;
420 int ret;
421
422 pl080_plat_data.slave_channels = spear320_dma_info; 240 pl080_plat_data.slave_channels = spear320_dma_info;
423 pl080_plat_data.num_slave_channels = ARRAY_SIZE(spear320_dma_info); 241 pl080_plat_data.num_slave_channels = ARRAY_SIZE(spear320_dma_info);
424 242
425 of_platform_populate(NULL, of_default_bus_match_table, 243 of_platform_populate(NULL, of_default_bus_match_table,
426 spear320_auxdata_lookup, NULL); 244 spear320_auxdata_lookup, NULL);
427
428 /* shared irq registration */
429 base = ioremap(SPEAR320_SOC_CONFIG_BASE, SZ_4K);
430 if (base) {
431 /* shirq 1 */
432 shirq_ras1.regs.base = base;
433 ret = spear_shirq_register(&shirq_ras1);
434 if (ret)
435 pr_err("Error registering Shared IRQ 1\n");
436
437 /* shirq 3 */
438 shirq_ras3.regs.base = base;
439 ret = spear_shirq_register(&shirq_ras3);
440 if (ret)
441 pr_err("Error registering Shared IRQ 3\n");
442
443 /* shirq 4 */
444 shirq_intrcomm_ras.regs.base = base;
445 ret = spear_shirq_register(&shirq_intrcomm_ras);
446 if (ret)
447 pr_err("Error registering Shared IRQ 4\n");
448 }
449} 245}
450 246
451static const char * const spear320_dt_board_compat[] = { 247static const char * const spear320_dt_board_compat[] = {
diff --git a/arch/arm/mach-spear3xx/spear3xx.c b/arch/arm/mach-spear3xx/spear3xx.c
index 98144baf888..f1aaf5b168b 100644
--- a/arch/arm/mach-spear3xx/spear3xx.c
+++ b/arch/arm/mach-spear3xx/spear3xx.c
@@ -20,6 +20,7 @@
20#include <asm/hardware/pl080.h> 20#include <asm/hardware/pl080.h>
21#include <asm/hardware/vic.h> 21#include <asm/hardware/vic.h>
22#include <plat/pl080.h> 22#include <plat/pl080.h>
23#include <plat/shirq.h>
23#include <mach/generic.h> 24#include <mach/generic.h>
24#include <mach/spear.h> 25#include <mach/spear.h>
25 26
@@ -121,6 +122,9 @@ struct sys_timer spear3xx_timer = {
121 122
122static const struct of_device_id vic_of_match[] __initconst = { 123static const struct of_device_id vic_of_match[] __initconst = {
123 { .compatible = "arm,pl190-vic", .data = vic_of_init, }, 124 { .compatible = "arm,pl190-vic", .data = vic_of_init, },
125 { .compatible = "st,spear300-shirq", .data = spear300_shirq_of_init, },
126 { .compatible = "st,spear310-shirq", .data = spear310_shirq_of_init, },
127 { .compatible = "st,spear320-shirq", .data = spear320_shirq_of_init, },
124 { /* Sentinel */ } 128 { /* Sentinel */ }
125}; 129};
126 130
diff --git a/arch/arm/plat-spear/include/plat/shirq.h b/arch/arm/plat-spear/include/plat/shirq.h
index 88a7fbd2479..c51b355f00d 100644
--- a/arch/arm/plat-spear/include/plat/shirq.h
+++ b/arch/arm/plat-spear/include/plat/shirq.h
@@ -18,24 +18,8 @@
18#include <linux/types.h> 18#include <linux/types.h>
19 19
20/* 20/*
21 * struct shirq_dev_config: shared irq device configuration
22 *
23 * virq: virtual irq number of device
24 * enb_mask: enable mask of device
25 * status_mask: status mask of device
26 * clear_mask: clear mask of device
27 */
28struct shirq_dev_config {
29 u32 virq;
30 u32 enb_mask;
31 u32 status_mask;
32 u32 clear_mask;
33};
34
35/*
36 * struct shirq_regs: shared irq register configuration 21 * struct shirq_regs: shared irq register configuration
37 * 22 *
38 * base: base address of shared irq register
39 * enb_reg: enable register offset 23 * enb_reg: enable register offset
40 * reset_to_enb: val 1 indicates, we need to clear bit for enabling interrupt 24 * reset_to_enb: val 1 indicates, we need to clear bit for enabling interrupt
41 * status_reg: status register offset 25 * status_reg: status register offset
@@ -44,11 +28,9 @@ struct shirq_dev_config {
44 * reset_to_clear: val 1 indicates, we need to clear bit for clearing interrupt 28 * reset_to_clear: val 1 indicates, we need to clear bit for clearing interrupt
45 */ 29 */
46struct shirq_regs { 30struct shirq_regs {
47 void __iomem *base;
48 u32 enb_reg; 31 u32 enb_reg;
49 u32 reset_to_enb; 32 u32 reset_to_enb;
50 u32 status_reg; 33 u32 status_reg;
51 u32 status_reg_mask;
52 u32 clear_reg; 34 u32 clear_reg;
53 u32 reset_to_clear; 35 u32 reset_to_clear;
54}; 36};
@@ -57,17 +39,28 @@ struct shirq_regs {
57 * struct spear_shirq: shared irq structure 39 * struct spear_shirq: shared irq structure
58 * 40 *
59 * irq: hardware irq number 41 * irq: hardware irq number
60 * dev_config: array of device config structures which are using "irq" line 42 * irq_base: base irq in linux domain
61 * dev_count: size of dev_config array 43 * irq_nr: no. of shared interrupts in a particular block
44 * irq_bit_off: starting bit offset in the status register
45 * invalid_irq: irq group is currently disabled
46 * base: base address of shared irq register
62 * regs: register configuration for shared irq block 47 * regs: register configuration for shared irq block
63 */ 48 */
64struct spear_shirq { 49struct spear_shirq {
65 u32 irq; 50 u32 irq;
66 struct shirq_dev_config *dev_config; 51 u32 irq_base;
67 u32 dev_count; 52 u32 irq_nr;
53 u32 irq_bit_off;
54 int invalid_irq;
55 void __iomem *base;
68 struct shirq_regs regs; 56 struct shirq_regs regs;
69}; 57};
70 58
71int spear_shirq_register(struct spear_shirq *shirq); 59int __init spear300_shirq_of_init(struct device_node *np,
60 struct device_node *parent);
61int __init spear310_shirq_of_init(struct device_node *np,
62 struct device_node *parent);
63int __init spear320_shirq_of_init(struct device_node *np,
64 struct device_node *parent);
72 65
73#endif /* __PLAT_SHIRQ_H */ 66#endif /* __PLAT_SHIRQ_H */
diff --git a/arch/arm/plat-spear/shirq.c b/arch/arm/plat-spear/shirq.c
index 853e891e118..955c7249a5c 100644
--- a/arch/arm/plat-spear/shirq.c
+++ b/arch/arm/plat-spear/shirq.c
@@ -10,56 +10,182 @@
10 * License version 2. This program is licensed "as is" without any 10 * License version 2. This program is licensed "as is" without any
11 * warranty of any kind, whether express or implied. 11 * warranty of any kind, whether express or implied.
12 */ 12 */
13#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
13 14
14#include <linux/err.h> 15#include <linux/err.h>
16#include <linux/export.h>
17#include <linux/interrupt.h>
15#include <linux/io.h> 18#include <linux/io.h>
16#include <linux/irq.h> 19#include <linux/irq.h>
20#include <linux/irqdomain.h>
21#include <linux/of.h>
22#include <linux/of_address.h>
23#include <linux/of_irq.h>
17#include <linux/spinlock.h> 24#include <linux/spinlock.h>
18#include <plat/shirq.h> 25#include <plat/shirq.h>
19 26
20struct spear_shirq *shirq;
21static DEFINE_SPINLOCK(lock); 27static DEFINE_SPINLOCK(lock);
22 28
23static void shirq_irq_mask(struct irq_data *d) 29/* spear300 shared irq registers offsets and masks */
30#define SPEAR300_INT_ENB_MASK_REG 0x54
31#define SPEAR300_INT_STS_MASK_REG 0x58
32
33static struct spear_shirq spear300_shirq_ras1 = {
34 .irq_nr = 9,
35 .irq_bit_off = 0,
36 .regs = {
37 .enb_reg = SPEAR300_INT_ENB_MASK_REG,
38 .status_reg = SPEAR300_INT_STS_MASK_REG,
39 .clear_reg = -1,
40 },
41};
42
43static struct spear_shirq *spear300_shirq_blocks[] = {
44 &spear300_shirq_ras1,
45};
46
47/* spear310 shared irq registers offsets and masks */
48#define SPEAR310_INT_STS_MASK_REG 0x04
49
50static struct spear_shirq spear310_shirq_ras1 = {
51 .irq_nr = 8,
52 .irq_bit_off = 0,
53 .regs = {
54 .enb_reg = -1,
55 .status_reg = SPEAR310_INT_STS_MASK_REG,
56 .clear_reg = -1,
57 },
58};
59
60static struct spear_shirq spear310_shirq_ras2 = {
61 .irq_nr = 5,
62 .irq_bit_off = 8,
63 .regs = {
64 .enb_reg = -1,
65 .status_reg = SPEAR310_INT_STS_MASK_REG,
66 .clear_reg = -1,
67 },
68};
69
70static struct spear_shirq spear310_shirq_ras3 = {
71 .irq_nr = 1,
72 .irq_bit_off = 13,
73 .regs = {
74 .enb_reg = -1,
75 .status_reg = SPEAR310_INT_STS_MASK_REG,
76 .clear_reg = -1,
77 },
78};
79
80static struct spear_shirq spear310_shirq_intrcomm_ras = {
81 .irq_nr = 3,
82 .irq_bit_off = 14,
83 .regs = {
84 .enb_reg = -1,
85 .status_reg = SPEAR310_INT_STS_MASK_REG,
86 .clear_reg = -1,
87 },
88};
89
90static struct spear_shirq *spear310_shirq_blocks[] = {
91 &spear310_shirq_ras1,
92 &spear310_shirq_ras2,
93 &spear310_shirq_ras3,
94 &spear310_shirq_intrcomm_ras,
95};
96
97/* spear320 shared irq registers offsets and masks */
98#define SPEAR320_INT_STS_MASK_REG 0x04
99#define SPEAR320_INT_CLR_MASK_REG 0x04
100#define SPEAR320_INT_ENB_MASK_REG 0x08
101
102static struct spear_shirq spear320_shirq_ras1 = {
103 .irq_nr = 3,
104 .irq_bit_off = 7,
105 .regs = {
106 .enb_reg = -1,
107 .status_reg = SPEAR320_INT_STS_MASK_REG,
108 .clear_reg = SPEAR320_INT_CLR_MASK_REG,
109 .reset_to_clear = 1,
110 },
111};
112
113static struct spear_shirq spear320_shirq_ras2 = {
114 .irq_nr = 1,
115 .irq_bit_off = 10,
116 .regs = {
117 .enb_reg = -1,
118 .status_reg = SPEAR320_INT_STS_MASK_REG,
119 .clear_reg = SPEAR320_INT_CLR_MASK_REG,
120 .reset_to_clear = 1,
121 },
122};
123
124static struct spear_shirq spear320_shirq_ras3 = {
125 .irq_nr = 3,
126 .irq_bit_off = 0,
127 .invalid_irq = 1,
128 .regs = {
129 .enb_reg = SPEAR320_INT_ENB_MASK_REG,
130 .reset_to_enb = 1,
131 .status_reg = SPEAR320_INT_STS_MASK_REG,
132 .clear_reg = SPEAR320_INT_CLR_MASK_REG,
133 .reset_to_clear = 1,
134 },
135};
136
137static struct spear_shirq spear320_shirq_intrcomm_ras = {
138 .irq_nr = 11,
139 .irq_bit_off = 11,
140 .regs = {
141 .enb_reg = -1,
142 .status_reg = SPEAR320_INT_STS_MASK_REG,
143 .clear_reg = SPEAR320_INT_CLR_MASK_REG,
144 .reset_to_clear = 1,
145 },
146};
147
148static struct spear_shirq *spear320_shirq_blocks[] = {
149 &spear320_shirq_ras3,
150 &spear320_shirq_ras1,
151 &spear320_shirq_ras2,
152 &spear320_shirq_intrcomm_ras,
153};
154
155static void shirq_irq_mask_unmask(struct irq_data *d, bool mask)
24{ 156{
25 struct spear_shirq *shirq = irq_data_get_irq_chip_data(d); 157 struct spear_shirq *shirq = irq_data_get_irq_chip_data(d);
26 u32 val, id = d->irq - shirq->dev_config[0].virq; 158 u32 val, offset = d->irq - shirq->irq_base;
27 unsigned long flags; 159 unsigned long flags;
28 160
29 if ((shirq->regs.enb_reg == -1) || shirq->dev_config[id].enb_mask == -1) 161 if (shirq->regs.enb_reg == -1)
30 return; 162 return;
31 163
32 spin_lock_irqsave(&lock, flags); 164 spin_lock_irqsave(&lock, flags);
33 val = readl(shirq->regs.base + shirq->regs.enb_reg); 165 val = readl(shirq->base + shirq->regs.enb_reg);
34 if (shirq->regs.reset_to_enb) 166
35 val |= shirq->dev_config[id].enb_mask; 167 if (mask ^ shirq->regs.reset_to_enb)
168 val &= ~(0x1 << shirq->irq_bit_off << offset);
36 else 169 else
37 val &= ~(shirq->dev_config[id].enb_mask); 170 val |= 0x1 << shirq->irq_bit_off << offset;
38 writel(val, shirq->regs.base + shirq->regs.enb_reg); 171
172 writel(val, shirq->base + shirq->regs.enb_reg);
39 spin_unlock_irqrestore(&lock, flags); 173 spin_unlock_irqrestore(&lock, flags);
174
40} 175}
41 176
42static void shirq_irq_unmask(struct irq_data *d) 177static void shirq_irq_mask(struct irq_data *d)
43{ 178{
44 struct spear_shirq *shirq = irq_data_get_irq_chip_data(d); 179 shirq_irq_mask_unmask(d, 1);
45 u32 val, id = d->irq - shirq->dev_config[0].virq; 180}
46 unsigned long flags;
47
48 if ((shirq->regs.enb_reg == -1) || shirq->dev_config[id].enb_mask == -1)
49 return;
50 181
51 spin_lock_irqsave(&lock, flags); 182static void shirq_irq_unmask(struct irq_data *d)
52 val = readl(shirq->regs.base + shirq->regs.enb_reg); 183{
53 if (shirq->regs.reset_to_enb) 184 shirq_irq_mask_unmask(d, 0);
54 val &= ~(shirq->dev_config[id].enb_mask);
55 else
56 val |= shirq->dev_config[id].enb_mask;
57 writel(val, shirq->regs.base + shirq->regs.enb_reg);
58 spin_unlock_irqrestore(&lock, flags);
59} 185}
60 186
61static struct irq_chip shirq_chip = { 187static struct irq_chip shirq_chip = {
62 .name = "spear_shirq", 188 .name = "spear-shirq",
63 .irq_ack = shirq_irq_mask, 189 .irq_ack = shirq_irq_mask,
64 .irq_mask = shirq_irq_mask, 190 .irq_mask = shirq_irq_mask,
65 .irq_unmask = shirq_irq_unmask, 191 .irq_unmask = shirq_irq_unmask,
@@ -67,52 +193,123 @@ static struct irq_chip shirq_chip = {
67 193
68static void shirq_handler(unsigned irq, struct irq_desc *desc) 194static void shirq_handler(unsigned irq, struct irq_desc *desc)
69{ 195{
70 u32 i, val, mask; 196 u32 i, j, val, mask, tmp;
197 struct irq_chip *chip;
71 struct spear_shirq *shirq = irq_get_handler_data(irq); 198 struct spear_shirq *shirq = irq_get_handler_data(irq);
72 199
73 desc->irq_data.chip->irq_ack(&desc->irq_data); 200 chip = irq_get_chip(irq);
74 while ((val = readl(shirq->regs.base + shirq->regs.status_reg) & 201 chip->irq_ack(&desc->irq_data);
75 shirq->regs.status_reg_mask)) { 202
76 for (i = 0; (i < shirq->dev_count) && val; i++) { 203 mask = ((0x1 << shirq->irq_nr) - 1) << shirq->irq_bit_off;
77 if (!(shirq->dev_config[i].status_mask & val)) 204 while ((val = readl(shirq->base + shirq->regs.status_reg) &
205 mask)) {
206
207 val >>= shirq->irq_bit_off;
208 for (i = 0, j = 1; i < shirq->irq_nr; i++, j <<= 1) {
209
210 if (!(j & val))
78 continue; 211 continue;
79 212
80 generic_handle_irq(shirq->dev_config[i].virq); 213 generic_handle_irq(shirq->irq_base + i);
81 214
82 /* clear interrupt */ 215 /* clear interrupt */
83 val &= ~shirq->dev_config[i].status_mask; 216 if (shirq->regs.clear_reg == -1)
84 if ((shirq->regs.clear_reg == -1) ||
85 shirq->dev_config[i].clear_mask == -1)
86 continue; 217 continue;
87 mask = readl(shirq->regs.base + shirq->regs.clear_reg); 218
219 tmp = readl(shirq->base + shirq->regs.clear_reg);
88 if (shirq->regs.reset_to_clear) 220 if (shirq->regs.reset_to_clear)
89 mask &= ~shirq->dev_config[i].clear_mask; 221 tmp &= ~(j << shirq->irq_bit_off);
90 else 222 else
91 mask |= shirq->dev_config[i].clear_mask; 223 tmp |= (j << shirq->irq_bit_off);
92 writel(mask, shirq->regs.base + shirq->regs.clear_reg); 224 writel(tmp, shirq->base + shirq->regs.clear_reg);
93 } 225 }
94 } 226 }
95 desc->irq_data.chip->irq_unmask(&desc->irq_data); 227 chip->irq_unmask(&desc->irq_data);
96} 228}
97 229
98int spear_shirq_register(struct spear_shirq *shirq) 230static void __init spear_shirq_register(struct spear_shirq *shirq)
99{ 231{
100 int i; 232 int i;
101 233
102 if (!shirq || !shirq->dev_config || !shirq->regs.base) 234 if (shirq->invalid_irq)
103 return -EFAULT; 235 return;
104
105 if (!shirq->dev_count)
106 return -EINVAL;
107 236
108 irq_set_chained_handler(shirq->irq, shirq_handler); 237 irq_set_chained_handler(shirq->irq, shirq_handler);
109 for (i = 0; i < shirq->dev_count; i++) { 238 for (i = 0; i < shirq->irq_nr; i++) {
110 irq_set_chip_and_handler(shirq->dev_config[i].virq, 239 irq_set_chip_and_handler(shirq->irq_base + i,
111 &shirq_chip, handle_simple_irq); 240 &shirq_chip, handle_simple_irq);
112 set_irq_flags(shirq->dev_config[i].virq, IRQF_VALID); 241 set_irq_flags(shirq->irq_base + i, IRQF_VALID);
113 irq_set_chip_data(shirq->dev_config[i].virq, shirq); 242 irq_set_chip_data(shirq->irq_base + i, shirq);
114 } 243 }
115 244
116 irq_set_handler_data(shirq->irq, shirq); 245 irq_set_handler_data(shirq->irq, shirq);
246}
247
248static int __init shirq_init(struct spear_shirq **shirq_blocks, int block_nr,
249 struct device_node *np)
250{
251 int i, irq_base, hwirq = 0, irq_nr = 0;
252 static struct irq_domain *shirq_domain;
253 void __iomem *base;
254
255 base = of_iomap(np, 0);
256 if (!base) {
257 pr_err("%s: failed to map shirq registers\n", __func__);
258 return -ENXIO;
259 }
260
261 for (i = 0; i < block_nr; i++)
262 irq_nr += shirq_blocks[i]->irq_nr;
263
264 irq_base = irq_alloc_descs(-1, 0, irq_nr, 0);
265 if (IS_ERR_VALUE(irq_base)) {
266 pr_err("%s: irq desc alloc failed\n", __func__);
267 goto err_unmap;
268 }
269
270 shirq_domain = irq_domain_add_legacy(np, irq_nr, irq_base, 0,
271 &irq_domain_simple_ops, NULL);
272 if (WARN_ON(!shirq_domain)) {
273 pr_warn("%s: irq domain init failed\n", __func__);
274 goto err_free_desc;
275 }
276
277 for (i = 0; i < block_nr; i++) {
278 shirq_blocks[i]->base = base;
279 shirq_blocks[i]->irq_base = irq_find_mapping(shirq_domain,
280 hwirq);
281 shirq_blocks[i]->irq = irq_of_parse_and_map(np, i);
282
283 spear_shirq_register(shirq_blocks[i]);
284 hwirq += shirq_blocks[i]->irq_nr;
285 }
286
117 return 0; 287 return 0;
288
289err_free_desc:
290 irq_free_descs(irq_base, irq_nr);
291err_unmap:
292 iounmap(base);
293 return -ENXIO;
294}
295
296int __init spear300_shirq_of_init(struct device_node *np,
297 struct device_node *parent)
298{
299 return shirq_init(spear300_shirq_blocks,
300 ARRAY_SIZE(spear300_shirq_blocks), np);
301}
302
303int __init spear310_shirq_of_init(struct device_node *np,
304 struct device_node *parent)
305{
306 return shirq_init(spear310_shirq_blocks,
307 ARRAY_SIZE(spear310_shirq_blocks), np);
308}
309
310int __init spear320_shirq_of_init(struct device_node *np,
311 struct device_node *parent)
312{
313 return shirq_init(spear320_shirq_blocks,
314 ARRAY_SIZE(spear320_shirq_blocks), np);
118} 315}