diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2006-07-03 05:32:51 -0400 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2006-07-03 05:55:12 -0400 |
commit | b9e5b4e6a991a5a6d521f2e20a65835404b4169f (patch) | |
tree | a0ac972faae4bf9133f576d842667bb134190341 /arch/powerpc/platforms/cell/spider-pic.c | |
parent | 5a43a066b11ac2fe84cf67307f20b83bea390f83 (diff) |
[POWERPC] Use the genirq framework
This adapts the generic powerpc interrupt handling code, and all of
the platforms except for the embedded 6xx machines, to use the new
genirq framework.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/platforms/cell/spider-pic.c')
-rw-r--r-- | arch/powerpc/platforms/cell/spider-pic.c | 173 |
1 files changed, 76 insertions, 97 deletions
diff --git a/arch/powerpc/platforms/cell/spider-pic.c b/arch/powerpc/platforms/cell/spider-pic.c index 7c3a0b6d34f..98425acb6cd 100644 --- a/arch/powerpc/platforms/cell/spider-pic.c +++ b/arch/powerpc/platforms/cell/spider-pic.c | |||
@@ -82,17 +82,20 @@ static void __iomem *spider_get_irq_config(int irq) | |||
82 | return pic + TIR_CFGA + 8 * spider_get_nr(irq); | 82 | return pic + TIR_CFGA + 8 * spider_get_nr(irq); |
83 | } | 83 | } |
84 | 84 | ||
85 | static void spider_enable_irq(unsigned int irq) | 85 | static void spider_unmask_irq(unsigned int irq) |
86 | { | 86 | { |
87 | int nodeid = (irq / IIC_NODE_STRIDE) * 0x10; | 87 | int nodeid = (irq / IIC_NODE_STRIDE) * 0x10; |
88 | void __iomem *cfg = spider_get_irq_config(irq); | 88 | void __iomem *cfg = spider_get_irq_config(irq); |
89 | irq = spider_get_nr(irq); | 89 | irq = spider_get_nr(irq); |
90 | 90 | ||
91 | /* FIXME: Most of that is configuration and has nothing to do with enabling/disable, | ||
92 | * besides, it's also partially bogus. | ||
93 | */ | ||
91 | out_be32(cfg, (in_be32(cfg) & ~0xf0)| 0x3107000eu | nodeid); | 94 | out_be32(cfg, (in_be32(cfg) & ~0xf0)| 0x3107000eu | nodeid); |
92 | out_be32(cfg + 4, in_be32(cfg + 4) | 0x00020000u | irq); | 95 | out_be32(cfg + 4, in_be32(cfg + 4) | 0x00020000u | irq); |
93 | } | 96 | } |
94 | 97 | ||
95 | static void spider_disable_irq(unsigned int irq) | 98 | static void spider_mask_irq(unsigned int irq) |
96 | { | 99 | { |
97 | void __iomem *cfg = spider_get_irq_config(irq); | 100 | void __iomem *cfg = spider_get_irq_config(irq); |
98 | irq = spider_get_nr(irq); | 101 | irq = spider_get_nr(irq); |
@@ -100,39 +103,21 @@ static void spider_disable_irq(unsigned int irq) | |||
100 | out_be32(cfg, in_be32(cfg) & ~0x30000000u); | 103 | out_be32(cfg, in_be32(cfg) & ~0x30000000u); |
101 | } | 104 | } |
102 | 105 | ||
103 | static unsigned int spider_startup_irq(unsigned int irq) | ||
104 | { | ||
105 | spider_enable_irq(irq); | ||
106 | return 0; | ||
107 | } | ||
108 | |||
109 | static void spider_shutdown_irq(unsigned int irq) | ||
110 | { | ||
111 | spider_disable_irq(irq); | ||
112 | } | ||
113 | |||
114 | static void spider_end_irq(unsigned int irq) | ||
115 | { | ||
116 | spider_enable_irq(irq); | ||
117 | } | ||
118 | |||
119 | static void spider_ack_irq(unsigned int irq) | 106 | static void spider_ack_irq(unsigned int irq) |
120 | { | 107 | { |
121 | spider_disable_irq(irq); | 108 | /* Should reset edge detection logic but we don't configure any edge interrupt |
122 | iic_local_enable(); | 109 | * at the moment. |
110 | */ | ||
123 | } | 111 | } |
124 | 112 | ||
125 | static struct hw_interrupt_type spider_pic = { | 113 | static struct irq_chip spider_pic = { |
126 | .typename = " SPIDER ", | 114 | .typename = " SPIDER ", |
127 | .startup = spider_startup_irq, | 115 | .unmask = spider_unmask_irq, |
128 | .shutdown = spider_shutdown_irq, | 116 | .mask = spider_mask_irq, |
129 | .enable = spider_enable_irq, | ||
130 | .disable = spider_disable_irq, | ||
131 | .ack = spider_ack_irq, | 117 | .ack = spider_ack_irq, |
132 | .end = spider_end_irq, | ||
133 | }; | 118 | }; |
134 | 119 | ||
135 | int spider_get_irq(int node) | 120 | static int spider_get_irq(int node) |
136 | { | 121 | { |
137 | unsigned long cs; | 122 | unsigned long cs; |
138 | void __iomem *regs = spider_pics[node]; | 123 | void __iomem *regs = spider_pics[node]; |
@@ -145,95 +130,89 @@ int spider_get_irq(int node) | |||
145 | return cs; | 130 | return cs; |
146 | } | 131 | } |
147 | 132 | ||
133 | static void spider_irq_cascade(unsigned int irq, struct irq_desc *desc, | ||
134 | struct pt_regs *regs) | ||
135 | { | ||
136 | int node = (int)(long)desc->handler_data; | ||
137 | int cascade_irq; | ||
138 | |||
139 | cascade_irq = spider_get_irq(node); | ||
140 | generic_handle_irq(cascade_irq, regs); | ||
141 | desc->chip->eoi(irq); | ||
142 | } | ||
143 | |||
148 | /* hardcoded part to be compatible with older firmware */ | 144 | /* hardcoded part to be compatible with older firmware */ |
149 | 145 | ||
150 | void spider_init_IRQ_hardcoded(void) | 146 | static void __init spider_init_one(int node, unsigned long addr) |
151 | { | 147 | { |
152 | int node; | 148 | int n, irq; |
153 | long spiderpic; | 149 | |
154 | long pics[] = { 0x24000008000, 0x34000008000 }; | 150 | spider_pics[node] = ioremap(addr, 0x800); |
155 | int n; | 151 | if (spider_pics[node] == NULL) |
156 | 152 | panic("spider_pic: can't map registers !"); | |
157 | pr_debug("%s(%d): Using hardcoded defaults\n", __FUNCTION__, __LINE__); | 153 | |
158 | 154 | printk(KERN_INFO "spider_pic: mapped for node %d, addr: 0x%lx mapped to %p\n", | |
159 | for (node = 0; node < num_present_cpus()/2; node++) { | 155 | node, addr, spider_pics[node]); |
160 | spiderpic = pics[node]; | 156 | |
161 | printk(KERN_DEBUG "SPIDER addr: %lx\n", spiderpic); | 157 | for (n = 0; n < IIC_NUM_EXT; n++) { |
162 | spider_pics[node] = ioremap(spiderpic, 0x800); | 158 | if (n == IIC_EXT_CASCADE) |
163 | for (n = 0; n < IIC_NUM_EXT; n++) { | 159 | continue; |
164 | int irq = n + IIC_EXT_OFFSET + node * IIC_NODE_STRIDE; | 160 | irq = n + IIC_EXT_OFFSET + node * IIC_NODE_STRIDE; |
165 | get_irq_desc(irq)->chip = &spider_pic; | 161 | set_irq_chip_and_handler(irq, &spider_pic, handle_level_irq); |
166 | } | 162 | get_irq_desc(irq)->status |= IRQ_LEVEL; |
167 | |||
168 | /* do not mask any interrupts because of level */ | ||
169 | out_be32(spider_pics[node] + TIR_MSK, 0x0); | ||
170 | |||
171 | /* disable edge detection clear */ | ||
172 | /* out_be32(spider_pics[node] + TIR_EDC, 0x0); */ | ||
173 | |||
174 | /* enable interrupt packets to be output */ | ||
175 | out_be32(spider_pics[node] + TIR_PIEN, | ||
176 | in_be32(spider_pics[node] + TIR_PIEN) | 0x1); | ||
177 | |||
178 | /* Enable the interrupt detection enable bit. Do this last! */ | ||
179 | out_be32(spider_pics[node] + TIR_DEN, | ||
180 | in_be32(spider_pics[node] + TIR_DEN) | 0x1); | ||
181 | } | 163 | } |
164 | |||
165 | /* do not mask any interrupts because of level */ | ||
166 | out_be32(spider_pics[node] + TIR_MSK, 0x0); | ||
167 | |||
168 | /* disable edge detection clear */ | ||
169 | /* out_be32(spider_pics[node] + TIR_EDC, 0x0); */ | ||
170 | |||
171 | /* enable interrupt packets to be output */ | ||
172 | out_be32(spider_pics[node] + TIR_PIEN, | ||
173 | in_be32(spider_pics[node] + TIR_PIEN) | 0x1); | ||
174 | |||
175 | /* Hook up cascade */ | ||
176 | irq = IIC_EXT_CASCADE + node * IIC_NODE_STRIDE; | ||
177 | set_irq_data(irq, (void *)(long)node); | ||
178 | set_irq_chained_handler(irq, spider_irq_cascade); | ||
179 | |||
180 | /* Enable the interrupt detection enable bit. Do this last! */ | ||
181 | out_be32(spider_pics[node] + TIR_DEN, | ||
182 | in_be32(spider_pics[node] + TIR_DEN) | 0x1); | ||
182 | } | 183 | } |
183 | 184 | ||
184 | void spider_init_IRQ(void) | 185 | void __init spider_init_IRQ(void) |
185 | { | 186 | { |
186 | long spider_reg; | 187 | unsigned long *spider_reg; |
187 | struct device_node *dn; | 188 | struct device_node *dn; |
188 | char *compatible; | 189 | char *compatible; |
189 | int n, node = 0; | 190 | int node = 0; |
190 | 191 | ||
192 | /* XXX node numbers are totally bogus. We _hope_ we get the device nodes in the right | ||
193 | * order here but that's definitely not guaranteed, we need to get the node from the | ||
194 | * device tree instead. There is currently no proper property for it (but our whole | ||
195 | * device-tree is bogus anyway) so all we can do is pray or maybe test the address | ||
196 | * and deduce the node-id | ||
197 | */ | ||
191 | for (dn = NULL; (dn = of_find_node_by_name(dn, "interrupt-controller"));) { | 198 | for (dn = NULL; (dn = of_find_node_by_name(dn, "interrupt-controller"));) { |
192 | compatible = (char *)get_property(dn, "compatible", NULL); | 199 | compatible = (char *)get_property(dn, "compatible", NULL); |
193 | 200 | ||
194 | if (!compatible) | 201 | if (!compatible) |
195 | continue; | 202 | continue; |
196 | 203 | ||
197 | if (strstr(compatible, "CBEA,platform-spider-pic")) | 204 | if (strstr(compatible, "CBEA,platform-spider-pic")) |
198 | spider_reg = *(long *)get_property(dn,"reg", NULL); | 205 | spider_reg = (unsigned long *)get_property(dn, "reg", NULL); |
199 | else if (strstr(compatible, "sti,platform-spider-pic")) { | 206 | else if (strstr(compatible, "sti,platform-spider-pic") && (node < 2)) { |
200 | spider_init_IRQ_hardcoded(); | 207 | static long hard_coded_pics[] = { 0x24000008000, 0x34000008000 }; |
201 | return; | 208 | spider_reg = &hard_coded_pics[node]; |
202 | } else | 209 | } else |
203 | continue; | 210 | continue; |
204 | 211 | ||
205 | if (!spider_reg) | 212 | if (spider_reg == NULL) |
206 | printk("interrupt controller does not have reg property !\n"); | 213 | printk(KERN_ERR "spider_pic: No address for node %d\n", node); |
207 | |||
208 | n = prom_n_addr_cells(dn); | ||
209 | |||
210 | if ( n != 2) | ||
211 | printk("reg property with invalid number of elements \n"); | ||
212 | |||
213 | spider_pics[node] = ioremap(spider_reg, 0x800); | ||
214 | |||
215 | printk("SPIDER addr: %lx with %i addr_cells mapped to %p\n", | ||
216 | spider_reg, n, spider_pics[node]); | ||
217 | |||
218 | for (n = 0; n < IIC_NUM_EXT; n++) { | ||
219 | int irq = n + IIC_EXT_OFFSET + node * IIC_NODE_STRIDE; | ||
220 | get_irq_desc(irq)->chip = &spider_pic; | ||
221 | } | ||
222 | |||
223 | /* do not mask any interrupts because of level */ | ||
224 | out_be32(spider_pics[node] + TIR_MSK, 0x0); | ||
225 | |||
226 | /* disable edge detection clear */ | ||
227 | /* out_be32(spider_pics[node] + TIR_EDC, 0x0); */ | ||
228 | |||
229 | /* enable interrupt packets to be output */ | ||
230 | out_be32(spider_pics[node] + TIR_PIEN, | ||
231 | in_be32(spider_pics[node] + TIR_PIEN) | 0x1); | ||
232 | |||
233 | /* Enable the interrupt detection enable bit. Do this last! */ | ||
234 | out_be32(spider_pics[node] + TIR_DEN, | ||
235 | in_be32(spider_pics[node] + TIR_DEN) | 0x1); | ||
236 | 214 | ||
215 | spider_init_one(node, *spider_reg); | ||
237 | node++; | 216 | node++; |
238 | } | 217 | } |
239 | } | 218 | } |