aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc64/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc64/kernel')
-rw-r--r--arch/sparc64/kernel/of_device.c19
-rw-r--r--arch/sparc64/kernel/pci.c97
2 files changed, 103 insertions, 13 deletions
diff --git a/arch/sparc64/kernel/of_device.c b/arch/sparc64/kernel/of_device.c
index 16cc46a71872..6676b93219dc 100644
--- a/arch/sparc64/kernel/of_device.c
+++ b/arch/sparc64/kernel/of_device.c
@@ -343,6 +343,15 @@ static int of_bus_simba_match(struct device_node *np)
343 343
344 if (model && !strcmp(model, "SUNW,simba")) 344 if (model && !strcmp(model, "SUNW,simba"))
345 return 1; 345 return 1;
346
347 /* Treat PCI busses lacking ranges property just like
348 * simba.
349 */
350 if (!strcmp(np->type, "pci") || !strcmp(np->type, "pciex")) {
351 if (!of_find_property(np, "ranges", NULL))
352 return 1;
353 }
354
346 return 0; 355 return 0;
347} 356}
348 357
@@ -549,8 +558,6 @@ static int __init build_one_resource(struct device_node *parent,
549 558
550static int __init use_1to1_mapping(struct device_node *pp) 559static int __init use_1to1_mapping(struct device_node *pp)
551{ 560{
552 const char *model;
553
554 /* If this is on the PMU bus, don't try to translate it even 561 /* If this is on the PMU bus, don't try to translate it even
555 * if a ranges property exists. 562 * if a ranges property exists.
556 */ 563 */
@@ -567,9 +574,11 @@ static int __init use_1to1_mapping(struct device_node *pp)
567 if (!strcmp(pp->name, "dma")) 574 if (!strcmp(pp->name, "dma"))
568 return 0; 575 return 0;
569 576
570 /* Similarly for Simba PCI bridges. */ 577 /* Similarly for all PCI bridges, if we get this far
571 model = of_get_property(pp, "model", NULL); 578 * it lacks a ranges property, and this will include
572 if (model && !strcmp(model, "SUNW,simba")) 579 * cases like Simba.
580 */
581 if (!strcmp(pp->type, "pci") || !strcmp(pp->type, "pciex"))
573 return 0; 582 return 0;
574 583
575 return 1; 584 return 1;
diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c
index 38a32bc95d22..81f4a5ea05f7 100644
--- a/arch/sparc64/kernel/pci.c
+++ b/arch/sparc64/kernel/pci.c
@@ -522,6 +522,89 @@ static void pci_resource_adjust(struct resource *res,
522 res->end += root->start; 522 res->end += root->start;
523} 523}
524 524
525/* For PCI bus devices which lack a 'ranges' property we interrogate
526 * the config space values to set the resources, just like the generic
527 * Linux PCI probing code does.
528 */
529static void __devinit pci_cfg_fake_ranges(struct pci_dev *dev,
530 struct pci_bus *bus,
531 struct pci_pbm_info *pbm)
532{
533 struct resource *res;
534 u8 io_base_lo, io_limit_lo;
535 u16 mem_base_lo, mem_limit_lo;
536 unsigned long base, limit;
537
538 pci_read_config_byte(dev, PCI_IO_BASE, &io_base_lo);
539 pci_read_config_byte(dev, PCI_IO_LIMIT, &io_limit_lo);
540 base = (io_base_lo & PCI_IO_RANGE_MASK) << 8;
541 limit = (io_limit_lo & PCI_IO_RANGE_MASK) << 8;
542
543 if ((io_base_lo & PCI_IO_RANGE_TYPE_MASK) == PCI_IO_RANGE_TYPE_32) {
544 u16 io_base_hi, io_limit_hi;
545
546 pci_read_config_word(dev, PCI_IO_BASE_UPPER16, &io_base_hi);
547 pci_read_config_word(dev, PCI_IO_LIMIT_UPPER16, &io_limit_hi);
548 base |= (io_base_hi << 16);
549 limit |= (io_limit_hi << 16);
550 }
551
552 res = bus->resource[0];
553 if (base <= limit) {
554 res->flags = (io_base_lo & PCI_IO_RANGE_TYPE_MASK) | IORESOURCE_IO;
555 if (!res->start)
556 res->start = base;
557 if (!res->end)
558 res->end = limit + 0xfff;
559 pci_resource_adjust(res, &pbm->io_space);
560 }
561
562 pci_read_config_word(dev, PCI_MEMORY_BASE, &mem_base_lo);
563 pci_read_config_word(dev, PCI_MEMORY_LIMIT, &mem_limit_lo);
564 base = (mem_base_lo & PCI_MEMORY_RANGE_MASK) << 16;
565 limit = (mem_limit_lo & PCI_MEMORY_RANGE_MASK) << 16;
566
567 res = bus->resource[1];
568 if (base <= limit) {
569 res->flags = ((mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) |
570 IORESOURCE_MEM);
571 res->start = base;
572 res->end = limit + 0xfffff;
573 pci_resource_adjust(res, &pbm->mem_space);
574 }
575
576 pci_read_config_word(dev, PCI_PREF_MEMORY_BASE, &mem_base_lo);
577 pci_read_config_word(dev, PCI_PREF_MEMORY_LIMIT, &mem_limit_lo);
578 base = (mem_base_lo & PCI_PREF_RANGE_MASK) << 16;
579 limit = (mem_limit_lo & PCI_PREF_RANGE_MASK) << 16;
580
581 if ((mem_base_lo & PCI_PREF_RANGE_TYPE_MASK) == PCI_PREF_RANGE_TYPE_64) {
582 u32 mem_base_hi, mem_limit_hi;
583
584 pci_read_config_dword(dev, PCI_PREF_BASE_UPPER32, &mem_base_hi);
585 pci_read_config_dword(dev, PCI_PREF_LIMIT_UPPER32, &mem_limit_hi);
586
587 /*
588 * Some bridges set the base > limit by default, and some
589 * (broken) BIOSes do not initialize them. If we find
590 * this, just assume they are not being used.
591 */
592 if (mem_base_hi <= mem_limit_hi) {
593 base |= ((long) mem_base_hi) << 32;
594 limit |= ((long) mem_limit_hi) << 32;
595 }
596 }
597
598 res = bus->resource[2];
599 if (base <= limit) {
600 res->flags = ((mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) |
601 IORESOURCE_MEM | IORESOURCE_PREFETCH);
602 res->start = base;
603 res->end = limit + 0xfffff;
604 pci_resource_adjust(res, &pbm->mem_space);
605 }
606}
607
525/* Cook up fake bus resources for SUNW,simba PCI bridges which lack 608/* Cook up fake bus resources for SUNW,simba PCI bridges which lack
526 * a proper 'ranges' property. 609 * a proper 'ranges' property.
527 */ 610 */
@@ -581,13 +664,8 @@ static void __devinit of_scan_pci_bridge(struct pci_pbm_info *pbm,
581 simba = 0; 664 simba = 0;
582 if (ranges == NULL) { 665 if (ranges == NULL) {
583 const char *model = of_get_property(node, "model", NULL); 666 const char *model = of_get_property(node, "model", NULL);
584 if (model && !strcmp(model, "SUNW,simba")) { 667 if (model && !strcmp(model, "SUNW,simba"))
585 simba = 1; 668 simba = 1;
586 } else {
587 printk(KERN_DEBUG "Can't get ranges for PCI-PCI bridge %s\n",
588 node->full_name);
589 return;
590 }
591 } 669 }
592 670
593 bus = pci_add_new_bus(dev->bus, dev, busrange[0]); 671 bus = pci_add_new_bus(dev->bus, dev, busrange[0]);
@@ -611,7 +689,10 @@ static void __devinit of_scan_pci_bridge(struct pci_pbm_info *pbm,
611 } 689 }
612 if (simba) { 690 if (simba) {
613 apb_fake_ranges(dev, bus, pbm); 691 apb_fake_ranges(dev, bus, pbm);
614 goto simba_cont; 692 goto after_ranges;
693 } else if (ranges == NULL) {
694 pci_cfg_fake_ranges(dev, bus, pbm);
695 goto after_ranges;
615 } 696 }
616 i = 1; 697 i = 1;
617 for (; len >= 32; len -= 32, ranges += 8) { 698 for (; len >= 32; len -= 32, ranges += 8) {
@@ -650,7 +731,7 @@ static void __devinit of_scan_pci_bridge(struct pci_pbm_info *pbm,
650 */ 731 */
651 pci_resource_adjust(res, root); 732 pci_resource_adjust(res, root);
652 } 733 }
653simba_cont: 734after_ranges:
654 sprintf(bus->name, "PCI Bus %04x:%02x", pci_domain_nr(bus), 735 sprintf(bus->name, "PCI Bus %04x:%02x", pci_domain_nr(bus),
655 bus->number); 736 bus->number);
656 if (ofpci_verbose) 737 if (ofpci_verbose)