summaryrefslogtreecommitdiffstats
path: root/drivers/irqchip/irq-csky-apb-intc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/irqchip/irq-csky-apb-intc.c')
-rw-r--r--drivers/irqchip/irq-csky-apb-intc.c77
1 files changed, 42 insertions, 35 deletions
diff --git a/drivers/irqchip/irq-csky-apb-intc.c b/drivers/irqchip/irq-csky-apb-intc.c
index 2543baba8b1f..5a2ec43b7ddd 100644
--- a/drivers/irqchip/irq-csky-apb-intc.c
+++ b/drivers/irqchip/irq-csky-apb-intc.c
@@ -95,7 +95,7 @@ static inline void setup_irq_channel(u32 magic, void __iomem *reg_addr)
95 95
96 /* Setup 64 channel slots */ 96 /* Setup 64 channel slots */
97 for (i = 0; i < INTC_IRQS; i += 4) 97 for (i = 0; i < INTC_IRQS; i += 4)
98 writel_relaxed(build_channel_val(i, magic), reg_addr + i); 98 writel(build_channel_val(i, magic), reg_addr + i);
99} 99}
100 100
101static int __init 101static int __init
@@ -135,16 +135,10 @@ ck_intc_init_comm(struct device_node *node, struct device_node *parent)
135static inline bool handle_irq_perbit(struct pt_regs *regs, u32 hwirq, 135static inline bool handle_irq_perbit(struct pt_regs *regs, u32 hwirq,
136 u32 irq_base) 136 u32 irq_base)
137{ 137{
138 u32 irq;
139
140 if (hwirq == 0) 138 if (hwirq == 0)
141 return 0; 139 return 0;
142 140
143 while (hwirq) { 141 handle_domain_irq(root_domain, irq_base + __fls(hwirq), regs);
144 irq = __ffs(hwirq);
145 hwirq &= ~BIT(irq);
146 handle_domain_irq(root_domain, irq_base + irq, regs);
147 }
148 142
149 return 1; 143 return 1;
150} 144}
@@ -154,12 +148,16 @@ static void gx_irq_handler(struct pt_regs *regs)
154{ 148{
155 bool ret; 149 bool ret;
156 150
157 do { 151retry:
158 ret = handle_irq_perbit(regs, 152 ret = handle_irq_perbit(regs,
159 readl_relaxed(reg_base + GX_INTC_PEN31_00), 0); 153 readl(reg_base + GX_INTC_PEN63_32), 32);
160 ret |= handle_irq_perbit(regs, 154 if (ret)
161 readl_relaxed(reg_base + GX_INTC_PEN63_32), 32); 155 goto retry;
162 } while (ret); 156
157 ret = handle_irq_perbit(regs,
158 readl(reg_base + GX_INTC_PEN31_00), 0);
159 if (ret)
160 goto retry;
163} 161}
164 162
165static int __init 163static int __init
@@ -174,14 +172,14 @@ gx_intc_init(struct device_node *node, struct device_node *parent)
174 /* 172 /*
175 * Initial enable reg to disable all interrupts 173 * Initial enable reg to disable all interrupts
176 */ 174 */
177 writel_relaxed(0x0, reg_base + GX_INTC_NEN31_00); 175 writel(0x0, reg_base + GX_INTC_NEN31_00);
178 writel_relaxed(0x0, reg_base + GX_INTC_NEN63_32); 176 writel(0x0, reg_base + GX_INTC_NEN63_32);
179 177
180 /* 178 /*
181 * Initial mask reg with all unmasked, because we only use enalbe reg 179 * Initial mask reg with all unmasked, because we only use enalbe reg
182 */ 180 */
183 writel_relaxed(0x0, reg_base + GX_INTC_NMASK31_00); 181 writel(0x0, reg_base + GX_INTC_NMASK31_00);
184 writel_relaxed(0x0, reg_base + GX_INTC_NMASK63_32); 182 writel(0x0, reg_base + GX_INTC_NMASK63_32);
185 183
186 setup_irq_channel(0x03020100, reg_base + GX_INTC_SOURCE); 184 setup_irq_channel(0x03020100, reg_base + GX_INTC_SOURCE);
187 185
@@ -204,20 +202,29 @@ static void ck_irq_handler(struct pt_regs *regs)
204 void __iomem *reg_pen_lo = reg_base + CK_INTC_PEN31_00; 202 void __iomem *reg_pen_lo = reg_base + CK_INTC_PEN31_00;
205 void __iomem *reg_pen_hi = reg_base + CK_INTC_PEN63_32; 203 void __iomem *reg_pen_hi = reg_base + CK_INTC_PEN63_32;
206 204
207 do { 205retry:
208 /* handle 0 - 31 irqs */ 206 /* handle 0 - 63 irqs */
209 ret = handle_irq_perbit(regs, readl_relaxed(reg_pen_lo), 0); 207 ret = handle_irq_perbit(regs, readl(reg_pen_hi), 32);
210 ret |= handle_irq_perbit(regs, readl_relaxed(reg_pen_hi), 32); 208 if (ret)
209 goto retry;
211 210
212 if (nr_irq == INTC_IRQS) 211 ret = handle_irq_perbit(regs, readl(reg_pen_lo), 0);
213 continue; 212 if (ret)
213 goto retry;
214
215 if (nr_irq == INTC_IRQS)
216 return;
214 217
215 /* handle 64 - 127 irqs */ 218 /* handle 64 - 127 irqs */
216 ret |= handle_irq_perbit(regs, 219 ret = handle_irq_perbit(regs,
217 readl_relaxed(reg_pen_lo + CK_INTC_DUAL_BASE), 64); 220 readl(reg_pen_hi + CK_INTC_DUAL_BASE), 96);
218 ret |= handle_irq_perbit(regs, 221 if (ret)
219 readl_relaxed(reg_pen_hi + CK_INTC_DUAL_BASE), 96); 222 goto retry;
220 } while (ret); 223
224 ret = handle_irq_perbit(regs,
225 readl(reg_pen_lo + CK_INTC_DUAL_BASE), 64);
226 if (ret)
227 goto retry;
221} 228}
222 229
223static int __init 230static int __init
@@ -230,11 +237,11 @@ ck_intc_init(struct device_node *node, struct device_node *parent)
230 return ret; 237 return ret;
231 238
232 /* Initial enable reg to disable all interrupts */ 239 /* Initial enable reg to disable all interrupts */
233 writel_relaxed(0, reg_base + CK_INTC_NEN31_00); 240 writel(0, reg_base + CK_INTC_NEN31_00);
234 writel_relaxed(0, reg_base + CK_INTC_NEN63_32); 241 writel(0, reg_base + CK_INTC_NEN63_32);
235 242
236 /* Enable irq intc */ 243 /* Enable irq intc */
237 writel_relaxed(BIT(31), reg_base + CK_INTC_ICR); 244 writel(BIT(31), reg_base + CK_INTC_ICR);
238 245
239 ck_set_gc(node, reg_base, CK_INTC_NEN31_00, 0); 246 ck_set_gc(node, reg_base, CK_INTC_NEN31_00, 0);
240 ck_set_gc(node, reg_base, CK_INTC_NEN63_32, 32); 247 ck_set_gc(node, reg_base, CK_INTC_NEN63_32, 32);
@@ -260,8 +267,8 @@ ck_dual_intc_init(struct device_node *node, struct device_node *parent)
260 return ret; 267 return ret;
261 268
262 /* Initial enable reg to disable all interrupts */ 269 /* Initial enable reg to disable all interrupts */
263 writel_relaxed(0, reg_base + CK_INTC_NEN31_00 + CK_INTC_DUAL_BASE); 270 writel(0, reg_base + CK_INTC_NEN31_00 + CK_INTC_DUAL_BASE);
264 writel_relaxed(0, reg_base + CK_INTC_NEN63_32 + CK_INTC_DUAL_BASE); 271 writel(0, reg_base + CK_INTC_NEN63_32 + CK_INTC_DUAL_BASE);
265 272
266 ck_set_gc(node, reg_base + CK_INTC_DUAL_BASE, CK_INTC_NEN31_00, 64); 273 ck_set_gc(node, reg_base + CK_INTC_DUAL_BASE, CK_INTC_NEN31_00, 64);
267 ck_set_gc(node, reg_base + CK_INTC_DUAL_BASE, CK_INTC_NEN63_32, 96); 274 ck_set_gc(node, reg_base + CK_INTC_DUAL_BASE, CK_INTC_NEN63_32, 96);