Loading arch/sh/kernel/cpu/irq/intc2.c +24 −114 Original line number Original line Diff line number Diff line Loading @@ -10,93 +10,32 @@ * These are the "new Hitachi style" interrupts, as present on the * These are the "new Hitachi style" interrupts, as present on the * Hitachi 7751, the STM ST40 STB1, SH7760, and SH7780. * Hitachi 7751, the STM ST40 STB1, SH7760, and SH7780. */ */ #include <linux/kernel.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/init.h> #include <linux/irq.h> #include <linux/irq.h> #include <asm/system.h> #include <asm/system.h> #include <asm/io.h> #include <asm/io.h> #include <asm/machvec.h> struct intc2_data { unsigned char msk_offset; unsigned char msk_shift; int (*clear_irq) (int); }; static struct intc2_data intc2_data[NR_INTC2_IRQS]; static void enable_intc2_irq(unsigned int irq); static void disable_intc2_irq(unsigned int irq); /* shutdown is same as "disable" */ #define shutdown_intc2_irq disable_intc2_irq static void mask_and_ack_intc2(unsigned int); static void end_intc2_irq(unsigned int irq); static unsigned int startup_intc2_irq(unsigned int irq) { enable_intc2_irq(irq); return 0; /* never anything pending */ } static struct hw_interrupt_type intc2_irq_type = { .typename = "INTC2-IRQ", .startup = startup_intc2_irq, .shutdown = shutdown_intc2_irq, .enable = enable_intc2_irq, .disable = disable_intc2_irq, .ack = mask_and_ack_intc2, .end = end_intc2_irq }; static void disable_intc2_irq(unsigned int irq) static void disable_intc2_irq(unsigned int irq) { { int irq_offset = irq - INTC2_FIRST_IRQ; struct intc2_data *p = get_irq_chip_data(irq); int msk_shift, msk_offset; ctrl_outl(1 << p->msk_shift, INTC2_BASE + INTC2_INTMSK_OFFSET + p->msk_offset); /* Sanity check */ if (unlikely(irq_offset < 0 || irq_offset >= NR_INTC2_IRQS)) return; msk_shift = intc2_data[irq_offset].msk_shift; msk_offset = intc2_data[irq_offset].msk_offset; ctrl_outl(1 << msk_shift, INTC2_BASE + INTC2_INTMSK_OFFSET + msk_offset); } } static void enable_intc2_irq(unsigned int irq) static void enable_intc2_irq(unsigned int irq) { { int irq_offset = irq - INTC2_FIRST_IRQ; struct intc2_data *p = get_irq_chip_data(irq); int msk_shift, msk_offset; ctrl_outl(1 << p->msk_shift, INTC2_BASE + INTC2_INTMSKCLR_OFFSET + p->msk_offset); /* Sanity check */ if (unlikely(irq_offset < 0 || irq_offset >= NR_INTC2_IRQS)) return; msk_shift = intc2_data[irq_offset].msk_shift; msk_offset = intc2_data[irq_offset].msk_offset; ctrl_outl(1 << msk_shift, INTC2_BASE + INTC2_INTMSKCLR_OFFSET + msk_offset); } static void mask_and_ack_intc2(unsigned int irq) { disable_intc2_irq(irq); } } static void end_intc2_irq(unsigned int irq) static struct irq_chip intc2_irq_chip = { { .typename = "intc2", if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) .mask = disable_intc2_irq, enable_intc2_irq(irq); .unmask = enable_intc2_irq, .mask_ack = disable_intc2_irq, if (unlikely(intc2_data[irq - INTC2_FIRST_IRQ].clear_irq)) }; intc2_data[irq - INTC2_FIRST_IRQ].clear_irq(irq); } /* /* * Setup an INTC2 style interrupt. * Setup an INTC2 style interrupt. Loading @@ -108,46 +47,30 @@ static void end_intc2_irq(unsigned int irq) * | | | | * | | | | * make_intc2_irq(84, 0, 16, 0, 13); * make_intc2_irq(84, 0, 16, 0, 13); */ */ void make_intc2_irq(unsigned int irq, void make_intc2_irq(struct intc2_data *p) unsigned int ipr_offset, unsigned int ipr_shift, unsigned int msk_offset, unsigned int msk_shift, unsigned int priority) { { int irq_offset = irq - INTC2_FIRST_IRQ; unsigned int flags; unsigned int flags; unsigned long ipr; unsigned long ipr; if (unlikely(irq_offset < 0 || irq_offset >= NR_INTC2_IRQS)) disable_irq_nosync(p->irq); return; disable_irq_nosync(irq); /* Fill the data we need */ intc2_data[irq_offset].msk_offset = msk_offset; intc2_data[irq_offset].msk_shift = msk_shift; intc2_data[irq_offset].clear_irq = NULL; /* Set the priority level */ /* Set the priority level */ local_irq_save(flags); local_irq_save(flags); ipr = ctrl_inl(INTC2_BASE + INTC2_INTPRI_OFFSET + ipr_offset); ipr = ctrl_inl(INTC2_BASE + INTC2_INTPRI_OFFSET + p->ipr_offset); ipr &= ~(0xf << ipr_shift); ipr &= ~(0xf << p->ipr_shift); ipr |= priority << ipr_shift; ipr |= p->priority << p->ipr_shift; ctrl_outl(ipr, INTC2_BASE + INTC2_INTPRI_OFFSET + ipr_offset); ctrl_outl(ipr, INTC2_BASE + INTC2_INTPRI_OFFSET + p->ipr_offset); local_irq_restore(flags); local_irq_restore(flags); irq_desc[irq].chip = &intc2_irq_type; set_irq_chip_and_handler(p->irq, &intc2_irq_chip, handle_level_irq); set_irq_chip_data(p->irq, p); disable_intc2_irq(irq); enable_intc2_irq(p->irq); } } static struct intc2_init { static struct intc2_data intc2_irq_table[] = { unsigned short irq; unsigned char ipr_offset, ipr_shift; unsigned char msk_offset, msk_shift; unsigned char priority; } intc2_init_data[] __initdata = { #if defined(CONFIG_CPU_SUBTYPE_ST40) #if defined(CONFIG_CPU_SUBTYPE_ST40) {64, 0, 0, 0, 0, 13}, /* PCI serr */ {64, 0, 0, 0, 0, 13}, /* PCI serr */ {65, 0, 4, 0, 1, 13}, /* PCI err */ {65, 0, 4, 0, 1, 13}, /* PCI err */ Loading Loading @@ -266,19 +189,6 @@ void __init init_IRQ_intc2(void) { { int i; int i; for (i = 0; i < ARRAY_SIZE(intc2_init_data); i++) { for (i = 0; i < ARRAY_SIZE(intc2_irq_table); i++) struct intc2_init *p = intc2_init_data + i; make_intc2_irq(intc2_irq_table + i); make_intc2_irq(p->irq, p->ipr_offset, p->ipr_shift, p-> msk_offset, p->msk_shift, p->priority); } } /* Adds a termination callback to the interrupt */ void intc2_add_clear_irq(int irq, int (*fn)(int)) { if (unlikely(irq < INTC2_FIRST_IRQ)) return; intc2_data[irq - INTC2_FIRST_IRQ].clear_irq = fn; } } include/asm-sh/irq.h +8 −6 Original line number Original line Diff line number Diff line Loading @@ -697,13 +697,15 @@ extern int ipr_irq_demux(int irq); #define INTC2_INTPRI_OFFSET 0x00 #define INTC2_INTPRI_OFFSET 0x00 void make_intc2_irq(unsigned int irq, struct intc2_data { unsigned int ipr_offset, unsigned int ipr_shift, unsigned short irq; unsigned int msk_offset, unsigned int msk_shift, unsigned char ipr_offset, ipr_shift; unsigned int priority); unsigned char msk_offset, msk_shift; unsigned char priority; }; void make_intc2_irq(struct intc2_data *); void init_IRQ_intc2(void); void init_IRQ_intc2(void); void intc2_add_clear_irq(int irq, int (*fn)(int)); #endif #endif extern int shmse_irq_demux(int irq); extern int shmse_irq_demux(int irq); Loading Loading
arch/sh/kernel/cpu/irq/intc2.c +24 −114 Original line number Original line Diff line number Diff line Loading @@ -10,93 +10,32 @@ * These are the "new Hitachi style" interrupts, as present on the * These are the "new Hitachi style" interrupts, as present on the * Hitachi 7751, the STM ST40 STB1, SH7760, and SH7780. * Hitachi 7751, the STM ST40 STB1, SH7760, and SH7780. */ */ #include <linux/kernel.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/init.h> #include <linux/irq.h> #include <linux/irq.h> #include <asm/system.h> #include <asm/system.h> #include <asm/io.h> #include <asm/io.h> #include <asm/machvec.h> struct intc2_data { unsigned char msk_offset; unsigned char msk_shift; int (*clear_irq) (int); }; static struct intc2_data intc2_data[NR_INTC2_IRQS]; static void enable_intc2_irq(unsigned int irq); static void disable_intc2_irq(unsigned int irq); /* shutdown is same as "disable" */ #define shutdown_intc2_irq disable_intc2_irq static void mask_and_ack_intc2(unsigned int); static void end_intc2_irq(unsigned int irq); static unsigned int startup_intc2_irq(unsigned int irq) { enable_intc2_irq(irq); return 0; /* never anything pending */ } static struct hw_interrupt_type intc2_irq_type = { .typename = "INTC2-IRQ", .startup = startup_intc2_irq, .shutdown = shutdown_intc2_irq, .enable = enable_intc2_irq, .disable = disable_intc2_irq, .ack = mask_and_ack_intc2, .end = end_intc2_irq }; static void disable_intc2_irq(unsigned int irq) static void disable_intc2_irq(unsigned int irq) { { int irq_offset = irq - INTC2_FIRST_IRQ; struct intc2_data *p = get_irq_chip_data(irq); int msk_shift, msk_offset; ctrl_outl(1 << p->msk_shift, INTC2_BASE + INTC2_INTMSK_OFFSET + p->msk_offset); /* Sanity check */ if (unlikely(irq_offset < 0 || irq_offset >= NR_INTC2_IRQS)) return; msk_shift = intc2_data[irq_offset].msk_shift; msk_offset = intc2_data[irq_offset].msk_offset; ctrl_outl(1 << msk_shift, INTC2_BASE + INTC2_INTMSK_OFFSET + msk_offset); } } static void enable_intc2_irq(unsigned int irq) static void enable_intc2_irq(unsigned int irq) { { int irq_offset = irq - INTC2_FIRST_IRQ; struct intc2_data *p = get_irq_chip_data(irq); int msk_shift, msk_offset; ctrl_outl(1 << p->msk_shift, INTC2_BASE + INTC2_INTMSKCLR_OFFSET + p->msk_offset); /* Sanity check */ if (unlikely(irq_offset < 0 || irq_offset >= NR_INTC2_IRQS)) return; msk_shift = intc2_data[irq_offset].msk_shift; msk_offset = intc2_data[irq_offset].msk_offset; ctrl_outl(1 << msk_shift, INTC2_BASE + INTC2_INTMSKCLR_OFFSET + msk_offset); } static void mask_and_ack_intc2(unsigned int irq) { disable_intc2_irq(irq); } } static void end_intc2_irq(unsigned int irq) static struct irq_chip intc2_irq_chip = { { .typename = "intc2", if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) .mask = disable_intc2_irq, enable_intc2_irq(irq); .unmask = enable_intc2_irq, .mask_ack = disable_intc2_irq, if (unlikely(intc2_data[irq - INTC2_FIRST_IRQ].clear_irq)) }; intc2_data[irq - INTC2_FIRST_IRQ].clear_irq(irq); } /* /* * Setup an INTC2 style interrupt. * Setup an INTC2 style interrupt. Loading @@ -108,46 +47,30 @@ static void end_intc2_irq(unsigned int irq) * | | | | * | | | | * make_intc2_irq(84, 0, 16, 0, 13); * make_intc2_irq(84, 0, 16, 0, 13); */ */ void make_intc2_irq(unsigned int irq, void make_intc2_irq(struct intc2_data *p) unsigned int ipr_offset, unsigned int ipr_shift, unsigned int msk_offset, unsigned int msk_shift, unsigned int priority) { { int irq_offset = irq - INTC2_FIRST_IRQ; unsigned int flags; unsigned int flags; unsigned long ipr; unsigned long ipr; if (unlikely(irq_offset < 0 || irq_offset >= NR_INTC2_IRQS)) disable_irq_nosync(p->irq); return; disable_irq_nosync(irq); /* Fill the data we need */ intc2_data[irq_offset].msk_offset = msk_offset; intc2_data[irq_offset].msk_shift = msk_shift; intc2_data[irq_offset].clear_irq = NULL; /* Set the priority level */ /* Set the priority level */ local_irq_save(flags); local_irq_save(flags); ipr = ctrl_inl(INTC2_BASE + INTC2_INTPRI_OFFSET + ipr_offset); ipr = ctrl_inl(INTC2_BASE + INTC2_INTPRI_OFFSET + p->ipr_offset); ipr &= ~(0xf << ipr_shift); ipr &= ~(0xf << p->ipr_shift); ipr |= priority << ipr_shift; ipr |= p->priority << p->ipr_shift; ctrl_outl(ipr, INTC2_BASE + INTC2_INTPRI_OFFSET + ipr_offset); ctrl_outl(ipr, INTC2_BASE + INTC2_INTPRI_OFFSET + p->ipr_offset); local_irq_restore(flags); local_irq_restore(flags); irq_desc[irq].chip = &intc2_irq_type; set_irq_chip_and_handler(p->irq, &intc2_irq_chip, handle_level_irq); set_irq_chip_data(p->irq, p); disable_intc2_irq(irq); enable_intc2_irq(p->irq); } } static struct intc2_init { static struct intc2_data intc2_irq_table[] = { unsigned short irq; unsigned char ipr_offset, ipr_shift; unsigned char msk_offset, msk_shift; unsigned char priority; } intc2_init_data[] __initdata = { #if defined(CONFIG_CPU_SUBTYPE_ST40) #if defined(CONFIG_CPU_SUBTYPE_ST40) {64, 0, 0, 0, 0, 13}, /* PCI serr */ {64, 0, 0, 0, 0, 13}, /* PCI serr */ {65, 0, 4, 0, 1, 13}, /* PCI err */ {65, 0, 4, 0, 1, 13}, /* PCI err */ Loading Loading @@ -266,19 +189,6 @@ void __init init_IRQ_intc2(void) { { int i; int i; for (i = 0; i < ARRAY_SIZE(intc2_init_data); i++) { for (i = 0; i < ARRAY_SIZE(intc2_irq_table); i++) struct intc2_init *p = intc2_init_data + i; make_intc2_irq(intc2_irq_table + i); make_intc2_irq(p->irq, p->ipr_offset, p->ipr_shift, p-> msk_offset, p->msk_shift, p->priority); } } /* Adds a termination callback to the interrupt */ void intc2_add_clear_irq(int irq, int (*fn)(int)) { if (unlikely(irq < INTC2_FIRST_IRQ)) return; intc2_data[irq - INTC2_FIRST_IRQ].clear_irq = fn; } }
include/asm-sh/irq.h +8 −6 Original line number Original line Diff line number Diff line Loading @@ -697,13 +697,15 @@ extern int ipr_irq_demux(int irq); #define INTC2_INTPRI_OFFSET 0x00 #define INTC2_INTPRI_OFFSET 0x00 void make_intc2_irq(unsigned int irq, struct intc2_data { unsigned int ipr_offset, unsigned int ipr_shift, unsigned short irq; unsigned int msk_offset, unsigned int msk_shift, unsigned char ipr_offset, ipr_shift; unsigned int priority); unsigned char msk_offset, msk_shift; unsigned char priority; }; void make_intc2_irq(struct intc2_data *); void init_IRQ_intc2(void); void init_IRQ_intc2(void); void intc2_add_clear_irq(int irq, int (*fn)(int)); #endif #endif extern int shmse_irq_demux(int irq); extern int shmse_irq_demux(int irq); Loading