diff options
Diffstat (limited to 'drivers/irqchip/irq-csky-apb-intc.c')
-rw-r--r-- | drivers/irqchip/irq-csky-apb-intc.c | 77 |
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 | ||
101 | static int __init | 101 | static int __init |
@@ -135,16 +135,10 @@ ck_intc_init_comm(struct device_node *node, struct device_node *parent) | |||
135 | static inline bool handle_irq_perbit(struct pt_regs *regs, u32 hwirq, | 135 | static 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 { | 151 | retry: |
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 | ||
165 | static int __init | 163 | static 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 { | 205 | retry: |
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 | ||
223 | static int __init | 230 | static 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); |