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

opp: Allow opp-supported-hw to contain multiple versions

The bindings allow multiple versions to be passed to "opp-supported-hw"
property, either of which can result in enabling of the OPP.

Update code to allow that.

Tested-by: Stephan Gerhold <stephan@gerhold.net>
Tested-by: Dmitry Osipenko <digetx@gmail.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>

+35 -16
+35 -16
drivers/opp/of.c
··· 434 434 static bool _opp_is_supported(struct device *dev, struct opp_table *opp_table, 435 435 struct device_node *np) 436 436 { 437 - unsigned int count = opp_table->supported_hw_count; 438 - u32 version; 439 - int ret; 437 + unsigned int levels = opp_table->supported_hw_count; 438 + int count, versions, ret, i, j; 439 + u32 val; 440 440 441 441 if (!opp_table->supported_hw) { 442 442 /* ··· 451 451 return true; 452 452 } 453 453 454 - while (count--) { 455 - ret = of_property_read_u32_index(np, "opp-supported-hw", count, 456 - &version); 457 - if (ret) { 458 - dev_warn(dev, "%s: failed to read opp-supported-hw property at index %d: %d\n", 459 - __func__, count, ret); 460 - return false; 461 - } 462 - 463 - /* Both of these are bitwise masks of the versions */ 464 - if (!(version & opp_table->supported_hw[count])) 465 - return false; 454 + count = of_property_count_u32_elems(np, "opp-supported-hw"); 455 + if (count <= 0 || count % levels) { 456 + dev_err(dev, "%s: Invalid opp-supported-hw property (%d)\n", 457 + __func__, count); 458 + return false; 466 459 } 467 460 468 - return true; 461 + versions = count / levels; 462 + 463 + /* All levels in at least one of the versions should match */ 464 + for (i = 0; i < versions; i++) { 465 + bool supported = true; 466 + 467 + for (j = 0; j < levels; j++) { 468 + ret = of_property_read_u32_index(np, "opp-supported-hw", 469 + i * levels + j, &val); 470 + if (ret) { 471 + dev_warn(dev, "%s: failed to read opp-supported-hw property at index %d: %d\n", 472 + __func__, i * levels + j, ret); 473 + return false; 474 + } 475 + 476 + /* Check if the level is supported */ 477 + if (!(val & opp_table->supported_hw[j])) { 478 + supported = false; 479 + break; 480 + } 481 + } 482 + 483 + if (supported) 484 + return true; 485 + } 486 + 487 + return false; 469 488 } 470 489 471 490 static int opp_parse_supplies(struct dev_pm_opp *opp, struct device *dev,