aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/sysdev/ppc4xx_pci.c
diff options
context:
space:
mode:
authorAyman El-Khashab <ayman@elkhashab.com>2011-07-19 23:02:29 -0400
committerJosh Boyer <jwboyer@gmail.com>2011-08-11 13:51:18 -0400
commite7fa1d131472b1134d33aba56a83f8f7689f54fd (patch)
treecb728714ba8f2916c214ec9e8c9367bdfdb0a683 /arch/powerpc/sysdev/ppc4xx_pci.c
parent2f6bab96ef60dd87e0a17272f9f8a6ee12118d32 (diff)
powerpc/4xx: enable and fix pcie gen1/gen2 on the 460sx
Adds a register to the config space for the 460sx. Changes the vc0 detect to a pll detect. maps configuration space to test the link status. changes the setup to enable gen2 devices to operate at gen2 speeds. fixes mapping that was not correct for the 460sx. added bit definitions for the OMRxMSKL registers. Removed reserved bit that was set incorrectly in the OMR2MSKL register. tested on the 460sx eiger and custom board Signed-off-by: Ayman El-Khashab <ayman@elkhashab.com> Signed-off-by: Josh Boyer <jwboyer@gmail.com>
Diffstat (limited to 'arch/powerpc/sysdev/ppc4xx_pci.c')
-rw-r--r--arch/powerpc/sysdev/ppc4xx_pci.c89
1 files changed, 72 insertions, 17 deletions
diff --git a/arch/powerpc/sysdev/ppc4xx_pci.c b/arch/powerpc/sysdev/ppc4xx_pci.c
index a59ba96d2c21..edd51c85835a 100644
--- a/arch/powerpc/sysdev/ppc4xx_pci.c
+++ b/arch/powerpc/sysdev/ppc4xx_pci.c
@@ -1091,6 +1091,10 @@ static int __init ppc460sx_pciex_core_init(struct device_node *np)
1091 mtdcri(SDR0, PESDR1_460SX_HSSSLEW, 0xFFFF0000); 1091 mtdcri(SDR0, PESDR1_460SX_HSSSLEW, 0xFFFF0000);
1092 mtdcri(SDR0, PESDR2_460SX_HSSSLEW, 0xFFFF0000); 1092 mtdcri(SDR0, PESDR2_460SX_HSSSLEW, 0xFFFF0000);
1093 1093
1094 /* Set HSS PRBS enabled */
1095 mtdcri(SDR0, PESDR0_460SX_HSSCTLSET, 0x00001130);
1096 mtdcri(SDR0, PESDR2_460SX_HSSCTLSET, 0x00001130);
1097
1094 udelay(100); 1098 udelay(100);
1095 1099
1096 /* De-assert PLLRESET */ 1100 /* De-assert PLLRESET */
@@ -1131,9 +1135,6 @@ static int ppc460sx_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
1131 dcri_clrset(SDR0, port->sdr_base + PESDRn_UTLSET2, 1135 dcri_clrset(SDR0, port->sdr_base + PESDRn_UTLSET2,
1132 0, 0x01000000); 1136 0, 0x01000000);
1133 1137
1134 /*Gen-1*/
1135 mtdcri(SDR0, port->sdr_base + PESDRn_460SX_RCEI, 0x08000000);
1136
1137 dcri_clrset(SDR0, port->sdr_base + PESDRn_RCSSET, 1138 dcri_clrset(SDR0, port->sdr_base + PESDRn_RCSSET,
1138 (PESDRx_RCSSET_RSTGU | PESDRx_RCSSET_RSTDL), 1139 (PESDRx_RCSSET_RSTGU | PESDRx_RCSSET_RSTDL),
1139 PESDRx_RCSSET_RSTPYN); 1140 PESDRx_RCSSET_RSTPYN);
@@ -1147,14 +1148,42 @@ static int ppc460sx_pciex_init_utl(struct ppc4xx_pciex_port *port)
1147{ 1148{
1148 /* Max 128 Bytes */ 1149 /* Max 128 Bytes */
1149 out_be32 (port->utl_base + PEUTL_PBBSZ, 0x00000000); 1150 out_be32 (port->utl_base + PEUTL_PBBSZ, 0x00000000);
1151 /* Assert VRB and TXE - per datasheet turn off addr validation */
1152 out_be32(port->utl_base + PEUTL_PCTL, 0x80800000);
1150 return 0; 1153 return 0;
1151} 1154}
1152 1155
1156static void __init ppc460sx_pciex_check_link(struct ppc4xx_pciex_port *port)
1157{
1158 void __iomem *mbase;
1159 int attempt = 50;
1160
1161 port->link = 0;
1162
1163 mbase = ioremap(port->cfg_space.start + 0x10000000, 0x1000);
1164 if (mbase == NULL) {
1165 printk(KERN_ERR "%s: Can't map internal config space !",
1166 port->node->full_name);
1167 goto done;
1168 }
1169
1170 while (attempt && (0 == (in_le32(mbase + PECFG_460SX_DLLSTA)
1171 & PECFG_460SX_DLLSTA_LINKUP))) {
1172 attempt--;
1173 mdelay(10);
1174 }
1175 if (attempt)
1176 port->link = 1;
1177done:
1178 iounmap(mbase);
1179
1180}
1181
1153static struct ppc4xx_pciex_hwops ppc460sx_pcie_hwops __initdata = { 1182static struct ppc4xx_pciex_hwops ppc460sx_pcie_hwops __initdata = {
1154 .core_init = ppc460sx_pciex_core_init, 1183 .core_init = ppc460sx_pciex_core_init,
1155 .port_init_hw = ppc460sx_pciex_init_port_hw, 1184 .port_init_hw = ppc460sx_pciex_init_port_hw,
1156 .setup_utl = ppc460sx_pciex_init_utl, 1185 .setup_utl = ppc460sx_pciex_init_utl,
1157 .check_link = ppc4xx_pciex_check_link_sdr, 1186 .check_link = ppc460sx_pciex_check_link,
1158}; 1187};
1159 1188
1160#endif /* CONFIG_44x */ 1189#endif /* CONFIG_44x */
@@ -1337,15 +1366,15 @@ static int __init ppc4xx_pciex_port_init(struct ppc4xx_pciex_port *port)
1337 if (rc != 0) 1366 if (rc != 0)
1338 return rc; 1367 return rc;
1339 1368
1340 if (ppc4xx_pciex_hwops->check_link)
1341 ppc4xx_pciex_hwops->check_link(port);
1342
1343 /* 1369 /*
1344 * Initialize mapping: disable all regions and configure 1370 * Initialize mapping: disable all regions and configure
1345 * CFG and REG regions based on resources in the device tree 1371 * CFG and REG regions based on resources in the device tree
1346 */ 1372 */
1347 ppc4xx_pciex_port_init_mapping(port); 1373 ppc4xx_pciex_port_init_mapping(port);
1348 1374
1375 if (ppc4xx_pciex_hwops->check_link)
1376 ppc4xx_pciex_hwops->check_link(port);
1377
1349 /* 1378 /*
1350 * Map UTL 1379 * Map UTL
1351 */ 1380 */
@@ -1359,13 +1388,23 @@ static int __init ppc4xx_pciex_port_init(struct ppc4xx_pciex_port *port)
1359 ppc4xx_pciex_hwops->setup_utl(port); 1388 ppc4xx_pciex_hwops->setup_utl(port);
1360 1389
1361 /* 1390 /*
1362 * Check for VC0 active and assert RDY. 1391 * Check for VC0 active or PLL Locked and assert RDY.
1363 */ 1392 */
1364 if (port->sdr_base) { 1393 if (port->sdr_base) {
1365 if (port->link && 1394 if (of_device_is_compatible(port->node,
1366 ppc4xx_pciex_wait_on_sdr(port, PESDRn_RCSSTS, 1395 "ibm,plb-pciex-460sx")){
1367 1 << 16, 1 << 16, 5000)) { 1396 if (port->link && ppc4xx_pciex_wait_on_sdr(port,
1368 printk(KERN_INFO "PCIE%d: VC0 not active\n", port->index); 1397 PESDRn_RCSSTS,
1398 1 << 12, 1 << 12, 5000)) {
1399 printk(KERN_INFO "PCIE%d: PLL not locked\n",
1400 port->index);
1401 port->link = 0;
1402 }
1403 } else if (port->link &&
1404 ppc4xx_pciex_wait_on_sdr(port, PESDRn_RCSSTS,
1405 1 << 16, 1 << 16, 5000)) {
1406 printk(KERN_INFO "PCIE%d: VC0 not active\n",
1407 port->index);
1369 port->link = 0; 1408 port->link = 0;
1370 } 1409 }
1371 1410
@@ -1572,8 +1611,15 @@ static int __init ppc4xx_setup_one_pciex_POM(struct ppc4xx_pciex_port *port,
1572 dcr_write(port->dcrs, DCRO_PEGPL_OMR1BAH, lah); 1611 dcr_write(port->dcrs, DCRO_PEGPL_OMR1BAH, lah);
1573 dcr_write(port->dcrs, DCRO_PEGPL_OMR1BAL, lal); 1612 dcr_write(port->dcrs, DCRO_PEGPL_OMR1BAL, lal);
1574 dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKH, 0x7fffffff); 1613 dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKH, 0x7fffffff);
1575 /* Note that 3 here means enabled | single region */ 1614 /*Enabled and single region */
1576 dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKL, sa | 3); 1615 if (of_device_is_compatible(port->node, "ibm,plb-pciex-460sx"))
1616 dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKL,
1617 sa | DCRO_PEGPL_460SX_OMR1MSKL_UOT
1618 | DCRO_PEGPL_OMRxMSKL_VAL);
1619 else
1620 dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKL,
1621 sa | DCRO_PEGPL_OMR1MSKL_UOT
1622 | DCRO_PEGPL_OMRxMSKL_VAL);
1577 break; 1623 break;
1578 case 1: 1624 case 1:
1579 out_le32(mbase + PECFG_POM1LAH, pciah); 1625 out_le32(mbase + PECFG_POM1LAH, pciah);
@@ -1581,8 +1627,8 @@ static int __init ppc4xx_setup_one_pciex_POM(struct ppc4xx_pciex_port *port,
1581 dcr_write(port->dcrs, DCRO_PEGPL_OMR2BAH, lah); 1627 dcr_write(port->dcrs, DCRO_PEGPL_OMR2BAH, lah);
1582 dcr_write(port->dcrs, DCRO_PEGPL_OMR2BAL, lal); 1628 dcr_write(port->dcrs, DCRO_PEGPL_OMR2BAL, lal);
1583 dcr_write(port->dcrs, DCRO_PEGPL_OMR2MSKH, 0x7fffffff); 1629 dcr_write(port->dcrs, DCRO_PEGPL_OMR2MSKH, 0x7fffffff);
1584 /* Note that 3 here means enabled | single region */ 1630 dcr_write(port->dcrs, DCRO_PEGPL_OMR2MSKL,
1585 dcr_write(port->dcrs, DCRO_PEGPL_OMR2MSKL, sa | 3); 1631 sa | DCRO_PEGPL_OMRxMSKL_VAL);
1586 break; 1632 break;
1587 case 2: 1633 case 2:
1588 out_le32(mbase + PECFG_POM2LAH, pciah); 1634 out_le32(mbase + PECFG_POM2LAH, pciah);
@@ -1591,7 +1637,9 @@ static int __init ppc4xx_setup_one_pciex_POM(struct ppc4xx_pciex_port *port,
1591 dcr_write(port->dcrs, DCRO_PEGPL_OMR3BAL, lal); 1637 dcr_write(port->dcrs, DCRO_PEGPL_OMR3BAL, lal);
1592 dcr_write(port->dcrs, DCRO_PEGPL_OMR3MSKH, 0x7fffffff); 1638 dcr_write(port->dcrs, DCRO_PEGPL_OMR3MSKH, 0x7fffffff);
1593 /* Note that 3 here means enabled | IO space !!! */ 1639 /* Note that 3 here means enabled | IO space !!! */
1594 dcr_write(port->dcrs, DCRO_PEGPL_OMR3MSKL, sa | 3); 1640 dcr_write(port->dcrs, DCRO_PEGPL_OMR3MSKL,
1641 sa | DCRO_PEGPL_OMR3MSKL_IO
1642 | DCRO_PEGPL_OMRxMSKL_VAL);
1595 break; 1643 break;
1596 } 1644 }
1597 1645
@@ -1692,6 +1740,9 @@ static void __init ppc4xx_configure_pciex_PIMs(struct ppc4xx_pciex_port *port,
1692 if (res->flags & IORESOURCE_PREFETCH) 1740 if (res->flags & IORESOURCE_PREFETCH)
1693 sa |= 0x8; 1741 sa |= 0x8;
1694 1742
1743 if (of_device_is_compatible(port->node, "ibm,plb-pciex-460sx"))
1744 sa |= PCI_BASE_ADDRESS_MEM_TYPE_64;
1745
1695 out_le32(mbase + PECFG_BAR0HMPA, RES_TO_U32_HIGH(sa)); 1746 out_le32(mbase + PECFG_BAR0HMPA, RES_TO_U32_HIGH(sa));
1696 out_le32(mbase + PECFG_BAR0LMPA, RES_TO_U32_LOW(sa)); 1747 out_le32(mbase + PECFG_BAR0LMPA, RES_TO_U32_LOW(sa));
1697 1748
@@ -1853,6 +1904,10 @@ static void __init ppc4xx_pciex_port_setup_hose(struct ppc4xx_pciex_port *port)
1853 } 1904 }
1854 out_le16(mbase + 0x202, val); 1905 out_le16(mbase + 0x202, val);
1855 1906
1907 /* Enable Bus master, memory, and io space */
1908 if (of_device_is_compatible(port->node, "ibm,plb-pciex-460sx"))
1909 out_le16(mbase + 0x204, 0x7);
1910
1856 if (!port->endpoint) { 1911 if (!port->endpoint) {
1857 /* Set Class Code to PCI-PCI bridge and Revision Id to 1 */ 1912 /* Set Class Code to PCI-PCI bridge and Revision Id to 1 */
1858 out_le32(mbase + 0x208, 0x06040001); 1913 out_le32(mbase + 0x208, 0x06040001);