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

PM / OPP: Add infrastructure to manage multiple regulators

This patch adds infrastructure to manage multiple regulators and updates
the only user (cpufreq-dt) of dev_pm_opp_set{put}_regulator().

This is preparatory work for adding full support for devices with
multiple regulators.

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
Tested-by: Dave Gerlach <d-gerlach@ti.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

authored by

Viresh Kumar and committed by
Rafael J. Wysocki
dfbe4678 ce31781a

+299 -126
+170 -76
drivers/base/power/opp/core.c
··· 93 93 * Return: voltage in micro volt corresponding to the opp, else 94 94 * return 0 95 95 * 96 + * This is useful only for devices with single power supply. 97 + * 96 98 * Locking: This function must be called under rcu_read_lock(). opp is a rcu 97 99 * protected pointer. This means that opp which could have been fetched by 98 100 * opp_find_freq_{exact,ceil,floor} functions is valid as long as we are ··· 114 112 if (IS_ERR_OR_NULL(tmp_opp)) 115 113 pr_err("%s: Invalid parameters\n", __func__); 116 114 else 117 - v = tmp_opp->supply.u_volt; 115 + v = tmp_opp->supplies[0].u_volt; 118 116 119 117 return v; 120 118 } ··· 212 210 } 213 211 EXPORT_SYMBOL_GPL(dev_pm_opp_get_max_clock_latency); 214 212 213 + static int _get_regulator_count(struct device *dev) 214 + { 215 + struct opp_table *opp_table; 216 + int count; 217 + 218 + rcu_read_lock(); 219 + 220 + opp_table = _find_opp_table(dev); 221 + if (!IS_ERR(opp_table)) 222 + count = opp_table->regulator_count; 223 + else 224 + count = 0; 225 + 226 + rcu_read_unlock(); 227 + 228 + return count; 229 + } 230 + 215 231 /** 216 232 * dev_pm_opp_get_max_volt_latency() - Get max voltage latency in nanoseconds 217 233 * @dev: device for which we do this operation ··· 242 222 { 243 223 struct opp_table *opp_table; 244 224 struct dev_pm_opp *opp; 245 - struct regulator *reg; 225 + struct regulator *reg, **regulators; 246 226 unsigned long latency_ns = 0; 247 - unsigned long min_uV = ~0, max_uV = 0; 248 - int ret; 227 + int ret, i, count; 228 + struct { 229 + unsigned long min; 230 + unsigned long max; 231 + } *uV; 232 + 233 + count = _get_regulator_count(dev); 234 + 235 + /* Regulator may not be required for the device */ 236 + if (!count) 237 + return 0; 238 + 239 + regulators = kmalloc_array(count, sizeof(*regulators), GFP_KERNEL); 240 + if (!regulators) 241 + return 0; 242 + 243 + uV = kmalloc_array(count, sizeof(*uV), GFP_KERNEL); 244 + if (!uV) 245 + goto free_regulators; 249 246 250 247 rcu_read_lock(); 251 248 252 249 opp_table = _find_opp_table(dev); 253 250 if (IS_ERR(opp_table)) { 254 251 rcu_read_unlock(); 255 - return 0; 252 + goto free_uV; 256 253 } 257 254 258 - reg = opp_table->regulator; 259 - if (IS_ERR(reg)) { 260 - /* Regulator may not be required for device */ 261 - rcu_read_unlock(); 262 - return 0; 263 - } 255 + memcpy(regulators, opp_table->regulators, count * sizeof(*regulators)); 264 256 265 - list_for_each_entry_rcu(opp, &opp_table->opp_list, node) { 266 - if (!opp->available) 267 - continue; 257 + for (i = 0; i < count; i++) { 258 + uV[i].min = ~0; 259 + uV[i].max = 0; 268 260 269 - if (opp->supply.u_volt_min < min_uV) 270 - min_uV = opp->supply.u_volt_min; 271 - if (opp->supply.u_volt_max > max_uV) 272 - max_uV = opp->supply.u_volt_max; 261 + list_for_each_entry_rcu(opp, &opp_table->opp_list, node) { 262 + if (!opp->available) 263 + continue; 264 + 265 + if (opp->supplies[i].u_volt_min < uV[i].min) 266 + uV[i].min = opp->supplies[i].u_volt_min; 267 + if (opp->supplies[i].u_volt_max > uV[i].max) 268 + uV[i].max = opp->supplies[i].u_volt_max; 269 + } 273 270 } 274 271 275 272 rcu_read_unlock(); ··· 295 258 * The caller needs to ensure that opp_table (and hence the regulator) 296 259 * isn't freed, while we are executing this routine. 297 260 */ 298 - ret = regulator_set_voltage_time(reg, min_uV, max_uV); 299 - if (ret > 0) 300 - latency_ns = ret * 1000; 261 + for (i = 0; reg = regulators[i], i < count; i++) { 262 + ret = regulator_set_voltage_time(reg, uV[i].min, uV[i].max); 263 + if (ret > 0) 264 + latency_ns += ret * 1000; 265 + } 266 + 267 + free_uV: 268 + kfree(uV); 269 + free_regulators: 270 + kfree(regulators); 301 271 302 272 return latency_ns; 303 273 } ··· 624 580 { 625 581 struct opp_table *opp_table; 626 582 struct dev_pm_opp *old_opp, *opp; 627 - struct regulator *reg; 583 + struct regulator *reg = ERR_PTR(-ENXIO); 628 584 struct clk *clk; 629 585 unsigned long freq, old_freq; 630 586 struct dev_pm_opp_supply old_supply, new_supply; ··· 677 633 return ret; 678 634 } 679 635 636 + if (opp_table->regulators) { 637 + /* This function only supports single regulator per device */ 638 + if (WARN_ON(opp_table->regulator_count > 1)) { 639 + dev_err(dev, "multiple regulators not supported\n"); 640 + rcu_read_unlock(); 641 + return -EINVAL; 642 + } 643 + 644 + reg = opp_table->regulators[0]; 645 + } 646 + 680 647 if (IS_ERR(old_opp)) 681 648 old_supply.u_volt = 0; 682 649 else 683 - memcpy(&old_supply, &old_opp->supply, sizeof(old_supply)); 650 + memcpy(&old_supply, old_opp->supplies, sizeof(old_supply)); 684 651 685 - memcpy(&new_supply, &opp->supply, sizeof(new_supply)); 686 - 687 - reg = opp_table->regulator; 652 + memcpy(&new_supply, opp->supplies, sizeof(new_supply)); 688 653 689 654 rcu_read_unlock(); 690 655 ··· 817 764 818 765 _of_init_opp_table(opp_table, dev); 819 766 820 - /* Set regulator to a non-NULL error value */ 821 - opp_table->regulator = ERR_PTR(-ENXIO); 822 - 823 767 /* Find clk for the device */ 824 768 opp_table->clk = clk_get(dev, NULL); 825 769 if (IS_ERR(opp_table->clk)) { ··· 865 815 if (opp_table->prop_name) 866 816 return; 867 817 868 - if (!IS_ERR(opp_table->regulator)) 818 + if (opp_table->regulators) 869 819 return; 870 820 871 821 /* Release clk */ ··· 974 924 struct opp_table **opp_table) 975 925 { 976 926 struct dev_pm_opp *opp; 927 + int count, supply_size; 928 + struct opp_table *table; 977 929 978 - /* allocate new OPP node */ 979 - opp = kzalloc(sizeof(*opp), GFP_KERNEL); 980 - if (!opp) 930 + table = _add_opp_table(dev); 931 + if (!table) 981 932 return NULL; 982 933 983 - INIT_LIST_HEAD(&opp->node); 934 + /* Allocate space for at least one supply */ 935 + count = table->regulator_count ? table->regulator_count : 1; 936 + supply_size = sizeof(*opp->supplies) * count; 984 937 985 - *opp_table = _add_opp_table(dev); 986 - if (!*opp_table) { 987 - kfree(opp); 938 + /* allocate new OPP node and supplies structures */ 939 + opp = kzalloc(sizeof(*opp) + supply_size, GFP_KERNEL); 940 + if (!opp) { 941 + kfree(table); 988 942 return NULL; 989 943 } 944 + 945 + /* Put the supplies at the end of the OPP structure as an empty array */ 946 + opp->supplies = (struct dev_pm_opp_supply *)(opp + 1); 947 + INIT_LIST_HEAD(&opp->node); 948 + 949 + *opp_table = table; 990 950 991 951 return opp; 992 952 } ··· 1004 944 static bool _opp_supported_by_regulators(struct dev_pm_opp *opp, 1005 945 struct opp_table *opp_table) 1006 946 { 1007 - struct regulator *reg = opp_table->regulator; 947 + struct regulator *reg; 948 + int i; 1008 949 1009 - if (!IS_ERR(reg) && 1010 - !regulator_is_supported_voltage(reg, opp->supply.u_volt_min, 1011 - opp->supply.u_volt_max)) { 1012 - pr_warn("%s: OPP minuV: %lu maxuV: %lu, not supported by regulator\n", 1013 - __func__, opp->supply.u_volt_min, 1014 - opp->supply.u_volt_max); 1015 - return false; 950 + for (i = 0; i < opp_table->regulator_count; i++) { 951 + reg = opp_table->regulators[i]; 952 + 953 + if (!regulator_is_supported_voltage(reg, 954 + opp->supplies[i].u_volt_min, 955 + opp->supplies[i].u_volt_max)) { 956 + pr_warn("%s: OPP minuV: %lu maxuV: %lu, not supported by regulator\n", 957 + __func__, opp->supplies[i].u_volt_min, 958 + opp->supplies[i].u_volt_max); 959 + return false; 960 + } 1016 961 } 1017 962 1018 963 return true; ··· 1049 984 1050 985 /* Duplicate OPPs */ 1051 986 dev_warn(dev, "%s: duplicate OPPs detected. Existing: freq: %lu, volt: %lu, enabled: %d. New: freq: %lu, volt: %lu, enabled: %d\n", 1052 - __func__, opp->rate, opp->supply.u_volt, 1053 - opp->available, new_opp->rate, new_opp->supply.u_volt, 1054 - new_opp->available); 987 + __func__, opp->rate, opp->supplies[0].u_volt, 988 + opp->available, new_opp->rate, 989 + new_opp->supplies[0].u_volt, new_opp->available); 1055 990 991 + /* Should we compare voltages for all regulators here ? */ 1056 992 return opp->available && 1057 - new_opp->supply.u_volt == opp->supply.u_volt ? 0 : -EEXIST; 993 + new_opp->supplies[0].u_volt == opp->supplies[0].u_volt ? 0 : -EEXIST; 1058 994 } 1059 995 1060 996 new_opp->opp_table = opp_table; ··· 1122 1056 /* populate the opp table */ 1123 1057 new_opp->rate = freq; 1124 1058 tol = u_volt * opp_table->voltage_tolerance_v1 / 100; 1125 - new_opp->supply.u_volt = u_volt; 1126 - new_opp->supply.u_volt_min = u_volt - tol; 1127 - new_opp->supply.u_volt_max = u_volt + tol; 1059 + new_opp->supplies[0].u_volt = u_volt; 1060 + new_opp->supplies[0].u_volt_min = u_volt - tol; 1061 + new_opp->supplies[0].u_volt_max = u_volt + tol; 1128 1062 new_opp->available = true; 1129 1063 new_opp->dynamic = dynamic; 1130 1064 ··· 1369 1303 EXPORT_SYMBOL_GPL(dev_pm_opp_put_prop_name); 1370 1304 1371 1305 /** 1372 - * dev_pm_opp_set_regulator() - Set regulator name for the device 1306 + * dev_pm_opp_set_regulators() - Set regulator names for the device 1373 1307 * @dev: Device for which regulator name is being set. 1374 - * @name: Name of the regulator. 1308 + * @names: Array of pointers to the names of the regulator. 1309 + * @count: Number of regulators. 1375 1310 * 1376 1311 * In order to support OPP switching, OPP layer needs to know the name of the 1377 - * device's regulator, as the core would be required to switch voltages as well. 1312 + * device's regulators, as the core would be required to switch voltages as 1313 + * well. 1378 1314 * 1379 1315 * This must be called before any OPPs are initialized for the device. 1380 1316 * ··· 1386 1318 * that this function is *NOT* called under RCU protection or in contexts where 1387 1319 * mutex cannot be locked. 1388 1320 */ 1389 - struct opp_table *dev_pm_opp_set_regulator(struct device *dev, const char *name) 1321 + struct opp_table *dev_pm_opp_set_regulators(struct device *dev, 1322 + const char * const names[], 1323 + unsigned int count) 1390 1324 { 1391 1325 struct opp_table *opp_table; 1392 1326 struct regulator *reg; 1393 - int ret; 1327 + int ret, i; 1394 1328 1395 1329 mutex_lock(&opp_table_lock); 1396 1330 ··· 1408 1338 goto err; 1409 1339 } 1410 1340 1411 - /* Already have a regulator set */ 1412 - if (WARN_ON(!IS_ERR(opp_table->regulator))) { 1341 + /* Already have regulators set */ 1342 + if (WARN_ON(opp_table->regulators)) { 1413 1343 ret = -EBUSY; 1414 1344 goto err; 1415 1345 } 1416 - /* Allocate the regulator */ 1417 - reg = regulator_get_optional(dev, name); 1418 - if (IS_ERR(reg)) { 1419 - ret = PTR_ERR(reg); 1420 - if (ret != -EPROBE_DEFER) 1421 - dev_err(dev, "%s: no regulator (%s) found: %d\n", 1422 - __func__, name, ret); 1346 + 1347 + opp_table->regulators = kmalloc_array(count, 1348 + sizeof(*opp_table->regulators), 1349 + GFP_KERNEL); 1350 + if (!opp_table->regulators) { 1351 + ret = -ENOMEM; 1423 1352 goto err; 1424 1353 } 1425 1354 1426 - opp_table->regulator = reg; 1355 + for (i = 0; i < count; i++) { 1356 + reg = regulator_get_optional(dev, names[i]); 1357 + if (IS_ERR(reg)) { 1358 + ret = PTR_ERR(reg); 1359 + if (ret != -EPROBE_DEFER) 1360 + dev_err(dev, "%s: no regulator (%s) found: %d\n", 1361 + __func__, names[i], ret); 1362 + goto free_regulators; 1363 + } 1364 + 1365 + opp_table->regulators[i] = reg; 1366 + } 1367 + 1368 + opp_table->regulator_count = count; 1427 1369 1428 1370 mutex_unlock(&opp_table_lock); 1429 1371 return opp_table; 1430 1372 1373 + free_regulators: 1374 + while (i != 0) 1375 + regulator_put(opp_table->regulators[--i]); 1376 + 1377 + kfree(opp_table->regulators); 1378 + opp_table->regulators = NULL; 1431 1379 err: 1432 1380 _remove_opp_table(opp_table); 1433 1381 unlock: ··· 1453 1365 1454 1366 return ERR_PTR(ret); 1455 1367 } 1456 - EXPORT_SYMBOL_GPL(dev_pm_opp_set_regulator); 1368 + EXPORT_SYMBOL_GPL(dev_pm_opp_set_regulators); 1457 1369 1458 1370 /** 1459 - * dev_pm_opp_put_regulator() - Releases resources blocked for regulator 1460 - * @opp_table: OPP table returned from dev_pm_opp_set_regulator(). 1371 + * dev_pm_opp_put_regulators() - Releases resources blocked for regulator 1372 + * @opp_table: OPP table returned from dev_pm_opp_set_regulators(). 1461 1373 * 1462 1374 * Locking: The internal opp_table and opp structures are RCU protected. 1463 1375 * Hence this function internally uses RCU updater strategy with mutex locks ··· 1465 1377 * that this function is *NOT* called under RCU protection or in contexts where 1466 1378 * mutex cannot be locked. 1467 1379 */ 1468 - void dev_pm_opp_put_regulator(struct opp_table *opp_table) 1380 + void dev_pm_opp_put_regulators(struct opp_table *opp_table) 1469 1381 { 1382 + int i; 1383 + 1470 1384 mutex_lock(&opp_table_lock); 1471 1385 1472 - if (IS_ERR(opp_table->regulator)) { 1473 - pr_err("%s: Doesn't have regulator set\n", __func__); 1386 + if (!opp_table->regulators) { 1387 + pr_err("%s: Doesn't have regulators set\n", __func__); 1474 1388 goto unlock; 1475 1389 } 1476 1390 1477 1391 /* Make sure there are no concurrent readers while updating opp_table */ 1478 1392 WARN_ON(!list_empty(&opp_table->opp_list)); 1479 1393 1480 - regulator_put(opp_table->regulator); 1481 - opp_table->regulator = ERR_PTR(-ENXIO); 1394 + for (i = opp_table->regulator_count - 1; i >= 0; i--) 1395 + regulator_put(opp_table->regulators[i]); 1396 + 1397 + kfree(opp_table->regulators); 1398 + opp_table->regulators = NULL; 1399 + opp_table->regulator_count = 0; 1482 1400 1483 1401 /* Try freeing opp_table if this was the last blocking resource */ 1484 1402 _remove_opp_table(opp_table); ··· 1492 1398 unlock: 1493 1399 mutex_unlock(&opp_table_lock); 1494 1400 } 1495 - EXPORT_SYMBOL_GPL(dev_pm_opp_put_regulator); 1401 + EXPORT_SYMBOL_GPL(dev_pm_opp_put_regulators); 1496 1402 1497 1403 /** 1498 1404 * dev_pm_opp_add() - Add an OPP table from a table definitions
+42 -10
drivers/base/power/opp/debugfs.c
··· 15 15 #include <linux/err.h> 16 16 #include <linux/init.h> 17 17 #include <linux/limits.h> 18 + #include <linux/slab.h> 18 19 19 20 #include "opp.h" 20 21 ··· 33 32 void opp_debug_remove_one(struct dev_pm_opp *opp) 34 33 { 35 34 debugfs_remove_recursive(opp->dentry); 35 + } 36 + 37 + static bool opp_debug_create_supplies(struct dev_pm_opp *opp, 38 + struct opp_table *opp_table, 39 + struct dentry *pdentry) 40 + { 41 + struct dentry *d; 42 + int i = 0; 43 + char *name; 44 + 45 + /* Always create at least supply-0 directory */ 46 + do { 47 + name = kasprintf(GFP_KERNEL, "supply-%d", i); 48 + 49 + /* Create per-opp directory */ 50 + d = debugfs_create_dir(name, pdentry); 51 + 52 + kfree(name); 53 + 54 + if (!d) 55 + return false; 56 + 57 + if (!debugfs_create_ulong("u_volt_target", S_IRUGO, d, 58 + &opp->supplies[i].u_volt)) 59 + return false; 60 + 61 + if (!debugfs_create_ulong("u_volt_min", S_IRUGO, d, 62 + &opp->supplies[i].u_volt_min)) 63 + return false; 64 + 65 + if (!debugfs_create_ulong("u_volt_max", S_IRUGO, d, 66 + &opp->supplies[i].u_volt_max)) 67 + return false; 68 + 69 + if (!debugfs_create_ulong("u_amp", S_IRUGO, d, 70 + &opp->supplies[i].u_amp)) 71 + return false; 72 + } while (++i < opp_table->regulator_count); 73 + 74 + return true; 36 75 } 37 76 38 77 int opp_debug_create_one(struct dev_pm_opp *opp, struct opp_table *opp_table) ··· 104 63 if (!debugfs_create_ulong("rate_hz", S_IRUGO, d, &opp->rate)) 105 64 return -ENOMEM; 106 65 107 - if (!debugfs_create_ulong("u_volt_target", S_IRUGO, d, &opp->supply.u_volt)) 108 - return -ENOMEM; 109 - 110 - if (!debugfs_create_ulong("u_volt_min", S_IRUGO, d, &opp->supply.u_volt_min)) 111 - return -ENOMEM; 112 - 113 - if (!debugfs_create_ulong("u_volt_max", S_IRUGO, d, &opp->supply.u_volt_max)) 114 - return -ENOMEM; 115 - 116 - if (!debugfs_create_ulong("u_amp", S_IRUGO, d, &opp->supply.u_amp)) 66 + if (!opp_debug_create_supplies(opp, opp_table, d)) 117 67 return -ENOMEM; 118 68 119 69 if (!debugfs_create_ulong("clock_latency_ns", S_IRUGO, d,
+74 -29
drivers/base/power/opp/of.c
··· 17 17 #include <linux/errno.h> 18 18 #include <linux/device.h> 19 19 #include <linux/of.h> 20 + #include <linux/slab.h> 20 21 #include <linux/export.h> 21 22 22 23 #include "opp.h" ··· 102 101 return true; 103 102 } 104 103 105 - /* TODO: Support multiple regulators */ 106 104 static int opp_parse_supplies(struct dev_pm_opp *opp, struct device *dev, 107 105 struct opp_table *opp_table) 108 106 { 109 - u32 microvolt[3] = {0}; 110 - u32 val; 111 - int count, ret; 107 + u32 *microvolt, *microamp = NULL; 108 + int supplies, vcount, icount, ret, i, j; 112 109 struct property *prop = NULL; 113 110 char name[NAME_MAX]; 111 + 112 + supplies = opp_table->regulator_count ? opp_table->regulator_count : 1; 114 113 115 114 /* Search for "opp-microvolt-<name>" */ 116 115 if (opp_table->prop_name) { ··· 129 128 return 0; 130 129 } 131 130 132 - count = of_property_count_u32_elems(opp->np, name); 133 - if (count < 0) { 131 + vcount = of_property_count_u32_elems(opp->np, name); 132 + if (vcount < 0) { 134 133 dev_err(dev, "%s: Invalid %s property (%d)\n", 135 - __func__, name, count); 136 - return count; 134 + __func__, name, vcount); 135 + return vcount; 137 136 } 138 137 139 - /* There can be one or three elements here */ 140 - if (count != 1 && count != 3) { 141 - dev_err(dev, "%s: Invalid number of elements in %s property (%d)\n", 142 - __func__, name, count); 138 + /* There can be one or three elements per supply */ 139 + if (vcount != supplies && vcount != supplies * 3) { 140 + dev_err(dev, "%s: Invalid number of elements in %s property (%d) with supplies (%d)\n", 141 + __func__, name, vcount, supplies); 143 142 return -EINVAL; 144 143 } 145 144 146 - ret = of_property_read_u32_array(opp->np, name, microvolt, count); 145 + microvolt = kmalloc_array(vcount, sizeof(*microvolt), GFP_KERNEL); 146 + if (!microvolt) 147 + return -ENOMEM; 148 + 149 + ret = of_property_read_u32_array(opp->np, name, microvolt, vcount); 147 150 if (ret) { 148 151 dev_err(dev, "%s: error parsing %s: %d\n", __func__, name, ret); 149 - return -EINVAL; 150 - } 151 - 152 - opp->supply.u_volt = microvolt[0]; 153 - 154 - if (count == 1) { 155 - opp->supply.u_volt_min = opp->supply.u_volt; 156 - opp->supply.u_volt_max = opp->supply.u_volt; 157 - } else { 158 - opp->supply.u_volt_min = microvolt[1]; 159 - opp->supply.u_volt_max = microvolt[2]; 152 + ret = -EINVAL; 153 + goto free_microvolt; 160 154 } 161 155 162 156 /* Search for "opp-microamp-<name>" */ ··· 168 172 prop = of_find_property(opp->np, name, NULL); 169 173 } 170 174 171 - if (prop && !of_property_read_u32(opp->np, name, &val)) 172 - opp->supply.u_amp = val; 175 + if (prop) { 176 + icount = of_property_count_u32_elems(opp->np, name); 177 + if (icount < 0) { 178 + dev_err(dev, "%s: Invalid %s property (%d)\n", __func__, 179 + name, icount); 180 + ret = icount; 181 + goto free_microvolt; 182 + } 173 183 174 - return 0; 184 + if (icount != supplies) { 185 + dev_err(dev, "%s: Invalid number of elements in %s property (%d) with supplies (%d)\n", 186 + __func__, name, icount, supplies); 187 + ret = -EINVAL; 188 + goto free_microvolt; 189 + } 190 + 191 + microamp = kmalloc_array(icount, sizeof(*microamp), GFP_KERNEL); 192 + if (!microamp) { 193 + ret = -EINVAL; 194 + goto free_microvolt; 195 + } 196 + 197 + ret = of_property_read_u32_array(opp->np, name, microamp, 198 + icount); 199 + if (ret) { 200 + dev_err(dev, "%s: error parsing %s: %d\n", __func__, 201 + name, ret); 202 + ret = -EINVAL; 203 + goto free_microamp; 204 + } 205 + } 206 + 207 + for (i = 0, j = 0; i < supplies; i++) { 208 + opp->supplies[i].u_volt = microvolt[j++]; 209 + 210 + if (vcount == supplies) { 211 + opp->supplies[i].u_volt_min = opp->supplies[i].u_volt; 212 + opp->supplies[i].u_volt_max = opp->supplies[i].u_volt; 213 + } else { 214 + opp->supplies[i].u_volt_min = microvolt[j++]; 215 + opp->supplies[i].u_volt_max = microvolt[j++]; 216 + } 217 + 218 + if (microamp) 219 + opp->supplies[i].u_amp = microamp[i]; 220 + } 221 + 222 + free_microamp: 223 + kfree(microamp); 224 + free_microvolt: 225 + kfree(microvolt); 226 + 227 + return ret; 175 228 } 176 229 177 230 /** ··· 349 304 350 305 pr_debug("%s: turbo:%d rate:%lu uv:%lu uvmin:%lu uvmax:%lu latency:%lu\n", 351 306 __func__, new_opp->turbo, new_opp->rate, 352 - new_opp->supply.u_volt, new_opp->supply.u_volt_min, 353 - new_opp->supply.u_volt_max, new_opp->clock_latency_ns); 307 + new_opp->supplies[0].u_volt, new_opp->supplies[0].u_volt_min, 308 + new_opp->supplies[0].u_volt_max, new_opp->clock_latency_ns); 354 309 355 310 /* 356 311 * Notify the changes in the availability of the operable
+6 -4
drivers/base/power/opp/opp.h
··· 61 61 * @turbo: true if turbo (boost) OPP 62 62 * @suspend: true if suspend OPP 63 63 * @rate: Frequency in hertz 64 - * @supply: Power supply voltage/current values 64 + * @supplies: Power supplies voltage/current values 65 65 * @clock_latency_ns: Latency (in nanoseconds) of switching to this OPP's 66 66 * frequency from any other OPP's frequency. 67 67 * @opp_table: points back to the opp_table struct this opp belongs to ··· 80 80 bool suspend; 81 81 unsigned long rate; 82 82 83 - struct dev_pm_opp_supply supply; 83 + struct dev_pm_opp_supply *supplies; 84 84 85 85 unsigned long clock_latency_ns; 86 86 ··· 139 139 * @supported_hw_count: Number of elements in supported_hw array. 140 140 * @prop_name: A name to postfix to many DT properties, while parsing them. 141 141 * @clk: Device's clock handle 142 - * @regulator: Supply regulator 142 + * @regulators: Supply regulators 143 + * @regulator_count: Number of power supply regulators 143 144 * @dentry: debugfs dentry pointer of the real device directory (not links). 144 145 * @dentry_name: Name of the real dentry. 145 146 * ··· 175 174 unsigned int supported_hw_count; 176 175 const char *prop_name; 177 176 struct clk *clk; 178 - struct regulator *regulator; 177 + struct regulator **regulators; 178 + unsigned int regulator_count; 179 179 180 180 #ifdef CONFIG_DEBUG_FS 181 181 struct dentry *dentry;
+3 -3
drivers/cpufreq/cpufreq-dt.c
··· 188 188 */ 189 189 name = find_supply_name(cpu_dev); 190 190 if (name) { 191 - opp_table = dev_pm_opp_set_regulator(cpu_dev, name); 191 + opp_table = dev_pm_opp_set_regulators(cpu_dev, &name, 1); 192 192 if (IS_ERR(opp_table)) { 193 193 ret = PTR_ERR(opp_table); 194 194 dev_err(cpu_dev, "Failed to set regulator for cpu%d: %d\n", ··· 289 289 out_free_opp: 290 290 dev_pm_opp_of_cpumask_remove_table(policy->cpus); 291 291 if (name) 292 - dev_pm_opp_put_regulator(opp_table); 292 + dev_pm_opp_put_regulators(opp_table); 293 293 out_put_clk: 294 294 clk_put(cpu_clk); 295 295 ··· 304 304 dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &policy->freq_table); 305 305 dev_pm_opp_of_cpumask_remove_table(policy->related_cpus); 306 306 if (priv->reg_name) 307 - dev_pm_opp_put_regulator(priv->opp_table); 307 + dev_pm_opp_put_regulators(priv->opp_table); 308 308 309 309 clk_put(policy->clk); 310 310 kfree(priv);
+4 -4
include/linux/pm_opp.h
··· 79 79 void dev_pm_opp_put_supported_hw(struct device *dev); 80 80 int dev_pm_opp_set_prop_name(struct device *dev, const char *name); 81 81 void dev_pm_opp_put_prop_name(struct device *dev); 82 - struct opp_table *dev_pm_opp_set_regulator(struct device *dev, const char *name); 83 - void dev_pm_opp_put_regulator(struct opp_table *opp_table); 82 + struct opp_table *dev_pm_opp_set_regulators(struct device *dev, const char * const names[], unsigned int count); 83 + void dev_pm_opp_put_regulators(struct opp_table *opp_table); 84 84 int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq); 85 85 int dev_pm_opp_set_sharing_cpus(struct device *cpu_dev, const struct cpumask *cpumask); 86 86 int dev_pm_opp_get_sharing_cpus(struct device *cpu_dev, struct cpumask *cpumask); ··· 187 187 188 188 static inline void dev_pm_opp_put_prop_name(struct device *dev) {} 189 189 190 - static inline struct opp_table *dev_pm_opp_set_regulator(struct device *dev, const char *name) 190 + static inline struct opp_table *dev_pm_opp_set_regulators(struct device *dev, const char * const names[], unsigned int count) 191 191 { 192 192 return ERR_PTR(-ENOTSUPP); 193 193 } 194 194 195 - static inline void dev_pm_opp_put_regulator(struct opp_table *opp_table) {} 195 + static inline void dev_pm_opp_put_regulators(struct opp_table *opp_table) {} 196 196 197 197 static inline int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq) 198 198 {