diff options
author | Ionela Voinescu <ionela.voinescu@arm.com> | 2018-06-12 18:55:41 +0100 |
---|---|---|
committer | Arvind Chauhan <arvcha01@a075555-lin.blr.arm.com> | 2018-07-14 15:32:29 +0530 |
commit | d4c7d1c81b043f3b60b6a7df8a581e81d57e170e (patch) | |
tree | 3ed324fe98e7af9123aeca976f0487484d1484af | |
parent | 78e8dbbfb6ed794443370b142b37423fd5012e56 (diff) |
thermal/devfreq_cooling: obtain power value from OPP coreack-4.9-armlt-20180817ack-4.9-armlt-18.07
Rely on dev_pm_opp_get_power() to provide power values for each OPP if
no custom function is provided to obtain dynamic power.
If a custom node exists for the power model of the device which contains
the dynamic_power_coefficient, a custom function needs to be provided to
compute the dynamic power based on this coefficient.
Change-Id: I6f7f4e16d20db2e00ee3601df238eb9aa2e48071
Signed-off-by: Ionela Voinescu <ionela.voinescu@arm.com>
-rw-r--r-- | drivers/thermal/devfreq_cooling.c | 58 |
1 files changed, 38 insertions, 20 deletions
diff --git a/drivers/thermal/devfreq_cooling.c b/drivers/thermal/devfreq_cooling.c index 81631b110e17..2ee8613c8adf 100644 --- a/drivers/thermal/devfreq_cooling.c +++ b/drivers/thermal/devfreq_cooling.c @@ -246,6 +246,7 @@ get_static_power(struct devfreq_cooling_device *dfc, unsigned long freq) * @dfc: Pointer to devfreq cooling device * @freq: Frequency in Hz * @voltage: Voltage in millivolts + * @opp_power: Power in miliwatts * * Calculate the dynamic power in milliwatts consumed by the device at * frequency @freq and voltage @voltage. If the get_dynamic_power() @@ -255,18 +256,19 @@ get_static_power(struct devfreq_cooling_device *dfc, unsigned long freq) */ static unsigned long get_dynamic_power(struct devfreq_cooling_device *dfc, unsigned long freq, - unsigned long voltage) + unsigned long voltage, unsigned long opp_power) { - u64 power; - u32 freq_mhz; - struct devfreq_cooling_power *dfc_power = dfc->power_ops; + unsigned long power = 0; - if (dfc_power->get_dynamic_power) - return dfc_power->get_dynamic_power(freq, voltage); + if (dfc->power_ops->get_dynamic_power) + power = dfc->power_ops->get_dynamic_power(freq, voltage); - freq_mhz = freq / 1000000; - power = (u64)dfc_power->dyn_power_coeff * freq_mhz * voltage * voltage; - do_div(power, 1000000000); + /* + * Voltage information might be 0. In this case, rely on the OPP + * framework to provide power values, if it can. + */ + if (!power) + power = opp_power; return power; } @@ -390,6 +392,7 @@ static int devfreq_cooling_gen_tables(struct devfreq_cooling_device *dfc) u32 *power_table = NULL; u32 *freq_table; int i; + bool found_power = true; num_opps = dev_pm_opp_get_opp_count(dev); @@ -408,7 +411,7 @@ static int devfreq_cooling_gen_tables(struct devfreq_cooling_device *dfc) } for (i = 0, freq = ULONG_MAX; i < num_opps; i++, freq--) { - unsigned long power_dyn, voltage; + unsigned long power_dyn, voltage, opp_power; struct dev_pm_opp *opp; rcu_read_lock(); @@ -421,27 +424,38 @@ static int devfreq_cooling_gen_tables(struct devfreq_cooling_device *dfc) } voltage = dev_pm_opp_get_voltage(opp) / 1000; /* mV */ + opp_power = dev_pm_opp_get_power(opp) / 1000; /* mV */ rcu_read_unlock(); if (dfc->power_ops) { - power_dyn = get_dynamic_power(dfc, freq, voltage); + power_dyn = get_dynamic_power(dfc, freq, voltage, opp_power); dev_dbg(dev, "Dynamic power table: %lu MHz @ %lu mV: %lu = %lu mW\n", freq / 1000000, voltage, power_dyn, power_dyn); power_table[i] = power_dyn; + + if (!power_dyn) + found_power = false; } freq_table[i] = freq; } - if (dfc->power_ops) - dfc->power_table = power_table; - dfc->freq_table = freq_table; dfc->freq_table_size = num_opps; + if (dfc->power_ops) { + if (found_power) + dfc->power_table = power_table; + else { + dev_err(dev, "The Dynamic power model contains power values set to 0!\n"); + ret = -ENODATA; + goto free_power_table; + } + } + return 0; free_tables: @@ -482,19 +496,23 @@ of_devfreq_cooling_register_power(struct device_node *np, struct devfreq *df, dfc->devfreq = df; - if (dfc_power) { - dfc->power_ops = dfc_power; + dfc->power_ops = dfc_power; + err = devfreq_cooling_gen_tables(dfc); + if (err) { + if (-ENODATA == err) + /* Invalidate power ops */ + dfc->power_ops = NULL; + else + goto free_dfc; + } + if (dfc->power_ops) { devfreq_cooling_ops.get_requested_power = devfreq_cooling_get_requested_power; devfreq_cooling_ops.state2power = devfreq_cooling_state2power; devfreq_cooling_ops.power2state = devfreq_cooling_power2state; } - err = devfreq_cooling_gen_tables(dfc); - if (err) - goto free_dfc; - err = get_idr(&devfreq_idr, &dfc->id); if (err) goto free_tables; |