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

PCI: tegra: Add Tegra186 PCIe support

Add Tegra186 PCIe support. UPHY programming is performed by BPMP; PHY
enable calls are not required for Tegra186 PCIe.

Power partition ungate is done by BPMP powergate driver. The Tegra186
DT description must include a "power-domains" property, which results in
dev->pm_domain being set.

Tested-by: Mikko Perttunen <mperttunen@nvidia.com>
Tested-by: Thierry Reding <treding@nvidia.com>
Signed-off-by: Manikanta Maddireddy <mmaddireddy@nvidia.com>
[bhelgaas: add "power-domains" reference]
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Reviewed-by: Mikko Perttunen <mperttunen@nvidia.com>
Acked-by: Thierry Reding <treding@nvidia.com>

authored by

Manikanta Maddireddy and committed by
Bjorn Helgaas
9cea513d 904fb8e4

+109 -25
+109 -25
drivers/pci/host/pci-tegra.c
··· 159 159 #define AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_SINGLE (0x0 << 20) 160 160 #define AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_420 (0x0 << 20) 161 161 #define AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_X2_X1 (0x0 << 20) 162 + #define AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_401 (0x0 << 20) 162 163 #define AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_DUAL (0x1 << 20) 163 164 #define AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_222 (0x1 << 20) 164 165 #define AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_X4_X1 (0x1 << 20) 166 + #define AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_211 (0x1 << 20) 165 167 #define AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_411 (0x2 << 20) 168 + #define AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_111 (0x2 << 20) 166 169 167 170 #define AFI_FUSE 0x104 168 171 #define AFI_FUSE_PCIE_T0_GEN2_DIS (1 << 2) ··· 255 252 bool has_cml_clk; 256 253 bool has_gen2; 257 254 bool force_pca_enable; 255 + bool program_uphy; 258 256 }; 259 257 260 258 static inline struct tegra_msi *to_tegra_msi(struct msi_controller *chip) ··· 1036 1032 afi_writel(pcie, value, AFI_FUSE); 1037 1033 } 1038 1034 1039 - err = tegra_pcie_phy_power_on(pcie); 1040 - if (err < 0) { 1041 - dev_err(dev, "failed to power on PHY(s): %d\n", err); 1042 - return err; 1035 + if (soc->program_uphy) { 1036 + err = tegra_pcie_phy_power_on(pcie); 1037 + if (err < 0) { 1038 + dev_err(dev, "failed to power on PHY(s): %d\n", err); 1039 + return err; 1040 + } 1043 1041 } 1044 1042 1045 1043 /* take the PCIe interface module out of reset */ ··· 1074 1068 static void tegra_pcie_power_off(struct tegra_pcie *pcie) 1075 1069 { 1076 1070 struct device *dev = pcie->dev; 1071 + const struct tegra_pcie_soc *soc = pcie->soc; 1077 1072 int err; 1078 1073 1079 1074 /* TODO: disable and unprepare clocks? */ 1080 1075 1081 - err = tegra_pcie_phy_power_off(pcie); 1082 - if (err < 0) 1083 - dev_err(dev, "failed to power off PHY(s): %d\n", err); 1076 + if (soc->program_uphy) { 1077 + err = tegra_pcie_phy_power_off(pcie); 1078 + if (err < 0) 1079 + dev_err(dev, "failed to power off PHY(s): %d\n", err); 1080 + } 1084 1081 1085 1082 reset_control_assert(pcie->pcie_xrst); 1086 1083 reset_control_assert(pcie->afi_rst); 1087 1084 reset_control_assert(pcie->pex_rst); 1088 1085 1089 - tegra_powergate_power_off(TEGRA_POWERGATE_PCIE); 1086 + if (!dev->pm_domain) 1087 + tegra_powergate_power_off(TEGRA_POWERGATE_PCIE); 1090 1088 1091 1089 err = regulator_bulk_disable(pcie->num_supplies, pcie->supplies); 1092 1090 if (err < 0) ··· 1107 1097 reset_control_assert(pcie->afi_rst); 1108 1098 reset_control_assert(pcie->pex_rst); 1109 1099 1110 - tegra_powergate_power_off(TEGRA_POWERGATE_PCIE); 1100 + if (!dev->pm_domain) 1101 + tegra_powergate_power_off(TEGRA_POWERGATE_PCIE); 1111 1102 1112 1103 /* enable regulators */ 1113 1104 err = regulator_bulk_enable(pcie->num_supplies, pcie->supplies); 1114 1105 if (err < 0) 1115 1106 dev_err(dev, "failed to enable regulators: %d\n", err); 1116 1107 1117 - err = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_PCIE, 1118 - pcie->pex_clk, 1119 - pcie->pex_rst); 1120 - if (err) { 1121 - dev_err(dev, "powerup sequence failed: %d\n", err); 1122 - return err; 1108 + if (dev->pm_domain) { 1109 + err = clk_prepare_enable(pcie->pex_clk); 1110 + if (err) { 1111 + dev_err(dev, "failed to enable PEX clock: %d\n", err); 1112 + return err; 1113 + } 1114 + reset_control_deassert(pcie->pex_rst); 1115 + } else { 1116 + err = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_PCIE, 1117 + pcie->pex_clk, 1118 + pcie->pex_rst); 1119 + if (err) { 1120 + dev_err(dev, "powerup sequence failed: %d\n", err); 1121 + return err; 1122 + } 1123 1123 } 1124 1124 1125 1125 reset_control_deassert(pcie->afi_rst); ··· 1302 1282 struct device *dev = pcie->dev; 1303 1283 struct platform_device *pdev = to_platform_device(dev); 1304 1284 struct resource *pads, *afi, *res; 1285 + const struct tegra_pcie_soc *soc = pcie->soc; 1305 1286 int err; 1306 1287 1307 1288 err = tegra_pcie_clocks_get(pcie); ··· 1317 1296 return err; 1318 1297 } 1319 1298 1320 - err = tegra_pcie_phys_get(pcie); 1321 - if (err < 0) { 1322 - dev_err(dev, "failed to get PHYs: %d\n", err); 1323 - return err; 1299 + if (soc->program_uphy) { 1300 + err = tegra_pcie_phys_get(pcie); 1301 + if (err < 0) { 1302 + dev_err(dev, "failed to get PHYs: %d\n", err); 1303 + return err; 1304 + } 1324 1305 } 1325 1306 1326 1307 err = tegra_pcie_power_on(pcie); ··· 1384 1361 static int tegra_pcie_put_resources(struct tegra_pcie *pcie) 1385 1362 { 1386 1363 struct device *dev = pcie->dev; 1364 + const struct tegra_pcie_soc *soc = pcie->soc; 1387 1365 int err; 1388 1366 1389 1367 if (pcie->irq > 0) ··· 1392 1368 1393 1369 tegra_pcie_power_off(pcie); 1394 1370 1395 - err = phy_exit(pcie->phy); 1396 - if (err < 0) 1397 - dev_err(dev, "failed to teardown PHY: %d\n", err); 1371 + if (soc->program_uphy) { 1372 + err = phy_exit(pcie->phy); 1373 + if (err < 0) 1374 + dev_err(dev, "failed to teardown PHY: %d\n", err); 1375 + } 1398 1376 1399 1377 return 0; 1400 1378 } ··· 1662 1636 struct device *dev = pcie->dev; 1663 1637 struct device_node *np = dev->of_node; 1664 1638 1665 - if (of_device_is_compatible(np, "nvidia,tegra124-pcie") || 1666 - of_device_is_compatible(np, "nvidia,tegra210-pcie")) { 1639 + if (of_device_is_compatible(np, "nvidia,tegra186-pcie")) { 1640 + switch (lanes) { 1641 + case 0x010004: 1642 + dev_info(dev, "4x1, 1x1 configuration\n"); 1643 + *xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_401; 1644 + return 0; 1645 + 1646 + case 0x010102: 1647 + dev_info(dev, "2x1, 1X1, 1x1 configuration\n"); 1648 + *xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_211; 1649 + return 0; 1650 + 1651 + case 0x010101: 1652 + dev_info(dev, "1x1, 1x1, 1x1 configuration\n"); 1653 + *xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_111; 1654 + return 0; 1655 + 1656 + default: 1657 + dev_info(dev, "wrong configuration updated in DT, " 1658 + "switching to default 2x1, 1x1, 1x1 " 1659 + "configuration\n"); 1660 + *xbar = AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_211; 1661 + return 0; 1662 + } 1663 + } else if (of_device_is_compatible(np, "nvidia,tegra124-pcie") || 1664 + of_device_is_compatible(np, "nvidia,tegra210-pcie")) { 1667 1665 switch (lanes) { 1668 1666 case 0x0000104: 1669 1667 dev_info(dev, "4x1, 1x1 configuration\n"); ··· 1807 1757 struct device_node *np = dev->of_node; 1808 1758 unsigned int i = 0; 1809 1759 1810 - if (of_device_is_compatible(np, "nvidia,tegra210-pcie")) { 1760 + if (of_device_is_compatible(np, "nvidia,tegra186-pcie")) { 1761 + pcie->num_supplies = 4; 1762 + 1763 + pcie->supplies = devm_kcalloc(pcie->dev, pcie->num_supplies, 1764 + sizeof(*pcie->supplies), 1765 + GFP_KERNEL); 1766 + if (!pcie->supplies) 1767 + return -ENOMEM; 1768 + 1769 + pcie->supplies[i++].supply = "dvdd-pex"; 1770 + pcie->supplies[i++].supply = "hvdd-pex-pll"; 1771 + pcie->supplies[i++].supply = "hvdd-pex"; 1772 + pcie->supplies[i++].supply = "vddio-pexctl-aud"; 1773 + } else if (of_device_is_compatible(np, "nvidia,tegra210-pcie")) { 1811 1774 pcie->num_supplies = 6; 1812 1775 1813 1776 pcie->supplies = devm_kcalloc(pcie->dev, pcie->num_supplies, ··· 2159 2096 .has_cml_clk = false, 2160 2097 .has_gen2 = false, 2161 2098 .force_pca_enable = false, 2099 + .program_uphy = true, 2162 2100 }; 2163 2101 2164 2102 static const struct tegra_pcie_soc tegra30_pcie = { ··· 2175 2111 .has_cml_clk = true, 2176 2112 .has_gen2 = false, 2177 2113 .force_pca_enable = false, 2114 + .program_uphy = true, 2178 2115 }; 2179 2116 2180 2117 static const struct tegra_pcie_soc tegra124_pcie = { ··· 2190 2125 .has_cml_clk = true, 2191 2126 .has_gen2 = true, 2192 2127 .force_pca_enable = false, 2128 + .program_uphy = true, 2193 2129 }; 2194 2130 2195 2131 static const struct tegra_pcie_soc tegra210_pcie = { ··· 2205 2139 .has_cml_clk = true, 2206 2140 .has_gen2 = true, 2207 2141 .force_pca_enable = true, 2142 + .program_uphy = true, 2143 + }; 2144 + 2145 + static const struct tegra_pcie_soc tegra186_pcie = { 2146 + .num_ports = 3, 2147 + .msi_base_shift = 8, 2148 + .pads_pll_ctl = PADS_PLL_CTL_TEGRA30, 2149 + .tx_ref_sel = PADS_PLL_CTL_TXCLKREF_BUF_EN, 2150 + .pads_refclk_cfg0 = 0x80b880b8, 2151 + .pads_refclk_cfg1 = 0x000480b8, 2152 + .has_pex_clkreq_en = true, 2153 + .has_pex_bias_ctrl = true, 2154 + .has_intr_prsnt_sense = true, 2155 + .has_cml_clk = false, 2156 + .has_gen2 = true, 2157 + .force_pca_enable = false, 2158 + .program_uphy = false, 2208 2159 }; 2209 2160 2210 2161 static const struct of_device_id tegra_pcie_of_match[] = { 2162 + { .compatible = "nvidia,tegra186-pcie", .data = &tegra186_pcie }, 2211 2163 { .compatible = "nvidia,tegra210-pcie", .data = &tegra210_pcie }, 2212 2164 { .compatible = "nvidia,tegra124-pcie", .data = &tegra124_pcie }, 2213 2165 { .compatible = "nvidia,tegra30-pcie", .data = &tegra30_pcie },