diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2005-12-13 21:10:10 -0500 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2006-01-08 23:03:17 -0500 |
commit | 1beb6a7d6cbed3ac03500ce9b5b9bb632c512039 (patch) | |
tree | 727aa76da5a82fca449dadf3cebbadc414ad6555 /arch/powerpc/kernel/prom.c | |
parent | cd0c7f06803be06a5cf4564aa5a900f4b6aea603 (diff) |
[PATCH] powerpc: Experimental support for new G5 Macs (#2)
This adds some very basic support for the new machines, including the
Quad G5 (tested), and other new dual core based machines and iMac G5
iSight (untested). This is still experimental ! There is no thermal
control yet, there is no proper handing of MSIs, etc.. but it
boots, I have all 4 cores up on my machine. Compared to the previous
version of this patch, this one adds DART IOMMU support for the U4
chipset and thus should work fine on setups with more than 2Gb of RAM.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/kernel/prom.c')
-rw-r--r-- | arch/powerpc/kernel/prom.c | 26 |
1 files changed, 23 insertions, 3 deletions
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 1b97e13657e5..977ee3adaf2d 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c | |||
@@ -298,6 +298,16 @@ static int __devinit finish_node_interrupts(struct device_node *np, | |||
298 | int i, j, n, sense; | 298 | int i, j, n, sense; |
299 | unsigned int *irq, virq; | 299 | unsigned int *irq, virq; |
300 | struct device_node *ic; | 300 | struct device_node *ic; |
301 | int trace = 0; | ||
302 | |||
303 | //#define TRACE(fmt...) do { if (trace) { printk(fmt); mdelay(1000); } } while(0) | ||
304 | #define TRACE(fmt...) | ||
305 | |||
306 | if (!strcmp(np->name, "smu-doorbell")) | ||
307 | trace = 1; | ||
308 | |||
309 | TRACE("Finishing SMU doorbell ! num_interrupt_controllers = %d\n", | ||
310 | num_interrupt_controllers); | ||
301 | 311 | ||
302 | if (num_interrupt_controllers == 0) { | 312 | if (num_interrupt_controllers == 0) { |
303 | /* | 313 | /* |
@@ -332,11 +342,12 @@ static int __devinit finish_node_interrupts(struct device_node *np, | |||
332 | } | 342 | } |
333 | 343 | ||
334 | ints = (unsigned int *) get_property(np, "interrupts", &intlen); | 344 | ints = (unsigned int *) get_property(np, "interrupts", &intlen); |
345 | TRACE("ints=%p, intlen=%d\n", ints, intlen); | ||
335 | if (ints == NULL) | 346 | if (ints == NULL) |
336 | return 0; | 347 | return 0; |
337 | intrcells = prom_n_intr_cells(np); | 348 | intrcells = prom_n_intr_cells(np); |
338 | intlen /= intrcells * sizeof(unsigned int); | 349 | intlen /= intrcells * sizeof(unsigned int); |
339 | 350 | TRACE("intrcells=%d, new intlen=%d\n", intrcells, intlen); | |
340 | np->intrs = prom_alloc(intlen * sizeof(*(np->intrs)), mem_start); | 351 | np->intrs = prom_alloc(intlen * sizeof(*(np->intrs)), mem_start); |
341 | if (!np->intrs) | 352 | if (!np->intrs) |
342 | return -ENOMEM; | 353 | return -ENOMEM; |
@@ -347,6 +358,7 @@ static int __devinit finish_node_interrupts(struct device_node *np, | |||
347 | intrcount = 0; | 358 | intrcount = 0; |
348 | for (i = 0; i < intlen; ++i, ints += intrcells) { | 359 | for (i = 0; i < intlen; ++i, ints += intrcells) { |
349 | n = map_interrupt(&irq, &ic, np, ints, intrcells); | 360 | n = map_interrupt(&irq, &ic, np, ints, intrcells); |
361 | TRACE("map, irq=%d, ic=%p, n=%d\n", irq, ic, n); | ||
350 | if (n <= 0) | 362 | if (n <= 0) |
351 | continue; | 363 | continue; |
352 | 364 | ||
@@ -357,6 +369,7 @@ static int __devinit finish_node_interrupts(struct device_node *np, | |||
357 | np->intrs[intrcount].sense = map_isa_senses[sense]; | 369 | np->intrs[intrcount].sense = map_isa_senses[sense]; |
358 | } else { | 370 | } else { |
359 | virq = virt_irq_create_mapping(irq[0]); | 371 | virq = virt_irq_create_mapping(irq[0]); |
372 | TRACE("virq=%d\n", virq); | ||
360 | #ifdef CONFIG_PPC64 | 373 | #ifdef CONFIG_PPC64 |
361 | if (virq == NO_IRQ) { | 374 | if (virq == NO_IRQ) { |
362 | printk(KERN_CRIT "Could not allocate interrupt" | 375 | printk(KERN_CRIT "Could not allocate interrupt" |
@@ -366,6 +379,12 @@ static int __devinit finish_node_interrupts(struct device_node *np, | |||
366 | #endif | 379 | #endif |
367 | np->intrs[intrcount].line = irq_offset_up(virq); | 380 | np->intrs[intrcount].line = irq_offset_up(virq); |
368 | sense = (n > 1)? (irq[1] & 3): 1; | 381 | sense = (n > 1)? (irq[1] & 3): 1; |
382 | |||
383 | /* Apple uses bits in there in a different way, let's | ||
384 | * only keep the real sense bit on macs | ||
385 | */ | ||
386 | if (_machine == PLATFORM_POWERMAC) | ||
387 | sense &= 0x1; | ||
369 | np->intrs[intrcount].sense = map_mpic_senses[sense]; | 388 | np->intrs[intrcount].sense = map_mpic_senses[sense]; |
370 | } | 389 | } |
371 | 390 | ||
@@ -375,12 +394,13 @@ static int __devinit finish_node_interrupts(struct device_node *np, | |||
375 | char *name = get_property(ic->parent, "name", NULL); | 394 | char *name = get_property(ic->parent, "name", NULL); |
376 | if (name && !strcmp(name, "u3")) | 395 | if (name && !strcmp(name, "u3")) |
377 | np->intrs[intrcount].line += 128; | 396 | np->intrs[intrcount].line += 128; |
378 | else if (!(name && !strcmp(name, "mac-io"))) | 397 | else if (!(name && (!strcmp(name, "mac-io") || |
398 | !strcmp(name, "u4")))) | ||
379 | /* ignore other cascaded controllers, such as | 399 | /* ignore other cascaded controllers, such as |
380 | the k2-sata-root */ | 400 | the k2-sata-root */ |
381 | break; | 401 | break; |
382 | } | 402 | } |
383 | #endif | 403 | #endif /* CONFIG_PPC64 */ |
384 | if (n > 2) { | 404 | if (n > 2) { |
385 | printk("hmmm, got %d intr cells for %s:", n, | 405 | printk("hmmm, got %d intr cells for %s:", n, |
386 | np->full_name); | 406 | np->full_name); |