diff options
Diffstat (limited to 'arch/sparc64/kernel')
-rw-r--r-- | arch/sparc64/kernel/of_device.c | 29 | ||||
-rw-r--r-- | arch/sparc64/kernel/pci.c | 80 | ||||
-rw-r--r-- | arch/sparc64/kernel/pci_sabre.c | 340 |
3 files changed, 165 insertions, 284 deletions
diff --git a/arch/sparc64/kernel/of_device.c b/arch/sparc64/kernel/of_device.c index 6b8798141f2c..8964eacb0048 100644 --- a/arch/sparc64/kernel/of_device.c +++ b/arch/sparc64/kernel/of_device.c | |||
@@ -317,6 +317,11 @@ static unsigned int of_bus_default_get_flags(const u32 *addr) | |||
317 | static int of_bus_pci_match(struct device_node *np) | 317 | static int of_bus_pci_match(struct device_node *np) |
318 | { | 318 | { |
319 | if (!strcmp(np->type, "pci") || !strcmp(np->type, "pciex")) { | 319 | if (!strcmp(np->type, "pci") || !strcmp(np->type, "pciex")) { |
320 | char *model = of_get_property(np, "model", NULL); | ||
321 | |||
322 | if (model && !strcmp(model, "SUNW,simba")) | ||
323 | return 0; | ||
324 | |||
320 | /* Do not do PCI specific frobbing if the | 325 | /* Do not do PCI specific frobbing if the |
321 | * PCI bridge lacks a ranges property. We | 326 | * PCI bridge lacks a ranges property. We |
322 | * want to pass it through up to the next | 327 | * want to pass it through up to the next |
@@ -332,6 +337,21 @@ static int of_bus_pci_match(struct device_node *np) | |||
332 | return 0; | 337 | return 0; |
333 | } | 338 | } |
334 | 339 | ||
340 | static int of_bus_simba_match(struct device_node *np) | ||
341 | { | ||
342 | char *model = of_get_property(np, "model", NULL); | ||
343 | |||
344 | if (model && !strcmp(model, "SUNW,simba")) | ||
345 | return 1; | ||
346 | return 0; | ||
347 | } | ||
348 | |||
349 | static int of_bus_simba_map(u32 *addr, const u32 *range, | ||
350 | int na, int ns, int pna) | ||
351 | { | ||
352 | return 0; | ||
353 | } | ||
354 | |||
335 | static void of_bus_pci_count_cells(struct device_node *np, | 355 | static void of_bus_pci_count_cells(struct device_node *np, |
336 | int *addrc, int *sizec) | 356 | int *addrc, int *sizec) |
337 | { | 357 | { |
@@ -436,6 +456,15 @@ static struct of_bus of_busses[] = { | |||
436 | .map = of_bus_pci_map, | 456 | .map = of_bus_pci_map, |
437 | .get_flags = of_bus_pci_get_flags, | 457 | .get_flags = of_bus_pci_get_flags, |
438 | }, | 458 | }, |
459 | /* SIMBA */ | ||
460 | { | ||
461 | .name = "simba", | ||
462 | .addr_prop_name = "assigned-addresses", | ||
463 | .match = of_bus_simba_match, | ||
464 | .count_cells = of_bus_pci_count_cells, | ||
465 | .map = of_bus_simba_map, | ||
466 | .get_flags = of_bus_pci_get_flags, | ||
467 | }, | ||
439 | /* SBUS */ | 468 | /* SBUS */ |
440 | { | 469 | { |
441 | .name = "sbus", | 470 | .name = "sbus", |
diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index 425e883e7e3b..b63341c2a334 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <asm/ebus.h> | 26 | #include <asm/ebus.h> |
27 | #include <asm/isa.h> | 27 | #include <asm/isa.h> |
28 | #include <asm/prom.h> | 28 | #include <asm/prom.h> |
29 | #include <asm/apb.h> | ||
29 | 30 | ||
30 | #include "pci_impl.h" | 31 | #include "pci_impl.h" |
31 | 32 | ||
@@ -372,6 +373,7 @@ struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm, | |||
372 | struct dev_archdata *sd; | 373 | struct dev_archdata *sd; |
373 | struct pci_dev *dev; | 374 | struct pci_dev *dev; |
374 | const char *type; | 375 | const char *type; |
376 | u32 class; | ||
375 | 377 | ||
376 | dev = kzalloc(sizeof(struct pci_dev), GFP_KERNEL); | 378 | dev = kzalloc(sizeof(struct pci_dev), GFP_KERNEL); |
377 | if (!dev) | 379 | if (!dev) |
@@ -409,7 +411,15 @@ struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm, | |||
409 | 411 | ||
410 | sprintf(pci_name(dev), "%04x:%02x:%02x.%d", pci_domain_nr(bus), | 412 | sprintf(pci_name(dev), "%04x:%02x:%02x.%d", pci_domain_nr(bus), |
411 | dev->bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn)); | 413 | dev->bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn)); |
412 | dev->class = of_getintprop_default(node, "class-code", 0); | 414 | |
415 | /* dev->class = of_getintprop_default(node, "class-code", 0); */ | ||
416 | /* We can't actually use the firmware value, we have to read what | ||
417 | * is in the register right now. One reason is that in the case | ||
418 | * of IDE interfaces the firmware can sample the value before the | ||
419 | * the IDE interface is programmed into native mode. | ||
420 | */ | ||
421 | pci_read_config_dword(dev, PCI_CLASS_REVISION, &class); | ||
422 | dev->class = class >> 8; | ||
413 | 423 | ||
414 | printk(" class: 0x%x\n", dev->class); | 424 | printk(" class: 0x%x\n", dev->class); |
415 | 425 | ||
@@ -440,6 +450,53 @@ struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm, | |||
440 | return dev; | 450 | return dev; |
441 | } | 451 | } |
442 | 452 | ||
453 | static void __init apb_calc_first_last(u8 map, u32 *first_p, u32 *last_p) | ||
454 | { | ||
455 | u32 idx, first, last; | ||
456 | |||
457 | first = 8; | ||
458 | last = 0; | ||
459 | for (idx = 0; idx < 8; idx++) { | ||
460 | if ((map & (1 << idx)) != 0) { | ||
461 | if (first > idx) | ||
462 | first = idx; | ||
463 | if (last < idx) | ||
464 | last = idx; | ||
465 | } | ||
466 | } | ||
467 | |||
468 | *first_p = first; | ||
469 | *last_p = last; | ||
470 | } | ||
471 | |||
472 | /* Cook up fake bus resources for SUNW,simba PCI bridges which lack | ||
473 | * a proper 'ranges' property. | ||
474 | */ | ||
475 | static void __init apb_fake_ranges(struct pci_dev *dev, | ||
476 | struct pci_bus *bus, | ||
477 | struct pci_pbm_info *pbm) | ||
478 | { | ||
479 | struct resource *res; | ||
480 | u32 first, last; | ||
481 | u8 map; | ||
482 | |||
483 | pci_read_config_byte(dev, APB_IO_ADDRESS_MAP, &map); | ||
484 | apb_calc_first_last(map, &first, &last); | ||
485 | res = bus->resource[0]; | ||
486 | res->start = (first << 21); | ||
487 | res->end = (last << 21) + ((1 << 21) - 1); | ||
488 | res->flags = IORESOURCE_IO; | ||
489 | pbm->parent->resource_adjust(dev, res, &pbm->io_space); | ||
490 | |||
491 | pci_read_config_byte(dev, APB_MEM_ADDRESS_MAP, &map); | ||
492 | apb_calc_first_last(map, &first, &last); | ||
493 | res = bus->resource[1]; | ||
494 | res->start = (first << 21); | ||
495 | res->end = (last << 21) + ((1 << 21) - 1); | ||
496 | res->flags = IORESOURCE_MEM; | ||
497 | pbm->parent->resource_adjust(dev, res, &pbm->mem_space); | ||
498 | } | ||
499 | |||
443 | static void __init pci_of_scan_bus(struct pci_pbm_info *pbm, | 500 | static void __init pci_of_scan_bus(struct pci_pbm_info *pbm, |
444 | struct device_node *node, | 501 | struct device_node *node, |
445 | struct pci_bus *bus); | 502 | struct pci_bus *bus); |
@@ -452,7 +509,7 @@ void __devinit of_scan_pci_bridge(struct pci_pbm_info *pbm, | |||
452 | { | 509 | { |
453 | struct pci_bus *bus; | 510 | struct pci_bus *bus; |
454 | const u32 *busrange, *ranges; | 511 | const u32 *busrange, *ranges; |
455 | int len, i; | 512 | int len, i, simba; |
456 | struct resource *res; | 513 | struct resource *res; |
457 | unsigned int flags; | 514 | unsigned int flags; |
458 | u64 size; | 515 | u64 size; |
@@ -467,10 +524,16 @@ void __devinit of_scan_pci_bridge(struct pci_pbm_info *pbm, | |||
467 | return; | 524 | return; |
468 | } | 525 | } |
469 | ranges = of_get_property(node, "ranges", &len); | 526 | ranges = of_get_property(node, "ranges", &len); |
527 | simba = 0; | ||
470 | if (ranges == NULL) { | 528 | if (ranges == NULL) { |
471 | printk(KERN_DEBUG "Can't get ranges for PCI-PCI bridge %s\n", | 529 | char *model = of_get_property(node, "model", NULL); |
472 | node->full_name); | 530 | if (model && !strcmp(model, "SUNW,simba")) { |
473 | return; | 531 | simba = 1; |
532 | } else { | ||
533 | printk(KERN_DEBUG "Can't get ranges for PCI-PCI bridge %s\n", | ||
534 | node->full_name); | ||
535 | return; | ||
536 | } | ||
474 | } | 537 | } |
475 | 538 | ||
476 | bus = pci_add_new_bus(dev->bus, dev, busrange[0]); | 539 | bus = pci_add_new_bus(dev->bus, dev, busrange[0]); |
@@ -484,7 +547,7 @@ void __devinit of_scan_pci_bridge(struct pci_pbm_info *pbm, | |||
484 | bus->subordinate = busrange[1]; | 547 | bus->subordinate = busrange[1]; |
485 | bus->bridge_ctl = 0; | 548 | bus->bridge_ctl = 0; |
486 | 549 | ||
487 | /* parse ranges property */ | 550 | /* parse ranges property, or cook one up by hand for Simba */ |
488 | /* PCI #address-cells == 3 and #size-cells == 2 always */ | 551 | /* PCI #address-cells == 3 and #size-cells == 2 always */ |
489 | res = &dev->resource[PCI_BRIDGE_RESOURCES]; | 552 | res = &dev->resource[PCI_BRIDGE_RESOURCES]; |
490 | for (i = 0; i < PCI_NUM_RESOURCES - PCI_BRIDGE_RESOURCES; ++i) { | 553 | for (i = 0; i < PCI_NUM_RESOURCES - PCI_BRIDGE_RESOURCES; ++i) { |
@@ -492,6 +555,10 @@ void __devinit of_scan_pci_bridge(struct pci_pbm_info *pbm, | |||
492 | bus->resource[i] = res; | 555 | bus->resource[i] = res; |
493 | ++res; | 556 | ++res; |
494 | } | 557 | } |
558 | if (simba) { | ||
559 | apb_fake_ranges(dev, bus, pbm); | ||
560 | goto simba_cont; | ||
561 | } | ||
495 | i = 1; | 562 | i = 1; |
496 | for (; len >= 32; len -= 32, ranges += 8) { | 563 | for (; len >= 32; len -= 32, ranges += 8) { |
497 | struct resource *root; | 564 | struct resource *root; |
@@ -529,6 +596,7 @@ void __devinit of_scan_pci_bridge(struct pci_pbm_info *pbm, | |||
529 | */ | 596 | */ |
530 | pbm->parent->resource_adjust(dev, res, root); | 597 | pbm->parent->resource_adjust(dev, res, root); |
531 | } | 598 | } |
599 | simba_cont: | ||
532 | sprintf(bus->name, "PCI Bus %04x:%02x", pci_domain_nr(bus), | 600 | sprintf(bus->name, "PCI Bus %04x:%02x", pci_domain_nr(bus), |
533 | bus->number); | 601 | bus->number); |
534 | printk(" bus name: %s\n", bus->name); | 602 | printk(" bus name: %s\n", bus->name); |
diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c index bbf624517508..f4e346092a53 100644 --- a/arch/sparc64/kernel/pci_sabre.c +++ b/arch/sparc64/kernel/pci_sabre.c | |||
@@ -254,9 +254,6 @@ static int __sabre_out_of_range(struct pci_pbm_info *pbm, | |||
254 | return 0; | 254 | return 0; |
255 | 255 | ||
256 | return ((pbm->parent == 0) || | 256 | return ((pbm->parent == 0) || |
257 | ((pbm == &pbm->parent->pbm_B) && | ||
258 | (bus == pbm->pci_first_busno) && | ||
259 | PCI_SLOT(devfn) > 8) || | ||
260 | ((pbm == &pbm->parent->pbm_A) && | 257 | ((pbm == &pbm->parent->pbm_A) && |
261 | (bus == pbm->pci_first_busno) && | 258 | (bus == pbm->pci_first_busno) && |
262 | PCI_SLOT(devfn) > 8)); | 259 | PCI_SLOT(devfn) > 8)); |
@@ -800,12 +797,10 @@ static irqreturn_t sabre_pcierr_intr(int irq, void *dev_id) | |||
800 | if (error_bits & (SABRE_PIOAFSR_PTA | SABRE_PIOAFSR_STA)) { | 797 | if (error_bits & (SABRE_PIOAFSR_PTA | SABRE_PIOAFSR_STA)) { |
801 | sabre_check_iommu_error(p, afsr, afar); | 798 | sabre_check_iommu_error(p, afsr, afar); |
802 | pci_scan_for_target_abort(p, &p->pbm_A, p->pbm_A.pci_bus); | 799 | pci_scan_for_target_abort(p, &p->pbm_A, p->pbm_A.pci_bus); |
803 | pci_scan_for_target_abort(p, &p->pbm_B, p->pbm_B.pci_bus); | ||
804 | } | 800 | } |
805 | if (error_bits & (SABRE_PIOAFSR_PMA | SABRE_PIOAFSR_SMA)) { | 801 | if (error_bits & (SABRE_PIOAFSR_PMA | SABRE_PIOAFSR_SMA)) |
806 | pci_scan_for_master_abort(p, &p->pbm_A, p->pbm_A.pci_bus); | 802 | pci_scan_for_master_abort(p, &p->pbm_A, p->pbm_A.pci_bus); |
807 | pci_scan_for_master_abort(p, &p->pbm_B, p->pbm_B.pci_bus); | 803 | |
808 | } | ||
809 | /* For excessive retries, SABRE/PBM will abort the device | 804 | /* For excessive retries, SABRE/PBM will abort the device |
810 | * and there is no way to specifically check for excessive | 805 | * and there is no way to specifically check for excessive |
811 | * retries in the config space status registers. So what | 806 | * retries in the config space status registers. So what |
@@ -813,10 +808,8 @@ static irqreturn_t sabre_pcierr_intr(int irq, void *dev_id) | |||
813 | * abort events. | 808 | * abort events. |
814 | */ | 809 | */ |
815 | 810 | ||
816 | if (error_bits & (SABRE_PIOAFSR_PPERR | SABRE_PIOAFSR_SPERR)) { | 811 | if (error_bits & (SABRE_PIOAFSR_PPERR | SABRE_PIOAFSR_SPERR)) |
817 | pci_scan_for_parity_error(p, &p->pbm_A, p->pbm_A.pci_bus); | 812 | pci_scan_for_parity_error(p, &p->pbm_A, p->pbm_A.pci_bus); |
818 | pci_scan_for_parity_error(p, &p->pbm_B, p->pbm_B.pci_bus); | ||
819 | } | ||
820 | 813 | ||
821 | return IRQ_HANDLED; | 814 | return IRQ_HANDLED; |
822 | } | 815 | } |
@@ -935,44 +928,33 @@ static void apb_init(struct pci_controller_info *p, struct pci_bus *sabre_bus) | |||
935 | struct pci_dev *pdev; | 928 | struct pci_dev *pdev; |
936 | 929 | ||
937 | list_for_each_entry(pdev, &sabre_bus->devices, bus_list) { | 930 | list_for_each_entry(pdev, &sabre_bus->devices, bus_list) { |
938 | |||
939 | if (pdev->vendor == PCI_VENDOR_ID_SUN && | 931 | if (pdev->vendor == PCI_VENDOR_ID_SUN && |
940 | pdev->device == PCI_DEVICE_ID_SUN_SIMBA) { | 932 | pdev->device == PCI_DEVICE_ID_SUN_SIMBA) { |
941 | u32 word32; | ||
942 | u16 word16; | 933 | u16 word16; |
943 | 934 | ||
944 | sabre_read_pci_cfg(pdev->bus, pdev->devfn, | 935 | pci_read_config_word(pdev, PCI_COMMAND, &word16); |
945 | PCI_COMMAND, 2, &word32); | ||
946 | word16 = (u16) word32; | ||
947 | word16 |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY | | 936 | word16 |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY | |
948 | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY | | 937 | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY | |
949 | PCI_COMMAND_IO; | 938 | PCI_COMMAND_IO; |
950 | word32 = (u32) word16; | 939 | pci_write_config_word(pdev, PCI_COMMAND, word16); |
951 | sabre_write_pci_cfg(pdev->bus, pdev->devfn, | ||
952 | PCI_COMMAND, 2, word32); | ||
953 | 940 | ||
954 | /* Status register bits are "write 1 to clear". */ | 941 | /* Status register bits are "write 1 to clear". */ |
955 | sabre_write_pci_cfg(pdev->bus, pdev->devfn, | 942 | pci_write_config_word(pdev, PCI_STATUS, 0xffff); |
956 | PCI_STATUS, 2, 0xffff); | 943 | pci_write_config_word(pdev, PCI_SEC_STATUS, 0xffff); |
957 | sabre_write_pci_cfg(pdev->bus, pdev->devfn, | ||
958 | PCI_SEC_STATUS, 2, 0xffff); | ||
959 | 944 | ||
960 | /* Use a primary/seconday latency timer value | 945 | /* Use a primary/seconday latency timer value |
961 | * of 64. | 946 | * of 64. |
962 | */ | 947 | */ |
963 | sabre_write_pci_cfg(pdev->bus, pdev->devfn, | 948 | pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64); |
964 | PCI_LATENCY_TIMER, 1, 64); | 949 | pci_write_config_byte(pdev, PCI_SEC_LATENCY_TIMER, 64); |
965 | sabre_write_pci_cfg(pdev->bus, pdev->devfn, | ||
966 | PCI_SEC_LATENCY_TIMER, 1, 64); | ||
967 | 950 | ||
968 | /* Enable reporting/forwarding of master aborts, | 951 | /* Enable reporting/forwarding of master aborts, |
969 | * parity, and SERR. | 952 | * parity, and SERR. |
970 | */ | 953 | */ |
971 | sabre_write_pci_cfg(pdev->bus, pdev->devfn, | 954 | pci_write_config_byte(pdev, PCI_BRIDGE_CONTROL, |
972 | PCI_BRIDGE_CONTROL, 1, | 955 | (PCI_BRIDGE_CTL_PARITY | |
973 | (PCI_BRIDGE_CTL_PARITY | | 956 | PCI_BRIDGE_CTL_SERR | |
974 | PCI_BRIDGE_CTL_SERR | | 957 | PCI_BRIDGE_CTL_MASTER_ABORT)); |
975 | PCI_BRIDGE_CTL_MASTER_ABORT)); | ||
976 | } | 958 | } |
977 | } | 959 | } |
978 | } | 960 | } |
@@ -980,16 +962,13 @@ static void apb_init(struct pci_controller_info *p, struct pci_bus *sabre_bus) | |||
980 | static void sabre_scan_bus(struct pci_controller_info *p) | 962 | static void sabre_scan_bus(struct pci_controller_info *p) |
981 | { | 963 | { |
982 | static int once; | 964 | static int once; |
983 | struct pci_bus *sabre_bus, *pbus; | 965 | struct pci_bus *pbus; |
984 | struct pci_pbm_info *pbm; | ||
985 | int sabres_scanned; | ||
986 | 966 | ||
987 | /* The APB bridge speaks to the Sabre host PCI bridge | 967 | /* The APB bridge speaks to the Sabre host PCI bridge |
988 | * at 66Mhz, but the front side of APB runs at 33Mhz | 968 | * at 66Mhz, but the front side of APB runs at 33Mhz |
989 | * for both segments. | 969 | * for both segments. |
990 | */ | 970 | */ |
991 | p->pbm_A.is_66mhz_capable = 0; | 971 | p->pbm_A.is_66mhz_capable = 0; |
992 | p->pbm_B.is_66mhz_capable = 0; | ||
993 | 972 | ||
994 | /* This driver has not been verified to handle | 973 | /* This driver has not been verified to handle |
995 | * multiple SABREs yet, so trap this. | 974 | * multiple SABREs yet, so trap this. |
@@ -1003,36 +982,13 @@ static void sabre_scan_bus(struct pci_controller_info *p) | |||
1003 | } | 982 | } |
1004 | once++; | 983 | once++; |
1005 | 984 | ||
1006 | sabre_bus = pci_scan_one_pbm(&p->pbm_A); | 985 | pbus = pci_scan_one_pbm(&p->pbm_A); |
1007 | if (!sabre_bus) | 986 | if (!pbus) |
1008 | return; | 987 | return; |
1009 | 988 | ||
1010 | sabre_root_bus = sabre_bus; | 989 | sabre_root_bus = pbus; |
1011 | |||
1012 | apb_init(p, sabre_bus); | ||
1013 | |||
1014 | sabres_scanned = 0; | ||
1015 | 990 | ||
1016 | list_for_each_entry(pbus, &sabre_bus->children, node) { | 991 | apb_init(p, pbus); |
1017 | |||
1018 | if (pbus->number == p->pbm_A.pci_first_busno) { | ||
1019 | pbm = &p->pbm_A; | ||
1020 | } else if (pbus->number == p->pbm_B.pci_first_busno) { | ||
1021 | pbm = &p->pbm_B; | ||
1022 | } else | ||
1023 | continue; | ||
1024 | |||
1025 | sabres_scanned++; | ||
1026 | pbus->sysdata = pbm; | ||
1027 | pbm->pci_bus = pbus; | ||
1028 | } | ||
1029 | |||
1030 | if (!sabres_scanned) { | ||
1031 | /* Hummingbird, no APBs. */ | ||
1032 | pbm = &p->pbm_A; | ||
1033 | sabre_bus->sysdata = pbm; | ||
1034 | pbm->pci_bus = sabre_bus; | ||
1035 | } | ||
1036 | 992 | ||
1037 | sabre_register_error_handlers(p); | 993 | sabre_register_error_handlers(p); |
1038 | } | 994 | } |
@@ -1089,213 +1045,54 @@ static void sabre_iommu_init(struct pci_controller_info *p, | |||
1089 | sabre_write(p->pbm_A.controller_regs + SABRE_IOMMU_CONTROL, control); | 1045 | sabre_write(p->pbm_A.controller_regs + SABRE_IOMMU_CONTROL, control); |
1090 | } | 1046 | } |
1091 | 1047 | ||
1092 | static void pbm_register_toplevel_resources(struct pci_controller_info *p, | 1048 | static void sabre_pbm_init(struct pci_controller_info *p, struct device_node *dp, u32 dma_start, u32 dma_end) |
1093 | struct pci_pbm_info *pbm) | ||
1094 | { | 1049 | { |
1095 | char *name = pbm->name; | 1050 | struct pci_pbm_info *pbm; |
1096 | unsigned long ibase = p->pbm_A.controller_regs + SABRE_IOSPACE; | 1051 | struct resource *rp; |
1097 | unsigned long mbase = p->pbm_A.controller_regs + SABRE_MEMSPACE; | 1052 | |
1098 | unsigned int devfn; | 1053 | pbm = &p->pbm_A; |
1099 | unsigned long first, last, i; | 1054 | pbm->name = dp->full_name; |
1100 | u8 *addr, map; | 1055 | printk("%s: SABRE PCI Bus Module\n", pbm->name); |
1101 | 1056 | ||
1102 | sprintf(name, "SABRE%d PBM%c", | 1057 | pbm->chip_type = PBM_CHIP_TYPE_SABRE; |
1103 | p->index, | 1058 | pbm->parent = p; |
1104 | (pbm == &p->pbm_A ? 'A' : 'B')); | 1059 | pbm->prom_node = dp; |
1105 | pbm->io_space.name = pbm->mem_space.name = name; | 1060 | pbm->pci_first_slot = 1; |
1106 | 1061 | pbm->pci_first_busno = p->pci_first_busno; | |
1107 | devfn = PCI_DEVFN(1, (pbm == &p->pbm_A) ? 0 : 1); | 1062 | pbm->pci_last_busno = p->pci_last_busno; |
1108 | addr = sabre_pci_config_mkaddr(pbm, 0, devfn, APB_IO_ADDRESS_MAP); | 1063 | |
1109 | map = 0; | 1064 | pbm->io_space.name = pbm->mem_space.name = pbm->name; |
1110 | pci_config_read8(addr, &map); | 1065 | |
1111 | 1066 | pbm->io_space.start = p->pbm_A.controller_regs + SABRE_IOSPACE; | |
1112 | first = 8; | 1067 | pbm->io_space.end = pbm->io_space.start + (1UL << 24) - 1UL; |
1113 | last = 0; | ||
1114 | for (i = 0; i < 8; i++) { | ||
1115 | if ((map & (1 << i)) != 0) { | ||
1116 | if (first > i) | ||
1117 | first = i; | ||
1118 | if (last < i) | ||
1119 | last = i; | ||
1120 | } | ||
1121 | } | ||
1122 | pbm->io_space.start = ibase + (first << 21UL); | ||
1123 | pbm->io_space.end = ibase + (last << 21UL) + ((1 << 21UL) - 1); | ||
1124 | pbm->io_space.flags = IORESOURCE_IO; | 1068 | pbm->io_space.flags = IORESOURCE_IO; |
1125 | 1069 | ||
1126 | addr = sabre_pci_config_mkaddr(pbm, 0, devfn, APB_MEM_ADDRESS_MAP); | 1070 | pbm->mem_space.start = (p->pbm_A.controller_regs + SABRE_MEMSPACE); |
1127 | map = 0; | 1071 | pbm->mem_space.end = (pbm->mem_space.start + ((1UL << 32UL) - 1UL)); |
1128 | pci_config_read8(addr, &map); | ||
1129 | |||
1130 | first = 8; | ||
1131 | last = 0; | ||
1132 | for (i = 0; i < 8; i++) { | ||
1133 | if ((map & (1 << i)) != 0) { | ||
1134 | if (first > i) | ||
1135 | first = i; | ||
1136 | if (last < i) | ||
1137 | last = i; | ||
1138 | } | ||
1139 | } | ||
1140 | pbm->mem_space.start = mbase + (first << 29UL); | ||
1141 | pbm->mem_space.end = mbase + (last << 29UL) + ((1 << 29UL) - 1); | ||
1142 | pbm->mem_space.flags = IORESOURCE_MEM; | 1072 | pbm->mem_space.flags = IORESOURCE_MEM; |
1143 | 1073 | ||
1144 | if (request_resource(&ioport_resource, &pbm->io_space) < 0) { | 1074 | if (request_resource(&ioport_resource, &pbm->io_space) < 0) { |
1145 | prom_printf("Cannot register PBM-%c's IO space.\n", | 1075 | prom_printf("Cannot register Sabre's IO space.\n"); |
1146 | (pbm == &p->pbm_A ? 'A' : 'B')); | ||
1147 | prom_halt(); | 1076 | prom_halt(); |
1148 | } | 1077 | } |
1149 | if (request_resource(&iomem_resource, &pbm->mem_space) < 0) { | 1078 | if (request_resource(&iomem_resource, &pbm->mem_space) < 0) { |
1150 | prom_printf("Cannot register PBM-%c's MEM space.\n", | 1079 | prom_printf("Cannot register Sabre's MEM space.\n"); |
1151 | (pbm == &p->pbm_A ? 'A' : 'B')); | ||
1152 | prom_halt(); | 1080 | prom_halt(); |
1153 | } | 1081 | } |
1154 | 1082 | ||
1155 | /* Register legacy regions if this PBM covers that area. */ | 1083 | rp = kmalloc(sizeof(*rp), GFP_KERNEL); |
1156 | if (pbm->io_space.start == ibase && | 1084 | if (!rp) { |
1157 | pbm->mem_space.start == mbase) | 1085 | prom_printf("Cannot allocate IOMMU resource.\n"); |
1158 | pci_register_legacy_regions(&pbm->io_space, | 1086 | prom_halt(); |
1159 | &pbm->mem_space); | ||
1160 | } | ||
1161 | |||
1162 | static void sabre_pbm_init(struct pci_controller_info *p, struct device_node *dp, u32 dma_start, u32 dma_end) | ||
1163 | { | ||
1164 | struct pci_pbm_info *pbm; | ||
1165 | struct device_node *node; | ||
1166 | struct property *prop; | ||
1167 | u32 *busrange; | ||
1168 | int len, simbas_found; | ||
1169 | |||
1170 | simbas_found = 0; | ||
1171 | node = dp->child; | ||
1172 | while (node != NULL) { | ||
1173 | if (strcmp(node->name, "pci")) | ||
1174 | goto next_pci; | ||
1175 | |||
1176 | prop = of_find_property(node, "model", NULL); | ||
1177 | if (!prop || strncmp(prop->value, "SUNW,simba", prop->length)) | ||
1178 | goto next_pci; | ||
1179 | |||
1180 | simbas_found++; | ||
1181 | |||
1182 | prop = of_find_property(node, "bus-range", NULL); | ||
1183 | busrange = prop->value; | ||
1184 | if (busrange[0] == 1) | ||
1185 | pbm = &p->pbm_B; | ||
1186 | else | ||
1187 | pbm = &p->pbm_A; | ||
1188 | |||
1189 | pbm->name = node->full_name; | ||
1190 | printk("%s: SABRE PCI Bus Module\n", pbm->name); | ||
1191 | |||
1192 | pbm->chip_type = PBM_CHIP_TYPE_SABRE; | ||
1193 | pbm->parent = p; | ||
1194 | pbm->prom_node = node; | ||
1195 | pbm->pci_first_slot = 1; | ||
1196 | pbm->pci_first_busno = busrange[0]; | ||
1197 | pbm->pci_last_busno = busrange[1]; | ||
1198 | |||
1199 | prop = of_find_property(node, "ranges", &len); | ||
1200 | if (prop) { | ||
1201 | pbm->pbm_ranges = prop->value; | ||
1202 | pbm->num_pbm_ranges = | ||
1203 | (len / sizeof(struct linux_prom_pci_ranges)); | ||
1204 | } else { | ||
1205 | pbm->num_pbm_ranges = 0; | ||
1206 | } | ||
1207 | |||
1208 | prop = of_find_property(node, "interrupt-map", &len); | ||
1209 | if (prop) { | ||
1210 | pbm->pbm_intmap = prop->value; | ||
1211 | pbm->num_pbm_intmap = | ||
1212 | (len / sizeof(struct linux_prom_pci_intmap)); | ||
1213 | |||
1214 | prop = of_find_property(node, "interrupt-map-mask", | ||
1215 | NULL); | ||
1216 | pbm->pbm_intmask = prop->value; | ||
1217 | } else { | ||
1218 | pbm->num_pbm_intmap = 0; | ||
1219 | } | ||
1220 | |||
1221 | pbm_register_toplevel_resources(p, pbm); | ||
1222 | |||
1223 | next_pci: | ||
1224 | node = node->sibling; | ||
1225 | } | ||
1226 | if (simbas_found == 0) { | ||
1227 | struct resource *rp; | ||
1228 | |||
1229 | /* No APBs underneath, probably this is a hummingbird | ||
1230 | * system. | ||
1231 | */ | ||
1232 | pbm = &p->pbm_A; | ||
1233 | pbm->parent = p; | ||
1234 | pbm->prom_node = dp; | ||
1235 | pbm->pci_first_busno = p->pci_first_busno; | ||
1236 | pbm->pci_last_busno = p->pci_last_busno; | ||
1237 | |||
1238 | prop = of_find_property(dp, "ranges", &len); | ||
1239 | if (prop) { | ||
1240 | pbm->pbm_ranges = prop->value; | ||
1241 | pbm->num_pbm_ranges = | ||
1242 | (len / sizeof(struct linux_prom_pci_ranges)); | ||
1243 | } else { | ||
1244 | pbm->num_pbm_ranges = 0; | ||
1245 | } | ||
1246 | |||
1247 | prop = of_find_property(dp, "interrupt-map", &len); | ||
1248 | if (prop) { | ||
1249 | pbm->pbm_intmap = prop->value; | ||
1250 | pbm->num_pbm_intmap = | ||
1251 | (len / sizeof(struct linux_prom_pci_intmap)); | ||
1252 | |||
1253 | prop = of_find_property(dp, "interrupt-map-mask", | ||
1254 | NULL); | ||
1255 | pbm->pbm_intmask = prop->value; | ||
1256 | } else { | ||
1257 | pbm->num_pbm_intmap = 0; | ||
1258 | } | ||
1259 | |||
1260 | pbm->name = dp->full_name; | ||
1261 | printk("%s: SABRE PCI Bus Module\n", pbm->name); | ||
1262 | |||
1263 | pbm->io_space.name = pbm->mem_space.name = pbm->name; | ||
1264 | |||
1265 | /* Hack up top-level resources. */ | ||
1266 | pbm->io_space.start = p->pbm_A.controller_regs + SABRE_IOSPACE; | ||
1267 | pbm->io_space.end = pbm->io_space.start + (1UL << 24) - 1UL; | ||
1268 | pbm->io_space.flags = IORESOURCE_IO; | ||
1269 | |||
1270 | pbm->mem_space.start = | ||
1271 | (p->pbm_A.controller_regs + SABRE_MEMSPACE); | ||
1272 | pbm->mem_space.end = | ||
1273 | (pbm->mem_space.start + ((1UL << 32UL) - 1UL)); | ||
1274 | pbm->mem_space.flags = IORESOURCE_MEM; | ||
1275 | |||
1276 | if (request_resource(&ioport_resource, &pbm->io_space) < 0) { | ||
1277 | prom_printf("Cannot register Hummingbird's IO space.\n"); | ||
1278 | prom_halt(); | ||
1279 | } | ||
1280 | if (request_resource(&iomem_resource, &pbm->mem_space) < 0) { | ||
1281 | prom_printf("Cannot register Hummingbird's MEM space.\n"); | ||
1282 | prom_halt(); | ||
1283 | } | ||
1284 | |||
1285 | rp = kmalloc(sizeof(*rp), GFP_KERNEL); | ||
1286 | if (!rp) { | ||
1287 | prom_printf("Cannot allocate IOMMU resource.\n"); | ||
1288 | prom_halt(); | ||
1289 | } | ||
1290 | rp->name = "IOMMU"; | ||
1291 | rp->start = pbm->mem_space.start + (unsigned long) dma_start; | ||
1292 | rp->end = pbm->mem_space.start + (unsigned long) dma_end - 1UL; | ||
1293 | rp->flags = IORESOURCE_BUSY; | ||
1294 | request_resource(&pbm->mem_space, rp); | ||
1295 | |||
1296 | pci_register_legacy_regions(&pbm->io_space, | ||
1297 | &pbm->mem_space); | ||
1298 | } | 1087 | } |
1088 | rp->name = "IOMMU"; | ||
1089 | rp->start = pbm->mem_space.start + (unsigned long) dma_start; | ||
1090 | rp->end = pbm->mem_space.start + (unsigned long) dma_end - 1UL; | ||
1091 | rp->flags = IORESOURCE_BUSY; | ||
1092 | request_resource(&pbm->mem_space, rp); | ||
1093 | |||
1094 | pci_register_legacy_regions(&pbm->io_space, | ||
1095 | &pbm->mem_space); | ||
1299 | } | 1096 | } |
1300 | 1097 | ||
1301 | void sabre_init(struct device_node *dp, char *model_name) | 1098 | void sabre_init(struct device_node *dp, char *model_name) |
@@ -1303,7 +1100,6 @@ void sabre_init(struct device_node *dp, char *model_name) | |||
1303 | struct linux_prom64_registers *pr_regs; | 1100 | struct linux_prom64_registers *pr_regs; |
1304 | struct pci_controller_info *p; | 1101 | struct pci_controller_info *p; |
1305 | struct pci_iommu *iommu; | 1102 | struct pci_iommu *iommu; |
1306 | struct property *prop; | ||
1307 | int tsbsize; | 1103 | int tsbsize; |
1308 | u32 *busrange; | 1104 | u32 *busrange; |
1309 | u32 *vdma; | 1105 | u32 *vdma; |
@@ -1314,13 +1110,9 @@ void sabre_init(struct device_node *dp, char *model_name) | |||
1314 | if (!strcmp(model_name, "pci108e,a001")) | 1110 | if (!strcmp(model_name, "pci108e,a001")) |
1315 | hummingbird_p = 1; | 1111 | hummingbird_p = 1; |
1316 | else if (!strcmp(model_name, "SUNW,sabre")) { | 1112 | else if (!strcmp(model_name, "SUNW,sabre")) { |
1317 | prop = of_find_property(dp, "compatible", NULL); | 1113 | const char *compat = of_get_property(dp, "compatible", NULL); |
1318 | if (prop) { | 1114 | if (compat && !strcmp(compat, "pci108e,a001")) |
1319 | const char *compat = prop->value; | 1115 | hummingbird_p = 1; |
1320 | |||
1321 | if (!strcmp(compat, "pci108e,a001")) | ||
1322 | hummingbird_p = 1; | ||
1323 | } | ||
1324 | if (!hummingbird_p) { | 1116 | if (!hummingbird_p) { |
1325 | struct device_node *dp; | 1117 | struct device_node *dp; |
1326 | 1118 | ||
@@ -1344,18 +1136,14 @@ void sabre_init(struct device_node *dp, char *model_name) | |||
1344 | prom_printf("SABRE: Error, kmalloc(pci_iommu) failed.\n"); | 1136 | prom_printf("SABRE: Error, kmalloc(pci_iommu) failed.\n"); |
1345 | prom_halt(); | 1137 | prom_halt(); |
1346 | } | 1138 | } |
1347 | p->pbm_A.iommu = p->pbm_B.iommu = iommu; | 1139 | p->pbm_A.iommu = iommu; |
1348 | 1140 | ||
1349 | upa_portid = 0xff; | 1141 | upa_portid = of_getintprop_default(dp, "upa-portid", 0xff); |
1350 | prop = of_find_property(dp, "upa-portid", NULL); | ||
1351 | if (prop) | ||
1352 | upa_portid = *(u32 *) prop->value; | ||
1353 | 1142 | ||
1354 | p->next = pci_controller_root; | 1143 | p->next = pci_controller_root; |
1355 | pci_controller_root = p; | 1144 | pci_controller_root = p; |
1356 | 1145 | ||
1357 | p->pbm_A.portid = upa_portid; | 1146 | p->pbm_A.portid = upa_portid; |
1358 | p->pbm_B.portid = upa_portid; | ||
1359 | p->index = pci_num_controllers++; | 1147 | p->index = pci_num_controllers++; |
1360 | p->pbms_same_domain = 1; | 1148 | p->pbms_same_domain = 1; |
1361 | p->scan_bus = sabre_scan_bus; | 1149 | p->scan_bus = sabre_scan_bus; |
@@ -1367,14 +1155,12 @@ void sabre_init(struct device_node *dp, char *model_name) | |||
1367 | * Map in SABRE register set and report the presence of this SABRE. | 1155 | * Map in SABRE register set and report the presence of this SABRE. |
1368 | */ | 1156 | */ |
1369 | 1157 | ||
1370 | prop = of_find_property(dp, "reg", NULL); | 1158 | pr_regs = of_get_property(dp, "reg", NULL); |
1371 | pr_regs = prop->value; | ||
1372 | 1159 | ||
1373 | /* | 1160 | /* |
1374 | * First REG in property is base of entire SABRE register space. | 1161 | * First REG in property is base of entire SABRE register space. |
1375 | */ | 1162 | */ |
1376 | p->pbm_A.controller_regs = pr_regs[0].phys_addr; | 1163 | p->pbm_A.controller_regs = pr_regs[0].phys_addr; |
1377 | p->pbm_B.controller_regs = pr_regs[0].phys_addr; | ||
1378 | 1164 | ||
1379 | /* Clear interrupts */ | 1165 | /* Clear interrupts */ |
1380 | 1166 | ||
@@ -1392,11 +1178,10 @@ void sabre_init(struct device_node *dp, char *model_name) | |||
1392 | SABRE_PCICTRL_ARBPARK | SABRE_PCICTRL_AEN)); | 1178 | SABRE_PCICTRL_ARBPARK | SABRE_PCICTRL_AEN)); |
1393 | 1179 | ||
1394 | /* Now map in PCI config space for entire SABRE. */ | 1180 | /* Now map in PCI config space for entire SABRE. */ |
1395 | p->pbm_A.config_space = p->pbm_B.config_space = | 1181 | p->pbm_A.config_space = |
1396 | (p->pbm_A.controller_regs + SABRE_CONFIGSPACE); | 1182 | (p->pbm_A.controller_regs + SABRE_CONFIGSPACE); |
1397 | 1183 | ||
1398 | prop = of_find_property(dp, "virtual-dma", NULL); | 1184 | vdma = of_get_property(dp, "virtual-dma", NULL); |
1399 | vdma = prop->value; | ||
1400 | 1185 | ||
1401 | dma_mask = vdma[0]; | 1186 | dma_mask = vdma[0]; |
1402 | switch(vdma[1]) { | 1187 | switch(vdma[1]) { |
@@ -1420,8 +1205,7 @@ void sabre_init(struct device_node *dp, char *model_name) | |||
1420 | 1205 | ||
1421 | sabre_iommu_init(p, tsbsize, vdma[0], dma_mask); | 1206 | sabre_iommu_init(p, tsbsize, vdma[0], dma_mask); |
1422 | 1207 | ||
1423 | prop = of_find_property(dp, "bus-range", NULL); | 1208 | busrange = of_get_property(dp, "bus-range", NULL); |
1424 | busrange = prop->value; | ||
1425 | p->pci_first_busno = busrange[0]; | 1209 | p->pci_first_busno = busrange[0]; |
1426 | p->pci_last_busno = busrange[1]; | 1210 | p->pci_last_busno = busrange[1]; |
1427 | 1211 | ||