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 | |
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')
-rw-r--r-- | arch/powerpc/kernel/pci_64.c | 35 | ||||
-rw-r--r-- | arch/powerpc/kernel/prom.c | 26 | ||||
-rw-r--r-- | arch/powerpc/kernel/udbg.c | 2 |
3 files changed, 54 insertions, 9 deletions
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index 523f35087e81..f73a16e9867a 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c | |||
@@ -34,7 +34,7 @@ | |||
34 | 34 | ||
35 | #ifdef DEBUG | 35 | #ifdef DEBUG |
36 | #include <asm/udbg.h> | 36 | #include <asm/udbg.h> |
37 | #define DBG(fmt...) udbg_printf(fmt) | 37 | #define DBG(fmt...) printk(fmt) |
38 | #else | 38 | #else |
39 | #define DBG(fmt...) | 39 | #define DBG(fmt...) |
40 | #endif | 40 | #endif |
@@ -323,6 +323,7 @@ static void pci_parse_of_addrs(struct device_node *node, struct pci_dev *dev) | |||
323 | addrs = (u32 *) get_property(node, "assigned-addresses", &proplen); | 323 | addrs = (u32 *) get_property(node, "assigned-addresses", &proplen); |
324 | if (!addrs) | 324 | if (!addrs) |
325 | return; | 325 | return; |
326 | DBG(" parse addresses (%d bytes) @ %p\n", proplen, addrs); | ||
326 | for (; proplen >= 20; proplen -= 20, addrs += 5) { | 327 | for (; proplen >= 20; proplen -= 20, addrs += 5) { |
327 | flags = pci_parse_of_flags(addrs[0]); | 328 | flags = pci_parse_of_flags(addrs[0]); |
328 | if (!flags) | 329 | if (!flags) |
@@ -332,6 +333,9 @@ static void pci_parse_of_addrs(struct device_node *node, struct pci_dev *dev) | |||
332 | if (!size) | 333 | if (!size) |
333 | continue; | 334 | continue; |
334 | i = addrs[0] & 0xff; | 335 | i = addrs[0] & 0xff; |
336 | DBG(" base: %llx, size: %llx, i: %x\n", | ||
337 | (unsigned long long)base, (unsigned long long)size, i); | ||
338 | |||
335 | if (PCI_BASE_ADDRESS_0 <= i && i <= PCI_BASE_ADDRESS_5) { | 339 | if (PCI_BASE_ADDRESS_0 <= i && i <= PCI_BASE_ADDRESS_5) { |
336 | res = &dev->resource[(i - PCI_BASE_ADDRESS_0) >> 2]; | 340 | res = &dev->resource[(i - PCI_BASE_ADDRESS_0) >> 2]; |
337 | } else if (i == dev->rom_base_reg) { | 341 | } else if (i == dev->rom_base_reg) { |
@@ -362,6 +366,8 @@ struct pci_dev *of_create_pci_dev(struct device_node *node, | |||
362 | if (type == NULL) | 366 | if (type == NULL) |
363 | type = ""; | 367 | type = ""; |
364 | 368 | ||
369 | DBG(" create device, devfn: %x, type: %s\n", devfn, type); | ||
370 | |||
365 | memset(dev, 0, sizeof(struct pci_dev)); | 371 | memset(dev, 0, sizeof(struct pci_dev)); |
366 | dev->bus = bus; | 372 | dev->bus = bus; |
367 | dev->sysdata = node; | 373 | dev->sysdata = node; |
@@ -381,6 +387,8 @@ struct pci_dev *of_create_pci_dev(struct device_node *node, | |||
381 | dev->bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn)); | 387 | dev->bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn)); |
382 | dev->class = get_int_prop(node, "class-code", 0); | 388 | dev->class = get_int_prop(node, "class-code", 0); |
383 | 389 | ||
390 | DBG(" class: 0x%x\n", dev->class); | ||
391 | |||
384 | dev->current_state = 4; /* unknown power state */ | 392 | dev->current_state = 4; /* unknown power state */ |
385 | 393 | ||
386 | if (!strcmp(type, "pci")) { | 394 | if (!strcmp(type, "pci")) { |
@@ -402,6 +410,8 @@ struct pci_dev *of_create_pci_dev(struct device_node *node, | |||
402 | 410 | ||
403 | pci_parse_of_addrs(node, dev); | 411 | pci_parse_of_addrs(node, dev); |
404 | 412 | ||
413 | DBG(" adding to system ...\n"); | ||
414 | |||
405 | pci_device_add(dev, bus); | 415 | pci_device_add(dev, bus); |
406 | 416 | ||
407 | /* XXX pci_scan_msi_device(dev); */ | 417 | /* XXX pci_scan_msi_device(dev); */ |
@@ -418,15 +428,21 @@ void __devinit of_scan_bus(struct device_node *node, | |||
418 | int reglen, devfn; | 428 | int reglen, devfn; |
419 | struct pci_dev *dev; | 429 | struct pci_dev *dev; |
420 | 430 | ||
431 | DBG("of_scan_bus(%s) bus no %d... \n", node->full_name, bus->number); | ||
432 | |||
421 | while ((child = of_get_next_child(node, child)) != NULL) { | 433 | while ((child = of_get_next_child(node, child)) != NULL) { |
434 | DBG(" * %s\n", child->full_name); | ||
422 | reg = (u32 *) get_property(child, "reg", ®len); | 435 | reg = (u32 *) get_property(child, "reg", ®len); |
423 | if (reg == NULL || reglen < 20) | 436 | if (reg == NULL || reglen < 20) |
424 | continue; | 437 | continue; |
425 | devfn = (reg[0] >> 8) & 0xff; | 438 | devfn = (reg[0] >> 8) & 0xff; |
439 | |||
426 | /* create a new pci_dev for this device */ | 440 | /* create a new pci_dev for this device */ |
427 | dev = of_create_pci_dev(child, bus, devfn); | 441 | dev = of_create_pci_dev(child, bus, devfn); |
428 | if (!dev) | 442 | if (!dev) |
429 | continue; | 443 | continue; |
444 | DBG("dev header type: %x\n", dev->hdr_type); | ||
445 | |||
430 | if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || | 446 | if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || |
431 | dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) | 447 | dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) |
432 | of_scan_pci_bridge(child, dev); | 448 | of_scan_pci_bridge(child, dev); |
@@ -446,16 +462,18 @@ void __devinit of_scan_pci_bridge(struct device_node *node, | |||
446 | unsigned int flags; | 462 | unsigned int flags; |
447 | u64 size; | 463 | u64 size; |
448 | 464 | ||
465 | DBG("of_scan_pci_bridge(%s)\n", node->full_name); | ||
466 | |||
449 | /* parse bus-range property */ | 467 | /* parse bus-range property */ |
450 | busrange = (u32 *) get_property(node, "bus-range", &len); | 468 | busrange = (u32 *) get_property(node, "bus-range", &len); |
451 | if (busrange == NULL || len != 8) { | 469 | if (busrange == NULL || len != 8) { |
452 | printk(KERN_ERR "Can't get bus-range for PCI-PCI bridge %s\n", | 470 | printk(KERN_DEBUG "Can't get bus-range for PCI-PCI bridge %s\n", |
453 | node->full_name); | 471 | node->full_name); |
454 | return; | 472 | return; |
455 | } | 473 | } |
456 | ranges = (u32 *) get_property(node, "ranges", &len); | 474 | ranges = (u32 *) get_property(node, "ranges", &len); |
457 | if (ranges == NULL) { | 475 | if (ranges == NULL) { |
458 | printk(KERN_ERR "Can't get ranges for PCI-PCI bridge %s\n", | 476 | printk(KERN_DEBUG "Can't get ranges for PCI-PCI bridge %s\n", |
459 | node->full_name); | 477 | node->full_name); |
460 | return; | 478 | return; |
461 | } | 479 | } |
@@ -509,10 +527,13 @@ void __devinit of_scan_pci_bridge(struct device_node *node, | |||
509 | } | 527 | } |
510 | sprintf(bus->name, "PCI Bus %04x:%02x", pci_domain_nr(bus), | 528 | sprintf(bus->name, "PCI Bus %04x:%02x", pci_domain_nr(bus), |
511 | bus->number); | 529 | bus->number); |
530 | DBG(" bus name: %s\n", bus->name); | ||
512 | 531 | ||
513 | mode = PCI_PROBE_NORMAL; | 532 | mode = PCI_PROBE_NORMAL; |
514 | if (ppc_md.pci_probe_mode) | 533 | if (ppc_md.pci_probe_mode) |
515 | mode = ppc_md.pci_probe_mode(bus); | 534 | mode = ppc_md.pci_probe_mode(bus); |
535 | DBG(" probe mode: %d\n", mode); | ||
536 | |||
516 | if (mode == PCI_PROBE_DEVTREE) | 537 | if (mode == PCI_PROBE_DEVTREE) |
517 | of_scan_bus(node, bus); | 538 | of_scan_bus(node, bus); |
518 | else if (mode == PCI_PROBE_NORMAL) | 539 | else if (mode == PCI_PROBE_NORMAL) |
@@ -528,6 +549,8 @@ void __devinit scan_phb(struct pci_controller *hose) | |||
528 | int i, mode; | 549 | int i, mode; |
529 | struct resource *res; | 550 | struct resource *res; |
530 | 551 | ||
552 | DBG("Scanning PHB %s\n", node ? node->full_name : "<NO NAME>"); | ||
553 | |||
531 | bus = pci_create_bus(NULL, hose->first_busno, hose->ops, node); | 554 | bus = pci_create_bus(NULL, hose->first_busno, hose->ops, node); |
532 | if (bus == NULL) { | 555 | if (bus == NULL) { |
533 | printk(KERN_ERR "Failed to create bus for PCI domain %04x\n", | 556 | printk(KERN_ERR "Failed to create bus for PCI domain %04x\n", |
@@ -552,8 +575,9 @@ void __devinit scan_phb(struct pci_controller *hose) | |||
552 | 575 | ||
553 | mode = PCI_PROBE_NORMAL; | 576 | mode = PCI_PROBE_NORMAL; |
554 | #ifdef CONFIG_PPC_MULTIPLATFORM | 577 | #ifdef CONFIG_PPC_MULTIPLATFORM |
555 | if (ppc_md.pci_probe_mode) | 578 | if (node && ppc_md.pci_probe_mode) |
556 | mode = ppc_md.pci_probe_mode(bus); | 579 | mode = ppc_md.pci_probe_mode(bus); |
580 | DBG(" probe mode: %d\n", mode); | ||
557 | if (mode == PCI_PROBE_DEVTREE) { | 581 | if (mode == PCI_PROBE_DEVTREE) { |
558 | bus->subordinate = hose->last_busno; | 582 | bus->subordinate = hose->last_busno; |
559 | of_scan_bus(node, bus); | 583 | of_scan_bus(node, bus); |
@@ -842,8 +866,7 @@ pgprot_t pci_phys_mem_access_prot(struct file *file, | |||
842 | * Returns a negative error code on failure, zero on success. | 866 | * Returns a negative error code on failure, zero on success. |
843 | */ | 867 | */ |
844 | int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, | 868 | int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, |
845 | enum pci_mmap_state mmap_state, | 869 | enum pci_mmap_state mmap_state, int write_combine) |
846 | int write_combine) | ||
847 | { | 870 | { |
848 | unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; | 871 | unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; |
849 | struct resource *rp; | 872 | struct resource *rp; |
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); |
diff --git a/arch/powerpc/kernel/udbg.c b/arch/powerpc/kernel/udbg.c index a058285a70e7..9567d9474c80 100644 --- a/arch/powerpc/kernel/udbg.c +++ b/arch/powerpc/kernel/udbg.c | |||
@@ -110,10 +110,12 @@ static int early_console_initialized; | |||
110 | 110 | ||
111 | void __init disable_early_printk(void) | 111 | void __init disable_early_printk(void) |
112 | { | 112 | { |
113 | #if 1 | ||
113 | if (!early_console_initialized) | 114 | if (!early_console_initialized) |
114 | return; | 115 | return; |
115 | unregister_console(&udbg_console); | 116 | unregister_console(&udbg_console); |
116 | early_console_initialized = 0; | 117 | early_console_initialized = 0; |
118 | #endif | ||
117 | } | 119 | } |
118 | 120 | ||
119 | /* called by setup_system */ | 121 | /* called by setup_system */ |