|
54 | 54 | #define PCIE20_PARF_LTSSM 0x1B0
|
55 | 55 | #define PCIE20_PARF_SID_OFFSET 0x234
|
56 | 56 | #define PCIE20_PARF_BDF_TRANSLATE_CFG 0x24C
|
| 57 | +#define PCIE20_PARF_DEVICE_TYPE 0x1000 |
57 | 58 |
|
58 | 59 | #define PCIE20_ELBI_SYS_CTRL 0x04
|
59 | 60 | #define PCIE20_ELBI_SYS_CTRL_LT_ENABLE BIT(0)
|
|
80 | 81 | #define PCIE20_v3_PARF_SLV_ADDR_SPACE_SIZE 0x358
|
81 | 82 | #define SLV_ADDR_SPACE_SZ 0x10000000
|
82 | 83 |
|
| 84 | +#define DEVICE_TYPE_RC 0x4 |
| 85 | + |
83 | 86 | #define QCOM_PCIE_2_1_0_MAX_SUPPLY 3
|
84 | 87 | struct qcom_pcie_resources_2_1_0 {
|
85 | 88 | struct clk *iface_clk;
|
@@ -139,12 +142,20 @@ struct qcom_pcie_resources_2_3_3 {
|
139 | 142 | struct reset_control *rst[7];
|
140 | 143 | };
|
141 | 144 |
|
| 145 | +struct qcom_pcie_resources_2_7_0 { |
| 146 | + struct clk_bulk_data clks[6]; |
| 147 | + struct regulator_bulk_data supplies[2]; |
| 148 | + struct reset_control *pci_reset; |
| 149 | + struct clk *pipe_clk; |
| 150 | +}; |
| 151 | + |
142 | 152 | union qcom_pcie_resources {
|
143 | 153 | struct qcom_pcie_resources_1_0_0 v1_0_0;
|
144 | 154 | struct qcom_pcie_resources_2_1_0 v2_1_0;
|
145 | 155 | struct qcom_pcie_resources_2_3_2 v2_3_2;
|
146 | 156 | struct qcom_pcie_resources_2_3_3 v2_3_3;
|
147 | 157 | struct qcom_pcie_resources_2_4_0 v2_4_0;
|
| 158 | + struct qcom_pcie_resources_2_7_0 v2_7_0; |
148 | 159 | };
|
149 | 160 |
|
150 | 161 | struct qcom_pcie;
|
@@ -1068,6 +1079,134 @@ static int qcom_pcie_init_2_3_3(struct qcom_pcie *pcie)
|
1068 | 1079 | return ret;
|
1069 | 1080 | }
|
1070 | 1081 |
|
| 1082 | +static int qcom_pcie_get_resources_2_7_0(struct qcom_pcie *pcie) |
| 1083 | +{ |
| 1084 | + struct qcom_pcie_resources_2_7_0 *res = &pcie->res.v2_7_0; |
| 1085 | + struct dw_pcie *pci = pcie->pci; |
| 1086 | + struct device *dev = pci->dev; |
| 1087 | + int ret; |
| 1088 | + |
| 1089 | + res->pci_reset = devm_reset_control_get_exclusive(dev, "pci"); |
| 1090 | + if (IS_ERR(res->pci_reset)) |
| 1091 | + return PTR_ERR(res->pci_reset); |
| 1092 | + |
| 1093 | + res->supplies[0].supply = "vdda"; |
| 1094 | + res->supplies[1].supply = "vddpe-3v3"; |
| 1095 | + ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(res->supplies), |
| 1096 | + res->supplies); |
| 1097 | + if (ret) |
| 1098 | + return ret; |
| 1099 | + |
| 1100 | + res->clks[0].id = "aux"; |
| 1101 | + res->clks[1].id = "cfg"; |
| 1102 | + res->clks[2].id = "bus_master"; |
| 1103 | + res->clks[3].id = "bus_slave"; |
| 1104 | + res->clks[4].id = "slave_q2a"; |
| 1105 | + res->clks[5].id = "tbu"; |
| 1106 | + |
| 1107 | + ret = devm_clk_bulk_get(dev, ARRAY_SIZE(res->clks), res->clks); |
| 1108 | + if (ret < 0) |
| 1109 | + return ret; |
| 1110 | + |
| 1111 | + res->pipe_clk = devm_clk_get(dev, "pipe"); |
| 1112 | + return PTR_ERR_OR_ZERO(res->pipe_clk); |
| 1113 | +} |
| 1114 | + |
| 1115 | +static int qcom_pcie_init_2_7_0(struct qcom_pcie *pcie) |
| 1116 | +{ |
| 1117 | + struct qcom_pcie_resources_2_7_0 *res = &pcie->res.v2_7_0; |
| 1118 | + struct dw_pcie *pci = pcie->pci; |
| 1119 | + struct device *dev = pci->dev; |
| 1120 | + u32 val; |
| 1121 | + int ret; |
| 1122 | + |
| 1123 | + ret = regulator_bulk_enable(ARRAY_SIZE(res->supplies), res->supplies); |
| 1124 | + if (ret < 0) { |
| 1125 | + dev_err(dev, "cannot enable regulators\n"); |
| 1126 | + return ret; |
| 1127 | + } |
| 1128 | + |
| 1129 | + ret = clk_bulk_prepare_enable(ARRAY_SIZE(res->clks), res->clks); |
| 1130 | + if (ret < 0) |
| 1131 | + goto err_disable_regulators; |
| 1132 | + |
| 1133 | + ret = reset_control_assert(res->pci_reset); |
| 1134 | + if (ret < 0) { |
| 1135 | + dev_err(dev, "cannot deassert pci reset\n"); |
| 1136 | + goto err_disable_clocks; |
| 1137 | + } |
| 1138 | + |
| 1139 | + usleep_range(1000, 1500); |
| 1140 | + |
| 1141 | + ret = reset_control_deassert(res->pci_reset); |
| 1142 | + if (ret < 0) { |
| 1143 | + dev_err(dev, "cannot deassert pci reset\n"); |
| 1144 | + goto err_disable_clocks; |
| 1145 | + } |
| 1146 | + |
| 1147 | + ret = clk_prepare_enable(res->pipe_clk); |
| 1148 | + if (ret) { |
| 1149 | + dev_err(dev, "cannot prepare/enable pipe clock\n"); |
| 1150 | + goto err_disable_clocks; |
| 1151 | + } |
| 1152 | + |
| 1153 | + /* configure PCIe to RC mode */ |
| 1154 | + writel(DEVICE_TYPE_RC, pcie->parf + PCIE20_PARF_DEVICE_TYPE); |
| 1155 | + |
| 1156 | + /* enable PCIe clocks and resets */ |
| 1157 | + val = readl(pcie->parf + PCIE20_PARF_PHY_CTRL); |
| 1158 | + val &= ~BIT(0); |
| 1159 | + writel(val, pcie->parf + PCIE20_PARF_PHY_CTRL); |
| 1160 | + |
| 1161 | + /* change DBI base address */ |
| 1162 | + writel(0, pcie->parf + PCIE20_PARF_DBI_BASE_ADDR); |
| 1163 | + |
| 1164 | + /* MAC PHY_POWERDOWN MUX DISABLE */ |
| 1165 | + val = readl(pcie->parf + PCIE20_PARF_SYS_CTRL); |
| 1166 | + val &= ~BIT(29); |
| 1167 | + writel(val, pcie->parf + PCIE20_PARF_SYS_CTRL); |
| 1168 | + |
| 1169 | + val = readl(pcie->parf + PCIE20_PARF_MHI_CLOCK_RESET_CTRL); |
| 1170 | + val |= BIT(4); |
| 1171 | + writel(val, pcie->parf + PCIE20_PARF_MHI_CLOCK_RESET_CTRL); |
| 1172 | + |
| 1173 | + if (IS_ENABLED(CONFIG_PCI_MSI)) { |
| 1174 | + val = readl(pcie->parf + PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT); |
| 1175 | + val |= BIT(31); |
| 1176 | + writel(val, pcie->parf + PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT); |
| 1177 | + } |
| 1178 | + |
| 1179 | + return 0; |
| 1180 | +err_disable_clocks: |
| 1181 | + clk_bulk_disable_unprepare(ARRAY_SIZE(res->clks), res->clks); |
| 1182 | +err_disable_regulators: |
| 1183 | + regulator_bulk_disable(ARRAY_SIZE(res->supplies), res->supplies); |
| 1184 | + |
| 1185 | + return ret; |
| 1186 | +} |
| 1187 | + |
| 1188 | +static void qcom_pcie_deinit_2_7_0(struct qcom_pcie *pcie) |
| 1189 | +{ |
| 1190 | + struct qcom_pcie_resources_2_7_0 *res = &pcie->res.v2_7_0; |
| 1191 | + |
| 1192 | + clk_bulk_disable_unprepare(ARRAY_SIZE(res->clks), res->clks); |
| 1193 | + regulator_bulk_disable(ARRAY_SIZE(res->supplies), res->supplies); |
| 1194 | +} |
| 1195 | + |
| 1196 | +static int qcom_pcie_post_init_2_7_0(struct qcom_pcie *pcie) |
| 1197 | +{ |
| 1198 | + struct qcom_pcie_resources_2_7_0 *res = &pcie->res.v2_7_0; |
| 1199 | + |
| 1200 | + return clk_prepare_enable(res->pipe_clk); |
| 1201 | +} |
| 1202 | + |
| 1203 | +static void qcom_pcie_post_deinit_2_7_0(struct qcom_pcie *pcie) |
| 1204 | +{ |
| 1205 | + struct qcom_pcie_resources_2_7_0 *res = &pcie->res.v2_7_0; |
| 1206 | + |
| 1207 | + clk_disable_unprepare(res->pipe_clk); |
| 1208 | +} |
| 1209 | + |
1071 | 1210 | static int qcom_pcie_link_up(struct dw_pcie *pci)
|
1072 | 1211 | {
|
1073 | 1212 | u16 val = readw(pci->dbi_base + PCIE20_CAP + PCI_EXP_LNKSTA);
|
@@ -1167,6 +1306,16 @@ static const struct qcom_pcie_ops ops_2_3_3 = {
|
1167 | 1306 | .ltssm_enable = qcom_pcie_2_3_2_ltssm_enable,
|
1168 | 1307 | };
|
1169 | 1308 |
|
| 1309 | +/* Qcom IP rev.: 2.7.0 Synopsys IP rev.: 4.30a */ |
| 1310 | +static const struct qcom_pcie_ops ops_2_7_0 = { |
| 1311 | + .get_resources = qcom_pcie_get_resources_2_7_0, |
| 1312 | + .init = qcom_pcie_init_2_7_0, |
| 1313 | + .deinit = qcom_pcie_deinit_2_7_0, |
| 1314 | + .ltssm_enable = qcom_pcie_2_3_2_ltssm_enable, |
| 1315 | + .post_init = qcom_pcie_post_init_2_7_0, |
| 1316 | + .post_deinit = qcom_pcie_post_deinit_2_7_0, |
| 1317 | +}; |
| 1318 | + |
1170 | 1319 | static const struct dw_pcie_ops dw_pcie_ops = {
|
1171 | 1320 | .link_up = qcom_pcie_link_up,
|
1172 | 1321 | };
|
@@ -1282,6 +1431,7 @@ static const struct of_device_id qcom_pcie_match[] = {
|
1282 | 1431 | { .compatible = "qcom,pcie-ipq8074", .data = &ops_2_3_3 },
|
1283 | 1432 | { .compatible = "qcom,pcie-ipq4019", .data = &ops_2_4_0 },
|
1284 | 1433 | { .compatible = "qcom,pcie-qcs404", .data = &ops_2_4_0 },
|
| 1434 | + { .compatible = "qcom,pcie-sdm845", .data = &ops_2_7_0 }, |
1285 | 1435 | { }
|
1286 | 1436 | };
|
1287 | 1437 |
|
|
0 commit comments