diff options
Diffstat (limited to 'arch/powerpc/sysdev/ppc4xx_pci.c')
-rw-r--r-- | arch/powerpc/sysdev/ppc4xx_pci.c | 101 |
1 files changed, 78 insertions, 23 deletions
diff --git a/arch/powerpc/sysdev/ppc4xx_pci.c b/arch/powerpc/sysdev/ppc4xx_pci.c index dbfe96bc878a..862f11b3821e 100644 --- a/arch/powerpc/sysdev/ppc4xx_pci.c +++ b/arch/powerpc/sysdev/ppc4xx_pci.c | |||
@@ -834,7 +834,7 @@ static int __init ppc440spe_pciex_core_init(struct device_node *np) | |||
834 | return 3; | 834 | return 3; |
835 | } | 835 | } |
836 | 836 | ||
837 | static int ppc440spe_pciex_init_port_hw(struct ppc4xx_pciex_port *port) | 837 | static int __init ppc440spe_pciex_init_port_hw(struct ppc4xx_pciex_port *port) |
838 | { | 838 | { |
839 | u32 val = 1 << 24; | 839 | u32 val = 1 << 24; |
840 | 840 | ||
@@ -872,12 +872,12 @@ static int ppc440spe_pciex_init_port_hw(struct ppc4xx_pciex_port *port) | |||
872 | return ppc4xx_pciex_port_reset_sdr(port); | 872 | return ppc4xx_pciex_port_reset_sdr(port); |
873 | } | 873 | } |
874 | 874 | ||
875 | static int ppc440speA_pciex_init_port_hw(struct ppc4xx_pciex_port *port) | 875 | static int __init ppc440speA_pciex_init_port_hw(struct ppc4xx_pciex_port *port) |
876 | { | 876 | { |
877 | return ppc440spe_pciex_init_port_hw(port); | 877 | return ppc440spe_pciex_init_port_hw(port); |
878 | } | 878 | } |
879 | 879 | ||
880 | static int ppc440speB_pciex_init_port_hw(struct ppc4xx_pciex_port *port) | 880 | static int __init ppc440speB_pciex_init_port_hw(struct ppc4xx_pciex_port *port) |
881 | { | 881 | { |
882 | int rc = ppc440spe_pciex_init_port_hw(port); | 882 | int rc = ppc440spe_pciex_init_port_hw(port); |
883 | 883 | ||
@@ -936,7 +936,7 @@ static int __init ppc460ex_pciex_core_init(struct device_node *np) | |||
936 | return 2; | 936 | return 2; |
937 | } | 937 | } |
938 | 938 | ||
939 | static int ppc460ex_pciex_init_port_hw(struct ppc4xx_pciex_port *port) | 939 | static int __init ppc460ex_pciex_init_port_hw(struct ppc4xx_pciex_port *port) |
940 | { | 940 | { |
941 | u32 val; | 941 | u32 val; |
942 | u32 utlset1; | 942 | u32 utlset1; |
@@ -1092,6 +1092,10 @@ static int __init ppc460sx_pciex_core_init(struct device_node *np) | |||
1092 | mtdcri(SDR0, PESDR1_460SX_HSSSLEW, 0xFFFF0000); | 1092 | mtdcri(SDR0, PESDR1_460SX_HSSSLEW, 0xFFFF0000); |
1093 | mtdcri(SDR0, PESDR2_460SX_HSSSLEW, 0xFFFF0000); | 1093 | mtdcri(SDR0, PESDR2_460SX_HSSSLEW, 0xFFFF0000); |
1094 | 1094 | ||
1095 | /* Set HSS PRBS enabled */ | ||
1096 | mtdcri(SDR0, PESDR0_460SX_HSSCTLSET, 0x00001130); | ||
1097 | mtdcri(SDR0, PESDR2_460SX_HSSCTLSET, 0x00001130); | ||
1098 | |||
1095 | udelay(100); | 1099 | udelay(100); |
1096 | 1100 | ||
1097 | /* De-assert PLLRESET */ | 1101 | /* De-assert PLLRESET */ |
@@ -1122,7 +1126,7 @@ static int __init ppc460sx_pciex_core_init(struct device_node *np) | |||
1122 | return 2; | 1126 | return 2; |
1123 | } | 1127 | } |
1124 | 1128 | ||
1125 | static int ppc460sx_pciex_init_port_hw(struct ppc4xx_pciex_port *port) | 1129 | static int __init ppc460sx_pciex_init_port_hw(struct ppc4xx_pciex_port *port) |
1126 | { | 1130 | { |
1127 | 1131 | ||
1128 | if (port->endpoint) | 1132 | if (port->endpoint) |
@@ -1132,9 +1136,6 @@ static int ppc460sx_pciex_init_port_hw(struct ppc4xx_pciex_port *port) | |||
1132 | dcri_clrset(SDR0, port->sdr_base + PESDRn_UTLSET2, | 1136 | dcri_clrset(SDR0, port->sdr_base + PESDRn_UTLSET2, |
1133 | 0, 0x01000000); | 1137 | 0, 0x01000000); |
1134 | 1138 | ||
1135 | /*Gen-1*/ | ||
1136 | mtdcri(SDR0, port->sdr_base + PESDRn_460SX_RCEI, 0x08000000); | ||
1137 | |||
1138 | dcri_clrset(SDR0, port->sdr_base + PESDRn_RCSSET, | 1139 | dcri_clrset(SDR0, port->sdr_base + PESDRn_RCSSET, |
1139 | (PESDRx_RCSSET_RSTGU | PESDRx_RCSSET_RSTDL), | 1140 | (PESDRx_RCSSET_RSTGU | PESDRx_RCSSET_RSTDL), |
1140 | PESDRx_RCSSET_RSTPYN); | 1141 | PESDRx_RCSSET_RSTPYN); |
@@ -1148,14 +1149,42 @@ static int ppc460sx_pciex_init_utl(struct ppc4xx_pciex_port *port) | |||
1148 | { | 1149 | { |
1149 | /* Max 128 Bytes */ | 1150 | /* Max 128 Bytes */ |
1150 | out_be32 (port->utl_base + PEUTL_PBBSZ, 0x00000000); | 1151 | out_be32 (port->utl_base + PEUTL_PBBSZ, 0x00000000); |
1152 | /* Assert VRB and TXE - per datasheet turn off addr validation */ | ||
1153 | out_be32(port->utl_base + PEUTL_PCTL, 0x80800000); | ||
1151 | return 0; | 1154 | return 0; |
1152 | } | 1155 | } |
1153 | 1156 | ||
1157 | static void __init ppc460sx_pciex_check_link(struct ppc4xx_pciex_port *port) | ||
1158 | { | ||
1159 | void __iomem *mbase; | ||
1160 | int attempt = 50; | ||
1161 | |||
1162 | port->link = 0; | ||
1163 | |||
1164 | mbase = ioremap(port->cfg_space.start + 0x10000000, 0x1000); | ||
1165 | if (mbase == NULL) { | ||
1166 | printk(KERN_ERR "%s: Can't map internal config space !", | ||
1167 | port->node->full_name); | ||
1168 | goto done; | ||
1169 | } | ||
1170 | |||
1171 | while (attempt && (0 == (in_le32(mbase + PECFG_460SX_DLLSTA) | ||
1172 | & PECFG_460SX_DLLSTA_LINKUP))) { | ||
1173 | attempt--; | ||
1174 | mdelay(10); | ||
1175 | } | ||
1176 | if (attempt) | ||
1177 | port->link = 1; | ||
1178 | done: | ||
1179 | iounmap(mbase); | ||
1180 | |||
1181 | } | ||
1182 | |||
1154 | static struct ppc4xx_pciex_hwops ppc460sx_pcie_hwops __initdata = { | 1183 | static struct ppc4xx_pciex_hwops ppc460sx_pcie_hwops __initdata = { |
1155 | .core_init = ppc460sx_pciex_core_init, | 1184 | .core_init = ppc460sx_pciex_core_init, |
1156 | .port_init_hw = ppc460sx_pciex_init_port_hw, | 1185 | .port_init_hw = ppc460sx_pciex_init_port_hw, |
1157 | .setup_utl = ppc460sx_pciex_init_utl, | 1186 | .setup_utl = ppc460sx_pciex_init_utl, |
1158 | .check_link = ppc4xx_pciex_check_link_sdr, | 1187 | .check_link = ppc460sx_pciex_check_link, |
1159 | }; | 1188 | }; |
1160 | 1189 | ||
1161 | #endif /* CONFIG_44x */ | 1190 | #endif /* CONFIG_44x */ |
@@ -1189,7 +1218,7 @@ static void ppc405ex_pcie_phy_reset(struct ppc4xx_pciex_port *port) | |||
1189 | mtdcri(SDR0, port->sdr_base + PESDRn_RCSSET, 0x00101000); | 1218 | mtdcri(SDR0, port->sdr_base + PESDRn_RCSSET, 0x00101000); |
1190 | } | 1219 | } |
1191 | 1220 | ||
1192 | static int ppc405ex_pciex_init_port_hw(struct ppc4xx_pciex_port *port) | 1221 | static int __init ppc405ex_pciex_init_port_hw(struct ppc4xx_pciex_port *port) |
1193 | { | 1222 | { |
1194 | u32 val; | 1223 | u32 val; |
1195 | 1224 | ||
@@ -1338,15 +1367,15 @@ static int __init ppc4xx_pciex_port_init(struct ppc4xx_pciex_port *port) | |||
1338 | if (rc != 0) | 1367 | if (rc != 0) |
1339 | return rc; | 1368 | return rc; |
1340 | 1369 | ||
1341 | if (ppc4xx_pciex_hwops->check_link) | ||
1342 | ppc4xx_pciex_hwops->check_link(port); | ||
1343 | |||
1344 | /* | 1370 | /* |
1345 | * Initialize mapping: disable all regions and configure | 1371 | * Initialize mapping: disable all regions and configure |
1346 | * CFG and REG regions based on resources in the device tree | 1372 | * CFG and REG regions based on resources in the device tree |
1347 | */ | 1373 | */ |
1348 | ppc4xx_pciex_port_init_mapping(port); | 1374 | ppc4xx_pciex_port_init_mapping(port); |
1349 | 1375 | ||
1376 | if (ppc4xx_pciex_hwops->check_link) | ||
1377 | ppc4xx_pciex_hwops->check_link(port); | ||
1378 | |||
1350 | /* | 1379 | /* |
1351 | * Map UTL | 1380 | * Map UTL |
1352 | */ | 1381 | */ |
@@ -1360,13 +1389,23 @@ static int __init ppc4xx_pciex_port_init(struct ppc4xx_pciex_port *port) | |||
1360 | ppc4xx_pciex_hwops->setup_utl(port); | 1389 | ppc4xx_pciex_hwops->setup_utl(port); |
1361 | 1390 | ||
1362 | /* | 1391 | /* |
1363 | * Check for VC0 active and assert RDY. | 1392 | * Check for VC0 active or PLL Locked and assert RDY. |
1364 | */ | 1393 | */ |
1365 | if (port->sdr_base) { | 1394 | if (port->sdr_base) { |
1366 | if (port->link && | 1395 | if (of_device_is_compatible(port->node, |
1367 | ppc4xx_pciex_wait_on_sdr(port, PESDRn_RCSSTS, | 1396 | "ibm,plb-pciex-460sx")){ |
1368 | 1 << 16, 1 << 16, 5000)) { | 1397 | if (port->link && ppc4xx_pciex_wait_on_sdr(port, |
1369 | printk(KERN_INFO "PCIE%d: VC0 not active\n", port->index); | 1398 | PESDRn_RCSSTS, |
1399 | 1 << 12, 1 << 12, 5000)) { | ||
1400 | printk(KERN_INFO "PCIE%d: PLL not locked\n", | ||
1401 | port->index); | ||
1402 | port->link = 0; | ||
1403 | } | ||
1404 | } else if (port->link && | ||
1405 | ppc4xx_pciex_wait_on_sdr(port, PESDRn_RCSSTS, | ||
1406 | 1 << 16, 1 << 16, 5000)) { | ||
1407 | printk(KERN_INFO "PCIE%d: VC0 not active\n", | ||
1408 | port->index); | ||
1370 | port->link = 0; | 1409 | port->link = 0; |
1371 | } | 1410 | } |
1372 | 1411 | ||
@@ -1573,8 +1612,15 @@ static int __init ppc4xx_setup_one_pciex_POM(struct ppc4xx_pciex_port *port, | |||
1573 | dcr_write(port->dcrs, DCRO_PEGPL_OMR1BAH, lah); | 1612 | dcr_write(port->dcrs, DCRO_PEGPL_OMR1BAH, lah); |
1574 | dcr_write(port->dcrs, DCRO_PEGPL_OMR1BAL, lal); | 1613 | dcr_write(port->dcrs, DCRO_PEGPL_OMR1BAL, lal); |
1575 | dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKH, 0x7fffffff); | 1614 | dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKH, 0x7fffffff); |
1576 | /* Note that 3 here means enabled | single region */ | 1615 | /*Enabled and single region */ |
1577 | dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKL, sa | 3); | 1616 | if (of_device_is_compatible(port->node, "ibm,plb-pciex-460sx")) |
1617 | dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKL, | ||
1618 | sa | DCRO_PEGPL_460SX_OMR1MSKL_UOT | ||
1619 | | DCRO_PEGPL_OMRxMSKL_VAL); | ||
1620 | else | ||
1621 | dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKL, | ||
1622 | sa | DCRO_PEGPL_OMR1MSKL_UOT | ||
1623 | | DCRO_PEGPL_OMRxMSKL_VAL); | ||
1578 | break; | 1624 | break; |
1579 | case 1: | 1625 | case 1: |
1580 | out_le32(mbase + PECFG_POM1LAH, pciah); | 1626 | out_le32(mbase + PECFG_POM1LAH, pciah); |
@@ -1582,8 +1628,8 @@ static int __init ppc4xx_setup_one_pciex_POM(struct ppc4xx_pciex_port *port, | |||
1582 | dcr_write(port->dcrs, DCRO_PEGPL_OMR2BAH, lah); | 1628 | dcr_write(port->dcrs, DCRO_PEGPL_OMR2BAH, lah); |
1583 | dcr_write(port->dcrs, DCRO_PEGPL_OMR2BAL, lal); | 1629 | dcr_write(port->dcrs, DCRO_PEGPL_OMR2BAL, lal); |
1584 | dcr_write(port->dcrs, DCRO_PEGPL_OMR2MSKH, 0x7fffffff); | 1630 | dcr_write(port->dcrs, DCRO_PEGPL_OMR2MSKH, 0x7fffffff); |
1585 | /* Note that 3 here means enabled | single region */ | 1631 | dcr_write(port->dcrs, DCRO_PEGPL_OMR2MSKL, |
1586 | dcr_write(port->dcrs, DCRO_PEGPL_OMR2MSKL, sa | 3); | 1632 | sa | DCRO_PEGPL_OMRxMSKL_VAL); |
1587 | break; | 1633 | break; |
1588 | case 2: | 1634 | case 2: |
1589 | out_le32(mbase + PECFG_POM2LAH, pciah); | 1635 | out_le32(mbase + PECFG_POM2LAH, pciah); |
@@ -1592,7 +1638,9 @@ static int __init ppc4xx_setup_one_pciex_POM(struct ppc4xx_pciex_port *port, | |||
1592 | dcr_write(port->dcrs, DCRO_PEGPL_OMR3BAL, lal); | 1638 | dcr_write(port->dcrs, DCRO_PEGPL_OMR3BAL, lal); |
1593 | dcr_write(port->dcrs, DCRO_PEGPL_OMR3MSKH, 0x7fffffff); | 1639 | dcr_write(port->dcrs, DCRO_PEGPL_OMR3MSKH, 0x7fffffff); |
1594 | /* Note that 3 here means enabled | IO space !!! */ | 1640 | /* Note that 3 here means enabled | IO space !!! */ |
1595 | dcr_write(port->dcrs, DCRO_PEGPL_OMR3MSKL, sa | 3); | 1641 | dcr_write(port->dcrs, DCRO_PEGPL_OMR3MSKL, |
1642 | sa | DCRO_PEGPL_OMR3MSKL_IO | ||
1643 | | DCRO_PEGPL_OMRxMSKL_VAL); | ||
1596 | break; | 1644 | break; |
1597 | } | 1645 | } |
1598 | 1646 | ||
@@ -1693,6 +1741,9 @@ static void __init ppc4xx_configure_pciex_PIMs(struct ppc4xx_pciex_port *port, | |||
1693 | if (res->flags & IORESOURCE_PREFETCH) | 1741 | if (res->flags & IORESOURCE_PREFETCH) |
1694 | sa |= 0x8; | 1742 | sa |= 0x8; |
1695 | 1743 | ||
1744 | if (of_device_is_compatible(port->node, "ibm,plb-pciex-460sx")) | ||
1745 | sa |= PCI_BASE_ADDRESS_MEM_TYPE_64; | ||
1746 | |||
1696 | out_le32(mbase + PECFG_BAR0HMPA, RES_TO_U32_HIGH(sa)); | 1747 | out_le32(mbase + PECFG_BAR0HMPA, RES_TO_U32_HIGH(sa)); |
1697 | out_le32(mbase + PECFG_BAR0LMPA, RES_TO_U32_LOW(sa)); | 1748 | out_le32(mbase + PECFG_BAR0LMPA, RES_TO_U32_LOW(sa)); |
1698 | 1749 | ||
@@ -1854,6 +1905,10 @@ static void __init ppc4xx_pciex_port_setup_hose(struct ppc4xx_pciex_port *port) | |||
1854 | } | 1905 | } |
1855 | out_le16(mbase + 0x202, val); | 1906 | out_le16(mbase + 0x202, val); |
1856 | 1907 | ||
1908 | /* Enable Bus master, memory, and io space */ | ||
1909 | if (of_device_is_compatible(port->node, "ibm,plb-pciex-460sx")) | ||
1910 | out_le16(mbase + 0x204, 0x7); | ||
1911 | |||
1857 | if (!port->endpoint) { | 1912 | if (!port->endpoint) { |
1858 | /* Set Class Code to PCI-PCI bridge and Revision Id to 1 */ | 1913 | /* Set Class Code to PCI-PCI bridge and Revision Id to 1 */ |
1859 | out_le32(mbase + 0x208, 0x06040001); | 1914 | out_le32(mbase + 0x208, 0x06040001); |