aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/sh/kernel/cpu/irq/intc.c78
-rw-r--r--include/asm-sh/hw_irq.h12
2 files changed, 69 insertions, 21 deletions
diff --git a/arch/sh/kernel/cpu/irq/intc.c b/arch/sh/kernel/cpu/irq/intc.c
index 481871fee1a8..6ac018c15e03 100644
--- a/arch/sh/kernel/cpu/irq/intc.c
+++ b/arch/sh/kernel/cpu/irq/intc.c
@@ -40,6 +40,9 @@ struct intc_handle_int {
40 40
41struct intc_desc_int { 41struct intc_desc_int {
42 unsigned long *reg; 42 unsigned long *reg;
43#ifdef CONFIG_SMP
44 unsigned long *smp;
45#endif
43 unsigned int nr_reg; 46 unsigned int nr_reg;
44 struct intc_handle_int *prio; 47 struct intc_handle_int *prio;
45 unsigned int nr_prio; 48 unsigned int nr_prio;
@@ -48,6 +51,16 @@ struct intc_desc_int {
48 struct irq_chip chip; 51 struct irq_chip chip;
49}; 52};
50 53
54#ifdef CONFIG_SMP
55#define IS_SMP(x) x.smp
56#define INTC_REG(d, x, c) (d->reg[(x)] + ((d->smp[(x)] & 0xff) * c))
57#define SMP_NR(d, x) ((d->smp[(x)] >> 8) ? (d->smp[(x)] >> 8) : 1)
58#else
59#define IS_SMP(x) 0
60#define INTC_REG(d, x, c) (d->reg[(x)])
61#define SMP_NR(d, x) 1
62#endif
63
51static unsigned int intc_prio_level[NR_IRQS]; /* for now */ 64static unsigned int intc_prio_level[NR_IRQS]; /* for now */
52 65
53static inline struct intc_desc_int *get_intc_desc(unsigned int irq) 66static inline struct intc_desc_int *get_intc_desc(unsigned int irq)
@@ -177,11 +190,14 @@ static void (*intc_disable_fns[])(unsigned long addr,
177static inline void _intc_enable(unsigned int irq, unsigned long handle) 190static inline void _intc_enable(unsigned int irq, unsigned long handle)
178{ 191{
179 struct intc_desc_int *d = get_intc_desc(irq); 192 struct intc_desc_int *d = get_intc_desc(irq);
180 unsigned long addr = d->reg[_INTC_ADDR_E(handle)]; 193 unsigned long addr;
194 unsigned int cpu;
181 195
182 intc_enable_fns[_INTC_MODE(handle)](addr, handle, 196 for (cpu = 0; cpu < SMP_NR(d, _INTC_ADDR_E(handle)); cpu++) {
183 intc_reg_fns[_INTC_FN(handle)], 197 addr = INTC_REG(d, _INTC_ADDR_E(handle), cpu);
184 irq); 198 intc_enable_fns[_INTC_MODE(handle)](addr, handle, intc_reg_fns\
199 [_INTC_FN(handle)], irq);
200 }
185} 201}
186 202
187static void intc_enable(unsigned int irq) 203static void intc_enable(unsigned int irq)
@@ -191,13 +207,16 @@ static void intc_enable(unsigned int irq)
191 207
192static void intc_disable(unsigned int irq) 208static void intc_disable(unsigned int irq)
193{ 209{
194 struct intc_desc_int *desc = get_intc_desc(irq); 210 struct intc_desc_int *d = get_intc_desc(irq);
195 unsigned long handle = (unsigned long) get_irq_chip_data(irq); 211 unsigned long handle = (unsigned long) get_irq_chip_data(irq);
196 unsigned long addr = desc->reg[_INTC_ADDR_D(handle)]; 212 unsigned long addr;
213 unsigned int cpu;
197 214
198 intc_disable_fns[_INTC_MODE(handle)](addr, handle, 215 for (cpu = 0; cpu < SMP_NR(d, _INTC_ADDR_D(handle)); cpu++) {
199 intc_reg_fns[_INTC_FN(handle)], 216 addr = INTC_REG(d, _INTC_ADDR_D(handle), cpu);
200 irq); 217 intc_disable_fns[_INTC_MODE(handle)](addr, handle,intc_reg_fns\
218 [_INTC_FN(handle)], irq);
219 }
201} 220}
202 221
203static struct intc_handle_int *intc_find_irq(struct intc_handle_int *hp, 222static struct intc_handle_int *intc_find_irq(struct intc_handle_int *hp,
@@ -276,7 +295,7 @@ static int intc_set_sense(unsigned int irq, unsigned int type)
276 295
277 ihp = intc_find_irq(d->sense, d->nr_sense, irq); 296 ihp = intc_find_irq(d->sense, d->nr_sense, irq);
278 if (ihp) { 297 if (ihp) {
279 addr = d->reg[_INTC_ADDR_E(ihp->handle)]; 298 addr = INTC_REG(d, _INTC_ADDR_E(ihp->handle), 0);
280 intc_reg_fns[_INTC_FN(ihp->handle)](addr, ihp->handle, value); 299 intc_reg_fns[_INTC_FN(ihp->handle)](addr, ihp->handle, value);
281 } 300 }
282 return 0; 301 return 0;
@@ -536,9 +555,26 @@ static void __init intc_register_irq(struct intc_desc *desc,
536 d->chip.mask(irq); 555 d->chip.mask(irq);
537} 556}
538 557
558static unsigned int __init save_reg(struct intc_desc_int *d,
559 unsigned int cnt,
560 unsigned long value,
561 unsigned int smp)
562{
563 if (value) {
564 d->reg[cnt] = value;
565#ifdef CONFIG_SMP
566 d->smp[cnt] = smp;
567#endif
568 return 1;
569 }
570
571 return 0;
572}
573
574
539void __init register_intc_controller(struct intc_desc *desc) 575void __init register_intc_controller(struct intc_desc *desc)
540{ 576{
541 unsigned int i, k; 577 unsigned int i, k, smp;
542 struct intc_desc_int *d; 578 struct intc_desc_int *d;
543 579
544 d = alloc_bootmem(sizeof(*d)); 580 d = alloc_bootmem(sizeof(*d));
@@ -548,14 +584,16 @@ void __init register_intc_controller(struct intc_desc *desc)
548 d->nr_reg += desc->sense_regs ? desc->nr_sense_regs : 0; 584 d->nr_reg += desc->sense_regs ? desc->nr_sense_regs : 0;
549 585
550 d->reg = alloc_bootmem(d->nr_reg * sizeof(*d->reg)); 586 d->reg = alloc_bootmem(d->nr_reg * sizeof(*d->reg));
587#ifdef CONFIG_SMP
588 d->smp = alloc_bootmem(d->nr_reg * sizeof(*d->smp));
589#endif
551 k = 0; 590 k = 0;
552 591
553 if (desc->mask_regs) { 592 if (desc->mask_regs) {
554 for (i = 0; i < desc->nr_mask_regs; i++) { 593 for (i = 0; i < desc->nr_mask_regs; i++) {
555 if (desc->mask_regs[i].set_reg) 594 smp = IS_SMP(desc->mask_regs[i]);
556 d->reg[k++] = desc->mask_regs[i].set_reg; 595 k += save_reg(d, k, desc->mask_regs[i].set_reg, smp);
557 if (desc->mask_regs[i].clr_reg) 596 k += save_reg(d, k, desc->mask_regs[i].clr_reg, smp);
558 d->reg[k++] = desc->mask_regs[i].clr_reg;
559 } 597 }
560 } 598 }
561 599
@@ -563,10 +601,9 @@ void __init register_intc_controller(struct intc_desc *desc)
563 d->prio = alloc_bootmem(desc->nr_vectors * sizeof(*d->prio)); 601 d->prio = alloc_bootmem(desc->nr_vectors * sizeof(*d->prio));
564 602
565 for (i = 0; i < desc->nr_prio_regs; i++) { 603 for (i = 0; i < desc->nr_prio_regs; i++) {
566 if (desc->prio_regs[i].set_reg) 604 smp = IS_SMP(desc->prio_regs[i]);
567 d->reg[k++] = desc->prio_regs[i].set_reg; 605 k += save_reg(d, k, desc->prio_regs[i].set_reg, smp);
568 if (desc->prio_regs[i].clr_reg) 606 k += save_reg(d, k, desc->prio_regs[i].clr_reg, smp);
569 d->reg[k++] = desc->prio_regs[i].clr_reg;
570 } 607 }
571 } 608 }
572 609
@@ -574,8 +611,7 @@ void __init register_intc_controller(struct intc_desc *desc)
574 d->sense = alloc_bootmem(desc->nr_vectors * sizeof(*d->sense)); 611 d->sense = alloc_bootmem(desc->nr_vectors * sizeof(*d->sense));
575 612
576 for (i = 0; i < desc->nr_sense_regs; i++) { 613 for (i = 0; i < desc->nr_sense_regs; i++) {
577 if (desc->sense_regs[i].reg) 614 k += save_reg(d, k, desc->sense_regs[i].reg, 0);
578 d->reg[k++] = desc->sense_regs[i].reg;
579 } 615 }
580 } 616 }
581 617
diff --git a/include/asm-sh/hw_irq.h b/include/asm-sh/hw_irq.h
index 96d971040503..cb0b6c9f7020 100644
--- a/include/asm-sh/hw_irq.h
+++ b/include/asm-sh/hw_irq.h
@@ -50,11 +50,17 @@ struct intc_group {
50struct intc_mask_reg { 50struct intc_mask_reg {
51 unsigned long set_reg, clr_reg, reg_width; 51 unsigned long set_reg, clr_reg, reg_width;
52 intc_enum enum_ids[32]; 52 intc_enum enum_ids[32];
53#ifdef CONFIG_SMP
54 unsigned long smp;
55#endif
53}; 56};
54 57
55struct intc_prio_reg { 58struct intc_prio_reg {
56 unsigned long set_reg, clr_reg, reg_width, field_width; 59 unsigned long set_reg, clr_reg, reg_width, field_width;
57 intc_enum enum_ids[16]; 60 intc_enum enum_ids[16];
61#ifdef CONFIG_SMP
62 unsigned long smp;
63#endif
58}; 64};
59 65
60struct intc_sense_reg { 66struct intc_sense_reg {
@@ -62,6 +68,12 @@ struct intc_sense_reg {
62 intc_enum enum_ids[16]; 68 intc_enum enum_ids[16];
63}; 69};
64 70
71#ifdef CONFIG_SMP
72#define INTC_SMP(stride, nr) .smp = (stride) | ((nr) << 8)
73#else
74#define INTC_SMP(stride, nr)
75#endif
76
65struct intc_desc { 77struct intc_desc {
66 struct intc_vect *vectors; 78 struct intc_vect *vectors;
67 unsigned int nr_vectors; 79 unsigned int nr_vectors;