diff options
Diffstat (limited to 'arch/sparc64/kernel/pci.c')
-rw-r--r-- | arch/sparc64/kernel/pci.c | 603 |
1 files changed, 516 insertions, 87 deletions
diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index 196b4b72482b..023af41ad68d 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c | |||
@@ -1,9 +1,11 @@ | |||
1 | /* $Id: pci.c,v 1.39 2002/01/05 01:13:43 davem Exp $ | 1 | /* pci.c: UltraSparc PCI controller support. |
2 | * pci.c: UltraSparc PCI controller support. | ||
3 | * | 2 | * |
4 | * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@redhat.com) | 3 | * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@redhat.com) |
5 | * Copyright (C) 1998, 1999 Eddie C. Dost (ecd@skynet.be) | 4 | * Copyright (C) 1998, 1999 Eddie C. Dost (ecd@skynet.be) |
6 | * Copyright (C) 1999 Jakub Jelinek (jj@ultra.linux.cz) | 5 | * Copyright (C) 1999 Jakub Jelinek (jj@ultra.linux.cz) |
6 | * | ||
7 | * OF tree based PCI bus probing taken from the PowerPC port | ||
8 | * with minor modifications, see there for credits. | ||
7 | */ | 9 | */ |
8 | 10 | ||
9 | #include <linux/module.h> | 11 | #include <linux/module.h> |
@@ -24,6 +26,9 @@ | |||
24 | #include <asm/ebus.h> | 26 | #include <asm/ebus.h> |
25 | #include <asm/isa.h> | 27 | #include <asm/isa.h> |
26 | #include <asm/prom.h> | 28 | #include <asm/prom.h> |
29 | #include <asm/apb.h> | ||
30 | |||
31 | #include "pci_impl.h" | ||
27 | 32 | ||
28 | unsigned long pci_memspace_mask = 0xffffffffUL; | 33 | unsigned long pci_memspace_mask = 0xffffffffUL; |
29 | 34 | ||
@@ -277,10 +282,10 @@ int __init pcic_present(void) | |||
277 | return pci_controller_scan(pci_is_controller); | 282 | return pci_controller_scan(pci_is_controller); |
278 | } | 283 | } |
279 | 284 | ||
280 | struct pci_iommu_ops *pci_iommu_ops; | 285 | const struct pci_iommu_ops *pci_iommu_ops; |
281 | EXPORT_SYMBOL(pci_iommu_ops); | 286 | EXPORT_SYMBOL(pci_iommu_ops); |
282 | 287 | ||
283 | extern struct pci_iommu_ops pci_sun4u_iommu_ops, | 288 | extern const struct pci_iommu_ops pci_sun4u_iommu_ops, |
284 | pci_sun4v_iommu_ops; | 289 | pci_sun4v_iommu_ops; |
285 | 290 | ||
286 | /* Find each controller in the system, attach and initialize | 291 | /* Find each controller in the system, attach and initialize |
@@ -300,6 +305,467 @@ static void __init pci_controller_probe(void) | |||
300 | pci_controller_scan(pci_controller_init); | 305 | pci_controller_scan(pci_controller_init); |
301 | } | 306 | } |
302 | 307 | ||
308 | static unsigned long pci_parse_of_flags(u32 addr0) | ||
309 | { | ||
310 | unsigned long flags = 0; | ||
311 | |||
312 | if (addr0 & 0x02000000) { | ||
313 | flags = IORESOURCE_MEM | PCI_BASE_ADDRESS_SPACE_MEMORY; | ||
314 | flags |= (addr0 >> 22) & PCI_BASE_ADDRESS_MEM_TYPE_64; | ||
315 | flags |= (addr0 >> 28) & PCI_BASE_ADDRESS_MEM_TYPE_1M; | ||
316 | if (addr0 & 0x40000000) | ||
317 | flags |= IORESOURCE_PREFETCH | ||
318 | | PCI_BASE_ADDRESS_MEM_PREFETCH; | ||
319 | } else if (addr0 & 0x01000000) | ||
320 | flags = IORESOURCE_IO | PCI_BASE_ADDRESS_SPACE_IO; | ||
321 | return flags; | ||
322 | } | ||
323 | |||
324 | /* The of_device layer has translated all of the assigned-address properties | ||
325 | * into physical address resources, we only have to figure out the register | ||
326 | * mapping. | ||
327 | */ | ||
328 | static void pci_parse_of_addrs(struct of_device *op, | ||
329 | struct device_node *node, | ||
330 | struct pci_dev *dev) | ||
331 | { | ||
332 | struct resource *op_res; | ||
333 | const u32 *addrs; | ||
334 | int proplen; | ||
335 | |||
336 | addrs = of_get_property(node, "assigned-addresses", &proplen); | ||
337 | if (!addrs) | ||
338 | return; | ||
339 | printk(" parse addresses (%d bytes) @ %p\n", proplen, addrs); | ||
340 | op_res = &op->resource[0]; | ||
341 | for (; proplen >= 20; proplen -= 20, addrs += 5, op_res++) { | ||
342 | struct resource *res; | ||
343 | unsigned long flags; | ||
344 | int i; | ||
345 | |||
346 | flags = pci_parse_of_flags(addrs[0]); | ||
347 | if (!flags) | ||
348 | continue; | ||
349 | i = addrs[0] & 0xff; | ||
350 | printk(" start: %lx, end: %lx, i: %x\n", | ||
351 | op_res->start, op_res->end, i); | ||
352 | |||
353 | if (PCI_BASE_ADDRESS_0 <= i && i <= PCI_BASE_ADDRESS_5) { | ||
354 | res = &dev->resource[(i - PCI_BASE_ADDRESS_0) >> 2]; | ||
355 | } else if (i == dev->rom_base_reg) { | ||
356 | res = &dev->resource[PCI_ROM_RESOURCE]; | ||
357 | flags |= IORESOURCE_READONLY | IORESOURCE_CACHEABLE; | ||
358 | } else { | ||
359 | printk(KERN_ERR "PCI: bad cfg reg num 0x%x\n", i); | ||
360 | continue; | ||
361 | } | ||
362 | res->start = op_res->start; | ||
363 | res->end = op_res->end; | ||
364 | res->flags = flags; | ||
365 | res->name = pci_name(dev); | ||
366 | } | ||
367 | } | ||
368 | |||
369 | struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm, | ||
370 | struct device_node *node, | ||
371 | struct pci_bus *bus, int devfn, | ||
372 | int host_controller) | ||
373 | { | ||
374 | struct dev_archdata *sd; | ||
375 | struct pci_dev *dev; | ||
376 | const char *type; | ||
377 | u32 class; | ||
378 | |||
379 | dev = kzalloc(sizeof(struct pci_dev), GFP_KERNEL); | ||
380 | if (!dev) | ||
381 | return NULL; | ||
382 | |||
383 | sd = &dev->dev.archdata; | ||
384 | sd->iommu = pbm->iommu; | ||
385 | sd->stc = &pbm->stc; | ||
386 | sd->host_controller = pbm; | ||
387 | sd->prom_node = node; | ||
388 | sd->op = of_find_device_by_node(node); | ||
389 | sd->msi_num = 0xffffffff; | ||
390 | |||
391 | type = of_get_property(node, "device_type", NULL); | ||
392 | if (type == NULL) | ||
393 | type = ""; | ||
394 | |||
395 | printk(" create device, devfn: %x, type: %s hostcontroller(%d)\n", | ||
396 | devfn, type, host_controller); | ||
397 | |||
398 | dev->bus = bus; | ||
399 | dev->sysdata = node; | ||
400 | dev->dev.parent = bus->bridge; | ||
401 | dev->dev.bus = &pci_bus_type; | ||
402 | dev->devfn = devfn; | ||
403 | dev->multifunction = 0; /* maybe a lie? */ | ||
404 | |||
405 | if (host_controller) { | ||
406 | dev->vendor = 0x108e; | ||
407 | dev->device = 0x8000; | ||
408 | dev->subsystem_vendor = 0x0000; | ||
409 | dev->subsystem_device = 0x0000; | ||
410 | dev->cfg_size = 256; | ||
411 | dev->class = PCI_CLASS_BRIDGE_HOST << 8; | ||
412 | sprintf(pci_name(dev), "%04x:%02x:%02x.%d", pci_domain_nr(bus), | ||
413 | 0x00, PCI_SLOT(devfn), PCI_FUNC(devfn)); | ||
414 | } else { | ||
415 | dev->vendor = of_getintprop_default(node, "vendor-id", 0xffff); | ||
416 | dev->device = of_getintprop_default(node, "device-id", 0xffff); | ||
417 | dev->subsystem_vendor = | ||
418 | of_getintprop_default(node, "subsystem-vendor-id", 0); | ||
419 | dev->subsystem_device = | ||
420 | of_getintprop_default(node, "subsystem-id", 0); | ||
421 | |||
422 | dev->cfg_size = pci_cfg_space_size(dev); | ||
423 | |||
424 | /* We can't actually use the firmware value, we have | ||
425 | * to read what is in the register right now. One | ||
426 | * reason is that in the case of IDE interfaces the | ||
427 | * firmware can sample the value before the the IDE | ||
428 | * interface is programmed into native mode. | ||
429 | */ | ||
430 | pci_read_config_dword(dev, PCI_CLASS_REVISION, &class); | ||
431 | dev->class = class >> 8; | ||
432 | |||
433 | sprintf(pci_name(dev), "%04x:%02x:%02x.%d", pci_domain_nr(bus), | ||
434 | dev->bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn)); | ||
435 | } | ||
436 | printk(" class: 0x%x device name: %s\n", | ||
437 | dev->class, pci_name(dev)); | ||
438 | |||
439 | dev->current_state = 4; /* unknown power state */ | ||
440 | dev->error_state = pci_channel_io_normal; | ||
441 | |||
442 | if (host_controller) { | ||
443 | dev->hdr_type = PCI_HEADER_TYPE_BRIDGE; | ||
444 | dev->rom_base_reg = PCI_ROM_ADDRESS1; | ||
445 | dev->irq = PCI_IRQ_NONE; | ||
446 | } else { | ||
447 | if (!strcmp(type, "pci") || !strcmp(type, "pciex")) { | ||
448 | /* a PCI-PCI bridge */ | ||
449 | dev->hdr_type = PCI_HEADER_TYPE_BRIDGE; | ||
450 | dev->rom_base_reg = PCI_ROM_ADDRESS1; | ||
451 | } else if (!strcmp(type, "cardbus")) { | ||
452 | dev->hdr_type = PCI_HEADER_TYPE_CARDBUS; | ||
453 | } else { | ||
454 | dev->hdr_type = PCI_HEADER_TYPE_NORMAL; | ||
455 | dev->rom_base_reg = PCI_ROM_ADDRESS; | ||
456 | |||
457 | dev->irq = sd->op->irqs[0]; | ||
458 | if (dev->irq == 0xffffffff) | ||
459 | dev->irq = PCI_IRQ_NONE; | ||
460 | } | ||
461 | } | ||
462 | pci_parse_of_addrs(sd->op, node, dev); | ||
463 | |||
464 | printk(" adding to system ...\n"); | ||
465 | |||
466 | pci_device_add(dev, bus); | ||
467 | |||
468 | return dev; | ||
469 | } | ||
470 | |||
471 | static void __init apb_calc_first_last(u8 map, u32 *first_p, u32 *last_p) | ||
472 | { | ||
473 | u32 idx, first, last; | ||
474 | |||
475 | first = 8; | ||
476 | last = 0; | ||
477 | for (idx = 0; idx < 8; idx++) { | ||
478 | if ((map & (1 << idx)) != 0) { | ||
479 | if (first > idx) | ||
480 | first = idx; | ||
481 | if (last < idx) | ||
482 | last = idx; | ||
483 | } | ||
484 | } | ||
485 | |||
486 | *first_p = first; | ||
487 | *last_p = last; | ||
488 | } | ||
489 | |||
490 | static void __init pci_resource_adjust(struct resource *res, | ||
491 | struct resource *root) | ||
492 | { | ||
493 | res->start += root->start; | ||
494 | res->end += root->start; | ||
495 | } | ||
496 | |||
497 | /* Cook up fake bus resources for SUNW,simba PCI bridges which lack | ||
498 | * a proper 'ranges' property. | ||
499 | */ | ||
500 | static void __init apb_fake_ranges(struct pci_dev *dev, | ||
501 | struct pci_bus *bus, | ||
502 | struct pci_pbm_info *pbm) | ||
503 | { | ||
504 | struct resource *res; | ||
505 | u32 first, last; | ||
506 | u8 map; | ||
507 | |||
508 | pci_read_config_byte(dev, APB_IO_ADDRESS_MAP, &map); | ||
509 | apb_calc_first_last(map, &first, &last); | ||
510 | res = bus->resource[0]; | ||
511 | res->start = (first << 21); | ||
512 | res->end = (last << 21) + ((1 << 21) - 1); | ||
513 | res->flags = IORESOURCE_IO; | ||
514 | pci_resource_adjust(res, &pbm->io_space); | ||
515 | |||
516 | pci_read_config_byte(dev, APB_MEM_ADDRESS_MAP, &map); | ||
517 | apb_calc_first_last(map, &first, &last); | ||
518 | res = bus->resource[1]; | ||
519 | res->start = (first << 21); | ||
520 | res->end = (last << 21) + ((1 << 21) - 1); | ||
521 | res->flags = IORESOURCE_MEM; | ||
522 | pci_resource_adjust(res, &pbm->mem_space); | ||
523 | } | ||
524 | |||
525 | static void __init pci_of_scan_bus(struct pci_pbm_info *pbm, | ||
526 | struct device_node *node, | ||
527 | struct pci_bus *bus); | ||
528 | |||
529 | #define GET_64BIT(prop, i) ((((u64) (prop)[(i)]) << 32) | (prop)[(i)+1]) | ||
530 | |||
531 | void __devinit of_scan_pci_bridge(struct pci_pbm_info *pbm, | ||
532 | struct device_node *node, | ||
533 | struct pci_dev *dev) | ||
534 | { | ||
535 | struct pci_bus *bus; | ||
536 | const u32 *busrange, *ranges; | ||
537 | int len, i, simba; | ||
538 | struct resource *res; | ||
539 | unsigned int flags; | ||
540 | u64 size; | ||
541 | |||
542 | printk("of_scan_pci_bridge(%s)\n", node->full_name); | ||
543 | |||
544 | /* parse bus-range property */ | ||
545 | busrange = of_get_property(node, "bus-range", &len); | ||
546 | if (busrange == NULL || len != 8) { | ||
547 | printk(KERN_DEBUG "Can't get bus-range for PCI-PCI bridge %s\n", | ||
548 | node->full_name); | ||
549 | return; | ||
550 | } | ||
551 | ranges = of_get_property(node, "ranges", &len); | ||
552 | simba = 0; | ||
553 | if (ranges == NULL) { | ||
554 | const char *model = of_get_property(node, "model", NULL); | ||
555 | if (model && !strcmp(model, "SUNW,simba")) { | ||
556 | simba = 1; | ||
557 | } else { | ||
558 | printk(KERN_DEBUG "Can't get ranges for PCI-PCI bridge %s\n", | ||
559 | node->full_name); | ||
560 | return; | ||
561 | } | ||
562 | } | ||
563 | |||
564 | bus = pci_add_new_bus(dev->bus, dev, busrange[0]); | ||
565 | if (!bus) { | ||
566 | printk(KERN_ERR "Failed to create pci bus for %s\n", | ||
567 | node->full_name); | ||
568 | return; | ||
569 | } | ||
570 | |||
571 | bus->primary = dev->bus->number; | ||
572 | bus->subordinate = busrange[1]; | ||
573 | bus->bridge_ctl = 0; | ||
574 | |||
575 | /* parse ranges property, or cook one up by hand for Simba */ | ||
576 | /* PCI #address-cells == 3 and #size-cells == 2 always */ | ||
577 | res = &dev->resource[PCI_BRIDGE_RESOURCES]; | ||
578 | for (i = 0; i < PCI_NUM_RESOURCES - PCI_BRIDGE_RESOURCES; ++i) { | ||
579 | res->flags = 0; | ||
580 | bus->resource[i] = res; | ||
581 | ++res; | ||
582 | } | ||
583 | if (simba) { | ||
584 | apb_fake_ranges(dev, bus, pbm); | ||
585 | goto simba_cont; | ||
586 | } | ||
587 | i = 1; | ||
588 | for (; len >= 32; len -= 32, ranges += 8) { | ||
589 | struct resource *root; | ||
590 | |||
591 | flags = pci_parse_of_flags(ranges[0]); | ||
592 | size = GET_64BIT(ranges, 6); | ||
593 | if (flags == 0 || size == 0) | ||
594 | continue; | ||
595 | if (flags & IORESOURCE_IO) { | ||
596 | res = bus->resource[0]; | ||
597 | if (res->flags) { | ||
598 | printk(KERN_ERR "PCI: ignoring extra I/O range" | ||
599 | " for bridge %s\n", node->full_name); | ||
600 | continue; | ||
601 | } | ||
602 | root = &pbm->io_space; | ||
603 | } else { | ||
604 | if (i >= PCI_NUM_RESOURCES - PCI_BRIDGE_RESOURCES) { | ||
605 | printk(KERN_ERR "PCI: too many memory ranges" | ||
606 | " for bridge %s\n", node->full_name); | ||
607 | continue; | ||
608 | } | ||
609 | res = bus->resource[i]; | ||
610 | ++i; | ||
611 | root = &pbm->mem_space; | ||
612 | } | ||
613 | |||
614 | res->start = GET_64BIT(ranges, 1); | ||
615 | res->end = res->start + size - 1; | ||
616 | res->flags = flags; | ||
617 | |||
618 | /* Another way to implement this would be to add an of_device | ||
619 | * layer routine that can calculate a resource for a given | ||
620 | * range property value in a PCI device. | ||
621 | */ | ||
622 | pci_resource_adjust(res, root); | ||
623 | } | ||
624 | simba_cont: | ||
625 | sprintf(bus->name, "PCI Bus %04x:%02x", pci_domain_nr(bus), | ||
626 | bus->number); | ||
627 | printk(" bus name: %s\n", bus->name); | ||
628 | |||
629 | pci_of_scan_bus(pbm, node, bus); | ||
630 | } | ||
631 | |||
632 | static void __init pci_of_scan_bus(struct pci_pbm_info *pbm, | ||
633 | struct device_node *node, | ||
634 | struct pci_bus *bus) | ||
635 | { | ||
636 | struct device_node *child; | ||
637 | const u32 *reg; | ||
638 | int reglen, devfn; | ||
639 | struct pci_dev *dev; | ||
640 | |||
641 | printk("PCI: scan_bus[%s] bus no %d\n", | ||
642 | node->full_name, bus->number); | ||
643 | |||
644 | child = NULL; | ||
645 | while ((child = of_get_next_child(node, child)) != NULL) { | ||
646 | printk(" * %s\n", child->full_name); | ||
647 | reg = of_get_property(child, "reg", ®len); | ||
648 | if (reg == NULL || reglen < 20) | ||
649 | continue; | ||
650 | devfn = (reg[0] >> 8) & 0xff; | ||
651 | |||
652 | /* create a new pci_dev for this device */ | ||
653 | dev = of_create_pci_dev(pbm, child, bus, devfn, 0); | ||
654 | if (!dev) | ||
655 | continue; | ||
656 | printk("PCI: dev header type: %x\n", dev->hdr_type); | ||
657 | |||
658 | if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || | ||
659 | dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) | ||
660 | of_scan_pci_bridge(pbm, child, dev); | ||
661 | } | ||
662 | } | ||
663 | |||
664 | static ssize_t | ||
665 | show_pciobppath_attr(struct device * dev, struct device_attribute * attr, char * buf) | ||
666 | { | ||
667 | struct pci_dev *pdev; | ||
668 | struct device_node *dp; | ||
669 | |||
670 | pdev = to_pci_dev(dev); | ||
671 | dp = pdev->dev.archdata.prom_node; | ||
672 | |||
673 | return snprintf (buf, PAGE_SIZE, "%s\n", dp->full_name); | ||
674 | } | ||
675 | |||
676 | static DEVICE_ATTR(obppath, S_IRUSR | S_IRGRP | S_IROTH, show_pciobppath_attr, NULL); | ||
677 | |||
678 | static void __devinit pci_bus_register_of_sysfs(struct pci_bus *bus) | ||
679 | { | ||
680 | struct pci_dev *dev; | ||
681 | struct pci_bus *child_bus; | ||
682 | int err; | ||
683 | |||
684 | list_for_each_entry(dev, &bus->devices, bus_list) { | ||
685 | /* we don't really care if we can create this file or | ||
686 | * not, but we need to assign the result of the call | ||
687 | * or the world will fall under alien invasion and | ||
688 | * everybody will be frozen on a spaceship ready to be | ||
689 | * eaten on alpha centauri by some green and jelly | ||
690 | * humanoid. | ||
691 | */ | ||
692 | err = sysfs_create_file(&dev->dev.kobj, &dev_attr_obppath.attr); | ||
693 | } | ||
694 | list_for_each_entry(child_bus, &bus->children, node) | ||
695 | pci_bus_register_of_sysfs(child_bus); | ||
696 | } | ||
697 | |||
698 | int pci_host_bridge_read_pci_cfg(struct pci_bus *bus_dev, | ||
699 | unsigned int devfn, | ||
700 | int where, int size, | ||
701 | u32 *value) | ||
702 | { | ||
703 | static u8 fake_pci_config[] = { | ||
704 | 0x8e, 0x10, /* Vendor: 0x108e (Sun) */ | ||
705 | 0x00, 0x80, /* Device: 0x8000 (PBM) */ | ||
706 | 0x46, 0x01, /* Command: 0x0146 (SERR, PARITY, MASTER, MEM) */ | ||
707 | 0xa0, 0x22, /* Status: 0x02a0 (DEVSEL_MED, FB2B, 66MHZ) */ | ||
708 | 0x00, 0x00, 0x00, 0x06, /* Class: 0x06000000 host bridge */ | ||
709 | 0x00, /* Cacheline: 0x00 */ | ||
710 | 0x40, /* Latency: 0x40 */ | ||
711 | 0x00, /* Header-Type: 0x00 normal */ | ||
712 | }; | ||
713 | |||
714 | *value = 0; | ||
715 | if (where >= 0 && where < sizeof(fake_pci_config) && | ||
716 | (where + size) >= 0 && | ||
717 | (where + size) < sizeof(fake_pci_config) && | ||
718 | size <= sizeof(u32)) { | ||
719 | while (size--) { | ||
720 | *value <<= 8; | ||
721 | *value |= fake_pci_config[where + size]; | ||
722 | } | ||
723 | } | ||
724 | |||
725 | return PCIBIOS_SUCCESSFUL; | ||
726 | } | ||
727 | |||
728 | int pci_host_bridge_write_pci_cfg(struct pci_bus *bus_dev, | ||
729 | unsigned int devfn, | ||
730 | int where, int size, | ||
731 | u32 value) | ||
732 | { | ||
733 | return PCIBIOS_SUCCESSFUL; | ||
734 | } | ||
735 | |||
736 | struct pci_bus * __init pci_scan_one_pbm(struct pci_pbm_info *pbm) | ||
737 | { | ||
738 | struct pci_controller_info *p = pbm->parent; | ||
739 | struct device_node *node = pbm->prom_node; | ||
740 | struct pci_dev *host_pdev; | ||
741 | struct pci_bus *bus; | ||
742 | |||
743 | printk("PCI: Scanning PBM %s\n", node->full_name); | ||
744 | |||
745 | /* XXX parent device? XXX */ | ||
746 | bus = pci_create_bus(NULL, pbm->pci_first_busno, p->pci_ops, pbm); | ||
747 | if (!bus) { | ||
748 | printk(KERN_ERR "Failed to create bus for %s\n", | ||
749 | node->full_name); | ||
750 | return NULL; | ||
751 | } | ||
752 | bus->secondary = pbm->pci_first_busno; | ||
753 | bus->subordinate = pbm->pci_last_busno; | ||
754 | |||
755 | bus->resource[0] = &pbm->io_space; | ||
756 | bus->resource[1] = &pbm->mem_space; | ||
757 | |||
758 | /* Create the dummy host bridge and link it in. */ | ||
759 | host_pdev = of_create_pci_dev(pbm, node, bus, 0x00, 1); | ||
760 | bus->self = host_pdev; | ||
761 | |||
762 | pci_of_scan_bus(pbm, node, bus); | ||
763 | pci_bus_add_devices(bus); | ||
764 | pci_bus_register_of_sysfs(bus); | ||
765 | |||
766 | return bus; | ||
767 | } | ||
768 | |||
303 | static void __init pci_scan_each_controller_bus(void) | 769 | static void __init pci_scan_each_controller_bus(void) |
304 | { | 770 | { |
305 | struct pci_controller_info *p; | 771 | struct pci_controller_info *p; |
@@ -327,7 +793,7 @@ static int __init pcibios_init(void) | |||
327 | 793 | ||
328 | subsys_initcall(pcibios_init); | 794 | subsys_initcall(pcibios_init); |
329 | 795 | ||
330 | void pcibios_fixup_bus(struct pci_bus *pbus) | 796 | void __devinit pcibios_fixup_bus(struct pci_bus *pbus) |
331 | { | 797 | { |
332 | struct pci_pbm_info *pbm = pbus->sysdata; | 798 | struct pci_pbm_info *pbm = pbus->sysdata; |
333 | 799 | ||
@@ -360,8 +826,33 @@ void pcibios_align_resource(void *data, struct resource *res, | |||
360 | { | 826 | { |
361 | } | 827 | } |
362 | 828 | ||
363 | int pcibios_enable_device(struct pci_dev *pdev, int mask) | 829 | int pcibios_enable_device(struct pci_dev *dev, int mask) |
364 | { | 830 | { |
831 | u16 cmd, oldcmd; | ||
832 | int i; | ||
833 | |||
834 | pci_read_config_word(dev, PCI_COMMAND, &cmd); | ||
835 | oldcmd = cmd; | ||
836 | |||
837 | for (i = 0; i < PCI_NUM_RESOURCES; i++) { | ||
838 | struct resource *res = &dev->resource[i]; | ||
839 | |||
840 | /* Only set up the requested stuff */ | ||
841 | if (!(mask & (1<<i))) | ||
842 | continue; | ||
843 | |||
844 | if (res->flags & IORESOURCE_IO) | ||
845 | cmd |= PCI_COMMAND_IO; | ||
846 | if (res->flags & IORESOURCE_MEM) | ||
847 | cmd |= PCI_COMMAND_MEMORY; | ||
848 | } | ||
849 | |||
850 | if (cmd != oldcmd) { | ||
851 | printk(KERN_DEBUG "PCI: Enabling device: (%s), cmd %x\n", | ||
852 | pci_name(dev), cmd); | ||
853 | /* Enable the appropriate bits in the PCI command register. */ | ||
854 | pci_write_config_word(dev, PCI_COMMAND, cmd); | ||
855 | } | ||
365 | return 0; | 856 | return 0; |
366 | } | 857 | } |
367 | 858 | ||
@@ -380,7 +871,7 @@ void pcibios_resource_to_bus(struct pci_dev *pdev, struct pci_bus_region *region | |||
380 | else | 871 | else |
381 | root = &pbm->mem_space; | 872 | root = &pbm->mem_space; |
382 | 873 | ||
383 | pbm->parent->resource_adjust(pdev, &zero_res, root); | 874 | pci_resource_adjust(&zero_res, root); |
384 | 875 | ||
385 | region->start = res->start - zero_res.start; | 876 | region->start = res->start - zero_res.start; |
386 | region->end = res->end - zero_res.start; | 877 | region->end = res->end - zero_res.start; |
@@ -401,11 +892,11 @@ void pcibios_bus_to_resource(struct pci_dev *pdev, struct resource *res, | |||
401 | else | 892 | else |
402 | root = &pbm->mem_space; | 893 | root = &pbm->mem_space; |
403 | 894 | ||
404 | pbm->parent->resource_adjust(pdev, res, root); | 895 | pci_resource_adjust(res, root); |
405 | } | 896 | } |
406 | EXPORT_SYMBOL(pcibios_bus_to_resource); | 897 | EXPORT_SYMBOL(pcibios_bus_to_resource); |
407 | 898 | ||
408 | char * __init pcibios_setup(char *str) | 899 | char * __devinit pcibios_setup(char *str) |
409 | { | 900 | { |
410 | return str; | 901 | return str; |
411 | } | 902 | } |
@@ -422,55 +913,17 @@ char * __init pcibios_setup(char *str) | |||
422 | static int __pci_mmap_make_offset_bus(struct pci_dev *pdev, struct vm_area_struct *vma, | 913 | static int __pci_mmap_make_offset_bus(struct pci_dev *pdev, struct vm_area_struct *vma, |
423 | enum pci_mmap_state mmap_state) | 914 | enum pci_mmap_state mmap_state) |
424 | { | 915 | { |
425 | struct pcidev_cookie *pcp = pdev->sysdata; | 916 | struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller; |
426 | struct pci_pbm_info *pbm; | ||
427 | struct pci_controller_info *p; | 917 | struct pci_controller_info *p; |
428 | unsigned long space_size, user_offset, user_size; | 918 | unsigned long space_size, user_offset, user_size; |
429 | 919 | ||
430 | if (!pcp) | ||
431 | return -ENXIO; | ||
432 | pbm = pcp->pbm; | ||
433 | if (!pbm) | ||
434 | return -ENXIO; | ||
435 | |||
436 | p = pbm->parent; | 920 | p = pbm->parent; |
437 | if (p->pbms_same_domain) { | 921 | if (mmap_state == pci_mmap_io) { |
438 | unsigned long lowest, highest; | 922 | space_size = (pbm->io_space.end - |
439 | 923 | pbm->io_space.start) + 1; | |
440 | lowest = ~0UL; highest = 0UL; | ||
441 | if (mmap_state == pci_mmap_io) { | ||
442 | if (p->pbm_A.io_space.flags) { | ||
443 | lowest = p->pbm_A.io_space.start; | ||
444 | highest = p->pbm_A.io_space.end + 1; | ||
445 | } | ||
446 | if (p->pbm_B.io_space.flags) { | ||
447 | if (lowest > p->pbm_B.io_space.start) | ||
448 | lowest = p->pbm_B.io_space.start; | ||
449 | if (highest < p->pbm_B.io_space.end + 1) | ||
450 | highest = p->pbm_B.io_space.end + 1; | ||
451 | } | ||
452 | space_size = highest - lowest; | ||
453 | } else { | ||
454 | if (p->pbm_A.mem_space.flags) { | ||
455 | lowest = p->pbm_A.mem_space.start; | ||
456 | highest = p->pbm_A.mem_space.end + 1; | ||
457 | } | ||
458 | if (p->pbm_B.mem_space.flags) { | ||
459 | if (lowest > p->pbm_B.mem_space.start) | ||
460 | lowest = p->pbm_B.mem_space.start; | ||
461 | if (highest < p->pbm_B.mem_space.end + 1) | ||
462 | highest = p->pbm_B.mem_space.end + 1; | ||
463 | } | ||
464 | space_size = highest - lowest; | ||
465 | } | ||
466 | } else { | 924 | } else { |
467 | if (mmap_state == pci_mmap_io) { | 925 | space_size = (pbm->mem_space.end - |
468 | space_size = (pbm->io_space.end - | 926 | pbm->mem_space.start) + 1; |
469 | pbm->io_space.start) + 1; | ||
470 | } else { | ||
471 | space_size = (pbm->mem_space.end - | ||
472 | pbm->mem_space.start) + 1; | ||
473 | } | ||
474 | } | 927 | } |
475 | 928 | ||
476 | /* Make sure the request is in range. */ | 929 | /* Make sure the request is in range. */ |
@@ -481,31 +934,12 @@ static int __pci_mmap_make_offset_bus(struct pci_dev *pdev, struct vm_area_struc | |||
481 | (user_offset + user_size) > space_size) | 934 | (user_offset + user_size) > space_size) |
482 | return -EINVAL; | 935 | return -EINVAL; |
483 | 936 | ||
484 | if (p->pbms_same_domain) { | 937 | if (mmap_state == pci_mmap_io) { |
485 | unsigned long lowest = ~0UL; | 938 | vma->vm_pgoff = (pbm->io_space.start + |
486 | 939 | user_offset) >> PAGE_SHIFT; | |
487 | if (mmap_state == pci_mmap_io) { | ||
488 | if (p->pbm_A.io_space.flags) | ||
489 | lowest = p->pbm_A.io_space.start; | ||
490 | if (p->pbm_B.io_space.flags && | ||
491 | lowest > p->pbm_B.io_space.start) | ||
492 | lowest = p->pbm_B.io_space.start; | ||
493 | } else { | ||
494 | if (p->pbm_A.mem_space.flags) | ||
495 | lowest = p->pbm_A.mem_space.start; | ||
496 | if (p->pbm_B.mem_space.flags && | ||
497 | lowest > p->pbm_B.mem_space.start) | ||
498 | lowest = p->pbm_B.mem_space.start; | ||
499 | } | ||
500 | vma->vm_pgoff = (lowest + user_offset) >> PAGE_SHIFT; | ||
501 | } else { | 940 | } else { |
502 | if (mmap_state == pci_mmap_io) { | 941 | vma->vm_pgoff = (pbm->mem_space.start + |
503 | vma->vm_pgoff = (pbm->io_space.start + | 942 | user_offset) >> PAGE_SHIFT; |
504 | user_offset) >> PAGE_SHIFT; | ||
505 | } else { | ||
506 | vma->vm_pgoff = (pbm->mem_space.start + | ||
507 | user_offset) >> PAGE_SHIFT; | ||
508 | } | ||
509 | } | 943 | } |
510 | 944 | ||
511 | return 0; | 945 | return 0; |
@@ -639,9 +1073,8 @@ int pci_domain_nr(struct pci_bus *pbus) | |||
639 | struct pci_controller_info *p = pbm->parent; | 1073 | struct pci_controller_info *p = pbm->parent; |
640 | 1074 | ||
641 | ret = p->index; | 1075 | ret = p->index; |
642 | if (p->pbms_same_domain == 0) | 1076 | ret = ((ret << 1) + |
643 | ret = ((ret << 1) + | 1077 | ((pbm == &pbm->parent->pbm_B) ? 1 : 0)); |
644 | ((pbm == &pbm->parent->pbm_B) ? 1 : 0)); | ||
645 | } | 1078 | } |
646 | 1079 | ||
647 | return ret; | 1080 | return ret; |
@@ -651,8 +1084,7 @@ EXPORT_SYMBOL(pci_domain_nr); | |||
651 | #ifdef CONFIG_PCI_MSI | 1084 | #ifdef CONFIG_PCI_MSI |
652 | int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc) | 1085 | int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc) |
653 | { | 1086 | { |
654 | struct pcidev_cookie *pcp = pdev->sysdata; | 1087 | struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller; |
655 | struct pci_pbm_info *pbm = pcp->pbm; | ||
656 | struct pci_controller_info *p = pbm->parent; | 1088 | struct pci_controller_info *p = pbm->parent; |
657 | int virt_irq, err; | 1089 | int virt_irq, err; |
658 | 1090 | ||
@@ -670,8 +1102,7 @@ void arch_teardown_msi_irq(unsigned int virt_irq) | |||
670 | { | 1102 | { |
671 | struct msi_desc *entry = get_irq_msi(virt_irq); | 1103 | struct msi_desc *entry = get_irq_msi(virt_irq); |
672 | struct pci_dev *pdev = entry->dev; | 1104 | struct pci_dev *pdev = entry->dev; |
673 | struct pcidev_cookie *pcp = pdev->sysdata; | 1105 | struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller; |
674 | struct pci_pbm_info *pbm = pcp->pbm; | ||
675 | struct pci_controller_info *p = pbm->parent; | 1106 | struct pci_controller_info *p = pbm->parent; |
676 | 1107 | ||
677 | if (!pbm->msi_num || !p->setup_msi_irq) | 1108 | if (!pbm->msi_num || !p->setup_msi_irq) |
@@ -683,9 +1114,7 @@ void arch_teardown_msi_irq(unsigned int virt_irq) | |||
683 | 1114 | ||
684 | struct device_node *pci_device_to_OF_node(struct pci_dev *pdev) | 1115 | struct device_node *pci_device_to_OF_node(struct pci_dev *pdev) |
685 | { | 1116 | { |
686 | struct pcidev_cookie *pc = pdev->sysdata; | 1117 | return pdev->dev.archdata.prom_node; |
687 | |||
688 | return pc->op->node; | ||
689 | } | 1118 | } |
690 | EXPORT_SYMBOL(pci_device_to_OF_node); | 1119 | EXPORT_SYMBOL(pci_device_to_OF_node); |
691 | 1120 | ||