Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[POWERPC] 4xx: PLB to PCI Express support

This adds to the previous 2 patches the support for the 4xx PCI Express
cells as found in the 440SPe revA, revB and 405EX.

Unfortunately, due to significant differences between these, and other
interesting "features" of those pieces of HW, the code isn't as simple
as it is for PCI and PCI-X and some of the functions differ significantly
between the 3 implementations. Thus, not only this code can only support
those 3 implementations for now and will refuse to operate on any other,
but there are added ifdef's to avoid the bloat of building a fairly large
amount of code on platforms that don't need it.

Also, this code currently only supports fully initializing root complex
nodes, not endpoint. Some more code will have to be lifted from the
arch/ppc implementation to add the endpoint support, though it's mostly
differences in memory mapping, and the question on how to represent
endpoint mode PCI in the device-tree is thus open.

Many thanks to Stefan Roese for testing & fixing up the 405EX bits !

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Stefan Roese <sr@denx.de>
Signed-off-by: Josh Boyer <jwboyer@linux.vnet.ibm.com>

authored by

Benjamin Herrenschmidt and committed by
Josh Boyer
a2d2e1ec c839e0ef

+1227 -18
+1
arch/powerpc/Kconfig
··· 166 166 167 167 source "init/Kconfig" 168 168 169 + source "arch/powerpc/sysdev/Kconfig" 169 170 source "arch/powerpc/platforms/Kconfig" 170 171 171 172 menu "Kernel options"
+8
arch/powerpc/sysdev/Kconfig
··· 1 + # For a description of the syntax of this configuration file, 2 + # see Documentation/kbuild/kconfig-language.txt. 3 + # 4 + 5 + config PPC4xx_PCI_EXPRESS 6 + bool 7 + depends on PCI && 4xx 8 + default n
+976 -18
arch/powerpc/sysdev/ppc4xx_pci.c
··· 3 3 * 4 4 * Copyright 2007 Ben. Herrenschmidt <benh@kernel.crashing.org>, IBM Corp. 5 5 * 6 + * Most PCI Express code is coming from Stefan Roese implementation for 7 + * arch/ppc in the Denx tree, slightly reworked by me. 8 + * 9 + * Copyright 2007 DENX Software Engineering, Stefan Roese <sr@denx.de> 10 + * 11 + * Some of that comes itself from a previous implementation for 440SPE only 12 + * by Roland Dreier: 13 + * 14 + * Copyright (c) 2005 Cisco Systems. All rights reserved. 15 + * Roland Dreier <rolandd@cisco.com> 16 + * 6 17 */ 7 18 8 19 #include <linux/kernel.h> 9 20 #include <linux/pci.h> 10 21 #include <linux/init.h> 11 22 #include <linux/of.h> 23 + #include <linux/bootmem.h> 24 + #include <linux/delay.h> 12 25 13 26 #include <asm/io.h> 14 27 #include <asm/pci-bridge.h> 15 28 #include <asm/machdep.h> 29 + #include <asm/dcr.h> 30 + #include <asm/dcr-regs.h> 16 31 17 32 #include "ppc4xx_pci.h" 18 33 ··· 35 20 36 21 /* Move that to a useable header */ 37 22 extern unsigned long total_memory; 23 + 24 + #define U64_TO_U32_LOW(val) ((u32)((val) & 0x00000000ffffffffULL)) 25 + #define U64_TO_U32_HIGH(val) ((u32)((val) >> 32)) 26 + 27 + #ifdef CONFIG_RESOURCES_64BIT 28 + #define RES_TO_U32_LOW(val) U64_TO_U32_LOW(val) 29 + #define RES_TO_U32_HIGH(val) U64_TO_U32_HIGH(val) 30 + #else 31 + #define RES_TO_U32_LOW(val) (val) 32 + #define RES_TO_U32_HIGH(val) (0) 33 + #endif 38 34 39 35 static void fixup_ppc4xx_pci_bridge(struct pci_dev *dev) 40 36 { ··· 204 178 205 179 /* Calculate register values */ 206 180 la = res->start; 207 - #ifdef CONFIG_RESOURCES_64BIT 208 - pciha = (res->start - hose->pci_mem_offset) >> 32; 209 - pcila = (res->start - hose->pci_mem_offset) & 0xffffffffu; 210 - #else 211 - pciha = 0; 212 - pcila = res->start - hose->pci_mem_offset; 213 - #endif 181 + pciha = RES_TO_U32_HIGH(res->start - hose->pci_mem_offset); 182 + pcila = RES_TO_U32_LOW(res->start - hose->pci_mem_offset); 214 183 215 184 ma = res->end + 1 - res->start; 216 185 if (!is_power_of_2(ma) || ma < 0x1000 || ma > 0xffffffffu) { ··· 354 333 } 355 334 356 335 /* Calculate register values */ 357 - #ifdef CONFIG_RESOURCES_64BIT 358 - lah = res->start >> 32; 359 - lal = res->start & 0xffffffffu; 360 - pciah = (res->start - hose->pci_mem_offset) >> 32; 361 - pcial = (res->start - hose->pci_mem_offset) & 0xffffffffu; 362 - #else 363 - lah = pciah = 0; 364 - lal = res->start; 365 - pcial = res->start - hose->pci_mem_offset; 366 - #endif 336 + lah = RES_TO_U32_HIGH(res->start); 337 + lal = RES_TO_U32_LOW(res->start); 338 + pciah = RES_TO_U32_HIGH(res->start - hose->pci_mem_offset); 339 + pcial = RES_TO_U32_LOW(res->start - hose->pci_mem_offset); 367 340 sa = res->end + 1 - res->start; 368 341 if (!is_power_of_2(sa) || sa < 0x100000 || 369 342 sa > 0xffffffffu) { ··· 507 492 iounmap(reg); 508 493 } 509 494 495 + #ifdef CONFIG_PPC4xx_PCI_EXPRESS 496 + 510 497 /* 511 498 * 4xx PCI-Express part 499 + * 500 + * We support 3 parts currently based on the compatible property: 501 + * 502 + * ibm,plb-pciex-440speA 503 + * ibm,plb-pciex-440speB 504 + * ibm,plb-pciex-405ex 505 + * 506 + * Anything else will be rejected for now as they are all subtly 507 + * different unfortunately. 508 + * 512 509 */ 510 + 511 + #define MAX_PCIE_BUS_MAPPED 0x10 512 + 513 + struct ppc4xx_pciex_port 514 + { 515 + struct pci_controller *hose; 516 + struct device_node *node; 517 + unsigned int index; 518 + int endpoint; 519 + unsigned int sdr_base; 520 + dcr_host_t dcrs; 521 + struct resource cfg_space; 522 + struct resource utl_regs; 523 + }; 524 + 525 + static struct ppc4xx_pciex_port *ppc4xx_pciex_ports; 526 + static unsigned int ppc4xx_pciex_port_count; 527 + 528 + struct ppc4xx_pciex_hwops 529 + { 530 + int (*core_init)(struct device_node *np); 531 + int (*port_init_hw)(struct ppc4xx_pciex_port *port); 532 + int (*setup_utl)(struct ppc4xx_pciex_port *port); 533 + }; 534 + 535 + static struct ppc4xx_pciex_hwops *ppc4xx_pciex_hwops; 536 + 537 + #ifdef CONFIG_44x 538 + 539 + /* Check various reset bits of the 440SPe PCIe core */ 540 + static int __init ppc440spe_pciex_check_reset(struct device_node *np) 541 + { 542 + u32 valPE0, valPE1, valPE2; 543 + int err = 0; 544 + 545 + /* SDR0_PEGPLLLCT1 reset */ 546 + if (!(mfdcri(SDR0, PESDR0_PLLLCT1) & 0x01000000)) { 547 + /* 548 + * the PCIe core was probably already initialised 549 + * by firmware - let's re-reset RCSSET regs 550 + * 551 + * -- Shouldn't we also re-reset the whole thing ? -- BenH 552 + */ 553 + pr_debug("PCIE: SDR0_PLLLCT1 already reset.\n"); 554 + mtdcri(SDR0, PESDR0_440SPE_RCSSET, 0x01010000); 555 + mtdcri(SDR0, PESDR1_440SPE_RCSSET, 0x01010000); 556 + mtdcri(SDR0, PESDR2_440SPE_RCSSET, 0x01010000); 557 + } 558 + 559 + valPE0 = mfdcri(SDR0, PESDR0_440SPE_RCSSET); 560 + valPE1 = mfdcri(SDR0, PESDR1_440SPE_RCSSET); 561 + valPE2 = mfdcri(SDR0, PESDR2_440SPE_RCSSET); 562 + 563 + /* SDR0_PExRCSSET rstgu */ 564 + if (!(valPE0 & 0x01000000) || 565 + !(valPE1 & 0x01000000) || 566 + !(valPE2 & 0x01000000)) { 567 + printk(KERN_INFO "PCIE: SDR0_PExRCSSET rstgu error\n"); 568 + err = -1; 569 + } 570 + 571 + /* SDR0_PExRCSSET rstdl */ 572 + if (!(valPE0 & 0x00010000) || 573 + !(valPE1 & 0x00010000) || 574 + !(valPE2 & 0x00010000)) { 575 + printk(KERN_INFO "PCIE: SDR0_PExRCSSET rstdl error\n"); 576 + err = -1; 577 + } 578 + 579 + /* SDR0_PExRCSSET rstpyn */ 580 + if ((valPE0 & 0x00001000) || 581 + (valPE1 & 0x00001000) || 582 + (valPE2 & 0x00001000)) { 583 + printk(KERN_INFO "PCIE: SDR0_PExRCSSET rstpyn error\n"); 584 + err = -1; 585 + } 586 + 587 + /* SDR0_PExRCSSET hldplb */ 588 + if ((valPE0 & 0x10000000) || 589 + (valPE1 & 0x10000000) || 590 + (valPE2 & 0x10000000)) { 591 + printk(KERN_INFO "PCIE: SDR0_PExRCSSET hldplb error\n"); 592 + err = -1; 593 + } 594 + 595 + /* SDR0_PExRCSSET rdy */ 596 + if ((valPE0 & 0x00100000) || 597 + (valPE1 & 0x00100000) || 598 + (valPE2 & 0x00100000)) { 599 + printk(KERN_INFO "PCIE: SDR0_PExRCSSET rdy error\n"); 600 + err = -1; 601 + } 602 + 603 + /* SDR0_PExRCSSET shutdown */ 604 + if ((valPE0 & 0x00000100) || 605 + (valPE1 & 0x00000100) || 606 + (valPE2 & 0x00000100)) { 607 + printk(KERN_INFO "PCIE: SDR0_PExRCSSET shutdown error\n"); 608 + err = -1; 609 + } 610 + 611 + return err; 612 + } 613 + 614 + /* Global PCIe core initializations for 440SPe core */ 615 + static int __init ppc440spe_pciex_core_init(struct device_node *np) 616 + { 617 + int time_out = 20; 618 + 619 + /* Set PLL clock receiver to LVPECL */ 620 + mtdcri(SDR0, PESDR0_PLLLCT1, mfdcri(SDR0, PESDR0_PLLLCT1) | 1 << 28); 621 + 622 + /* Shouldn't we do all the calibration stuff etc... here ? */ 623 + if (ppc440spe_pciex_check_reset(np)) 624 + return -ENXIO; 625 + 626 + if (!(mfdcri(SDR0, PESDR0_PLLLCT2) & 0x10000)) { 627 + printk(KERN_INFO "PCIE: PESDR_PLLCT2 resistance calibration " 628 + "failed (0x%08x)\n", 629 + mfdcri(SDR0, PESDR0_PLLLCT2)); 630 + return -1; 631 + } 632 + 633 + /* De-assert reset of PCIe PLL, wait for lock */ 634 + mtdcri(SDR0, PESDR0_PLLLCT1, 635 + mfdcri(SDR0, PESDR0_PLLLCT1) & ~(1 << 24)); 636 + udelay(3); 637 + 638 + while (time_out) { 639 + if (!(mfdcri(SDR0, PESDR0_PLLLCT3) & 0x10000000)) { 640 + time_out--; 641 + udelay(1); 642 + } else 643 + break; 644 + } 645 + if (!time_out) { 646 + printk(KERN_INFO "PCIE: VCO output not locked\n"); 647 + return -1; 648 + } 649 + 650 + pr_debug("PCIE initialization OK\n"); 651 + 652 + return 3; 653 + } 654 + 655 + static int ppc440spe_pciex_init_port_hw(struct ppc4xx_pciex_port *port) 656 + { 657 + u32 val = 1 << 24; 658 + 659 + if (port->endpoint) 660 + val = PTYPE_LEGACY_ENDPOINT << 20; 661 + else 662 + val = PTYPE_ROOT_PORT << 20; 663 + 664 + if (port->index == 0) 665 + val |= LNKW_X8 << 12; 666 + else 667 + val |= LNKW_X4 << 12; 668 + 669 + mtdcri(SDR0, port->sdr_base + PESDRn_DLPSET, val); 670 + mtdcri(SDR0, port->sdr_base + PESDRn_UTLSET1, 0x20222222); 671 + if (of_device_is_compatible(port->node, "ibm,plb-pciex-440speA")) 672 + mtdcri(SDR0, port->sdr_base + PESDRn_UTLSET2, 0x11000000); 673 + mtdcri(SDR0, port->sdr_base + PESDRn_440SPE_HSSL0SET1, 0x35000000); 674 + mtdcri(SDR0, port->sdr_base + PESDRn_440SPE_HSSL1SET1, 0x35000000); 675 + mtdcri(SDR0, port->sdr_base + PESDRn_440SPE_HSSL2SET1, 0x35000000); 676 + mtdcri(SDR0, port->sdr_base + PESDRn_440SPE_HSSL3SET1, 0x35000000); 677 + if (port->index == 0) { 678 + mtdcri(SDR0, port->sdr_base + PESDRn_440SPE_HSSL4SET1, 679 + 0x35000000); 680 + mtdcri(SDR0, port->sdr_base + PESDRn_440SPE_HSSL5SET1, 681 + 0x35000000); 682 + mtdcri(SDR0, port->sdr_base + PESDRn_440SPE_HSSL6SET1, 683 + 0x35000000); 684 + mtdcri(SDR0, port->sdr_base + PESDRn_440SPE_HSSL7SET1, 685 + 0x35000000); 686 + } 687 + val = mfdcri(SDR0, port->sdr_base + PESDRn_RCSSET); 688 + mtdcri(SDR0, port->sdr_base + PESDRn_RCSSET, 689 + (val & ~(1 << 24 | 1 << 16)) | 1 << 12); 690 + 691 + return 0; 692 + } 693 + 694 + static int ppc440speA_pciex_init_utl(struct ppc4xx_pciex_port *port) 695 + { 696 + void __iomem *utl_base; 697 + 698 + /* XXX Check what that value means... I hate magic */ 699 + dcr_write(port->dcrs, DCRO_PEGPL_SPECIAL, 0x68782800); 700 + 701 + utl_base = ioremap(port->utl_regs.start, 0x100); 702 + BUG_ON(utl_base == NULL); 703 + 704 + /* 705 + * Set buffer allocations and then assert VRB and TXE. 706 + */ 707 + out_be32(utl_base + PEUTL_OUTTR, 0x08000000); 708 + out_be32(utl_base + PEUTL_INTR, 0x02000000); 709 + out_be32(utl_base + PEUTL_OPDBSZ, 0x10000000); 710 + out_be32(utl_base + PEUTL_PBBSZ, 0x53000000); 711 + out_be32(utl_base + PEUTL_IPHBSZ, 0x08000000); 712 + out_be32(utl_base + PEUTL_IPDBSZ, 0x10000000); 713 + out_be32(utl_base + PEUTL_RCIRQEN, 0x00f00000); 714 + out_be32(utl_base + PEUTL_PCTL, 0x80800066); 715 + 716 + iounmap(utl_base); 717 + 718 + return 0; 719 + } 720 + 721 + static struct ppc4xx_pciex_hwops ppc440speA_pcie_hwops __initdata = 722 + { 723 + .core_init = ppc440spe_pciex_core_init, 724 + .port_init_hw = ppc440spe_pciex_init_port_hw, 725 + .setup_utl = ppc440speA_pciex_init_utl, 726 + }; 727 + 728 + static struct ppc4xx_pciex_hwops ppc440speB_pcie_hwops __initdata = 729 + { 730 + .core_init = ppc440spe_pciex_core_init, 731 + .port_init_hw = ppc440spe_pciex_init_port_hw, 732 + }; 733 + 734 + 735 + #endif /* CONFIG_44x */ 736 + 737 + #ifdef CONFIG_40x 738 + 739 + static int __init ppc405ex_pciex_core_init(struct device_node *np) 740 + { 741 + /* Nothing to do, return 2 ports */ 742 + return 2; 743 + } 744 + 745 + static void ppc405ex_pcie_phy_reset(struct ppc4xx_pciex_port *port) 746 + { 747 + /* Assert the PE0_PHY reset */ 748 + mtdcri(SDR0, port->sdr_base + PESDRn_RCSSET, 0x01010000); 749 + msleep(1); 750 + 751 + /* deassert the PE0_hotreset */ 752 + if (port->endpoint) 753 + mtdcri(SDR0, port->sdr_base + PESDRn_RCSSET, 0x01111000); 754 + else 755 + mtdcri(SDR0, port->sdr_base + PESDRn_RCSSET, 0x01101000); 756 + 757 + /* poll for phy !reset */ 758 + /* XXX FIXME add timeout */ 759 + while (!(mfdcri(SDR0, port->sdr_base + PESDRn_405EX_PHYSTA) & 0x00001000)) 760 + ; 761 + 762 + /* deassert the PE0_gpl_utl_reset */ 763 + mtdcri(SDR0, port->sdr_base + PESDRn_RCSSET, 0x00101000); 764 + } 765 + 766 + static int ppc405ex_pciex_init_port_hw(struct ppc4xx_pciex_port *port) 767 + { 768 + u32 val; 769 + 770 + if (port->endpoint) 771 + val = PTYPE_LEGACY_ENDPOINT; 772 + else 773 + val = PTYPE_ROOT_PORT; 774 + 775 + mtdcri(SDR0, port->sdr_base + PESDRn_DLPSET, 776 + 1 << 24 | val << 20 | LNKW_X1 << 12); 777 + 778 + mtdcri(SDR0, port->sdr_base + PESDRn_UTLSET1, 0x00000000); 779 + mtdcri(SDR0, port->sdr_base + PESDRn_UTLSET2, 0x01010000); 780 + mtdcri(SDR0, port->sdr_base + PESDRn_405EX_PHYSET1, 0x720F0000); 781 + mtdcri(SDR0, port->sdr_base + PESDRn_405EX_PHYSET2, 0x70600003); 782 + 783 + /* 784 + * Only reset the PHY when no link is currently established. 785 + * This is for the Atheros PCIe board which has problems to establish 786 + * the link (again) after this PHY reset. All other currently tested 787 + * PCIe boards don't show this problem. 788 + * This has to be re-tested and fixed in a later release! 789 + */ 790 + #if 0 /* XXX FIXME: Not resetting the PHY will leave all resources 791 + * configured as done previously by U-Boot. Then Linux will currently 792 + * not reassign them. So the PHY reset is now done always. This will 793 + * lead to problems with the Atheros PCIe board again. 794 + */ 795 + val = mfdcri(SDR0, port->sdr_base + PESDRn_LOOP); 796 + if (!(val & 0x00001000)) 797 + ppc405ex_pcie_phy_reset(port); 798 + #else 799 + ppc405ex_pcie_phy_reset(port); 800 + #endif 801 + 802 + dcr_write(port->dcrs, DCRO_PEGPL_CFG, 0x10000000); /* guarded on */ 803 + 804 + return 0; 805 + } 806 + 807 + static int ppc405ex_pciex_init_utl(struct ppc4xx_pciex_port *port) 808 + { 809 + void __iomem *utl_base; 810 + 811 + dcr_write(port->dcrs, DCRO_PEGPL_SPECIAL, 0x0); 812 + 813 + utl_base = ioremap(port->utl_regs.start, 0x100); 814 + BUG_ON(utl_base == NULL); 815 + 816 + /* 817 + * Set buffer allocations and then assert VRB and TXE. 818 + */ 819 + out_be32(utl_base + PEUTL_OUTTR, 0x02000000); 820 + out_be32(utl_base + PEUTL_INTR, 0x02000000); 821 + out_be32(utl_base + PEUTL_OPDBSZ, 0x04000000); 822 + out_be32(utl_base + PEUTL_PBBSZ, 0x21000000); 823 + out_be32(utl_base + PEUTL_IPHBSZ, 0x02000000); 824 + out_be32(utl_base + PEUTL_IPDBSZ, 0x04000000); 825 + out_be32(utl_base + PEUTL_RCIRQEN, 0x00f00000); 826 + out_be32(utl_base + PEUTL_PCTL, 0x80800066); 827 + 828 + out_be32(utl_base + PEUTL_PBCTL, 0x0800000c); 829 + out_be32(utl_base + PEUTL_RCSTA, 830 + in_be32(utl_base + PEUTL_RCSTA) | 0x000040000); 831 + 832 + iounmap(utl_base); 833 + 834 + return 0; 835 + } 836 + 837 + static struct ppc4xx_pciex_hwops ppc405ex_pcie_hwops __initdata = 838 + { 839 + .core_init = ppc405ex_pciex_core_init, 840 + .port_init_hw = ppc405ex_pciex_init_port_hw, 841 + .setup_utl = ppc405ex_pciex_init_utl, 842 + }; 843 + 844 + #endif /* CONFIG_40x */ 845 + 846 + 847 + /* Check that the core has been initied and if not, do it */ 848 + static int __init ppc4xx_pciex_check_core_init(struct device_node *np) 849 + { 850 + static int core_init; 851 + int count = -ENODEV; 852 + 853 + if (core_init++) 854 + return 0; 855 + 856 + #ifdef CONFIG_44x 857 + if (of_device_is_compatible(np, "ibm,plb-pciex-440speA")) 858 + ppc4xx_pciex_hwops = &ppc440speA_pcie_hwops; 859 + else if (of_device_is_compatible(np, "ibm,plb-pciex-440speB")) 860 + ppc4xx_pciex_hwops = &ppc440speB_pcie_hwops; 861 + #endif /* CONFIG_44x */ 862 + #ifdef CONFIG_40x 863 + if (of_device_is_compatible(np, "ibm,plb-pciex-405ex")) 864 + ppc4xx_pciex_hwops = &ppc405ex_pcie_hwops; 865 + #endif 866 + if (ppc4xx_pciex_hwops == NULL) { 867 + printk(KERN_WARNING "PCIE: unknown host type %s\n", 868 + np->full_name); 869 + return -ENODEV; 870 + } 871 + 872 + count = ppc4xx_pciex_hwops->core_init(np); 873 + if (count > 0) { 874 + ppc4xx_pciex_ports = 875 + kzalloc(count * sizeof(struct ppc4xx_pciex_port), 876 + GFP_KERNEL); 877 + if (ppc4xx_pciex_ports) { 878 + ppc4xx_pciex_port_count = count; 879 + return 0; 880 + } 881 + printk(KERN_WARNING "PCIE: failed to allocate ports array\n"); 882 + return -ENOMEM; 883 + } 884 + return -ENODEV; 885 + } 886 + 887 + static void __init ppc4xx_pciex_port_init_mapping(struct ppc4xx_pciex_port *port) 888 + { 889 + /* We map PCI Express configuration based on the reg property */ 890 + dcr_write(port->dcrs, DCRO_PEGPL_CFGBAH, 891 + RES_TO_U32_HIGH(port->cfg_space.start)); 892 + dcr_write(port->dcrs, DCRO_PEGPL_CFGBAL, 893 + RES_TO_U32_LOW(port->cfg_space.start)); 894 + 895 + /* XXX FIXME: Use size from reg property. For now, map 512M */ 896 + dcr_write(port->dcrs, DCRO_PEGPL_CFGMSK, 0xe0000001); 897 + 898 + /* We map UTL registers based on the reg property */ 899 + dcr_write(port->dcrs, DCRO_PEGPL_REGBAH, 900 + RES_TO_U32_HIGH(port->utl_regs.start)); 901 + dcr_write(port->dcrs, DCRO_PEGPL_REGBAL, 902 + RES_TO_U32_LOW(port->utl_regs.start)); 903 + 904 + /* XXX FIXME: Use size from reg property */ 905 + dcr_write(port->dcrs, DCRO_PEGPL_REGMSK, 0x00007001); 906 + 907 + /* Disable all other outbound windows */ 908 + dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKL, 0); 909 + dcr_write(port->dcrs, DCRO_PEGPL_OMR2MSKL, 0); 910 + dcr_write(port->dcrs, DCRO_PEGPL_OMR3MSKL, 0); 911 + dcr_write(port->dcrs, DCRO_PEGPL_MSGMSK, 0); 912 + } 913 + 914 + static int __init ppc4xx_pciex_port_init(struct ppc4xx_pciex_port *port) 915 + { 916 + int attempts, rc = 0; 917 + u32 val; 918 + 919 + /* Check if it's endpoint or root complex 920 + * 921 + * XXX Do we want to use the device-tree instead ? --BenH. 922 + */ 923 + val = mfdcri(SDR0, port->sdr_base + PESDRn_DLPSET); 924 + port->endpoint = (((val >> 20) & 0xf) != PTYPE_ROOT_PORT); 925 + 926 + /* Init HW */ 927 + if (ppc4xx_pciex_hwops->port_init_hw) 928 + rc = ppc4xx_pciex_hwops->port_init_hw(port); 929 + if (rc != 0) 930 + return rc; 931 + 932 + /* 933 + * Notice: the following delay has critical impact on device 934 + * initialization - if too short (<50ms) the link doesn't get up. 935 + * 936 + * XXX FIXME: There are various issues with that link up thingy, 937 + * we could just wait for the link with a timeout but Stefan says 938 + * some cards need more time even after the link is up. I'll 939 + * investigate. For now, we keep a fixed 1s delay. 940 + * 941 + * Ultimately, it should be made asynchronous so all ports are 942 + * brought up simultaneously though. 943 + */ 944 + printk(KERN_INFO "PCIE%d: Waiting for link to go up...\n", 945 + port->index); 946 + msleep(1000); 947 + 948 + /* 949 + * Check that we exited the reset state properly 950 + */ 951 + val = mfdcri(SDR0, port->sdr_base + PESDRn_RCSSTS); 952 + if (val & (1 << 20)) { 953 + printk(KERN_WARNING "PCIE%d: PGRST failed %08x\n", 954 + port->index, val); 955 + return -1; 956 + } 957 + 958 + /* 959 + * Verify link is up 960 + */ 961 + val = mfdcri(SDR0, port->sdr_base + PESDRn_LOOP); 962 + if (!(val & 0x00001000)) { 963 + printk(KERN_INFO "PCIE%d: link is not up !\n", 964 + port->index); 965 + return -1; 966 + } 967 + 968 + printk(KERN_INFO "PCIE%d: link is up !\n", 969 + port->index); 970 + 971 + /* 972 + * Initialize mapping: disable all regions and configure 973 + * CFG and REG regions based on resources in the device tree 974 + */ 975 + ppc4xx_pciex_port_init_mapping(port); 976 + 977 + /* 978 + * Setup UTL registers - but only on revA! 979 + * We use default settings for revB chip. 980 + * 981 + * To be reworked. We may also be able to move that to 982 + * before the link wait 983 + * --BenH. 984 + */ 985 + if (ppc4xx_pciex_hwops->setup_utl) 986 + ppc4xx_pciex_hwops->setup_utl(port); 987 + 988 + /* 989 + * Check for VC0 active and assert RDY. 990 + */ 991 + attempts = 10; 992 + while (!(mfdcri(SDR0, port->sdr_base + PESDRn_RCSSTS) & (1 << 16))) { 993 + if (!(attempts--)) { 994 + printk(KERN_INFO "PCIE%d: VC0 not active\n", 995 + port->index); 996 + return -1; 997 + } 998 + msleep(1000); 999 + } 1000 + mtdcri(SDR0, port->sdr_base + PESDRn_RCSSET, 1001 + mfdcri(SDR0, port->sdr_base + PESDRn_RCSSET) | 1 << 20); 1002 + msleep(100); 1003 + 1004 + return 0; 1005 + } 1006 + 1007 + static int ppc4xx_pciex_validate_bdf(struct ppc4xx_pciex_port *port, 1008 + struct pci_bus *bus, 1009 + unsigned int devfn) 1010 + { 1011 + static int message; 1012 + 1013 + /* Endpoint can not generate upstream(remote) config cycles */ 1014 + if (port->endpoint && bus->number != port->hose->first_busno) 1015 + return PCIBIOS_DEVICE_NOT_FOUND; 1016 + 1017 + /* Check we are within the mapped range */ 1018 + if (bus->number > port->hose->last_busno) { 1019 + if (!message) { 1020 + printk(KERN_WARNING "Warning! Probing bus %u" 1021 + " out of range !\n", bus->number); 1022 + message++; 1023 + } 1024 + return PCIBIOS_DEVICE_NOT_FOUND; 1025 + } 1026 + 1027 + /* The root complex has only one device / function */ 1028 + if (bus->number == port->hose->first_busno && devfn != 0) 1029 + return PCIBIOS_DEVICE_NOT_FOUND; 1030 + 1031 + /* The other side of the RC has only one device as well */ 1032 + if (bus->number == (port->hose->first_busno + 1) && 1033 + PCI_SLOT(devfn) != 0) 1034 + return PCIBIOS_DEVICE_NOT_FOUND; 1035 + 1036 + return 0; 1037 + } 1038 + 1039 + static void __iomem *ppc4xx_pciex_get_config_base(struct ppc4xx_pciex_port *port, 1040 + struct pci_bus *bus, 1041 + unsigned int devfn) 1042 + { 1043 + int relbus; 1044 + 1045 + /* Remove the casts when we finally remove the stupid volatile 1046 + * in struct pci_controller 1047 + */ 1048 + if (bus->number == port->hose->first_busno) 1049 + return (void __iomem *)port->hose->cfg_addr; 1050 + 1051 + relbus = bus->number - (port->hose->first_busno + 1); 1052 + return (void __iomem *)port->hose->cfg_data + 1053 + ((relbus << 20) | (devfn << 12)); 1054 + } 1055 + 1056 + static int ppc4xx_pciex_read_config(struct pci_bus *bus, unsigned int devfn, 1057 + int offset, int len, u32 *val) 1058 + { 1059 + struct pci_controller *hose = (struct pci_controller *) bus->sysdata; 1060 + struct ppc4xx_pciex_port *port = 1061 + &ppc4xx_pciex_ports[hose->indirect_type]; 1062 + void __iomem *addr; 1063 + u32 gpl_cfg; 1064 + 1065 + BUG_ON(hose != port->hose); 1066 + 1067 + if (ppc4xx_pciex_validate_bdf(port, bus, devfn) != 0) 1068 + return PCIBIOS_DEVICE_NOT_FOUND; 1069 + 1070 + addr = ppc4xx_pciex_get_config_base(port, bus, devfn); 1071 + 1072 + /* 1073 + * Reading from configuration space of non-existing device can 1074 + * generate transaction errors. For the read duration we suppress 1075 + * assertion of machine check exceptions to avoid those. 1076 + */ 1077 + gpl_cfg = dcr_read(port->dcrs, DCRO_PEGPL_CFG); 1078 + dcr_write(port->dcrs, DCRO_PEGPL_CFG, gpl_cfg | GPL_DMER_MASK_DISA); 1079 + 1080 + switch (len) { 1081 + case 1: 1082 + *val = in_8((u8 *)(addr + offset)); 1083 + break; 1084 + case 2: 1085 + *val = in_le16((u16 *)(addr + offset)); 1086 + break; 1087 + default: 1088 + *val = in_le32((u32 *)(addr + offset)); 1089 + break; 1090 + } 1091 + 1092 + pr_debug("pcie-config-read: bus=%3d [%3d..%3d] devfn=0x%04x" 1093 + " offset=0x%04x len=%d, addr=0x%p val=0x%08x\n", 1094 + bus->number, hose->first_busno, hose->last_busno, 1095 + devfn, offset, len, addr + offset, *val); 1096 + 1097 + dcr_write(port->dcrs, DCRO_PEGPL_CFG, gpl_cfg); 1098 + 1099 + return PCIBIOS_SUCCESSFUL; 1100 + } 1101 + 1102 + static int ppc4xx_pciex_write_config(struct pci_bus *bus, unsigned int devfn, 1103 + int offset, int len, u32 val) 1104 + { 1105 + struct pci_controller *hose = (struct pci_controller *) bus->sysdata; 1106 + struct ppc4xx_pciex_port *port = 1107 + &ppc4xx_pciex_ports[hose->indirect_type]; 1108 + void __iomem *addr; 1109 + u32 gpl_cfg; 1110 + 1111 + if (ppc4xx_pciex_validate_bdf(port, bus, devfn) != 0) 1112 + return PCIBIOS_DEVICE_NOT_FOUND; 1113 + 1114 + addr = ppc4xx_pciex_get_config_base(port, bus, devfn); 1115 + 1116 + /* 1117 + * Reading from configuration space of non-existing device can 1118 + * generate transaction errors. For the read duration we suppress 1119 + * assertion of machine check exceptions to avoid those. 1120 + */ 1121 + gpl_cfg = dcr_read(port->dcrs, DCRO_PEGPL_CFG); 1122 + dcr_write(port->dcrs, DCRO_PEGPL_CFG, gpl_cfg | GPL_DMER_MASK_DISA); 1123 + 1124 + pr_debug("pcie-config-write: bus=%3d [%3d..%3d] devfn=0x%04x" 1125 + " offset=0x%04x len=%d, addr=0x%p val=0x%08x\n", 1126 + bus->number, hose->first_busno, hose->last_busno, 1127 + devfn, offset, len, addr + offset, val); 1128 + 1129 + switch (len) { 1130 + case 1: 1131 + out_8((u8 *)(addr + offset), val); 1132 + break; 1133 + case 2: 1134 + out_le16((u16 *)(addr + offset), val); 1135 + break; 1136 + default: 1137 + out_le32((u32 *)(addr + offset), val); 1138 + break; 1139 + } 1140 + 1141 + dcr_write(port->dcrs, DCRO_PEGPL_CFG, gpl_cfg); 1142 + 1143 + return PCIBIOS_SUCCESSFUL; 1144 + } 1145 + 1146 + static struct pci_ops ppc4xx_pciex_pci_ops = 1147 + { 1148 + .read = ppc4xx_pciex_read_config, 1149 + .write = ppc4xx_pciex_write_config, 1150 + }; 1151 + 1152 + static void __init ppc4xx_configure_pciex_POMs(struct ppc4xx_pciex_port *port, 1153 + struct pci_controller *hose, 1154 + void __iomem *mbase) 1155 + { 1156 + u32 lah, lal, pciah, pcial, sa; 1157 + int i, j; 1158 + 1159 + /* Setup outbound memory windows */ 1160 + for (i = j = 0; i < 3; i++) { 1161 + struct resource *res = &hose->mem_resources[i]; 1162 + 1163 + /* we only care about memory windows */ 1164 + if (!(res->flags & IORESOURCE_MEM)) 1165 + continue; 1166 + if (j > 1) { 1167 + printk(KERN_WARNING "%s: Too many ranges\n", 1168 + port->node->full_name); 1169 + break; 1170 + } 1171 + 1172 + /* Calculate register values */ 1173 + lah = RES_TO_U32_HIGH(res->start); 1174 + lal = RES_TO_U32_LOW(res->start); 1175 + pciah = RES_TO_U32_HIGH(res->start - hose->pci_mem_offset); 1176 + pcial = RES_TO_U32_LOW(res->start - hose->pci_mem_offset); 1177 + sa = res->end + 1 - res->start; 1178 + if (!is_power_of_2(sa) || sa < 0x100000 || 1179 + sa > 0xffffffffu) { 1180 + printk(KERN_WARNING "%s: Resource out of range\n", 1181 + port->node->full_name); 1182 + continue; 1183 + } 1184 + sa = (0xffffffffu << ilog2(sa)) | 0x1; 1185 + 1186 + /* Program register values */ 1187 + switch (j) { 1188 + case 0: 1189 + out_le32(mbase + PECFG_POM0LAH, pciah); 1190 + out_le32(mbase + PECFG_POM0LAL, pcial); 1191 + dcr_write(port->dcrs, DCRO_PEGPL_OMR1BAH, lah); 1192 + dcr_write(port->dcrs, DCRO_PEGPL_OMR1BAL, lal); 1193 + dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKH, 0x7fffffff); 1194 + dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKL, sa | 3); 1195 + break; 1196 + case 1: 1197 + out_le32(mbase + PECFG_POM1LAH, pciah); 1198 + out_le32(mbase + PECFG_POM1LAL, pcial); 1199 + dcr_write(port->dcrs, DCRO_PEGPL_OMR2BAH, lah); 1200 + dcr_write(port->dcrs, DCRO_PEGPL_OMR2BAL, lal); 1201 + dcr_write(port->dcrs, DCRO_PEGPL_OMR2MSKH, 0x7fffffff); 1202 + dcr_write(port->dcrs, DCRO_PEGPL_OMR2MSKL, sa | 3); 1203 + break; 1204 + } 1205 + j++; 1206 + } 1207 + 1208 + /* Configure IO, always 64K starting at 0 */ 1209 + if (hose->io_resource.flags & IORESOURCE_IO) { 1210 + lah = RES_TO_U32_HIGH(hose->io_base_phys); 1211 + lal = RES_TO_U32_LOW(hose->io_base_phys); 1212 + out_le32(mbase + PECFG_POM2LAH, 0); 1213 + out_le32(mbase + PECFG_POM2LAL, 0); 1214 + dcr_write(port->dcrs, DCRO_PEGPL_OMR3BAH, lah); 1215 + dcr_write(port->dcrs, DCRO_PEGPL_OMR3BAL, lal); 1216 + dcr_write(port->dcrs, DCRO_PEGPL_OMR3MSKH, 0x7fffffff); 1217 + dcr_write(port->dcrs, DCRO_PEGPL_OMR3MSKL, 0xffff0000 | 3); 1218 + } 1219 + } 1220 + 1221 + static void __init ppc4xx_configure_pciex_PIMs(struct ppc4xx_pciex_port *port, 1222 + struct pci_controller *hose, 1223 + void __iomem *mbase, 1224 + struct resource *res) 1225 + { 1226 + resource_size_t size = res->end - res->start + 1; 1227 + u64 sa; 1228 + 1229 + /* Calculate window size */ 1230 + sa = (0xffffffffffffffffull << ilog2(size));; 1231 + if (res->flags & IORESOURCE_PREFETCH) 1232 + sa |= 0x8; 1233 + 1234 + out_le32(mbase + PECFG_BAR0HMPA, RES_TO_U32_HIGH(sa)); 1235 + out_le32(mbase + PECFG_BAR0LMPA, RES_TO_U32_LOW(sa)); 1236 + 1237 + /* The setup of the split looks weird to me ... let's see if it works */ 1238 + out_le32(mbase + PECFG_PIM0LAL, 0x00000000); 1239 + out_le32(mbase + PECFG_PIM0LAH, 0x00000000); 1240 + out_le32(mbase + PECFG_PIM1LAL, 0x00000000); 1241 + out_le32(mbase + PECFG_PIM1LAH, 0x00000000); 1242 + out_le32(mbase + PECFG_PIM01SAH, 0xffff0000); 1243 + out_le32(mbase + PECFG_PIM01SAL, 0x00000000); 1244 + 1245 + /* Enable inbound mapping */ 1246 + out_le32(mbase + PECFG_PIMEN, 0x1); 1247 + 1248 + out_le32(mbase + PCI_BASE_ADDRESS_0, RES_TO_U32_LOW(res->start)); 1249 + out_le32(mbase + PCI_BASE_ADDRESS_1, RES_TO_U32_HIGH(res->start)); 1250 + 1251 + /* Enable I/O, Mem, and Busmaster cycles */ 1252 + out_le16(mbase + PCI_COMMAND, 1253 + in_le16(mbase + PCI_COMMAND) | 1254 + PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); 1255 + } 1256 + 1257 + static void __init ppc4xx_pciex_port_setup_hose(struct ppc4xx_pciex_port *port) 1258 + { 1259 + struct resource dma_window; 1260 + struct pci_controller *hose = NULL; 1261 + const int *bus_range; 1262 + int primary = 0, busses; 1263 + void __iomem *mbase = NULL, *cfg_data = NULL; 1264 + 1265 + /* XXX FIXME: Handle endpoint mode properly */ 1266 + if (port->endpoint) 1267 + return; 1268 + 1269 + /* Check if primary bridge */ 1270 + if (of_get_property(port->node, "primary", NULL)) 1271 + primary = 1; 1272 + 1273 + /* Get bus range if any */ 1274 + bus_range = of_get_property(port->node, "bus-range", NULL); 1275 + 1276 + /* Allocate the host controller data structure */ 1277 + hose = pcibios_alloc_controller(port->node); 1278 + if (!hose) 1279 + goto fail; 1280 + 1281 + /* We stick the port number in "indirect_type" so the config space 1282 + * ops can retrieve the port data structure easily 1283 + */ 1284 + hose->indirect_type = port->index; 1285 + 1286 + /* Get bus range */ 1287 + hose->first_busno = bus_range ? bus_range[0] : 0x0; 1288 + hose->last_busno = bus_range ? bus_range[1] : 0xff; 1289 + 1290 + /* Because of how big mapping the config space is (1M per bus), we 1291 + * limit how many busses we support. In the long run, we could replace 1292 + * that with something akin to kmap_atomic instead. We set aside 1 bus 1293 + * for the host itself too. 1294 + */ 1295 + busses = hose->last_busno - hose->first_busno; /* This is off by 1 */ 1296 + if (busses > MAX_PCIE_BUS_MAPPED) { 1297 + busses = MAX_PCIE_BUS_MAPPED; 1298 + hose->last_busno = hose->first_busno + busses; 1299 + } 1300 + 1301 + /* We map the external config space in cfg_data and the host config 1302 + * space in cfg_addr. External space is 1M per bus, internal space 1303 + * is 4K 1304 + */ 1305 + cfg_data = ioremap(port->cfg_space.start + 1306 + (hose->first_busno + 1) * 0x100000, 1307 + busses * 0x100000); 1308 + mbase = ioremap(port->cfg_space.start + 0x10000000, 0x1000); 1309 + if (cfg_data == NULL || mbase == NULL) { 1310 + printk(KERN_ERR "%s: Can't map config space !", 1311 + port->node->full_name); 1312 + goto fail; 1313 + } 1314 + 1315 + hose->cfg_data = cfg_data; 1316 + hose->cfg_addr = mbase; 1317 + 1318 + pr_debug("PCIE %s, bus %d..%d\n", port->node->full_name, 1319 + hose->first_busno, hose->last_busno); 1320 + pr_debug(" config space mapped at: root @0x%p, other @0x%p\n", 1321 + hose->cfg_addr, hose->cfg_data); 1322 + 1323 + /* Setup config space */ 1324 + hose->ops = &ppc4xx_pciex_pci_ops; 1325 + port->hose = hose; 1326 + mbase = (void __iomem *)hose->cfg_addr; 1327 + 1328 + /* 1329 + * Set bus numbers on our root port 1330 + */ 1331 + out_8(mbase + PCI_PRIMARY_BUS, hose->first_busno); 1332 + out_8(mbase + PCI_SECONDARY_BUS, hose->first_busno + 1); 1333 + out_8(mbase + PCI_SUBORDINATE_BUS, hose->last_busno); 1334 + 1335 + /* 1336 + * OMRs are already reset, also disable PIMs 1337 + */ 1338 + out_le32(mbase + PECFG_PIMEN, 0); 1339 + 1340 + /* Parse outbound mapping resources */ 1341 + pci_process_bridge_OF_ranges(hose, port->node, primary); 1342 + 1343 + /* Parse inbound mapping resources */ 1344 + if (ppc4xx_parse_dma_ranges(hose, mbase, &dma_window) != 0) 1345 + goto fail; 1346 + 1347 + /* Configure outbound ranges POMs */ 1348 + ppc4xx_configure_pciex_POMs(port, hose, mbase); 1349 + 1350 + /* Configure inbound ranges PIMs */ 1351 + ppc4xx_configure_pciex_PIMs(port, hose, mbase, &dma_window); 1352 + 1353 + /* The root complex doesn't show up if we don't set some vendor 1354 + * and device IDs into it. Those are the same bogus one that the 1355 + * initial code in arch/ppc add. We might want to change that. 1356 + */ 1357 + out_le16(mbase + 0x200, 0xaaa0 + port->index); 1358 + out_le16(mbase + 0x202, 0xbed0 + port->index); 1359 + 1360 + /* Set Class Code to PCI-PCI bridge and Revision Id to 1 */ 1361 + out_le32(mbase + 0x208, 0x06040001); 1362 + 1363 + printk(KERN_INFO "PCIE%d: successfully set as root-complex\n", 1364 + port->index); 1365 + return; 1366 + fail: 1367 + if (hose) 1368 + pcibios_free_controller(hose); 1369 + if (cfg_data) 1370 + iounmap(cfg_data); 1371 + if (mbase) 1372 + iounmap(mbase); 1373 + } 1374 + 513 1375 static void __init ppc4xx_probe_pciex_bridge(struct device_node *np) 514 1376 { 515 - /* NYI */ 1377 + struct ppc4xx_pciex_port *port; 1378 + const u32 *pval; 1379 + int portno; 1380 + unsigned int dcrs; 1381 + 1382 + /* First, proceed to core initialization as we assume there's 1383 + * only one PCIe core in the system 1384 + */ 1385 + if (ppc4xx_pciex_check_core_init(np)) 1386 + return; 1387 + 1388 + /* Get the port number from the device-tree */ 1389 + pval = of_get_property(np, "port", NULL); 1390 + if (pval == NULL) { 1391 + printk(KERN_ERR "PCIE: Can't find port number for %s\n", 1392 + np->full_name); 1393 + return; 1394 + } 1395 + portno = *pval; 1396 + if (portno >= ppc4xx_pciex_port_count) { 1397 + printk(KERN_ERR "PCIE: port number out of range for %s\n", 1398 + np->full_name); 1399 + return; 1400 + } 1401 + port = &ppc4xx_pciex_ports[portno]; 1402 + port->index = portno; 1403 + port->node = of_node_get(np); 1404 + pval = of_get_property(np, "sdr-base", NULL); 1405 + if (pval == NULL) { 1406 + printk(KERN_ERR "PCIE: missing sdr-base for %s\n", 1407 + np->full_name); 1408 + return; 1409 + } 1410 + port->sdr_base = *pval; 1411 + 1412 + /* Fetch config space registers address */ 1413 + if (of_address_to_resource(np, 0, &port->cfg_space)) { 1414 + printk(KERN_ERR "%s: Can't get PCI-E config space !", 1415 + np->full_name); 1416 + return; 1417 + } 1418 + /* Fetch host bridge internal registers address */ 1419 + if (of_address_to_resource(np, 1, &port->utl_regs)) { 1420 + printk(KERN_ERR "%s: Can't get UTL register base !", 1421 + np->full_name); 1422 + return; 1423 + } 1424 + 1425 + /* Map DCRs */ 1426 + dcrs = dcr_resource_start(np, 0); 1427 + if (dcrs == 0) { 1428 + printk(KERN_ERR "%s: Can't get DCR register base !", 1429 + np->full_name); 1430 + return; 1431 + } 1432 + port->dcrs = dcr_map(np, dcrs, dcr_resource_len(np, 0)); 1433 + 1434 + /* Initialize the port specific registers */ 1435 + if (ppc4xx_pciex_port_init(port)) 1436 + return; 1437 + 1438 + /* Setup the linux hose data structure */ 1439 + ppc4xx_pciex_port_setup_hose(port); 516 1440 } 1441 + 1442 + #endif /* CONFIG_PPC4xx_PCI_EXPRESS */ 517 1443 518 1444 static int __init ppc4xx_pci_find_bridges(void) 519 1445 { 520 1446 struct device_node *np; 521 1447 1448 + #ifdef CONFIG_PPC4xx_PCI_EXPRESS 522 1449 for_each_compatible_node(np, NULL, "ibm,plb-pciex") 523 1450 ppc4xx_probe_pciex_bridge(np); 1451 + #endif 524 1452 for_each_compatible_node(np, NULL, "ibm,plb-pcix") 525 1453 ppc4xx_probe_pcix_bridge(np); 526 1454 for_each_compatible_node(np, NULL, "ibm,plb-pci")
+242
arch/powerpc/sysdev/ppc4xx_pci.h
··· 121 121 #define PCIL0_PTM2MS 0x38 122 122 #define PCIL0_PTM2LA 0x3c 123 123 124 + /* 125 + * 4xx PCIe bridge register definitions 126 + */ 127 + 128 + /* DCR offsets */ 129 + #define DCRO_PEGPL_CFGBAH 0x00 130 + #define DCRO_PEGPL_CFGBAL 0x01 131 + #define DCRO_PEGPL_CFGMSK 0x02 132 + #define DCRO_PEGPL_MSGBAH 0x03 133 + #define DCRO_PEGPL_MSGBAL 0x04 134 + #define DCRO_PEGPL_MSGMSK 0x05 135 + #define DCRO_PEGPL_OMR1BAH 0x06 136 + #define DCRO_PEGPL_OMR1BAL 0x07 137 + #define DCRO_PEGPL_OMR1MSKH 0x08 138 + #define DCRO_PEGPL_OMR1MSKL 0x09 139 + #define DCRO_PEGPL_OMR2BAH 0x0a 140 + #define DCRO_PEGPL_OMR2BAL 0x0b 141 + #define DCRO_PEGPL_OMR2MSKH 0x0c 142 + #define DCRO_PEGPL_OMR2MSKL 0x0d 143 + #define DCRO_PEGPL_OMR3BAH 0x0e 144 + #define DCRO_PEGPL_OMR3BAL 0x0f 145 + #define DCRO_PEGPL_OMR3MSKH 0x10 146 + #define DCRO_PEGPL_OMR3MSKL 0x11 147 + #define DCRO_PEGPL_REGBAH 0x12 148 + #define DCRO_PEGPL_REGBAL 0x13 149 + #define DCRO_PEGPL_REGMSK 0x14 150 + #define DCRO_PEGPL_SPECIAL 0x15 151 + #define DCRO_PEGPL_CFG 0x16 152 + #define DCRO_PEGPL_ESR 0x17 153 + #define DCRO_PEGPL_EARH 0x18 154 + #define DCRO_PEGPL_EARL 0x19 155 + #define DCRO_PEGPL_EATR 0x1a 156 + 157 + /* DMER mask */ 158 + #define GPL_DMER_MASK_DISA 0x02000000 159 + 160 + /* 161 + * System DCRs (SDRs) 162 + */ 163 + #define PESDR0_PLLLCT1 0x03a0 164 + #define PESDR0_PLLLCT2 0x03a1 165 + #define PESDR0_PLLLCT3 0x03a2 166 + 167 + /* 168 + * 440SPe additional DCRs 169 + */ 170 + #define PESDR0_440SPE_UTLSET1 0x0300 171 + #define PESDR0_440SPE_UTLSET2 0x0301 172 + #define PESDR0_440SPE_DLPSET 0x0302 173 + #define PESDR0_440SPE_LOOP 0x0303 174 + #define PESDR0_440SPE_RCSSET 0x0304 175 + #define PESDR0_440SPE_RCSSTS 0x0305 176 + #define PESDR0_440SPE_HSSL0SET1 0x0306 177 + #define PESDR0_440SPE_HSSL0SET2 0x0307 178 + #define PESDR0_440SPE_HSSL0STS 0x0308 179 + #define PESDR0_440SPE_HSSL1SET1 0x0309 180 + #define PESDR0_440SPE_HSSL1SET2 0x030a 181 + #define PESDR0_440SPE_HSSL1STS 0x030b 182 + #define PESDR0_440SPE_HSSL2SET1 0x030c 183 + #define PESDR0_440SPE_HSSL2SET2 0x030d 184 + #define PESDR0_440SPE_HSSL2STS 0x030e 185 + #define PESDR0_440SPE_HSSL3SET1 0x030f 186 + #define PESDR0_440SPE_HSSL3SET2 0x0310 187 + #define PESDR0_440SPE_HSSL3STS 0x0311 188 + #define PESDR0_440SPE_HSSL4SET1 0x0312 189 + #define PESDR0_440SPE_HSSL4SET2 0x0313 190 + #define PESDR0_440SPE_HSSL4STS 0x0314 191 + #define PESDR0_440SPE_HSSL5SET1 0x0315 192 + #define PESDR0_440SPE_HSSL5SET2 0x0316 193 + #define PESDR0_440SPE_HSSL5STS 0x0317 194 + #define PESDR0_440SPE_HSSL6SET1 0x0318 195 + #define PESDR0_440SPE_HSSL6SET2 0x0319 196 + #define PESDR0_440SPE_HSSL6STS 0x031a 197 + #define PESDR0_440SPE_HSSL7SET1 0x031b 198 + #define PESDR0_440SPE_HSSL7SET2 0x031c 199 + #define PESDR0_440SPE_HSSL7STS 0x031d 200 + #define PESDR0_440SPE_HSSCTLSET 0x031e 201 + #define PESDR0_440SPE_LANE_ABCD 0x031f 202 + #define PESDR0_440SPE_LANE_EFGH 0x0320 203 + 204 + #define PESDR1_440SPE_UTLSET1 0x0340 205 + #define PESDR1_440SPE_UTLSET2 0x0341 206 + #define PESDR1_440SPE_DLPSET 0x0342 207 + #define PESDR1_440SPE_LOOP 0x0343 208 + #define PESDR1_440SPE_RCSSET 0x0344 209 + #define PESDR1_440SPE_RCSSTS 0x0345 210 + #define PESDR1_440SPE_HSSL0SET1 0x0346 211 + #define PESDR1_440SPE_HSSL0SET2 0x0347 212 + #define PESDR1_440SPE_HSSL0STS 0x0348 213 + #define PESDR1_440SPE_HSSL1SET1 0x0349 214 + #define PESDR1_440SPE_HSSL1SET2 0x034a 215 + #define PESDR1_440SPE_HSSL1STS 0x034b 216 + #define PESDR1_440SPE_HSSL2SET1 0x034c 217 + #define PESDR1_440SPE_HSSL2SET2 0x034d 218 + #define PESDR1_440SPE_HSSL2STS 0x034e 219 + #define PESDR1_440SPE_HSSL3SET1 0x034f 220 + #define PESDR1_440SPE_HSSL3SET2 0x0350 221 + #define PESDR1_440SPE_HSSL3STS 0x0351 222 + #define PESDR1_440SPE_HSSCTLSET 0x0352 223 + #define PESDR1_440SPE_LANE_ABCD 0x0353 224 + 225 + #define PESDR2_440SPE_UTLSET1 0x0370 226 + #define PESDR2_440SPE_UTLSET2 0x0371 227 + #define PESDR2_440SPE_DLPSET 0x0372 228 + #define PESDR2_440SPE_LOOP 0x0373 229 + #define PESDR2_440SPE_RCSSET 0x0374 230 + #define PESDR2_440SPE_RCSSTS 0x0375 231 + #define PESDR2_440SPE_HSSL0SET1 0x0376 232 + #define PESDR2_440SPE_HSSL0SET2 0x0377 233 + #define PESDR2_440SPE_HSSL0STS 0x0378 234 + #define PESDR2_440SPE_HSSL1SET1 0x0379 235 + #define PESDR2_440SPE_HSSL1SET2 0x037a 236 + #define PESDR2_440SPE_HSSL1STS 0x037b 237 + #define PESDR2_440SPE_HSSL2SET1 0x037c 238 + #define PESDR2_440SPE_HSSL2SET2 0x037d 239 + #define PESDR2_440SPE_HSSL2STS 0x037e 240 + #define PESDR2_440SPE_HSSL3SET1 0x037f 241 + #define PESDR2_440SPE_HSSL3SET2 0x0380 242 + #define PESDR2_440SPE_HSSL3STS 0x0381 243 + #define PESDR2_440SPE_HSSCTLSET 0x0382 244 + #define PESDR2_440SPE_LANE_ABCD 0x0383 245 + 246 + /* 247 + * 405EX additional DCRs 248 + */ 249 + #define PESDR0_405EX_UTLSET1 0x0400 250 + #define PESDR0_405EX_UTLSET2 0x0401 251 + #define PESDR0_405EX_DLPSET 0x0402 252 + #define PESDR0_405EX_LOOP 0x0403 253 + #define PESDR0_405EX_RCSSET 0x0404 254 + #define PESDR0_405EX_RCSSTS 0x0405 255 + #define PESDR0_405EX_PHYSET1 0x0406 256 + #define PESDR0_405EX_PHYSET2 0x0407 257 + #define PESDR0_405EX_BIST 0x0408 258 + #define PESDR0_405EX_LPB 0x040B 259 + #define PESDR0_405EX_PHYSTA 0x040C 260 + 261 + #define PESDR1_405EX_UTLSET1 0x0440 262 + #define PESDR1_405EX_UTLSET2 0x0441 263 + #define PESDR1_405EX_DLPSET 0x0442 264 + #define PESDR1_405EX_LOOP 0x0443 265 + #define PESDR1_405EX_RCSSET 0x0444 266 + #define PESDR1_405EX_RCSSTS 0x0445 267 + #define PESDR1_405EX_PHYSET1 0x0446 268 + #define PESDR1_405EX_PHYSET2 0x0447 269 + #define PESDR1_405EX_BIST 0x0448 270 + #define PESDR1_405EX_LPB 0x044B 271 + #define PESDR1_405EX_PHYSTA 0x044C 272 + 273 + /* 274 + * Of the above, some are common offsets from the base 275 + */ 276 + #define PESDRn_UTLSET1 0x00 277 + #define PESDRn_UTLSET2 0x01 278 + #define PESDRn_DLPSET 0x02 279 + #define PESDRn_LOOP 0x03 280 + #define PESDRn_RCSSET 0x04 281 + #define PESDRn_RCSSTS 0x05 282 + 283 + /* 440spe only */ 284 + #define PESDRn_440SPE_HSSL0SET1 0x06 285 + #define PESDRn_440SPE_HSSL0SET2 0x07 286 + #define PESDRn_440SPE_HSSL0STS 0x08 287 + #define PESDRn_440SPE_HSSL1SET1 0x09 288 + #define PESDRn_440SPE_HSSL1SET2 0x0a 289 + #define PESDRn_440SPE_HSSL1STS 0x0b 290 + #define PESDRn_440SPE_HSSL2SET1 0x0c 291 + #define PESDRn_440SPE_HSSL2SET2 0x0d 292 + #define PESDRn_440SPE_HSSL2STS 0x0e 293 + #define PESDRn_440SPE_HSSL3SET1 0x0f 294 + #define PESDRn_440SPE_HSSL3SET2 0x10 295 + #define PESDRn_440SPE_HSSL3STS 0x11 296 + 297 + /* 440spe port 0 only */ 298 + #define PESDRn_440SPE_HSSL4SET1 0x12 299 + #define PESDRn_440SPE_HSSL4SET2 0x13 300 + #define PESDRn_440SPE_HSSL4STS 0x14 301 + #define PESDRn_440SPE_HSSL5SET1 0x15 302 + #define PESDRn_440SPE_HSSL5SET2 0x16 303 + #define PESDRn_440SPE_HSSL5STS 0x17 304 + #define PESDRn_440SPE_HSSL6SET1 0x18 305 + #define PESDRn_440SPE_HSSL6SET2 0x19 306 + #define PESDRn_440SPE_HSSL6STS 0x1a 307 + #define PESDRn_440SPE_HSSL7SET1 0x1b 308 + #define PESDRn_440SPE_HSSL7SET2 0x1c 309 + #define PESDRn_440SPE_HSSL7STS 0x1d 310 + 311 + /* 405ex only */ 312 + #define PESDRn_405EX_PHYSET1 0x06 313 + #define PESDRn_405EX_PHYSET2 0x07 314 + #define PESDRn_405EX_PHYSTA 0x0c 315 + 316 + /* 317 + * UTL register offsets 318 + */ 319 + #define PEUTL_PBCTL 0x00 320 + #define PEUTL_PBBSZ 0x20 321 + #define PEUTL_OPDBSZ 0x68 322 + #define PEUTL_IPHBSZ 0x70 323 + #define PEUTL_IPDBSZ 0x78 324 + #define PEUTL_OUTTR 0x90 325 + #define PEUTL_INTR 0x98 326 + #define PEUTL_PCTL 0xa0 327 + #define PEUTL_RCSTA 0xB0 328 + #define PEUTL_RCIRQEN 0xb8 329 + 330 + /* 331 + * Config space register offsets 332 + */ 333 + #define PECFG_BAR0LMPA 0x210 334 + #define PECFG_BAR0HMPA 0x214 335 + #define PECFG_BAR1MPA 0x218 336 + #define PECFG_BAR2LMPA 0x220 337 + #define PECFG_BAR2HMPA 0x224 338 + 339 + #define PECFG_PIMEN 0x33c 340 + #define PECFG_PIM0LAL 0x340 341 + #define PECFG_PIM0LAH 0x344 342 + #define PECFG_PIM1LAL 0x348 343 + #define PECFG_PIM1LAH 0x34c 344 + #define PECFG_PIM01SAL 0x350 345 + #define PECFG_PIM01SAH 0x354 346 + 347 + #define PECFG_POM0LAL 0x380 348 + #define PECFG_POM0LAH 0x384 349 + #define PECFG_POM1LAL 0x388 350 + #define PECFG_POM1LAH 0x38c 351 + #define PECFG_POM2LAL 0x390 352 + #define PECFG_POM2LAH 0x394 353 + 354 + 355 + enum 356 + { 357 + PTYPE_ENDPOINT = 0x0, 358 + PTYPE_LEGACY_ENDPOINT = 0x1, 359 + PTYPE_ROOT_PORT = 0x4, 360 + 361 + LNKW_X1 = 0x1, 362 + LNKW_X4 = 0x4, 363 + LNKW_X8 = 0x8 364 + }; 365 + 124 366 125 367 #endif /* __PPC4XX_PCI_H__ */