diff options
author | David S. Miller <davem@sunset.davemloft.net> | 2007-03-11 19:42:53 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-04-26 04:55:19 -0400 |
commit | 97b3cf050b467dda571943ceadff5452bed04549 (patch) | |
tree | c5dbb828eb40f84d6203cfd5aaa56f12c4548b71 /arch | |
parent | c6e87566ea080bbbe926c0e429fed48e6f680d93 (diff) |
[SPARC64]: Add dummy host controller to root of all PCI domains.
We fake up a dummy one in all cases because that is the simplest
thing to do and it happens to be necessary for hypervisor systems.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/sparc64/kernel/pci.c | 119 | ||||
-rw-r--r-- | arch/sparc64/kernel/pci_impl.h | 9 | ||||
-rw-r--r-- | arch/sparc64/kernel/pci_psycho.c | 7 | ||||
-rw-r--r-- | arch/sparc64/kernel/pci_sabre.c | 12 | ||||
-rw-r--r-- | arch/sparc64/kernel/pci_schizo.c | 6 | ||||
-rw-r--r-- | arch/sparc64/kernel/pci_sun4v.c | 6 |
6 files changed, 129 insertions, 30 deletions
diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index 914a216da339..ec5f85b030ef 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c | |||
@@ -368,7 +368,8 @@ static void pci_parse_of_addrs(struct of_device *op, | |||
368 | 368 | ||
369 | struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm, | 369 | struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm, |
370 | struct device_node *node, | 370 | struct device_node *node, |
371 | struct pci_bus *bus, int devfn) | 371 | struct pci_bus *bus, int devfn, |
372 | int host_controller) | ||
372 | { | 373 | { |
373 | struct dev_archdata *sd; | 374 | struct dev_archdata *sd; |
374 | struct pci_dev *dev; | 375 | struct pci_dev *dev; |
@@ -400,47 +401,62 @@ struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm, | |||
400 | dev->devfn = devfn; | 401 | dev->devfn = devfn; |
401 | dev->multifunction = 0; /* maybe a lie? */ | 402 | dev->multifunction = 0; /* maybe a lie? */ |
402 | 403 | ||
403 | dev->vendor = of_getintprop_default(node, "vendor-id", 0xffff); | 404 | if (host_controller) { |
404 | dev->device = of_getintprop_default(node, "device-id", 0xffff); | 405 | dev->vendor = 0x108e; |
405 | dev->subsystem_vendor = | 406 | dev->device = 0x8000; |
406 | of_getintprop_default(node, "subsystem-vendor-id", 0); | 407 | dev->subsystem_vendor = 0x0000; |
407 | dev->subsystem_device = | 408 | dev->subsystem_device = 0x0000; |
408 | of_getintprop_default(node, "subsystem-id", 0); | 409 | dev->cfg_size = 256; |
409 | 410 | } else { | |
410 | dev->cfg_size = pci_cfg_space_size(dev); | 411 | dev->vendor = of_getintprop_default(node, "vendor-id", 0xffff); |
411 | 412 | dev->device = of_getintprop_default(node, "device-id", 0xffff); | |
413 | dev->subsystem_vendor = | ||
414 | of_getintprop_default(node, "subsystem-vendor-id", 0); | ||
415 | dev->subsystem_device = | ||
416 | of_getintprop_default(node, "subsystem-id", 0); | ||
417 | |||
418 | dev->cfg_size = pci_cfg_space_size(dev); | ||
419 | } | ||
412 | sprintf(pci_name(dev), "%04x:%02x:%02x.%d", pci_domain_nr(bus), | 420 | sprintf(pci_name(dev), "%04x:%02x:%02x.%d", pci_domain_nr(bus), |
413 | dev->bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn)); | 421 | dev->bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn)); |
414 | 422 | ||
415 | /* dev->class = of_getintprop_default(node, "class-code", 0); */ | 423 | if (host_controller) { |
416 | /* We can't actually use the firmware value, we have to read what | 424 | dev->class = PCI_CLASS_BRIDGE_HOST << 8; |
417 | * is in the register right now. One reason is that in the case | 425 | } else { |
418 | * of IDE interfaces the firmware can sample the value before the | 426 | /* We can't actually use the firmware value, we have |
419 | * the IDE interface is programmed into native mode. | 427 | * to read what is in the register right now. One |
420 | */ | 428 | * reason is that in the case of IDE interfaces the |
421 | pci_read_config_dword(dev, PCI_CLASS_REVISION, &class); | 429 | * firmware can sample the value before the the IDE |
422 | dev->class = class >> 8; | 430 | * interface is programmed into native mode. |
423 | 431 | */ | |
432 | pci_read_config_dword(dev, PCI_CLASS_REVISION, &class); | ||
433 | dev->class = class >> 8; | ||
434 | } | ||
424 | printk(" class: 0x%x\n", dev->class); | 435 | printk(" class: 0x%x\n", dev->class); |
425 | 436 | ||
426 | dev->current_state = 4; /* unknown power state */ | 437 | dev->current_state = 4; /* unknown power state */ |
427 | dev->error_state = pci_channel_io_normal; | 438 | dev->error_state = pci_channel_io_normal; |
428 | 439 | ||
429 | if (!strcmp(type, "pci") || !strcmp(type, "pciex")) { | 440 | if (host_controller) { |
430 | /* a PCI-PCI bridge */ | ||
431 | dev->hdr_type = PCI_HEADER_TYPE_BRIDGE; | 441 | dev->hdr_type = PCI_HEADER_TYPE_BRIDGE; |
432 | dev->rom_base_reg = PCI_ROM_ADDRESS1; | 442 | dev->rom_base_reg = PCI_ROM_ADDRESS1; |
433 | } else if (!strcmp(type, "cardbus")) { | 443 | dev->irq = PCI_IRQ_NONE; |
434 | dev->hdr_type = PCI_HEADER_TYPE_CARDBUS; | ||
435 | } else { | 444 | } else { |
436 | dev->hdr_type = PCI_HEADER_TYPE_NORMAL; | 445 | if (!strcmp(type, "pci") || !strcmp(type, "pciex")) { |
437 | dev->rom_base_reg = PCI_ROM_ADDRESS; | 446 | /* a PCI-PCI bridge */ |
447 | dev->hdr_type = PCI_HEADER_TYPE_BRIDGE; | ||
448 | dev->rom_base_reg = PCI_ROM_ADDRESS1; | ||
449 | } else if (!strcmp(type, "cardbus")) { | ||
450 | dev->hdr_type = PCI_HEADER_TYPE_CARDBUS; | ||
451 | } else { | ||
452 | dev->hdr_type = PCI_HEADER_TYPE_NORMAL; | ||
453 | dev->rom_base_reg = PCI_ROM_ADDRESS; | ||
438 | 454 | ||
439 | dev->irq = sd->op->irqs[0]; | 455 | dev->irq = sd->op->irqs[0]; |
440 | if (dev->irq == 0xffffffff) | 456 | if (dev->irq == 0xffffffff) |
441 | dev->irq = PCI_IRQ_NONE; | 457 | dev->irq = PCI_IRQ_NONE; |
458 | } | ||
442 | } | 459 | } |
443 | |||
444 | pci_parse_of_addrs(sd->op, node, dev); | 460 | pci_parse_of_addrs(sd->op, node, dev); |
445 | 461 | ||
446 | printk(" adding to system ...\n"); | 462 | printk(" adding to system ...\n"); |
@@ -632,7 +648,7 @@ static void __init pci_of_scan_bus(struct pci_pbm_info *pbm, | |||
632 | devfn = (reg[0] >> 8) & 0xff; | 648 | devfn = (reg[0] >> 8) & 0xff; |
633 | 649 | ||
634 | /* create a new pci_dev for this device */ | 650 | /* create a new pci_dev for this device */ |
635 | dev = of_create_pci_dev(pbm, child, bus, devfn); | 651 | dev = of_create_pci_dev(pbm, child, bus, devfn, 0); |
636 | if (!dev) | 652 | if (!dev) |
637 | continue; | 653 | continue; |
638 | printk("PCI: dev header type: %x\n", dev->hdr_type); | 654 | printk("PCI: dev header type: %x\n", dev->hdr_type); |
@@ -677,10 +693,49 @@ static void __devinit pci_bus_register_of_sysfs(struct pci_bus *bus) | |||
677 | pci_bus_register_of_sysfs(child_bus); | 693 | pci_bus_register_of_sysfs(child_bus); |
678 | } | 694 | } |
679 | 695 | ||
696 | int pci_host_bridge_read_pci_cfg(struct pci_bus *bus_dev, | ||
697 | unsigned int devfn, | ||
698 | int where, int size, | ||
699 | u32 *value) | ||
700 | { | ||
701 | static u8 fake_pci_config[] = { | ||
702 | 0x8e, 0x10, /* Vendor: 0x108e (Sun) */ | ||
703 | 0x00, 0x80, /* Device: 0x8000 (PBM) */ | ||
704 | 0x46, 0x01, /* Command: 0x0146 (SERR, PARITY, MASTER, MEM) */ | ||
705 | 0xa0, 0x22, /* Status: 0x02a0 (DEVSEL_MED, FB2B, 66MHZ) */ | ||
706 | 0x00, 0x00, 0x00, 0x06, /* Class: 0x06000000 host bridge */ | ||
707 | 0x00, /* Cacheline: 0x00 */ | ||
708 | 0x40, /* Latency: 0x40 */ | ||
709 | 0x00, /* Header-Type: 0x00 normal */ | ||
710 | }; | ||
711 | |||
712 | *value = 0; | ||
713 | if (where >= 0 && where < sizeof(fake_pci_config) && | ||
714 | (where + size) >= 0 && | ||
715 | (where + size) < sizeof(fake_pci_config) && | ||
716 | size <= sizeof(u32)) { | ||
717 | while (size--) { | ||
718 | *value <<= 8; | ||
719 | *value |= fake_pci_config[where + size]; | ||
720 | } | ||
721 | } | ||
722 | |||
723 | return PCIBIOS_SUCCESSFUL; | ||
724 | } | ||
725 | |||
726 | int pci_host_bridge_write_pci_cfg(struct pci_bus *bus_dev, | ||
727 | unsigned int devfn, | ||
728 | int where, int size, | ||
729 | u32 value) | ||
730 | { | ||
731 | return PCIBIOS_SUCCESSFUL; | ||
732 | } | ||
733 | |||
680 | struct pci_bus * __init pci_scan_one_pbm(struct pci_pbm_info *pbm) | 734 | struct pci_bus * __init pci_scan_one_pbm(struct pci_pbm_info *pbm) |
681 | { | 735 | { |
682 | struct pci_controller_info *p = pbm->parent; | 736 | struct pci_controller_info *p = pbm->parent; |
683 | struct device_node *node = pbm->prom_node; | 737 | struct device_node *node = pbm->prom_node; |
738 | struct pci_dev *host_pdev; | ||
684 | struct pci_bus *bus; | 739 | struct pci_bus *bus; |
685 | 740 | ||
686 | printk("PCI: Scanning PBM %s\n", node->full_name); | 741 | printk("PCI: Scanning PBM %s\n", node->full_name); |
@@ -698,6 +753,10 @@ struct pci_bus * __init pci_scan_one_pbm(struct pci_pbm_info *pbm) | |||
698 | bus->resource[0] = &pbm->io_space; | 753 | bus->resource[0] = &pbm->io_space; |
699 | bus->resource[1] = &pbm->mem_space; | 754 | bus->resource[1] = &pbm->mem_space; |
700 | 755 | ||
756 | /* Create the dummy host bridge and link it in. */ | ||
757 | host_pdev = of_create_pci_dev(pbm, node, bus, 0x00, 1); | ||
758 | bus->self = host_pdev; | ||
759 | |||
701 | pci_of_scan_bus(pbm, node, bus); | 760 | pci_of_scan_bus(pbm, node, bus); |
702 | pci_bus_add_devices(bus); | 761 | pci_bus_add_devices(bus); |
703 | pci_bus_register_of_sysfs(bus); | 762 | pci_bus_register_of_sysfs(bus); |
diff --git a/arch/sparc64/kernel/pci_impl.h b/arch/sparc64/kernel/pci_impl.h index c6714548d823..1208583fcb83 100644 --- a/arch/sparc64/kernel/pci_impl.h +++ b/arch/sparc64/kernel/pci_impl.h | |||
@@ -20,6 +20,15 @@ extern int pci_num_controllers; | |||
20 | extern struct pci_bus *pci_scan_one_pbm(struct pci_pbm_info *pbm); | 20 | extern struct pci_bus *pci_scan_one_pbm(struct pci_pbm_info *pbm); |
21 | extern void pci_determine_mem_io_space(struct pci_pbm_info *pbm); | 21 | extern void pci_determine_mem_io_space(struct pci_pbm_info *pbm); |
22 | 22 | ||
23 | extern int pci_host_bridge_read_pci_cfg(struct pci_bus *bus_dev, | ||
24 | unsigned int devfn, | ||
25 | int where, int size, | ||
26 | u32 *value); | ||
27 | extern int pci_host_bridge_write_pci_cfg(struct pci_bus *bus_dev, | ||
28 | unsigned int devfn, | ||
29 | int where, int size, | ||
30 | u32 value); | ||
31 | |||
23 | /* Error reporting support. */ | 32 | /* Error reporting support. */ |
24 | extern void pci_scan_for_target_abort(struct pci_controller_info *, struct pci_pbm_info *, struct pci_bus *); | 33 | extern void pci_scan_for_target_abort(struct pci_controller_info *, struct pci_pbm_info *, struct pci_bus *); |
25 | extern void pci_scan_for_master_abort(struct pci_controller_info *, struct pci_pbm_info *, struct pci_bus *); | 34 | extern void pci_scan_for_master_abort(struct pci_controller_info *, struct pci_pbm_info *, struct pci_bus *); |
diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c index 2e5d40a26dbd..154c03290d5d 100644 --- a/arch/sparc64/kernel/pci_psycho.c +++ b/arch/sparc64/kernel/pci_psycho.c | |||
@@ -118,6 +118,10 @@ static int psycho_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, | |||
118 | u16 tmp16; | 118 | u16 tmp16; |
119 | u8 tmp8; | 119 | u8 tmp8; |
120 | 120 | ||
121 | if (bus_dev == pbm->pci_bus && devfn == 0x00) | ||
122 | return pci_host_bridge_read_pci_cfg(bus_dev, devfn, where, | ||
123 | size, value); | ||
124 | |||
121 | switch (size) { | 125 | switch (size) { |
122 | case 1: | 126 | case 1: |
123 | *value = 0xff; | 127 | *value = 0xff; |
@@ -171,6 +175,9 @@ static int psycho_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, | |||
171 | unsigned char bus = bus_dev->number; | 175 | unsigned char bus = bus_dev->number; |
172 | u32 *addr; | 176 | u32 *addr; |
173 | 177 | ||
178 | if (bus_dev == pbm->pci_bus && devfn == 0x00) | ||
179 | return pci_host_bridge_write_pci_cfg(bus_dev, devfn, where, | ||
180 | size, value); | ||
174 | addr = psycho_pci_config_mkaddr(pbm, bus, devfn, where); | 181 | addr = psycho_pci_config_mkaddr(pbm, bus, devfn, where); |
175 | if (!addr) | 182 | if (!addr) |
176 | return PCIBIOS_SUCCESSFUL; | 183 | return PCIBIOS_SUCCESSFUL; |
diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c index 1bd7fc7c05e6..a2f129d29c20 100644 --- a/arch/sparc64/kernel/pci_sabre.c +++ b/arch/sparc64/kernel/pci_sabre.c | |||
@@ -319,6 +319,12 @@ static int __sabre_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, | |||
319 | static int sabre_read_pci_cfg(struct pci_bus *bus, unsigned int devfn, | 319 | static int sabre_read_pci_cfg(struct pci_bus *bus, unsigned int devfn, |
320 | int where, int size, u32 *value) | 320 | int where, int size, u32 *value) |
321 | { | 321 | { |
322 | struct pci_pbm_info *pbm = bus->sysdata; | ||
323 | |||
324 | if (bus == pbm->pci_bus && devfn == 0x00) | ||
325 | return pci_host_bridge_read_pci_cfg(bus, devfn, where, | ||
326 | size, value); | ||
327 | |||
322 | if (!bus->number && sabre_out_of_range(devfn)) { | 328 | if (!bus->number && sabre_out_of_range(devfn)) { |
323 | switch (size) { | 329 | switch (size) { |
324 | case 1: | 330 | case 1: |
@@ -435,6 +441,12 @@ static int __sabre_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, | |||
435 | static int sabre_write_pci_cfg(struct pci_bus *bus, unsigned int devfn, | 441 | static int sabre_write_pci_cfg(struct pci_bus *bus, unsigned int devfn, |
436 | int where, int size, u32 value) | 442 | int where, int size, u32 value) |
437 | { | 443 | { |
444 | struct pci_pbm_info *pbm = bus->sysdata; | ||
445 | |||
446 | if (bus == pbm->pci_bus && devfn == 0x00) | ||
447 | return pci_host_bridge_write_pci_cfg(bus, devfn, where, | ||
448 | size, value); | ||
449 | |||
438 | if (bus->number) | 450 | if (bus->number) |
439 | return __sabre_write_pci_cfg(bus, devfn, where, size, value); | 451 | return __sabre_write_pci_cfg(bus, devfn, where, size, value); |
440 | 452 | ||
diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c index f1f105af8d3c..322cdbf50eff 100644 --- a/arch/sparc64/kernel/pci_schizo.c +++ b/arch/sparc64/kernel/pci_schizo.c | |||
@@ -125,6 +125,9 @@ static int schizo_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, | |||
125 | u16 tmp16; | 125 | u16 tmp16; |
126 | u8 tmp8; | 126 | u8 tmp8; |
127 | 127 | ||
128 | if (bus_dev == pbm->pci_bus && devfn == 0x00) | ||
129 | return pci_host_bridge_read_pci_cfg(bus_dev, devfn, where, | ||
130 | size, value); | ||
128 | switch (size) { | 131 | switch (size) { |
129 | case 1: | 132 | case 1: |
130 | *value = 0xff; | 133 | *value = 0xff; |
@@ -178,6 +181,9 @@ static int schizo_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, | |||
178 | unsigned char bus = bus_dev->number; | 181 | unsigned char bus = bus_dev->number; |
179 | u32 *addr; | 182 | u32 *addr; |
180 | 183 | ||
184 | if (bus_dev == pbm->pci_bus && devfn == 0x00) | ||
185 | return pci_host_bridge_write_pci_cfg(bus_dev, devfn, where, | ||
186 | size, value); | ||
181 | addr = schizo_pci_config_mkaddr(pbm, bus, devfn, where); | 187 | addr = schizo_pci_config_mkaddr(pbm, bus, devfn, where); |
182 | if (!addr) | 188 | if (!addr) |
183 | return PCIBIOS_SUCCESSFUL; | 189 | return PCIBIOS_SUCCESSFUL; |
diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c index a8c12c1e8039..52bd4563492d 100644 --- a/arch/sparc64/kernel/pci_sun4v.c +++ b/arch/sparc64/kernel/pci_sun4v.c | |||
@@ -612,6 +612,9 @@ static int pci_sun4v_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, | |||
612 | unsigned int func = PCI_FUNC(devfn); | 612 | unsigned int func = PCI_FUNC(devfn); |
613 | unsigned long ret; | 613 | unsigned long ret; |
614 | 614 | ||
615 | if (bus_dev == pbm->pci_bus && devfn == 0x00) | ||
616 | return pci_host_bridge_read_pci_cfg(bus_dev, devfn, where, | ||
617 | size, value); | ||
615 | if (pci_sun4v_out_of_range(pbm, bus, device, func)) { | 618 | if (pci_sun4v_out_of_range(pbm, bus, device, func)) { |
616 | ret = ~0UL; | 619 | ret = ~0UL; |
617 | } else { | 620 | } else { |
@@ -650,6 +653,9 @@ static int pci_sun4v_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn, | |||
650 | unsigned int func = PCI_FUNC(devfn); | 653 | unsigned int func = PCI_FUNC(devfn); |
651 | unsigned long ret; | 654 | unsigned long ret; |
652 | 655 | ||
656 | if (bus_dev == pbm->pci_bus && devfn == 0x00) | ||
657 | return pci_host_bridge_write_pci_cfg(bus_dev, devfn, where, | ||
658 | size, value); | ||
653 | if (pci_sun4v_out_of_range(pbm, bus, device, func)) { | 659 | if (pci_sun4v_out_of_range(pbm, bus, device, func)) { |
654 | /* Do nothing. */ | 660 | /* Do nothing. */ |
655 | } else { | 661 | } else { |