diff options
Diffstat (limited to 'arch/powerpc/platforms/iseries/pci.c')
-rw-r--r-- | arch/powerpc/platforms/iseries/pci.c | 372 |
1 files changed, 156 insertions, 216 deletions
diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c index 4aa165e010d9..4a06d9c34986 100644 --- a/arch/powerpc/platforms/iseries/pci.c +++ b/arch/powerpc/platforms/iseries/pci.c | |||
@@ -156,53 +156,6 @@ static void pci_Log_Error(char *Error_Text, int Bus, int SubBus, | |||
156 | } | 156 | } |
157 | 157 | ||
158 | /* | 158 | /* |
159 | * iSeries_pcibios_init | ||
160 | * | ||
161 | * Description: | ||
162 | * This function checks for all possible system PCI host bridges that connect | ||
163 | * PCI buses. The system hypervisor is queried as to the guest partition | ||
164 | * ownership status. A pci_controller is built for any bus which is partially | ||
165 | * owned or fully owned by this guest partition. | ||
166 | */ | ||
167 | void iSeries_pcibios_init(void) | ||
168 | { | ||
169 | struct pci_controller *phb; | ||
170 | struct device_node *root = of_find_node_by_path("/"); | ||
171 | struct device_node *node = NULL; | ||
172 | |||
173 | if (root == NULL) { | ||
174 | printk(KERN_CRIT "iSeries_pcibios_init: can't find root " | ||
175 | "of device tree\n"); | ||
176 | return; | ||
177 | } | ||
178 | while ((node = of_get_next_child(root, node)) != NULL) { | ||
179 | HvBusNumber bus; | ||
180 | const u32 *busp; | ||
181 | |||
182 | if ((node->type == NULL) || (strcmp(node->type, "pci") != 0)) | ||
183 | continue; | ||
184 | |||
185 | busp = get_property(node, "bus-range", NULL); | ||
186 | if (busp == NULL) | ||
187 | continue; | ||
188 | bus = *busp; | ||
189 | printk("bus %d appears to exist\n", bus); | ||
190 | phb = pcibios_alloc_controller(node); | ||
191 | if (phb == NULL) | ||
192 | continue; | ||
193 | |||
194 | phb->pci_mem_offset = phb->local_number = bus; | ||
195 | phb->first_busno = bus; | ||
196 | phb->last_busno = bus; | ||
197 | phb->ops = &iSeries_pci_ops; | ||
198 | } | ||
199 | |||
200 | of_node_put(root); | ||
201 | |||
202 | pci_devs_phb_init(); | ||
203 | } | ||
204 | |||
205 | /* | ||
206 | * iSeries_pci_final_fixup(void) | 159 | * iSeries_pci_final_fixup(void) |
207 | */ | 160 | */ |
208 | void __init iSeries_pci_final_fixup(void) | 161 | void __init iSeries_pci_final_fixup(void) |
@@ -253,7 +206,7 @@ void __init iSeries_pci_final_fixup(void) | |||
253 | PCI_DN(node)->pcidev = pdev; | 206 | PCI_DN(node)->pcidev = pdev; |
254 | allocate_device_bars(pdev); | 207 | allocate_device_bars(pdev); |
255 | iSeries_Device_Information(pdev, DeviceCount); | 208 | iSeries_Device_Information(pdev, DeviceCount); |
256 | iommu_devnode_init_iSeries(node); | 209 | iommu_devnode_init_iSeries(pdev, node); |
257 | } else | 210 | } else |
258 | printk("PCI: Device Tree not found for 0x%016lX\n", | 211 | printk("PCI: Device Tree not found for 0x%016lX\n", |
259 | (unsigned long)pdev); | 212 | (unsigned long)pdev); |
@@ -438,11 +391,7 @@ static inline struct device_node *xlate_iomm_address( | |||
438 | /* | 391 | /* |
439 | * Read MM I/O Instructions for the iSeries | 392 | * Read MM I/O Instructions for the iSeries |
440 | * On MM I/O error, all ones are returned and iSeries_pci_IoError is cal | 393 | * On MM I/O error, all ones are returned and iSeries_pci_IoError is cal |
441 | * else, data is returned in big Endian format. | 394 | * else, data is returned in Big Endian format. |
442 | * | ||
443 | * iSeries_Read_Byte = Read Byte ( 8 bit) | ||
444 | * iSeries_Read_Word = Read Word (16 bit) | ||
445 | * iSeries_Read_Long = Read Long (32 bit) | ||
446 | */ | 395 | */ |
447 | static u8 iSeries_Read_Byte(const volatile void __iomem *IoAddress) | 396 | static u8 iSeries_Read_Byte(const volatile void __iomem *IoAddress) |
448 | { | 397 | { |
@@ -462,14 +411,15 @@ static u8 iSeries_Read_Byte(const volatile void __iomem *IoAddress) | |||
462 | num_printed = 0; | 411 | num_printed = 0; |
463 | } | 412 | } |
464 | if (num_printed++ < 10) | 413 | if (num_printed++ < 10) |
465 | printk(KERN_ERR "iSeries_Read_Byte: invalid access at IO address %p\n", IoAddress); | 414 | printk(KERN_ERR "iSeries_Read_Byte: invalid access at IO address %p\n", |
415 | IoAddress); | ||
466 | return 0xff; | 416 | return 0xff; |
467 | } | 417 | } |
468 | do { | 418 | do { |
469 | HvCall3Ret16(HvCallPciBarLoad8, &ret, dsa, BarOffset, 0); | 419 | HvCall3Ret16(HvCallPciBarLoad8, &ret, dsa, BarOffset, 0); |
470 | } while (CheckReturnCode("RDB", DevNode, &retry, ret.rc) != 0); | 420 | } while (CheckReturnCode("RDB", DevNode, &retry, ret.rc) != 0); |
471 | 421 | ||
472 | return (u8)ret.value; | 422 | return ret.value; |
473 | } | 423 | } |
474 | 424 | ||
475 | static u16 iSeries_Read_Word(const volatile void __iomem *IoAddress) | 425 | static u16 iSeries_Read_Word(const volatile void __iomem *IoAddress) |
@@ -490,7 +440,8 @@ static u16 iSeries_Read_Word(const volatile void __iomem *IoAddress) | |||
490 | num_printed = 0; | 440 | num_printed = 0; |
491 | } | 441 | } |
492 | if (num_printed++ < 10) | 442 | if (num_printed++ < 10) |
493 | printk(KERN_ERR "iSeries_Read_Word: invalid access at IO address %p\n", IoAddress); | 443 | printk(KERN_ERR "iSeries_Read_Word: invalid access at IO address %p\n", |
444 | IoAddress); | ||
494 | return 0xffff; | 445 | return 0xffff; |
495 | } | 446 | } |
496 | do { | 447 | do { |
@@ -498,7 +449,7 @@ static u16 iSeries_Read_Word(const volatile void __iomem *IoAddress) | |||
498 | BarOffset, 0); | 449 | BarOffset, 0); |
499 | } while (CheckReturnCode("RDW", DevNode, &retry, ret.rc) != 0); | 450 | } while (CheckReturnCode("RDW", DevNode, &retry, ret.rc) != 0); |
500 | 451 | ||
501 | return swab16((u16)ret.value); | 452 | return ret.value; |
502 | } | 453 | } |
503 | 454 | ||
504 | static u32 iSeries_Read_Long(const volatile void __iomem *IoAddress) | 455 | static u32 iSeries_Read_Long(const volatile void __iomem *IoAddress) |
@@ -519,7 +470,8 @@ static u32 iSeries_Read_Long(const volatile void __iomem *IoAddress) | |||
519 | num_printed = 0; | 470 | num_printed = 0; |
520 | } | 471 | } |
521 | if (num_printed++ < 10) | 472 | if (num_printed++ < 10) |
522 | printk(KERN_ERR "iSeries_Read_Long: invalid access at IO address %p\n", IoAddress); | 473 | printk(KERN_ERR "iSeries_Read_Long: invalid access at IO address %p\n", |
474 | IoAddress); | ||
523 | return 0xffffffff; | 475 | return 0xffffffff; |
524 | } | 476 | } |
525 | do { | 477 | do { |
@@ -527,15 +479,12 @@ static u32 iSeries_Read_Long(const volatile void __iomem *IoAddress) | |||
527 | BarOffset, 0); | 479 | BarOffset, 0); |
528 | } while (CheckReturnCode("RDL", DevNode, &retry, ret.rc) != 0); | 480 | } while (CheckReturnCode("RDL", DevNode, &retry, ret.rc) != 0); |
529 | 481 | ||
530 | return swab32((u32)ret.value); | 482 | return ret.value; |
531 | } | 483 | } |
532 | 484 | ||
533 | /* | 485 | /* |
534 | * Write MM I/O Instructions for the iSeries | 486 | * Write MM I/O Instructions for the iSeries |
535 | * | 487 | * |
536 | * iSeries_Write_Byte = Write Byte (8 bit) | ||
537 | * iSeries_Write_Word = Write Word(16 bit) | ||
538 | * iSeries_Write_Long = Write Long(32 bit) | ||
539 | */ | 488 | */ |
540 | static void iSeries_Write_Byte(u8 data, volatile void __iomem *IoAddress) | 489 | static void iSeries_Write_Byte(u8 data, volatile void __iomem *IoAddress) |
541 | { | 490 | { |
@@ -581,11 +530,12 @@ static void iSeries_Write_Word(u16 data, volatile void __iomem *IoAddress) | |||
581 | num_printed = 0; | 530 | num_printed = 0; |
582 | } | 531 | } |
583 | if (num_printed++ < 10) | 532 | if (num_printed++ < 10) |
584 | printk(KERN_ERR "iSeries_Write_Word: invalid access at IO address %p\n", IoAddress); | 533 | printk(KERN_ERR "iSeries_Write_Word: invalid access at IO address %p\n", |
534 | IoAddress); | ||
585 | return; | 535 | return; |
586 | } | 536 | } |
587 | do { | 537 | do { |
588 | rc = HvCall4(HvCallPciBarStore16, dsa, BarOffset, swab16(data), 0); | 538 | rc = HvCall4(HvCallPciBarStore16, dsa, BarOffset, data, 0); |
589 | } while (CheckReturnCode("WWW", DevNode, &retry, rc) != 0); | 539 | } while (CheckReturnCode("WWW", DevNode, &retry, rc) != 0); |
590 | } | 540 | } |
591 | 541 | ||
@@ -607,231 +557,221 @@ static void iSeries_Write_Long(u32 data, volatile void __iomem *IoAddress) | |||
607 | num_printed = 0; | 557 | num_printed = 0; |
608 | } | 558 | } |
609 | if (num_printed++ < 10) | 559 | if (num_printed++ < 10) |
610 | printk(KERN_ERR "iSeries_Write_Long: invalid access at IO address %p\n", IoAddress); | 560 | printk(KERN_ERR "iSeries_Write_Long: invalid access at IO address %p\n", |
561 | IoAddress); | ||
611 | return; | 562 | return; |
612 | } | 563 | } |
613 | do { | 564 | do { |
614 | rc = HvCall4(HvCallPciBarStore32, dsa, BarOffset, swab32(data), 0); | 565 | rc = HvCall4(HvCallPciBarStore32, dsa, BarOffset, data, 0); |
615 | } while (CheckReturnCode("WWL", DevNode, &retry, rc) != 0); | 566 | } while (CheckReturnCode("WWL", DevNode, &retry, rc) != 0); |
616 | } | 567 | } |
617 | 568 | ||
618 | extern unsigned char __raw_readb(const volatile void __iomem *addr) | 569 | static u8 iseries_readb(const volatile void __iomem *addr) |
619 | { | 570 | { |
620 | BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); | 571 | return iSeries_Read_Byte(addr); |
621 | |||
622 | return *(volatile unsigned char __force *)addr; | ||
623 | } | 572 | } |
624 | EXPORT_SYMBOL(__raw_readb); | ||
625 | 573 | ||
626 | extern unsigned short __raw_readw(const volatile void __iomem *addr) | 574 | static u16 iseries_readw(const volatile void __iomem *addr) |
627 | { | 575 | { |
628 | BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); | 576 | return le16_to_cpu(iSeries_Read_Word(addr)); |
629 | |||
630 | return *(volatile unsigned short __force *)addr; | ||
631 | } | 577 | } |
632 | EXPORT_SYMBOL(__raw_readw); | ||
633 | 578 | ||
634 | extern unsigned int __raw_readl(const volatile void __iomem *addr) | 579 | static u32 iseries_readl(const volatile void __iomem *addr) |
635 | { | 580 | { |
636 | BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); | 581 | return le32_to_cpu(iSeries_Read_Long(addr)); |
637 | |||
638 | return *(volatile unsigned int __force *)addr; | ||
639 | } | 582 | } |
640 | EXPORT_SYMBOL(__raw_readl); | ||
641 | 583 | ||
642 | extern unsigned long __raw_readq(const volatile void __iomem *addr) | 584 | static u16 iseries_readw_be(const volatile void __iomem *addr) |
643 | { | 585 | { |
644 | BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); | 586 | return iSeries_Read_Word(addr); |
645 | |||
646 | return *(volatile unsigned long __force *)addr; | ||
647 | } | 587 | } |
648 | EXPORT_SYMBOL(__raw_readq); | ||
649 | 588 | ||
650 | extern void __raw_writeb(unsigned char v, volatile void __iomem *addr) | 589 | static u32 iseries_readl_be(const volatile void __iomem *addr) |
651 | { | 590 | { |
652 | BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); | 591 | return iSeries_Read_Long(addr); |
653 | |||
654 | *(volatile unsigned char __force *)addr = v; | ||
655 | } | 592 | } |
656 | EXPORT_SYMBOL(__raw_writeb); | ||
657 | 593 | ||
658 | extern void __raw_writew(unsigned short v, volatile void __iomem *addr) | 594 | static void iseries_writeb(u8 data, volatile void __iomem *addr) |
659 | { | 595 | { |
660 | BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); | 596 | iSeries_Write_Byte(data, addr); |
661 | |||
662 | *(volatile unsigned short __force *)addr = v; | ||
663 | } | 597 | } |
664 | EXPORT_SYMBOL(__raw_writew); | ||
665 | 598 | ||
666 | extern void __raw_writel(unsigned int v, volatile void __iomem *addr) | 599 | static void iseries_writew(u16 data, volatile void __iomem *addr) |
667 | { | 600 | { |
668 | BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); | 601 | iSeries_Write_Word(cpu_to_le16(data), addr); |
669 | |||
670 | *(volatile unsigned int __force *)addr = v; | ||
671 | } | 602 | } |
672 | EXPORT_SYMBOL(__raw_writel); | ||
673 | 603 | ||
674 | extern void __raw_writeq(unsigned long v, volatile void __iomem *addr) | 604 | static void iseries_writel(u32 data, volatile void __iomem *addr) |
675 | { | 605 | { |
676 | BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); | 606 | iSeries_Write_Long(cpu_to_le32(data), addr); |
677 | |||
678 | *(volatile unsigned long __force *)addr = v; | ||
679 | } | 607 | } |
680 | EXPORT_SYMBOL(__raw_writeq); | ||
681 | 608 | ||
682 | int in_8(const volatile unsigned char __iomem *addr) | 609 | static void iseries_writew_be(u16 data, volatile void __iomem *addr) |
683 | { | 610 | { |
684 | if (firmware_has_feature(FW_FEATURE_ISERIES)) | 611 | iSeries_Write_Word(data, addr); |
685 | return iSeries_Read_Byte(addr); | ||
686 | return __in_8(addr); | ||
687 | } | 612 | } |
688 | EXPORT_SYMBOL(in_8); | ||
689 | 613 | ||
690 | void out_8(volatile unsigned char __iomem *addr, int val) | 614 | static void iseries_writel_be(u32 data, volatile void __iomem *addr) |
691 | { | 615 | { |
692 | if (firmware_has_feature(FW_FEATURE_ISERIES)) | 616 | iSeries_Write_Long(data, addr); |
693 | iSeries_Write_Byte(val, addr); | ||
694 | else | ||
695 | __out_8(addr, val); | ||
696 | } | 617 | } |
697 | EXPORT_SYMBOL(out_8); | ||
698 | 618 | ||
699 | int in_le16(const volatile unsigned short __iomem *addr) | 619 | static void iseries_readsb(const volatile void __iomem *addr, void *buf, |
620 | unsigned long count) | ||
700 | { | 621 | { |
701 | if (firmware_has_feature(FW_FEATURE_ISERIES)) | 622 | u8 *dst = buf; |
702 | return iSeries_Read_Word(addr); | 623 | while(count-- > 0) |
703 | return __in_le16(addr); | 624 | *(dst++) = iSeries_Read_Byte(addr); |
704 | } | 625 | } |
705 | EXPORT_SYMBOL(in_le16); | ||
706 | 626 | ||
707 | int in_be16(const volatile unsigned short __iomem *addr) | 627 | static void iseries_readsw(const volatile void __iomem *addr, void *buf, |
628 | unsigned long count) | ||
708 | { | 629 | { |
709 | BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); | 630 | u16 *dst = buf; |
710 | 631 | while(count-- > 0) | |
711 | return __in_be16(addr); | 632 | *(dst++) = iSeries_Read_Word(addr); |
712 | } | 633 | } |
713 | EXPORT_SYMBOL(in_be16); | ||
714 | 634 | ||
715 | void out_le16(volatile unsigned short __iomem *addr, int val) | 635 | static void iseries_readsl(const volatile void __iomem *addr, void *buf, |
636 | unsigned long count) | ||
716 | { | 637 | { |
717 | if (firmware_has_feature(FW_FEATURE_ISERIES)) | 638 | u32 *dst = buf; |
718 | iSeries_Write_Word(val, addr); | 639 | while(count-- > 0) |
719 | else | 640 | *(dst++) = iSeries_Read_Long(addr); |
720 | __out_le16(addr, val); | ||
721 | } | 641 | } |
722 | EXPORT_SYMBOL(out_le16); | ||
723 | 642 | ||
724 | void out_be16(volatile unsigned short __iomem *addr, int val) | 643 | static void iseries_writesb(volatile void __iomem *addr, const void *buf, |
644 | unsigned long count) | ||
725 | { | 645 | { |
726 | BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); | 646 | const u8 *src = buf; |
727 | 647 | while(count-- > 0) | |
728 | __out_be16(addr, val); | 648 | iSeries_Write_Byte(*(src++), addr); |
729 | } | 649 | } |
730 | EXPORT_SYMBOL(out_be16); | ||
731 | 650 | ||
732 | unsigned in_le32(const volatile unsigned __iomem *addr) | 651 | static void iseries_writesw(volatile void __iomem *addr, const void *buf, |
652 | unsigned long count) | ||
733 | { | 653 | { |
734 | if (firmware_has_feature(FW_FEATURE_ISERIES)) | 654 | const u16 *src = buf; |
735 | return iSeries_Read_Long(addr); | 655 | while(count-- > 0) |
736 | return __in_le32(addr); | 656 | iSeries_Write_Word(*(src++), addr); |
737 | } | 657 | } |
738 | EXPORT_SYMBOL(in_le32); | ||
739 | 658 | ||
740 | unsigned in_be32(const volatile unsigned __iomem *addr) | 659 | static void iseries_writesl(volatile void __iomem *addr, const void *buf, |
660 | unsigned long count) | ||
741 | { | 661 | { |
742 | BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); | 662 | const u32 *src = buf; |
743 | 663 | while(count-- > 0) | |
744 | return __in_be32(addr); | 664 | iSeries_Write_Long(*(src++), addr); |
745 | } | 665 | } |
746 | EXPORT_SYMBOL(in_be32); | ||
747 | 666 | ||
748 | void out_le32(volatile unsigned __iomem *addr, int val) | 667 | static void iseries_memset_io(volatile void __iomem *addr, int c, |
668 | unsigned long n) | ||
749 | { | 669 | { |
750 | if (firmware_has_feature(FW_FEATURE_ISERIES)) | 670 | volatile char __iomem *d = addr; |
751 | iSeries_Write_Long(val, addr); | ||
752 | else | ||
753 | __out_le32(addr, val); | ||
754 | } | ||
755 | EXPORT_SYMBOL(out_le32); | ||
756 | 671 | ||
757 | void out_be32(volatile unsigned __iomem *addr, int val) | 672 | while (n-- > 0) |
758 | { | 673 | iSeries_Write_Byte(c, d++); |
759 | BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); | ||
760 | |||
761 | __out_be32(addr, val); | ||
762 | } | 674 | } |
763 | EXPORT_SYMBOL(out_be32); | ||
764 | 675 | ||
765 | unsigned long in_le64(const volatile unsigned long __iomem *addr) | 676 | static void iseries_memcpy_fromio(void *dest, const volatile void __iomem *src, |
677 | unsigned long n) | ||
766 | { | 678 | { |
767 | BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); | 679 | char *d = dest; |
680 | const volatile char __iomem *s = src; | ||
768 | 681 | ||
769 | return __in_le64(addr); | 682 | while (n-- > 0) |
683 | *d++ = iSeries_Read_Byte(s++); | ||
770 | } | 684 | } |
771 | EXPORT_SYMBOL(in_le64); | ||
772 | 685 | ||
773 | unsigned long in_be64(const volatile unsigned long __iomem *addr) | 686 | static void iseries_memcpy_toio(volatile void __iomem *dest, const void *src, |
687 | unsigned long n) | ||
774 | { | 688 | { |
775 | BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); | 689 | const char *s = src; |
690 | volatile char __iomem *d = dest; | ||
776 | 691 | ||
777 | return __in_be64(addr); | 692 | while (n-- > 0) |
693 | iSeries_Write_Byte(*s++, d++); | ||
778 | } | 694 | } |
779 | EXPORT_SYMBOL(in_be64); | ||
780 | |||
781 | void out_le64(volatile unsigned long __iomem *addr, unsigned long val) | ||
782 | { | ||
783 | BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); | ||
784 | 695 | ||
785 | __out_le64(addr, val); | 696 | /* We only set MMIO ops. The default PIO ops will be default |
786 | } | 697 | * to the MMIO ops + pci_io_base which is 0 on iSeries as |
787 | EXPORT_SYMBOL(out_le64); | 698 | * expected so both should work. |
699 | * | ||
700 | * Note that we don't implement the readq/writeq versions as | ||
701 | * I don't know of an HV call for doing so. Thus, the default | ||
702 | * operation will be used instead, which will fault a the value | ||
703 | * return by iSeries for MMIO addresses always hits a non mapped | ||
704 | * area. This is as good as the BUG() we used to have there. | ||
705 | */ | ||
706 | static struct ppc_pci_io __initdata iseries_pci_io = { | ||
707 | .readb = iseries_readb, | ||
708 | .readw = iseries_readw, | ||
709 | .readl = iseries_readl, | ||
710 | .readw_be = iseries_readw_be, | ||
711 | .readl_be = iseries_readl_be, | ||
712 | .writeb = iseries_writeb, | ||
713 | .writew = iseries_writew, | ||
714 | .writel = iseries_writel, | ||
715 | .writew_be = iseries_writew_be, | ||
716 | .writel_be = iseries_writel_be, | ||
717 | .readsb = iseries_readsb, | ||
718 | .readsw = iseries_readsw, | ||
719 | .readsl = iseries_readsl, | ||
720 | .writesb = iseries_writesb, | ||
721 | .writesw = iseries_writesw, | ||
722 | .writesl = iseries_writesl, | ||
723 | .memset_io = iseries_memset_io, | ||
724 | .memcpy_fromio = iseries_memcpy_fromio, | ||
725 | .memcpy_toio = iseries_memcpy_toio, | ||
726 | }; | ||
788 | 727 | ||
789 | void out_be64(volatile unsigned long __iomem *addr, unsigned long val) | 728 | /* |
729 | * iSeries_pcibios_init | ||
730 | * | ||
731 | * Description: | ||
732 | * This function checks for all possible system PCI host bridges that connect | ||
733 | * PCI buses. The system hypervisor is queried as to the guest partition | ||
734 | * ownership status. A pci_controller is built for any bus which is partially | ||
735 | * owned or fully owned by this guest partition. | ||
736 | */ | ||
737 | void __init iSeries_pcibios_init(void) | ||
790 | { | 738 | { |
791 | BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES)); | 739 | struct pci_controller *phb; |
740 | struct device_node *root = of_find_node_by_path("/"); | ||
741 | struct device_node *node = NULL; | ||
792 | 742 | ||
793 | __out_be64(addr, val); | 743 | /* Install IO hooks */ |
794 | } | 744 | ppc_pci_io = iseries_pci_io; |
795 | EXPORT_SYMBOL(out_be64); | ||
796 | 745 | ||
797 | void memset_io(volatile void __iomem *addr, int c, unsigned long n) | 746 | if (root == NULL) { |
798 | { | 747 | printk(KERN_CRIT "iSeries_pcibios_init: can't find root " |
799 | if (firmware_has_feature(FW_FEATURE_ISERIES)) { | 748 | "of device tree\n"); |
800 | volatile char __iomem *d = addr; | 749 | return; |
750 | } | ||
751 | while ((node = of_get_next_child(root, node)) != NULL) { | ||
752 | HvBusNumber bus; | ||
753 | const u32 *busp; | ||
801 | 754 | ||
802 | while (n-- > 0) { | 755 | if ((node->type == NULL) || (strcmp(node->type, "pci") != 0)) |
803 | iSeries_Write_Byte(c, d++); | 756 | continue; |
804 | } | ||
805 | } else | ||
806 | eeh_memset_io(addr, c, n); | ||
807 | } | ||
808 | EXPORT_SYMBOL(memset_io); | ||
809 | 757 | ||
810 | void memcpy_fromio(void *dest, const volatile void __iomem *src, | 758 | busp = get_property(node, "bus-range", NULL); |
811 | unsigned long n) | 759 | if (busp == NULL) |
812 | { | 760 | continue; |
813 | if (firmware_has_feature(FW_FEATURE_ISERIES)) { | 761 | bus = *busp; |
814 | char *d = dest; | 762 | printk("bus %d appears to exist\n", bus); |
815 | const volatile char __iomem *s = src; | 763 | phb = pcibios_alloc_controller(node); |
764 | if (phb == NULL) | ||
765 | continue; | ||
816 | 766 | ||
817 | while (n-- > 0) { | 767 | phb->pci_mem_offset = phb->local_number = bus; |
818 | *d++ = iSeries_Read_Byte(s++); | 768 | phb->first_busno = bus; |
819 | } | 769 | phb->last_busno = bus; |
820 | } else | 770 | phb->ops = &iSeries_pci_ops; |
821 | eeh_memcpy_fromio(dest, src, n); | 771 | } |
822 | } | ||
823 | EXPORT_SYMBOL(memcpy_fromio); | ||
824 | 772 | ||
825 | void memcpy_toio(volatile void __iomem *dest, const void *src, unsigned long n) | 773 | of_node_put(root); |
826 | { | ||
827 | if (firmware_has_feature(FW_FEATURE_ISERIES)) { | ||
828 | const char *s = src; | ||
829 | volatile char __iomem *d = dest; | ||
830 | 774 | ||
831 | while (n-- > 0) { | 775 | pci_devs_phb_init(); |
832 | iSeries_Write_Byte(*s++, d++); | ||
833 | } | ||
834 | } else | ||
835 | eeh_memcpy_toio(dest, src, n); | ||
836 | } | 776 | } |
837 | EXPORT_SYMBOL(memcpy_toio); | 777 | |