aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/common/vic.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/common/vic.c')
-rw-r--r--arch/arm/common/vic.c107
1 files changed, 52 insertions, 55 deletions
diff --git a/arch/arm/common/vic.c b/arch/arm/common/vic.c
index 1cf999ade4bc..ba65f6eedca6 100644
--- a/arch/arm/common/vic.c
+++ b/arch/arm/common/vic.c
@@ -266,13 +266,53 @@ static int vic_set_wake(unsigned int irq, unsigned int on)
266#endif /* CONFIG_PM */ 266#endif /* CONFIG_PM */
267 267
268static struct irq_chip vic_chip = { 268static struct irq_chip vic_chip = {
269 .name = "VIC", 269 .name = "VIC",
270 .ack = vic_ack_irq, 270 .ack = vic_ack_irq,
271 .mask = vic_mask_irq, 271 .mask = vic_mask_irq,
272 .unmask = vic_unmask_irq, 272 .unmask = vic_unmask_irq,
273 .set_wake = vic_set_wake, 273 .set_wake = vic_set_wake,
274}; 274};
275 275
276static void __init vic_disable(void __iomem *base)
277{
278 writel(0, base + VIC_INT_SELECT);
279 writel(0, base + VIC_INT_ENABLE);
280 writel(~0, base + VIC_INT_ENABLE_CLEAR);
281 writel(0, base + VIC_IRQ_STATUS);
282 writel(0, base + VIC_ITCR);
283 writel(~0, base + VIC_INT_SOFT_CLEAR);
284}
285
286static void __init vic_clear_interrupts(void __iomem *base)
287{
288 unsigned int i;
289
290 writel(0, base + VIC_PL190_VECT_ADDR);
291 for (i = 0; i < 19; i++) {
292 unsigned int value;
293
294 value = readl(base + VIC_PL190_VECT_ADDR);
295 writel(value, base + VIC_PL190_VECT_ADDR);
296 }
297}
298
299static void __init vic_set_irq_sources(void __iomem *base,
300 unsigned int irq_start, u32 vic_sources)
301{
302 unsigned int i;
303
304 for (i = 0; i < 32; i++) {
305 if (vic_sources & (1 << i)) {
306 unsigned int irq = irq_start + i;
307
308 set_irq_chip(irq, &vic_chip);
309 set_irq_chip_data(irq, base);
310 set_irq_handler(irq, handle_level_irq);
311 set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
312 }
313 }
314}
315
276/* 316/*
277 * The PL190 cell from ARM has been modified by ST to handle 64 interrupts. 317 * The PL190 cell from ARM has been modified by ST to handle 64 interrupts.
278 * The original cell has 32 interrupts, while the modified one has 64, 318 * The original cell has 32 interrupts, while the modified one has 64,
@@ -287,13 +327,7 @@ static void __init vic_init_st(void __iomem *base, unsigned int irq_start,
287 int vic_2nd_block = ((unsigned long)base & ~PAGE_MASK) != 0; 327 int vic_2nd_block = ((unsigned long)base & ~PAGE_MASK) != 0;
288 328
289 /* Disable all interrupts initially. */ 329 /* Disable all interrupts initially. */
290 330 vic_disable(base);
291 writel(0, base + VIC_INT_SELECT);
292 writel(0, base + VIC_INT_ENABLE);
293 writel(~0, base + VIC_INT_ENABLE_CLEAR);
294 writel(0, base + VIC_IRQ_STATUS);
295 writel(0, base + VIC_ITCR);
296 writel(~0, base + VIC_INT_SOFT_CLEAR);
297 331
298 /* 332 /*
299 * Make sure we clear all existing interrupts. The vector registers 333 * Make sure we clear all existing interrupts. The vector registers
@@ -302,13 +336,8 @@ static void __init vic_init_st(void __iomem *base, unsigned int irq_start,
302 * the second base address, which is 0x20 in the page 336 * the second base address, which is 0x20 in the page
303 */ 337 */
304 if (vic_2nd_block) { 338 if (vic_2nd_block) {
305 writel(0, base + VIC_PL190_VECT_ADDR); 339 vic_clear_interrupts(base);
306 for (i = 0; i < 19; i++) {
307 unsigned int value;
308 340
309 value = readl(base + VIC_PL190_VECT_ADDR);
310 writel(value, base + VIC_PL190_VECT_ADDR);
311 }
312 /* ST has 16 vectors as well, but we don't enable them by now */ 341 /* ST has 16 vectors as well, but we don't enable them by now */
313 for (i = 0; i < 16; i++) { 342 for (i = 0; i < 16; i++) {
314 void __iomem *reg = base + VIC_VECT_CNTL0 + (i * 4); 343 void __iomem *reg = base + VIC_VECT_CNTL0 + (i * 4);
@@ -318,16 +347,7 @@ static void __init vic_init_st(void __iomem *base, unsigned int irq_start,
318 writel(32, base + VIC_PL190_DEF_VECT_ADDR); 347 writel(32, base + VIC_PL190_DEF_VECT_ADDR);
319 } 348 }
320 349
321 for (i = 0; i < 32; i++) { 350 vic_set_irq_sources(base, irq_start, vic_sources);
322 if (vic_sources & (1 << i)) {
323 unsigned int irq = irq_start + i;
324
325 set_irq_chip(irq, &vic_chip);
326 set_irq_chip_data(irq, base);
327 set_irq_handler(irq, handle_level_irq);
328 set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
329 }
330 }
331} 351}
332 352
333/** 353/**
@@ -365,37 +385,14 @@ void __init vic_init(void __iomem *base, unsigned int irq_start,
365 } 385 }
366 386
367 /* Disable all interrupts initially. */ 387 /* Disable all interrupts initially. */
388 vic_disable(base);
368 389
369 writel(0, base + VIC_INT_SELECT); 390 /* Make sure we clear all existing interrupts */
370 writel(0, base + VIC_INT_ENABLE); 391 vic_clear_interrupts(base);
371 writel(~0, base + VIC_INT_ENABLE_CLEAR);
372 writel(0, base + VIC_IRQ_STATUS);
373 writel(0, base + VIC_ITCR);
374 writel(~0, base + VIC_INT_SOFT_CLEAR);
375
376 /*
377 * Make sure we clear all existing interrupts
378 */
379 writel(0, base + VIC_PL190_VECT_ADDR);
380 for (i = 0; i < 19; i++) {
381 unsigned int value;
382
383 value = readl(base + VIC_PL190_VECT_ADDR);
384 writel(value, base + VIC_PL190_VECT_ADDR);
385 }
386 392
387 vic_init2(base); 393 vic_init2(base);
388 394
389 for (i = 0; i < 32; i++) { 395 vic_set_irq_sources(base, irq_start, vic_sources);
390 if (vic_sources & (1 << i)) {
391 unsigned int irq = irq_start + i;
392
393 set_irq_chip(irq, &vic_chip);
394 set_irq_chip_data(irq, base);
395 set_irq_handler(irq, handle_level_irq);
396 set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
397 }
398 }
399 396
400 vic_pm_register(base, irq_start, resume_sources); 397 vic_pm_register(base, irq_start, resume_sources);
401} 398}