diff options
Diffstat (limited to 'arch/powerpc/platforms/powermac/pci.c')
-rw-r--r-- | arch/powerpc/platforms/powermac/pci.c | 194 |
1 files changed, 85 insertions, 109 deletions
diff --git a/arch/powerpc/platforms/powermac/pci.c b/arch/powerpc/platforms/powermac/pci.c index 40bcd3e55afb..afb147e6b89f 100644 --- a/arch/powerpc/platforms/powermac/pci.c +++ b/arch/powerpc/platforms/powermac/pci.c | |||
@@ -1,8 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Support for PCI bridges found on Power Macintoshes. | 2 | * Support for PCI bridges found on Power Macintoshes. |
3 | * At present the "bandit" and "chaos" bridges are supported. | ||
4 | * Fortunately you access configuration space in the same | ||
5 | * way with either bridge. | ||
6 | * | 3 | * |
7 | * Copyright (C) 2003 Benjamin Herrenschmuidt (benh@kernel.crashing.org) | 4 | * Copyright (C) 2003 Benjamin Herrenschmuidt (benh@kernel.crashing.org) |
8 | * Copyright (C) 1997 Paul Mackerras (paulus@samba.org) | 5 | * Copyright (C) 1997 Paul Mackerras (paulus@samba.org) |
@@ -26,6 +23,10 @@ | |||
26 | #include <asm/pci-bridge.h> | 23 | #include <asm/pci-bridge.h> |
27 | #include <asm/machdep.h> | 24 | #include <asm/machdep.h> |
28 | #include <asm/pmac_feature.h> | 25 | #include <asm/pmac_feature.h> |
26 | #ifdef CONFIG_PPC64 | ||
27 | #include <asm/iommu.h> | ||
28 | #include <asm/ppc-pci.h> | ||
29 | #endif | ||
29 | 30 | ||
30 | #undef DEBUG | 31 | #undef DEBUG |
31 | 32 | ||
@@ -160,9 +161,13 @@ static unsigned long macrisc_cfg_access(struct pci_controller* hose, | |||
160 | static int macrisc_read_config(struct pci_bus *bus, unsigned int devfn, | 161 | static int macrisc_read_config(struct pci_bus *bus, unsigned int devfn, |
161 | int offset, int len, u32 *val) | 162 | int offset, int len, u32 *val) |
162 | { | 163 | { |
163 | struct pci_controller *hose = bus->sysdata; | 164 | struct pci_controller *hose; |
164 | unsigned long addr; | 165 | unsigned long addr; |
165 | 166 | ||
167 | hose = pci_bus_to_host(bus); | ||
168 | if (hose == NULL) | ||
169 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
170 | |||
166 | addr = macrisc_cfg_access(hose, bus->number, devfn, offset); | 171 | addr = macrisc_cfg_access(hose, bus->number, devfn, offset); |
167 | if (!addr) | 172 | if (!addr) |
168 | return PCIBIOS_DEVICE_NOT_FOUND; | 173 | return PCIBIOS_DEVICE_NOT_FOUND; |
@@ -187,9 +192,13 @@ static int macrisc_read_config(struct pci_bus *bus, unsigned int devfn, | |||
187 | static int macrisc_write_config(struct pci_bus *bus, unsigned int devfn, | 192 | static int macrisc_write_config(struct pci_bus *bus, unsigned int devfn, |
188 | int offset, int len, u32 val) | 193 | int offset, int len, u32 val) |
189 | { | 194 | { |
190 | struct pci_controller *hose = bus->sysdata; | 195 | struct pci_controller *hose; |
191 | unsigned long addr; | 196 | unsigned long addr; |
192 | 197 | ||
198 | hose = pci_bus_to_host(bus); | ||
199 | if (hose == NULL) | ||
200 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
201 | |||
193 | addr = macrisc_cfg_access(hose, bus->number, devfn, offset); | 202 | addr = macrisc_cfg_access(hose, bus->number, devfn, offset); |
194 | if (!addr) | 203 | if (!addr) |
195 | return PCIBIOS_DEVICE_NOT_FOUND; | 204 | return PCIBIOS_DEVICE_NOT_FOUND; |
@@ -221,7 +230,7 @@ static struct pci_ops macrisc_pci_ops = | |||
221 | }; | 230 | }; |
222 | 231 | ||
223 | /* | 232 | /* |
224 | * Verifiy that a specific (bus, dev_fn) exists on chaos | 233 | * Verify that a specific (bus, dev_fn) exists on chaos |
225 | */ | 234 | */ |
226 | static int | 235 | static int |
227 | chaos_validate_dev(struct pci_bus *bus, int devfn, int offset) | 236 | chaos_validate_dev(struct pci_bus *bus, int devfn, int offset) |
@@ -274,7 +283,6 @@ static struct pci_ops chaos_pci_ops = | |||
274 | }; | 283 | }; |
275 | 284 | ||
276 | #ifdef CONFIG_POWER4 | 285 | #ifdef CONFIG_POWER4 |
277 | |||
278 | /* | 286 | /* |
279 | * These versions of U3 HyperTransport config space access ops do not | 287 | * These versions of U3 HyperTransport config space access ops do not |
280 | * implement self-view of the HT host yet | 288 | * implement self-view of the HT host yet |
@@ -342,11 +350,11 @@ static unsigned long u3_ht_cfg_access(struct pci_controller* hose, | |||
342 | static int u3_ht_read_config(struct pci_bus *bus, unsigned int devfn, | 350 | static int u3_ht_read_config(struct pci_bus *bus, unsigned int devfn, |
343 | int offset, int len, u32 *val) | 351 | int offset, int len, u32 *val) |
344 | { | 352 | { |
345 | struct pci_controller *hose = bus->sysdata; | 353 | struct pci_controller *hose; |
346 | unsigned long addr; | 354 | unsigned long addr; |
347 | 355 | ||
348 | struct device_node *np = pci_busdev_to_OF_node(bus, devfn); | 356 | hose = pci_bus_to_host(bus); |
349 | if (np == NULL) | 357 | if (hose == NULL) |
350 | return PCIBIOS_DEVICE_NOT_FOUND; | 358 | return PCIBIOS_DEVICE_NOT_FOUND; |
351 | 359 | ||
352 | addr = u3_ht_cfg_access(hose, bus->number, devfn, offset); | 360 | addr = u3_ht_cfg_access(hose, bus->number, devfn, offset); |
@@ -357,19 +365,19 @@ static int u3_ht_read_config(struct pci_bus *bus, unsigned int devfn, | |||
357 | case 0: | 365 | case 0: |
358 | break; | 366 | break; |
359 | case 1: | 367 | case 1: |
360 | switch (len) { | 368 | switch (len) { |
361 | case 1: | 369 | case 1: |
362 | *val = 0xff; break; | 370 | *val = 0xff; break; |
363 | case 2: | 371 | case 2: |
364 | *val = 0xffff; break; | 372 | *val = 0xffff; break; |
365 | default: | 373 | default: |
366 | *val = 0xfffffffful; break; | 374 | *val = 0xfffffffful; break; |
367 | } | 375 | } |
368 | return PCIBIOS_SUCCESSFUL; | 376 | return PCIBIOS_SUCCESSFUL; |
369 | default: | 377 | default: |
370 | return PCIBIOS_DEVICE_NOT_FOUND; | 378 | return PCIBIOS_DEVICE_NOT_FOUND; |
371 | } | 379 | } |
372 | 380 | ||
373 | /* | 381 | /* |
374 | * Note: the caller has already checked that offset is | 382 | * Note: the caller has already checked that offset is |
375 | * suitably aligned and that len is 1, 2 or 4. | 383 | * suitably aligned and that len is 1, 2 or 4. |
@@ -391,11 +399,11 @@ static int u3_ht_read_config(struct pci_bus *bus, unsigned int devfn, | |||
391 | static int u3_ht_write_config(struct pci_bus *bus, unsigned int devfn, | 399 | static int u3_ht_write_config(struct pci_bus *bus, unsigned int devfn, |
392 | int offset, int len, u32 val) | 400 | int offset, int len, u32 val) |
393 | { | 401 | { |
394 | struct pci_controller *hose = bus->sysdata; | 402 | struct pci_controller *hose; |
395 | unsigned long addr; | 403 | unsigned long addr; |
396 | 404 | ||
397 | struct device_node *np = pci_busdev_to_OF_node(bus, devfn); | 405 | hose = pci_bus_to_host(bus); |
398 | if (np == NULL) | 406 | if (hose == NULL) |
399 | return PCIBIOS_DEVICE_NOT_FOUND; | 407 | return PCIBIOS_DEVICE_NOT_FOUND; |
400 | 408 | ||
401 | addr = u3_ht_cfg_access(hose, bus->number, devfn, offset); | 409 | addr = u3_ht_cfg_access(hose, bus->number, devfn, offset); |
@@ -437,15 +445,13 @@ static struct pci_ops u3_ht_pci_ops = | |||
437 | u3_ht_read_config, | 445 | u3_ht_read_config, |
438 | u3_ht_write_config | 446 | u3_ht_write_config |
439 | }; | 447 | }; |
440 | |||
441 | #endif /* CONFIG_POWER4 */ | 448 | #endif /* CONFIG_POWER4 */ |
442 | 449 | ||
443 | /* | 450 | /* |
444 | * For a bandit bridge, turn on cache coherency if necessary. | 451 | * For a bandit bridge, turn on cache coherency if necessary. |
445 | * N.B. we could clean this up using the hose ops directly. | 452 | * N.B. we could clean this up using the hose ops directly. |
446 | */ | 453 | */ |
447 | static void __init | 454 | static void __init init_bandit(struct pci_controller *bp) |
448 | init_bandit(struct pci_controller *bp) | ||
449 | { | 455 | { |
450 | unsigned int vendev, magic; | 456 | unsigned int vendev, magic; |
451 | int rev; | 457 | int rev; |
@@ -485,8 +491,7 @@ init_bandit(struct pci_controller *bp) | |||
485 | /* | 491 | /* |
486 | * Tweak the PCI-PCI bridge chip on the blue & white G3s. | 492 | * Tweak the PCI-PCI bridge chip on the blue & white G3s. |
487 | */ | 493 | */ |
488 | static void __init | 494 | static void __init init_p2pbridge(void) |
489 | init_p2pbridge(void) | ||
490 | { | 495 | { |
491 | struct device_node *p2pbridge; | 496 | struct device_node *p2pbridge; |
492 | struct pci_controller* hose; | 497 | struct pci_controller* hose; |
@@ -526,8 +531,7 @@ init_p2pbridge(void) | |||
526 | * EHCI part of it so it behaves like a pair of OHCI's. This fixup | 531 | * EHCI part of it so it behaves like a pair of OHCI's. This fixup |
527 | * code re-enables it ;) | 532 | * code re-enables it ;) |
528 | */ | 533 | */ |
529 | static void __init | 534 | static void __init fixup_nec_usb2(void) |
530 | fixup_nec_usb2(void) | ||
531 | { | 535 | { |
532 | struct device_node *nec; | 536 | struct device_node *nec; |
533 | 537 | ||
@@ -567,77 +571,6 @@ fixup_nec_usb2(void) | |||
567 | } | 571 | } |
568 | } | 572 | } |
569 | 573 | ||
570 | void __init | ||
571 | pmac_find_bridges(void) | ||
572 | { | ||
573 | struct device_node *np, *root; | ||
574 | struct device_node *ht = NULL; | ||
575 | |||
576 | root = of_find_node_by_path("/"); | ||
577 | if (root == NULL) { | ||
578 | printk(KERN_CRIT "pmac_find_bridges: can't find root of device tree\n"); | ||
579 | return; | ||
580 | } | ||
581 | for (np = NULL; (np = of_get_next_child(root, np)) != NULL;) { | ||
582 | if (np->name == NULL) | ||
583 | continue; | ||
584 | if (strcmp(np->name, "bandit") == 0 | ||
585 | || strcmp(np->name, "chaos") == 0 | ||
586 | || strcmp(np->name, "pci") == 0) { | ||
587 | if (add_bridge(np) == 0) | ||
588 | of_node_get(np); | ||
589 | } | ||
590 | if (strcmp(np->name, "ht") == 0) { | ||
591 | of_node_get(np); | ||
592 | ht = np; | ||
593 | } | ||
594 | } | ||
595 | of_node_put(root); | ||
596 | |||
597 | /* Probe HT last as it relies on the agp resources to be already | ||
598 | * setup | ||
599 | */ | ||
600 | if (ht && add_bridge(ht) != 0) | ||
601 | of_node_put(ht); | ||
602 | |||
603 | init_p2pbridge(); | ||
604 | fixup_nec_usb2(); | ||
605 | |||
606 | /* We are still having some issues with the Xserve G4, enabling | ||
607 | * some offset between bus number and domains for now when we | ||
608 | * assign all busses should help for now | ||
609 | */ | ||
610 | if (pci_assign_all_busses) | ||
611 | pcibios_assign_bus_offset = 0x10; | ||
612 | |||
613 | #ifdef CONFIG_POWER4 | ||
614 | /* There is something wrong with DMA on U3/HT. I haven't figured out | ||
615 | * the details yet, but if I set the cache line size to 128 bytes like | ||
616 | * it should, I'm getting memory corruption caused by devices like | ||
617 | * sungem (even without the MWI bit set, but maybe sungem doesn't | ||
618 | * care). Right now, it appears that setting up a 64 bytes line size | ||
619 | * works properly, 64 bytes beeing the max transfer size of HT, I | ||
620 | * suppose this is related the way HT/PCI are hooked together. I still | ||
621 | * need to dive into more specs though to be really sure of what's | ||
622 | * going on. --BenH. | ||
623 | * | ||
624 | * Ok, apparently, it's just that HT can't do more than 64 bytes | ||
625 | * transactions. MWI seem to be meaningless there as well, it may | ||
626 | * be worth nop'ing out pci_set_mwi too though I haven't done that | ||
627 | * yet. | ||
628 | * | ||
629 | * Note that it's a bit different for whatever is in the AGP slot. | ||
630 | * For now, I don't care, but this can become a real issue, we | ||
631 | * should probably hook pci_set_mwi anyway to make sure it sets | ||
632 | * the real cache line size in there. | ||
633 | */ | ||
634 | if (machine_is_compatible("MacRISC4")) | ||
635 | pci_cache_line_size = 16; /* 64 bytes */ | ||
636 | |||
637 | pmac_check_ht_link(); | ||
638 | #endif /* CONFIG_POWER4 */ | ||
639 | } | ||
640 | |||
641 | #define GRACKLE_CFA(b, d, o) (0x80 | ((b) << 8) | ((d) << 16) \ | 574 | #define GRACKLE_CFA(b, d, o) (0x80 | ((b) << 8) | ((d) << 16) \ |
642 | | (((o) & ~3) << 24)) | 575 | | (((o) & ~3) << 24)) |
643 | 576 | ||
@@ -703,7 +636,6 @@ setup_chaos(struct pci_controller* hose, struct reg_property* addr) | |||
703 | } | 636 | } |
704 | 637 | ||
705 | #ifdef CONFIG_POWER4 | 638 | #ifdef CONFIG_POWER4 |
706 | |||
707 | static void __init setup_u3_agp(struct pci_controller* hose) | 639 | static void __init setup_u3_agp(struct pci_controller* hose) |
708 | { | 640 | { |
709 | /* On G5, we move AGP up to high bus number so we don't need | 641 | /* On G5, we move AGP up to high bus number so we don't need |
@@ -715,7 +647,7 @@ static void __init setup_u3_agp(struct pci_controller* hose) | |||
715 | * the reg address cell, we shall fix that by killing struct | 647 | * the reg address cell, we shall fix that by killing struct |
716 | * reg_property and using some accessor functions instead | 648 | * reg_property and using some accessor functions instead |
717 | */ | 649 | */ |
718 | hose->first_busno = 0xf0; | 650 | hose->first_busno = 0xf0; |
719 | hose->last_busno = 0xff; | 651 | hose->last_busno = 0xff; |
720 | has_uninorth = 1; | 652 | has_uninorth = 1; |
721 | hose->ops = ¯isc_pci_ops; | 653 | hose->ops = ¯isc_pci_ops; |
@@ -748,7 +680,7 @@ static void __init setup_u3_ht(struct pci_controller* hose) | |||
748 | */ | 680 | */ |
749 | hose->io_base_phys = 0xf4000000; | 681 | hose->io_base_phys = 0xf4000000; |
750 | hose->io_base_virt = ioremap(hose->io_base_phys, 0x00400000); | 682 | hose->io_base_virt = ioremap(hose->io_base_phys, 0x00400000); |
751 | isa_io_base = (unsigned long) hose->io_base_virt; | 683 | isa_io_base = pci_io_base = (unsigned long) hose->io_base_virt; |
752 | hose->io_resource.name = np->full_name; | 684 | hose->io_resource.name = np->full_name; |
753 | hose->io_resource.start = 0; | 685 | hose->io_resource.start = 0; |
754 | hose->io_resource.end = 0x003fffff; | 686 | hose->io_resource.end = 0x003fffff; |
@@ -794,13 +726,13 @@ static void __init setup_u3_ht(struct pci_controller* hose) | |||
794 | } | 726 | } |
795 | /* No, it's not the case, we need a hole */ | 727 | /* No, it's not the case, we need a hole */ |
796 | if (cur == 2) { | 728 | if (cur == 2) { |
797 | /* not enough resources to make a hole, we drop part of the range */ | 729 | /* not enough resources for a hole, we drop part of the range */ |
798 | printk(KERN_WARNING "Running out of resources for /ht host !\n"); | 730 | printk(KERN_WARNING "Running out of resources for /ht host !\n"); |
799 | hose->mem_resources[cur].end = res->start - 1; | 731 | hose->mem_resources[cur].end = res->start - 1; |
800 | continue; | 732 | continue; |
801 | } | 733 | } |
802 | cur++; | 734 | cur++; |
803 | DBG("U3/HT: hole, %d end at %08lx, %d start at %08lx\n", | 735 | DBG("U3/HT: hole, %d end at %08lx, %d start at %08lx\n", |
804 | cur-1, res->start - 1, cur, res->end + 1); | 736 | cur-1, res->start - 1, cur, res->end + 1); |
805 | hose->mem_resources[cur].name = np->full_name; | 737 | hose->mem_resources[cur].name = np->full_name; |
806 | hose->mem_resources[cur].flags = IORESOURCE_MEM; | 738 | hose->mem_resources[cur].flags = IORESOURCE_MEM; |
@@ -981,7 +913,7 @@ static int __init add_bridge(struct device_node *dev) | |||
981 | if (device_is_compatible(dev, "uni-north")) { | 913 | if (device_is_compatible(dev, "uni-north")) { |
982 | primary = setup_uninorth(hose, addr); | 914 | primary = setup_uninorth(hose, addr); |
983 | disp_name = "UniNorth"; | 915 | disp_name = "UniNorth"; |
984 | } else if (strcmp(dev->name, "pci") == 0) { | 916 | } else if (strcmp(dev->name, "pci") == 0) { |
985 | /* XXX assume this is a mpc106 (grackle) */ | 917 | /* XXX assume this is a mpc106 (grackle) */ |
986 | setup_grackle(hose); | 918 | setup_grackle(hose); |
987 | disp_name = "Grackle (MPC106)"; | 919 | disp_name = "Grackle (MPC106)"; |
@@ -993,7 +925,7 @@ static int __init add_bridge(struct device_node *dev) | |||
993 | disp_name = "Chaos"; | 925 | disp_name = "Chaos"; |
994 | primary = 0; | 926 | primary = 0; |
995 | } | 927 | } |
996 | printk(KERN_INFO "Found %s PCI host bridge at 0x%08x. Firmware bus number: %d->%d\n", | 928 | printk(KERN_INFO "Found %s PCI host bridge at 0x%08lx. Firmware bus number: %d->%d\n", |
997 | disp_name, addr->address, hose->first_busno, hose->last_busno); | 929 | disp_name, addr->address, hose->first_busno, hose->last_busno); |
998 | DBG(" ->Hose at 0x%p, cfg_addr=0x%p,cfg_data=0x%p\n", | 930 | DBG(" ->Hose at 0x%p, cfg_addr=0x%p,cfg_data=0x%p\n", |
999 | hose, hose->cfg_addr, hose->cfg_data); | 931 | hose, hose->cfg_addr, hose->cfg_data); |
@@ -1036,6 +968,50 @@ pmac_pcibios_fixup(void) | |||
1036 | pcibios_fixup_OF_interrupts(); | 968 | pcibios_fixup_OF_interrupts(); |
1037 | } | 969 | } |
1038 | 970 | ||
971 | void __init pmac_find_bridges(void) | ||
972 | { | ||
973 | struct device_node *np, *root; | ||
974 | struct device_node *ht = NULL; | ||
975 | |||
976 | root = of_find_node_by_path("/"); | ||
977 | if (root == NULL) { | ||
978 | printk(KERN_CRIT "pmac_find_bridges: can't find root of device tree\n"); | ||
979 | return; | ||
980 | } | ||
981 | for (np = NULL; (np = of_get_next_child(root, np)) != NULL;) { | ||
982 | if (np->name == NULL) | ||
983 | continue; | ||
984 | if (strcmp(np->name, "bandit") == 0 | ||
985 | || strcmp(np->name, "chaos") == 0 | ||
986 | || strcmp(np->name, "pci") == 0) { | ||
987 | if (add_bridge(np) == 0) | ||
988 | of_node_get(np); | ||
989 | } | ||
990 | if (strcmp(np->name, "ht") == 0) { | ||
991 | of_node_get(np); | ||
992 | ht = np; | ||
993 | } | ||
994 | } | ||
995 | of_node_put(root); | ||
996 | |||
997 | /* Probe HT last as it relies on the agp resources to be already | ||
998 | * setup | ||
999 | */ | ||
1000 | if (ht && add_bridge(ht) != 0) | ||
1001 | of_node_put(ht); | ||
1002 | |||
1003 | init_p2pbridge(); | ||
1004 | fixup_nec_usb2(); | ||
1005 | |||
1006 | /* We are still having some issues with the Xserve G4, enabling | ||
1007 | * some offset between bus number and domains for now when we | ||
1008 | * assign all busses should help for now | ||
1009 | */ | ||
1010 | if (pci_assign_all_busses) | ||
1011 | pcibios_assign_bus_offset = 0x10; | ||
1012 | |||
1013 | } | ||
1014 | |||
1039 | int | 1015 | int |
1040 | pmac_pci_enable_device_hook(struct pci_dev *dev, int initial) | 1016 | pmac_pci_enable_device_hook(struct pci_dev *dev, int initial) |
1041 | { | 1017 | { |