aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh
diff options
context:
space:
mode:
authorMagnus Damm <damm@igel.co.jp>2007-09-21 05:16:42 -0400
committerPaul Mundt <lethal@linux-sh.org>2007-09-21 05:16:42 -0400
commitf18d533e3cd476aedf41fe1e6e9dc3e0a2446bba (patch)
tree64e54cb0572f62f8d171ce7f779b50226bfe931f /arch/sh
parent9964fa8bf952c5c4df9676223fab4cd886d18200 (diff)
sh: intc - initial SMP support.
This implements initial support for the SMP INTC (particularly INTC2) controllers. These are largely implemented as conventional blocks, with register sets grouped together at fixed strides relative to the CPU id. Signed-off-by: Magnus Damm <damm@igel.co.jp> Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/sh')
-rw-r--r--arch/sh/kernel/cpu/irq/intc.c78
1 files changed, 57 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