.. | .. |
---|
1165 | 1165 | } |
---|
1166 | 1166 | |
---|
1167 | 1167 | void rockchip_of_get_pvtm_sel(struct device *dev, struct device_node *np, |
---|
1168 | | - char *reg_name, int process, |
---|
| 1168 | + char *reg_name, int bin, int process, |
---|
1169 | 1169 | int *volt_sel, int *scale_sel) |
---|
1170 | 1170 | { |
---|
1171 | 1171 | struct property *prop = NULL; |
---|
1172 | 1172 | char name[NAME_MAX]; |
---|
1173 | 1173 | int pvtm, ret; |
---|
| 1174 | + u32 hw = 0; |
---|
1174 | 1175 | |
---|
1175 | 1176 | if (of_property_read_bool(np, "rockchip,pvtm-pvtpll")) |
---|
1176 | 1177 | pvtm = rockchip_get_pvtm_pvtpll(dev, np, reg_name); |
---|
.. | .. |
---|
1185 | 1186 | snprintf(name, sizeof(name), |
---|
1186 | 1187 | "rockchip,p%d-pvtm-voltage-sel", process); |
---|
1187 | 1188 | prop = of_find_property(np, name, NULL); |
---|
| 1189 | + } else if (bin >= 0) { |
---|
| 1190 | + of_property_read_u32(np, "rockchip,pvtm-hw", &hw); |
---|
| 1191 | + if (hw && (hw & BIT(bin))) { |
---|
| 1192 | + sprintf(name, "rockchip,pvtm-voltage-sel-hw"); |
---|
| 1193 | + prop = of_find_property(np, name, NULL); |
---|
| 1194 | + } |
---|
1188 | 1195 | } |
---|
1189 | 1196 | if (!prop) |
---|
1190 | 1197 | sprintf(name, "rockchip,pvtm-voltage-sel"); |
---|
.. | .. |
---|
1195 | 1202 | next: |
---|
1196 | 1203 | if (!scale_sel) |
---|
1197 | 1204 | return; |
---|
| 1205 | + prop = NULL; |
---|
1198 | 1206 | if (process >= 0) { |
---|
1199 | 1207 | snprintf(name, sizeof(name), |
---|
1200 | 1208 | "rockchip,p%d-pvtm-scaling-sel", process); |
---|
.. | .. |
---|
1294 | 1302 | } |
---|
1295 | 1303 | EXPORT_SYMBOL(rockchip_get_volt_rm_table); |
---|
1296 | 1304 | |
---|
| 1305 | +int rockchip_get_soc_info(struct device *dev, struct device_node *np, int *bin, |
---|
| 1306 | + int *process) |
---|
| 1307 | +{ |
---|
| 1308 | + u8 value = 0; |
---|
| 1309 | + int ret = 0; |
---|
| 1310 | + |
---|
| 1311 | + if (*bin >= 0 || *process >= 0) |
---|
| 1312 | + return 0; |
---|
| 1313 | + |
---|
| 1314 | + if (of_property_match_string(np, "nvmem-cell-names", |
---|
| 1315 | + "remark_spec_serial_number") >= 0) |
---|
| 1316 | + rockchip_nvmem_cell_read_u8(np, "remark_spec_serial_number", &value); |
---|
| 1317 | + |
---|
| 1318 | + if (!value && of_property_match_string(np, "nvmem-cell-names", |
---|
| 1319 | + "specification_serial_number") >= 0) { |
---|
| 1320 | + ret = rockchip_nvmem_cell_read_u8(np, |
---|
| 1321 | + "specification_serial_number", |
---|
| 1322 | + &value); |
---|
| 1323 | + if (ret) { |
---|
| 1324 | + dev_err(dev, |
---|
| 1325 | + "Failed to get specification_serial_number\n"); |
---|
| 1326 | + return ret; |
---|
| 1327 | + } |
---|
| 1328 | + } |
---|
| 1329 | + |
---|
| 1330 | + /* M */ |
---|
| 1331 | + if (value == 0xd) |
---|
| 1332 | + *bin = 1; |
---|
| 1333 | + /* J */ |
---|
| 1334 | + else if (value == 0xa) |
---|
| 1335 | + *bin = 2; |
---|
| 1336 | + |
---|
| 1337 | + if (*bin < 0) |
---|
| 1338 | + *bin = 0; |
---|
| 1339 | + dev_info(dev, "bin=%d\n", *bin); |
---|
| 1340 | + |
---|
| 1341 | + return 0; |
---|
| 1342 | +} |
---|
| 1343 | +EXPORT_SYMBOL(rockchip_get_soc_info); |
---|
| 1344 | + |
---|
1297 | 1345 | void rockchip_get_scale_volt_sel(struct device *dev, char *lkg_name, |
---|
1298 | 1346 | char *reg_name, int bin, int process, |
---|
1299 | 1347 | int *scale, int *volt_sel) |
---|
.. | .. |
---|
1311 | 1359 | |
---|
1312 | 1360 | rockchip_of_get_lkg_sel(dev, np, lkg_name, process, |
---|
1313 | 1361 | &lkg_volt_sel, &lkg_scale); |
---|
1314 | | - rockchip_of_get_pvtm_sel(dev, np, reg_name, process, |
---|
| 1362 | + rockchip_of_get_pvtm_sel(dev, np, reg_name, bin, process, |
---|
1315 | 1363 | &pvtm_volt_sel, &pvtm_scale); |
---|
1316 | 1364 | rockchip_of_get_bin_sel(dev, np, bin, &bin_scale); |
---|
1317 | 1365 | rockchip_of_get_bin_volt_sel(dev, np, bin, &bin_volt_sel); |
---|
.. | .. |
---|
1348 | 1396 | return dev_pm_opp_set_prop_name(dev, name); |
---|
1349 | 1397 | } |
---|
1350 | 1398 | EXPORT_SYMBOL(rockchip_set_opp_prop_name); |
---|
| 1399 | + |
---|
| 1400 | +struct opp_table *rockchip_set_opp_supported_hw(struct device *dev, |
---|
| 1401 | + struct device_node *np, |
---|
| 1402 | + int bin, int volt_sel) |
---|
| 1403 | +{ |
---|
| 1404 | + struct opp_table *opp_table; |
---|
| 1405 | + u32 supported_hw[2]; |
---|
| 1406 | + u32 version = 0, speed = 0; |
---|
| 1407 | + |
---|
| 1408 | + if (!of_property_read_bool(np, "rockchip,supported-hw")) |
---|
| 1409 | + return NULL; |
---|
| 1410 | + |
---|
| 1411 | + opp_table = dev_pm_opp_get_opp_table(dev); |
---|
| 1412 | + if (!opp_table) |
---|
| 1413 | + return NULL; |
---|
| 1414 | + if (opp_table->supported_hw) { |
---|
| 1415 | + dev_pm_opp_put_opp_table(opp_table); |
---|
| 1416 | + return NULL; |
---|
| 1417 | + } |
---|
| 1418 | + dev_pm_opp_put_opp_table(opp_table); |
---|
| 1419 | + |
---|
| 1420 | + if (bin >= 0) |
---|
| 1421 | + version = bin; |
---|
| 1422 | + if (volt_sel >= 0) |
---|
| 1423 | + speed = volt_sel; |
---|
| 1424 | + |
---|
| 1425 | + /* SoC Version */ |
---|
| 1426 | + supported_hw[0] = BIT(version); |
---|
| 1427 | + /* Speed Grade */ |
---|
| 1428 | + supported_hw[1] = BIT(speed); |
---|
| 1429 | + |
---|
| 1430 | + dev_info(dev, "soc version=%d, speed=%d\n", version, speed); |
---|
| 1431 | + |
---|
| 1432 | + return dev_pm_opp_set_supported_hw(dev, supported_hw, 2); |
---|
| 1433 | +} |
---|
| 1434 | +EXPORT_SYMBOL(rockchip_set_opp_supported_hw); |
---|
1351 | 1435 | |
---|
1352 | 1436 | static int rockchip_adjust_opp_by_irdrop(struct device *dev, |
---|
1353 | 1437 | struct device_node *np, |
---|
.. | .. |
---|
1484 | 1568 | if (opp->rate > opp_info.max_freq * 1000000) |
---|
1485 | 1569 | continue; |
---|
1486 | 1570 | |
---|
1487 | | - opp->supplies->u_volt += opp_info.volt * 1000; |
---|
1488 | | - if (opp->supplies->u_volt > opp->supplies->u_volt_max) |
---|
1489 | | - opp->supplies->u_volt = opp->supplies->u_volt_max; |
---|
| 1571 | + opp->supplies[0].u_volt += opp_info.volt * 1000; |
---|
| 1572 | + if (opp->supplies[0].u_volt > opp->supplies[0].u_volt_max) |
---|
| 1573 | + opp->supplies[0].u_volt = opp->supplies[0].u_volt_max; |
---|
| 1574 | + if (opp_table->regulator_count > 1) { |
---|
| 1575 | + opp->supplies[1].u_volt += opp_info.volt * 1000; |
---|
| 1576 | + if (opp->supplies[1].u_volt > opp->supplies[1].u_volt_max) |
---|
| 1577 | + opp->supplies[1].u_volt = opp->supplies[1].u_volt_max; |
---|
| 1578 | + } |
---|
1490 | 1579 | } |
---|
1491 | 1580 | mutex_unlock(&opp_table->lock); |
---|
1492 | 1581 | |
---|
.. | .. |
---|
1810 | 1899 | info->data->get_soc_info(dev, np, &bin, &process); |
---|
1811 | 1900 | |
---|
1812 | 1901 | next: |
---|
| 1902 | + rockchip_get_soc_info(dev, np, &bin, &process); |
---|
1813 | 1903 | rockchip_get_scale_volt_sel(dev, lkg_name, reg_name, bin, process, |
---|
1814 | 1904 | &scale, &volt_sel); |
---|
1815 | 1905 | if (info && info->data && info->data->set_soc_info) |
---|
1816 | 1906 | info->data->set_soc_info(dev, np, bin, process, volt_sel); |
---|
1817 | 1907 | rockchip_set_opp_prop_name(dev, process, volt_sel); |
---|
| 1908 | + rockchip_set_opp_supported_hw(dev, np, bin, volt_sel); |
---|
1818 | 1909 | ret = dev_pm_opp_of_add_table(dev); |
---|
1819 | 1910 | if (ret) { |
---|
1820 | 1911 | dev_err(dev, "Invalid operating-points in device tree.\n"); |
---|