aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sh')
-rw-r--r--arch/sh/kernel/cpu/irq/intc.c79
-rw-r--r--arch/sh/kernel/cpu/sh3/setup-sh3.c15
2 files changed, 87 insertions, 7 deletions
diff --git a/arch/sh/kernel/cpu/irq/intc.c b/arch/sh/kernel/cpu/irq/intc.c
index 84806b2027f8..df3695406d80 100644
--- a/arch/sh/kernel/cpu/irq/intc.c
+++ b/arch/sh/kernel/cpu/irq/intc.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * Shared interrupt handling code for IPR and INTC2 types of IRQs. 2 * Shared interrupt handling code for IPR and INTC2 types of IRQs.
3 * 3 *
4 * Copyright (C) 2007 Magnus Damm 4 * Copyright (C) 2007, 2008 Magnus Damm
5 * 5 *
6 * Based on intc2.c and ipr.c 6 * Based on intc2.c and ipr.c
7 * 7 *
@@ -62,6 +62,9 @@ struct intc_desc_int {
62#endif 62#endif
63 63
64static unsigned int intc_prio_level[NR_IRQS]; /* for now */ 64static unsigned int intc_prio_level[NR_IRQS]; /* for now */
65#ifdef CONFIG_CPU_SH3
66static unsigned long ack_handle[NR_IRQS];
67#endif
65 68
66static inline struct intc_desc_int *get_intc_desc(unsigned int irq) 69static inline struct intc_desc_int *get_intc_desc(unsigned int irq)
67{ 70{
@@ -219,6 +222,25 @@ static void intc_disable(unsigned int irq)
219 } 222 }
220} 223}
221 224
225#ifdef CONFIG_CPU_SH3
226static void intc_mask_ack(unsigned int irq)
227{
228 struct intc_desc_int *d = get_intc_desc(irq);
229 unsigned long handle = ack_handle[irq];
230 unsigned long addr;
231
232 intc_disable(irq);
233
234 /* read register and write zero only to the assocaited bit */
235
236 if (handle) {
237 addr = INTC_REG(d, _INTC_ADDR_D(handle), 0);
238 ctrl_inb(addr);
239 ctrl_outb(0x3f ^ set_field(0, 1, handle), addr);
240 }
241}
242#endif
243
222static struct intc_handle_int *intc_find_irq(struct intc_handle_int *hp, 244static struct intc_handle_int *intc_find_irq(struct intc_handle_int *hp,
223 unsigned int nr_hp, 245 unsigned int nr_hp,
224 unsigned int irq) 246 unsigned int irq)
@@ -430,6 +452,40 @@ static unsigned int __init intc_prio_data(struct intc_desc *desc,
430 return 0; 452 return 0;
431} 453}
432 454
455#ifdef CONFIG_CPU_SH3
456static unsigned int __init intc_ack_data(struct intc_desc *desc,
457 struct intc_desc_int *d,
458 intc_enum enum_id)
459{
460 struct intc_mask_reg *mr = desc->ack_regs;
461 unsigned int i, j, fn, mode;
462 unsigned long reg_e, reg_d;
463
464 for (i = 0; mr && enum_id && i < desc->nr_ack_regs; i++) {
465 mr = desc->ack_regs + i;
466
467 for (j = 0; j < ARRAY_SIZE(mr->enum_ids); j++) {
468 if (mr->enum_ids[j] != enum_id)
469 continue;
470
471 fn = REG_FN_MODIFY_BASE;
472 mode = MODE_ENABLE_REG;
473 reg_e = mr->set_reg;
474 reg_d = mr->set_reg;
475
476 fn += (mr->reg_width >> 3) - 1;
477 return _INTC_MK(fn, mode,
478 intc_get_reg(d, reg_e),
479 intc_get_reg(d, reg_d),
480 1,
481 (mr->reg_width - 1) - j);
482 }
483 }
484
485 return 0;
486}
487#endif
488
433static unsigned int __init intc_sense_data(struct intc_desc *desc, 489static unsigned int __init intc_sense_data(struct intc_desc *desc,
434 struct intc_desc_int *d, 490 struct intc_desc_int *d,
435 intc_enum enum_id) 491 intc_enum enum_id)
@@ -530,6 +586,11 @@ static void __init intc_register_irq(struct intc_desc *desc,
530 586
531 /* irq should be disabled by default */ 587 /* irq should be disabled by default */
532 d->chip.mask(irq); 588 d->chip.mask(irq);
589
590#ifdef CONFIG_CPU_SH3
591 if (desc->ack_regs)
592 ack_handle[irq] = intc_ack_data(desc, d, enum_id);
593#endif
533} 594}
534 595
535static unsigned int __init save_reg(struct intc_desc_int *d, 596static unsigned int __init save_reg(struct intc_desc_int *d,
@@ -560,6 +621,9 @@ void __init register_intc_controller(struct intc_desc *desc)
560 d->nr_reg += desc->prio_regs ? desc->nr_prio_regs * 2 : 0; 621 d->nr_reg += desc->prio_regs ? desc->nr_prio_regs * 2 : 0;
561 d->nr_reg += desc->sense_regs ? desc->nr_sense_regs : 0; 622 d->nr_reg += desc->sense_regs ? desc->nr_sense_regs : 0;
562 623
624#ifdef CONFIG_CPU_SH3
625 d->nr_reg += desc->ack_regs ? desc->nr_ack_regs : 0;
626#endif
563 d->reg = alloc_bootmem(d->nr_reg * sizeof(*d->reg)); 627 d->reg = alloc_bootmem(d->nr_reg * sizeof(*d->reg));
564#ifdef CONFIG_SMP 628#ifdef CONFIG_SMP
565 d->smp = alloc_bootmem(d->nr_reg * sizeof(*d->smp)); 629 d->smp = alloc_bootmem(d->nr_reg * sizeof(*d->smp));
@@ -592,14 +656,23 @@ void __init register_intc_controller(struct intc_desc *desc)
592 } 656 }
593 } 657 }
594 658
595 BUG_ON(k > 256); /* _INTC_ADDR_E() and _INTC_ADDR_D() are 8 bits */
596
597 d->chip.name = desc->name; 659 d->chip.name = desc->name;
598 d->chip.mask = intc_disable; 660 d->chip.mask = intc_disable;
599 d->chip.unmask = intc_enable; 661 d->chip.unmask = intc_enable;
600 d->chip.mask_ack = intc_disable; 662 d->chip.mask_ack = intc_disable;
601 d->chip.set_type = intc_set_sense; 663 d->chip.set_type = intc_set_sense;
602 664
665#ifdef CONFIG_CPU_SH3
666 if (desc->ack_regs) {
667 for (i = 0; i < desc->nr_ack_regs; i++)
668 k += save_reg(d, k, desc->ack_regs[i].set_reg, 0);
669
670 d->chip.mask_ack = intc_mask_ack;
671 }
672#endif
673
674 BUG_ON(k > 256); /* _INTC_ADDR_E() and _INTC_ADDR_D() are 8 bits */
675
603 for (i = 0; i < desc->nr_vectors; i++) { 676 for (i = 0; i < desc->nr_vectors; i++) {
604 struct intc_vect *vect = desc->vectors + i; 677 struct intc_vect *vect = desc->vectors + i;
605 678
diff --git a/arch/sh/kernel/cpu/sh3/setup-sh3.c b/arch/sh/kernel/cpu/sh3/setup-sh3.c
index 28e7d6553091..c98846857855 100644
--- a/arch/sh/kernel/cpu/sh3/setup-sh3.c
+++ b/arch/sh/kernel/cpu/sh3/setup-sh3.c
@@ -35,15 +35,22 @@ static struct intc_prio_reg prio_registers[] __initdata = {
35 { 0xa4000018, 0, 16, 4, /* IPRD */ { 0, 0, IRQ5, IRQ4 } }, 35 { 0xa4000018, 0, 16, 4, /* IPRD */ { 0, 0, IRQ5, IRQ4 } },
36}; 36};
37 37
38static struct intc_mask_reg ack_registers[] __initdata = {
39 { 0xa4000004, 0, 8, /* IRR0 */
40 { 0, 0, IRQ5, IRQ4, IRQ3, IRQ2, IRQ1, IRQ0 } },
41};
42
38static struct intc_sense_reg sense_registers[] __initdata = { 43static struct intc_sense_reg sense_registers[] __initdata = {
39 { 0xa4000010, 16, 2, { 0, 0, IRQ5, IRQ4, IRQ3, IRQ2, IRQ1, IRQ0 } }, 44 { 0xa4000010, 16, 2, { 0, 0, IRQ5, IRQ4, IRQ3, IRQ2, IRQ1, IRQ0 } },
40}; 45};
41 46
42static DECLARE_INTC_DESC(intc_desc_irq0123, "sh3-irq0123", vectors_irq0123, 47static DECLARE_INTC_DESC_ACK(intc_desc_irq0123, "sh3-irq0123",
43 NULL, NULL, prio_registers, sense_registers); 48 vectors_irq0123, NULL, NULL,
49 prio_registers, sense_registers, ack_registers);
44 50
45static DECLARE_INTC_DESC(intc_desc_irq45, "sh3-irq45", vectors_irq45, 51static DECLARE_INTC_DESC_ACK(intc_desc_irq45, "sh3-irq45",
46 NULL, NULL, prio_registers, sense_registers); 52 vectors_irq45, NULL, NULL,
53 prio_registers, sense_registers, ack_registers);
47 54
48#define INTC_ICR1 0xa4000010UL 55#define INTC_ICR1 0xa4000010UL
49#define INTC_ICR1_IRQLVL (1<<14) 56#define INTC_ICR1_IRQLVL (1<<14)