diff options
author | Jens Osterkamp <Jens.Osterkamp@de.ibm.com> | 2006-03-22 18:00:06 -0500 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2006-03-26 22:48:18 -0500 |
commit | d0e57c68373f8ded8c50245fd082e606f9f63221 (patch) | |
tree | e74b9d732e519c150e12b16026a782e4987b5c7c /arch/powerpc/platforms/cell/spider-pic.c | |
parent | 1a19f85584414ae0a9f94406ffd628096127583e (diff) |
[PATCH] powerpc: cell interrupt controller updates
The current interrupt controller setup on Cell is done
in a rather ad-hoc way with device tree properties
that are not standardized at all.
In an attempt to do something that follows the OF standard
(or at least the IBM extensions to it) more closely,
we have now come up with this patch. It still provides
a fallback to the old behaviour when we find older firmware,
that hack can not be removed until the existing customer
installations have upgraded.
Cc: hpenner@de.ibm.com
Cc: stk@de.ibm.com
Cc: Segher Boessenkool <segher@kernel.crashing.org>
Cc: Milton Miller <miltonm@bga.com>
Cc: benh@kernel.crashing.org
Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>
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 | 106 |
1 files changed, 77 insertions, 29 deletions
diff --git a/arch/powerpc/platforms/cell/spider-pic.c b/arch/powerpc/platforms/cell/spider-pic.c index e74132188bdf..0e9bb0b72c50 100644 --- a/arch/powerpc/platforms/cell/spider-pic.c +++ b/arch/powerpc/platforms/cell/spider-pic.c | |||
@@ -84,10 +84,11 @@ static void __iomem *spider_get_irq_config(int irq) | |||
84 | 84 | ||
85 | static void spider_enable_irq(unsigned int irq) | 85 | static void spider_enable_irq(unsigned int irq) |
86 | { | 86 | { |
87 | int nodeid = (irq / IIC_NODE_STRIDE) * 0x10; | ||
87 | void __iomem *cfg = spider_get_irq_config(irq); | 88 | void __iomem *cfg = spider_get_irq_config(irq); |
88 | irq = spider_get_nr(irq); | 89 | irq = spider_get_nr(irq); |
89 | 90 | ||
90 | out_be32(cfg, in_be32(cfg) | 0x3107000eu); | 91 | out_be32(cfg, in_be32(cfg) | 0x3107000eu | nodeid); |
91 | out_be32(cfg + 4, in_be32(cfg + 4) | 0x00020000u | irq); | 92 | out_be32(cfg + 4, in_be32(cfg + 4) | 0x00020000u | irq); |
92 | } | 93 | } |
93 | 94 | ||
@@ -131,61 +132,108 @@ static struct hw_interrupt_type spider_pic = { | |||
131 | .end = spider_end_irq, | 132 | .end = spider_end_irq, |
132 | }; | 133 | }; |
133 | 134 | ||
134 | 135 | int spider_get_irq(int node) | |
135 | int spider_get_irq(unsigned long int_pending) | ||
136 | { | 136 | { |
137 | void __iomem *regs = spider_get_pic(int_pending); | ||
138 | unsigned long cs; | 137 | unsigned long cs; |
139 | int irq; | 138 | void __iomem *regs = spider_pics[node]; |
140 | |||
141 | cs = in_be32(regs + TIR_CS); | ||
142 | 139 | ||
143 | irq = cs >> 24; | 140 | cs = in_be32(regs + TIR_CS) >> 24; |
144 | if (irq != 63) | ||
145 | return irq; | ||
146 | 141 | ||
147 | return -1; | 142 | if (cs == 63) |
143 | return -1; | ||
144 | else | ||
145 | return cs; | ||
148 | } | 146 | } |
149 | 147 | ||
150 | void spider_init_IRQ(void) | 148 | /* hardcoded part to be compatible with older firmware */ |
149 | |||
150 | void spider_init_IRQ_hardcoded(void) | ||
151 | { | 151 | { |
152 | int node; | 152 | int node; |
153 | struct device_node *dn; | ||
154 | unsigned int *property; | ||
155 | long spiderpic; | 153 | long spiderpic; |
154 | long pics[] = { 0x24000008000, 0x34000008000 }; | ||
156 | int n; | 155 | int n; |
157 | 156 | ||
158 | /* FIXME: detect multiple PICs as soon as the device tree has them */ | 157 | pr_debug("%s(%d): Using hardcoded defaults\n", __FUNCTION__, __LINE__); |
159 | for (node = 0; node < 1; node++) { | ||
160 | dn = of_find_node_by_path("/"); | ||
161 | n = prom_n_addr_cells(dn); | ||
162 | property = (unsigned int *) get_property(dn, | ||
163 | "platform-spider-pic", NULL); | ||
164 | 158 | ||
165 | if (!property) | 159 | for (node = 0; node < num_present_cpus()/2; node++) { |
166 | continue; | 160 | spiderpic = pics[node]; |
167 | for (spiderpic = 0; n > 0; --n) | ||
168 | spiderpic = (spiderpic << 32) + *property++; | ||
169 | printk(KERN_DEBUG "SPIDER addr: %lx\n", spiderpic); | 161 | printk(KERN_DEBUG "SPIDER addr: %lx\n", spiderpic); |
170 | spider_pics[node] = __ioremap(spiderpic, 0x800, _PAGE_NO_CACHE); | 162 | spider_pics[node] = __ioremap(spiderpic, 0x800, _PAGE_NO_CACHE); |
171 | for (n = 0; n < IIC_NUM_EXT; n++) { | 163 | for (n = 0; n < IIC_NUM_EXT; n++) { |
172 | int irq = n + IIC_EXT_OFFSET + node * IIC_NODE_STRIDE; | 164 | int irq = n + IIC_EXT_OFFSET + node * IIC_NODE_STRIDE; |
173 | get_irq_desc(irq)->handler = &spider_pic; | 165 | get_irq_desc(irq)->handler = &spider_pic; |
166 | } | ||
174 | 167 | ||
175 | /* do not mask any interrupts because of level */ | 168 | /* do not mask any interrupts because of level */ |
176 | out_be32(spider_pics[node] + TIR_MSK, 0x0); | 169 | out_be32(spider_pics[node] + TIR_MSK, 0x0); |
177 | 170 | ||
178 | /* disable edge detection clear */ | 171 | /* disable edge detection clear */ |
179 | /* out_be32(spider_pics[node] + TIR_EDC, 0x0); */ | 172 | /* out_be32(spider_pics[node] + TIR_EDC, 0x0); */ |
180 | 173 | ||
181 | /* enable interrupt packets to be output */ | 174 | /* enable interrupt packets to be output */ |
182 | out_be32(spider_pics[node] + TIR_PIEN, | 175 | out_be32(spider_pics[node] + TIR_PIEN, |
183 | in_be32(spider_pics[node] + TIR_PIEN) | 0x1); | 176 | in_be32(spider_pics[node] + TIR_PIEN) | 0x1); |
184 | 177 | ||
185 | /* Enable the interrupt detection enable bit. Do this last! */ | 178 | /* Enable the interrupt detection enable bit. Do this last! */ |
186 | out_be32(spider_pics[node] + TIR_DEN, | 179 | out_be32(spider_pics[node] + TIR_DEN, |
187 | in_be32(spider_pics[node] +TIR_DEN) | 0x1); | 180 | in_be32(spider_pics[node] + TIR_DEN) | 0x1); |
181 | } | ||
182 | } | ||
183 | |||
184 | void spider_init_IRQ(void) | ||
185 | { | ||
186 | long spider_reg; | ||
187 | struct device_node *dn; | ||
188 | char *compatible; | ||
189 | int n, node = 0; | ||
190 | |||
191 | for (dn = NULL; (dn = of_find_node_by_name(dn, "interrupt-controller"));) { | ||
192 | compatible = (char *)get_property(dn, "compatible", NULL); | ||
188 | 193 | ||
194 | if (!compatible) | ||
195 | continue; | ||
196 | |||
197 | if (strstr(compatible, "CBEA,platform-spider-pic")) | ||
198 | spider_reg = *(long *)get_property(dn,"reg", NULL); | ||
199 | else if (strstr(compatible, "sti,platform-spider-pic")) { | ||
200 | spider_init_IRQ_hardcoded(); | ||
201 | return; | ||
202 | } else | ||
203 | continue; | ||
204 | |||
205 | if (!spider_reg) | ||
206 | printk("interrupt controller does not have reg property !\n"); | ||
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, _PAGE_NO_CACHE); | ||
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)->handler = &spider_pic; | ||
189 | } | 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 | |||
237 | node++; | ||
190 | } | 238 | } |
191 | } | 239 | } |