Merge "driver: thermal: msm_lmh_dcvs: Register LMH DCVS cooling device"
This commit is contained in:
commit
bab8b37633
3 changed files with 122 additions and 8 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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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