diff options
author | David S. Miller <davem@ultra5.davemloft.net> | 2007-03-04 15:53:19 -0500 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-04-26 04:55:10 -0400 |
commit | 01f94c4a6ced476ce69b895426fc29bfc48c69bd (patch) | |
tree | 68866108644a1e90ae7688d2e35cb8462ab6a07c | |
parent | a378fd0ee8ea6af5dafd0ab3d634f22b926b5ac4 (diff) |
[SPARC64]: Fix sabre pci controllers with new probing scheme.
The SIMBA APB bridge is strange, it is a PCI bridge but it lacks
some standard OF properties, in particular it lacks a 'ranges'
property.
What you have to do is read the IO and MEM range registers in
the APB bridge to determine the ranges handled by each bridge.
So fill in the bus resources by doing that.
Since we now handle this quirk in the generic PCI and OF device
probing layers, we can flat out eliminate all of that code from
the sabre pci controller driver.
In fact we can thus eliminate completely another quirk of the sabre
driver. It tried to make the two APB bridges look like PBMs but that
makes zero sense now (and it's questionable whether it ever made sense).
So now just use pbm_A and probe the whole PCI hierarchy using that as
the root.
This simplification allows many future cleanups to occur.
Also, I've found yet another quirk that needs to be worked around
while testing this. You can't use the 'class-code' OF firmware
property, especially for IDE controllers. We have to read the value
out of PCI config space or else we'll see the value the device was
showing before it was programmed into native mode.
I'm starting to think it might be wise to just read all of the values
out of PCI config space instead of using the OF properties. :-/
Signed-off-by: David S. Miller <davem@davemloft.net>
-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 | ||