diff options
Diffstat (limited to 'arch/powerpc/kernel/prom.c')
-rw-r--r-- | arch/powerpc/kernel/prom.c | 451 |
1 files changed, 2 insertions, 449 deletions
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index ef3619c28702..a1787ffb6319 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/module.h> | 30 | #include <linux/module.h> |
31 | #include <linux/kexec.h> | 31 | #include <linux/kexec.h> |
32 | #include <linux/debugfs.h> | 32 | #include <linux/debugfs.h> |
33 | #include <linux/irq.h> | ||
33 | 34 | ||
34 | #include <asm/prom.h> | 35 | #include <asm/prom.h> |
35 | #include <asm/rtas.h> | 36 | #include <asm/rtas.h> |
@@ -86,424 +87,6 @@ static DEFINE_RWLOCK(devtree_lock); | |||
86 | /* export that to outside world */ | 87 | /* export that to outside world */ |
87 | struct device_node *of_chosen; | 88 | struct device_node *of_chosen; |
88 | 89 | ||
89 | struct device_node *dflt_interrupt_controller; | ||
90 | int num_interrupt_controllers; | ||
91 | |||
92 | /* | ||
93 | * Wrapper for allocating memory for various data that needs to be | ||
94 | * attached to device nodes as they are processed at boot or when | ||
95 | * added to the device tree later (e.g. DLPAR). At boot there is | ||
96 | * already a region reserved so we just increment *mem_start by size; | ||
97 | * otherwise we call kmalloc. | ||
98 | */ | ||
99 | static void * prom_alloc(unsigned long size, unsigned long *mem_start) | ||
100 | { | ||
101 | unsigned long tmp; | ||
102 | |||
103 | if (!mem_start) | ||
104 | return kmalloc(size, GFP_KERNEL); | ||
105 | |||
106 | tmp = *mem_start; | ||
107 | *mem_start += size; | ||
108 | return (void *)tmp; | ||
109 | } | ||
110 | |||
111 | /* | ||
112 | * Find the device_node with a given phandle. | ||
113 | */ | ||
114 | static struct device_node * find_phandle(phandle ph) | ||
115 | { | ||
116 | struct device_node *np; | ||
117 | |||
118 | for (np = allnodes; np != 0; np = np->allnext) | ||
119 | if (np->linux_phandle == ph) | ||
120 | return np; | ||
121 | return NULL; | ||
122 | } | ||
123 | |||
124 | /* | ||
125 | * Find the interrupt parent of a node. | ||
126 | */ | ||
127 | static struct device_node * __devinit intr_parent(struct device_node *p) | ||
128 | { | ||
129 | phandle *parp; | ||
130 | |||
131 | parp = (phandle *) get_property(p, "interrupt-parent", NULL); | ||
132 | if (parp == NULL) | ||
133 | return p->parent; | ||
134 | p = find_phandle(*parp); | ||
135 | if (p != NULL) | ||
136 | return p; | ||
137 | /* | ||
138 | * On a powermac booted with BootX, we don't get to know the | ||
139 | * phandles for any nodes, so find_phandle will return NULL. | ||
140 | * Fortunately these machines only have one interrupt controller | ||
141 | * so there isn't in fact any ambiguity. -- paulus | ||
142 | */ | ||
143 | if (num_interrupt_controllers == 1) | ||
144 | p = dflt_interrupt_controller; | ||
145 | return p; | ||
146 | } | ||
147 | |||
148 | /* | ||
149 | * Find out the size of each entry of the interrupts property | ||
150 | * for a node. | ||
151 | */ | ||
152 | int __devinit prom_n_intr_cells(struct device_node *np) | ||
153 | { | ||
154 | struct device_node *p; | ||
155 | unsigned int *icp; | ||
156 | |||
157 | for (p = np; (p = intr_parent(p)) != NULL; ) { | ||
158 | icp = (unsigned int *) | ||
159 | get_property(p, "#interrupt-cells", NULL); | ||
160 | if (icp != NULL) | ||
161 | return *icp; | ||
162 | if (get_property(p, "interrupt-controller", NULL) != NULL | ||
163 | || get_property(p, "interrupt-map", NULL) != NULL) { | ||
164 | printk("oops, node %s doesn't have #interrupt-cells\n", | ||
165 | p->full_name); | ||
166 | return 1; | ||
167 | } | ||
168 | } | ||
169 | #ifdef DEBUG_IRQ | ||
170 | printk("prom_n_intr_cells failed for %s\n", np->full_name); | ||
171 | #endif | ||
172 | return 1; | ||
173 | } | ||
174 | |||
175 | /* | ||
176 | * Map an interrupt from a device up to the platform interrupt | ||
177 | * descriptor. | ||
178 | */ | ||
179 | static int __devinit map_interrupt(unsigned int **irq, struct device_node **ictrler, | ||
180 | struct device_node *np, unsigned int *ints, | ||
181 | int nintrc) | ||
182 | { | ||
183 | struct device_node *p, *ipar; | ||
184 | unsigned int *imap, *imask, *ip; | ||
185 | int i, imaplen, match; | ||
186 | int newintrc = 0, newaddrc = 0; | ||
187 | unsigned int *reg; | ||
188 | int naddrc; | ||
189 | |||
190 | reg = (unsigned int *) get_property(np, "reg", NULL); | ||
191 | naddrc = prom_n_addr_cells(np); | ||
192 | p = intr_parent(np); | ||
193 | while (p != NULL) { | ||
194 | if (get_property(p, "interrupt-controller", NULL) != NULL) | ||
195 | /* this node is an interrupt controller, stop here */ | ||
196 | break; | ||
197 | imap = (unsigned int *) | ||
198 | get_property(p, "interrupt-map", &imaplen); | ||
199 | if (imap == NULL) { | ||
200 | p = intr_parent(p); | ||
201 | continue; | ||
202 | } | ||
203 | imask = (unsigned int *) | ||
204 | get_property(p, "interrupt-map-mask", NULL); | ||
205 | if (imask == NULL) { | ||
206 | printk("oops, %s has interrupt-map but no mask\n", | ||
207 | p->full_name); | ||
208 | return 0; | ||
209 | } | ||
210 | imaplen /= sizeof(unsigned int); | ||
211 | match = 0; | ||
212 | ipar = NULL; | ||
213 | while (imaplen > 0 && !match) { | ||
214 | /* check the child-interrupt field */ | ||
215 | match = 1; | ||
216 | for (i = 0; i < naddrc && match; ++i) | ||
217 | match = ((reg[i] ^ imap[i]) & imask[i]) == 0; | ||
218 | for (; i < naddrc + nintrc && match; ++i) | ||
219 | match = ((ints[i-naddrc] ^ imap[i]) & imask[i]) == 0; | ||
220 | imap += naddrc + nintrc; | ||
221 | imaplen -= naddrc + nintrc; | ||
222 | /* grab the interrupt parent */ | ||
223 | ipar = find_phandle((phandle) *imap++); | ||
224 | --imaplen; | ||
225 | if (ipar == NULL && num_interrupt_controllers == 1) | ||
226 | /* cope with BootX not giving us phandles */ | ||
227 | ipar = dflt_interrupt_controller; | ||
228 | if (ipar == NULL) { | ||
229 | printk("oops, no int parent %x in map of %s\n", | ||
230 | imap[-1], p->full_name); | ||
231 | return 0; | ||
232 | } | ||
233 | /* find the parent's # addr and intr cells */ | ||
234 | ip = (unsigned int *) | ||
235 | get_property(ipar, "#interrupt-cells", NULL); | ||
236 | if (ip == NULL) { | ||
237 | printk("oops, no #interrupt-cells on %s\n", | ||
238 | ipar->full_name); | ||
239 | return 0; | ||
240 | } | ||
241 | newintrc = *ip; | ||
242 | ip = (unsigned int *) | ||
243 | get_property(ipar, "#address-cells", NULL); | ||
244 | newaddrc = (ip == NULL)? 0: *ip; | ||
245 | imap += newaddrc + newintrc; | ||
246 | imaplen -= newaddrc + newintrc; | ||
247 | } | ||
248 | if (imaplen < 0) { | ||
249 | printk("oops, error decoding int-map on %s, len=%d\n", | ||
250 | p->full_name, imaplen); | ||
251 | return 0; | ||
252 | } | ||
253 | if (!match) { | ||
254 | #ifdef DEBUG_IRQ | ||
255 | printk("oops, no match in %s int-map for %s\n", | ||
256 | p->full_name, np->full_name); | ||
257 | #endif | ||
258 | return 0; | ||
259 | } | ||
260 | p = ipar; | ||
261 | naddrc = newaddrc; | ||
262 | nintrc = newintrc; | ||
263 | ints = imap - nintrc; | ||
264 | reg = ints - naddrc; | ||
265 | } | ||
266 | if (p == NULL) { | ||
267 | #ifdef DEBUG_IRQ | ||
268 | printk("hmmm, int tree for %s doesn't have ctrler\n", | ||
269 | np->full_name); | ||
270 | #endif | ||
271 | return 0; | ||
272 | } | ||
273 | *irq = ints; | ||
274 | *ictrler = p; | ||
275 | return nintrc; | ||
276 | } | ||
277 | |||
278 | static unsigned char map_isa_senses[4] = { | ||
279 | IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE, | ||
280 | IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE, | ||
281 | IRQ_SENSE_EDGE | IRQ_POLARITY_NEGATIVE, | ||
282 | IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE | ||
283 | }; | ||
284 | |||
285 | static unsigned char map_mpic_senses[4] = { | ||
286 | IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE, | ||
287 | IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE, | ||
288 | /* 2 seems to be used for the 8259 cascade... */ | ||
289 | IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE, | ||
290 | IRQ_SENSE_EDGE | IRQ_POLARITY_NEGATIVE, | ||
291 | }; | ||
292 | |||
293 | static int __devinit finish_node_interrupts(struct device_node *np, | ||
294 | unsigned long *mem_start, | ||
295 | int measure_only) | ||
296 | { | ||
297 | unsigned int *ints; | ||
298 | int intlen, intrcells, intrcount; | ||
299 | int i, j, n, sense; | ||
300 | unsigned int *irq, virq; | ||
301 | struct device_node *ic; | ||
302 | int trace = 0; | ||
303 | |||
304 | //#define TRACE(fmt...) do { if (trace) { printk(fmt); mdelay(1000); } } while(0) | ||
305 | #define TRACE(fmt...) | ||
306 | |||
307 | if (!strcmp(np->name, "smu-doorbell")) | ||
308 | trace = 1; | ||
309 | |||
310 | TRACE("Finishing SMU doorbell ! num_interrupt_controllers = %d\n", | ||
311 | num_interrupt_controllers); | ||
312 | |||
313 | if (num_interrupt_controllers == 0) { | ||
314 | /* | ||
315 | * Old machines just have a list of interrupt numbers | ||
316 | * and no interrupt-controller nodes. | ||
317 | */ | ||
318 | ints = (unsigned int *) get_property(np, "AAPL,interrupts", | ||
319 | &intlen); | ||
320 | /* XXX old interpret_pci_props looked in parent too */ | ||
321 | /* XXX old interpret_macio_props looked for interrupts | ||
322 | before AAPL,interrupts */ | ||
323 | if (ints == NULL) | ||
324 | ints = (unsigned int *) get_property(np, "interrupts", | ||
325 | &intlen); | ||
326 | if (ints == NULL) | ||
327 | return 0; | ||
328 | |||
329 | np->n_intrs = intlen / sizeof(unsigned int); | ||
330 | np->intrs = prom_alloc(np->n_intrs * sizeof(np->intrs[0]), | ||
331 | mem_start); | ||
332 | if (!np->intrs) | ||
333 | return -ENOMEM; | ||
334 | if (measure_only) | ||
335 | return 0; | ||
336 | |||
337 | for (i = 0; i < np->n_intrs; ++i) { | ||
338 | np->intrs[i].line = *ints++; | ||
339 | np->intrs[i].sense = IRQ_SENSE_LEVEL | ||
340 | | IRQ_POLARITY_NEGATIVE; | ||
341 | } | ||
342 | return 0; | ||
343 | } | ||
344 | |||
345 | ints = (unsigned int *) get_property(np, "interrupts", &intlen); | ||
346 | TRACE("ints=%p, intlen=%d\n", ints, intlen); | ||
347 | if (ints == NULL) | ||
348 | return 0; | ||
349 | intrcells = prom_n_intr_cells(np); | ||
350 | intlen /= intrcells * sizeof(unsigned int); | ||
351 | TRACE("intrcells=%d, new intlen=%d\n", intrcells, intlen); | ||
352 | np->intrs = prom_alloc(intlen * sizeof(*(np->intrs)), mem_start); | ||
353 | if (!np->intrs) | ||
354 | return -ENOMEM; | ||
355 | |||
356 | if (measure_only) | ||
357 | return 0; | ||
358 | |||
359 | intrcount = 0; | ||
360 | for (i = 0; i < intlen; ++i, ints += intrcells) { | ||
361 | n = map_interrupt(&irq, &ic, np, ints, intrcells); | ||
362 | TRACE("map, irq=%d, ic=%p, n=%d\n", irq, ic, n); | ||
363 | if (n <= 0) | ||
364 | continue; | ||
365 | |||
366 | /* don't map IRQ numbers under a cascaded 8259 controller */ | ||
367 | if (ic && device_is_compatible(ic, "chrp,iic")) { | ||
368 | np->intrs[intrcount].line = irq[0]; | ||
369 | sense = (n > 1)? (irq[1] & 3): 3; | ||
370 | np->intrs[intrcount].sense = map_isa_senses[sense]; | ||
371 | } else { | ||
372 | virq = virt_irq_create_mapping(irq[0]); | ||
373 | TRACE("virq=%d\n", virq); | ||
374 | #ifdef CONFIG_PPC64 | ||
375 | if (virq == NO_IRQ) { | ||
376 | printk(KERN_CRIT "Could not allocate interrupt" | ||
377 | " number for %s\n", np->full_name); | ||
378 | continue; | ||
379 | } | ||
380 | #endif | ||
381 | np->intrs[intrcount].line = irq_offset_up(virq); | ||
382 | sense = (n > 1)? (irq[1] & 3): 1; | ||
383 | |||
384 | /* Apple uses bits in there in a different way, let's | ||
385 | * only keep the real sense bit on macs | ||
386 | */ | ||
387 | if (machine_is(powermac)) | ||
388 | sense &= 0x1; | ||
389 | np->intrs[intrcount].sense = map_mpic_senses[sense]; | ||
390 | } | ||
391 | |||
392 | #ifdef CONFIG_PPC64 | ||
393 | /* We offset irq numbers for the u3 MPIC by 128 in PowerMac */ | ||
394 | if (machine_is(powermac) && ic && ic->parent) { | ||
395 | char *name = get_property(ic->parent, "name", NULL); | ||
396 | if (name && !strcmp(name, "u3")) | ||
397 | np->intrs[intrcount].line += 128; | ||
398 | else if (!(name && (!strcmp(name, "mac-io") || | ||
399 | !strcmp(name, "u4")))) | ||
400 | /* ignore other cascaded controllers, such as | ||
401 | the k2-sata-root */ | ||
402 | break; | ||
403 | } | ||
404 | #endif /* CONFIG_PPC64 */ | ||
405 | if (n > 2) { | ||
406 | printk("hmmm, got %d intr cells for %s:", n, | ||
407 | np->full_name); | ||
408 | for (j = 0; j < n; ++j) | ||
409 | printk(" %d", irq[j]); | ||
410 | printk("\n"); | ||
411 | } | ||
412 | ++intrcount; | ||
413 | } | ||
414 | np->n_intrs = intrcount; | ||
415 | |||
416 | return 0; | ||
417 | } | ||
418 | |||
419 | static int __devinit finish_node(struct device_node *np, | ||
420 | unsigned long *mem_start, | ||
421 | int measure_only) | ||
422 | { | ||
423 | struct device_node *child; | ||
424 | int rc = 0; | ||
425 | |||
426 | rc = finish_node_interrupts(np, mem_start, measure_only); | ||
427 | if (rc) | ||
428 | goto out; | ||
429 | |||
430 | for (child = np->child; child != NULL; child = child->sibling) { | ||
431 | rc = finish_node(child, mem_start, measure_only); | ||
432 | if (rc) | ||
433 | goto out; | ||
434 | } | ||
435 | out: | ||
436 | return rc; | ||
437 | } | ||
438 | |||
439 | static void __init scan_interrupt_controllers(void) | ||
440 | { | ||
441 | struct device_node *np; | ||
442 | int n = 0; | ||
443 | char *name, *ic; | ||
444 | int iclen; | ||
445 | |||
446 | for (np = allnodes; np != NULL; np = np->allnext) { | ||
447 | ic = get_property(np, "interrupt-controller", &iclen); | ||
448 | name = get_property(np, "name", NULL); | ||
449 | /* checking iclen makes sure we don't get a false | ||
450 | match on /chosen.interrupt_controller */ | ||
451 | if ((name != NULL | ||
452 | && strcmp(name, "interrupt-controller") == 0) | ||
453 | || (ic != NULL && iclen == 0 | ||
454 | && strcmp(name, "AppleKiwi"))) { | ||
455 | if (n == 0) | ||
456 | dflt_interrupt_controller = np; | ||
457 | ++n; | ||
458 | } | ||
459 | } | ||
460 | num_interrupt_controllers = n; | ||
461 | } | ||
462 | |||
463 | /** | ||
464 | * finish_device_tree is called once things are running normally | ||
465 | * (i.e. with text and data mapped to the address they were linked at). | ||
466 | * It traverses the device tree and fills in some of the additional, | ||
467 | * fields in each node like {n_}addrs and {n_}intrs, the virt interrupt | ||
468 | * mapping is also initialized at this point. | ||
469 | */ | ||
470 | void __init finish_device_tree(void) | ||
471 | { | ||
472 | unsigned long start, end, size = 0; | ||
473 | |||
474 | DBG(" -> finish_device_tree\n"); | ||
475 | |||
476 | #ifdef CONFIG_PPC64 | ||
477 | /* Initialize virtual IRQ map */ | ||
478 | virt_irq_init(); | ||
479 | #endif | ||
480 | scan_interrupt_controllers(); | ||
481 | |||
482 | /* | ||
483 | * Finish device-tree (pre-parsing some properties etc...) | ||
484 | * We do this in 2 passes. One with "measure_only" set, which | ||
485 | * will only measure the amount of memory needed, then we can | ||
486 | * allocate that memory, and call finish_node again. However, | ||
487 | * we must be careful as most routines will fail nowadays when | ||
488 | * prom_alloc() returns 0, so we must make sure our first pass | ||
489 | * doesn't start at 0. We pre-initialize size to 16 for that | ||
490 | * reason and then remove those additional 16 bytes | ||
491 | */ | ||
492 | size = 16; | ||
493 | finish_node(allnodes, &size, 1); | ||
494 | size -= 16; | ||
495 | |||
496 | if (0 == size) | ||
497 | end = start = 0; | ||
498 | else | ||
499 | end = start = (unsigned long)__va(lmb_alloc(size, 128)); | ||
500 | |||
501 | finish_node(allnodes, &end, 0); | ||
502 | BUG_ON(end != start + size); | ||
503 | |||
504 | DBG(" <- finish_device_tree\n"); | ||
505 | } | ||
506 | |||
507 | static inline char *find_flat_dt_string(u32 offset) | 90 | static inline char *find_flat_dt_string(u32 offset) |
508 | { | 91 | { |
509 | return ((char *)initial_boot_params) + | 92 | return ((char *)initial_boot_params) + |
@@ -1389,27 +972,6 @@ prom_n_size_cells(struct device_node* np) | |||
1389 | EXPORT_SYMBOL(prom_n_size_cells); | 972 | EXPORT_SYMBOL(prom_n_size_cells); |
1390 | 973 | ||
1391 | /** | 974 | /** |
1392 | * Work out the sense (active-low level / active-high edge) | ||
1393 | * of each interrupt from the device tree. | ||
1394 | */ | ||
1395 | void __init prom_get_irq_senses(unsigned char *senses, int off, int max) | ||
1396 | { | ||
1397 | struct device_node *np; | ||
1398 | int i, j; | ||
1399 | |||
1400 | /* default to level-triggered */ | ||
1401 | memset(senses, IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE, max - off); | ||
1402 | |||
1403 | for (np = allnodes; np != 0; np = np->allnext) { | ||
1404 | for (j = 0; j < np->n_intrs; j++) { | ||
1405 | i = np->intrs[j].line; | ||
1406 | if (i >= off && i < max) | ||
1407 | senses[i-off] = np->intrs[j].sense; | ||
1408 | } | ||
1409 | } | ||
1410 | } | ||
1411 | |||
1412 | /** | ||
1413 | * Construct and return a list of the device_nodes with a given name. | 975 | * Construct and return a list of the device_nodes with a given name. |
1414 | */ | 976 | */ |
1415 | struct device_node *find_devices(const char *name) | 977 | struct device_node *find_devices(const char *name) |
@@ -1808,7 +1370,6 @@ static void of_node_release(struct kref *kref) | |||
1808 | node->deadprops = NULL; | 1370 | node->deadprops = NULL; |
1809 | } | 1371 | } |
1810 | } | 1372 | } |
1811 | kfree(node->intrs); | ||
1812 | kfree(node->full_name); | 1373 | kfree(node->full_name); |
1813 | kfree(node->data); | 1374 | kfree(node->data); |
1814 | kfree(node); | 1375 | kfree(node); |
@@ -1881,13 +1442,7 @@ void of_detach_node(const struct device_node *np) | |||
1881 | #ifdef CONFIG_PPC_PSERIES | 1442 | #ifdef CONFIG_PPC_PSERIES |
1882 | /* | 1443 | /* |
1883 | * Fix up the uninitialized fields in a new device node: | 1444 | * Fix up the uninitialized fields in a new device node: |
1884 | * name, type, n_addrs, addrs, n_intrs, intrs, and pci-specific fields | 1445 | * name, type and pci-specific fields |
1885 | * | ||
1886 | * A lot of boot-time code is duplicated here, because functions such | ||
1887 | * as finish_node_interrupts, interpret_pci_props, etc. cannot use the | ||
1888 | * slab allocator. | ||
1889 | * | ||
1890 | * This should probably be split up into smaller chunks. | ||
1891 | */ | 1446 | */ |
1892 | 1447 | ||
1893 | static int of_finish_dynamic_node(struct device_node *node) | 1448 | static int of_finish_dynamic_node(struct device_node *node) |
@@ -1928,8 +1483,6 @@ static int prom_reconfig_notifier(struct notifier_block *nb, | |||
1928 | switch (action) { | 1483 | switch (action) { |
1929 | case PSERIES_RECONFIG_ADD: | 1484 | case PSERIES_RECONFIG_ADD: |
1930 | err = of_finish_dynamic_node(node); | 1485 | err = of_finish_dynamic_node(node); |
1931 | if (!err) | ||
1932 | finish_node(node, NULL, 0); | ||
1933 | if (err < 0) { | 1486 | if (err < 0) { |
1934 | printk(KERN_ERR "finish_node returned %d\n", err); | 1487 | printk(KERN_ERR "finish_node returned %d\n", err); |
1935 | err = NOTIFY_BAD; | 1488 | err = NOTIFY_BAD; |