aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/sysdev/ppc4xx_pci.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/sysdev/ppc4xx_pci.c')
-rw-r--r--arch/powerpc/sysdev/ppc4xx_pci.c133
1 files changed, 117 insertions, 16 deletions
diff --git a/arch/powerpc/sysdev/ppc4xx_pci.c b/arch/powerpc/sysdev/ppc4xx_pci.c
index 5abfcd157483..1814adbd2236 100644
--- a/arch/powerpc/sysdev/ppc4xx_pci.c
+++ b/arch/powerpc/sysdev/ppc4xx_pci.c
@@ -527,6 +527,7 @@ static void __init ppc4xx_probe_pcix_bridge(struct device_node *np)
527 * 527 *
528 * ibm,plb-pciex-440spe 528 * ibm,plb-pciex-440spe
529 * ibm,plb-pciex-405ex 529 * ibm,plb-pciex-405ex
530 * ibm,plb-pciex-460ex
530 * 531 *
531 * Anything else will be rejected for now as they are all subtly 532 * Anything else will be rejected for now as they are all subtly
532 * different unfortunately. 533 * different unfortunately.
@@ -645,7 +646,7 @@ static int __init ppc440spe_pciex_core_init(struct device_node *np)
645 int time_out = 20; 646 int time_out = 20;
646 647
647 /* Set PLL clock receiver to LVPECL */ 648 /* Set PLL clock receiver to LVPECL */
648 mtdcri(SDR0, PESDR0_PLLLCT1, mfdcri(SDR0, PESDR0_PLLLCT1) | 1 << 28); 649 dcri_clrset(SDR0, PESDR0_PLLLCT1, 0, 1 << 28);
649 650
650 /* Shouldn't we do all the calibration stuff etc... here ? */ 651 /* Shouldn't we do all the calibration stuff etc... here ? */
651 if (ppc440spe_pciex_check_reset(np)) 652 if (ppc440spe_pciex_check_reset(np))
@@ -659,8 +660,7 @@ static int __init ppc440spe_pciex_core_init(struct device_node *np)
659 } 660 }
660 661
661 /* De-assert reset of PCIe PLL, wait for lock */ 662 /* De-assert reset of PCIe PLL, wait for lock */
662 mtdcri(SDR0, PESDR0_PLLLCT1, 663 dcri_clrset(SDR0, PESDR0_PLLLCT1, 1 << 24, 0);
663 mfdcri(SDR0, PESDR0_PLLLCT1) & ~(1 << 24));
664 udelay(3); 664 udelay(3);
665 665
666 while (time_out) { 666 while (time_out) {
@@ -712,9 +712,8 @@ static int ppc440spe_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
712 mtdcri(SDR0, port->sdr_base + PESDRn_440SPE_HSSL7SET1, 712 mtdcri(SDR0, port->sdr_base + PESDRn_440SPE_HSSL7SET1,
713 0x35000000); 713 0x35000000);
714 } 714 }
715 val = mfdcri(SDR0, port->sdr_base + PESDRn_RCSSET); 715 dcri_clrset(SDR0, port->sdr_base + PESDRn_RCSSET,
716 mtdcri(SDR0, port->sdr_base + PESDRn_RCSSET, 716 (1 << 24) | (1 << 16), 1 << 12);
717 (val & ~(1 << 24 | 1 << 16)) | 1 << 12);
718 717
719 return 0; 718 return 0;
720} 719}
@@ -775,6 +774,115 @@ static struct ppc4xx_pciex_hwops ppc440speB_pcie_hwops __initdata =
775 .setup_utl = ppc440speB_pciex_init_utl, 774 .setup_utl = ppc440speB_pciex_init_utl,
776}; 775};
777 776
777static int __init ppc460ex_pciex_core_init(struct device_node *np)
778{
779 /* Nothing to do, return 2 ports */
780 return 2;
781}
782
783static int ppc460ex_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
784{
785 u32 val;
786 u32 utlset1;
787
788 if (port->endpoint)
789 val = PTYPE_LEGACY_ENDPOINT << 20;
790 else
791 val = PTYPE_ROOT_PORT << 20;
792
793 if (port->index == 0) {
794 val |= LNKW_X1 << 12;
795 utlset1 = 0x20000000;
796 } else {
797 val |= LNKW_X4 << 12;
798 utlset1 = 0x20101101;
799 }
800
801 mtdcri(SDR0, port->sdr_base + PESDRn_DLPSET, val);
802 mtdcri(SDR0, port->sdr_base + PESDRn_UTLSET1, utlset1);
803 mtdcri(SDR0, port->sdr_base + PESDRn_UTLSET2, 0x01210000);
804
805 switch (port->index) {
806 case 0:
807 mtdcri(SDR0, PESDR0_460EX_L0CDRCTL, 0x00003230);
808 mtdcri(SDR0, PESDR0_460EX_L0DRV, 0x00000136);
809 mtdcri(SDR0, PESDR0_460EX_L0CLK, 0x00000006);
810
811 mtdcri(SDR0, PESDR0_460EX_PHY_CTL_RST,0x10000000);
812 break;
813
814 case 1:
815 mtdcri(SDR0, PESDR1_460EX_L0CDRCTL, 0x00003230);
816 mtdcri(SDR0, PESDR1_460EX_L1CDRCTL, 0x00003230);
817 mtdcri(SDR0, PESDR1_460EX_L2CDRCTL, 0x00003230);
818 mtdcri(SDR0, PESDR1_460EX_L3CDRCTL, 0x00003230);
819 mtdcri(SDR0, PESDR1_460EX_L0DRV, 0x00000136);
820 mtdcri(SDR0, PESDR1_460EX_L1DRV, 0x00000136);
821 mtdcri(SDR0, PESDR1_460EX_L2DRV, 0x00000136);
822 mtdcri(SDR0, PESDR1_460EX_L3DRV, 0x00000136);
823 mtdcri(SDR0, PESDR1_460EX_L0CLK, 0x00000006);
824 mtdcri(SDR0, PESDR1_460EX_L1CLK, 0x00000006);
825 mtdcri(SDR0, PESDR1_460EX_L2CLK, 0x00000006);
826 mtdcri(SDR0, PESDR1_460EX_L3CLK, 0x00000006);
827
828 mtdcri(SDR0, PESDR1_460EX_PHY_CTL_RST,0x10000000);
829 break;
830 }
831
832 mtdcri(SDR0, port->sdr_base + PESDRn_RCSSET,
833 mfdcri(SDR0, port->sdr_base + PESDRn_RCSSET) |
834 (PESDRx_RCSSET_RSTGU | PESDRx_RCSSET_RSTPYN));
835
836 /* Poll for PHY reset */
837 /* XXX FIXME add timeout */
838 switch (port->index) {
839 case 0:
840 while (!(mfdcri(SDR0, PESDR0_460EX_RSTSTA) & 0x1))
841 udelay(10);
842 break;
843 case 1:
844 while (!(mfdcri(SDR0, PESDR1_460EX_RSTSTA) & 0x1))
845 udelay(10);
846 break;
847 }
848
849 mtdcri(SDR0, port->sdr_base + PESDRn_RCSSET,
850 (mfdcri(SDR0, port->sdr_base + PESDRn_RCSSET) &
851 ~(PESDRx_RCSSET_RSTGU | PESDRx_RCSSET_RSTDL)) |
852 PESDRx_RCSSET_RSTPYN);
853
854 port->has_ibpre = 1;
855
856 return 0;
857}
858
859static int ppc460ex_pciex_init_utl(struct ppc4xx_pciex_port *port)
860{
861 dcr_write(port->dcrs, DCRO_PEGPL_SPECIAL, 0x0);
862
863 /*
864 * Set buffer allocations and then assert VRB and TXE.
865 */
866 out_be32(port->utl_base + PEUTL_PBCTL, 0x0800000c);
867 out_be32(port->utl_base + PEUTL_OUTTR, 0x08000000);
868 out_be32(port->utl_base + PEUTL_INTR, 0x02000000);
869 out_be32(port->utl_base + PEUTL_OPDBSZ, 0x04000000);
870 out_be32(port->utl_base + PEUTL_PBBSZ, 0x00000000);
871 out_be32(port->utl_base + PEUTL_IPHBSZ, 0x02000000);
872 out_be32(port->utl_base + PEUTL_IPDBSZ, 0x04000000);
873 out_be32(port->utl_base + PEUTL_RCIRQEN,0x00f00000);
874 out_be32(port->utl_base + PEUTL_PCTL, 0x80800066);
875
876 return 0;
877}
878
879static struct ppc4xx_pciex_hwops ppc460ex_pcie_hwops __initdata =
880{
881 .core_init = ppc460ex_pciex_core_init,
882 .port_init_hw = ppc460ex_pciex_init_port_hw,
883 .setup_utl = ppc460ex_pciex_init_utl,
884};
885
778#endif /* CONFIG_44x */ 886#endif /* CONFIG_44x */
779 887
780#ifdef CONFIG_40x 888#ifdef CONFIG_40x
@@ -830,17 +938,9 @@ static int ppc405ex_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
830 * PCIe boards don't show this problem. 938 * PCIe boards don't show this problem.
831 * This has to be re-tested and fixed in a later release! 939 * This has to be re-tested and fixed in a later release!
832 */ 940 */
833#if 0 /* XXX FIXME: Not resetting the PHY will leave all resources
834 * configured as done previously by U-Boot. Then Linux will currently
835 * not reassign them. So the PHY reset is now done always. This will
836 * lead to problems with the Atheros PCIe board again.
837 */
838 val = mfdcri(SDR0, port->sdr_base + PESDRn_LOOP); 941 val = mfdcri(SDR0, port->sdr_base + PESDRn_LOOP);
839 if (!(val & 0x00001000)) 942 if (!(val & 0x00001000))
840 ppc405ex_pcie_phy_reset(port); 943 ppc405ex_pcie_phy_reset(port);
841#else
842 ppc405ex_pcie_phy_reset(port);
843#endif
844 944
845 dcr_write(port->dcrs, DCRO_PEGPL_CFG, 0x10000000); /* guarded on */ 945 dcr_write(port->dcrs, DCRO_PEGPL_CFG, 0x10000000); /* guarded on */
846 946
@@ -896,6 +996,8 @@ static int __init ppc4xx_pciex_check_core_init(struct device_node *np)
896 else 996 else
897 ppc4xx_pciex_hwops = &ppc440speB_pcie_hwops; 997 ppc4xx_pciex_hwops = &ppc440speB_pcie_hwops;
898 } 998 }
999 if (of_device_is_compatible(np, "ibm,plb-pciex-460ex"))
1000 ppc4xx_pciex_hwops = &ppc460ex_pcie_hwops;
899#endif /* CONFIG_44x */ 1001#endif /* CONFIG_44x */
900#ifdef CONFIG_40x 1002#ifdef CONFIG_40x
901 if (of_device_is_compatible(np, "ibm,plb-pciex-405ex")) 1003 if (of_device_is_compatible(np, "ibm,plb-pciex-405ex"))
@@ -1042,8 +1144,7 @@ static int __init ppc4xx_pciex_port_init(struct ppc4xx_pciex_port *port)
1042 port->link = 0; 1144 port->link = 0;
1043 } 1145 }
1044 1146
1045 mtdcri(SDR0, port->sdr_base + PESDRn_RCSSET, 1147 dcri_clrset(SDR0, port->sdr_base + PESDRn_RCSSET, 0, 1 << 20);
1046 mfdcri(SDR0, port->sdr_base + PESDRn_RCSSET) | 1 << 20);
1047 msleep(100); 1148 msleep(100);
1048 1149
1049 return 0; 1150 return 0;