.. | .. |
---|
12 | 12 | #include <linux/nvmem-consumer.h> |
---|
13 | 13 | #include <linux/regmap.h> |
---|
14 | 14 | #include <linux/regulator/consumer.h> |
---|
| 15 | +#include <linux/rockchip/rockchip_sip.h> |
---|
15 | 16 | #include <linux/slab.h> |
---|
16 | 17 | #include <linux/soc/rockchip/pvtm.h> |
---|
17 | 18 | #include <linux/thermal.h> |
---|
.. | .. |
---|
1004 | 1005 | } |
---|
1005 | 1006 | |
---|
1006 | 1007 | if (of_property_read_u32(np, "rockchip,pvtpll-len-min-rate", &min_rate)) |
---|
1007 | | - return; |
---|
| 1008 | + goto out; |
---|
1008 | 1009 | if (of_property_read_u32(np, "rockchip,pvtpll-len-max-rate", &max_rate)) |
---|
1009 | | - return; |
---|
| 1010 | + goto out; |
---|
1010 | 1011 | if (of_property_read_u32(np, "rockchip,pvtpll-len-margin", &margin)) |
---|
1011 | | - return; |
---|
| 1012 | + goto out; |
---|
1012 | 1013 | |
---|
1013 | 1014 | opp_table = dev_pm_opp_get_opp_table(info->dev); |
---|
1014 | 1015 | if (!opp_table) |
---|
1015 | | - return; |
---|
| 1016 | + goto out; |
---|
1016 | 1017 | old_rate = clk_get_rate(opp_table->clk); |
---|
1017 | 1018 | opp_flag = OPP_ADD_LENGTH | ((margin & OPP_LENGTH_MASK) << OPP_LENGTH_SHIFT); |
---|
1018 | 1019 | |
---|
.. | .. |
---|
1033 | 1034 | clk_set_rate(opp_table->clk, old_rate); |
---|
1034 | 1035 | |
---|
1035 | 1036 | dev_pm_opp_put_opp_table(opp_table); |
---|
| 1037 | +out: |
---|
| 1038 | + of_node_put(np); |
---|
1036 | 1039 | } |
---|
1037 | 1040 | EXPORT_SYMBOL(rockchip_pvtpll_add_length); |
---|
| 1041 | + |
---|
| 1042 | +void rockchip_init_pvtpll_table(struct rockchip_opp_info *info, int bin) |
---|
| 1043 | +{ |
---|
| 1044 | + struct device_node *np = NULL; |
---|
| 1045 | + struct property *prop = NULL; |
---|
| 1046 | + struct of_phandle_args clkspec = { 0 }; |
---|
| 1047 | + struct arm_smccc_res res; |
---|
| 1048 | + char prop_name[NAME_MAX]; |
---|
| 1049 | + u32 *value; |
---|
| 1050 | + int count; |
---|
| 1051 | + int ret, i; |
---|
| 1052 | + |
---|
| 1053 | + if (!info) |
---|
| 1054 | + return; |
---|
| 1055 | + |
---|
| 1056 | + np = of_parse_phandle(info->dev->of_node, "operating-points-v2", 0); |
---|
| 1057 | + if (!np) { |
---|
| 1058 | + dev_warn(info->dev, "OPP-v2 not supported\n"); |
---|
| 1059 | + return; |
---|
| 1060 | + } |
---|
| 1061 | + |
---|
| 1062 | + ret = of_parse_phandle_with_args(info->dev->of_node, "clocks", |
---|
| 1063 | + "#clock-cells", 0, &clkspec); |
---|
| 1064 | + if (ret) |
---|
| 1065 | + goto out; |
---|
| 1066 | + info->pvtpll_clk_id = clkspec.args[0]; |
---|
| 1067 | + of_node_put(clkspec.np); |
---|
| 1068 | + |
---|
| 1069 | + res = sip_smc_get_pvtpll_info(PVTPLL_GET_INFO, info->pvtpll_clk_id); |
---|
| 1070 | + if (res.a0) |
---|
| 1071 | + goto out; |
---|
| 1072 | + if (!res.a1) |
---|
| 1073 | + info->pvtpll_low_temp = true; |
---|
| 1074 | + |
---|
| 1075 | + if (bin > 0) { |
---|
| 1076 | + snprintf(prop_name, sizeof(prop_name), |
---|
| 1077 | + "rockchip,pvtpll-table-B%d", bin); |
---|
| 1078 | + prop = of_find_property(np, prop_name, NULL); |
---|
| 1079 | + } |
---|
| 1080 | + if (!prop) |
---|
| 1081 | + sprintf(prop_name, "rockchip,pvtpll-table"); |
---|
| 1082 | + |
---|
| 1083 | + prop = of_find_property(np, prop_name, NULL); |
---|
| 1084 | + if (!prop) |
---|
| 1085 | + goto out; |
---|
| 1086 | + |
---|
| 1087 | + count = of_property_count_u32_elems(np, prop_name); |
---|
| 1088 | + if (count < 0) { |
---|
| 1089 | + dev_err(info->dev, "%s: Invalid %s property (%d)\n", |
---|
| 1090 | + __func__, prop_name, count); |
---|
| 1091 | + goto out; |
---|
| 1092 | + } else if (count % 5) { |
---|
| 1093 | + dev_err(info->dev, "Invalid count of %s\n", prop_name); |
---|
| 1094 | + goto out; |
---|
| 1095 | + } |
---|
| 1096 | + |
---|
| 1097 | + value = kmalloc_array(count, sizeof(*value), GFP_KERNEL); |
---|
| 1098 | + if (!value) |
---|
| 1099 | + goto out; |
---|
| 1100 | + ret = of_property_read_u32_array(np, prop_name, value, count); |
---|
| 1101 | + if (ret) { |
---|
| 1102 | + dev_err(info->dev, "%s: error parsing %s: %d\n", |
---|
| 1103 | + __func__, prop_name, ret); |
---|
| 1104 | + goto free_value; |
---|
| 1105 | + } |
---|
| 1106 | + |
---|
| 1107 | + for (i = 0; i < count; i += 5) { |
---|
| 1108 | + res = sip_smc_pvtpll_config(PVTPLL_ADJUST_TABLE, |
---|
| 1109 | + info->pvtpll_clk_id, value[i], |
---|
| 1110 | + value[i + 1], value[i + 2], |
---|
| 1111 | + value[i + 3], value[i + 4]); |
---|
| 1112 | + if (res.a0) { |
---|
| 1113 | + dev_err(info->dev, |
---|
| 1114 | + "%s: error cfg clk_id=%u %u %u %u %u %u (%d)\n", |
---|
| 1115 | + __func__, info->pvtpll_clk_id, value[i], |
---|
| 1116 | + value[i + 1], value[i + 2], value[i + 3], |
---|
| 1117 | + value[i + 4], (int)res.a0); |
---|
| 1118 | + goto free_value; |
---|
| 1119 | + } |
---|
| 1120 | + } |
---|
| 1121 | + |
---|
| 1122 | +free_value: |
---|
| 1123 | + kfree(value); |
---|
| 1124 | +out: |
---|
| 1125 | + of_node_put(np); |
---|
| 1126 | +} |
---|
| 1127 | +EXPORT_SYMBOL(rockchip_init_pvtpll_table); |
---|
1038 | 1128 | |
---|
1039 | 1129 | static int rockchip_get_pvtm_pvtpll(struct device *dev, struct device_node *np, |
---|
1040 | 1130 | char *reg_name) |
---|
.. | .. |
---|
1165 | 1255 | } |
---|
1166 | 1256 | |
---|
1167 | 1257 | void rockchip_of_get_pvtm_sel(struct device *dev, struct device_node *np, |
---|
1168 | | - char *reg_name, int process, |
---|
| 1258 | + char *reg_name, int bin, int process, |
---|
1169 | 1259 | int *volt_sel, int *scale_sel) |
---|
1170 | 1260 | { |
---|
1171 | 1261 | struct property *prop = NULL; |
---|
1172 | 1262 | char name[NAME_MAX]; |
---|
1173 | 1263 | int pvtm, ret; |
---|
| 1264 | + u32 hw = 0; |
---|
1174 | 1265 | |
---|
1175 | 1266 | if (of_property_read_bool(np, "rockchip,pvtm-pvtpll")) |
---|
1176 | 1267 | pvtm = rockchip_get_pvtm_pvtpll(dev, np, reg_name); |
---|
.. | .. |
---|
1185 | 1276 | snprintf(name, sizeof(name), |
---|
1186 | 1277 | "rockchip,p%d-pvtm-voltage-sel", process); |
---|
1187 | 1278 | prop = of_find_property(np, name, NULL); |
---|
| 1279 | + } else if (bin > 0) { |
---|
| 1280 | + of_property_read_u32(np, "rockchip,pvtm-hw", &hw); |
---|
| 1281 | + if (hw && (hw & BIT(bin))) { |
---|
| 1282 | + sprintf(name, "rockchip,pvtm-voltage-sel-hw"); |
---|
| 1283 | + prop = of_find_property(np, name, NULL); |
---|
| 1284 | + } |
---|
| 1285 | + if (!prop) { |
---|
| 1286 | + snprintf(name, sizeof(name), |
---|
| 1287 | + "rockchip,pvtm-voltage-sel-B%d", bin); |
---|
| 1288 | + prop = of_find_property(np, name, NULL); |
---|
| 1289 | + } |
---|
1188 | 1290 | } |
---|
1189 | 1291 | if (!prop) |
---|
1190 | 1292 | sprintf(name, "rockchip,pvtm-voltage-sel"); |
---|
.. | .. |
---|
1195 | 1297 | next: |
---|
1196 | 1298 | if (!scale_sel) |
---|
1197 | 1299 | return; |
---|
| 1300 | + prop = NULL; |
---|
1198 | 1301 | if (process >= 0) { |
---|
1199 | 1302 | snprintf(name, sizeof(name), |
---|
1200 | 1303 | "rockchip,p%d-pvtm-scaling-sel", process); |
---|
.. | .. |
---|
1294 | 1397 | } |
---|
1295 | 1398 | EXPORT_SYMBOL(rockchip_get_volt_rm_table); |
---|
1296 | 1399 | |
---|
| 1400 | +int rockchip_get_soc_info(struct device *dev, struct device_node *np, int *bin, |
---|
| 1401 | + int *process) |
---|
| 1402 | +{ |
---|
| 1403 | + u8 value = 0; |
---|
| 1404 | + int ret = 0; |
---|
| 1405 | + |
---|
| 1406 | + if (*bin >= 0 || *process >= 0) |
---|
| 1407 | + return 0; |
---|
| 1408 | + |
---|
| 1409 | + if (of_property_match_string(np, "nvmem-cell-names", |
---|
| 1410 | + "remark_spec_serial_number") >= 0) |
---|
| 1411 | + rockchip_nvmem_cell_read_u8(np, "remark_spec_serial_number", &value); |
---|
| 1412 | + |
---|
| 1413 | + if (!value && of_property_match_string(np, "nvmem-cell-names", |
---|
| 1414 | + "specification_serial_number") >= 0) { |
---|
| 1415 | + ret = rockchip_nvmem_cell_read_u8(np, |
---|
| 1416 | + "specification_serial_number", |
---|
| 1417 | + &value); |
---|
| 1418 | + if (ret) { |
---|
| 1419 | + dev_err(dev, |
---|
| 1420 | + "Failed to get specification_serial_number\n"); |
---|
| 1421 | + return ret; |
---|
| 1422 | + } |
---|
| 1423 | + } |
---|
| 1424 | + |
---|
| 1425 | + /* M */ |
---|
| 1426 | + if (value == 0xd) |
---|
| 1427 | + *bin = 1; |
---|
| 1428 | + /* J */ |
---|
| 1429 | + else if (value == 0xa) |
---|
| 1430 | + *bin = 2; |
---|
| 1431 | + |
---|
| 1432 | + if (*bin < 0) |
---|
| 1433 | + *bin = 0; |
---|
| 1434 | + dev_info(dev, "bin=%d\n", *bin); |
---|
| 1435 | + |
---|
| 1436 | + return 0; |
---|
| 1437 | +} |
---|
| 1438 | +EXPORT_SYMBOL(rockchip_get_soc_info); |
---|
| 1439 | + |
---|
1297 | 1440 | void rockchip_get_scale_volt_sel(struct device *dev, char *lkg_name, |
---|
1298 | 1441 | char *reg_name, int bin, int process, |
---|
1299 | 1442 | int *scale, int *volt_sel) |
---|
.. | .. |
---|
1311 | 1454 | |
---|
1312 | 1455 | rockchip_of_get_lkg_sel(dev, np, lkg_name, process, |
---|
1313 | 1456 | &lkg_volt_sel, &lkg_scale); |
---|
1314 | | - rockchip_of_get_pvtm_sel(dev, np, reg_name, process, |
---|
| 1457 | + rockchip_of_get_pvtm_sel(dev, np, reg_name, bin, process, |
---|
1315 | 1458 | &pvtm_volt_sel, &pvtm_scale); |
---|
1316 | 1459 | rockchip_of_get_bin_sel(dev, np, bin, &bin_scale); |
---|
1317 | 1460 | rockchip_of_get_bin_volt_sel(dev, np, bin, &bin_volt_sel); |
---|
.. | .. |
---|
1348 | 1491 | return dev_pm_opp_set_prop_name(dev, name); |
---|
1349 | 1492 | } |
---|
1350 | 1493 | EXPORT_SYMBOL(rockchip_set_opp_prop_name); |
---|
| 1494 | + |
---|
| 1495 | +struct opp_table *rockchip_set_opp_supported_hw(struct device *dev, |
---|
| 1496 | + struct device_node *np, |
---|
| 1497 | + int bin, int volt_sel) |
---|
| 1498 | +{ |
---|
| 1499 | + struct opp_table *opp_table; |
---|
| 1500 | + u32 supported_hw[2]; |
---|
| 1501 | + u32 version = 0, speed = 0; |
---|
| 1502 | + |
---|
| 1503 | + if (!of_property_read_bool(np, "rockchip,supported-hw")) |
---|
| 1504 | + return NULL; |
---|
| 1505 | + |
---|
| 1506 | + opp_table = dev_pm_opp_get_opp_table(dev); |
---|
| 1507 | + if (!opp_table) |
---|
| 1508 | + return NULL; |
---|
| 1509 | + if (opp_table->supported_hw) { |
---|
| 1510 | + dev_pm_opp_put_opp_table(opp_table); |
---|
| 1511 | + return NULL; |
---|
| 1512 | + } |
---|
| 1513 | + dev_pm_opp_put_opp_table(opp_table); |
---|
| 1514 | + |
---|
| 1515 | + if (bin >= 0) |
---|
| 1516 | + version = bin; |
---|
| 1517 | + if (volt_sel >= 0) |
---|
| 1518 | + speed = volt_sel; |
---|
| 1519 | + |
---|
| 1520 | + /* SoC Version */ |
---|
| 1521 | + supported_hw[0] = BIT(version); |
---|
| 1522 | + /* Speed Grade */ |
---|
| 1523 | + supported_hw[1] = BIT(speed); |
---|
| 1524 | + |
---|
| 1525 | + dev_info(dev, "soc version=%d, speed=%d\n", version, speed); |
---|
| 1526 | + |
---|
| 1527 | + return dev_pm_opp_set_supported_hw(dev, supported_hw, 2); |
---|
| 1528 | +} |
---|
| 1529 | +EXPORT_SYMBOL(rockchip_set_opp_supported_hw); |
---|
1351 | 1530 | |
---|
1352 | 1531 | static int rockchip_adjust_opp_by_irdrop(struct device *dev, |
---|
1353 | 1532 | struct device_node *np, |
---|
.. | .. |
---|
1484 | 1663 | if (opp->rate > opp_info.max_freq * 1000000) |
---|
1485 | 1664 | continue; |
---|
1486 | 1665 | |
---|
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; |
---|
| 1666 | + opp->supplies[0].u_volt += opp_info.volt * 1000; |
---|
| 1667 | + if (opp->supplies[0].u_volt > opp->supplies[0].u_volt_max) |
---|
| 1668 | + opp->supplies[0].u_volt = opp->supplies[0].u_volt_max; |
---|
| 1669 | + if (opp_table->regulator_count > 1) { |
---|
| 1670 | + opp->supplies[1].u_volt += opp_info.volt * 1000; |
---|
| 1671 | + if (opp->supplies[1].u_volt > opp->supplies[1].u_volt_max) |
---|
| 1672 | + opp->supplies[1].u_volt = opp->supplies[1].u_volt_max; |
---|
| 1673 | + } |
---|
1490 | 1674 | } |
---|
1491 | 1675 | mutex_unlock(&opp_table->lock); |
---|
1492 | 1676 | |
---|
.. | .. |
---|
1544 | 1728 | rockchip_adjust_opp_by_irdrop(dev, np, &safe_rate, &max_rate); |
---|
1545 | 1729 | |
---|
1546 | 1730 | dev_info(dev, "avs=%d\n", avs); |
---|
| 1731 | + |
---|
| 1732 | + if (!safe_rate && !scale) |
---|
| 1733 | + goto out_np; |
---|
| 1734 | + |
---|
1547 | 1735 | clk = of_clk_get_by_name(np, NULL); |
---|
1548 | 1736 | if (IS_ERR(clk)) { |
---|
1549 | 1737 | if (!safe_rate) |
---|
.. | .. |
---|
1557 | 1745 | |
---|
1558 | 1746 | if (safe_rate) |
---|
1559 | 1747 | irdrop_scale = rockchip_pll_clk_rate_to_scale(clk, safe_rate); |
---|
1560 | | - if (max_rate) |
---|
1561 | | - opp_scale = rockchip_pll_clk_rate_to_scale(clk, max_rate); |
---|
1562 | 1748 | target_scale = max(irdrop_scale, scale); |
---|
1563 | 1749 | if (target_scale <= 0) |
---|
1564 | 1750 | goto out_clk; |
---|
1565 | 1751 | dev_dbg(dev, "target_scale=%d, irdrop_scale=%d, scale=%d\n", |
---|
1566 | 1752 | target_scale, irdrop_scale, scale); |
---|
1567 | 1753 | |
---|
| 1754 | + if (max_rate) |
---|
| 1755 | + opp_scale = rockchip_pll_clk_rate_to_scale(clk, max_rate); |
---|
1568 | 1756 | if (avs == AVS_SCALING_RATE) { |
---|
1569 | 1757 | ret = rockchip_pll_clk_adaptive_scaling(clk, target_scale); |
---|
1570 | 1758 | if (ret) |
---|
.. | .. |
---|
1749 | 1937 | } |
---|
1750 | 1938 | EXPORT_SYMBOL(rockchip_set_intermediate_rate); |
---|
1751 | 1939 | |
---|
| 1940 | +static int rockchip_get_opp_clk(struct device *dev, struct device_node *np, |
---|
| 1941 | + struct rockchip_opp_info *info) |
---|
| 1942 | +{ |
---|
| 1943 | + struct clk_bulk_data *clks; |
---|
| 1944 | + struct of_phandle_args clkspec; |
---|
| 1945 | + int ret = 0, num_clks = 0, i; |
---|
| 1946 | + |
---|
| 1947 | + if (of_find_property(np, "rockchip,opp-clocks", NULL)) { |
---|
| 1948 | + num_clks = of_count_phandle_with_args(np, "rockchip,opp-clocks", |
---|
| 1949 | + "#clock-cells"); |
---|
| 1950 | + if (num_clks <= 0) |
---|
| 1951 | + return 0; |
---|
| 1952 | + clks = devm_kcalloc(dev, num_clks, sizeof(*clks), GFP_KERNEL); |
---|
| 1953 | + if (!clks) |
---|
| 1954 | + return -ENOMEM; |
---|
| 1955 | + for (i = 0; i < num_clks; i++) { |
---|
| 1956 | + ret = of_parse_phandle_with_args(np, |
---|
| 1957 | + "rockchip,opp-clocks", |
---|
| 1958 | + "#clock-cells", i, |
---|
| 1959 | + &clkspec); |
---|
| 1960 | + if (ret < 0) { |
---|
| 1961 | + dev_err(dev, "%s: failed to parse opp clk %d\n", |
---|
| 1962 | + np->name, i); |
---|
| 1963 | + goto error; |
---|
| 1964 | + } |
---|
| 1965 | + clks[i].clk = of_clk_get_from_provider(&clkspec); |
---|
| 1966 | + of_node_put(clkspec.np); |
---|
| 1967 | + if (IS_ERR(clks[i].clk)) { |
---|
| 1968 | + ret = PTR_ERR(clks[i].clk); |
---|
| 1969 | + clks[i].clk = NULL; |
---|
| 1970 | + dev_err(dev, "%s: failed to get opp clk %d\n", |
---|
| 1971 | + np->name, i); |
---|
| 1972 | + goto error; |
---|
| 1973 | + } |
---|
| 1974 | + } |
---|
| 1975 | + } else { |
---|
| 1976 | + num_clks = of_clk_get_parent_count(np); |
---|
| 1977 | + if (num_clks <= 0) |
---|
| 1978 | + return 0; |
---|
| 1979 | + clks = devm_kcalloc(dev, num_clks, sizeof(*clks), GFP_KERNEL); |
---|
| 1980 | + if (!clks) |
---|
| 1981 | + return -ENOMEM; |
---|
| 1982 | + for (i = 0; i < num_clks; i++) { |
---|
| 1983 | + clks[i].clk = of_clk_get(np, i); |
---|
| 1984 | + if (IS_ERR(clks[i].clk)) { |
---|
| 1985 | + ret = PTR_ERR(clks[i].clk); |
---|
| 1986 | + clks[i].clk = NULL; |
---|
| 1987 | + dev_err(dev, "%s: failed to get clk %d\n", |
---|
| 1988 | + np->name, i); |
---|
| 1989 | + goto error; |
---|
| 1990 | + } |
---|
| 1991 | + } |
---|
| 1992 | + } |
---|
| 1993 | + info->clks = clks; |
---|
| 1994 | + info->num_clks = num_clks; |
---|
| 1995 | + |
---|
| 1996 | + return 0; |
---|
| 1997 | +error: |
---|
| 1998 | + while (--i >= 0) |
---|
| 1999 | + clk_put(clks[i].clk); |
---|
| 2000 | + devm_kfree(dev, clks); |
---|
| 2001 | + |
---|
| 2002 | + return ret; |
---|
| 2003 | +} |
---|
| 2004 | + |
---|
1752 | 2005 | int rockchip_init_opp_table(struct device *dev, struct rockchip_opp_info *info, |
---|
1753 | 2006 | char *lkg_name, char *reg_name) |
---|
1754 | 2007 | { |
---|
1755 | 2008 | struct device_node *np; |
---|
1756 | 2009 | int bin = -EINVAL, process = -EINVAL; |
---|
1757 | 2010 | int scale = 0, volt_sel = -EINVAL; |
---|
1758 | | - int ret = 0, num_clks = 0, i; |
---|
| 2011 | + int ret = 0; |
---|
1759 | 2012 | u32 freq; |
---|
1760 | 2013 | |
---|
1761 | 2014 | /* Get OPP descriptor node */ |
---|
.. | .. |
---|
1768 | 2021 | goto next; |
---|
1769 | 2022 | info->dev = dev; |
---|
1770 | 2023 | |
---|
1771 | | - num_clks = of_clk_get_parent_count(np); |
---|
1772 | | - if (num_clks > 0) { |
---|
1773 | | - info->clks = devm_kcalloc(dev, num_clks, sizeof(*info->clks), |
---|
1774 | | - GFP_KERNEL); |
---|
1775 | | - if (!info->clks) { |
---|
1776 | | - ret = -ENOMEM; |
---|
1777 | | - goto out; |
---|
1778 | | - } |
---|
1779 | | - for (i = 0; i < num_clks; i++) { |
---|
1780 | | - info->clks[i].clk = of_clk_get(np, i); |
---|
1781 | | - if (IS_ERR(info->clks[i].clk)) { |
---|
1782 | | - ret = PTR_ERR(info->clks[i].clk); |
---|
1783 | | - dev_err(dev, "%s: failed to get clk %d\n", |
---|
1784 | | - np->name, i); |
---|
1785 | | - goto out; |
---|
1786 | | - } |
---|
1787 | | - } |
---|
1788 | | - info->num_clks = num_clks; |
---|
| 2024 | + ret = rockchip_get_opp_clk(dev, np, info); |
---|
| 2025 | + if (ret) |
---|
| 2026 | + goto out; |
---|
| 2027 | + if (info->clks) { |
---|
1789 | 2028 | ret = clk_bulk_prepare_enable(info->num_clks, info->clks); |
---|
1790 | 2029 | if (ret) { |
---|
1791 | 2030 | dev_err(dev, "failed to enable opp clks\n"); |
---|
.. | .. |
---|
1810 | 2049 | info->data->get_soc_info(dev, np, &bin, &process); |
---|
1811 | 2050 | |
---|
1812 | 2051 | next: |
---|
| 2052 | + rockchip_get_soc_info(dev, np, &bin, &process); |
---|
| 2053 | + rockchip_init_pvtpll_table(info, bin); |
---|
1813 | 2054 | rockchip_get_scale_volt_sel(dev, lkg_name, reg_name, bin, process, |
---|
1814 | 2055 | &scale, &volt_sel); |
---|
1815 | 2056 | if (info && info->data && info->data->set_soc_info) |
---|
1816 | 2057 | info->data->set_soc_info(dev, np, bin, process, volt_sel); |
---|
1817 | 2058 | rockchip_set_opp_prop_name(dev, process, volt_sel); |
---|
| 2059 | + rockchip_set_opp_supported_hw(dev, np, bin, volt_sel); |
---|
1818 | 2060 | ret = dev_pm_opp_of_add_table(dev); |
---|
1819 | 2061 | if (ret) { |
---|
1820 | 2062 | dev_err(dev, "Invalid operating-points in device tree.\n"); |
---|
.. | .. |
---|
1834 | 2076 | } |
---|
1835 | 2077 | EXPORT_SYMBOL(rockchip_init_opp_table); |
---|
1836 | 2078 | |
---|
| 2079 | +void rockchip_uninit_opp_table(struct device *dev, struct rockchip_opp_info *info) |
---|
| 2080 | +{ |
---|
| 2081 | + struct opp_table *opp_table; |
---|
| 2082 | + |
---|
| 2083 | + if (info) { |
---|
| 2084 | + kfree(info->opp_table); |
---|
| 2085 | + info->opp_table = NULL; |
---|
| 2086 | + devm_kfree(dev, info->clks); |
---|
| 2087 | + info->clks = NULL; |
---|
| 2088 | + devm_kfree(dev, info->volt_rm_tbl); |
---|
| 2089 | + info->volt_rm_tbl = NULL; |
---|
| 2090 | + } |
---|
| 2091 | + |
---|
| 2092 | + opp_table = dev_pm_opp_get_opp_table(dev); |
---|
| 2093 | + if (IS_ERR(opp_table)) |
---|
| 2094 | + return; |
---|
| 2095 | + dev_pm_opp_of_remove_table(dev); |
---|
| 2096 | + if (opp_table->prop_name) |
---|
| 2097 | + dev_pm_opp_put_prop_name(opp_table); |
---|
| 2098 | + if (opp_table->supported_hw) |
---|
| 2099 | + dev_pm_opp_put_supported_hw(opp_table); |
---|
| 2100 | + dev_pm_opp_put_opp_table(opp_table); |
---|
| 2101 | +} |
---|
| 2102 | +EXPORT_SYMBOL(rockchip_uninit_opp_table); |
---|
| 2103 | + |
---|
1837 | 2104 | MODULE_DESCRIPTION("ROCKCHIP OPP Select"); |
---|
1838 | 2105 | MODULE_AUTHOR("Finley Xiao <finley.xiao@rock-chips.com>, Liang Chen <cl@rock-chips.com>"); |
---|
1839 | 2106 | MODULE_LICENSE("GPL"); |
---|