Commit 48180cab3adf4cb290c28b70e44e958b7fb8a5b0

Authored by Magnus Damm
Committed by Paul Mundt
1 parent 51da64264b

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 */