diff options
Diffstat (limited to 'arch/sh')
-rw-r--r-- | arch/sh/kernel/cpu/irq/intc.c | 78 |
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 | ||
41 | struct intc_desc_int { | 41 | struct 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 | |||
51 | static unsigned int intc_prio_level[NR_IRQS]; /* for now */ | 64 | static unsigned int intc_prio_level[NR_IRQS]; /* for now */ |
52 | 65 | ||
53 | static inline struct intc_desc_int *get_intc_desc(unsigned int irq) | 66 | static inline struct intc_desc_int *get_intc_desc(unsigned int irq) |
@@ -177,11 +190,14 @@ static void (*intc_disable_fns[])(unsigned long addr, | |||
177 | static inline void _intc_enable(unsigned int irq, unsigned long handle) | 190 | static 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 | ||
187 | static void intc_enable(unsigned int irq) | 203 | static void intc_enable(unsigned int irq) |
@@ -191,13 +207,16 @@ static void intc_enable(unsigned int irq) | |||
191 | 207 | ||
192 | static void intc_disable(unsigned int irq) | 208 | static 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 | ||
203 | static struct intc_handle_int *intc_find_irq(struct intc_handle_int *hp, | 222 | static 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 | ||
558 | static 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 | |||
539 | void __init register_intc_controller(struct intc_desc *desc) | 575 | void __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 | ||