Merge "driver: thermal: msm_lmh_dcvs: Register LMH DCVS cooling device"

This commit is contained in:
Linux Build Service Account 2016-10-21 17:16:03 -07:00 committed by Gerrit - the friendly Code Review server
commit bab8b37633
3 changed files with 122 additions and 8 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

@ -24,6 +24,7 @@
#include <linux/interrupt.h>
#include <linux/timer.h>
#include <linux/pm_opp.h>
#include <linux/cpu_cooling.h>
#include <asm/smp_plat.h>
#include <asm/cacheflush.h>
@ -40,6 +41,7 @@
#define MSM_LIMITS_NODE_DCVS 0x44435653
#define MSM_LIMITS_SUB_FN_THERMAL 0x54484D4C
#define MSM_LIMITS_SUB_FN_GENERAL 0x47454E00
#define MSM_LIMITS_ALGO_MODE_ENABLE 0x454E424C
@ -49,6 +51,8 @@
#define MSM_LIMITS_CLUSTER_0 0x6370302D
#define MSM_LIMITS_CLUSTER_1 0x6370312D
#define MSM_LIMITS_DOMAIN_MAX 0x444D4158
#define MSM_LIMITS_HIGH_THRESHOLD_VAL 95000
#define MSM_LIMITS_ARM_THRESHOLD_VAL 65000
#define MSM_LIMITS_POLLING_DELAY_MS 10
@ -77,8 +81,12 @@ struct msm_lmh_dcvs_hw {
cpumask_t core_map;
struct timer_list poll_timer;
uint32_t max_freq;
uint32_t hw_freq_limit;
struct list_head list;
};
LIST_HEAD(lmh_dcvs_hw_list);
static void msm_lmh_dcvs_get_max_freq(uint32_t cpu, uint32_t *max_freq)
{
unsigned long freq_ceil = UINT_MAX;
@ -104,6 +112,7 @@ static uint32_t msm_lmh_mitigation_notify(struct msm_lmh_dcvs_hw *hw)
dcvsh_get_frequency(val, max_limit);
sched_update_cpu_freq_min_max(&hw->core_map, 0, max_limit);
trace_lmh_dcvs_freq(cpumask_first(&hw->core_map), max_limit);
hw->hw_freq_limit = max_limit;
return max_limit;
}
@ -250,6 +259,45 @@ static int trip_notify(enum thermal_trip_type type, int temp, void *data)
return 0;
}
static struct msm_lmh_dcvs_hw *get_dcvsh_hw_from_cpu(int cpu)
{
struct msm_lmh_dcvs_hw *hw;
list_for_each_entry(hw, &lmh_dcvs_hw_list, list) {
if (cpumask_test_cpu(cpu, &hw->core_map))
return hw;
}
return NULL;
}
static int lmh_set_max_limit(int cpu, u32 freq)
{
struct msm_lmh_dcvs_hw *hw = get_dcvsh_hw_from_cpu(cpu);
if (!hw)
return -EINVAL;
return msm_lmh_dcvs_write(hw->affinity, MSM_LIMITS_SUB_FN_GENERAL,
MSM_LIMITS_DOMAIN_MAX, freq);
}
static int lmh_get_cur_limit(int cpu, unsigned long *freq)
{
struct msm_lmh_dcvs_hw *hw = get_dcvsh_hw_from_cpu(cpu);
if (!hw)
return -EINVAL;
*freq = hw->hw_freq_limit;
return 0;
}
static struct cpu_cooling_ops cd_ops = {
.get_cur_state = lmh_get_cur_limit,
.ceil_limit = lmh_set_max_limit,
};
static int msm_lmh_dcvs_probe(struct platform_device *pdev)
{
int ret;
@ -257,6 +305,7 @@ static int msm_lmh_dcvs_probe(struct platform_device *pdev)
struct msm_lmh_dcvs_hw *hw;
char sensor_name[] = "limits_sensor-00";
struct thermal_zone_device *tzdev;
struct thermal_cooling_device *cdev;
struct device_node *dn = pdev->dev.of_node;
struct device_node *cpu_node, *lmh_node;
uint32_t id, max_freq, request_reg, clear_reg;
@ -331,6 +380,10 @@ static int msm_lmh_dcvs_probe(struct platform_device *pdev)
if (IS_ERR_OR_NULL(tzdev))
return PTR_ERR(tzdev);
/* Setup cooling devices to request mitigation states */
cdev = cpufreq_platform_cooling_register(&hw->core_map, &cd_ops);
if (IS_ERR_OR_NULL(cdev))
return PTR_ERR(cdev);
/*
* Driver defaults to for low and hi thresholds.
* Since we make a check for hi > lo value, set the hi threshold
@ -356,7 +409,7 @@ static int msm_lmh_dcvs_probe(struct platform_device *pdev)
return ret;
}
hw->max_freq = max_freq;
hw->hw_freq_limit = hw->max_freq = max_freq;
switch (affinity) {
case 0:
@ -399,6 +452,9 @@ static int msm_lmh_dcvs_probe(struct platform_device *pdev)
return ret;
}
INIT_LIST_HEAD(&hw->list);
list_add(&hw->list, &lmh_dcvs_hw_list);
return ret;
}

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