diff options
| author | Paul Mundt <lethal@linux-sh.org> | 2006-10-06 04:35:48 -0400 |
|---|---|---|
| committer | Paul Mundt <lethal@linux-sh.org> | 2006-10-06 04:35:48 -0400 |
| commit | 525ccc452c79db41874c5edac3f67618a0997d6f (patch) | |
| tree | 937987eae54debb7b23d4473089229a798bacc32 /arch/sh/kernel/cpu/irq | |
| parent | 580410005daecd8e9f0e1baa9ddadbb7f706e7e2 (diff) | |
sh: Convert INTC2 IRQ handler to irq_chip.
More struct irq_chip conversions, this time the INTC2 handlers.
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/sh/kernel/cpu/irq')
| -rw-r--r-- | arch/sh/kernel/cpu/irq/intc2.c | 138 |
1 files changed, 24 insertions, 114 deletions
diff --git a/arch/sh/kernel/cpu/irq/intc2.c b/arch/sh/kernel/cpu/irq/intc2.c index e30e4b7aa7..d4b2bb7e08 100644 --- a/arch/sh/kernel/cpu/irq/intc2.c +++ b/arch/sh/kernel/cpu/irq/intc2.c | |||
| @@ -10,93 +10,32 @@ | |||
| 10 | * These are the "new Hitachi style" interrupts, as present on the | 10 | * These are the "new Hitachi style" interrupts, as present on the |
| 11 | * Hitachi 7751, the STM ST40 STB1, SH7760, and SH7780. | 11 | * Hitachi 7751, the STM ST40 STB1, SH7760, and SH7780. |
| 12 | */ | 12 | */ |
| 13 | |||
| 14 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
| 15 | #include <linux/init.h> | 14 | #include <linux/init.h> |
| 16 | #include <linux/irq.h> | 15 | #include <linux/irq.h> |
| 17 | #include <asm/system.h> | 16 | #include <asm/system.h> |
| 18 | #include <asm/io.h> | 17 | #include <asm/io.h> |
| 19 | #include <asm/machvec.h> | ||
| 20 | |||
| 21 | struct intc2_data { | ||
| 22 | unsigned char msk_offset; | ||
| 23 | unsigned char msk_shift; | ||
| 24 | |||
| 25 | int (*clear_irq) (int); | ||
| 26 | }; | ||
| 27 | |||
| 28 | static struct intc2_data intc2_data[NR_INTC2_IRQS]; | ||
| 29 | |||
| 30 | static void enable_intc2_irq(unsigned int irq); | ||
| 31 | static void disable_intc2_irq(unsigned int irq); | ||
| 32 | |||
| 33 | /* shutdown is same as "disable" */ | ||
| 34 | #define shutdown_intc2_irq disable_intc2_irq | ||
| 35 | |||
| 36 | static void mask_and_ack_intc2(unsigned int); | ||
| 37 | static void end_intc2_irq(unsigned int irq); | ||
| 38 | |||
| 39 | static unsigned int startup_intc2_irq(unsigned int irq) | ||
| 40 | { | ||
| 41 | enable_intc2_irq(irq); | ||
| 42 | return 0; /* never anything pending */ | ||
| 43 | } | ||
| 44 | |||
| 45 | static struct hw_interrupt_type intc2_irq_type = { | ||
| 46 | .typename = "INTC2-IRQ", | ||
| 47 | .startup = startup_intc2_irq, | ||
| 48 | .shutdown = shutdown_intc2_irq, | ||
| 49 | .enable = enable_intc2_irq, | ||
| 50 | .disable = disable_intc2_irq, | ||
| 51 | .ack = mask_and_ack_intc2, | ||
| 52 | .end = end_intc2_irq | ||
| 53 | }; | ||
| 54 | 18 | ||
| 55 | static void disable_intc2_irq(unsigned int irq) | 19 | static void disable_intc2_irq(unsigned int irq) |
| 56 | { | 20 | { |
| 57 | int irq_offset = irq - INTC2_FIRST_IRQ; | 21 | struct intc2_data *p = get_irq_chip_data(irq); |
| 58 | int msk_shift, msk_offset; | 22 | ctrl_outl(1 << p->msk_shift, |
| 59 | 23 | INTC2_BASE + INTC2_INTMSK_OFFSET + p->msk_offset); | |
| 60 | /* Sanity check */ | ||
| 61 | if (unlikely(irq_offset < 0 || irq_offset >= NR_INTC2_IRQS)) | ||
| 62 | return; | ||
| 63 | |||
| 64 | msk_shift = intc2_data[irq_offset].msk_shift; | ||
| 65 | msk_offset = intc2_data[irq_offset].msk_offset; | ||
| 66 | |||
| 67 | ctrl_outl(1 << msk_shift, | ||
| 68 | INTC2_BASE + INTC2_INTMSK_OFFSET + msk_offset); | ||
| 69 | } | 24 | } |
| 70 | 25 | ||
| 71 | static void enable_intc2_irq(unsigned int irq) | 26 | static void enable_intc2_irq(unsigned int irq) |
| 72 | { | 27 | { |
| 73 | int irq_offset = irq - INTC2_FIRST_IRQ; | 28 | struct intc2_data *p = get_irq_chip_data(irq); |
| 74 | int msk_shift, msk_offset; | 29 | ctrl_outl(1 << p->msk_shift, |
| 75 | 30 | INTC2_BASE + INTC2_INTMSKCLR_OFFSET + p->msk_offset); | |
| 76 | /* Sanity check */ | ||
| 77 | if (unlikely(irq_offset < 0 || irq_offset >= NR_INTC2_IRQS)) | ||
| 78 | return; | ||
| 79 | |||
| 80 | msk_shift = intc2_data[irq_offset].msk_shift; | ||
| 81 | msk_offset = intc2_data[irq_offset].msk_offset; | ||
| 82 | |||
| 83 | ctrl_outl(1 << msk_shift, | ||
| 84 | INTC2_BASE + INTC2_INTMSKCLR_OFFSET + msk_offset); | ||
| 85 | } | ||
| 86 | |||
| 87 | static void mask_and_ack_intc2(unsigned int irq) | ||
| 88 | { | ||
| 89 | disable_intc2_irq(irq); | ||
| 90 | } | 31 | } |
| 91 | 32 | ||
| 92 | static void end_intc2_irq(unsigned int irq) | 33 | static struct irq_chip intc2_irq_chip = { |
| 93 | { | 34 | .typename = "intc2", |
| 94 | if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) | 35 | .mask = disable_intc2_irq, |
| 95 | enable_intc2_irq(irq); | 36 | .unmask = enable_intc2_irq, |
| 96 | 37 | .mask_ack = disable_intc2_irq, | |
| 97 | if (unlikely(intc2_data[irq - INTC2_FIRST_IRQ].clear_irq)) | 38 | }; |
| 98 | intc2_data[irq - INTC2_FIRST_IRQ].clear_irq(irq); | ||
| 99 | } | ||
| 100 | 39 | ||
| 101 | /* | 40 | /* |
| 102 | * Setup an INTC2 style interrupt. | 41 | * Setup an INTC2 style interrupt. |
| @@ -108,46 +47,30 @@ static void end_intc2_irq(unsigned int irq) | |||
| 108 | * | | | | | 47 | * | | | | |
| 109 | * make_intc2_irq(84, 0, 16, 0, 13); | 48 | * make_intc2_irq(84, 0, 16, 0, 13); |
| 110 | */ | 49 | */ |
| 111 | void make_intc2_irq(unsigned int irq, | 50 | void make_intc2_irq(struct intc2_data *p) |
| 112 | unsigned int ipr_offset, unsigned int ipr_shift, | ||
| 113 | unsigned int msk_offset, unsigned int msk_shift, | ||
| 114 | unsigned int priority) | ||
| 115 | { | 51 | { |
| 116 | int irq_offset = irq - INTC2_FIRST_IRQ; | ||
| 117 | unsigned int flags; | 52 | unsigned int flags; |
| 118 | unsigned long ipr; | 53 | unsigned long ipr; |
| 119 | 54 | ||
| 120 | if (unlikely(irq_offset < 0 || irq_offset >= NR_INTC2_IRQS)) | 55 | disable_irq_nosync(p->irq); |
| 121 | return; | ||
| 122 | |||
| 123 | disable_irq_nosync(irq); | ||
| 124 | |||
| 125 | /* Fill the data we need */ | ||
| 126 | intc2_data[irq_offset].msk_offset = msk_offset; | ||
| 127 | intc2_data[irq_offset].msk_shift = msk_shift; | ||
| 128 | intc2_data[irq_offset].clear_irq = NULL; | ||
| 129 | 56 | ||
| 130 | /* Set the priority level */ | 57 | /* Set the priority level */ |
| 131 | local_irq_save(flags); | 58 | local_irq_save(flags); |
| 132 | 59 | ||
| 133 | ipr = ctrl_inl(INTC2_BASE + INTC2_INTPRI_OFFSET + ipr_offset); | 60 | ipr = ctrl_inl(INTC2_BASE + INTC2_INTPRI_OFFSET + p->ipr_offset); |
| 134 | ipr &= ~(0xf << ipr_shift); | 61 | ipr &= ~(0xf << p->ipr_shift); |
| 135 | ipr |= priority << ipr_shift; | 62 | ipr |= p->priority << p->ipr_shift; |
| 136 | ctrl_outl(ipr, INTC2_BASE + INTC2_INTPRI_OFFSET + ipr_offset); | 63 | ctrl_outl(ipr, INTC2_BASE + INTC2_INTPRI_OFFSET + p->ipr_offset); |
| 137 | 64 | ||
| 138 | local_irq_restore(flags); | 65 | local_irq_restore(flags); |
| 139 | 66 | ||
| 140 | irq_desc[irq].chip = &intc2_irq_type; | 67 | set_irq_chip_and_handler(p->irq, &intc2_irq_chip, handle_level_irq); |
| 68 | set_irq_chip_data(p->irq, p); | ||
| 141 | 69 | ||
| 142 | disable_intc2_irq(irq); | 70 | enable_intc2_irq(p->irq); |
| 143 | } | 71 | } |
| 144 | 72 | ||
| 145 | static struct intc2_init { | 73 | static struct intc2_data intc2_irq_table[] = { |
| 146 | unsigned short irq; | ||
| 147 | unsigned char ipr_offset, ipr_shift; | ||
| 148 | unsigned char msk_offset, msk_shift; | ||
| 149 | unsigned char priority; | ||
| 150 | } intc2_init_data[] __initdata = { | ||
| 151 | #if defined(CONFIG_CPU_SUBTYPE_ST40) | 74 | #if defined(CONFIG_CPU_SUBTYPE_ST40) |
| 152 | {64, 0, 0, 0, 0, 13}, /* PCI serr */ | 75 | {64, 0, 0, 0, 0, 13}, /* PCI serr */ |
| 153 | {65, 0, 4, 0, 1, 13}, /* PCI err */ | 76 | {65, 0, 4, 0, 1, 13}, /* PCI err */ |
| @@ -266,19 +189,6 @@ void __init init_IRQ_intc2(void) | |||
| 266 | { | 189 | { |
| 267 | int i; | 190 | int i; |
| 268 | 191 | ||
| 269 | for (i = 0; i < ARRAY_SIZE(intc2_init_data); i++) { | 192 | for (i = 0; i < ARRAY_SIZE(intc2_irq_table); i++) |
| 270 | struct intc2_init *p = intc2_init_data + i; | 193 | make_intc2_irq(intc2_irq_table + i); |
| 271 | make_intc2_irq(p->irq, p->ipr_offset, p->ipr_shift, | ||
| 272 | p-> msk_offset, p->msk_shift, p->priority); | ||
| 273 | } | ||
| 274 | } | ||
| 275 | |||
| 276 | /* Adds a termination callback to the interrupt */ | ||
| 277 | void intc2_add_clear_irq(int irq, int (*fn)(int)) | ||
| 278 | { | ||
| 279 | if (unlikely(irq < INTC2_FIRST_IRQ)) | ||
| 280 | return; | ||
| 281 | |||
| 282 | intc2_data[irq - INTC2_FIRST_IRQ].clear_irq = fn; | ||
| 283 | } | 194 | } |
| 284 | |||
