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:
Lina Iyer 2016-02-23 13:08:31 -07:00 committed by Ram Chandrasekar
parent 1ff56658f3
commit 64892ef328
2 changed files with 65 additions and 7 deletions

View file

@ -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);

View file

@ -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)
{