mirror of
https://github.com/torvalds/linux.git
synced 2024-12-29 06:12:08 +00:00
Merge branch 'pm-cpufreq-thermal' into pm-cpufreq
* pm-cpufreq-thermal: cpu_cooling: Remove static-power related documentation cpu_cooling: Drop static-power related stuff cpu_cooling: Keep only one of_cpufreq*cooling_register() helper cpu_cooling: Remove unused cpufreq_power_cooling_register() cpu_cooling: Make of_cpufreq_power_cooling_register() parse DT
This commit is contained in:
commit
f06970f4b0
@ -26,39 +26,16 @@ the user. The registration APIs returns the cooling device pointer.
|
||||
clip_cpus: cpumask of cpus where the frequency constraints will happen.
|
||||
|
||||
1.1.2 struct thermal_cooling_device *of_cpufreq_cooling_register(
|
||||
struct device_node *np, const struct cpumask *clip_cpus)
|
||||
struct cpufreq_policy *policy)
|
||||
|
||||
This interface function registers the cpufreq cooling device with
|
||||
the name "thermal-cpufreq-%x" linking it with a device tree node, in
|
||||
order to bind it via the thermal DT code. This api can support multiple
|
||||
instances of cpufreq cooling devices.
|
||||
|
||||
np: pointer to the cooling device device tree node
|
||||
clip_cpus: cpumask of cpus where the frequency constraints will happen.
|
||||
policy: CPUFreq policy.
|
||||
|
||||
1.1.3 struct thermal_cooling_device *cpufreq_power_cooling_register(
|
||||
const struct cpumask *clip_cpus, u32 capacitance,
|
||||
get_static_t plat_static_func)
|
||||
|
||||
Similar to cpufreq_cooling_register, this function registers a cpufreq
|
||||
cooling device. Using this function, the cooling device will
|
||||
implement the power extensions by using a simple cpu power model. The
|
||||
cpus must have registered their OPPs using the OPP library.
|
||||
|
||||
The additional parameters are needed for the power model (See 2. Power
|
||||
models). "capacitance" is the dynamic power coefficient (See 2.1
|
||||
Dynamic power). "plat_static_func" is a function to calculate the
|
||||
static power consumed by these cpus (See 2.2 Static power).
|
||||
|
||||
1.1.4 struct thermal_cooling_device *of_cpufreq_power_cooling_register(
|
||||
struct device_node *np, const struct cpumask *clip_cpus, u32 capacitance,
|
||||
get_static_t plat_static_func)
|
||||
|
||||
Similar to cpufreq_power_cooling_register, this function register a
|
||||
cpufreq cooling device with power extensions using the device tree
|
||||
information supplied by the np parameter.
|
||||
|
||||
1.1.5 void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev)
|
||||
1.1.3 void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev)
|
||||
|
||||
This interface function unregisters the "thermal-cpufreq-%x" cooling device.
|
||||
|
||||
@ -67,20 +44,14 @@ information supplied by the np parameter.
|
||||
2. Power models
|
||||
|
||||
The power API registration functions provide a simple power model for
|
||||
CPUs. The current power is calculated as dynamic + (optionally)
|
||||
static power. This power model requires that the operating-points of
|
||||
CPUs. The current power is calculated as dynamic power (static power isn't
|
||||
supported currently). This power model requires that the operating-points of
|
||||
the CPUs are registered using the kernel's opp library and the
|
||||
`cpufreq_frequency_table` is assigned to the `struct device` of the
|
||||
cpu. If you are using CONFIG_CPUFREQ_DT then the
|
||||
`cpufreq_frequency_table` should already be assigned to the cpu
|
||||
device.
|
||||
|
||||
The `plat_static_func` parameter of `cpufreq_power_cooling_register()`
|
||||
and `of_cpufreq_power_cooling_register()` is optional. If you don't
|
||||
provide it, only dynamic power will be considered.
|
||||
|
||||
2.1 Dynamic power
|
||||
|
||||
The dynamic power consumption of a processor depends on many factors.
|
||||
For a given processor implementation the primary factors are:
|
||||
|
||||
@ -119,79 +90,3 @@ mW/MHz/uVolt^2. Typical values for mobile CPUs might lie in range
|
||||
from 100 to 500. For reference, the approximate values for the SoC in
|
||||
ARM's Juno Development Platform are 530 for the Cortex-A57 cluster and
|
||||
140 for the Cortex-A53 cluster.
|
||||
|
||||
|
||||
2.2 Static power
|
||||
|
||||
Static leakage power consumption depends on a number of factors. For a
|
||||
given circuit implementation the primary factors are:
|
||||
|
||||
- Time the circuit spends in each 'power state'
|
||||
- Temperature
|
||||
- Operating voltage
|
||||
- Process grade
|
||||
|
||||
The time the circuit spends in each 'power state' for a given
|
||||
evaluation period at first order means OFF or ON. However,
|
||||
'retention' states can also be supported that reduce power during
|
||||
inactive periods without loss of context.
|
||||
|
||||
Note: The visibility of state entries to the OS can vary, according to
|
||||
platform specifics, and this can then impact the accuracy of a model
|
||||
based on OS state information alone. It might be possible in some
|
||||
cases to extract more accurate information from system resources.
|
||||
|
||||
The temperature, operating voltage and process 'grade' (slow to fast)
|
||||
of the circuit are all significant factors in static leakage power
|
||||
consumption. All of these have complex relationships to static power.
|
||||
|
||||
Circuit implementation specific factors include the chosen silicon
|
||||
process as well as the type, number and size of transistors in both
|
||||
the logic gates and any RAM elements included.
|
||||
|
||||
The static power consumption modelling must take into account the
|
||||
power managed regions that are implemented. Taking the example of an
|
||||
ARM processor cluster, the modelling would take into account whether
|
||||
each CPU can be powered OFF separately or if only a single power
|
||||
region is implemented for the complete cluster.
|
||||
|
||||
In one view, there are others, a static power consumption model can
|
||||
then start from a set of reference values for each power managed
|
||||
region (e.g. CPU, Cluster/L2) in each state (e.g. ON, OFF) at an
|
||||
arbitrary process grade, voltage and temperature point. These values
|
||||
are then scaled for all of the following: the time in each state, the
|
||||
process grade, the current temperature and the operating voltage.
|
||||
However, since both implementation specific and complex relationships
|
||||
dominate the estimate, the appropriate interface to the model from the
|
||||
cpu cooling device is to provide a function callback that calculates
|
||||
the static power in this platform. When registering the cpu cooling
|
||||
device pass a function pointer that follows the `get_static_t`
|
||||
prototype:
|
||||
|
||||
int plat_get_static(cpumask_t *cpumask, int interval,
|
||||
unsigned long voltage, u32 &power);
|
||||
|
||||
`cpumask` is the cpumask of the cpus involved in the calculation.
|
||||
`voltage` is the voltage at which they are operating. The function
|
||||
should calculate the average static power for the last `interval`
|
||||
milliseconds. It returns 0 on success, -E* on error. If it
|
||||
succeeds, it should store the static power in `power`. Reading the
|
||||
temperature of the cpus described by `cpumask` is left for
|
||||
plat_get_static() to do as the platform knows best which thermal
|
||||
sensor is closest to the cpu.
|
||||
|
||||
If `plat_static_func` is NULL, static power is considered to be
|
||||
negligible for this platform and only dynamic power is considered.
|
||||
|
||||
The platform specific callback can then use any combination of tables
|
||||
and/or equations to permute the estimated value. Process grade
|
||||
information is not passed to the model since access to such data, from
|
||||
on-chip measurement capability or manufacture time data, is platform
|
||||
specific.
|
||||
|
||||
Note: the significance of static power for CPUs in comparison to
|
||||
dynamic power is highly dependent on implementation. Given the
|
||||
potential complexity in implementation, the importance and accuracy of
|
||||
its inclusion when using cpu cooling devices should be assessed on a
|
||||
case by case basis.
|
||||
|
||||
|
@ -526,34 +526,13 @@ static int bL_cpufreq_exit(struct cpufreq_policy *policy)
|
||||
|
||||
static void bL_cpufreq_ready(struct cpufreq_policy *policy)
|
||||
{
|
||||
struct device *cpu_dev = get_cpu_device(policy->cpu);
|
||||
int cur_cluster = cpu_to_cluster(policy->cpu);
|
||||
struct device_node *np;
|
||||
|
||||
/* Do not register a cpu_cooling device if we are in IKS mode */
|
||||
if (cur_cluster >= MAX_CLUSTERS)
|
||||
return;
|
||||
|
||||
np = of_node_get(cpu_dev->of_node);
|
||||
if (WARN_ON(!np))
|
||||
return;
|
||||
|
||||
if (of_find_property(np, "#cooling-cells", NULL)) {
|
||||
u32 power_coefficient = 0;
|
||||
|
||||
of_property_read_u32(np, "dynamic-power-coefficient",
|
||||
&power_coefficient);
|
||||
|
||||
cdev[cur_cluster] = of_cpufreq_power_cooling_register(np,
|
||||
policy, power_coefficient, NULL);
|
||||
if (IS_ERR(cdev[cur_cluster])) {
|
||||
dev_err(cpu_dev,
|
||||
"running cpufreq without cooling device: %ld\n",
|
||||
PTR_ERR(cdev[cur_cluster]));
|
||||
cdev[cur_cluster] = NULL;
|
||||
}
|
||||
}
|
||||
of_node_put(np);
|
||||
cdev[cur_cluster] = of_cpufreq_cooling_register(policy);
|
||||
}
|
||||
|
||||
static struct cpufreq_driver bL_cpufreq_driver = {
|
||||
|
@ -319,33 +319,8 @@ static int cpufreq_exit(struct cpufreq_policy *policy)
|
||||
static void cpufreq_ready(struct cpufreq_policy *policy)
|
||||
{
|
||||
struct private_data *priv = policy->driver_data;
|
||||
struct device_node *np = of_node_get(priv->cpu_dev->of_node);
|
||||
|
||||
if (WARN_ON(!np))
|
||||
return;
|
||||
|
||||
/*
|
||||
* For now, just loading the cooling device;
|
||||
* thermal DT code takes care of matching them.
|
||||
*/
|
||||
if (of_find_property(np, "#cooling-cells", NULL)) {
|
||||
u32 power_coefficient = 0;
|
||||
|
||||
of_property_read_u32(np, "dynamic-power-coefficient",
|
||||
&power_coefficient);
|
||||
|
||||
priv->cdev = of_cpufreq_power_cooling_register(np,
|
||||
policy, power_coefficient, NULL);
|
||||
if (IS_ERR(priv->cdev)) {
|
||||
dev_err(priv->cpu_dev,
|
||||
"running cpufreq without cooling device: %ld\n",
|
||||
PTR_ERR(priv->cdev));
|
||||
|
||||
priv->cdev = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
of_node_put(np);
|
||||
priv->cdev = of_cpufreq_cooling_register(policy);
|
||||
}
|
||||
|
||||
static struct cpufreq_driver dt_cpufreq_driver = {
|
||||
|
@ -310,28 +310,8 @@ static int mtk_cpufreq_set_target(struct cpufreq_policy *policy,
|
||||
static void mtk_cpufreq_ready(struct cpufreq_policy *policy)
|
||||
{
|
||||
struct mtk_cpu_dvfs_info *info = policy->driver_data;
|
||||
struct device_node *np = of_node_get(info->cpu_dev->of_node);
|
||||
u32 capacitance = 0;
|
||||
|
||||
if (WARN_ON(!np))
|
||||
return;
|
||||
|
||||
if (of_find_property(np, "#cooling-cells", NULL)) {
|
||||
of_property_read_u32(np, DYNAMIC_POWER, &capacitance);
|
||||
|
||||
info->cdev = of_cpufreq_power_cooling_register(np,
|
||||
policy, capacitance, NULL);
|
||||
|
||||
if (IS_ERR(info->cdev)) {
|
||||
dev_err(info->cpu_dev,
|
||||
"running cpufreq without cooling device: %ld\n",
|
||||
PTR_ERR(info->cdev));
|
||||
|
||||
info->cdev = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
of_node_put(np);
|
||||
info->cdev = of_cpufreq_cooling_register(policy);
|
||||
}
|
||||
|
||||
static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu)
|
||||
|
@ -275,20 +275,8 @@ static int qoriq_cpufreq_target(struct cpufreq_policy *policy,
|
||||
static void qoriq_cpufreq_ready(struct cpufreq_policy *policy)
|
||||
{
|
||||
struct cpu_data *cpud = policy->driver_data;
|
||||
struct device_node *np = of_get_cpu_node(policy->cpu, NULL);
|
||||
|
||||
if (of_find_property(np, "#cooling-cells", NULL)) {
|
||||
cpud->cdev = of_cpufreq_cooling_register(np, policy);
|
||||
|
||||
if (IS_ERR(cpud->cdev) && PTR_ERR(cpud->cdev) != -ENOSYS) {
|
||||
pr_err("cpu%d is not running as cooling device: %ld\n",
|
||||
policy->cpu, PTR_ERR(cpud->cdev));
|
||||
|
||||
cpud->cdev = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
of_node_put(np);
|
||||
cpud->cdev = of_cpufreq_cooling_register(policy);
|
||||
}
|
||||
|
||||
static struct cpufreq_driver qoriq_cpufreq_driver = {
|
||||
|
@ -88,7 +88,6 @@ struct time_in_idle {
|
||||
* @policy: cpufreq policy.
|
||||
* @node: list_head to link all cpufreq_cooling_device together.
|
||||
* @idle_time: idle time stats
|
||||
* @plat_get_static_power: callback to calculate the static power
|
||||
*
|
||||
* This structure is required for keeping information of each registered
|
||||
* cpufreq_cooling_device.
|
||||
@ -104,7 +103,6 @@ struct cpufreq_cooling_device {
|
||||
struct cpufreq_policy *policy;
|
||||
struct list_head node;
|
||||
struct time_in_idle *idle_time;
|
||||
get_static_t plat_get_static_power;
|
||||
};
|
||||
|
||||
static DEFINE_IDA(cpufreq_ida);
|
||||
@ -318,60 +316,6 @@ static u32 get_load(struct cpufreq_cooling_device *cpufreq_cdev, int cpu,
|
||||
return load;
|
||||
}
|
||||
|
||||
/**
|
||||
* get_static_power() - calculate the static power consumed by the cpus
|
||||
* @cpufreq_cdev: struct &cpufreq_cooling_device for this cpu cdev
|
||||
* @tz: thermal zone device in which we're operating
|
||||
* @freq: frequency in KHz
|
||||
* @power: pointer in which to store the calculated static power
|
||||
*
|
||||
* Calculate the static power consumed by the cpus described by
|
||||
* @cpu_actor running at frequency @freq. This function relies on a
|
||||
* platform specific function that should have been provided when the
|
||||
* actor was registered. If it wasn't, the static power is assumed to
|
||||
* be negligible. The calculated static power is stored in @power.
|
||||
*
|
||||
* Return: 0 on success, -E* on failure.
|
||||
*/
|
||||
static int get_static_power(struct cpufreq_cooling_device *cpufreq_cdev,
|
||||
struct thermal_zone_device *tz, unsigned long freq,
|
||||
u32 *power)
|
||||
{
|
||||
struct dev_pm_opp *opp;
|
||||
unsigned long voltage;
|
||||
struct cpufreq_policy *policy = cpufreq_cdev->policy;
|
||||
struct cpumask *cpumask = policy->related_cpus;
|
||||
unsigned long freq_hz = freq * 1000;
|
||||
struct device *dev;
|
||||
|
||||
if (!cpufreq_cdev->plat_get_static_power) {
|
||||
*power = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
dev = get_cpu_device(policy->cpu);
|
||||
WARN_ON(!dev);
|
||||
|
||||
opp = dev_pm_opp_find_freq_exact(dev, freq_hz, true);
|
||||
if (IS_ERR(opp)) {
|
||||
dev_warn_ratelimited(dev, "Failed to find OPP for frequency %lu: %ld\n",
|
||||
freq_hz, PTR_ERR(opp));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
voltage = dev_pm_opp_get_voltage(opp);
|
||||
dev_pm_opp_put(opp);
|
||||
|
||||
if (voltage == 0) {
|
||||
dev_err_ratelimited(dev, "Failed to get voltage for frequency %lu\n",
|
||||
freq_hz);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return cpufreq_cdev->plat_get_static_power(cpumask, tz->passive_delay,
|
||||
voltage, power);
|
||||
}
|
||||
|
||||
/**
|
||||
* get_dynamic_power() - calculate the dynamic power
|
||||
* @cpufreq_cdev: &cpufreq_cooling_device for this cdev
|
||||
@ -491,8 +435,8 @@ static int cpufreq_get_requested_power(struct thermal_cooling_device *cdev,
|
||||
u32 *power)
|
||||
{
|
||||
unsigned long freq;
|
||||
int i = 0, cpu, ret;
|
||||
u32 static_power, dynamic_power, total_load = 0;
|
||||
int i = 0, cpu;
|
||||
u32 total_load = 0;
|
||||
struct cpufreq_cooling_device *cpufreq_cdev = cdev->devdata;
|
||||
struct cpufreq_policy *policy = cpufreq_cdev->policy;
|
||||
u32 *load_cpu = NULL;
|
||||
@ -522,22 +466,15 @@ static int cpufreq_get_requested_power(struct thermal_cooling_device *cdev,
|
||||
|
||||
cpufreq_cdev->last_load = total_load;
|
||||
|
||||
dynamic_power = get_dynamic_power(cpufreq_cdev, freq);
|
||||
ret = get_static_power(cpufreq_cdev, tz, freq, &static_power);
|
||||
if (ret) {
|
||||
kfree(load_cpu);
|
||||
return ret;
|
||||
}
|
||||
*power = get_dynamic_power(cpufreq_cdev, freq);
|
||||
|
||||
if (load_cpu) {
|
||||
trace_thermal_power_cpu_get_power(policy->related_cpus, freq,
|
||||
load_cpu, i, dynamic_power,
|
||||
static_power);
|
||||
load_cpu, i, *power);
|
||||
|
||||
kfree(load_cpu);
|
||||
}
|
||||
|
||||
*power = static_power + dynamic_power;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -561,8 +498,6 @@ static int cpufreq_state2power(struct thermal_cooling_device *cdev,
|
||||
unsigned long state, u32 *power)
|
||||
{
|
||||
unsigned int freq, num_cpus;
|
||||
u32 static_power, dynamic_power;
|
||||
int ret;
|
||||
struct cpufreq_cooling_device *cpufreq_cdev = cdev->devdata;
|
||||
|
||||
/* Request state should be less than max_level */
|
||||
@ -572,13 +507,9 @@ static int cpufreq_state2power(struct thermal_cooling_device *cdev,
|
||||
num_cpus = cpumask_weight(cpufreq_cdev->policy->cpus);
|
||||
|
||||
freq = cpufreq_cdev->freq_table[state].frequency;
|
||||
dynamic_power = cpu_freq_to_power(cpufreq_cdev, freq) * num_cpus;
|
||||
ret = get_static_power(cpufreq_cdev, tz, freq, &static_power);
|
||||
if (ret)
|
||||
return ret;
|
||||
*power = cpu_freq_to_power(cpufreq_cdev, freq) * num_cpus;
|
||||
|
||||
*power = static_power + dynamic_power;
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -606,21 +537,14 @@ static int cpufreq_power2state(struct thermal_cooling_device *cdev,
|
||||
unsigned long *state)
|
||||
{
|
||||
unsigned int cur_freq, target_freq;
|
||||
int ret;
|
||||
s32 dyn_power;
|
||||
u32 last_load, normalised_power, static_power;
|
||||
u32 last_load, normalised_power;
|
||||
struct cpufreq_cooling_device *cpufreq_cdev = cdev->devdata;
|
||||
struct cpufreq_policy *policy = cpufreq_cdev->policy;
|
||||
|
||||
cur_freq = cpufreq_quick_get(policy->cpu);
|
||||
ret = get_static_power(cpufreq_cdev, tz, cur_freq, &static_power);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
dyn_power = power - static_power;
|
||||
dyn_power = dyn_power > 0 ? dyn_power : 0;
|
||||
power = power > 0 ? power : 0;
|
||||
last_load = cpufreq_cdev->last_load ?: 1;
|
||||
normalised_power = (dyn_power * 100) / last_load;
|
||||
normalised_power = (power * 100) / last_load;
|
||||
target_freq = cpu_power_to_freq(cpufreq_cdev, normalised_power);
|
||||
|
||||
*state = get_level(cpufreq_cdev, target_freq);
|
||||
@ -671,8 +595,6 @@ static unsigned int find_next_max(struct cpufreq_frequency_table *table,
|
||||
* @policy: cpufreq policy
|
||||
* Normally this should be same as cpufreq policy->related_cpus.
|
||||
* @capacitance: dynamic power coefficient for these cpus
|
||||
* @plat_static_func: function to calculate the static power consumed by these
|
||||
* cpus (optional)
|
||||
*
|
||||
* This interface function registers the cpufreq cooling device with the name
|
||||
* "thermal-cpufreq-%x". This api can support multiple instances of cpufreq
|
||||
@ -684,8 +606,7 @@ static unsigned int find_next_max(struct cpufreq_frequency_table *table,
|
||||
*/
|
||||
static struct thermal_cooling_device *
|
||||
__cpufreq_cooling_register(struct device_node *np,
|
||||
struct cpufreq_policy *policy, u32 capacitance,
|
||||
get_static_t plat_static_func)
|
||||
struct cpufreq_policy *policy, u32 capacitance)
|
||||
{
|
||||
struct thermal_cooling_device *cdev;
|
||||
struct cpufreq_cooling_device *cpufreq_cdev;
|
||||
@ -755,8 +676,6 @@ __cpufreq_cooling_register(struct device_node *np,
|
||||
}
|
||||
|
||||
if (capacitance) {
|
||||
cpufreq_cdev->plat_get_static_power = plat_static_func;
|
||||
|
||||
ret = update_freq_table(cpufreq_cdev, capacitance);
|
||||
if (ret) {
|
||||
cdev = ERR_PTR(ret);
|
||||
@ -813,13 +732,12 @@ free_cdev:
|
||||
struct thermal_cooling_device *
|
||||
cpufreq_cooling_register(struct cpufreq_policy *policy)
|
||||
{
|
||||
return __cpufreq_cooling_register(NULL, policy, 0, NULL);
|
||||
return __cpufreq_cooling_register(NULL, policy, 0);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cpufreq_cooling_register);
|
||||
|
||||
/**
|
||||
* of_cpufreq_cooling_register - function to create cpufreq cooling device.
|
||||
* @np: a valid struct device_node to the cooling device device tree node
|
||||
* @policy: cpufreq policy
|
||||
*
|
||||
* This interface function registers the cpufreq cooling device with the name
|
||||
@ -827,86 +745,45 @@ EXPORT_SYMBOL_GPL(cpufreq_cooling_register);
|
||||
* cooling devices. Using this API, the cpufreq cooling device will be
|
||||
* linked to the device tree node provided.
|
||||
*
|
||||
* Return: a valid struct thermal_cooling_device pointer on success,
|
||||
* on failure, it returns a corresponding ERR_PTR().
|
||||
*/
|
||||
struct thermal_cooling_device *
|
||||
of_cpufreq_cooling_register(struct device_node *np,
|
||||
struct cpufreq_policy *policy)
|
||||
{
|
||||
if (!np)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
return __cpufreq_cooling_register(np, policy, 0, NULL);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(of_cpufreq_cooling_register);
|
||||
|
||||
/**
|
||||
* cpufreq_power_cooling_register() - create cpufreq cooling device with power extensions
|
||||
* @policy: cpufreq policy
|
||||
* @capacitance: dynamic power coefficient for these cpus
|
||||
* @plat_static_func: function to calculate the static power consumed by these
|
||||
* cpus (optional)
|
||||
*
|
||||
* This interface function registers the cpufreq cooling device with
|
||||
* the name "thermal-cpufreq-%x". This api can support multiple
|
||||
* instances of cpufreq cooling devices. Using this function, the
|
||||
* cooling device will implement the power extensions by using a
|
||||
* simple cpu power model. The cpus must have registered their OPPs
|
||||
* using the OPP library.
|
||||
*
|
||||
* An optional @plat_static_func may be provided to calculate the
|
||||
* static power consumed by these cpus. If the platform's static
|
||||
* power consumption is unknown or negligible, make it NULL.
|
||||
*
|
||||
* Return: a valid struct thermal_cooling_device pointer on success,
|
||||
* on failure, it returns a corresponding ERR_PTR().
|
||||
*/
|
||||
struct thermal_cooling_device *
|
||||
cpufreq_power_cooling_register(struct cpufreq_policy *policy, u32 capacitance,
|
||||
get_static_t plat_static_func)
|
||||
{
|
||||
return __cpufreq_cooling_register(NULL, policy, capacitance,
|
||||
plat_static_func);
|
||||
}
|
||||
EXPORT_SYMBOL(cpufreq_power_cooling_register);
|
||||
|
||||
/**
|
||||
* of_cpufreq_power_cooling_register() - create cpufreq cooling device with power extensions
|
||||
* @np: a valid struct device_node to the cooling device device tree node
|
||||
* @policy: cpufreq policy
|
||||
* @capacitance: dynamic power coefficient for these cpus
|
||||
* @plat_static_func: function to calculate the static power consumed by these
|
||||
* cpus (optional)
|
||||
*
|
||||
* This interface function registers the cpufreq cooling device with
|
||||
* the name "thermal-cpufreq-%x". This api can support multiple
|
||||
* instances of cpufreq cooling devices. Using this API, the cpufreq
|
||||
* cooling device will be linked to the device tree node provided.
|
||||
* Using this function, the cooling device will implement the power
|
||||
* extensions by using a simple cpu power model. The cpus must have
|
||||
* registered their OPPs using the OPP library.
|
||||
*
|
||||
* An optional @plat_static_func may be provided to calculate the
|
||||
* static power consumed by these cpus. If the platform's static
|
||||
* power consumption is unknown or negligible, make it NULL.
|
||||
* It also takes into account, if property present in policy CPU node, the
|
||||
* static power consumed by the cpu.
|
||||
*
|
||||
* Return: a valid struct thermal_cooling_device pointer on success,
|
||||
* on failure, it returns a corresponding ERR_PTR().
|
||||
* and NULL on failure.
|
||||
*/
|
||||
struct thermal_cooling_device *
|
||||
of_cpufreq_power_cooling_register(struct device_node *np,
|
||||
struct cpufreq_policy *policy,
|
||||
u32 capacitance,
|
||||
get_static_t plat_static_func)
|
||||
of_cpufreq_cooling_register(struct cpufreq_policy *policy)
|
||||
{
|
||||
if (!np)
|
||||
return ERR_PTR(-EINVAL);
|
||||
struct device_node *np = of_get_cpu_node(policy->cpu, NULL);
|
||||
struct thermal_cooling_device *cdev = NULL;
|
||||
u32 capacitance = 0;
|
||||
|
||||
return __cpufreq_cooling_register(np, policy, capacitance,
|
||||
plat_static_func);
|
||||
if (!np) {
|
||||
pr_err("cpu_cooling: OF node not available for cpu%d\n",
|
||||
policy->cpu);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (of_find_property(np, "#cooling-cells", NULL)) {
|
||||
of_property_read_u32(np, "dynamic-power-coefficient",
|
||||
&capacitance);
|
||||
|
||||
cdev = __cpufreq_cooling_register(np, policy, capacitance);
|
||||
if (IS_ERR(cdev)) {
|
||||
pr_err("cpu_cooling: cpu%d is not running as cooling device: %ld\n",
|
||||
policy->cpu, PTR_ERR(cdev));
|
||||
cdev = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
of_node_put(np);
|
||||
return cdev;
|
||||
}
|
||||
EXPORT_SYMBOL(of_cpufreq_power_cooling_register);
|
||||
EXPORT_SYMBOL_GPL(of_cpufreq_cooling_register);
|
||||
|
||||
/**
|
||||
* cpufreq_cooling_unregister - function to remove cpufreq cooling device.
|
||||
|
@ -30,9 +30,6 @@
|
||||
|
||||
struct cpufreq_policy;
|
||||
|
||||
typedef int (*get_static_t)(cpumask_t *cpumask, int interval,
|
||||
unsigned long voltage, u32 *power);
|
||||
|
||||
#ifdef CONFIG_CPU_THERMAL
|
||||
/**
|
||||
* cpufreq_cooling_register - function to create cpufreq cooling device.
|
||||
@ -41,43 +38,6 @@ typedef int (*get_static_t)(cpumask_t *cpumask, int interval,
|
||||
struct thermal_cooling_device *
|
||||
cpufreq_cooling_register(struct cpufreq_policy *policy);
|
||||
|
||||
struct thermal_cooling_device *
|
||||
cpufreq_power_cooling_register(struct cpufreq_policy *policy,
|
||||
u32 capacitance, get_static_t plat_static_func);
|
||||
|
||||
/**
|
||||
* of_cpufreq_cooling_register - create cpufreq cooling device based on DT.
|
||||
* @np: a valid struct device_node to the cooling device device tree node.
|
||||
* @policy: cpufreq policy.
|
||||
*/
|
||||
#ifdef CONFIG_THERMAL_OF
|
||||
struct thermal_cooling_device *
|
||||
of_cpufreq_cooling_register(struct device_node *np,
|
||||
struct cpufreq_policy *policy);
|
||||
|
||||
struct thermal_cooling_device *
|
||||
of_cpufreq_power_cooling_register(struct device_node *np,
|
||||
struct cpufreq_policy *policy,
|
||||
u32 capacitance,
|
||||
get_static_t plat_static_func);
|
||||
#else
|
||||
static inline struct thermal_cooling_device *
|
||||
of_cpufreq_cooling_register(struct device_node *np,
|
||||
struct cpufreq_policy *policy)
|
||||
{
|
||||
return ERR_PTR(-ENOSYS);
|
||||
}
|
||||
|
||||
static inline struct thermal_cooling_device *
|
||||
of_cpufreq_power_cooling_register(struct device_node *np,
|
||||
struct cpufreq_policy *policy,
|
||||
u32 capacitance,
|
||||
get_static_t plat_static_func)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* cpufreq_cooling_unregister - function to remove cpufreq cooling device.
|
||||
* @cdev: thermal cooling device pointer.
|
||||
@ -90,28 +50,6 @@ cpufreq_cooling_register(struct cpufreq_policy *policy)
|
||||
{
|
||||
return ERR_PTR(-ENOSYS);
|
||||
}
|
||||
static inline struct thermal_cooling_device *
|
||||
cpufreq_power_cooling_register(struct cpufreq_policy *policy,
|
||||
u32 capacitance, get_static_t plat_static_func)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline struct thermal_cooling_device *
|
||||
of_cpufreq_cooling_register(struct device_node *np,
|
||||
struct cpufreq_policy *policy)
|
||||
{
|
||||
return ERR_PTR(-ENOSYS);
|
||||
}
|
||||
|
||||
static inline struct thermal_cooling_device *
|
||||
of_cpufreq_power_cooling_register(struct device_node *np,
|
||||
struct cpufreq_policy *policy,
|
||||
u32 capacitance,
|
||||
get_static_t plat_static_func)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline
|
||||
void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev)
|
||||
@ -120,4 +58,19 @@ void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev)
|
||||
}
|
||||
#endif /* CONFIG_CPU_THERMAL */
|
||||
|
||||
#if defined(CONFIG_THERMAL_OF) && defined(CONFIG_CPU_THERMAL)
|
||||
/**
|
||||
* of_cpufreq_cooling_register - create cpufreq cooling device based on DT.
|
||||
* @policy: cpufreq policy.
|
||||
*/
|
||||
struct thermal_cooling_device *
|
||||
of_cpufreq_cooling_register(struct cpufreq_policy *policy);
|
||||
#else
|
||||
static inline struct thermal_cooling_device *
|
||||
of_cpufreq_cooling_register(struct cpufreq_policy *policy)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
#endif /* defined(CONFIG_THERMAL_OF) && defined(CONFIG_CPU_THERMAL) */
|
||||
|
||||
#endif /* __CPU_COOLING_H__ */
|
||||
|
@ -94,9 +94,9 @@ TRACE_EVENT(thermal_zone_trip,
|
||||
#ifdef CONFIG_CPU_THERMAL
|
||||
TRACE_EVENT(thermal_power_cpu_get_power,
|
||||
TP_PROTO(const struct cpumask *cpus, unsigned long freq, u32 *load,
|
||||
size_t load_len, u32 dynamic_power, u32 static_power),
|
||||
size_t load_len, u32 dynamic_power),
|
||||
|
||||
TP_ARGS(cpus, freq, load, load_len, dynamic_power, static_power),
|
||||
TP_ARGS(cpus, freq, load, load_len, dynamic_power),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__bitmask(cpumask, num_possible_cpus())
|
||||
@ -104,7 +104,6 @@ TRACE_EVENT(thermal_power_cpu_get_power,
|
||||
__dynamic_array(u32, load, load_len)
|
||||
__field(size_t, load_len )
|
||||
__field(u32, dynamic_power )
|
||||
__field(u32, static_power )
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
@ -115,13 +114,12 @@ TRACE_EVENT(thermal_power_cpu_get_power,
|
||||
load_len * sizeof(*load));
|
||||
__entry->load_len = load_len;
|
||||
__entry->dynamic_power = dynamic_power;
|
||||
__entry->static_power = static_power;
|
||||
),
|
||||
|
||||
TP_printk("cpus=%s freq=%lu load={%s} dynamic_power=%d static_power=%d",
|
||||
TP_printk("cpus=%s freq=%lu load={%s} dynamic_power=%d",
|
||||
__get_bitmask(cpumask), __entry->freq,
|
||||
__print_array(__get_dynamic_array(load), __entry->load_len, 4),
|
||||
__entry->dynamic_power, __entry->static_power)
|
||||
__entry->dynamic_power)
|
||||
);
|
||||
|
||||
TRACE_EVENT(thermal_power_cpu_limit,
|
||||
|
Loading…
Reference in New Issue
Block a user