drivers: thermal: cpu_cooling: allow platform freq mitigation
cpu device can be controlled by a hardware platform device and in those cases the cpu cooling device interface should communicate with the platform device instead of the cpufreq module. Allow platform drivers to register with CPU cooling with their frequency mitigation functions. This allows the cpu cooling interface to communicate the frequency mitigations to the platform driver directly. Change-Id: I47960b002bf1bce1cd588de2892de46793a95562 Signed-off-by: Ram Chandrasekar <rkumbako@codeaurora.org>
This commit is contained in:
parent
1ff56658f3
commit
64892ef328
2 changed files with 65 additions and 7 deletions
|
@ -103,6 +103,7 @@ struct cpufreq_cooling_device {
|
|||
int dyn_power_table_entries;
|
||||
struct device *cpu_dev;
|
||||
get_static_t plat_get_static_power;
|
||||
struct cpu_cooling_ops *plat_ops;
|
||||
};
|
||||
static DEFINE_IDR(cpufreq_idr);
|
||||
static DEFINE_MUTEX(cooling_cpufreq_lock);
|
||||
|
@ -504,8 +505,13 @@ static int cpufreq_get_cur_state(struct thermal_cooling_device *cdev,
|
|||
unsigned long *state)
|
||||
{
|
||||
struct cpufreq_cooling_device *cpufreq_device = cdev->devdata;
|
||||
unsigned int cpu = cpumask_any(&cpufreq_device->allowed_cpus);
|
||||
|
||||
*state = cpufreq_device->cpufreq_state;
|
||||
if (cpufreq_device->plat_ops
|
||||
&& cpufreq_device->plat_ops->get_cur_state)
|
||||
cpufreq_device->plat_ops->get_cur_state(cpu, state);
|
||||
else
|
||||
*state = cpufreq_device->cpufreq_state;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -539,7 +545,17 @@ static int cpufreq_set_cur_state(struct thermal_cooling_device *cdev,
|
|||
cpufreq_device->cpufreq_state = state;
|
||||
cpufreq_device->clipped_freq = clip_freq;
|
||||
|
||||
cpufreq_update_policy(cpu);
|
||||
/* Check if the device has a platform mitigation function that
|
||||
* can handle the CPU freq mitigation, if not, notify cpufreq
|
||||
* framework.
|
||||
*/
|
||||
if (cpufreq_device->plat_ops) {
|
||||
if (cpufreq_device->plat_ops->ceil_limit)
|
||||
cpufreq_device->plat_ops->ceil_limit(cpu,
|
||||
clip_freq);
|
||||
} else {
|
||||
cpufreq_update_policy(cpu);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -773,6 +789,9 @@ static unsigned int find_next_max(struct cpufreq_frequency_table *table,
|
|||
* @capacitance: dynamic power coefficient for these cpus
|
||||
* @plat_static_func: function to calculate the static power consumed by these
|
||||
* cpus (optional)
|
||||
* @plat_mitig_func: function that does the mitigation by changing the
|
||||
* frequencies (Optional). By default, cpufreq framweork will
|
||||
* be notified of the new limits.
|
||||
*
|
||||
* This interface function registers the cpufreq cooling device with the name
|
||||
* "thermal-cpufreq-%x". This api can support multiple instances of cpufreq
|
||||
|
@ -785,7 +804,8 @@ static unsigned int find_next_max(struct cpufreq_frequency_table *table,
|
|||
static struct thermal_cooling_device *
|
||||
__cpufreq_cooling_register(struct device_node *np,
|
||||
const struct cpumask *clip_cpus, u32 capacitance,
|
||||
get_static_t plat_static_func)
|
||||
get_static_t plat_static_func,
|
||||
struct cpu_cooling_ops *plat_ops)
|
||||
{
|
||||
struct thermal_cooling_device *cool_dev;
|
||||
struct cpufreq_cooling_device *cpufreq_dev;
|
||||
|
@ -851,6 +871,8 @@ __cpufreq_cooling_register(struct device_node *np,
|
|||
}
|
||||
}
|
||||
|
||||
cpufreq_dev->plat_ops = plat_ops;
|
||||
|
||||
ret = get_idr(&cpufreq_idr, &cpufreq_dev->id);
|
||||
if (ret) {
|
||||
cool_dev = ERR_PTR(ret);
|
||||
|
@ -924,7 +946,7 @@ free_cdev:
|
|||
struct thermal_cooling_device *
|
||||
cpufreq_cooling_register(const struct cpumask *clip_cpus)
|
||||
{
|
||||
return __cpufreq_cooling_register(NULL, clip_cpus, 0, NULL);
|
||||
return __cpufreq_cooling_register(NULL, clip_cpus, 0, NULL, NULL);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cpufreq_cooling_register);
|
||||
|
||||
|
@ -948,7 +970,7 @@ of_cpufreq_cooling_register(struct device_node *np,
|
|||
if (!np)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
return __cpufreq_cooling_register(np, clip_cpus, 0, NULL);
|
||||
return __cpufreq_cooling_register(np, clip_cpus, 0, NULL, NULL);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(of_cpufreq_cooling_register);
|
||||
|
||||
|
@ -978,10 +1000,30 @@ cpufreq_power_cooling_register(const struct cpumask *clip_cpus, u32 capacitance,
|
|||
get_static_t plat_static_func)
|
||||
{
|
||||
return __cpufreq_cooling_register(NULL, clip_cpus, capacitance,
|
||||
plat_static_func);
|
||||
plat_static_func, NULL);
|
||||
}
|
||||
EXPORT_SYMBOL(cpufreq_power_cooling_register);
|
||||
|
||||
/**
|
||||
* cpufreq_platform_cooling_register() - create cpufreq cooling device with
|
||||
* additional platform specific mitigation function.
|
||||
*
|
||||
* @clip_cpus: cpumask of cpus where the frequency constraints will happen
|
||||
* @plat_ops: the platform mitigation functions that will be called insted of
|
||||
* cpufreq, if provided.
|
||||
*
|
||||
* Return: a valid struct thermal_cooling_device pointer on success,
|
||||
* on failure, it returns a corresponding ERR_PTR().
|
||||
*/
|
||||
struct thermal_cooling_device *
|
||||
cpufreq_platform_cooling_register(const struct cpumask *clip_cpus,
|
||||
struct cpu_cooling_ops *plat_ops)
|
||||
{
|
||||
return __cpufreq_cooling_register(NULL, clip_cpus, 0, NULL,
|
||||
plat_ops);
|
||||
}
|
||||
EXPORT_SYMBOL(cpufreq_platform_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
|
||||
|
@ -1015,7 +1057,7 @@ of_cpufreq_power_cooling_register(struct device_node *np,
|
|||
return ERR_PTR(-EINVAL);
|
||||
|
||||
return __cpufreq_cooling_register(np, clip_cpus, capacitance,
|
||||
plat_static_func);
|
||||
plat_static_func, NULL);
|
||||
}
|
||||
EXPORT_SYMBOL(of_cpufreq_power_cooling_register);
|
||||
|
||||
|
|
|
@ -31,6 +31,11 @@
|
|||
typedef int (*get_static_t)(cpumask_t *cpumask, int interval,
|
||||
unsigned long voltage, u32 *power);
|
||||
|
||||
struct cpu_cooling_ops {
|
||||
int (*ceil_limit)(int, u32);
|
||||
int (*get_cur_state)(int, unsigned long *);
|
||||
};
|
||||
|
||||
#ifdef CONFIG_CPU_THERMAL
|
||||
/**
|
||||
* cpufreq_cooling_register - function to create cpufreq cooling device.
|
||||
|
@ -43,6 +48,10 @@ struct thermal_cooling_device *
|
|||
cpufreq_power_cooling_register(const struct cpumask *clip_cpus,
|
||||
u32 capacitance, get_static_t plat_static_func);
|
||||
|
||||
struct thermal_cooling_device *
|
||||
cpufreq_platform_cooling_register(const struct cpumask *clip_cpus,
|
||||
struct cpu_cooling_ops *ops);
|
||||
|
||||
/**
|
||||
* of_cpufreq_cooling_register - create cpufreq cooling device based on DT.
|
||||
* @np: a valid struct device_node to the cooling device device tree node.
|
||||
|
@ -112,6 +121,13 @@ of_cpufreq_power_cooling_register(struct device_node *np,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static inline struct thermal_cooling_device *
|
||||
cpufreq_platform_cooling_register(const struct cpumask *clip_cpus,
|
||||
struct cpu_cooling_ops *ops)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline
|
||||
void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev)
|
||||
{
|
||||
|
|
Loading…
Add table
Reference in a new issue