diff options
author | Magnus Damm <damm@igel.co.jp> | 2007-06-15 11:56:19 +0200 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2007-06-15 11:56:19 +0200 |
commit | 68abdbbb03476a60d932eeba0035dd5069afec38 (patch) | |
tree | de3854f76d6d9aec121c432a3cd276bb756003c9 /arch/sh | |
parent | sh: Only support PMB for SH-X cores. (diff) | |
download | linux-68abdbbb03476a60d932eeba0035dd5069afec38.tar.xz linux-68abdbbb03476a60d932eeba0035dd5069afec38.zip |
sh: rework ipr code
This patch reworks the ipr code by grouping the offset array together
with the ipr_data structure in a new data structure called ipr_desc.
This new structure also contains the name of the controller in struct
irq_chip. The idea behind putting struct irq_chip in there is that we
can use offsetof() to locate the base addresses in the irq_chip
callbacks. This strategy has much in common with the recently merged
intc2 code.
One logic change has been made - the original ipr code enabled the
interrupts by default but with this patch they are all disabled by
default.
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/boards/se/770x/irq.c | 124 | ||||
-rw-r--r-- | arch/sh/boards/se/7722/irq.c | 15 | ||||
-rw-r--r-- | arch/sh/boards/se/7751/irq.c | 59 | ||||
-rw-r--r-- | arch/sh/boards/sh03/setup.c | 28 | ||||
-rw-r--r-- | arch/sh/boards/shmin/setup.c | 30 | ||||
-rw-r--r-- | arch/sh/boards/snapgear/setup.c | 28 | ||||
-rw-r--r-- | arch/sh/boards/titan/setup.c | 22 | ||||
-rw-r--r-- | arch/sh/kernel/cpu/irq/ipr.c | 59 | ||||
-rw-r--r-- | arch/sh/kernel/cpu/sh2/setup-sh7619.c | 24 | ||||
-rw-r--r-- | arch/sh/kernel/cpu/sh2a/setup-sh7206.c | 24 | ||||
-rw-r--r-- | arch/sh/kernel/cpu/sh3/setup-sh7705.c | 40 | ||||
-rw-r--r-- | arch/sh/kernel/cpu/sh3/setup-sh7709.c | 84 | ||||
-rw-r--r-- | arch/sh/kernel/cpu/sh3/setup-sh7710.c | 42 | ||||
-rw-r--r-- | arch/sh/kernel/cpu/sh4/setup-sh7750.c | 58 | ||||
-rw-r--r-- | arch/sh/kernel/cpu/sh4/setup-sh7760.c | 32 | ||||
-rw-r--r-- | arch/sh/kernel/cpu/sh4a/setup-sh7722.c | 21 |
16 files changed, 404 insertions, 286 deletions
diff --git a/arch/sh/boards/se/770x/irq.c b/arch/sh/boards/se/770x/irq.c index c8eccff77a04..cdb0807928a5 100644 --- a/arch/sh/boards/se/770x/irq.c +++ b/arch/sh/boards/se/770x/irq.c @@ -15,46 +15,7 @@ #include <asm/io.h> #include <asm/se.h> -/* - * If the problem of make_ipr_irq is solved, - * this code will become unnecessary. :-) - */ -static void se770x_disable_ipr_irq(unsigned int irq) -{ - struct ipr_data *p = get_irq_chip_data(irq); - - ctrl_outw(ctrl_inw(p->addr) & (0xffff ^ (0xf << p->shift)), p->addr); -} - -static void se770x_enable_ipr_irq(unsigned int irq) -{ - struct ipr_data *p = get_irq_chip_data(irq); - - ctrl_outw(ctrl_inw(p->addr) | (p->priority << p->shift), p->addr); -} - -static struct irq_chip se770x_irq_chip = { - .name = "MS770xSE-FPGA", - .mask = se770x_disable_ipr_irq, - .unmask = se770x_enable_ipr_irq, - .mask_ack = se770x_disable_ipr_irq, -}; - -void make_se770x_irq(struct ipr_data *table, unsigned int nr_irqs) -{ - int i; - - for (i = 0; i < nr_irqs; i++) { - unsigned int irq = table[i].irq; - disable_irq_nosync(irq); - set_irq_chip_and_handler_name(irq, &se770x_irq_chip, - handle_level_irq, "level"); - set_irq_chip_data(irq, &table[i]); - se770x_enable_ipr_irq(irq); - } -} - -static struct ipr_data se770x_ipr_map[] = { +static struct ipr_data ipr_irq_table[] = { /* * Super I/O (Just mimic PC): * 1: keyboard @@ -68,46 +29,67 @@ static struct ipr_data se770x_ipr_map[] = { */ #if defined(CONFIG_CPU_SUBTYPE_SH7705) /* This is default value */ - { 13, 0, 8, 0x0f-13 ,BCR_ILCRA}, - { 5 , 0, 4, 0x0f- 5 ,BCR_ILCRA}, - { 10, 0, 0, 0x0f-10, BCR_ILCRB}, - { 7 , 0, 4, 0x0f- 7, BCR_ILCRC}, - { 3 , 0, 0, 0x0f- 3, BCR_ILCRC}, - { 1 , 0, 12, 0x0f- 1, BCR_ILCRD}, - { 12, 0, 4, 0x0f-12, BCR_ILCRD}, /* LAN */ - { 2 , 0, 8, 0x0f- 2, BCR_ILCRE}, /* PCIRQ2 */ - { 6 , 0, 4, 0x0f- 6, BCR_ILCRE}, /* PCIRQ1 */ - { 14, 0, 0, 0x0f-14, BCR_ILCRE}, /* PCIRQ0 */ - { 0 , 0, 12, 0x0f , BCR_ILCRF}, - { 4 , 0, 4, 0x0f- 4, BCR_ILCRF}, - { 8 , 0, 12, 0x0f- 8, BCR_ILCRG}, - { 9 , 0, 8, 0x0f- 9, BCR_ILCRG}, - { 11, 0, 4, 0x0f-11, BCR_ILCRG}, + { 13, 0, 8, 0x0f-13, }, + { 5 , 0, 4, 0x0f- 5, }, + { 10, 1, 0, 0x0f-10, }, + { 7 , 2, 4, 0x0f- 7, }, + { 3 , 2, 0, 0x0f- 3, }, + { 1 , 3, 12, 0x0f- 1, }, + { 12, 3, 4, 0x0f-12, }, /* LAN */ + { 2 , 4, 8, 0x0f- 2, }, /* PCIRQ2 */ + { 6 , 4, 4, 0x0f- 6, }, /* PCIRQ1 */ + { 14, 4, 0, 0x0f-14, }, /* PCIRQ0 */ + { 0 , 5, 12, 0x0f , }, + { 4 , 5, 4, 0x0f- 4, }, + { 8 , 6, 12, 0x0f- 8, }, + { 9 , 6, 8, 0x0f- 9, }, + { 11, 6, 4, 0x0f-11, }, #else - { 14, 0, 8, 0x0f-14 ,BCR_ILCRA}, - { 12, 0, 4, 0x0f-12 ,BCR_ILCRA}, - { 8, 0, 4, 0x0f- 8 ,BCR_ILCRB}, - { 6, 0, 12, 0x0f- 6 ,BCR_ILCRC}, - { 5, 0, 8, 0x0f- 5 ,BCR_ILCRC}, - { 4, 0, 4, 0x0f- 4 ,BCR_ILCRC}, - { 3, 0, 0, 0x0f- 3 ,BCR_ILCRC}, - { 1, 0, 12, 0x0f- 1 ,BCR_ILCRD}, + { 14, 0, 8, 0x0f-14, }, + { 12, 0, 4, 0x0f-12, }, + { 8, 1, 4, 0x0f- 8, }, + { 6, 2, 12, 0x0f- 6, }, + { 5, 2, 8, 0x0f- 5, }, + { 4, 2, 4, 0x0f- 4, }, + { 3, 2, 0, 0x0f- 3, }, + { 1, 3, 12, 0x0f- 1, }, #if defined(CONFIG_STNIC) /* ST NIC */ - { 10, 0, 4, 0x0f-10 ,BCR_ILCRD}, /* LAN */ + { 10, 3, 4, 0x0f-10, }, /* LAN */ #endif /* MRSHPC IRQs setting */ - { 0, 0, 12, 0x0f- 0 ,BCR_ILCRE}, /* PCIRQ3 */ - { 11, 0, 8, 0x0f-11 ,BCR_ILCRE}, /* PCIRQ2 */ - { 9, 0, 4, 0x0f- 9 ,BCR_ILCRE}, /* PCIRQ1 */ - { 7, 0, 0, 0x0f- 7 ,BCR_ILCRE}, /* PCIRQ0 */ + { 0, 4, 12, 0x0f- 0, }, /* PCIRQ3 */ + { 11, 4, 8, 0x0f-11, }, /* PCIRQ2 */ + { 9, 4, 4, 0x0f- 9, }, /* PCIRQ1 */ + { 7, 4, 0, 0x0f- 7, }, /* PCIRQ0 */ /* #2, #13 are allocated for SLOT IRQ #1 and #2 (for now) */ /* NOTE: #2 and #13 are not used on PC */ - { 13, 0, 4, 0x0f-13 ,BCR_ILCRG}, /* SLOTIRQ2 */ - { 2, 0, 0, 0x0f- 2 ,BCR_ILCRG}, /* SLOTIRQ1 */ + { 13, 6, 4, 0x0f-13, }, /* SLOTIRQ2 */ + { 2, 6, 0, 0x0f- 2, }, /* SLOTIRQ1 */ #endif }; +static unsigned long ipr_offsets[] = { + BCR_ILCRA, + BCR_ILCRB, + BCR_ILCRC, + BCR_ILCRD, + BCR_ILCRE, + BCR_ILCRF, + BCR_ILCRG, +}; + +static struct ipr_desc ipr_irq_desc = { + .ipr_offsets = ipr_offsets, + .nr_offsets = ARRAY_SIZE(ipr_offsets), + + .ipr_data = ipr_irq_table, + .nr_irqs = ARRAY_SIZE(ipr_irq_table), + .chip = { + .name = "IPR-se770x", + }, +}; + /* * Initialize IRQ setting */ @@ -122,5 +104,5 @@ void __init init_se_IRQ(void) ctrl_outw(0, BCR_ILCRF); ctrl_outw(0, BCR_ILCRG); - make_se770x_irq(se770x_ipr_map, ARRAY_SIZE(se770x_ipr_map)); + register_ipr_controller(&ipr_irq_desc); } diff --git a/arch/sh/boards/se/7722/irq.c b/arch/sh/boards/se/7722/irq.c index 099e5deb77f8..26cff0efda40 100644 --- a/arch/sh/boards/se/7722/irq.c +++ b/arch/sh/boards/se/7722/irq.c @@ -19,15 +19,24 @@ #define INTC_INTMSK0 0xFFD00044 #define INTC_INTMSKCLR0 0xFFD00064 +struct se7722_data { + unsigned char irq; + unsigned char ipr_idx; + unsigned char shift; + unsigned short priority; + unsigned long addr; +}; + + static void disable_se7722_irq(unsigned int irq) { - struct ipr_data *p = get_irq_chip_data(irq); + struct se7722_data *p = get_irq_chip_data(irq); ctrl_outw( ctrl_inw( p->addr ) | p->priority , p->addr ); } static void enable_se7722_irq(unsigned int irq) { - struct ipr_data *p = get_irq_chip_data(irq); + struct se7722_data *p = get_irq_chip_data(irq); ctrl_outw( ctrl_inw( p->addr ) & ~p->priority , p->addr ); } @@ -38,7 +47,7 @@ static struct irq_chip se7722_irq_chip __read_mostly = { .mask_ack = disable_se7722_irq, }; -static struct ipr_data ipr_irq_table[] = { +static struct se7722_data ipr_irq_table[] = { /* irq ,idx,sft, priority , addr */ { MRSHPC_IRQ0 , 0 , 0 , MRSHPC_BIT0 , IRQ01_MASK } , { MRSHPC_IRQ1 , 0 , 0 , MRSHPC_BIT1 , IRQ01_MASK } , diff --git a/arch/sh/boards/se/7751/irq.c b/arch/sh/boards/se/7751/irq.c index e4c63a48296c..c3d12590e5db 100644 --- a/arch/sh/boards/se/7751/irq.c +++ b/arch/sh/boards/se/7751/irq.c @@ -14,44 +14,31 @@ #include <asm/irq.h> #include <asm/se7751.h> -static struct ipr_data se7751_ipr_map[] = { - /* Leave old Solution Engine code in for reference. */ -#if defined(CONFIG_SH_SOLUTION_ENGINE) - /* - * Super I/O (Just mimic PC): - * 1: keyboard - * 3: serial 0 - * 4: serial 1 - * 5: printer - * 6: floppy - * 8: rtc - * 12: mouse - * 14: ide0 - */ - { 14, BCR_ILCRA, 2, 0x0f-14 }, - { 12, BCR_ILCRA, 1, 0x0f-12 }, - { 8, BCR_ILCRB, 1, 0x0f- 8 }, - { 6, BCR_ILCRC, 3, 0x0f- 6 }, - { 5, BCR_ILCRC, 2, 0x0f- 5 }, - { 4, BCR_ILCRC, 1, 0x0f- 4 }, - { 3, BCR_ILCRC, 0, 0x0f- 3 }, - { 1, BCR_ILCRD, 3, 0x0f- 1 }, +static struct ipr_data ipr_irq_table[] = { + { 13, 3, 3, 2 }, + /* Add additional entries here as drivers are added and tested. */ +}; - { 10, BCR_ILCRD, 1, 0x0f-10 }, /* LAN */ +static unsigned long ipr_offsets[] = { + BCR_ILCRA, + BCR_ILCRB, + BCR_ILCRC, + BCR_ILCRD, + BCR_ILCRE, + BCR_ILCRF, + BCR_ILCRG, +}; - { 0, BCR_ILCRE, 3, 0x0f- 0 }, /* PCIRQ3 */ - { 11, BCR_ILCRE, 2, 0x0f-11 }, /* PCIRQ2 */ - { 9, BCR_ILCRE, 1, 0x0f- 9 }, /* PCIRQ1 */ - { 7, BCR_ILCRE, 0, 0x0f- 7 }, /* PCIRQ0 */ +static struct ipr_desc ipr_irq_desc = { + .ipr_offsets = ipr_offsets, + .nr_offsets = ARRAY_SIZE(ipr_offsets), - /* #2, #13 are allocated for SLOT IRQ #1 and #2 (for now) */ - /* NOTE: #2 and #13 are not used on PC */ - { 13, BCR_ILCRG, 1, 0x0f-13 }, /* SLOTIRQ2 */ - { 2, BCR_ILCRG, 0, 0x0f- 2 }, /* SLOTIRQ1 */ -#elif defined(CONFIG_SH_7751_SOLUTION_ENGINE) - { 13, BCR_ILCRD, 3, 2 }, - /* Add additional entries here as drivers are added and tested. */ -#endif + .ipr_data = ipr_irq_table, + .nr_irqs = ARRAY_SIZE(ipr_irq_table), + + .chip = { + .name = "IPR-se7751", + }, }; /* @@ -59,5 +46,5 @@ static struct ipr_data se7751_ipr_map[] = { */ void __init init_7751se_IRQ(void) { - make_ipr_irq(se7751_ipr_map, ARRAY_SIZE(se7751_ipr_map)); + register_ipr_controller(&ipr_irq_desc); } diff --git a/arch/sh/boards/sh03/setup.c b/arch/sh/boards/sh03/setup.c index d7867c190a96..9c031a8c0a1c 100644 --- a/arch/sh/boards/sh03/setup.c +++ b/arch/sh/boards/sh03/setup.c @@ -15,17 +15,33 @@ #include <asm/sh03/sh03.h> #include <asm/addrspace.h> -static struct ipr_data sh03_ipr_map[] = { - { IRL0_IRQ, IRL0_IPR_ADDR, IRL0_IPR_POS, IRL0_PRIORITY }, - { IRL1_IRQ, IRL1_IPR_ADDR, IRL1_IPR_POS, IRL1_PRIORITY }, - { IRL2_IRQ, IRL2_IPR_ADDR, IRL2_IPR_POS, IRL2_PRIORITY }, - { IRL3_IRQ, IRL3_IPR_ADDR, IRL3_IPR_POS, IRL3_PRIORITY }, +static struct ipr_data ipr_irq_table[] = { + { IRL0_IRQ, 0, IRL0_IPR_POS, IRL0_PRIORITY }, + { IRL1_IRQ, 0, IRL1_IPR_POS, IRL1_PRIORITY }, + { IRL2_IRQ, 0, IRL2_IPR_POS, IRL2_PRIORITY }, + { IRL3_IRQ, 0, IRL3_IPR_POS, IRL3_PRIORITY }, +}; + +static unsigned long ipr_offsets[] = { + INTC_IPRD, +}; + +static struct ipr_desc ipr_irq_desc = { + .ipr_offsets = ipr_offsets, + .nr_offsets = ARRAY_SIZE(ipr_offsets), + + .ipr_data = ipr_irq_table, + .nr_irqs = ARRAY_SIZE(ipr_irq_table), + + .chip = { + .name = "IPR-sh03", + }, }; static void __init init_sh03_IRQ(void) { ctrl_outw(ctrl_inw(INTC_ICR) | INTC_ICR_IRLM, INTC_ICR); - make_ipr_irq(sh03_ipr_map, ARRAY_SIZE(sh03_ipr_map)); + register_ipr_controller(&ipr_irq_desc); } extern void *cf_io_base; diff --git a/arch/sh/boards/shmin/setup.c b/arch/sh/boards/shmin/setup.c index 9c8bb51eb4bb..dfd124509f42 100644 --- a/arch/sh/boards/shmin/setup.c +++ b/arch/sh/boards/shmin/setup.c @@ -6,28 +6,44 @@ * SHMIN Support. */ #include <linux/init.h> +#include <linux/irq.h> #include <asm/machvec.h> #include <asm/shmin.h> #include <asm/clock.h> -#include <asm/irq.h> #include <asm/io.h> #define PFC_PHCR 0xa400010eUL #define INTC_ICR1 0xa4000010UL #define INTC_IPRC 0xa4000016UL -static struct ipr_data shmin_ipr_map[] = { - { .irq=32, .addr=INTC_IPRC, .shift= 0, .priority=0 }, - { .irq=33, .addr=INTC_IPRC, .shift= 4, .priority=0 }, - { .irq=34, .addr=INTC_IPRC, .shift= 8, .priority=8 }, - { .irq=35, .addr=INTC_IPRC, .shift=12, .priority=0 }, +static struct ipr_data ipr_irq_table[] = { + { 32, 0, 0, 0 }, + { 33, 0, 4, 0 }, + { 34, 0, 8, 8 }, + { 35, 0, 12, 0 }, +}; + +static unsigned long ipr_offsets[] = { + INTC_IPRC, +}; + +static struct ipr_desc ipr_irq_desc = { + .ipr_offsets = ipr_offsets, + .nr_offsets = ARRAY_SIZE(ipr_offsets), + + .ipr_data = ipr_irq_table, + .nr_irqs = ARRAY_SIZE(ipr_irq_table), + + .chip = { + .name = "IPR-shmin", + }, }; static void __init init_shmin_irq(void) { ctrl_outw(0x2a00, PFC_PHCR); // IRQ0-3=IRQ ctrl_outw(0x0aaa, INTC_ICR1); // IRQ0-3=IRQ-mode,Low-active. - make_ipr_irq(shmin_ipr_map, ARRAY_SIZE(shmin_ipr_map)); + register_ipr_controller(&ipr_irq_desc); } static void __iomem *shmin_ioport_map(unsigned long port, unsigned int size) diff --git a/arch/sh/boards/snapgear/setup.c b/arch/sh/boards/snapgear/setup.c index b40124c092f5..84271d85a8dd 100644 --- a/arch/sh/boards/snapgear/setup.c +++ b/arch/sh/boards/snapgear/setup.c @@ -68,11 +68,27 @@ module_init(eraseconfig_init); * IRL3 = crypto */ -static struct ipr_data snapgear_ipr_map[] = { - make_ipr_irq(IRL0_IRQ, IRL0_IPR_ADDR, IRL0_IPR_POS, IRL0_PRIORITY); - make_ipr_irq(IRL1_IRQ, IRL1_IPR_ADDR, IRL1_IPR_POS, IRL1_PRIORITY); - make_ipr_irq(IRL2_IRQ, IRL2_IPR_ADDR, IRL2_IPR_POS, IRL2_PRIORITY); - make_ipr_irq(IRL3_IRQ, IRL3_IPR_ADDR, IRL3_IPR_POS, IRL3_PRIORITY); +static struct ipr_data ipr_irq_table[] = { + { IRL0_IRQ, 0, IRL0_IPR_POS, IRL0_PRIORITY }, + { IRL1_IRQ, 0, IRL1_IPR_POS, IRL1_PRIORITY }, + { IRL2_IRQ, 0, IRL2_IPR_POS, IRL2_PRIORITY }, + { IRL3_IRQ, 0, IRL3_IPR_POS, IRL3_PRIORITY }, +}; + +static unsigned long ipr_offsets[] = { + INTC_IPRD, +}; + +static struct ipr_desc ipr_irq_desc = { + .ipr_offsets = ipr_offsets, + .nr_offsets = ARRAY_SIZE(ipr_offsets), + + .ipr_data = ipr_irq_table, + .nr_irqs = ARRAY_SIZE(ipr_irq_table), + + .chip = { + .name = "IPR-snapgear", + }, }; static void __init init_snapgear_IRQ(void) @@ -82,7 +98,7 @@ static void __init init_snapgear_IRQ(void) printk("Setup SnapGear IRQ/IPR ...\n"); - make_ipr_irq(snapgear_ipr_map, ARRAY_SIZE(snapgear_ipr_map)); + register_ipr_controller(&ipr_irq_desc); } /* diff --git a/arch/sh/boards/titan/setup.c b/arch/sh/boards/titan/setup.c index 630f62f69a36..606d25a4b870 100644 --- a/arch/sh/boards/titan/setup.c +++ b/arch/sh/boards/titan/setup.c @@ -12,7 +12,7 @@ #include <asm/titan.h> #include <asm/io.h> -static struct ipr_data titan_ipr_map[] = { +static struct ipr_data ipr_irq_table[] = { /* IRQ, IPR idx, shift, prio */ { TITAN_IRQ_WAN, 3, 12, 8 }, /* eth0 (WAN) */ { TITAN_IRQ_LAN, 3, 8, 8 }, /* eth1 (LAN) */ @@ -20,12 +20,30 @@ static struct ipr_data titan_ipr_map[] = { { TITAN_IRQ_USB, 3, 0, 8 }, /* mPCI B (bottom), USB */ }; +static unsigned long ipr_offsets[] = { /* stolen from setup-sh7750.c */ + 0xffd00004UL, /* 0: IPRA */ + 0xffd00008UL, /* 1: IPRB */ + 0xffd0000cUL, /* 2: IPRC */ + 0xffd00010UL, /* 3: IPRD */ +}; + +static struct ipr_desc ipr_irq_desc = { + .ipr_offsets = ipr_offsets, + .nr_offsets = ARRAY_SIZE(ipr_offsets), + + .ipr_data = ipr_irq_table, + .nr_irqs = ARRAY_SIZE(ipr_irq_table), + + .chip = { + .name = "IPR-titan", + }, +}; static void __init init_titan_irq(void) { /* enable individual interrupt mode for externals */ ipr_irq_enable_irlm(); /* register ipr irqs */ - make_ipr_irq(titan_ipr_map, ARRAY_SIZE(titan_ipr_map)); + register_ipr_controller(&ipr_irq_desc); } static struct sh_machine_vector mv_titan __initmv = { diff --git a/arch/sh/kernel/cpu/irq/ipr.c b/arch/sh/kernel/cpu/irq/ipr.c index 210280b6fddf..98e84f40c713 100644 --- a/arch/sh/kernel/cpu/irq/ipr.c +++ b/arch/sh/kernel/cpu/irq/ipr.c @@ -22,58 +22,57 @@ #include <linux/io.h> #include <linux/interrupt.h> +static inline struct ipr_desc *get_ipr_desc(unsigned int irq) +{ + struct irq_chip *chip = get_irq_chip(irq); + return (void *)((char *)chip - offsetof(struct ipr_desc, chip)); +} + static void disable_ipr_irq(unsigned int irq) { struct ipr_data *p = get_irq_chip_data(irq); + unsigned long addr = get_ipr_desc(irq)->ipr_offsets[p->ipr_idx]; /* Set the priority in IPR to 0 */ - ctrl_outw(ctrl_inw(p->addr) & (0xffff ^ (0xf << p->shift)), p->addr); + ctrl_outw(ctrl_inw(addr) & (0xffff ^ (0xf << p->shift)), addr); } static void enable_ipr_irq(unsigned int irq) { struct ipr_data *p = get_irq_chip_data(irq); + unsigned long addr = get_ipr_desc(irq)->ipr_offsets[p->ipr_idx]; /* Set priority in IPR back to original value */ - ctrl_outw(ctrl_inw(p->addr) | (p->priority << p->shift), p->addr); + ctrl_outw(ctrl_inw(addr) | (p->priority << p->shift), addr); } -static struct irq_chip ipr_irq_chip = { - .name = "IPR", - .mask = disable_ipr_irq, - .unmask = enable_ipr_irq, - .mask_ack = disable_ipr_irq, -}; - -unsigned int map_ipridx_to_addr(int idx) __attribute__ ((weak)); -unsigned int map_ipridx_to_addr(int idx) -{ - return 0; -} +/* + * The shift value is now the number of bits to shift, not the number of + * bits/4. This is to make it easier to read the value directly from the + * datasheets. The IPR address is calculated using the ipr_offset table. + */ -void make_ipr_irq(struct ipr_data *table, unsigned int nr_irqs) +void register_ipr_controller(struct ipr_desc *desc) { int i; - for (i = 0; i < nr_irqs; i++) { - unsigned int irq = table[i].irq; + desc->chip.mask = disable_ipr_irq; + desc->chip.unmask = enable_ipr_irq; + desc->chip.mask_ack = disable_ipr_irq; - if (!irq) - irq = table[i].irq = i; + for (i = 0; i < desc->nr_irqs; i++) { + struct ipr_data *p = desc->ipr_data + i; - /* could the IPR index be mapped, if not we ignore this */ - if (!table[i].addr) { - table[i].addr = map_ipridx_to_addr(table[i].ipr_idx); - if (!table[i].addr) - continue; - } + BUG_ON(p->ipr_idx >= desc->nr_offsets); + BUG_ON(!desc->ipr_offsets[p->ipr_idx]); - disable_irq_nosync(irq); - set_irq_chip_and_handler_name(irq, &ipr_irq_chip, + disable_irq_nosync(p->irq); + set_irq_chip_and_handler_name(p->irq, &desc->chip, handle_level_irq, "level"); - set_irq_chip_data(irq, &table[i]); - enable_ipr_irq(irq); + set_irq_chip_data(p->irq, p); + disable_ipr_irq(p->irq); } } -EXPORT_SYMBOL(make_ipr_irq); + +EXPORT_SYMBOL(register_ipr_controller); #if !defined(CONFIG_CPU_HAS_PINT_IRQ) int ipr_irq_demux(int irq) diff --git a/arch/sh/kernel/cpu/sh2/setup-sh7619.c b/arch/sh/kernel/cpu/sh2/setup-sh7619.c index f83ff8a68f35..1a107fe22dde 100644 --- a/arch/sh/kernel/cpu/sh2/setup-sh7619.c +++ b/arch/sh/kernel/cpu/sh2/setup-sh7619.c @@ -52,7 +52,7 @@ static int __init sh7619_devices_setup(void) } __initcall(sh7619_devices_setup); -static struct ipr_data sh7619_ipr_map[] = { +static struct ipr_data ipr_irq_table[] = { { 86, 0, 4, 2 }, /* CMI0 */ { 88, 1, 12, 3 }, /* SCIF0_ERI */ { 89, 1, 12, 3 }, /* SCIF0_RXI */ @@ -68,7 +68,7 @@ static struct ipr_data sh7619_ipr_map[] = { { 99, 1, 4, 3 }, /* SCIF2_TXI */ }; -static unsigned int ipr_offsets[] = { +static unsigned long ipr_offsets[] = { 0xf8080000, /* IPRC */ 0xf8080002, /* IPRD */ 0xf8080004, /* IPRE */ @@ -76,15 +76,19 @@ static unsigned int ipr_offsets[] = { 0xf8080008, /* IPRG */ }; -/* given the IPR index return the address of the IPR register */ -unsigned int map_ipridx_to_addr(int idx) -{ - if (unlikely(idx >= ARRAY_SIZE(ipr_offsets))) - return 0; - return ipr_offsets[idx]; -} +static struct ipr_desc ipr_irq_desc = { + .ipr_offsets = ipr_offsets, + .nr_offsets = ARRAY_SIZE(ipr_offsets), + + .ipr_data = ipr_irq_table, + .nr_irqs = ARRAY_SIZE(ipr_irq_table), + + .chip = { + .name = "IPR-sh7619", + }, +}; void __init init_IRQ_ipr(void) { - make_ipr_irq(sh7619_ipr_map, ARRAY_SIZE(sh7619_ipr_map)); + register_ipr_controller(&ipr_irq_desc); } diff --git a/arch/sh/kernel/cpu/sh2a/setup-sh7206.c b/arch/sh/kernel/cpu/sh2a/setup-sh7206.c index 4ed9110632bc..b6e3a6351fa6 100644 --- a/arch/sh/kernel/cpu/sh2a/setup-sh7206.c +++ b/arch/sh/kernel/cpu/sh2a/setup-sh7206.c @@ -57,7 +57,7 @@ static int __init sh7206_devices_setup(void) } __initcall(sh7206_devices_setup); -static struct ipr_data sh7206_ipr_map[] = { +static struct ipr_data ipr_irq_table[] = { { 140, 7, 12, 2 }, /* CMI0 */ { 164, 8, 4, 2 }, /* MTU2_TGI1A */ { 240, 13, 12, 3 }, /* SCIF0_BRI */ @@ -78,7 +78,7 @@ static struct ipr_data sh7206_ipr_map[] = { { 255, 13, 0, 3 }, /* SCIF3_TXI */ }; -static unsigned int ipr_offsets[] = { +static unsigned long ipr_offsets[] = { 0xfffe0818, /* IPR01 */ 0xfffe081a, /* IPR02 */ 0, /* unused */ @@ -95,15 +95,19 @@ static unsigned int ipr_offsets[] = { 0xfffe0c10, /* IPR14 */ }; -/* given the IPR index return the address of the IPR register */ -unsigned int map_ipridx_to_addr(int idx) -{ - if (unlikely(idx >= ARRAY_SIZE(ipr_offsets))) - return 0; - return ipr_offsets[idx]; -} +static struct ipr_desc ipr_irq_desc = { + .ipr_offsets = ipr_offsets, + .nr_offsets = ARRAY_SIZE(ipr_offsets), + + .ipr_data = ipr_irq_table, + .nr_irqs = ARRAY_SIZE(ipr_irq_table), + + .chip = { + .name = "IPR-sh7206", + }, +}; void __init init_IRQ_ipr(void) { - make_ipr_irq(sh7206_ipr_map, ARRAY_SIZE(sh7206_ipr_map)); + register_ipr_controller(&ipr_irq_desc); } diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7705.c b/arch/sh/kernel/cpu/sh3/setup-sh7705.c index 1983fb7ad6ea..a55b8ce2c54c 100644 --- a/arch/sh/kernel/cpu/sh3/setup-sh7705.c +++ b/arch/sh/kernel/cpu/sh3/setup-sh7705.c @@ -48,7 +48,7 @@ static int __init sh7705_devices_setup(void) } __initcall(sh7705_devices_setup); -static struct ipr_data sh7705_ipr_map[] = { +static struct ipr_data ipr_irq_table[] = { /* IRQ, IPR-idx, shift, priority */ { 16, 0, 12, 2 }, /* TMU0 TUNI*/ { 17, 0, 8, 2 }, /* TMU1 TUNI */ @@ -70,25 +70,29 @@ static struct ipr_data sh7705_ipr_map[] = { }; static unsigned long ipr_offsets[] = { - 0xFFFFFEE2 /* 0: IPRA */ -, 0xFFFFFEE4 /* 1: IPRB */ -, 0xA4000016 /* 2: IPRC */ -, 0xA4000018 /* 3: IPRD */ -, 0xA400001A /* 4: IPRE */ -, 0xA4080000 /* 5: IPRF */ -, 0xA4080002 /* 6: IPRG */ -, 0xA4080004 /* 7: IPRH */ + 0xFFFFFEE2, /* 0: IPRA */ + 0xFFFFFEE4, /* 1: IPRB */ + 0xA4000016, /* 2: IPRC */ + 0xA4000018, /* 3: IPRD */ + 0xA400001A, /* 4: IPRE */ + 0xA4080000, /* 5: IPRF */ + 0xA4080002, /* 6: IPRG */ + 0xA4080004, /* 7: IPRH */ }; -/* given the IPR index return the address of the IPR register */ -unsigned int map_ipridx_to_addr(int idx) -{ - if (idx >= ARRAY_SIZE(ipr_offsets)) - return 0; - return ipr_offsets[idx]; -} +static struct ipr_desc ipr_irq_desc = { + .ipr_offsets = ipr_offsets, + .nr_offsets = ARRAY_SIZE(ipr_offsets), + + .ipr_data = ipr_irq_table, + .nr_irqs = ARRAY_SIZE(ipr_irq_table), + + .chip = { + .name = "IPR-sh7705", + }, +}; -void __init init_IRQ_ipr() +void __init init_IRQ_ipr(void) { - make_ipr_irq(sh7705_ipr_map, ARRAY_SIZE(sh7705_ipr_map)); + register_ipr_controller(&ipr_irq_desc); } diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7709.c b/arch/sh/kernel/cpu/sh3/setup-sh7709.c index c7d7c35fc834..c0265a96e7d3 100644 --- a/arch/sh/kernel/cpu/sh3/setup-sh7709.c +++ b/arch/sh/kernel/cpu/sh3/setup-sh7709.c @@ -52,32 +52,66 @@ static int __init sh7709_devices_setup(void) } __initcall(sh7709_devices_setup); -#define IPRx(A,N) .addr=A, .shift=N -#define IPRA(N) IPRx(0xfffffee2UL,N) -#define IPRB(N) IPRx(0xfffffee4UL,N) -#define IPRC(N) IPRx(0xa4000016UL,N) -#define IPRD(N) IPRx(0xa4000018UL,N) -#define IPRE(N) IPRx(0xa400001aUL,N) - -static struct ipr_data sh7709_ipr_map[] = { - [16] = { IPRA(12), 2 }, /* TMU TUNI0 */ - [17] = { IPRA(8), 4 }, /* TMU TUNI1 */ - [18 ... 19] = { IPRA(4), 1 }, /* TMU TUNI1 */ - [20 ... 22] = { IPRA(0), 2 }, /* RTC CUI */ - [23 ... 26] = { IPRB(4), 3 }, /* SCI */ - [27] = { IPRB(12), 2 }, /* WDT ITI */ - [32] = { IPRC(0), 1 }, /* IRQ 0 */ - [33] = { IPRC(4), 1 }, /* IRQ 1 */ - [34] = { IPRC(8), 1 }, /* IRQ 2 APM */ - [35] = { IPRC(12), 1 }, /* IRQ 3 TOUCHSCREEN */ - [36] = { IPRD(0), 1 }, /* IRQ 4 */ - [37] = { IPRD(4), 1 }, /* IRQ 5 */ - [48 ... 51] = { IPRE(12), 7 }, /* DMA */ - [52 ... 55] = { IPRE(8), 3 }, /* IRDA */ - [56 ... 59] = { IPRE(4), 3 }, /* SCIF */ +static struct ipr_data ipr_irq_table[] = { + { 16, 0, 12, 2 }, /* TMU TUNI0 */ + { 17, 0, 8, 4 }, /* TMU TUNI1 */ + { 18, 0, 4, 1 }, /* TMU TUNI1 */ + { 19, 0, 4, 1 }, /* TMU TUNI1 */ + { 20, 0, 0, 2 }, /* RTC CUI */ + { 21, 0, 0, 2 }, /* RTC CUI */ + { 22, 0, 0, 2 }, /* RTC CUI */ + + { 23, 1, 4, 3 }, /* SCI */ + { 24, 1, 4, 3 }, /* SCI */ + { 25, 1, 4, 3 }, /* SCI */ + { 26, 1, 4, 3 }, /* SCI */ + { 27, 1, 12, 3 }, /* WDT ITI */ + + { 32, 2, 0, 1 }, /* IRQ 0 */ + { 33, 2, 4, 1 }, /* IRQ 1 */ + { 34, 2, 8, 1 }, /* IRQ 2 APM */ + { 35, 2, 12, 1 }, /* IRQ 3 TOUCHSCREEN */ + + { 36, 3, 0, 1 }, /* IRQ 4 */ + { 37, 3, 4, 1 }, /* IRQ 5 */ + + { 48, 4, 12, 7 }, /* DMA */ + { 49, 4, 12, 7 }, /* DMA */ + { 50, 4, 12, 7 }, /* DMA */ + { 51, 4, 12, 7 }, /* DMA */ + + { 52, 4, 8, 3 }, /* IRDA */ + { 53, 4, 8, 3 }, /* IRDA */ + { 54, 4, 8, 3 }, /* IRDA */ + { 55, 4, 8, 3 }, /* IRDA */ + + { 56, 4, 4, 3 }, /* SCIF */ + { 57, 4, 4, 3 }, /* SCIF */ + { 58, 4, 4, 3 }, /* SCIF */ + { 59, 4, 4, 3 }, /* SCIF */ +}; + +static unsigned long ipr_offsets[] = { + 0xfffffee2, /* 0: IPRA */ + 0xfffffee4, /* 1: IPRB */ + 0xa4000016, /* 2: IPRC */ + 0xa4000018, /* 3: IPRD */ + 0xa400001a, /* 4: IPRE */ +}; + +static struct ipr_desc ipr_irq_desc = { + .ipr_offsets = ipr_offsets, + .nr_offsets = ARRAY_SIZE(ipr_offsets), + + .ipr_data = ipr_irq_table, + .nr_irqs = ARRAY_SIZE(ipr_irq_table), + + .chip = { + .name = "IPR-sh7709", + }, }; -void __init init_IRQ_ipr() +void __init init_IRQ_ipr(void) { - make_ipr_irq(sh7709_ipr_map, ARRAY_SIZE(sh7709_ipr_map)); + register_ipr_controller(&ipr_irq_desc); } diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7710.c b/arch/sh/kernel/cpu/sh3/setup-sh7710.c index 51760a7e7f1c..f40e6dac337d 100644 --- a/arch/sh/kernel/cpu/sh3/setup-sh7710.c +++ b/arch/sh/kernel/cpu/sh3/setup-sh7710.c @@ -49,7 +49,7 @@ static int __init sh7710_devices_setup(void) } __initcall(sh7710_devices_setup); -static struct ipr_data sh7710_ipr_map[] = { +static struct ipr_data ipr_irq_table[] = { /* IRQ, IPR-idx, shift, priority */ { 16, 0, 12, 2 }, /* TMU0 TUNI*/ { 17, 0, 8, 2 }, /* TMU1 TUNI */ @@ -78,26 +78,30 @@ static struct ipr_data sh7710_ipr_map[] = { }; static unsigned long ipr_offsets[] = { - 0xA414FEE2 /* 0: IPRA */ -, 0xA414FEE4 /* 1: IPRB */ -, 0xA4140016 /* 2: IPRC */ -, 0xA4140018 /* 3: IPRD */ -, 0xA414001A /* 4: IPRE */ -, 0xA4080000 /* 5: IPRF */ -, 0xA4080002 /* 6: IPRG */ -, 0xA4080004 /* 7: IPRH */ -, 0xA4080006 /* 8: IPRI */ + 0xA414FEE2, /* 0: IPRA */ + 0xA414FEE4, /* 1: IPRB */ + 0xA4140016, /* 2: IPRC */ + 0xA4140018, /* 3: IPRD */ + 0xA414001A, /* 4: IPRE */ + 0xA4080000, /* 5: IPRF */ + 0xA4080002, /* 6: IPRG */ + 0xA4080004, /* 7: IPRH */ + 0xA4080006, /* 8: IPRI */ }; -/* given the IPR index return the address of the IPR register */ -unsigned int map_ipridx_to_addr(int idx) -{ - if (idx >= ARRAY_SIZE(ipr_offsets)) - return 0; - return ipr_offsets[idx]; -} +static struct ipr_desc ipr_irq_desc = { + .ipr_offsets = ipr_offsets, + .nr_offsets = ARRAY_SIZE(ipr_offsets), + + .ipr_data = ipr_irq_table, + .nr_irqs = ARRAY_SIZE(ipr_irq_table), + + .chip = { + .name = "IPR-sh7710", + }, +}; -void __init init_IRQ_ipr() +void __init init_IRQ_ipr(void) { - make_ipr_irq(sh7710_ipr_map, ARRAY_SIZE(sh7710_ipr_map)); + register_ipr_controller(&ipr_irq_desc); } diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7750.c b/arch/sh/kernel/cpu/sh4/setup-sh7750.c index 03b14cf78ddf..da153bcdfeb2 100644 --- a/arch/sh/kernel/cpu/sh4/setup-sh7750.c +++ b/arch/sh/kernel/cpu/sh4/setup-sh7750.c @@ -82,7 +82,7 @@ static int __init sh7750_devices_setup(void) } __initcall(sh7750_devices_setup); -static struct ipr_data sh7750_ipr_map[] = { +static struct ipr_data ipr_irq_table[] = { /* IRQ, IPR-idx, shift, priority */ { 16, 0, 12, 2 }, /* TMU0 TUNI*/ { 17, 0, 12, 2 }, /* TMU1 TUNI */ @@ -106,8 +106,27 @@ static struct ipr_data sh7750_ipr_map[] = { { 38, 2, 8, 7 }, /* DMAC DMAE */ }; +static unsigned long ipr_offsets[] = { + 0xffd00004UL, /* 0: IPRA */ + 0xffd00008UL, /* 1: IPRB */ + 0xffd0000cUL, /* 2: IPRC */ + 0xffd00010UL, /* 3: IPRD */ +}; + +static struct ipr_desc ipr_irq_desc = { + .ipr_offsets = ipr_offsets, + .nr_offsets = ARRAY_SIZE(ipr_offsets), + + .ipr_data = ipr_irq_table, + .nr_irqs = ARRAY_SIZE(ipr_irq_table), + + .chip = { + .name = "IPR-sh7750", + }, +}; + #ifdef CONFIG_CPU_SUBTYPE_SH7751 -static struct ipr_data sh7751_ipr_map[] = { +static struct ipr_data ipr_irq_table_sh7751[] = { { 44, 2, 8, 7 }, /* DMAC DMTE4 */ { 45, 2, 8, 7 }, /* DMAC DMTE5 */ { 46, 2, 8, 7 }, /* DMAC DMTE6 */ @@ -118,21 +137,26 @@ static struct ipr_data sh7751_ipr_map[] = { /*{ 72, INTPRI00, 8, ? },*/ /* TMU3 TUNI */ /*{ 76, INTPRI00, 12, ? },*/ /* TMU4 TUNI */ }; -#endif -static unsigned long ipr_offsets[] = { - 0xffd00004UL, /* 0: IPRA */ - 0xffd00008UL, /* 1: IPRB */ - 0xffd0000cUL, /* 2: IPRC */ - 0xffd00010UL, /* 3: IPRD */ +static struct ipr_desc ipr_irq_desc_sh7751 = { + .ipr_offsets = ipr_offsets, + .nr_offsets = ARRAY_SIZE(ipr_offsets), + + .ipr_data = ipr_irq_table_sh7751, + .nr_irqs = ARRAY_SIZE(ipr_irq_table_sh7751), + + .chip = { + .name = "IPR-sh7751", + }, }; +#endif -/* given the IPR index return the address of the IPR register */ -unsigned int map_ipridx_to_addr(int idx) +void __init init_IRQ_ipr(void) { - if (idx >= ARRAY_SIZE(ipr_offsets)) - return 0; - return ipr_offsets[idx]; + register_ipr_controller(&ipr_irq_desc); +#ifdef CONFIG_CPU_SUBTYPE_SH7751 + register_ipr_controller(&ipr_irq_desc_sh7751); +#endif } #define INTC_ICR 0xffd00000UL @@ -143,11 +167,3 @@ void ipr_irq_enable_irlm(void) { ctrl_outw(ctrl_inw(INTC_ICR) | INTC_ICR_IRLM, INTC_ICR); } - -void __init init_IRQ_ipr() -{ - make_ipr_irq(sh7750_ipr_map, ARRAY_SIZE(sh7750_ipr_map)); -#ifdef CONFIG_CPU_SUBTYPE_SH7751 - make_ipr_irq(sh7751_ipr_map, ARRAY_SIZE(sh7751_ipr_map)); -#endif -} diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7760.c b/arch/sh/kernel/cpu/sh4/setup-sh7760.c index 6d3c91897774..3df169755673 100644 --- a/arch/sh/kernel/cpu/sh4/setup-sh7760.c +++ b/arch/sh/kernel/cpu/sh4/setup-sh7760.c @@ -109,7 +109,12 @@ static struct intc2_desc intc2_irq_desc __read_mostly = { }, }; -static struct ipr_data sh7760_ipr_map[] = { +void __init init_IRQ_intc2(void) +{ + register_intc2_controller(&intc2_irq_desc); +} + +static struct ipr_data ipr_irq_table[] = { /* IRQ, IPR-idx, shift, priority */ { 16, 0, 12, 2 }, /* TMU0 TUNI*/ { 17, 0, 8, 2 }, /* TMU1 TUNI */ @@ -146,20 +151,19 @@ static unsigned long ipr_offsets[] = { 0xffd00010UL, /* 3: IPRD */ }; -/* given the IPR index return the address of the IPR register */ -unsigned int map_ipridx_to_addr(int idx) -{ - if (idx >= ARRAY_SIZE(ipr_offsets)) - return 0; - return ipr_offsets[idx]; -} +static struct ipr_desc ipr_irq_desc = { + .ipr_offsets = ipr_offsets, + .nr_offsets = ARRAY_SIZE(ipr_offsets), -void __init init_IRQ_intc2(void) -{ - register_intc2_controller(&intc2_irq_desc); -} + .ipr_data = ipr_irq_table, + .nr_irqs = ARRAY_SIZE(ipr_irq_table), + + .chip = { + .name = "IPR-sh7760", + }, +}; -void __init init_IRQ_ipr(void) +void __init init_IRQ_ipr(void) { - make_ipr_irq(sh7760_ipr_map, ARRAY_SIZE(sh7760_ipr_map)); + register_ipr_controller(&ipr_irq_desc); } diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c index fa07fab4797f..a3e159ef6dfe 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c @@ -44,7 +44,7 @@ static int __init sh7722_devices_setup(void) } __initcall(sh7722_devices_setup); -static struct ipr_data sh7722_ipr_map[] = { +static struct ipr_data ipr_irq_table[] = { /* IRQ, IPR-idx, shift, prio */ { 16, 0, 12, 2 }, /* TMU0 */ { 17, 0, 8, 2 }, /* TMU1 */ @@ -69,16 +69,21 @@ static unsigned long ipr_offsets[] = { 0xa408002c, /* 11: IPRL */ }; -unsigned int map_ipridx_to_addr(int idx) -{ - if (unlikely(idx >= ARRAY_SIZE(ipr_offsets))) - return 0; - return ipr_offsets[idx]; -} +static struct ipr_desc ipr_irq_desc = { + .ipr_offsets = ipr_offsets, + .nr_offsets = ARRAY_SIZE(ipr_offsets), + + .ipr_data = ipr_irq_table, + .nr_irqs = ARRAY_SIZE(ipr_irq_table), + + .chip = { + .name = "IPR-sh7722", + }, +}; void __init init_IRQ_ipr(void) { - make_ipr_irq(sh7722_ipr_map, ARRAY_SIZE(sh7722_ipr_map)); + register_ipr_controller(&ipr_irq_desc); } void __init plat_mem_setup(void) |