Commit 48180cab3adf4cb290c28b70e44e958b7fb8a5b0
Committed by
Paul Mundt
1 parent
51da64264b
Exists in
master
and in
7 other branches
sh: intc - convert voyagergx code
This patch converts the sh-specific voyagergx interrupt code to make use of intc. A lot of "interesting" old cruft gets replaced with intc tables and some simple demux code. - All interrupt sources in the sm501 data sheet are now in the header. - The number and order of IRQ values are disconnected from register bits. - Interrupt sources now start from IRQ 200. - set_irq_chained_handler() is now used to hook up the demux function. In the future it would probably make sense to move the interrupt demuxer into into the mfd driver, but this is probably a nice step in the right direction until that happens. Tested on a R2D-1 board using the serial port hooked up to the sm501. Signed-off-by: Magnus Damm <damm@igel.co.jp> Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Showing 4 changed files with 95 additions and 143 deletions Side-by-side Diff
arch/sh/boards/renesas/rts7751r2d/irq.c
... | ... | @@ -13,6 +13,7 @@ |
13 | 13 | #include <linux/irq.h> |
14 | 14 | #include <linux/interrupt.h> |
15 | 15 | #include <linux/io.h> |
16 | +#include <asm/voyagergx.h> | |
16 | 17 | #include <asm/rts7751r2d.h> |
17 | 18 | |
18 | 19 | #if defined(CONFIG_RTS7751R2D_REV11) |
... | ... | @@ -21,9 +22,6 @@ |
21 | 22 | static int mask_pos[] = {6, 11, 9, 8, 12, 10, 5, 4, 7, 14, 13, 0, 0, 0, 0}; |
22 | 23 | #endif |
23 | 24 | |
24 | -extern int voyagergx_irq_demux(int irq); | |
25 | -extern void setup_voyagergx_irq(void); | |
26 | - | |
27 | 25 | static void enable_rts7751r2d_irq(unsigned int irq) |
28 | 26 | { |
29 | 27 | /* Set priority in IPR back to original value */ |
... | ... | @@ -39,7 +37,7 @@ |
39 | 37 | |
40 | 38 | int rts7751r2d_irq_demux(int irq) |
41 | 39 | { |
42 | - return voyagergx_irq_demux(irq); | |
40 | + return irq; | |
43 | 41 | } |
44 | 42 | |
45 | 43 | static struct irq_chip rts7751r2d_irq_chip __read_mostly = { |
arch/sh/boards/renesas/rts7751r2d/setup.c
... | ... | @@ -82,7 +82,7 @@ |
82 | 82 | .membase = (void __iomem *)VOYAGER_UART_BASE, |
83 | 83 | .mapbase = VOYAGER_UART_BASE, |
84 | 84 | .iotype = UPIO_MEM, |
85 | - .irq = VOYAGER_UART0_IRQ, | |
85 | + .irq = IRQ_SM501_U0, | |
86 | 86 | .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, |
87 | 87 | .regshift = 2, |
88 | 88 | .uartclk = (9600 * 16), |
... | ... | @@ -125,7 +125,7 @@ |
125 | 125 | .flags = IORESOURCE_MEM, |
126 | 126 | }, |
127 | 127 | [2] = { |
128 | - .start = 32, | |
128 | + .start = IRQ_SM501_CV, | |
129 | 129 | .flags = IORESOURCE_IRQ, |
130 | 130 | }, |
131 | 131 | }; |
... | ... | @@ -187,7 +187,6 @@ |
187 | 187 | static struct sh_machine_vector mv_rts7751r2d __initmv = { |
188 | 188 | .mv_name = "RTS7751R2D", |
189 | 189 | .mv_setup = rts7751r2d_setup, |
190 | - .mv_nr_irqs = 72, | |
191 | 190 | |
192 | 191 | .mv_init_irq = init_rts7751r2d_IRQ, |
193 | 192 | .mv_irq_demux = rts7751r2d_irq_demux, |
arch/sh/cchips/voyagergx/irq.c
... | ... | @@ -23,150 +23,80 @@ |
23 | 23 | #include <asm/voyagergx.h> |
24 | 24 | #include <asm/rts7751r2d.h> |
25 | 25 | |
26 | -static void disable_voyagergx_irq(unsigned int irq) | |
27 | -{ | |
28 | - unsigned long val; | |
29 | - unsigned long mask = 1 << (irq - VOYAGER_IRQ_BASE); | |
26 | +enum { | |
27 | + UNUSED = 0, | |
30 | 28 | |
31 | - pr_debug("disable_voyagergx_irq(%d): mask=%lx\n", irq, mask); | |
32 | - val = readl((void __iomem *)VOYAGER_INT_MASK); | |
33 | - val &= ~mask; | |
34 | - writel(val, (void __iomem *)VOYAGER_INT_MASK); | |
35 | -} | |
29 | + /* voyager specific interrupt sources */ | |
30 | + UP, G54, G53, G52, G51, G50, G49, G48, | |
31 | + I2C, PW, DMA, PCI, I2S, AC, US, | |
32 | + U1, U0, CV, MC, S1, S0, | |
33 | + UH, TWOD, ZD, PV, CI, | |
34 | +}; | |
36 | 35 | |
37 | -static void enable_voyagergx_irq(unsigned int irq) | |
38 | -{ | |
39 | - unsigned long val; | |
40 | - unsigned long mask = 1 << (irq - VOYAGER_IRQ_BASE); | |
36 | +static struct intc_vect vectors[] = { | |
37 | + INTC_IRQ(UP, IRQ_SM501_UP), INTC_IRQ(G54, IRQ_SM501_G54), | |
38 | + INTC_IRQ(G53, IRQ_SM501_G53), INTC_IRQ(G52, IRQ_SM501_G52), | |
39 | + INTC_IRQ(G51, IRQ_SM501_G51), INTC_IRQ(G50, IRQ_SM501_G50), | |
40 | + INTC_IRQ(G49, IRQ_SM501_G49), INTC_IRQ(G48, IRQ_SM501_G48), | |
41 | + INTC_IRQ(I2C, IRQ_SM501_I2C), INTC_IRQ(PW, IRQ_SM501_PW), | |
42 | + INTC_IRQ(DMA, IRQ_SM501_DMA), INTC_IRQ(PCI, IRQ_SM501_PCI), | |
43 | + INTC_IRQ(I2S, IRQ_SM501_I2S), INTC_IRQ(AC, IRQ_SM501_AC), | |
44 | + INTC_IRQ(US, IRQ_SM501_US), INTC_IRQ(U1, IRQ_SM501_U1), | |
45 | + INTC_IRQ(U0, IRQ_SM501_U0), INTC_IRQ(CV, IRQ_SM501_CV), | |
46 | + INTC_IRQ(MC, IRQ_SM501_MC), INTC_IRQ(S1, IRQ_SM501_S1), | |
47 | + INTC_IRQ(S0, IRQ_SM501_S0), INTC_IRQ(UH, IRQ_SM501_UH), | |
48 | + INTC_IRQ(TWOD, IRQ_SM501_2D), INTC_IRQ(ZD, IRQ_SM501_ZD), | |
49 | + INTC_IRQ(PV, IRQ_SM501_PV), INTC_IRQ(CI, IRQ_SM501_CI), | |
50 | +}; | |
41 | 51 | |
42 | - pr_debug("disable_voyagergx_irq(%d): mask=%lx\n", irq, mask); | |
43 | - val = readl((void __iomem *)VOYAGER_INT_MASK); | |
44 | - val |= mask; | |
45 | - writel(val, (void __iomem *)VOYAGER_INT_MASK); | |
46 | -} | |
52 | +static struct intc_mask_reg mask_registers[] = { | |
53 | + { VOYAGER_INT_MASK, 1, 32, /* "Interrupt Mask", MMIO_base + 0x30 */ | |
54 | + { UP, G54, G53, G52, G51, G50, G49, G48, | |
55 | + I2C, PW, 0, DMA, PCI, I2S, AC, US, | |
56 | + 0, 0, U1, U0, CV, MC, S1, S0, | |
57 | + 0, UH, 0, 0, TWOD, ZD, PV, CI } }, | |
58 | +}; | |
47 | 59 | |
48 | -static void mask_and_ack_voyagergx(unsigned int irq) | |
49 | -{ | |
50 | - disable_voyagergx_irq(irq); | |
51 | -} | |
60 | +static DECLARE_INTC_DESC(intc_desc, "voyagergx", vectors, | |
61 | + NULL, NULL, mask_registers, NULL, NULL); | |
52 | 62 | |
53 | -static void end_voyagergx_irq(unsigned int irq) | |
54 | -{ | |
55 | - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) | |
56 | - enable_voyagergx_irq(irq); | |
57 | -} | |
58 | - | |
59 | -static unsigned int startup_voyagergx_irq(unsigned int irq) | |
60 | -{ | |
61 | - enable_voyagergx_irq(irq); | |
62 | - return 0; | |
63 | -} | |
64 | - | |
65 | -static void shutdown_voyagergx_irq(unsigned int irq) | |
66 | -{ | |
67 | - disable_voyagergx_irq(irq); | |
68 | -} | |
69 | - | |
70 | -static struct hw_interrupt_type voyagergx_irq_type = { | |
71 | - .typename = "VOYAGERGX-IRQ", | |
72 | - .startup = startup_voyagergx_irq, | |
73 | - .shutdown = shutdown_voyagergx_irq, | |
74 | - .enable = enable_voyagergx_irq, | |
75 | - .disable = disable_voyagergx_irq, | |
76 | - .ack = mask_and_ack_voyagergx, | |
77 | - .end = end_voyagergx_irq, | |
63 | +static unsigned int voyagergx_stat2irq[32] = { | |
64 | + IRQ_SM501_CI, IRQ_SM501_PV, IRQ_SM501_ZD, IRQ_SM501_2D, | |
65 | + 0, 0, IRQ_SM501_UH, 0, | |
66 | + IRQ_SM501_S0, IRQ_SM501_S1, IRQ_SM501_MC, IRQ_SM501_CV, | |
67 | + IRQ_SM501_U0, IRQ_SM501_U1, 0, 0, | |
68 | + IRQ_SM501_US, IRQ_SM501_AC, IRQ_SM501_I2S, IRQ_SM501_PCI, | |
69 | + IRQ_SM501_DMA, 0, IRQ_SM501_PW, IRQ_SM501_I2C, | |
70 | + IRQ_SM501_G48, IRQ_SM501_G49, IRQ_SM501_G50, IRQ_SM501_G51, | |
71 | + IRQ_SM501_G52, IRQ_SM501_G53, IRQ_SM501_G54, IRQ_SM501_UP | |
78 | 72 | }; |
79 | 73 | |
80 | -static irqreturn_t voyagergx_interrupt(int irq, void *dev_id) | |
74 | +static void voyagergx_irq_demux(unsigned int irq, struct irq_desc *desc) | |
81 | 75 | { |
82 | - printk(KERN_INFO | |
83 | - "VoyagerGX: spurious interrupt, status: 0x%x\n", | |
84 | - (unsigned int)readl((void __iomem *)INT_STATUS)); | |
85 | - return IRQ_HANDLED; | |
86 | -} | |
76 | + unsigned long intv = ctrl_inl(INT_STATUS); | |
77 | + struct irq_desc *ext_desc; | |
78 | + unsigned int ext_irq; | |
79 | + unsigned int k = 0; | |
87 | 80 | |
88 | -static struct { | |
89 | - int (*func)(int, void *); | |
90 | - void *dev; | |
91 | -} voyagergx_demux[VOYAGER_IRQ_NUM]; | |
92 | - | |
93 | -void voyagergx_register_irq_demux(int irq, | |
94 | - int (*demux)(int irq, void *dev), void *dev) | |
95 | -{ | |
96 | - voyagergx_demux[irq - VOYAGER_IRQ_BASE].func = demux; | |
97 | - voyagergx_demux[irq - VOYAGER_IRQ_BASE].dev = dev; | |
98 | -} | |
99 | - | |
100 | -void voyagergx_unregister_irq_demux(int irq) | |
101 | -{ | |
102 | - voyagergx_demux[irq - VOYAGER_IRQ_BASE].func = 0; | |
103 | -} | |
104 | - | |
105 | -int voyagergx_irq_demux(int irq) | |
106 | -{ | |
107 | - | |
108 | - if (irq == IRQ_VOYAGER ) { | |
109 | - unsigned long i = 0, bit __attribute__ ((unused)); | |
110 | - unsigned long val = readl((void __iomem *)INT_STATUS); | |
111 | - | |
112 | - if (val & (1 << 1)) | |
113 | - i = 1; | |
114 | - else if (val & (1 << 2)) | |
115 | - i = 2; | |
116 | - else if (val & (1 << 6)) | |
117 | - i = 6; | |
118 | - else if (val & (1 << 10)) | |
119 | - i = 10; | |
120 | - else if (val & (1 << 11)) | |
121 | - i = 11; | |
122 | - else if (val & (1 << 12)) | |
123 | - i = 12; | |
124 | - else if (val & (1 << 17)) | |
125 | - i = 17; | |
126 | - else | |
127 | - printk("Unexpected IRQ irq = %d status = 0x%08lx\n", irq, val); | |
128 | - pr_debug("voyagergx_irq_demux %ld \n", i); | |
129 | - if (i < VOYAGER_IRQ_NUM) { | |
130 | - irq = VOYAGER_IRQ_BASE + i; | |
131 | - if (voyagergx_demux[i].func != 0) | |
132 | - irq = voyagergx_demux[i].func(irq, | |
133 | - voyagergx_demux[i].dev); | |
81 | + while (intv) { | |
82 | + ext_irq = voyagergx_stat2irq[k]; | |
83 | + if (ext_irq && (intv & 1)) { | |
84 | + ext_desc = irq_desc + ext_irq; | |
85 | + handle_level_irq(ext_irq, ext_desc); | |
134 | 86 | } |
87 | + intv >>= 1; | |
88 | + k++; | |
135 | 89 | } |
136 | - return irq; | |
137 | 90 | } |
138 | 91 | |
139 | -static struct irqaction irq0 = { | |
140 | - .name = "voyagergx", | |
141 | - .handler = voyagergx_interrupt, | |
142 | - .flags = IRQF_DISABLED, | |
143 | - .mask = CPU_MASK_NONE, | |
144 | -}; | |
145 | - | |
146 | 92 | void __init setup_voyagergx_irq(void) |
147 | 93 | { |
148 | - int i, flag; | |
149 | - | |
150 | - printk(KERN_INFO "VoyagerGX configured at 0x%x on irq %d(mapped into %d to %d)\n", | |
151 | - VOYAGER_BASE, | |
94 | + printk(KERN_INFO "VoyagerGX on irq %d (mapped into %d to %d)\n", | |
152 | 95 | IRQ_VOYAGER, |
153 | 96 | VOYAGER_IRQ_BASE, |
154 | 97 | VOYAGER_IRQ_BASE + VOYAGER_IRQ_NUM - 1); |
155 | 98 | |
156 | - for (i=0; i<VOYAGER_IRQ_NUM; i++) { | |
157 | - flag = 0; | |
158 | - switch (VOYAGER_IRQ_BASE + i) { | |
159 | - case VOYAGER_USBH_IRQ: | |
160 | - case VOYAGER_8051_IRQ: | |
161 | - case VOYAGER_UART0_IRQ: | |
162 | - case VOYAGER_UART1_IRQ: | |
163 | - case VOYAGER_AC97_IRQ: | |
164 | - flag = 1; | |
165 | - } | |
166 | - if (flag == 1) | |
167 | - irq_desc[VOYAGER_IRQ_BASE + i].chip = &voyagergx_irq_type; | |
168 | - } | |
169 | - | |
170 | - setup_irq(IRQ_VOYAGER, &irq0); | |
99 | + register_intc_controller(&intc_desc); | |
100 | + set_irq_chained_handler(IRQ_VOYAGER, voyagergx_irq_demux); | |
171 | 101 | } |
include/asm-sh/voyagergx.h
... | ... | @@ -27,14 +27,36 @@ |
27 | 27 | #define VOYAGER_UART_BASE (0x30000 + VOYAGER_BASE) |
28 | 28 | #define VOYAGER_AC97_BASE (0xa0000 + VOYAGER_BASE) |
29 | 29 | |
30 | -#define VOYAGER_IRQ_NUM 32 | |
31 | -#define VOYAGER_IRQ_BASE 50 | |
32 | -#define VOYAGER_USBH_IRQ VOYAGER_IRQ_BASE + 6 | |
33 | -#define VOYAGER_8051_IRQ VOYAGER_IRQ_BASE + 10 | |
34 | -#define VOYAGER_UART0_IRQ VOYAGER_IRQ_BASE + 12 | |
35 | -#define VOYAGER_UART1_IRQ VOYAGER_IRQ_BASE + 13 | |
36 | -#define VOYAGER_AC97_IRQ VOYAGER_IRQ_BASE + 17 | |
30 | +#define VOYAGER_IRQ_NUM 26 | |
31 | +#define VOYAGER_IRQ_BASE 200 | |
37 | 32 | |
33 | +#define IRQ_SM501_UP (VOYAGER_IRQ_BASE + 0) | |
34 | +#define IRQ_SM501_G54 (VOYAGER_IRQ_BASE + 1) | |
35 | +#define IRQ_SM501_G53 (VOYAGER_IRQ_BASE + 2) | |
36 | +#define IRQ_SM501_G52 (VOYAGER_IRQ_BASE + 3) | |
37 | +#define IRQ_SM501_G51 (VOYAGER_IRQ_BASE + 4) | |
38 | +#define IRQ_SM501_G50 (VOYAGER_IRQ_BASE + 5) | |
39 | +#define IRQ_SM501_G49 (VOYAGER_IRQ_BASE + 6) | |
40 | +#define IRQ_SM501_G48 (VOYAGER_IRQ_BASE + 7) | |
41 | +#define IRQ_SM501_I2C (VOYAGER_IRQ_BASE + 8) | |
42 | +#define IRQ_SM501_PW (VOYAGER_IRQ_BASE + 9) | |
43 | +#define IRQ_SM501_DMA (VOYAGER_IRQ_BASE + 10) | |
44 | +#define IRQ_SM501_PCI (VOYAGER_IRQ_BASE + 11) | |
45 | +#define IRQ_SM501_I2S (VOYAGER_IRQ_BASE + 12) | |
46 | +#define IRQ_SM501_AC (VOYAGER_IRQ_BASE + 13) | |
47 | +#define IRQ_SM501_US (VOYAGER_IRQ_BASE + 14) | |
48 | +#define IRQ_SM501_U1 (VOYAGER_IRQ_BASE + 15) | |
49 | +#define IRQ_SM501_U0 (VOYAGER_IRQ_BASE + 16) | |
50 | +#define IRQ_SM501_CV (VOYAGER_IRQ_BASE + 17) | |
51 | +#define IRQ_SM501_MC (VOYAGER_IRQ_BASE + 18) | |
52 | +#define IRQ_SM501_S1 (VOYAGER_IRQ_BASE + 19) | |
53 | +#define IRQ_SM501_S0 (VOYAGER_IRQ_BASE + 20) | |
54 | +#define IRQ_SM501_UH (VOYAGER_IRQ_BASE + 21) | |
55 | +#define IRQ_SM501_2D (VOYAGER_IRQ_BASE + 22) | |
56 | +#define IRQ_SM501_ZD (VOYAGER_IRQ_BASE + 23) | |
57 | +#define IRQ_SM501_PV (VOYAGER_IRQ_BASE + 24) | |
58 | +#define IRQ_SM501_CI (VOYAGER_IRQ_BASE + 25) | |
59 | + | |
38 | 60 | /* ----- MISC controle register ------------------------------ */ |
39 | 61 | #define MISC_CTRL (0x000004 + VOYAGER_BASE) |
40 | 62 | #define MISC_CTRL_USBCLK_48 (3 << 28) |
... | ... | @@ -312,6 +334,9 @@ |
312 | 334 | /* arch/sh/cchips/voyagergx/consistent.c */ |
313 | 335 | void *voyagergx_consistent_alloc(struct device *, size_t, dma_addr_t *, gfp_t); |
314 | 336 | int voyagergx_consistent_free(struct device *, size_t, void *, dma_addr_t); |
337 | + | |
338 | +/* arch/sh/cchips/voyagergx/irq.c */ | |
339 | +void setup_voyagergx_irq(void); | |
315 | 340 | |
316 | 341 | #endif /* _VOYAGER_GX_REG_H */ |