aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMagnus Damm <damm@igel.co.jp>2007-06-15 05:56:19 -0400
committerPaul Mundt <lethal@linux-sh.org>2007-06-15 05:56:19 -0400
commit68abdbbb03476a60d932eeba0035dd5069afec38 (patch)
treede3854f76d6d9aec121c432a3cd276bb756003c9
parent50f63f2518ee68bc132d357d2b6fdb7f60ef79e0 (diff)
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>
-rw-r--r--arch/sh/boards/se/770x/irq.c124
-rw-r--r--arch/sh/boards/se/7722/irq.c15
-rw-r--r--arch/sh/boards/se/7751/irq.c59
-rw-r--r--arch/sh/boards/sh03/setup.c28
-rw-r--r--arch/sh/boards/shmin/setup.c30
-rw-r--r--arch/sh/boards/snapgear/setup.c28
-rw-r--r--arch/sh/boards/titan/setup.c22
-rw-r--r--arch/sh/kernel/cpu/irq/ipr.c59
-rw-r--r--arch/sh/kernel/cpu/sh2/setup-sh7619.c24
-rw-r--r--arch/sh/kernel/cpu/sh2a/setup-sh7206.c24
-rw-r--r--arch/sh/kernel/cpu/sh3/setup-sh7705.c40
-rw-r--r--arch/sh/kernel/cpu/sh3/setup-sh7709.c84
-rw-r--r--arch/sh/kernel/cpu/sh3/setup-sh7710.c42
-rw-r--r--arch/sh/kernel/cpu/sh4/setup-sh7750.c58
-rw-r--r--arch/sh/kernel/cpu/sh4/setup-sh7760.c32
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7722.c21
-rw-r--r--include/asm-sh/hw_irq.h23
-rw-r--r--include/asm-sh/irq.h30
-rw-r--r--include/asm-sh/sh03/io.h4
-rw-r--r--include/asm-sh/snapgear.h4
20 files changed, 427 insertions, 324 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 @@
15#include <asm/io.h> 15#include <asm/io.h>
16#include <asm/se.h> 16#include <asm/se.h>
17 17
18/* 18static struct ipr_data ipr_irq_table[] = {
19 * If the problem of make_ipr_irq is solved,
20 * this code will become unnecessary. :-)
21 */
22static void se770x_disable_ipr_irq(unsigned int irq)
23{
24 struct ipr_data *p = get_irq_chip_data(irq);
25
26 ctrl_outw(ctrl_inw(p->addr) & (0xffff ^ (0xf << p->shift)), p->addr);
27}
28
29static void se770x_enable_ipr_irq(unsigned int irq)
30{
31 struct ipr_data *p = get_irq_chip_data(irq);
32
33 ctrl_outw(ctrl_inw(p->addr) | (p->priority << p->shift), p->addr);
34}
35
36static struct irq_chip se770x_irq_chip = {
37 .name = "MS770xSE-FPGA",
38 .mask = se770x_disable_ipr_irq,
39 .unmask = se770x_enable_ipr_irq,
40 .mask_ack = se770x_disable_ipr_irq,
41};
42
43void make_se770x_irq(struct ipr_data *table, unsigned int nr_irqs)
44{
45 int i;
46
47 for (i = 0; i < nr_irqs; i++) {
48 unsigned int irq = table[i].irq;
49 disable_irq_nosync(irq);
50 set_irq_chip_and_handler_name(irq, &se770x_irq_chip,
51 handle_level_irq, "level");
52 set_irq_chip_data(irq, &table[i]);
53 se770x_enable_ipr_irq(irq);
54 }
55}
56
57static struct ipr_data se770x_ipr_map[] = {
58 /* 19 /*
59 * Super I/O (Just mimic PC): 20 * Super I/O (Just mimic PC):
60 * 1: keyboard 21 * 1: keyboard
@@ -68,46 +29,67 @@ static struct ipr_data se770x_ipr_map[] = {
68 */ 29 */
69#if defined(CONFIG_CPU_SUBTYPE_SH7705) 30#if defined(CONFIG_CPU_SUBTYPE_SH7705)
70 /* This is default value */ 31 /* This is default value */
71 { 13, 0, 8, 0x0f-13 ,BCR_ILCRA}, 32 { 13, 0, 8, 0x0f-13, },
72 { 5 , 0, 4, 0x0f- 5 ,BCR_ILCRA}, 33 { 5 , 0, 4, 0x0f- 5, },
73 { 10, 0, 0, 0x0f-10, BCR_ILCRB}, 34 { 10, 1, 0, 0x0f-10, },
74 { 7 , 0, 4, 0x0f- 7, BCR_ILCRC}, 35 { 7 , 2, 4, 0x0f- 7, },
75 { 3 , 0, 0, 0x0f- 3, BCR_ILCRC}, 36 { 3 , 2, 0, 0x0f- 3, },
76 { 1 , 0, 12, 0x0f- 1, BCR_ILCRD}, 37 { 1 , 3, 12, 0x0f- 1, },
77 { 12, 0, 4, 0x0f-12, BCR_ILCRD}, /* LAN */ 38 { 12, 3, 4, 0x0f-12, }, /* LAN */
78 { 2 , 0, 8, 0x0f- 2, BCR_ILCRE}, /* PCIRQ2 */ 39 { 2 , 4, 8, 0x0f- 2, }, /* PCIRQ2 */
79 { 6 , 0, 4, 0x0f- 6, BCR_ILCRE}, /* PCIRQ1 */ 40 { 6 , 4, 4, 0x0f- 6, }, /* PCIRQ1 */
80 { 14, 0, 0, 0x0f-14, BCR_ILCRE}, /* PCIRQ0 */ 41 { 14, 4, 0, 0x0f-14, }, /* PCIRQ0 */
81 { 0 , 0, 12, 0x0f , BCR_ILCRF}, 42 { 0 , 5, 12, 0x0f , },
82 { 4 , 0, 4, 0x0f- 4, BCR_ILCRF}, 43 { 4 , 5, 4, 0x0f- 4, },
83 { 8 , 0, 12, 0x0f- 8, BCR_ILCRG}, 44 { 8 , 6, 12, 0x0f- 8, },
84 { 9 , 0, 8, 0x0f- 9, BCR_ILCRG}, 45 { 9 , 6, 8, 0x0f- 9, },
85 { 11, 0, 4, 0x0f-11, BCR_ILCRG}, 46 { 11, 6, 4, 0x0f-11, },
86#else 47#else
87 { 14, 0, 8, 0x0f-14 ,BCR_ILCRA}, 48 { 14, 0, 8, 0x0f-14, },
88 { 12, 0, 4, 0x0f-12 ,BCR_ILCRA}, 49 { 12, 0, 4, 0x0f-12, },
89 { 8, 0, 4, 0x0f- 8 ,BCR_ILCRB}, 50 { 8, 1, 4, 0x0f- 8, },
90 { 6, 0, 12, 0x0f- 6 ,BCR_ILCRC}, 51 { 6, 2, 12, 0x0f- 6, },
91 { 5, 0, 8, 0x0f- 5 ,BCR_ILCRC}, 52 { 5, 2, 8, 0x0f- 5, },
92 { 4, 0, 4, 0x0f- 4 ,BCR_ILCRC}, 53 { 4, 2, 4, 0x0f- 4, },
93 { 3, 0, 0, 0x0f- 3 ,BCR_ILCRC}, 54 { 3, 2, 0, 0x0f- 3, },
94 { 1, 0, 12, 0x0f- 1 ,BCR_ILCRD}, 55 { 1, 3, 12, 0x0f- 1, },
95#if defined(CONFIG_STNIC) 56#if defined(CONFIG_STNIC)
96 /* ST NIC */ 57 /* ST NIC */
97 { 10, 0, 4, 0x0f-10 ,BCR_ILCRD}, /* LAN */ 58 { 10, 3, 4, 0x0f-10, }, /* LAN */
98#endif 59#endif
99 /* MRSHPC IRQs setting */ 60 /* MRSHPC IRQs setting */
100 { 0, 0, 12, 0x0f- 0 ,BCR_ILCRE}, /* PCIRQ3 */ 61 { 0, 4, 12, 0x0f- 0, }, /* PCIRQ3 */
101 { 11, 0, 8, 0x0f-11 ,BCR_ILCRE}, /* PCIRQ2 */ 62 { 11, 4, 8, 0x0f-11, }, /* PCIRQ2 */
102 { 9, 0, 4, 0x0f- 9 ,BCR_ILCRE}, /* PCIRQ1 */ 63 { 9, 4, 4, 0x0f- 9, }, /* PCIRQ1 */
103 { 7, 0, 0, 0x0f- 7 ,BCR_ILCRE}, /* PCIRQ0 */ 64 { 7, 4, 0, 0x0f- 7, }, /* PCIRQ0 */
104 /* #2, #13 are allocated for SLOT IRQ #1 and #2 (for now) */ 65 /* #2, #13 are allocated for SLOT IRQ #1 and #2 (for now) */
105 /* NOTE: #2 and #13 are not used on PC */ 66 /* NOTE: #2 and #13 are not used on PC */
106 { 13, 0, 4, 0x0f-13 ,BCR_ILCRG}, /* SLOTIRQ2 */ 67 { 13, 6, 4, 0x0f-13, }, /* SLOTIRQ2 */
107 { 2, 0, 0, 0x0f- 2 ,BCR_ILCRG}, /* SLOTIRQ1 */ 68 { 2, 6, 0, 0x0f- 2, }, /* SLOTIRQ1 */
108#endif 69#endif
109}; 70};
110 71
72static unsigned long ipr_offsets[] = {
73 BCR_ILCRA,
74 BCR_ILCRB,
75 BCR_ILCRC,
76 BCR_ILCRD,
77 BCR_ILCRE,
78 BCR_ILCRF,
79 BCR_ILCRG,
80};
81
82static struct ipr_desc ipr_irq_desc = {
83 .ipr_offsets = ipr_offsets,
84 .nr_offsets = ARRAY_SIZE(ipr_offsets),
85
86 .ipr_data = ipr_irq_table,
87 .nr_irqs = ARRAY_SIZE(ipr_irq_table),
88 .chip = {
89 .name = "IPR-se770x",
90 },
91};
92
111/* 93/*
112 * Initialize IRQ setting 94 * Initialize IRQ setting
113 */ 95 */
@@ -122,5 +104,5 @@ void __init init_se_IRQ(void)
122 ctrl_outw(0, BCR_ILCRF); 104 ctrl_outw(0, BCR_ILCRF);
123 ctrl_outw(0, BCR_ILCRG); 105 ctrl_outw(0, BCR_ILCRG);
124 106
125 make_se770x_irq(se770x_ipr_map, ARRAY_SIZE(se770x_ipr_map)); 107 register_ipr_controller(&ipr_irq_desc);
126} 108}
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 @@
19#define INTC_INTMSK0 0xFFD00044 19#define INTC_INTMSK0 0xFFD00044
20#define INTC_INTMSKCLR0 0xFFD00064 20#define INTC_INTMSKCLR0 0xFFD00064
21 21
22struct se7722_data {
23 unsigned char irq;
24 unsigned char ipr_idx;
25 unsigned char shift;
26 unsigned short priority;
27 unsigned long addr;
28};
29
30
22static void disable_se7722_irq(unsigned int irq) 31static void disable_se7722_irq(unsigned int irq)
23{ 32{
24 struct ipr_data *p = get_irq_chip_data(irq); 33 struct se7722_data *p = get_irq_chip_data(irq);
25 ctrl_outw( ctrl_inw( p->addr ) | p->priority , p->addr ); 34 ctrl_outw( ctrl_inw( p->addr ) | p->priority , p->addr );
26} 35}
27 36
28static void enable_se7722_irq(unsigned int irq) 37static void enable_se7722_irq(unsigned int irq)
29{ 38{
30 struct ipr_data *p = get_irq_chip_data(irq); 39 struct se7722_data *p = get_irq_chip_data(irq);
31 ctrl_outw( ctrl_inw( p->addr ) & ~p->priority , p->addr ); 40 ctrl_outw( ctrl_inw( p->addr ) & ~p->priority , p->addr );
32} 41}
33 42
@@ -38,7 +47,7 @@ static struct irq_chip se7722_irq_chip __read_mostly = {
38 .mask_ack = disable_se7722_irq, 47 .mask_ack = disable_se7722_irq,
39}; 48};
40 49
41static struct ipr_data ipr_irq_table[] = { 50static struct se7722_data ipr_irq_table[] = {
42 /* irq ,idx,sft, priority , addr */ 51 /* irq ,idx,sft, priority , addr */
43 { MRSHPC_IRQ0 , 0 , 0 , MRSHPC_BIT0 , IRQ01_MASK } , 52 { MRSHPC_IRQ0 , 0 , 0 , MRSHPC_BIT0 , IRQ01_MASK } ,
44 { MRSHPC_IRQ1 , 0 , 0 , MRSHPC_BIT1 , IRQ01_MASK } , 53 { 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 @@
14#include <asm/irq.h> 14#include <asm/irq.h>
15#include <asm/se7751.h> 15#include <asm/se7751.h>
16 16
17static struct ipr_data se7751_ipr_map[] = { 17static struct ipr_data ipr_irq_table[] = {
18 /* Leave old Solution Engine code in for reference. */ 18 { 13, 3, 3, 2 },
19#if defined(CONFIG_SH_SOLUTION_ENGINE) 19 /* Add additional entries here as drivers are added and tested. */
20 /* 20};
21 * Super I/O (Just mimic PC):
22 * 1: keyboard
23 * 3: serial 0
24 * 4: serial 1
25 * 5: printer
26 * 6: floppy
27 * 8: rtc
28 * 12: mouse
29 * 14: ide0
30 */
31 { 14, BCR_ILCRA, 2, 0x0f-14 },
32 { 12, BCR_ILCRA, 1, 0x0f-12 },
33 { 8, BCR_ILCRB, 1, 0x0f- 8 },
34 { 6, BCR_ILCRC, 3, 0x0f- 6 },
35 { 5, BCR_ILCRC, 2, 0x0f- 5 },
36 { 4, BCR_ILCRC, 1, 0x0f- 4 },
37 { 3, BCR_ILCRC, 0, 0x0f- 3 },
38 { 1, BCR_ILCRD, 3, 0x0f- 1 },
39 21
40 { 10, BCR_ILCRD, 1, 0x0f-10 }, /* LAN */ 22static unsigned long ipr_offsets[] = {
23 BCR_ILCRA,
24 BCR_ILCRB,
25 BCR_ILCRC,
26 BCR_ILCRD,
27 BCR_ILCRE,
28 BCR_ILCRF,
29 BCR_ILCRG,
30};
41 31
42 { 0, BCR_ILCRE, 3, 0x0f- 0 }, /* PCIRQ3 */ 32static struct ipr_desc ipr_irq_desc = {
43 { 11, BCR_ILCRE, 2, 0x0f-11 }, /* PCIRQ2 */ 33 .ipr_offsets = ipr_offsets,
44 { 9, BCR_ILCRE, 1, 0x0f- 9 }, /* PCIRQ1 */ 34 .nr_offsets = ARRAY_SIZE(ipr_offsets),
45 { 7, BCR_ILCRE, 0, 0x0f- 7 }, /* PCIRQ0 */
46 35
47 /* #2, #13 are allocated for SLOT IRQ #1 and #2 (for now) */ 36 .ipr_data = ipr_irq_table,
48 /* NOTE: #2 and #13 are not used on PC */ 37 .nr_irqs = ARRAY_SIZE(ipr_irq_table),
49 { 13, BCR_ILCRG, 1, 0x0f-13 }, /* SLOTIRQ2 */ 38
50 { 2, BCR_ILCRG, 0, 0x0f- 2 }, /* SLOTIRQ1 */ 39 .chip = {
51#elif defined(CONFIG_SH_7751_SOLUTION_ENGINE) 40 .name = "IPR-se7751",
52 { 13, BCR_ILCRD, 3, 2 }, 41 },
53 /* Add additional entries here as drivers are added and tested. */
54#endif
55}; 42};
56 43
57/* 44/*
@@ -59,5 +46,5 @@ static struct ipr_data se7751_ipr_map[] = {
59 */ 46 */
60void __init init_7751se_IRQ(void) 47void __init init_7751se_IRQ(void)
61{ 48{
62 make_ipr_irq(se7751_ipr_map, ARRAY_SIZE(se7751_ipr_map)); 49 register_ipr_controller(&ipr_irq_desc);
63} 50}
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 @@
15#include <asm/sh03/sh03.h> 15#include <asm/sh03/sh03.h>
16#include <asm/addrspace.h> 16#include <asm/addrspace.h>
17 17
18static struct ipr_data sh03_ipr_map[] = { 18static struct ipr_data ipr_irq_table[] = {
19 { IRL0_IRQ, IRL0_IPR_ADDR, IRL0_IPR_POS, IRL0_PRIORITY }, 19 { IRL0_IRQ, 0, IRL0_IPR_POS, IRL0_PRIORITY },
20 { IRL1_IRQ, IRL1_IPR_ADDR, IRL1_IPR_POS, IRL1_PRIORITY }, 20 { IRL1_IRQ, 0, IRL1_IPR_POS, IRL1_PRIORITY },
21 { IRL2_IRQ, IRL2_IPR_ADDR, IRL2_IPR_POS, IRL2_PRIORITY }, 21 { IRL2_IRQ, 0, IRL2_IPR_POS, IRL2_PRIORITY },
22 { IRL3_IRQ, IRL3_IPR_ADDR, IRL3_IPR_POS, IRL3_PRIORITY }, 22 { IRL3_IRQ, 0, IRL3_IPR_POS, IRL3_PRIORITY },
23};
24
25static unsigned long ipr_offsets[] = {
26 INTC_IPRD,
27};
28
29static struct ipr_desc ipr_irq_desc = {
30 .ipr_offsets = ipr_offsets,
31 .nr_offsets = ARRAY_SIZE(ipr_offsets),
32
33 .ipr_data = ipr_irq_table,
34 .nr_irqs = ARRAY_SIZE(ipr_irq_table),
35
36 .chip = {
37 .name = "IPR-sh03",
38 },
23}; 39};
24 40
25static void __init init_sh03_IRQ(void) 41static void __init init_sh03_IRQ(void)
26{ 42{
27 ctrl_outw(ctrl_inw(INTC_ICR) | INTC_ICR_IRLM, INTC_ICR); 43 ctrl_outw(ctrl_inw(INTC_ICR) | INTC_ICR_IRLM, INTC_ICR);
28 make_ipr_irq(sh03_ipr_map, ARRAY_SIZE(sh03_ipr_map)); 44 register_ipr_controller(&ipr_irq_desc);
29} 45}
30 46
31extern void *cf_io_base; 47extern 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 @@
6 * SHMIN Support. 6 * SHMIN Support.
7 */ 7 */
8#include <linux/init.h> 8#include <linux/init.h>
9#include <linux/irq.h>
9#include <asm/machvec.h> 10#include <asm/machvec.h>
10#include <asm/shmin.h> 11#include <asm/shmin.h>
11#include <asm/clock.h> 12#include <asm/clock.h>
12#include <asm/irq.h>
13#include <asm/io.h> 13#include <asm/io.h>
14 14
15#define PFC_PHCR 0xa400010eUL 15#define PFC_PHCR 0xa400010eUL
16#define INTC_ICR1 0xa4000010UL 16#define INTC_ICR1 0xa4000010UL
17#define INTC_IPRC 0xa4000016UL 17#define INTC_IPRC 0xa4000016UL
18 18
19static struct ipr_data shmin_ipr_map[] = { 19static struct ipr_data ipr_irq_table[] = {
20 { .irq=32, .addr=INTC_IPRC, .shift= 0, .priority=0 }, 20 { 32, 0, 0, 0 },
21 { .irq=33, .addr=INTC_IPRC, .shift= 4, .priority=0 }, 21 { 33, 0, 4, 0 },
22 { .irq=34, .addr=INTC_IPRC, .shift= 8, .priority=8 }, 22 { 34, 0, 8, 8 },
23 { .irq=35, .addr=INTC_IPRC, .shift=12, .priority=0 }, 23 { 35, 0, 12, 0 },
24};
25
26static unsigned long ipr_offsets[] = {
27 INTC_IPRC,
28};
29
30static struct ipr_desc ipr_irq_desc = {
31 .ipr_offsets = ipr_offsets,
32 .nr_offsets = ARRAY_SIZE(ipr_offsets),
33
34 .ipr_data = ipr_irq_table,
35 .nr_irqs = ARRAY_SIZE(ipr_irq_table),
36
37 .chip = {
38 .name = "IPR-shmin",
39 },
24}; 40};
25 41
26static void __init init_shmin_irq(void) 42static void __init init_shmin_irq(void)
27{ 43{
28 ctrl_outw(0x2a00, PFC_PHCR); // IRQ0-3=IRQ 44 ctrl_outw(0x2a00, PFC_PHCR); // IRQ0-3=IRQ
29 ctrl_outw(0x0aaa, INTC_ICR1); // IRQ0-3=IRQ-mode,Low-active. 45 ctrl_outw(0x0aaa, INTC_ICR1); // IRQ0-3=IRQ-mode,Low-active.
30 make_ipr_irq(shmin_ipr_map, ARRAY_SIZE(shmin_ipr_map)); 46 register_ipr_controller(&ipr_irq_desc);
31} 47}
32 48
33static void __iomem *shmin_ioport_map(unsigned long port, unsigned int size) 49static 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);
68 * IRL3 = crypto 68 * IRL3 = crypto
69 */ 69 */
70 70
71static struct ipr_data snapgear_ipr_map[] = { 71static struct ipr_data ipr_irq_table[] = {
72 make_ipr_irq(IRL0_IRQ, IRL0_IPR_ADDR, IRL0_IPR_POS, IRL0_PRIORITY); 72 { IRL0_IRQ, 0, IRL0_IPR_POS, IRL0_PRIORITY },
73 make_ipr_irq(IRL1_IRQ, IRL1_IPR_ADDR, IRL1_IPR_POS, IRL1_PRIORITY); 73 { IRL1_IRQ, 0, IRL1_IPR_POS, IRL1_PRIORITY },
74 make_ipr_irq(IRL2_IRQ, IRL2_IPR_ADDR, IRL2_IPR_POS, IRL2_PRIORITY); 74 { IRL2_IRQ, 0, IRL2_IPR_POS, IRL2_PRIORITY },
75 make_ipr_irq(IRL3_IRQ, IRL3_IPR_ADDR, IRL3_IPR_POS, IRL3_PRIORITY); 75 { IRL3_IRQ, 0, IRL3_IPR_POS, IRL3_PRIORITY },
76};
77
78static unsigned long ipr_offsets[] = {
79 INTC_IPRD,
80};
81
82static struct ipr_desc ipr_irq_desc = {
83 .ipr_offsets = ipr_offsets,
84 .nr_offsets = ARRAY_SIZE(ipr_offsets),
85
86 .ipr_data = ipr_irq_table,
87 .nr_irqs = ARRAY_SIZE(ipr_irq_table),
88
89 .chip = {
90 .name = "IPR-snapgear",
91 },
76}; 92};
77 93
78static void __init init_snapgear_IRQ(void) 94static void __init init_snapgear_IRQ(void)
@@ -82,7 +98,7 @@ static void __init init_snapgear_IRQ(void)
82 98
83 printk("Setup SnapGear IRQ/IPR ...\n"); 99 printk("Setup SnapGear IRQ/IPR ...\n");
84 100
85 make_ipr_irq(snapgear_ipr_map, ARRAY_SIZE(snapgear_ipr_map)); 101 register_ipr_controller(&ipr_irq_desc);
86} 102}
87 103
88/* 104/*
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 @@
12#include <asm/titan.h> 12#include <asm/titan.h>
13#include <asm/io.h> 13#include <asm/io.h>
14 14
15static struct ipr_data titan_ipr_map[] = { 15static struct ipr_data ipr_irq_table[] = {
16 /* IRQ, IPR idx, shift, prio */ 16 /* IRQ, IPR idx, shift, prio */
17 { TITAN_IRQ_WAN, 3, 12, 8 }, /* eth0 (WAN) */ 17 { TITAN_IRQ_WAN, 3, 12, 8 }, /* eth0 (WAN) */
18 { TITAN_IRQ_LAN, 3, 8, 8 }, /* eth1 (LAN) */ 18 { TITAN_IRQ_LAN, 3, 8, 8 }, /* eth1 (LAN) */
@@ -20,12 +20,30 @@ static struct ipr_data titan_ipr_map[] = {
20 { TITAN_IRQ_USB, 3, 0, 8 }, /* mPCI B (bottom), USB */ 20 { TITAN_IRQ_USB, 3, 0, 8 }, /* mPCI B (bottom), USB */
21}; 21};
22 22
23static unsigned long ipr_offsets[] = { /* stolen from setup-sh7750.c */
24 0xffd00004UL, /* 0: IPRA */
25 0xffd00008UL, /* 1: IPRB */
26 0xffd0000cUL, /* 2: IPRC */
27 0xffd00010UL, /* 3: IPRD */
28};
29
30static struct ipr_desc ipr_irq_desc = {
31 .ipr_offsets = ipr_offsets,
32 .nr_offsets = ARRAY_SIZE(ipr_offsets),
33
34 .ipr_data = ipr_irq_table,
35 .nr_irqs = ARRAY_SIZE(ipr_irq_table),
36
37 .chip = {
38 .name = "IPR-titan",
39 },
40};
23static void __init init_titan_irq(void) 41static void __init init_titan_irq(void)
24{ 42{
25 /* enable individual interrupt mode for externals */ 43 /* enable individual interrupt mode for externals */
26 ipr_irq_enable_irlm(); 44 ipr_irq_enable_irlm();
27 /* register ipr irqs */ 45 /* register ipr irqs */
28 make_ipr_irq(titan_ipr_map, ARRAY_SIZE(titan_ipr_map)); 46 register_ipr_controller(&ipr_irq_desc);
29} 47}
30 48
31static struct sh_machine_vector mv_titan __initmv = { 49static 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 @@
22#include <linux/io.h> 22#include <linux/io.h>
23#include <linux/interrupt.h> 23#include <linux/interrupt.h>
24 24
25static inline struct ipr_desc *get_ipr_desc(unsigned int irq)
26{
27 struct irq_chip *chip = get_irq_chip(irq);
28 return (void *)((char *)chip - offsetof(struct ipr_desc, chip));
29}
30
25static void disable_ipr_irq(unsigned int irq) 31static void disable_ipr_irq(unsigned int irq)
26{ 32{
27 struct ipr_data *p = get_irq_chip_data(irq); 33 struct ipr_data *p = get_irq_chip_data(irq);
34 unsigned long addr = get_ipr_desc(irq)->ipr_offsets[p->ipr_idx];
28 /* Set the priority in IPR to 0 */ 35 /* Set the priority in IPR to 0 */
29 ctrl_outw(ctrl_inw(p->addr) & (0xffff ^ (0xf << p->shift)), p->addr); 36 ctrl_outw(ctrl_inw(addr) & (0xffff ^ (0xf << p->shift)), addr);
30} 37}
31 38
32static void enable_ipr_irq(unsigned int irq) 39static void enable_ipr_irq(unsigned int irq)
33{ 40{
34 struct ipr_data *p = get_irq_chip_data(irq); 41 struct ipr_data *p = get_irq_chip_data(irq);
42 unsigned long addr = get_ipr_desc(irq)->ipr_offsets[p->ipr_idx];
35 /* Set priority in IPR back to original value */ 43 /* Set priority in IPR back to original value */
36 ctrl_outw(ctrl_inw(p->addr) | (p->priority << p->shift), p->addr); 44 ctrl_outw(ctrl_inw(addr) | (p->priority << p->shift), addr);
37} 45}
38 46
39static struct irq_chip ipr_irq_chip = { 47/*
40 .name = "IPR", 48 * The shift value is now the number of bits to shift, not the number of
41 .mask = disable_ipr_irq, 49 * bits/4. This is to make it easier to read the value directly from the
42 .unmask = enable_ipr_irq, 50 * datasheets. The IPR address is calculated using the ipr_offset table.
43 .mask_ack = disable_ipr_irq, 51 */
44};
45
46unsigned int map_ipridx_to_addr(int idx) __attribute__ ((weak));
47unsigned int map_ipridx_to_addr(int idx)
48{
49 return 0;
50}
51 52
52void make_ipr_irq(struct ipr_data *table, unsigned int nr_irqs) 53void register_ipr_controller(struct ipr_desc *desc)
53{ 54{
54 int i; 55 int i;
55 56
56 for (i = 0; i < nr_irqs; i++) { 57 desc->chip.mask = disable_ipr_irq;
57 unsigned int irq = table[i].irq; 58 desc->chip.unmask = enable_ipr_irq;
59 desc->chip.mask_ack = disable_ipr_irq;
58 60
59 if (!irq) 61 for (i = 0; i < desc->nr_irqs; i++) {
60 irq = table[i].irq = i; 62 struct ipr_data *p = desc->ipr_data + i;
61 63
62 /* could the IPR index be mapped, if not we ignore this */ 64 BUG_ON(p->ipr_idx >= desc->nr_offsets);
63 if (!table[i].addr) { 65 BUG_ON(!desc->ipr_offsets[p->ipr_idx]);
64 table[i].addr = map_ipridx_to_addr(table[i].ipr_idx);
65 if (!table[i].addr)
66 continue;
67 }
68 66
69 disable_irq_nosync(irq); 67 disable_irq_nosync(p->irq);
70 set_irq_chip_and_handler_name(irq, &ipr_irq_chip, 68 set_irq_chip_and_handler_name(p->irq, &desc->chip,
71 handle_level_irq, "level"); 69 handle_level_irq, "level");
72 set_irq_chip_data(irq, &table[i]); 70 set_irq_chip_data(p->irq, p);
73 enable_ipr_irq(irq); 71 disable_ipr_irq(p->irq);
74 } 72 }
75} 73}
76EXPORT_SYMBOL(make_ipr_irq); 74
75EXPORT_SYMBOL(register_ipr_controller);
77 76
78#if !defined(CONFIG_CPU_HAS_PINT_IRQ) 77#if !defined(CONFIG_CPU_HAS_PINT_IRQ)
79int ipr_irq_demux(int irq) 78int 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)
52} 52}
53__initcall(sh7619_devices_setup); 53__initcall(sh7619_devices_setup);
54 54
55static struct ipr_data sh7619_ipr_map[] = { 55static struct ipr_data ipr_irq_table[] = {
56 { 86, 0, 4, 2 }, /* CMI0 */ 56 { 86, 0, 4, 2 }, /* CMI0 */
57 { 88, 1, 12, 3 }, /* SCIF0_ERI */ 57 { 88, 1, 12, 3 }, /* SCIF0_ERI */
58 { 89, 1, 12, 3 }, /* SCIF0_RXI */ 58 { 89, 1, 12, 3 }, /* SCIF0_RXI */
@@ -68,7 +68,7 @@ static struct ipr_data sh7619_ipr_map[] = {
68 { 99, 1, 4, 3 }, /* SCIF2_TXI */ 68 { 99, 1, 4, 3 }, /* SCIF2_TXI */
69}; 69};
70 70
71static unsigned int ipr_offsets[] = { 71static unsigned long ipr_offsets[] = {
72 0xf8080000, /* IPRC */ 72 0xf8080000, /* IPRC */
73 0xf8080002, /* IPRD */ 73 0xf8080002, /* IPRD */
74 0xf8080004, /* IPRE */ 74 0xf8080004, /* IPRE */
@@ -76,15 +76,19 @@ static unsigned int ipr_offsets[] = {
76 0xf8080008, /* IPRG */ 76 0xf8080008, /* IPRG */
77}; 77};
78 78
79/* given the IPR index return the address of the IPR register */ 79static struct ipr_desc ipr_irq_desc = {
80unsigned int map_ipridx_to_addr(int idx) 80 .ipr_offsets = ipr_offsets,
81{ 81 .nr_offsets = ARRAY_SIZE(ipr_offsets),
82 if (unlikely(idx >= ARRAY_SIZE(ipr_offsets))) 82
83 return 0; 83 .ipr_data = ipr_irq_table,
84 return ipr_offsets[idx]; 84 .nr_irqs = ARRAY_SIZE(ipr_irq_table),
85} 85
86 .chip = {
87 .name = "IPR-sh7619",
88 },
89};
86 90
87void __init init_IRQ_ipr(void) 91void __init init_IRQ_ipr(void)
88{ 92{
89 make_ipr_irq(sh7619_ipr_map, ARRAY_SIZE(sh7619_ipr_map)); 93 register_ipr_controller(&ipr_irq_desc);
90} 94}
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)
57} 57}
58__initcall(sh7206_devices_setup); 58__initcall(sh7206_devices_setup);
59 59
60static struct ipr_data sh7206_ipr_map[] = { 60static struct ipr_data ipr_irq_table[] = {
61 { 140, 7, 12, 2 }, /* CMI0 */ 61 { 140, 7, 12, 2 }, /* CMI0 */
62 { 164, 8, 4, 2 }, /* MTU2_TGI1A */ 62 { 164, 8, 4, 2 }, /* MTU2_TGI1A */
63 { 240, 13, 12, 3 }, /* SCIF0_BRI */ 63 { 240, 13, 12, 3 }, /* SCIF0_BRI */
@@ -78,7 +78,7 @@ static struct ipr_data sh7206_ipr_map[] = {
78 { 255, 13, 0, 3 }, /* SCIF3_TXI */ 78 { 255, 13, 0, 3 }, /* SCIF3_TXI */
79}; 79};
80 80
81static unsigned int ipr_offsets[] = { 81static unsigned long ipr_offsets[] = {
82 0xfffe0818, /* IPR01 */ 82 0xfffe0818, /* IPR01 */
83 0xfffe081a, /* IPR02 */ 83 0xfffe081a, /* IPR02 */
84 0, /* unused */ 84 0, /* unused */
@@ -95,15 +95,19 @@ static unsigned int ipr_offsets[] = {
95 0xfffe0c10, /* IPR14 */ 95 0xfffe0c10, /* IPR14 */
96}; 96};
97 97
98/* given the IPR index return the address of the IPR register */ 98static struct ipr_desc ipr_irq_desc = {
99unsigned int map_ipridx_to_addr(int idx) 99 .ipr_offsets = ipr_offsets,
100{ 100 .nr_offsets = ARRAY_SIZE(ipr_offsets),
101 if (unlikely(idx >= ARRAY_SIZE(ipr_offsets))) 101
102 return 0; 102 .ipr_data = ipr_irq_table,
103 return ipr_offsets[idx]; 103 .nr_irqs = ARRAY_SIZE(ipr_irq_table),
104} 104
105 .chip = {
106 .name = "IPR-sh7206",
107 },
108};
105 109
106void __init init_IRQ_ipr(void) 110void __init init_IRQ_ipr(void)
107{ 111{
108 make_ipr_irq(sh7206_ipr_map, ARRAY_SIZE(sh7206_ipr_map)); 112 register_ipr_controller(&ipr_irq_desc);
109} 113}
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)
48} 48}
49__initcall(sh7705_devices_setup); 49__initcall(sh7705_devices_setup);
50 50
51static struct ipr_data sh7705_ipr_map[] = { 51static struct ipr_data ipr_irq_table[] = {
52 /* IRQ, IPR-idx, shift, priority */ 52 /* IRQ, IPR-idx, shift, priority */
53 { 16, 0, 12, 2 }, /* TMU0 TUNI*/ 53 { 16, 0, 12, 2 }, /* TMU0 TUNI*/
54 { 17, 0, 8, 2 }, /* TMU1 TUNI */ 54 { 17, 0, 8, 2 }, /* TMU1 TUNI */
@@ -70,25 +70,29 @@ static struct ipr_data sh7705_ipr_map[] = {
70}; 70};
71 71
72static unsigned long ipr_offsets[] = { 72static unsigned long ipr_offsets[] = {
73 0xFFFFFEE2 /* 0: IPRA */ 73 0xFFFFFEE2, /* 0: IPRA */
74, 0xFFFFFEE4 /* 1: IPRB */ 74 0xFFFFFEE4, /* 1: IPRB */
75, 0xA4000016 /* 2: IPRC */ 75 0xA4000016, /* 2: IPRC */
76, 0xA4000018 /* 3: IPRD */ 76 0xA4000018, /* 3: IPRD */
77, 0xA400001A /* 4: IPRE */ 77 0xA400001A, /* 4: IPRE */
78, 0xA4080000 /* 5: IPRF */ 78 0xA4080000, /* 5: IPRF */
79, 0xA4080002 /* 6: IPRG */ 79 0xA4080002, /* 6: IPRG */
80, 0xA4080004 /* 7: IPRH */ 80 0xA4080004, /* 7: IPRH */
81}; 81};
82 82
83/* given the IPR index return the address of the IPR register */ 83static struct ipr_desc ipr_irq_desc = {
84unsigned int map_ipridx_to_addr(int idx) 84 .ipr_offsets = ipr_offsets,
85{ 85 .nr_offsets = ARRAY_SIZE(ipr_offsets),
86 if (idx >= ARRAY_SIZE(ipr_offsets)) 86
87 return 0; 87 .ipr_data = ipr_irq_table,
88 return ipr_offsets[idx]; 88 .nr_irqs = ARRAY_SIZE(ipr_irq_table),
89} 89
90 .chip = {
91 .name = "IPR-sh7705",
92 },
93};
90 94
91void __init init_IRQ_ipr() 95void __init init_IRQ_ipr(void)
92{ 96{
93 make_ipr_irq(sh7705_ipr_map, ARRAY_SIZE(sh7705_ipr_map)); 97 register_ipr_controller(&ipr_irq_desc);
94} 98}
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)
52} 52}
53__initcall(sh7709_devices_setup); 53__initcall(sh7709_devices_setup);
54 54
55#define IPRx(A,N) .addr=A, .shift=N 55static struct ipr_data ipr_irq_table[] = {
56#define IPRA(N) IPRx(0xfffffee2UL,N) 56 { 16, 0, 12, 2 }, /* TMU TUNI0 */
57#define IPRB(N) IPRx(0xfffffee4UL,N) 57 { 17, 0, 8, 4 }, /* TMU TUNI1 */
58#define IPRC(N) IPRx(0xa4000016UL,N) 58 { 18, 0, 4, 1 }, /* TMU TUNI1 */
59#define IPRD(N) IPRx(0xa4000018UL,N) 59 { 19, 0, 4, 1 }, /* TMU TUNI1 */
60#define IPRE(N) IPRx(0xa400001aUL,N) 60 { 20, 0, 0, 2 }, /* RTC CUI */
61 61 { 21, 0, 0, 2 }, /* RTC CUI */
62static struct ipr_data sh7709_ipr_map[] = { 62 { 22, 0, 0, 2 }, /* RTC CUI */
63 [16] = { IPRA(12), 2 }, /* TMU TUNI0 */ 63
64 [17] = { IPRA(8), 4 }, /* TMU TUNI1 */ 64 { 23, 1, 4, 3 }, /* SCI */
65 [18 ... 19] = { IPRA(4), 1 }, /* TMU TUNI1 */ 65 { 24, 1, 4, 3 }, /* SCI */
66 [20 ... 22] = { IPRA(0), 2 }, /* RTC CUI */ 66 { 25, 1, 4, 3 }, /* SCI */
67 [23 ... 26] = { IPRB(4), 3 }, /* SCI */ 67 { 26, 1, 4, 3 }, /* SCI */
68 [27] = { IPRB(12), 2 }, /* WDT ITI */ 68 { 27, 1, 12, 3 }, /* WDT ITI */
69 [32] = { IPRC(0), 1 }, /* IRQ 0 */ 69
70 [33] = { IPRC(4), 1 }, /* IRQ 1 */ 70 { 32, 2, 0, 1 }, /* IRQ 0 */
71 [34] = { IPRC(8), 1 }, /* IRQ 2 APM */ 71 { 33, 2, 4, 1 }, /* IRQ 1 */
72 [35] = { IPRC(12), 1 }, /* IRQ 3 TOUCHSCREEN */ 72 { 34, 2, 8, 1 }, /* IRQ 2 APM */
73 [36] = { IPRD(0), 1 }, /* IRQ 4 */ 73 { 35, 2, 12, 1 }, /* IRQ 3 TOUCHSCREEN */
74 [37] = { IPRD(4), 1 }, /* IRQ 5 */ 74
75 [48 ... 51] = { IPRE(12), 7 }, /* DMA */ 75 { 36, 3, 0, 1 }, /* IRQ 4 */
76 [52 ... 55] = { IPRE(8), 3 }, /* IRDA */ 76 { 37, 3, 4, 1 }, /* IRQ 5 */
77 [56 ... 59] = { IPRE(4), 3 }, /* SCIF */ 77
78 { 48, 4, 12, 7 }, /* DMA */
79 { 49, 4, 12, 7 }, /* DMA */
80 { 50, 4, 12, 7 }, /* DMA */
81 { 51, 4, 12, 7 }, /* DMA */
82
83 { 52, 4, 8, 3 }, /* IRDA */
84 { 53, 4, 8, 3 }, /* IRDA */
85 { 54, 4, 8, 3 }, /* IRDA */
86 { 55, 4, 8, 3 }, /* IRDA */
87
88 { 56, 4, 4, 3 }, /* SCIF */
89 { 57, 4, 4, 3 }, /* SCIF */
90 { 58, 4, 4, 3 }, /* SCIF */
91 { 59, 4, 4, 3 }, /* SCIF */
92};
93
94static unsigned long ipr_offsets[] = {
95 0xfffffee2, /* 0: IPRA */
96 0xfffffee4, /* 1: IPRB */
97 0xa4000016, /* 2: IPRC */
98 0xa4000018, /* 3: IPRD */
99 0xa400001a, /* 4: IPRE */
100};
101
102static struct ipr_desc ipr_irq_desc = {
103 .ipr_offsets = ipr_offsets,
104 .nr_offsets = ARRAY_SIZE(ipr_offsets),
105
106 .ipr_data = ipr_irq_table,
107 .nr_irqs = ARRAY_SIZE(ipr_irq_table),
108
109 .chip = {
110 .name = "IPR-sh7709",
111 },
78}; 112};
79 113
80void __init init_IRQ_ipr() 114void __init init_IRQ_ipr(void)
81{ 115{
82 make_ipr_irq(sh7709_ipr_map, ARRAY_SIZE(sh7709_ipr_map)); 116 register_ipr_controller(&ipr_irq_desc);
83} 117}
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)
49} 49}
50__initcall(sh7710_devices_setup); 50__initcall(sh7710_devices_setup);
51 51
52static struct ipr_data sh7710_ipr_map[] = { 52static struct ipr_data ipr_irq_table[] = {
53 /* IRQ, IPR-idx, shift, priority */ 53 /* IRQ, IPR-idx, shift, priority */
54 { 16, 0, 12, 2 }, /* TMU0 TUNI*/ 54 { 16, 0, 12, 2 }, /* TMU0 TUNI*/
55 { 17, 0, 8, 2 }, /* TMU1 TUNI */ 55 { 17, 0, 8, 2 }, /* TMU1 TUNI */
@@ -78,26 +78,30 @@ static struct ipr_data sh7710_ipr_map[] = {
78}; 78};
79 79
80static unsigned long ipr_offsets[] = { 80static unsigned long ipr_offsets[] = {
81 0xA414FEE2 /* 0: IPRA */ 81 0xA414FEE2, /* 0: IPRA */
82, 0xA414FEE4 /* 1: IPRB */ 82 0xA414FEE4, /* 1: IPRB */
83, 0xA4140016 /* 2: IPRC */ 83 0xA4140016, /* 2: IPRC */
84, 0xA4140018 /* 3: IPRD */ 84 0xA4140018, /* 3: IPRD */
85, 0xA414001A /* 4: IPRE */ 85 0xA414001A, /* 4: IPRE */
86, 0xA4080000 /* 5: IPRF */ 86 0xA4080000, /* 5: IPRF */
87, 0xA4080002 /* 6: IPRG */ 87 0xA4080002, /* 6: IPRG */
88, 0xA4080004 /* 7: IPRH */ 88 0xA4080004, /* 7: IPRH */
89, 0xA4080006 /* 8: IPRI */ 89 0xA4080006, /* 8: IPRI */
90}; 90};
91 91
92/* given the IPR index return the address of the IPR register */ 92static struct ipr_desc ipr_irq_desc = {
93unsigned int map_ipridx_to_addr(int idx) 93 .ipr_offsets = ipr_offsets,
94{ 94 .nr_offsets = ARRAY_SIZE(ipr_offsets),
95 if (idx >= ARRAY_SIZE(ipr_offsets)) 95
96 return 0; 96 .ipr_data = ipr_irq_table,
97 return ipr_offsets[idx]; 97 .nr_irqs = ARRAY_SIZE(ipr_irq_table),
98} 98
99 .chip = {
100 .name = "IPR-sh7710",
101 },
102};
99 103
100void __init init_IRQ_ipr() 104void __init init_IRQ_ipr(void)
101{ 105{
102 make_ipr_irq(sh7710_ipr_map, ARRAY_SIZE(sh7710_ipr_map)); 106 register_ipr_controller(&ipr_irq_desc);
103} 107}
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)
82} 82}
83__initcall(sh7750_devices_setup); 83__initcall(sh7750_devices_setup);
84 84
85static struct ipr_data sh7750_ipr_map[] = { 85static struct ipr_data ipr_irq_table[] = {
86 /* IRQ, IPR-idx, shift, priority */ 86 /* IRQ, IPR-idx, shift, priority */
87 { 16, 0, 12, 2 }, /* TMU0 TUNI*/ 87 { 16, 0, 12, 2 }, /* TMU0 TUNI*/
88 { 17, 0, 12, 2 }, /* TMU1 TUNI */ 88 { 17, 0, 12, 2 }, /* TMU1 TUNI */
@@ -106,8 +106,27 @@ static struct ipr_data sh7750_ipr_map[] = {
106 { 38, 2, 8, 7 }, /* DMAC DMAE */ 106 { 38, 2, 8, 7 }, /* DMAC DMAE */
107}; 107};
108 108
109static unsigned long ipr_offsets[] = {
110 0xffd00004UL, /* 0: IPRA */
111 0xffd00008UL, /* 1: IPRB */
112 0xffd0000cUL, /* 2: IPRC */
113 0xffd00010UL, /* 3: IPRD */
114};
115
116static struct ipr_desc ipr_irq_desc = {
117 .ipr_offsets = ipr_offsets,
118 .nr_offsets = ARRAY_SIZE(ipr_offsets),
119
120 .ipr_data = ipr_irq_table,
121 .nr_irqs = ARRAY_SIZE(ipr_irq_table),
122
123 .chip = {
124 .name = "IPR-sh7750",
125 },
126};
127
109#ifdef CONFIG_CPU_SUBTYPE_SH7751 128#ifdef CONFIG_CPU_SUBTYPE_SH7751
110static struct ipr_data sh7751_ipr_map[] = { 129static struct ipr_data ipr_irq_table_sh7751[] = {
111 { 44, 2, 8, 7 }, /* DMAC DMTE4 */ 130 { 44, 2, 8, 7 }, /* DMAC DMTE4 */
112 { 45, 2, 8, 7 }, /* DMAC DMTE5 */ 131 { 45, 2, 8, 7 }, /* DMAC DMTE5 */
113 { 46, 2, 8, 7 }, /* DMAC DMTE6 */ 132 { 46, 2, 8, 7 }, /* DMAC DMTE6 */
@@ -118,21 +137,26 @@ static struct ipr_data sh7751_ipr_map[] = {
118 /*{ 72, INTPRI00, 8, ? },*/ /* TMU3 TUNI */ 137 /*{ 72, INTPRI00, 8, ? },*/ /* TMU3 TUNI */
119 /*{ 76, INTPRI00, 12, ? },*/ /* TMU4 TUNI */ 138 /*{ 76, INTPRI00, 12, ? },*/ /* TMU4 TUNI */
120}; 139};
121#endif
122 140
123static unsigned long ipr_offsets[] = { 141static struct ipr_desc ipr_irq_desc_sh7751 = {
124 0xffd00004UL, /* 0: IPRA */ 142 .ipr_offsets = ipr_offsets,
125 0xffd00008UL, /* 1: IPRB */ 143 .nr_offsets = ARRAY_SIZE(ipr_offsets),
126 0xffd0000cUL, /* 2: IPRC */ 144
127 0xffd00010UL, /* 3: IPRD */ 145 .ipr_data = ipr_irq_table_sh7751,
146 .nr_irqs = ARRAY_SIZE(ipr_irq_table_sh7751),
147
148 .chip = {
149 .name = "IPR-sh7751",
150 },
128}; 151};
152#endif
129 153
130/* given the IPR index return the address of the IPR register */ 154void __init init_IRQ_ipr(void)
131unsigned int map_ipridx_to_addr(int idx)
132{ 155{
133 if (idx >= ARRAY_SIZE(ipr_offsets)) 156 register_ipr_controller(&ipr_irq_desc);
134 return 0; 157#ifdef CONFIG_CPU_SUBTYPE_SH7751
135 return ipr_offsets[idx]; 158 register_ipr_controller(&ipr_irq_desc_sh7751);
159#endif
136} 160}
137 161
138#define INTC_ICR 0xffd00000UL 162#define INTC_ICR 0xffd00000UL
@@ -143,11 +167,3 @@ void ipr_irq_enable_irlm(void)
143{ 167{
144 ctrl_outw(ctrl_inw(INTC_ICR) | INTC_ICR_IRLM, INTC_ICR); 168 ctrl_outw(ctrl_inw(INTC_ICR) | INTC_ICR_IRLM, INTC_ICR);
145} 169}
146
147void __init init_IRQ_ipr()
148{
149 make_ipr_irq(sh7750_ipr_map, ARRAY_SIZE(sh7750_ipr_map));
150#ifdef CONFIG_CPU_SUBTYPE_SH7751
151 make_ipr_irq(sh7751_ipr_map, ARRAY_SIZE(sh7751_ipr_map));
152#endif
153}
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 = {
109 }, 109 },
110}; 110};
111 111
112static struct ipr_data sh7760_ipr_map[] = { 112void __init init_IRQ_intc2(void)
113{
114 register_intc2_controller(&intc2_irq_desc);
115}
116
117static struct ipr_data ipr_irq_table[] = {
113 /* IRQ, IPR-idx, shift, priority */ 118 /* IRQ, IPR-idx, shift, priority */
114 { 16, 0, 12, 2 }, /* TMU0 TUNI*/ 119 { 16, 0, 12, 2 }, /* TMU0 TUNI*/
115 { 17, 0, 8, 2 }, /* TMU1 TUNI */ 120 { 17, 0, 8, 2 }, /* TMU1 TUNI */
@@ -146,20 +151,19 @@ static unsigned long ipr_offsets[] = {
146 0xffd00010UL, /* 3: IPRD */ 151 0xffd00010UL, /* 3: IPRD */
147}; 152};
148 153
149/* given the IPR index return the address of the IPR register */ 154static struct ipr_desc ipr_irq_desc = {
150unsigned int map_ipridx_to_addr(int idx) 155 .ipr_offsets = ipr_offsets,
151{ 156 .nr_offsets = ARRAY_SIZE(ipr_offsets),
152 if (idx >= ARRAY_SIZE(ipr_offsets))
153 return 0;
154 return ipr_offsets[idx];
155}
156 157
157void __init init_IRQ_intc2(void) 158 .ipr_data = ipr_irq_table,
158{ 159 .nr_irqs = ARRAY_SIZE(ipr_irq_table),
159 register_intc2_controller(&intc2_irq_desc); 160
160} 161 .chip = {
162 .name = "IPR-sh7760",
163 },
164};
161 165
162void __init init_IRQ_ipr(void) 166void __init init_IRQ_ipr(void)
163{ 167{
164 make_ipr_irq(sh7760_ipr_map, ARRAY_SIZE(sh7760_ipr_map)); 168 register_ipr_controller(&ipr_irq_desc);
165} 169}
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)
44} 44}
45__initcall(sh7722_devices_setup); 45__initcall(sh7722_devices_setup);
46 46
47static struct ipr_data sh7722_ipr_map[] = { 47static struct ipr_data ipr_irq_table[] = {
48 /* IRQ, IPR-idx, shift, prio */ 48 /* IRQ, IPR-idx, shift, prio */
49 { 16, 0, 12, 2 }, /* TMU0 */ 49 { 16, 0, 12, 2 }, /* TMU0 */
50 { 17, 0, 8, 2 }, /* TMU1 */ 50 { 17, 0, 8, 2 }, /* TMU1 */
@@ -69,16 +69,21 @@ static unsigned long ipr_offsets[] = {
69 0xa408002c, /* 11: IPRL */ 69 0xa408002c, /* 11: IPRL */
70}; 70};
71 71
72unsigned int map_ipridx_to_addr(int idx) 72static struct ipr_desc ipr_irq_desc = {
73{ 73 .ipr_offsets = ipr_offsets,
74 if (unlikely(idx >= ARRAY_SIZE(ipr_offsets))) 74 .nr_offsets = ARRAY_SIZE(ipr_offsets),
75 return 0; 75
76 return ipr_offsets[idx]; 76 .ipr_data = ipr_irq_table,
77} 77 .nr_irqs = ARRAY_SIZE(ipr_irq_table),
78
79 .chip = {
80 .name = "IPR-sh7722",
81 },
82};
78 83
79void __init init_IRQ_ipr(void) 84void __init init_IRQ_ipr(void)
80{ 85{
81 make_ipr_irq(sh7722_ipr_map, ARRAY_SIZE(sh7722_ipr_map)); 86 register_ipr_controller(&ipr_irq_desc);
82} 87}
83 88
84void __init plat_mem_setup(void) 89void __init plat_mem_setup(void)
diff --git a/include/asm-sh/hw_irq.h b/include/asm-sh/hw_irq.h
index f9dfdc04aef5..4ca3f765bacc 100644
--- a/include/asm-sh/hw_irq.h
+++ b/include/asm-sh/hw_irq.h
@@ -24,4 +24,27 @@ struct intc2_desc {
24void register_intc2_controller(struct intc2_desc *); 24void register_intc2_controller(struct intc2_desc *);
25void init_IRQ_intc2(void); 25void init_IRQ_intc2(void);
26 26
27struct ipr_data {
28 unsigned char irq;
29 unsigned char ipr_idx; /* Index for the IPR registered */
30 unsigned char shift; /* Number of bits to shift the data */
31 unsigned char priority; /* The priority */
32};
33
34struct ipr_desc {
35 unsigned long *ipr_offsets;
36 unsigned int nr_offsets;
37 struct ipr_data *ipr_data;
38 unsigned int nr_irqs;
39 struct irq_chip chip;
40};
41
42void register_ipr_controller(struct ipr_desc *);
43void init_IRQ_ipr(void);
44
45/*
46 * Enable individual interrupt mode for external IPR IRQs.
47 */
48void ipr_irq_enable_irlm(void);
49
27#endif /* __ASM_SH_HW_IRQ_H */ 50#endif /* __ASM_SH_HW_IRQ_H */
diff --git a/include/asm-sh/irq.h b/include/asm-sh/irq.h
index c247b733a7d6..c61d902b8bff 100644
--- a/include/asm-sh/irq.h
+++ b/include/asm-sh/irq.h
@@ -31,37 +31,7 @@ extern unsigned short *irq_mask_register;
31 * PINT IRQs 31 * PINT IRQs
32 */ 32 */
33void init_IRQ_pint(void); 33void init_IRQ_pint(void);
34
35/*
36 * The shift value is now the number of bits to shift, not the number of
37 * bits/4. This is to make it easier to read the value directly from the
38 * datasheets. The IPR address, addr, will be set from ipr_idx via the
39 * map_ipridx_to_addr function.
40 */
41struct ipr_data {
42 unsigned int irq;
43 int ipr_idx; /* Index for the IPR registered */
44 int shift; /* Number of bits to shift the data */
45 int priority; /* The priority */
46 unsigned int addr; /* Address of Interrupt Priority Register */
47};
48
49/*
50 * Given an IPR IDX, map the value to an IPR register address.
51 */
52unsigned int map_ipridx_to_addr(int idx);
53
54/*
55 * Enable individual interrupt mode for external IPR IRQs.
56 */
57void ipr_irq_enable_irlm(void);
58
59/*
60 * Function for "on chip support modules".
61 */
62void make_ipr_irq(struct ipr_data *table, unsigned int nr_irqs);
63void make_imask_irq(unsigned int irq); 34void make_imask_irq(unsigned int irq);
64void init_IRQ_ipr(void);
65 35
66static inline int generic_irq_demux(int irq) 36static inline int generic_irq_demux(int irq)
67{ 37{
diff --git a/include/asm-sh/sh03/io.h b/include/asm-sh/sh03/io.h
index df3b187ef883..4ff1eb900301 100644
--- a/include/asm-sh/sh03/io.h
+++ b/include/asm-sh/sh03/io.h
@@ -14,22 +14,18 @@
14#define INTC_IPRD 0xffd00010UL 14#define INTC_IPRD 0xffd00010UL
15 15
16#define IRL0_IRQ 2 16#define IRL0_IRQ 2
17#define IRL0_IPR_ADDR INTC_IPRD
18#define IRL0_IPR_POS 3 17#define IRL0_IPR_POS 3
19#define IRL0_PRIORITY 13 18#define IRL0_PRIORITY 13
20 19
21#define IRL1_IRQ 5 20#define IRL1_IRQ 5
22#define IRL1_IPR_ADDR INTC_IPRD
23#define IRL1_IPR_POS 2 21#define IRL1_IPR_POS 2
24#define IRL1_PRIORITY 10 22#define IRL1_PRIORITY 10
25 23
26#define IRL2_IRQ 8 24#define IRL2_IRQ 8
27#define IRL2_IPR_ADDR INTC_IPRD
28#define IRL2_IPR_POS 1 25#define IRL2_IPR_POS 1
29#define IRL2_PRIORITY 7 26#define IRL2_PRIORITY 7
30 27
31#define IRL3_IRQ 11 28#define IRL3_IRQ 11
32#define IRL3_IPR_ADDR INTC_IPRD
33#define IRL3_IPR_POS 0 29#define IRL3_IPR_POS 0
34#define IRL3_PRIORITY 4 30#define IRL3_PRIORITY 4
35 31
diff --git a/include/asm-sh/snapgear.h b/include/asm-sh/snapgear.h
index 2d712e72c9e5..3554e3a74e99 100644
--- a/include/asm-sh/snapgear.h
+++ b/include/asm-sh/snapgear.h
@@ -20,22 +20,18 @@
20 */ 20 */
21 21
22#define IRL0_IRQ 2 22#define IRL0_IRQ 2
23#define IRL0_IPR_ADDR INTC_IPRD
24#define IRL0_IPR_POS 3 23#define IRL0_IPR_POS 3
25#define IRL0_PRIORITY 13 24#define IRL0_PRIORITY 13
26 25
27#define IRL1_IRQ 5 26#define IRL1_IRQ 5
28#define IRL1_IPR_ADDR INTC_IPRD
29#define IRL1_IPR_POS 2 27#define IRL1_IPR_POS 2
30#define IRL1_PRIORITY 10 28#define IRL1_PRIORITY 10
31 29
32#define IRL2_IRQ 8 30#define IRL2_IRQ 8
33#define IRL2_IPR_ADDR INTC_IPRD
34#define IRL2_IPR_POS 1 31#define IRL2_IPR_POS 1
35#define IRL2_PRIORITY 7 32#define IRL2_PRIORITY 7
36 33
37#define IRL3_IRQ 11 34#define IRL3_IRQ 11
38#define IRL3_IPR_ADDR INTC_IPRD
39#define IRL3_IPR_POS 0 35#define IRL3_IPR_POS 0
40#define IRL3_PRIORITY 4 36#define IRL3_PRIORITY 4
41#endif 37#endif