diff options
Diffstat (limited to 'drivers/irqchip')
-rw-r--r-- | drivers/irqchip/Kconfig | 7 | ||||
-rw-r--r-- | drivers/irqchip/Makefile | 4 | ||||
-rw-r--r-- | drivers/irqchip/irq-armada-370-xp.c | 2 | ||||
-rw-r--r-- | drivers/irqchip/irq-atmel-aic-common.c | 26 | ||||
-rw-r--r-- | drivers/irqchip/irq-atmel-aic-common.h | 2 | ||||
-rw-r--r-- | drivers/irqchip/irq-atmel-aic.c | 66 | ||||
-rw-r--r-- | drivers/irqchip/irq-atmel-aic5.c | 65 | ||||
-rw-r--r-- | drivers/irqchip/irq-bcm7120-l2.c | 174 | ||||
-rw-r--r-- | drivers/irqchip/irq-brcmstb-l2.c | 41 | ||||
-rw-r--r-- | drivers/irqchip/irq-dw-apb-ictl.c | 32 | ||||
-rw-r--r-- | drivers/irqchip/irq-hip04.c | 3 | ||||
-rw-r--r-- | drivers/irqchip/irq-sunxi-nmi.c | 4 | ||||
-rw-r--r-- | drivers/irqchip/irq-tb10x.c | 4 |
13 files changed, 271 insertions, 159 deletions
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index b21f12f1766d..9efe5f10f97b 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig | |||
@@ -48,14 +48,19 @@ config ATMEL_AIC5_IRQ | |||
48 | select MULTI_IRQ_HANDLER | 48 | select MULTI_IRQ_HANDLER |
49 | select SPARSE_IRQ | 49 | select SPARSE_IRQ |
50 | 50 | ||
51 | config BCM7120_L2_IRQ | ||
52 | bool | ||
53 | select GENERIC_IRQ_CHIP | ||
54 | select IRQ_DOMAIN | ||
55 | |||
51 | config BRCMSTB_L2_IRQ | 56 | config BRCMSTB_L2_IRQ |
52 | bool | 57 | bool |
53 | depends on ARM | ||
54 | select GENERIC_IRQ_CHIP | 58 | select GENERIC_IRQ_CHIP |
55 | select IRQ_DOMAIN | 59 | select IRQ_DOMAIN |
56 | 60 | ||
57 | config DW_APB_ICTL | 61 | config DW_APB_ICTL |
58 | bool | 62 | bool |
63 | select GENERIC_IRQ_CHIP | ||
59 | select IRQ_DOMAIN | 64 | select IRQ_DOMAIN |
60 | 65 | ||
61 | config IMGPDC_IRQ | 66 | config IMGPDC_IRQ |
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index 173bb5fa2cc9..f0909d05eae3 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile | |||
@@ -35,6 +35,6 @@ obj-$(CONFIG_TB10X_IRQC) += irq-tb10x.o | |||
35 | obj-$(CONFIG_XTENSA) += irq-xtensa-pic.o | 35 | obj-$(CONFIG_XTENSA) += irq-xtensa-pic.o |
36 | obj-$(CONFIG_XTENSA_MX) += irq-xtensa-mx.o | 36 | obj-$(CONFIG_XTENSA_MX) += irq-xtensa-mx.o |
37 | obj-$(CONFIG_IRQ_CROSSBAR) += irq-crossbar.o | 37 | obj-$(CONFIG_IRQ_CROSSBAR) += irq-crossbar.o |
38 | obj-$(CONFIG_BRCMSTB_L2_IRQ) += irq-brcmstb-l2.o \ | 38 | obj-$(CONFIG_BCM7120_L2_IRQ) += irq-bcm7120-l2.o |
39 | irq-bcm7120-l2.o | 39 | obj-$(CONFIG_BRCMSTB_L2_IRQ) += irq-brcmstb-l2.o |
40 | obj-$(CONFIG_KEYSTONE_IRQ) += irq-keystone.o | 40 | obj-$(CONFIG_KEYSTONE_IRQ) += irq-keystone.o |
diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c index b907550ae9a5..a3fd2b37ddb6 100644 --- a/drivers/irqchip/irq-armada-370-xp.c +++ b/drivers/irqchip/irq-armada-370-xp.c | |||
@@ -268,7 +268,7 @@ static int armada_xp_set_affinity(struct irq_data *d, | |||
268 | writel(reg, main_int_base + ARMADA_370_XP_INT_SOURCE_CTL(hwirq)); | 268 | writel(reg, main_int_base + ARMADA_370_XP_INT_SOURCE_CTL(hwirq)); |
269 | raw_spin_unlock(&irq_controller_lock); | 269 | raw_spin_unlock(&irq_controller_lock); |
270 | 270 | ||
271 | return 0; | 271 | return IRQ_SET_MASK_OK; |
272 | } | 272 | } |
273 | #endif | 273 | #endif |
274 | 274 | ||
diff --git a/drivers/irqchip/irq-atmel-aic-common.c b/drivers/irqchip/irq-atmel-aic-common.c index cc4f9d80122e..d111ac779c40 100644 --- a/drivers/irqchip/irq-atmel-aic-common.c +++ b/drivers/irqchip/irq-atmel-aic-common.c | |||
@@ -167,6 +167,32 @@ void __init aic_common_rtc_irq_fixup(struct device_node *root) | |||
167 | iounmap(regs); | 167 | iounmap(regs); |
168 | } | 168 | } |
169 | 169 | ||
170 | #define AT91_RTT_MR 0x00 /* Real-time Mode Register */ | ||
171 | #define AT91_RTT_ALMIEN (1 << 16) /* Alarm Interrupt Enable */ | ||
172 | #define AT91_RTT_RTTINCIEN (1 << 17) /* Real Time Timer Increment Interrupt Enable */ | ||
173 | |||
174 | void __init aic_common_rtt_irq_fixup(struct device_node *root) | ||
175 | { | ||
176 | struct device_node *np; | ||
177 | void __iomem *regs; | ||
178 | |||
179 | /* | ||
180 | * The at91sam9263 SoC has 2 instances of the RTT block, hence we | ||
181 | * iterate over the DT to find each occurrence. | ||
182 | */ | ||
183 | for_each_compatible_node(np, NULL, "atmel,at91sam9260-rtt") { | ||
184 | regs = of_iomap(np, 0); | ||
185 | if (!regs) | ||
186 | continue; | ||
187 | |||
188 | writel(readl(regs + AT91_RTT_MR) & | ||
189 | ~(AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN), | ||
190 | regs + AT91_RTT_MR); | ||
191 | |||
192 | iounmap(regs); | ||
193 | } | ||
194 | } | ||
195 | |||
170 | void __init aic_common_irq_fixup(const struct of_device_id *matches) | 196 | void __init aic_common_irq_fixup(const struct of_device_id *matches) |
171 | { | 197 | { |
172 | struct device_node *root = of_find_node_by_path("/"); | 198 | struct device_node *root = of_find_node_by_path("/"); |
diff --git a/drivers/irqchip/irq-atmel-aic-common.h b/drivers/irqchip/irq-atmel-aic-common.h index 90aa00e918d6..603f0a9d5411 100644 --- a/drivers/irqchip/irq-atmel-aic-common.h +++ b/drivers/irqchip/irq-atmel-aic-common.h | |||
@@ -34,6 +34,8 @@ struct irq_domain *__init aic_common_of_init(struct device_node *node, | |||
34 | 34 | ||
35 | void __init aic_common_rtc_irq_fixup(struct device_node *root); | 35 | void __init aic_common_rtc_irq_fixup(struct device_node *root); |
36 | 36 | ||
37 | void __init aic_common_rtt_irq_fixup(struct device_node *root); | ||
38 | |||
37 | void __init aic_common_irq_fixup(const struct of_device_id *matches); | 39 | void __init aic_common_irq_fixup(const struct of_device_id *matches); |
38 | 40 | ||
39 | #endif /* __IRQ_ATMEL_AIC_COMMON_H */ | 41 | #endif /* __IRQ_ATMEL_AIC_COMMON_H */ |
diff --git a/drivers/irqchip/irq-atmel-aic.c b/drivers/irqchip/irq-atmel-aic.c index 9a2cf3c1a3a5..dae3604b32a9 100644 --- a/drivers/irqchip/irq-atmel-aic.c +++ b/drivers/irqchip/irq-atmel-aic.c | |||
@@ -65,11 +65,11 @@ aic_handle(struct pt_regs *regs) | |||
65 | u32 irqnr; | 65 | u32 irqnr; |
66 | u32 irqstat; | 66 | u32 irqstat; |
67 | 67 | ||
68 | irqnr = irq_reg_readl(gc->reg_base + AT91_AIC_IVR); | 68 | irqnr = irq_reg_readl(gc, AT91_AIC_IVR); |
69 | irqstat = irq_reg_readl(gc->reg_base + AT91_AIC_ISR); | 69 | irqstat = irq_reg_readl(gc, AT91_AIC_ISR); |
70 | 70 | ||
71 | if (!irqstat) | 71 | if (!irqstat) |
72 | irq_reg_writel(0, gc->reg_base + AT91_AIC_EOICR); | 72 | irq_reg_writel(gc, 0, AT91_AIC_EOICR); |
73 | else | 73 | else |
74 | handle_domain_irq(aic_domain, irqnr, regs); | 74 | handle_domain_irq(aic_domain, irqnr, regs); |
75 | } | 75 | } |
@@ -80,7 +80,7 @@ static int aic_retrigger(struct irq_data *d) | |||
80 | 80 | ||
81 | /* Enable interrupt on AIC5 */ | 81 | /* Enable interrupt on AIC5 */ |
82 | irq_gc_lock(gc); | 82 | irq_gc_lock(gc); |
83 | irq_reg_writel(d->mask, gc->reg_base + AT91_AIC_ISCR); | 83 | irq_reg_writel(gc, d->mask, AT91_AIC_ISCR); |
84 | irq_gc_unlock(gc); | 84 | irq_gc_unlock(gc); |
85 | 85 | ||
86 | return 0; | 86 | return 0; |
@@ -92,12 +92,12 @@ static int aic_set_type(struct irq_data *d, unsigned type) | |||
92 | unsigned int smr; | 92 | unsigned int smr; |
93 | int ret; | 93 | int ret; |
94 | 94 | ||
95 | smr = irq_reg_readl(gc->reg_base + AT91_AIC_SMR(d->hwirq)); | 95 | smr = irq_reg_readl(gc, AT91_AIC_SMR(d->hwirq)); |
96 | ret = aic_common_set_type(d, type, &smr); | 96 | ret = aic_common_set_type(d, type, &smr); |
97 | if (ret) | 97 | if (ret) |
98 | return ret; | 98 | return ret; |
99 | 99 | ||
100 | irq_reg_writel(smr, gc->reg_base + AT91_AIC_SMR(d->hwirq)); | 100 | irq_reg_writel(gc, smr, AT91_AIC_SMR(d->hwirq)); |
101 | 101 | ||
102 | return 0; | 102 | return 0; |
103 | } | 103 | } |
@@ -108,8 +108,8 @@ static void aic_suspend(struct irq_data *d) | |||
108 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); | 108 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); |
109 | 109 | ||
110 | irq_gc_lock(gc); | 110 | irq_gc_lock(gc); |
111 | irq_reg_writel(gc->mask_cache, gc->reg_base + AT91_AIC_IDCR); | 111 | irq_reg_writel(gc, gc->mask_cache, AT91_AIC_IDCR); |
112 | irq_reg_writel(gc->wake_active, gc->reg_base + AT91_AIC_IECR); | 112 | irq_reg_writel(gc, gc->wake_active, AT91_AIC_IECR); |
113 | irq_gc_unlock(gc); | 113 | irq_gc_unlock(gc); |
114 | } | 114 | } |
115 | 115 | ||
@@ -118,8 +118,8 @@ static void aic_resume(struct irq_data *d) | |||
118 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); | 118 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); |
119 | 119 | ||
120 | irq_gc_lock(gc); | 120 | irq_gc_lock(gc); |
121 | irq_reg_writel(gc->wake_active, gc->reg_base + AT91_AIC_IDCR); | 121 | irq_reg_writel(gc, gc->wake_active, AT91_AIC_IDCR); |
122 | irq_reg_writel(gc->mask_cache, gc->reg_base + AT91_AIC_IECR); | 122 | irq_reg_writel(gc, gc->mask_cache, AT91_AIC_IECR); |
123 | irq_gc_unlock(gc); | 123 | irq_gc_unlock(gc); |
124 | } | 124 | } |
125 | 125 | ||
@@ -128,8 +128,8 @@ static void aic_pm_shutdown(struct irq_data *d) | |||
128 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); | 128 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); |
129 | 129 | ||
130 | irq_gc_lock(gc); | 130 | irq_gc_lock(gc); |
131 | irq_reg_writel(0xffffffff, gc->reg_base + AT91_AIC_IDCR); | 131 | irq_reg_writel(gc, 0xffffffff, AT91_AIC_IDCR); |
132 | irq_reg_writel(0xffffffff, gc->reg_base + AT91_AIC_ICCR); | 132 | irq_reg_writel(gc, 0xffffffff, AT91_AIC_ICCR); |
133 | irq_gc_unlock(gc); | 133 | irq_gc_unlock(gc); |
134 | } | 134 | } |
135 | #else | 135 | #else |
@@ -148,24 +148,24 @@ static void __init aic_hw_init(struct irq_domain *domain) | |||
148 | * will not Lock out nIRQ | 148 | * will not Lock out nIRQ |
149 | */ | 149 | */ |
150 | for (i = 0; i < 8; i++) | 150 | for (i = 0; i < 8; i++) |
151 | irq_reg_writel(0, gc->reg_base + AT91_AIC_EOICR); | 151 | irq_reg_writel(gc, 0, AT91_AIC_EOICR); |
152 | 152 | ||
153 | /* | 153 | /* |
154 | * Spurious Interrupt ID in Spurious Vector Register. | 154 | * Spurious Interrupt ID in Spurious Vector Register. |
155 | * When there is no current interrupt, the IRQ Vector Register | 155 | * When there is no current interrupt, the IRQ Vector Register |
156 | * reads the value stored in AIC_SPU | 156 | * reads the value stored in AIC_SPU |
157 | */ | 157 | */ |
158 | irq_reg_writel(0xffffffff, gc->reg_base + AT91_AIC_SPU); | 158 | irq_reg_writel(gc, 0xffffffff, AT91_AIC_SPU); |
159 | 159 | ||
160 | /* No debugging in AIC: Debug (Protect) Control Register */ | 160 | /* No debugging in AIC: Debug (Protect) Control Register */ |
161 | irq_reg_writel(0, gc->reg_base + AT91_AIC_DCR); | 161 | irq_reg_writel(gc, 0, AT91_AIC_DCR); |
162 | 162 | ||
163 | /* Disable and clear all interrupts initially */ | 163 | /* Disable and clear all interrupts initially */ |
164 | irq_reg_writel(0xffffffff, gc->reg_base + AT91_AIC_IDCR); | 164 | irq_reg_writel(gc, 0xffffffff, AT91_AIC_IDCR); |
165 | irq_reg_writel(0xffffffff, gc->reg_base + AT91_AIC_ICCR); | 165 | irq_reg_writel(gc, 0xffffffff, AT91_AIC_ICCR); |
166 | 166 | ||
167 | for (i = 0; i < 32; i++) | 167 | for (i = 0; i < 32; i++) |
168 | irq_reg_writel(i, gc->reg_base + AT91_AIC_SVR(i)); | 168 | irq_reg_writel(gc, i, AT91_AIC_SVR(i)); |
169 | } | 169 | } |
170 | 170 | ||
171 | static int aic_irq_domain_xlate(struct irq_domain *d, | 171 | static int aic_irq_domain_xlate(struct irq_domain *d, |
@@ -195,10 +195,10 @@ static int aic_irq_domain_xlate(struct irq_domain *d, | |||
195 | gc = dgc->gc[idx]; | 195 | gc = dgc->gc[idx]; |
196 | 196 | ||
197 | irq_gc_lock(gc); | 197 | irq_gc_lock(gc); |
198 | smr = irq_reg_readl(gc->reg_base + AT91_AIC_SMR(*out_hwirq)); | 198 | smr = irq_reg_readl(gc, AT91_AIC_SMR(*out_hwirq)); |
199 | ret = aic_common_set_priority(intspec[2], &smr); | 199 | ret = aic_common_set_priority(intspec[2], &smr); |
200 | if (!ret) | 200 | if (!ret) |
201 | irq_reg_writel(smr, gc->reg_base + AT91_AIC_SMR(*out_hwirq)); | 201 | irq_reg_writel(gc, smr, AT91_AIC_SMR(*out_hwirq)); |
202 | irq_gc_unlock(gc); | 202 | irq_gc_unlock(gc); |
203 | 203 | ||
204 | return ret; | 204 | return ret; |
@@ -209,16 +209,32 @@ static const struct irq_domain_ops aic_irq_ops = { | |||
209 | .xlate = aic_irq_domain_xlate, | 209 | .xlate = aic_irq_domain_xlate, |
210 | }; | 210 | }; |
211 | 211 | ||
212 | static void __init at91sam9_aic_irq_fixup(struct device_node *root) | 212 | static void __init at91rm9200_aic_irq_fixup(struct device_node *root) |
213 | { | 213 | { |
214 | aic_common_rtc_irq_fixup(root); | 214 | aic_common_rtc_irq_fixup(root); |
215 | } | 215 | } |
216 | 216 | ||
217 | static void __init at91sam9260_aic_irq_fixup(struct device_node *root) | ||
218 | { | ||
219 | aic_common_rtt_irq_fixup(root); | ||
220 | } | ||
221 | |||
222 | static void __init at91sam9g45_aic_irq_fixup(struct device_node *root) | ||
223 | { | ||
224 | aic_common_rtc_irq_fixup(root); | ||
225 | aic_common_rtt_irq_fixup(root); | ||
226 | } | ||
227 | |||
217 | static const struct of_device_id __initdata aic_irq_fixups[] = { | 228 | static const struct of_device_id __initdata aic_irq_fixups[] = { |
218 | { .compatible = "atmel,at91sam9g45", .data = at91sam9_aic_irq_fixup }, | 229 | { .compatible = "atmel,at91rm9200", .data = at91rm9200_aic_irq_fixup }, |
219 | { .compatible = "atmel,at91sam9n12", .data = at91sam9_aic_irq_fixup }, | 230 | { .compatible = "atmel,at91sam9g45", .data = at91sam9g45_aic_irq_fixup }, |
220 | { .compatible = "atmel,at91sam9rl", .data = at91sam9_aic_irq_fixup }, | 231 | { .compatible = "atmel,at91sam9n12", .data = at91rm9200_aic_irq_fixup }, |
221 | { .compatible = "atmel,at91sam9x5", .data = at91sam9_aic_irq_fixup }, | 232 | { .compatible = "atmel,at91sam9rl", .data = at91sam9g45_aic_irq_fixup }, |
233 | { .compatible = "atmel,at91sam9x5", .data = at91rm9200_aic_irq_fixup }, | ||
234 | { .compatible = "atmel,at91sam9260", .data = at91sam9260_aic_irq_fixup }, | ||
235 | { .compatible = "atmel,at91sam9261", .data = at91sam9260_aic_irq_fixup }, | ||
236 | { .compatible = "atmel,at91sam9263", .data = at91sam9260_aic_irq_fixup }, | ||
237 | { .compatible = "atmel,at91sam9g20", .data = at91sam9260_aic_irq_fixup }, | ||
222 | { /* sentinel */ }, | 238 | { /* sentinel */ }, |
223 | }; | 239 | }; |
224 | 240 | ||
diff --git a/drivers/irqchip/irq-atmel-aic5.c b/drivers/irqchip/irq-atmel-aic5.c index a11aae8fb006..a2e8c3f876cb 100644 --- a/drivers/irqchip/irq-atmel-aic5.c +++ b/drivers/irqchip/irq-atmel-aic5.c | |||
@@ -75,11 +75,11 @@ aic5_handle(struct pt_regs *regs) | |||
75 | u32 irqnr; | 75 | u32 irqnr; |
76 | u32 irqstat; | 76 | u32 irqstat; |
77 | 77 | ||
78 | irqnr = irq_reg_readl(gc->reg_base + AT91_AIC5_IVR); | 78 | irqnr = irq_reg_readl(gc, AT91_AIC5_IVR); |
79 | irqstat = irq_reg_readl(gc->reg_base + AT91_AIC5_ISR); | 79 | irqstat = irq_reg_readl(gc, AT91_AIC5_ISR); |
80 | 80 | ||
81 | if (!irqstat) | 81 | if (!irqstat) |
82 | irq_reg_writel(0, gc->reg_base + AT91_AIC5_EOICR); | 82 | irq_reg_writel(gc, 0, AT91_AIC5_EOICR); |
83 | else | 83 | else |
84 | handle_domain_irq(aic5_domain, irqnr, regs); | 84 | handle_domain_irq(aic5_domain, irqnr, regs); |
85 | } | 85 | } |
@@ -92,8 +92,8 @@ static void aic5_mask(struct irq_data *d) | |||
92 | 92 | ||
93 | /* Disable interrupt on AIC5 */ | 93 | /* Disable interrupt on AIC5 */ |
94 | irq_gc_lock(gc); | 94 | irq_gc_lock(gc); |
95 | irq_reg_writel(d->hwirq, gc->reg_base + AT91_AIC5_SSR); | 95 | irq_reg_writel(gc, d->hwirq, AT91_AIC5_SSR); |
96 | irq_reg_writel(1, gc->reg_base + AT91_AIC5_IDCR); | 96 | irq_reg_writel(gc, 1, AT91_AIC5_IDCR); |
97 | gc->mask_cache &= ~d->mask; | 97 | gc->mask_cache &= ~d->mask; |
98 | irq_gc_unlock(gc); | 98 | irq_gc_unlock(gc); |
99 | } | 99 | } |
@@ -106,8 +106,8 @@ static void aic5_unmask(struct irq_data *d) | |||
106 | 106 | ||
107 | /* Enable interrupt on AIC5 */ | 107 | /* Enable interrupt on AIC5 */ |
108 | irq_gc_lock(gc); | 108 | irq_gc_lock(gc); |
109 | irq_reg_writel(d->hwirq, gc->reg_base + AT91_AIC5_SSR); | 109 | irq_reg_writel(gc, d->hwirq, AT91_AIC5_SSR); |
110 | irq_reg_writel(1, gc->reg_base + AT91_AIC5_IECR); | 110 | irq_reg_writel(gc, 1, AT91_AIC5_IECR); |
111 | gc->mask_cache |= d->mask; | 111 | gc->mask_cache |= d->mask; |
112 | irq_gc_unlock(gc); | 112 | irq_gc_unlock(gc); |
113 | } | 113 | } |
@@ -120,8 +120,8 @@ static int aic5_retrigger(struct irq_data *d) | |||
120 | 120 | ||
121 | /* Enable interrupt on AIC5 */ | 121 | /* Enable interrupt on AIC5 */ |
122 | irq_gc_lock(gc); | 122 | irq_gc_lock(gc); |
123 | irq_reg_writel(d->hwirq, gc->reg_base + AT91_AIC5_SSR); | 123 | irq_reg_writel(gc, d->hwirq, AT91_AIC5_SSR); |
124 | irq_reg_writel(1, gc->reg_base + AT91_AIC5_ISCR); | 124 | irq_reg_writel(gc, 1, AT91_AIC5_ISCR); |
125 | irq_gc_unlock(gc); | 125 | irq_gc_unlock(gc); |
126 | 126 | ||
127 | return 0; | 127 | return 0; |
@@ -136,11 +136,11 @@ static int aic5_set_type(struct irq_data *d, unsigned type) | |||
136 | int ret; | 136 | int ret; |
137 | 137 | ||
138 | irq_gc_lock(gc); | 138 | irq_gc_lock(gc); |
139 | irq_reg_writel(d->hwirq, gc->reg_base + AT91_AIC5_SSR); | 139 | irq_reg_writel(gc, d->hwirq, AT91_AIC5_SSR); |
140 | smr = irq_reg_readl(gc->reg_base + AT91_AIC5_SMR); | 140 | smr = irq_reg_readl(gc, AT91_AIC5_SMR); |
141 | ret = aic_common_set_type(d, type, &smr); | 141 | ret = aic_common_set_type(d, type, &smr); |
142 | if (!ret) | 142 | if (!ret) |
143 | irq_reg_writel(smr, gc->reg_base + AT91_AIC5_SMR); | 143 | irq_reg_writel(gc, smr, AT91_AIC5_SMR); |
144 | irq_gc_unlock(gc); | 144 | irq_gc_unlock(gc); |
145 | 145 | ||
146 | return ret; | 146 | return ret; |
@@ -162,12 +162,11 @@ static void aic5_suspend(struct irq_data *d) | |||
162 | if ((mask & gc->mask_cache) == (mask & gc->wake_active)) | 162 | if ((mask & gc->mask_cache) == (mask & gc->wake_active)) |
163 | continue; | 163 | continue; |
164 | 164 | ||
165 | irq_reg_writel(i + gc->irq_base, | 165 | irq_reg_writel(bgc, i + gc->irq_base, AT91_AIC5_SSR); |
166 | bgc->reg_base + AT91_AIC5_SSR); | ||
167 | if (mask & gc->wake_active) | 166 | if (mask & gc->wake_active) |
168 | irq_reg_writel(1, bgc->reg_base + AT91_AIC5_IECR); | 167 | irq_reg_writel(bgc, 1, AT91_AIC5_IECR); |
169 | else | 168 | else |
170 | irq_reg_writel(1, bgc->reg_base + AT91_AIC5_IDCR); | 169 | irq_reg_writel(bgc, 1, AT91_AIC5_IDCR); |
171 | } | 170 | } |
172 | irq_gc_unlock(bgc); | 171 | irq_gc_unlock(bgc); |
173 | } | 172 | } |
@@ -187,12 +186,11 @@ static void aic5_resume(struct irq_data *d) | |||
187 | if ((mask & gc->mask_cache) == (mask & gc->wake_active)) | 186 | if ((mask & gc->mask_cache) == (mask & gc->wake_active)) |
188 | continue; | 187 | continue; |
189 | 188 | ||
190 | irq_reg_writel(i + gc->irq_base, | 189 | irq_reg_writel(bgc, i + gc->irq_base, AT91_AIC5_SSR); |
191 | bgc->reg_base + AT91_AIC5_SSR); | ||
192 | if (mask & gc->mask_cache) | 190 | if (mask & gc->mask_cache) |
193 | irq_reg_writel(1, bgc->reg_base + AT91_AIC5_IECR); | 191 | irq_reg_writel(bgc, 1, AT91_AIC5_IECR); |
194 | else | 192 | else |
195 | irq_reg_writel(1, bgc->reg_base + AT91_AIC5_IDCR); | 193 | irq_reg_writel(bgc, 1, AT91_AIC5_IDCR); |
196 | } | 194 | } |
197 | irq_gc_unlock(bgc); | 195 | irq_gc_unlock(bgc); |
198 | } | 196 | } |
@@ -207,10 +205,9 @@ static void aic5_pm_shutdown(struct irq_data *d) | |||
207 | 205 | ||
208 | irq_gc_lock(bgc); | 206 | irq_gc_lock(bgc); |
209 | for (i = 0; i < dgc->irqs_per_chip; i++) { | 207 | for (i = 0; i < dgc->irqs_per_chip; i++) { |
210 | irq_reg_writel(i + gc->irq_base, | 208 | irq_reg_writel(bgc, i + gc->irq_base, AT91_AIC5_SSR); |
211 | bgc->reg_base + AT91_AIC5_SSR); | 209 | irq_reg_writel(bgc, 1, AT91_AIC5_IDCR); |
212 | irq_reg_writel(1, bgc->reg_base + AT91_AIC5_IDCR); | 210 | irq_reg_writel(bgc, 1, AT91_AIC5_ICCR); |
213 | irq_reg_writel(1, bgc->reg_base + AT91_AIC5_ICCR); | ||
214 | } | 211 | } |
215 | irq_gc_unlock(bgc); | 212 | irq_gc_unlock(bgc); |
216 | } | 213 | } |
@@ -230,24 +227,24 @@ static void __init aic5_hw_init(struct irq_domain *domain) | |||
230 | * will not Lock out nIRQ | 227 | * will not Lock out nIRQ |
231 | */ | 228 | */ |
232 | for (i = 0; i < 8; i++) | 229 | for (i = 0; i < 8; i++) |
233 | irq_reg_writel(0, gc->reg_base + AT91_AIC5_EOICR); | 230 | irq_reg_writel(gc, 0, AT91_AIC5_EOICR); |
234 | 231 | ||
235 | /* | 232 | /* |
236 | * Spurious Interrupt ID in Spurious Vector Register. | 233 | * Spurious Interrupt ID in Spurious Vector Register. |
237 | * When there is no current interrupt, the IRQ Vector Register | 234 | * When there is no current interrupt, the IRQ Vector Register |
238 | * reads the value stored in AIC_SPU | 235 | * reads the value stored in AIC_SPU |
239 | */ | 236 | */ |
240 | irq_reg_writel(0xffffffff, gc->reg_base + AT91_AIC5_SPU); | 237 | irq_reg_writel(gc, 0xffffffff, AT91_AIC5_SPU); |
241 | 238 | ||
242 | /* No debugging in AIC: Debug (Protect) Control Register */ | 239 | /* No debugging in AIC: Debug (Protect) Control Register */ |
243 | irq_reg_writel(0, gc->reg_base + AT91_AIC5_DCR); | 240 | irq_reg_writel(gc, 0, AT91_AIC5_DCR); |
244 | 241 | ||
245 | /* Disable and clear all interrupts initially */ | 242 | /* Disable and clear all interrupts initially */ |
246 | for (i = 0; i < domain->revmap_size; i++) { | 243 | for (i = 0; i < domain->revmap_size; i++) { |
247 | irq_reg_writel(i, gc->reg_base + AT91_AIC5_SSR); | 244 | irq_reg_writel(gc, i, AT91_AIC5_SSR); |
248 | irq_reg_writel(i, gc->reg_base + AT91_AIC5_SVR); | 245 | irq_reg_writel(gc, i, AT91_AIC5_SVR); |
249 | irq_reg_writel(1, gc->reg_base + AT91_AIC5_IDCR); | 246 | irq_reg_writel(gc, 1, AT91_AIC5_IDCR); |
250 | irq_reg_writel(1, gc->reg_base + AT91_AIC5_ICCR); | 247 | irq_reg_writel(gc, 1, AT91_AIC5_ICCR); |
251 | } | 248 | } |
252 | } | 249 | } |
253 | 250 | ||
@@ -273,11 +270,11 @@ static int aic5_irq_domain_xlate(struct irq_domain *d, | |||
273 | gc = dgc->gc[0]; | 270 | gc = dgc->gc[0]; |
274 | 271 | ||
275 | irq_gc_lock(gc); | 272 | irq_gc_lock(gc); |
276 | irq_reg_writel(*out_hwirq, gc->reg_base + AT91_AIC5_SSR); | 273 | irq_reg_writel(gc, *out_hwirq, AT91_AIC5_SSR); |
277 | smr = irq_reg_readl(gc->reg_base + AT91_AIC5_SMR); | 274 | smr = irq_reg_readl(gc, AT91_AIC5_SMR); |
278 | ret = aic_common_set_priority(intspec[2], &smr); | 275 | ret = aic_common_set_priority(intspec[2], &smr); |
279 | if (!ret) | 276 | if (!ret) |
280 | irq_reg_writel(intspec[2] | smr, gc->reg_base + AT91_AIC5_SMR); | 277 | irq_reg_writel(gc, intspec[2] | smr, AT91_AIC5_SMR); |
281 | irq_gc_unlock(gc); | 278 | irq_gc_unlock(gc); |
282 | 279 | ||
283 | return ret; | 280 | return ret; |
diff --git a/drivers/irqchip/irq-bcm7120-l2.c b/drivers/irqchip/irq-bcm7120-l2.c index 5fb38a2ac226..8eec8e1201d9 100644 --- a/drivers/irqchip/irq-bcm7120-l2.c +++ b/drivers/irqchip/irq-bcm7120-l2.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/init.h> | 13 | #include <linux/init.h> |
14 | #include <linux/slab.h> | 14 | #include <linux/slab.h> |
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | #include <linux/kconfig.h> | ||
16 | #include <linux/platform_device.h> | 17 | #include <linux/platform_device.h> |
17 | #include <linux/of.h> | 18 | #include <linux/of.h> |
18 | #include <linux/of_irq.h> | 19 | #include <linux/of_irq.h> |
@@ -23,47 +24,52 @@ | |||
23 | #include <linux/io.h> | 24 | #include <linux/io.h> |
24 | #include <linux/irqdomain.h> | 25 | #include <linux/irqdomain.h> |
25 | #include <linux/reboot.h> | 26 | #include <linux/reboot.h> |
27 | #include <linux/bitops.h> | ||
26 | #include <linux/irqchip/chained_irq.h> | 28 | #include <linux/irqchip/chained_irq.h> |
27 | 29 | ||
28 | #include "irqchip.h" | 30 | #include "irqchip.h" |
29 | 31 | ||
30 | #include <asm/mach/irq.h> | ||
31 | |||
32 | /* Register offset in the L2 interrupt controller */ | 32 | /* Register offset in the L2 interrupt controller */ |
33 | #define IRQEN 0x00 | 33 | #define IRQEN 0x00 |
34 | #define IRQSTAT 0x04 | 34 | #define IRQSTAT 0x04 |
35 | 35 | ||
36 | #define MAX_WORDS 4 | ||
37 | #define IRQS_PER_WORD 32 | ||
38 | |||
36 | struct bcm7120_l2_intc_data { | 39 | struct bcm7120_l2_intc_data { |
37 | void __iomem *base; | 40 | unsigned int n_words; |
41 | void __iomem *base[MAX_WORDS]; | ||
38 | struct irq_domain *domain; | 42 | struct irq_domain *domain; |
39 | bool can_wake; | 43 | bool can_wake; |
40 | u32 irq_fwd_mask; | 44 | u32 irq_fwd_mask[MAX_WORDS]; |
41 | u32 irq_map_mask; | 45 | u32 irq_map_mask[MAX_WORDS]; |
42 | u32 saved_mask; | ||
43 | }; | 46 | }; |
44 | 47 | ||
45 | static void bcm7120_l2_intc_irq_handle(unsigned int irq, struct irq_desc *desc) | 48 | static void bcm7120_l2_intc_irq_handle(unsigned int irq, struct irq_desc *desc) |
46 | { | 49 | { |
47 | struct bcm7120_l2_intc_data *b = irq_desc_get_handler_data(desc); | 50 | struct bcm7120_l2_intc_data *b = irq_desc_get_handler_data(desc); |
48 | struct irq_chip *chip = irq_desc_get_chip(desc); | 51 | struct irq_chip *chip = irq_desc_get_chip(desc); |
49 | u32 status; | 52 | unsigned int idx; |
50 | 53 | ||
51 | chained_irq_enter(chip, desc); | 54 | chained_irq_enter(chip, desc); |
52 | 55 | ||
53 | status = __raw_readl(b->base + IRQSTAT); | 56 | for (idx = 0; idx < b->n_words; idx++) { |
54 | 57 | int base = idx * IRQS_PER_WORD; | |
55 | if (status == 0) { | 58 | struct irq_chip_generic *gc = |
56 | do_bad_IRQ(irq, desc); | 59 | irq_get_domain_generic_chip(b->domain, base); |
57 | goto out; | 60 | unsigned long pending; |
61 | int hwirq; | ||
62 | |||
63 | irq_gc_lock(gc); | ||
64 | pending = irq_reg_readl(gc, IRQSTAT) & gc->mask_cache; | ||
65 | irq_gc_unlock(gc); | ||
66 | |||
67 | for_each_set_bit(hwirq, &pending, IRQS_PER_WORD) { | ||
68 | generic_handle_irq(irq_find_mapping(b->domain, | ||
69 | base + hwirq)); | ||
70 | } | ||
58 | } | 71 | } |
59 | 72 | ||
60 | do { | ||
61 | irq = ffs(status) - 1; | ||
62 | status &= ~(1 << irq); | ||
63 | generic_handle_irq(irq_find_mapping(b->domain, irq)); | ||
64 | } while (status); | ||
65 | |||
66 | out: | ||
67 | chained_irq_exit(chip, desc); | 73 | chained_irq_exit(chip, desc); |
68 | } | 74 | } |
69 | 75 | ||
@@ -71,26 +77,20 @@ static void bcm7120_l2_intc_suspend(struct irq_data *d) | |||
71 | { | 77 | { |
72 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); | 78 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); |
73 | struct bcm7120_l2_intc_data *b = gc->private; | 79 | struct bcm7120_l2_intc_data *b = gc->private; |
74 | u32 reg; | ||
75 | 80 | ||
76 | irq_gc_lock(gc); | 81 | irq_gc_lock(gc); |
77 | /* Save the current mask and the interrupt forward mask */ | 82 | if (b->can_wake) |
78 | b->saved_mask = __raw_readl(b->base) | b->irq_fwd_mask; | 83 | irq_reg_writel(gc, gc->mask_cache | gc->wake_active, IRQEN); |
79 | if (b->can_wake) { | ||
80 | reg = b->saved_mask | gc->wake_active; | ||
81 | __raw_writel(reg, b->base); | ||
82 | } | ||
83 | irq_gc_unlock(gc); | 84 | irq_gc_unlock(gc); |
84 | } | 85 | } |
85 | 86 | ||
86 | static void bcm7120_l2_intc_resume(struct irq_data *d) | 87 | static void bcm7120_l2_intc_resume(struct irq_data *d) |
87 | { | 88 | { |
88 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); | 89 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); |
89 | struct bcm7120_l2_intc_data *b = gc->private; | ||
90 | 90 | ||
91 | /* Restore the saved mask */ | 91 | /* Restore the saved mask */ |
92 | irq_gc_lock(gc); | 92 | irq_gc_lock(gc); |
93 | __raw_writel(b->saved_mask, b->base); | 93 | irq_reg_writel(gc, gc->mask_cache, IRQEN); |
94 | irq_gc_unlock(gc); | 94 | irq_gc_unlock(gc); |
95 | } | 95 | } |
96 | 96 | ||
@@ -99,6 +99,7 @@ static int bcm7120_l2_intc_init_one(struct device_node *dn, | |||
99 | int irq, const __be32 *map_mask) | 99 | int irq, const __be32 *map_mask) |
100 | { | 100 | { |
101 | int parent_irq; | 101 | int parent_irq; |
102 | unsigned int idx; | ||
102 | 103 | ||
103 | parent_irq = irq_of_parse_and_map(dn, irq); | 104 | parent_irq = irq_of_parse_and_map(dn, irq); |
104 | if (!parent_irq) { | 105 | if (!parent_irq) { |
@@ -106,7 +107,12 @@ static int bcm7120_l2_intc_init_one(struct device_node *dn, | |||
106 | return -EINVAL; | 107 | return -EINVAL; |
107 | } | 108 | } |
108 | 109 | ||
109 | data->irq_map_mask |= be32_to_cpup(map_mask + irq); | 110 | /* For multiple parent IRQs with multiple words, this looks like: |
111 | * <irq0_w0 irq0_w1 irq1_w0 irq1_w1 ...> | ||
112 | */ | ||
113 | for (idx = 0; idx < data->n_words; idx++) | ||
114 | data->irq_map_mask[idx] |= | ||
115 | be32_to_cpup(map_mask + irq * data->n_words + idx); | ||
110 | 116 | ||
111 | irq_set_handler_data(parent_irq, data); | 117 | irq_set_handler_data(parent_irq, data); |
112 | irq_set_chained_handler(parent_irq, bcm7120_l2_intc_irq_handle); | 118 | irq_set_chained_handler(parent_irq, bcm7120_l2_intc_irq_handle); |
@@ -123,26 +129,41 @@ int __init bcm7120_l2_intc_of_init(struct device_node *dn, | |||
123 | struct irq_chip_type *ct; | 129 | struct irq_chip_type *ct; |
124 | const __be32 *map_mask; | 130 | const __be32 *map_mask; |
125 | int num_parent_irqs; | 131 | int num_parent_irqs; |
126 | int ret = 0, len, irq; | 132 | int ret = 0, len; |
133 | unsigned int idx, irq, flags; | ||
127 | 134 | ||
128 | data = kzalloc(sizeof(*data), GFP_KERNEL); | 135 | data = kzalloc(sizeof(*data), GFP_KERNEL); |
129 | if (!data) | 136 | if (!data) |
130 | return -ENOMEM; | 137 | return -ENOMEM; |
131 | 138 | ||
132 | data->base = of_iomap(dn, 0); | 139 | for (idx = 0; idx < MAX_WORDS; idx++) { |
133 | if (!data->base) { | 140 | data->base[idx] = of_iomap(dn, idx); |
141 | if (!data->base[idx]) | ||
142 | break; | ||
143 | data->n_words = idx + 1; | ||
144 | } | ||
145 | if (!data->n_words) { | ||
134 | pr_err("failed to remap intc L2 registers\n"); | 146 | pr_err("failed to remap intc L2 registers\n"); |
135 | ret = -ENOMEM; | 147 | ret = -ENOMEM; |
136 | goto out_free; | 148 | goto out_unmap; |
137 | } | 149 | } |
138 | 150 | ||
139 | if (of_property_read_u32(dn, "brcm,int-fwd-mask", &data->irq_fwd_mask)) | 151 | /* Enable all interrupts specified in the interrupt forward mask; |
140 | data->irq_fwd_mask = 0; | 152 | * disable all others. If the property doesn't exist (-EINVAL), |
141 | 153 | * assume all zeroes. | |
142 | /* Enable all interrupt specified in the interrupt forward mask and have | ||
143 | * the other disabled | ||
144 | */ | 154 | */ |
145 | __raw_writel(data->irq_fwd_mask, data->base + IRQEN); | 155 | ret = of_property_read_u32_array(dn, "brcm,int-fwd-mask", |
156 | data->irq_fwd_mask, data->n_words); | ||
157 | if (ret == 0 || ret == -EINVAL) { | ||
158 | for (idx = 0; idx < data->n_words; idx++) | ||
159 | __raw_writel(data->irq_fwd_mask[idx], | ||
160 | data->base[idx] + IRQEN); | ||
161 | } else { | ||
162 | /* property exists but has the wrong number of words */ | ||
163 | pr_err("invalid int-fwd-mask property\n"); | ||
164 | ret = -EINVAL; | ||
165 | goto out_unmap; | ||
166 | } | ||
146 | 167 | ||
147 | num_parent_irqs = of_irq_count(dn); | 168 | num_parent_irqs = of_irq_count(dn); |
148 | if (num_parent_irqs <= 0) { | 169 | if (num_parent_irqs <= 0) { |
@@ -152,7 +173,8 @@ int __init bcm7120_l2_intc_of_init(struct device_node *dn, | |||
152 | } | 173 | } |
153 | 174 | ||
154 | map_mask = of_get_property(dn, "brcm,int-map-mask", &len); | 175 | map_mask = of_get_property(dn, "brcm,int-map-mask", &len); |
155 | if (!map_mask || (len != (sizeof(*map_mask) * num_parent_irqs))) { | 176 | if (!map_mask || |
177 | (len != (sizeof(*map_mask) * num_parent_irqs * data->n_words))) { | ||
156 | pr_err("invalid brcm,int-map-mask property\n"); | 178 | pr_err("invalid brcm,int-map-mask property\n"); |
157 | ret = -EINVAL; | 179 | ret = -EINVAL; |
158 | goto out_unmap; | 180 | goto out_unmap; |
@@ -164,56 +186,70 @@ int __init bcm7120_l2_intc_of_init(struct device_node *dn, | |||
164 | goto out_unmap; | 186 | goto out_unmap; |
165 | } | 187 | } |
166 | 188 | ||
167 | data->domain = irq_domain_add_linear(dn, 32, | 189 | data->domain = irq_domain_add_linear(dn, IRQS_PER_WORD * data->n_words, |
168 | &irq_generic_chip_ops, NULL); | 190 | &irq_generic_chip_ops, NULL); |
169 | if (!data->domain) { | 191 | if (!data->domain) { |
170 | ret = -ENOMEM; | 192 | ret = -ENOMEM; |
171 | goto out_unmap; | 193 | goto out_unmap; |
172 | } | 194 | } |
173 | 195 | ||
174 | ret = irq_alloc_domain_generic_chips(data->domain, 32, 1, | 196 | /* MIPS chips strapped for BE will automagically configure the |
175 | dn->full_name, handle_level_irq, clr, 0, | 197 | * peripheral registers for CPU-native byte order. |
176 | IRQ_GC_INIT_MASK_CACHE); | 198 | */ |
199 | flags = IRQ_GC_INIT_MASK_CACHE; | ||
200 | if (IS_ENABLED(CONFIG_MIPS) && IS_ENABLED(CONFIG_CPU_BIG_ENDIAN)) | ||
201 | flags |= IRQ_GC_BE_IO; | ||
202 | |||
203 | ret = irq_alloc_domain_generic_chips(data->domain, IRQS_PER_WORD, 1, | ||
204 | dn->full_name, handle_level_irq, clr, 0, flags); | ||
177 | if (ret) { | 205 | if (ret) { |
178 | pr_err("failed to allocate generic irq chip\n"); | 206 | pr_err("failed to allocate generic irq chip\n"); |
179 | goto out_free_domain; | 207 | goto out_free_domain; |
180 | } | 208 | } |
181 | 209 | ||
182 | gc = irq_get_domain_generic_chip(data->domain, 0); | 210 | if (of_property_read_bool(dn, "brcm,irq-can-wake")) |
183 | gc->unused = 0xfffffff & ~data->irq_map_mask; | ||
184 | gc->reg_base = data->base; | ||
185 | gc->private = data; | ||
186 | ct = gc->chip_types; | ||
187 | |||
188 | ct->regs.mask = IRQEN; | ||
189 | ct->chip.irq_mask = irq_gc_mask_clr_bit; | ||
190 | ct->chip.irq_unmask = irq_gc_mask_set_bit; | ||
191 | ct->chip.irq_ack = irq_gc_noop; | ||
192 | ct->chip.irq_suspend = bcm7120_l2_intc_suspend; | ||
193 | ct->chip.irq_resume = bcm7120_l2_intc_resume; | ||
194 | |||
195 | if (of_property_read_bool(dn, "brcm,irq-can-wake")) { | ||
196 | data->can_wake = true; | 211 | data->can_wake = true; |
197 | /* This IRQ chip can wake the system, set all relevant child | 212 | |
198 | * interupts in wake_enabled mask | 213 | for (idx = 0; idx < data->n_words; idx++) { |
199 | */ | 214 | irq = idx * IRQS_PER_WORD; |
200 | gc->wake_enabled = 0xffffffff; | 215 | gc = irq_get_domain_generic_chip(data->domain, irq); |
201 | gc->wake_enabled &= ~gc->unused; | 216 | |
202 | ct->chip.irq_set_wake = irq_gc_set_wake; | 217 | gc->unused = 0xffffffff & ~data->irq_map_mask[idx]; |
218 | gc->reg_base = data->base[idx]; | ||
219 | gc->private = data; | ||
220 | ct = gc->chip_types; | ||
221 | |||
222 | ct->regs.mask = IRQEN; | ||
223 | ct->chip.irq_mask = irq_gc_mask_clr_bit; | ||
224 | ct->chip.irq_unmask = irq_gc_mask_set_bit; | ||
225 | ct->chip.irq_ack = irq_gc_noop; | ||
226 | ct->chip.irq_suspend = bcm7120_l2_intc_suspend; | ||
227 | ct->chip.irq_resume = bcm7120_l2_intc_resume; | ||
228 | |||
229 | if (data->can_wake) { | ||
230 | /* This IRQ chip can wake the system, set all | ||
231 | * relevant child interupts in wake_enabled mask | ||
232 | */ | ||
233 | gc->wake_enabled = 0xffffffff; | ||
234 | gc->wake_enabled &= ~gc->unused; | ||
235 | ct->chip.irq_set_wake = irq_gc_set_wake; | ||
236 | } | ||
203 | } | 237 | } |
204 | 238 | ||
205 | pr_info("registered BCM7120 L2 intc (mem: 0x%p, parent IRQ(s): %d)\n", | 239 | pr_info("registered BCM7120 L2 intc (mem: 0x%p, parent IRQ(s): %d)\n", |
206 | data->base, num_parent_irqs); | 240 | data->base[0], num_parent_irqs); |
207 | 241 | ||
208 | return 0; | 242 | return 0; |
209 | 243 | ||
210 | out_free_domain: | 244 | out_free_domain: |
211 | irq_domain_remove(data->domain); | 245 | irq_domain_remove(data->domain); |
212 | out_unmap: | 246 | out_unmap: |
213 | iounmap(data->base); | 247 | for (idx = 0; idx < MAX_WORDS; idx++) { |
214 | out_free: | 248 | if (data->base[idx]) |
249 | iounmap(data->base[idx]); | ||
250 | } | ||
215 | kfree(data); | 251 | kfree(data); |
216 | return ret; | 252 | return ret; |
217 | } | 253 | } |
218 | IRQCHIP_DECLARE(brcmstb_l2_intc, "brcm,bcm7120-l2-intc", | 254 | IRQCHIP_DECLARE(bcm7120_l2_intc, "brcm,bcm7120-l2-intc", |
219 | bcm7120_l2_intc_of_init); | 255 | bcm7120_l2_intc_of_init); |
diff --git a/drivers/irqchip/irq-brcmstb-l2.c b/drivers/irqchip/irq-brcmstb-l2.c index 14691a4cb84c..313c2c64498a 100644 --- a/drivers/irqchip/irq-brcmstb-l2.c +++ b/drivers/irqchip/irq-brcmstb-l2.c | |||
@@ -18,7 +18,9 @@ | |||
18 | #include <linux/init.h> | 18 | #include <linux/init.h> |
19 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
20 | #include <linux/module.h> | 20 | #include <linux/module.h> |
21 | #include <linux/kconfig.h> | ||
21 | #include <linux/platform_device.h> | 22 | #include <linux/platform_device.h> |
23 | #include <linux/spinlock.h> | ||
22 | #include <linux/of.h> | 24 | #include <linux/of.h> |
23 | #include <linux/of_irq.h> | 25 | #include <linux/of_irq.h> |
24 | #include <linux/of_address.h> | 26 | #include <linux/of_address.h> |
@@ -30,8 +32,6 @@ | |||
30 | #include <linux/irqchip.h> | 32 | #include <linux/irqchip.h> |
31 | #include <linux/irqchip/chained_irq.h> | 33 | #include <linux/irqchip/chained_irq.h> |
32 | 34 | ||
33 | #include <asm/mach/irq.h> | ||
34 | |||
35 | #include "irqchip.h" | 35 | #include "irqchip.h" |
36 | 36 | ||
37 | /* Register offsets in the L2 interrupt controller */ | 37 | /* Register offsets in the L2 interrupt controller */ |
@@ -54,23 +54,26 @@ struct brcmstb_l2_intc_data { | |||
54 | static void brcmstb_l2_intc_irq_handle(unsigned int irq, struct irq_desc *desc) | 54 | static void brcmstb_l2_intc_irq_handle(unsigned int irq, struct irq_desc *desc) |
55 | { | 55 | { |
56 | struct brcmstb_l2_intc_data *b = irq_desc_get_handler_data(desc); | 56 | struct brcmstb_l2_intc_data *b = irq_desc_get_handler_data(desc); |
57 | struct irq_chip_generic *gc = irq_get_domain_generic_chip(b->domain, 0); | ||
57 | struct irq_chip *chip = irq_desc_get_chip(desc); | 58 | struct irq_chip *chip = irq_desc_get_chip(desc); |
58 | u32 status; | 59 | u32 status; |
59 | 60 | ||
60 | chained_irq_enter(chip, desc); | 61 | chained_irq_enter(chip, desc); |
61 | 62 | ||
62 | status = __raw_readl(b->base + CPU_STATUS) & | 63 | status = irq_reg_readl(gc, CPU_STATUS) & |
63 | ~(__raw_readl(b->base + CPU_MASK_STATUS)); | 64 | ~(irq_reg_readl(gc, CPU_MASK_STATUS)); |
64 | 65 | ||
65 | if (status == 0) { | 66 | if (status == 0) { |
66 | do_bad_IRQ(irq, desc); | 67 | raw_spin_lock(&desc->lock); |
68 | handle_bad_irq(irq, desc); | ||
69 | raw_spin_unlock(&desc->lock); | ||
67 | goto out; | 70 | goto out; |
68 | } | 71 | } |
69 | 72 | ||
70 | do { | 73 | do { |
71 | irq = ffs(status) - 1; | 74 | irq = ffs(status) - 1; |
72 | /* ack at our level */ | 75 | /* ack at our level */ |
73 | __raw_writel(1 << irq, b->base + CPU_CLEAR); | 76 | irq_reg_writel(gc, 1 << irq, CPU_CLEAR); |
74 | status &= ~(1 << irq); | 77 | status &= ~(1 << irq); |
75 | generic_handle_irq(irq_find_mapping(b->domain, irq)); | 78 | generic_handle_irq(irq_find_mapping(b->domain, irq)); |
76 | } while (status); | 79 | } while (status); |
@@ -85,12 +88,12 @@ static void brcmstb_l2_intc_suspend(struct irq_data *d) | |||
85 | 88 | ||
86 | irq_gc_lock(gc); | 89 | irq_gc_lock(gc); |
87 | /* Save the current mask */ | 90 | /* Save the current mask */ |
88 | b->saved_mask = __raw_readl(b->base + CPU_MASK_STATUS); | 91 | b->saved_mask = irq_reg_readl(gc, CPU_MASK_STATUS); |
89 | 92 | ||
90 | if (b->can_wake) { | 93 | if (b->can_wake) { |
91 | /* Program the wakeup mask */ | 94 | /* Program the wakeup mask */ |
92 | __raw_writel(~gc->wake_active, b->base + CPU_MASK_SET); | 95 | irq_reg_writel(gc, ~gc->wake_active, CPU_MASK_SET); |
93 | __raw_writel(gc->wake_active, b->base + CPU_MASK_CLEAR); | 96 | irq_reg_writel(gc, gc->wake_active, CPU_MASK_CLEAR); |
94 | } | 97 | } |
95 | irq_gc_unlock(gc); | 98 | irq_gc_unlock(gc); |
96 | } | 99 | } |
@@ -102,11 +105,11 @@ static void brcmstb_l2_intc_resume(struct irq_data *d) | |||
102 | 105 | ||
103 | irq_gc_lock(gc); | 106 | irq_gc_lock(gc); |
104 | /* Clear unmasked non-wakeup interrupts */ | 107 | /* Clear unmasked non-wakeup interrupts */ |
105 | __raw_writel(~b->saved_mask & ~gc->wake_active, b->base + CPU_CLEAR); | 108 | irq_reg_writel(gc, ~b->saved_mask & ~gc->wake_active, CPU_CLEAR); |
106 | 109 | ||
107 | /* Restore the saved mask */ | 110 | /* Restore the saved mask */ |
108 | __raw_writel(b->saved_mask, b->base + CPU_MASK_SET); | 111 | irq_reg_writel(gc, b->saved_mask, CPU_MASK_SET); |
109 | __raw_writel(~b->saved_mask, b->base + CPU_MASK_CLEAR); | 112 | irq_reg_writel(gc, ~b->saved_mask, CPU_MASK_CLEAR); |
110 | irq_gc_unlock(gc); | 113 | irq_gc_unlock(gc); |
111 | } | 114 | } |
112 | 115 | ||
@@ -118,6 +121,7 @@ int __init brcmstb_l2_intc_of_init(struct device_node *np, | |||
118 | struct irq_chip_generic *gc; | 121 | struct irq_chip_generic *gc; |
119 | struct irq_chip_type *ct; | 122 | struct irq_chip_type *ct; |
120 | int ret; | 123 | int ret; |
124 | unsigned int flags; | ||
121 | 125 | ||
122 | data = kzalloc(sizeof(*data), GFP_KERNEL); | 126 | data = kzalloc(sizeof(*data), GFP_KERNEL); |
123 | if (!data) | 127 | if (!data) |
@@ -131,8 +135,8 @@ int __init brcmstb_l2_intc_of_init(struct device_node *np, | |||
131 | } | 135 | } |
132 | 136 | ||
133 | /* Disable all interrupts by default */ | 137 | /* Disable all interrupts by default */ |
134 | __raw_writel(0xffffffff, data->base + CPU_MASK_SET); | 138 | writel(0xffffffff, data->base + CPU_MASK_SET); |
135 | __raw_writel(0xffffffff, data->base + CPU_CLEAR); | 139 | writel(0xffffffff, data->base + CPU_CLEAR); |
136 | 140 | ||
137 | data->parent_irq = irq_of_parse_and_map(np, 0); | 141 | data->parent_irq = irq_of_parse_and_map(np, 0); |
138 | if (!data->parent_irq) { | 142 | if (!data->parent_irq) { |
@@ -148,9 +152,16 @@ int __init brcmstb_l2_intc_of_init(struct device_node *np, | |||
148 | goto out_unmap; | 152 | goto out_unmap; |
149 | } | 153 | } |
150 | 154 | ||
155 | /* MIPS chips strapped for BE will automagically configure the | ||
156 | * peripheral registers for CPU-native byte order. | ||
157 | */ | ||
158 | flags = 0; | ||
159 | if (IS_ENABLED(CONFIG_MIPS) && IS_ENABLED(CONFIG_CPU_BIG_ENDIAN)) | ||
160 | flags |= IRQ_GC_BE_IO; | ||
161 | |||
151 | /* Allocate a single Generic IRQ chip for this node */ | 162 | /* Allocate a single Generic IRQ chip for this node */ |
152 | ret = irq_alloc_domain_generic_chips(data->domain, 32, 1, | 163 | ret = irq_alloc_domain_generic_chips(data->domain, 32, 1, |
153 | np->full_name, handle_edge_irq, clr, 0, 0); | 164 | np->full_name, handle_edge_irq, clr, 0, flags); |
154 | if (ret) { | 165 | if (ret) { |
155 | pr_err("failed to allocate generic irq chip\n"); | 166 | pr_err("failed to allocate generic irq chip\n"); |
156 | goto out_free_domain; | 167 | goto out_free_domain; |
diff --git a/drivers/irqchip/irq-dw-apb-ictl.c b/drivers/irqchip/irq-dw-apb-ictl.c index 31e231e1f566..53bb7326a60a 100644 --- a/drivers/irqchip/irq-dw-apb-ictl.c +++ b/drivers/irqchip/irq-dw-apb-ictl.c | |||
@@ -50,6 +50,21 @@ static void dw_apb_ictl_handler(unsigned int irq, struct irq_desc *desc) | |||
50 | chained_irq_exit(chip, desc); | 50 | chained_irq_exit(chip, desc); |
51 | } | 51 | } |
52 | 52 | ||
53 | #ifdef CONFIG_PM | ||
54 | static void dw_apb_ictl_resume(struct irq_data *d) | ||
55 | { | ||
56 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); | ||
57 | struct irq_chip_type *ct = irq_data_get_chip_type(d); | ||
58 | |||
59 | irq_gc_lock(gc); | ||
60 | writel_relaxed(~0, gc->reg_base + ct->regs.enable); | ||
61 | writel_relaxed(*ct->mask_cache, gc->reg_base + ct->regs.mask); | ||
62 | irq_gc_unlock(gc); | ||
63 | } | ||
64 | #else | ||
65 | #define dw_apb_ictl_resume NULL | ||
66 | #endif /* CONFIG_PM */ | ||
67 | |||
53 | static int __init dw_apb_ictl_init(struct device_node *np, | 68 | static int __init dw_apb_ictl_init(struct device_node *np, |
54 | struct device_node *parent) | 69 | struct device_node *parent) |
55 | { | 70 | { |
@@ -94,16 +109,16 @@ static int __init dw_apb_ictl_init(struct device_node *np, | |||
94 | */ | 109 | */ |
95 | 110 | ||
96 | /* mask and enable all interrupts */ | 111 | /* mask and enable all interrupts */ |
97 | writel(~0, iobase + APB_INT_MASK_L); | 112 | writel_relaxed(~0, iobase + APB_INT_MASK_L); |
98 | writel(~0, iobase + APB_INT_MASK_H); | 113 | writel_relaxed(~0, iobase + APB_INT_MASK_H); |
99 | writel(~0, iobase + APB_INT_ENABLE_L); | 114 | writel_relaxed(~0, iobase + APB_INT_ENABLE_L); |
100 | writel(~0, iobase + APB_INT_ENABLE_H); | 115 | writel_relaxed(~0, iobase + APB_INT_ENABLE_H); |
101 | 116 | ||
102 | reg = readl(iobase + APB_INT_ENABLE_H); | 117 | reg = readl_relaxed(iobase + APB_INT_ENABLE_H); |
103 | if (reg) | 118 | if (reg) |
104 | nrirqs = 32 + fls(reg); | 119 | nrirqs = 32 + fls(reg); |
105 | else | 120 | else |
106 | nrirqs = fls(readl(iobase + APB_INT_ENABLE_L)); | 121 | nrirqs = fls(readl_relaxed(iobase + APB_INT_ENABLE_L)); |
107 | 122 | ||
108 | domain = irq_domain_add_linear(np, nrirqs, | 123 | domain = irq_domain_add_linear(np, nrirqs, |
109 | &irq_generic_chip_ops, NULL); | 124 | &irq_generic_chip_ops, NULL); |
@@ -115,6 +130,7 @@ static int __init dw_apb_ictl_init(struct device_node *np, | |||
115 | 130 | ||
116 | ret = irq_alloc_domain_generic_chips(domain, 32, (nrirqs > 32) ? 2 : 1, | 131 | ret = irq_alloc_domain_generic_chips(domain, 32, (nrirqs > 32) ? 2 : 1, |
117 | np->name, handle_level_irq, clr, 0, | 132 | np->name, handle_level_irq, clr, 0, |
133 | IRQ_GC_MASK_CACHE_PER_TYPE | | ||
118 | IRQ_GC_INIT_MASK_CACHE); | 134 | IRQ_GC_INIT_MASK_CACHE); |
119 | if (ret) { | 135 | if (ret) { |
120 | pr_err("%s: unable to alloc irq domain gc\n", np->full_name); | 136 | pr_err("%s: unable to alloc irq domain gc\n", np->full_name); |
@@ -126,13 +142,17 @@ static int __init dw_apb_ictl_init(struct device_node *np, | |||
126 | gc->reg_base = iobase; | 142 | gc->reg_base = iobase; |
127 | 143 | ||
128 | gc->chip_types[0].regs.mask = APB_INT_MASK_L; | 144 | gc->chip_types[0].regs.mask = APB_INT_MASK_L; |
145 | gc->chip_types[0].regs.enable = APB_INT_ENABLE_L; | ||
129 | gc->chip_types[0].chip.irq_mask = irq_gc_mask_set_bit; | 146 | gc->chip_types[0].chip.irq_mask = irq_gc_mask_set_bit; |
130 | gc->chip_types[0].chip.irq_unmask = irq_gc_mask_clr_bit; | 147 | gc->chip_types[0].chip.irq_unmask = irq_gc_mask_clr_bit; |
148 | gc->chip_types[0].chip.irq_resume = dw_apb_ictl_resume; | ||
131 | 149 | ||
132 | if (nrirqs > 32) { | 150 | if (nrirqs > 32) { |
133 | gc->chip_types[1].regs.mask = APB_INT_MASK_H; | 151 | gc->chip_types[1].regs.mask = APB_INT_MASK_H; |
152 | gc->chip_types[1].regs.enable = APB_INT_ENABLE_H; | ||
134 | gc->chip_types[1].chip.irq_mask = irq_gc_mask_set_bit; | 153 | gc->chip_types[1].chip.irq_mask = irq_gc_mask_set_bit; |
135 | gc->chip_types[1].chip.irq_unmask = irq_gc_mask_clr_bit; | 154 | gc->chip_types[1].chip.irq_unmask = irq_gc_mask_clr_bit; |
155 | gc->chip_types[1].chip.irq_resume = dw_apb_ictl_resume; | ||
136 | } | 156 | } |
137 | 157 | ||
138 | irq_set_handler_data(irq, gc); | 158 | irq_set_handler_data(irq, gc); |
diff --git a/drivers/irqchip/irq-hip04.c b/drivers/irqchip/irq-hip04.c index 9c8f833522e6..29b8f21b74d0 100644 --- a/drivers/irqchip/irq-hip04.c +++ b/drivers/irqchip/irq-hip04.c | |||
@@ -176,8 +176,7 @@ static void __exception_irq_entry hip04_handle_irq(struct pt_regs *regs) | |||
176 | irqnr = irqstat & GICC_IAR_INT_ID_MASK; | 176 | irqnr = irqstat & GICC_IAR_INT_ID_MASK; |
177 | 177 | ||
178 | if (likely(irqnr > 15 && irqnr <= HIP04_MAX_IRQS)) { | 178 | if (likely(irqnr > 15 && irqnr <= HIP04_MAX_IRQS)) { |
179 | irqnr = irq_find_mapping(hip04_data.domain, irqnr); | 179 | handle_domain_irq(hip04_data.domain, irqnr, regs); |
180 | handle_IRQ(irqnr, regs); | ||
181 | continue; | 180 | continue; |
182 | } | 181 | } |
183 | if (irqnr < 16) { | 182 | if (irqnr < 16) { |
diff --git a/drivers/irqchip/irq-sunxi-nmi.c b/drivers/irqchip/irq-sunxi-nmi.c index 12f547a44ae4..4a9ce5b50c5b 100644 --- a/drivers/irqchip/irq-sunxi-nmi.c +++ b/drivers/irqchip/irq-sunxi-nmi.c | |||
@@ -50,12 +50,12 @@ static struct sunxi_sc_nmi_reg_offs sun6i_reg_offs = { | |||
50 | static inline void sunxi_sc_nmi_write(struct irq_chip_generic *gc, u32 off, | 50 | static inline void sunxi_sc_nmi_write(struct irq_chip_generic *gc, u32 off, |
51 | u32 val) | 51 | u32 val) |
52 | { | 52 | { |
53 | irq_reg_writel(val, gc->reg_base + off); | 53 | irq_reg_writel(gc, val, off); |
54 | } | 54 | } |
55 | 55 | ||
56 | static inline u32 sunxi_sc_nmi_read(struct irq_chip_generic *gc, u32 off) | 56 | static inline u32 sunxi_sc_nmi_read(struct irq_chip_generic *gc, u32 off) |
57 | { | 57 | { |
58 | return irq_reg_readl(gc->reg_base + off); | 58 | return irq_reg_readl(gc, off); |
59 | } | 59 | } |
60 | 60 | ||
61 | static void sunxi_sc_nmi_handle_irq(unsigned int irq, struct irq_desc *desc) | 61 | static void sunxi_sc_nmi_handle_irq(unsigned int irq, struct irq_desc *desc) |
diff --git a/drivers/irqchip/irq-tb10x.c b/drivers/irqchip/irq-tb10x.c index 7c44c99bf1f2..accc20036a3c 100644 --- a/drivers/irqchip/irq-tb10x.c +++ b/drivers/irqchip/irq-tb10x.c | |||
@@ -43,12 +43,12 @@ | |||
43 | static inline void ab_irqctl_writereg(struct irq_chip_generic *gc, u32 reg, | 43 | static inline void ab_irqctl_writereg(struct irq_chip_generic *gc, u32 reg, |
44 | u32 val) | 44 | u32 val) |
45 | { | 45 | { |
46 | irq_reg_writel(val, gc->reg_base + reg); | 46 | irq_reg_writel(gc, val, reg); |
47 | } | 47 | } |
48 | 48 | ||
49 | static inline u32 ab_irqctl_readreg(struct irq_chip_generic *gc, u32 reg) | 49 | static inline u32 ab_irqctl_readreg(struct irq_chip_generic *gc, u32 reg) |
50 | { | 50 | { |
51 | return irq_reg_readl(gc->reg_base + reg); | 51 | return irq_reg_readl(gc, reg); |
52 | } | 52 | } |
53 | 53 | ||
54 | static int tb10x_irq_set_type(struct irq_data *data, unsigned int flow_type) | 54 | static int tb10x_irq_set_type(struct irq_data *data, unsigned int flow_type) |