drivers: thermal: Import xiaomi changes
The Patch based on QualComm release TAG:LA.UM.8.15.r1-06600-KAMORTA.0 Change-Id: I117e1bc42b15585916d32d37d9606a76952cc61c Signed-off-by: starlight5234 <starlight5234@protonmail.ch>
This commit is contained in:
parent
29d3d740d7
commit
b69a0d87dd
4 changed files with 349 additions and 19 deletions
|
@ -35,6 +35,8 @@
|
|||
|
||||
#include <trace/events/thermal.h>
|
||||
|
||||
#define USE_LMH_DEV 0
|
||||
|
||||
/*
|
||||
* Cooling state <-> CPUFreq frequency
|
||||
*
|
||||
|
@ -54,6 +56,12 @@
|
|||
* @time: previous reading of the absolute time that this cpu was idle
|
||||
* @timestamp: wall time of the last invocation of get_cpu_idle_time_us()
|
||||
*/
|
||||
|
||||
struct freq_table {
|
||||
u32 frequency;
|
||||
u32 power;
|
||||
};
|
||||
|
||||
struct time_in_idle {
|
||||
u64 time;
|
||||
u64 timestamp;
|
||||
|
@ -87,12 +95,14 @@ struct time_in_idle {
|
|||
*/
|
||||
struct cpufreq_cooling_device {
|
||||
int id;
|
||||
int cpu_id;
|
||||
u32 last_load;
|
||||
unsigned int cpufreq_state;
|
||||
unsigned int clipped_freq;
|
||||
unsigned int cpufreq_floor_state;
|
||||
unsigned int floor_freq;
|
||||
unsigned int max_level;
|
||||
struct freq_table *freq_table;
|
||||
struct em_perf_domain *em;
|
||||
struct thermal_cooling_device *cdev;
|
||||
struct cpufreq_policy *policy;
|
||||
|
@ -125,7 +135,7 @@ static int cpufreq_thermal_notifier(struct notifier_block *nb,
|
|||
unsigned long clipped_freq = ULONG_MAX, floor_freq = 0;
|
||||
struct cpufreq_cooling_device *cpufreq_cdev;
|
||||
|
||||
if (event != CPUFREQ_INCOMPATIBLE)
|
||||
if (event != CPUFREQ_THERMAL)
|
||||
return NOTIFY_DONE;
|
||||
|
||||
mutex_lock(&cooling_list_lock);
|
||||
|
@ -151,19 +161,49 @@ static int cpufreq_thermal_notifier(struct notifier_block *nb,
|
|||
* Similarly, if policy minimum set by the user is less than
|
||||
* the floor_frequency, then adjust the policy->min.
|
||||
*/
|
||||
clipped_freq = cpufreq_cdev->clipped_freq;
|
||||
floor_freq = cpufreq_cdev->floor_freq;
|
||||
if (policy->max > clipped_freq || policy->min < floor_freq)
|
||||
cpufreq_verify_within_limits(policy, floor_freq,
|
||||
clipped_freq);
|
||||
break;
|
||||
}
|
||||
if (clipped_freq > cpufreq_cdev->clipped_freq)
|
||||
{
|
||||
//pr_info("__test__, %s,cpu is %d, clipperd_freq is %d, %d.\n", __func__, policy->cpu, clipped_freq, cpufreq_cdev->clipped_freq);
|
||||
clipped_freq = cpufreq_cdev->clipped_freq;
|
||||
|
||||
}
|
||||
}
|
||||
cpufreq_verify_within_limits(policy, floor_freq, clipped_freq);
|
||||
mutex_unlock(&cooling_list_lock);
|
||||
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
|
||||
void cpu_limits_set_level(unsigned int cpu, unsigned int max_freq)
|
||||
{
|
||||
struct cpufreq_cooling_device *cpufreq_cdev;
|
||||
struct thermal_cooling_device *cdev;
|
||||
unsigned int cdev_cpu;
|
||||
unsigned int level;
|
||||
|
||||
list_for_each_entry(cpufreq_cdev, &cpufreq_cdev_list, node) {
|
||||
sscanf(cpufreq_cdev->cdev->type, "thermal-cpufreq-%d", &cdev_cpu);
|
||||
if (cdev_cpu == cpu) {
|
||||
for (level = 0; level <= cpufreq_cdev->max_level; level++) {
|
||||
int target_freq = cpufreq_cdev->em->table[level].frequency;
|
||||
if (max_freq <= target_freq) {
|
||||
cdev = cpufreq_cdev->cdev;
|
||||
if (cdev)
|
||||
{
|
||||
//pr_info("__test__, %s, cpu is %d, max_freq is %d, target_freq is %d.\n", __func__, cpu, max_freq, target_freq);
|
||||
cdev->ops->set_cur_state(cdev, cpufreq_cdev->max_level - level);
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_ENERGY_MODEL
|
||||
/**
|
||||
* get_level: Find the level for a particular frequency
|
||||
|
@ -405,7 +445,7 @@ static int cpufreq_set_cur_state(struct thermal_cooling_device *cdev,
|
|||
|
||||
/* Request state should be less than max_level */
|
||||
if (WARN_ON(state > cpufreq_cdev->max_level))
|
||||
return -EINVAL;
|
||||
return cpufreq_cdev->max_level;
|
||||
|
||||
/* Check if the old cooling action is same as new cooling action */
|
||||
if (cpufreq_cdev->cpufreq_state == state)
|
||||
|
@ -419,12 +459,18 @@ static int cpufreq_set_cur_state(struct thermal_cooling_device *cdev,
|
|||
* can handle the CPU freq mitigation, if not, notify cpufreq
|
||||
* framework.
|
||||
*/
|
||||
if (cpufreq_cdev->plat_ops &&
|
||||
cpufreq_cdev->plat_ops->ceil_limit)
|
||||
cpufreq_cdev->plat_ops->ceil_limit(cpufreq_cdev->policy->cpu,
|
||||
if (USE_LMH_DEV && cpufreq_cdev->plat_ops) {
|
||||
if (cpufreq_cdev->plat_ops->ceil_limit)
|
||||
cpufreq_cdev->plat_ops->ceil_limit(cpufreq_cdev->policy->cpu,
|
||||
clip_freq);
|
||||
else
|
||||
get_online_cpus();
|
||||
cpufreq_update_policy(cpufreq_cdev->policy->cpu);
|
||||
put_online_cpus();
|
||||
} else {
|
||||
get_online_cpus();
|
||||
cpufreq_update_policy(cpufreq_cdev->policy->cpu);
|
||||
put_online_cpus();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -701,7 +747,7 @@ __cpufreq_cooling_register(struct device_node *np,
|
|||
list_add(&cpufreq_cdev->node, &cpufreq_cdev_list);
|
||||
mutex_unlock(&cooling_list_lock);
|
||||
|
||||
if (first && !cpufreq_cdev->plat_ops)
|
||||
if (first)
|
||||
cpufreq_register_notifier(&thermal_cpufreq_notifier_block,
|
||||
CPUFREQ_POLICY_NOTIFIER);
|
||||
|
||||
|
@ -841,10 +887,9 @@ void cpufreq_cooling_unregister(struct thermal_cooling_device *cdev)
|
|||
mutex_unlock(&cooling_list_lock);
|
||||
|
||||
if (last) {
|
||||
if (!cpufreq_cdev->plat_ops)
|
||||
cpufreq_unregister_notifier(
|
||||
&thermal_cpufreq_notifier_block,
|
||||
CPUFREQ_POLICY_NOTIFIER);
|
||||
cpufreq_unregister_notifier(
|
||||
&thermal_cpufreq_notifier_block,
|
||||
CPUFREQ_POLICY_NOTIFIER);
|
||||
}
|
||||
|
||||
thermal_cooling_device_unregister(cpufreq_cdev->cdev);
|
||||
|
|
|
@ -22,6 +22,11 @@
|
|||
#include <net/netlink.h>
|
||||
#include <net/genetlink.h>
|
||||
#include <linux/suspend.h>
|
||||
#include <linux/cpu_cooling.h>
|
||||
|
||||
#ifdef CONFIG_DRM
|
||||
#include <drm/drm_notifier.h>
|
||||
#endif
|
||||
|
||||
#define CREATE_TRACE_POINTS
|
||||
#include <trace/events/thermal.h>
|
||||
|
@ -35,6 +40,8 @@ MODULE_LICENSE("GPL v2");
|
|||
|
||||
#define THERMAL_MAX_ACTIVE 16
|
||||
|
||||
#define CPU_LIMITS_PARAM_NUM 2
|
||||
|
||||
static DEFINE_IDA(thermal_tz_ida);
|
||||
static DEFINE_IDA(thermal_cdev_ida);
|
||||
|
||||
|
@ -46,6 +53,21 @@ static DEFINE_MUTEX(thermal_list_lock);
|
|||
static DEFINE_MUTEX(thermal_governor_lock);
|
||||
static DEFINE_MUTEX(poweroff_lock);
|
||||
|
||||
#ifdef CONFIG_DRM
|
||||
struct screen_monitor {
|
||||
struct notifier_block thermal_notifier;
|
||||
int screen_state;
|
||||
};
|
||||
|
||||
struct screen_monitor sm;
|
||||
#endif
|
||||
|
||||
static atomic_t switch_mode = ATOMIC_INIT(-1);
|
||||
static atomic_t temp_state = ATOMIC_INIT(0);
|
||||
static char boost_buf[128];
|
||||
const char *board_sensor;
|
||||
static char board_sensor_temp[128];
|
||||
|
||||
static atomic_t in_suspend;
|
||||
static bool power_off_triggered;
|
||||
|
||||
|
@ -939,6 +961,8 @@ static struct class thermal_class = {
|
|||
.dev_release = thermal_release,
|
||||
};
|
||||
|
||||
static struct device thermal_message_dev;
|
||||
|
||||
static inline
|
||||
void print_bind_err_msg(struct thermal_zone_device *tz,
|
||||
struct thermal_cooling_device *cdev, int ret)
|
||||
|
@ -1658,6 +1682,245 @@ static struct notifier_block thermal_pm_nb = {
|
|||
.notifier_call = thermal_pm_notify,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_DRM
|
||||
static ssize_t
|
||||
thermal_screen_state_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", sm.screen_state);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(screen_state, 0664,
|
||||
thermal_screen_state_show, NULL);
|
||||
#endif
|
||||
|
||||
static ssize_t
|
||||
thermal_sconfig_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", atomic_read(&switch_mode));
|
||||
}
|
||||
|
||||
|
||||
static ssize_t
|
||||
thermal_sconfig_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t len)
|
||||
{
|
||||
int val = -1;
|
||||
|
||||
val = simple_strtol(buf, NULL, 10);
|
||||
|
||||
atomic_set(&switch_mode, val);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(sconfig, 0664,
|
||||
thermal_sconfig_show, thermal_sconfig_store);
|
||||
|
||||
static ssize_t
|
||||
thermal_boost_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, boost_buf);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
thermal_boost_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t len)
|
||||
{
|
||||
int ret;
|
||||
ret = snprintf(boost_buf, sizeof(boost_buf), buf);
|
||||
return len;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(boost, 0644,
|
||||
thermal_boost_show, thermal_boost_store);
|
||||
|
||||
static ssize_t
|
||||
thermal_temp_state_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", atomic_read(&temp_state));
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
thermal_temp_state_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t len)
|
||||
{
|
||||
int val = -1;
|
||||
|
||||
val = simple_strtol(buf, NULL, 10);
|
||||
|
||||
atomic_set(&temp_state, val);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(temp_state, 0664,
|
||||
thermal_temp_state_show, thermal_temp_state_store);
|
||||
|
||||
static ssize_t
|
||||
cpu_limits_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
cpu_limits_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t len)
|
||||
{
|
||||
unsigned int cpu;
|
||||
unsigned int max;
|
||||
|
||||
if (sscanf(buf, "cpu%u %u", &cpu, &max) != CPU_LIMITS_PARAM_NUM) {
|
||||
pr_err("input param error, can not prase param\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
cpu_limits_set_level(cpu, max);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
thermal_board_sensor_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
if (!board_sensor)
|
||||
board_sensor = "invalid";
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%s", board_sensor);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(board_sensor, 0664,
|
||||
thermal_board_sensor_show, NULL);
|
||||
|
||||
static ssize_t
|
||||
thermal_board_sensor_temp_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, board_sensor_temp);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
thermal_board_sensor_temp_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t len)
|
||||
{
|
||||
snprintf(board_sensor_temp, sizeof(board_sensor_temp), buf);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(board_sensor_temp, 0664,
|
||||
thermal_board_sensor_temp_show, thermal_board_sensor_temp_store);
|
||||
|
||||
static DEVICE_ATTR(cpu_limits, 0664,
|
||||
cpu_limits_show, cpu_limits_store);
|
||||
|
||||
static int create_thermal_message_node(void)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
thermal_message_dev.class = &thermal_class;
|
||||
|
||||
dev_set_name(&thermal_message_dev, "thermal_message");
|
||||
ret = device_register(&thermal_message_dev);
|
||||
if (!ret) {
|
||||
#ifdef CONFIG_DRM
|
||||
ret = sysfs_create_file(&thermal_message_dev.kobj, &dev_attr_screen_state.attr);
|
||||
if (ret < 0)
|
||||
pr_warn("Thermal: create batt message node failed\n");
|
||||
#endif
|
||||
ret = sysfs_create_file(&thermal_message_dev.kobj, &dev_attr_sconfig.attr);
|
||||
if (ret < 0)
|
||||
pr_warn("Thermal: create sconfig node failed\n");
|
||||
|
||||
ret = sysfs_create_file(&thermal_message_dev.kobj, &dev_attr_boost.attr);
|
||||
if (ret < 0)
|
||||
pr_warn("Thermal: create boost node failed\n");
|
||||
|
||||
ret = sysfs_create_file(&thermal_message_dev.kobj, &dev_attr_temp_state.attr);
|
||||
if (ret < 0)
|
||||
pr_warn("Thermal: create temp state node failed\n");
|
||||
|
||||
ret = sysfs_create_file(&thermal_message_dev.kobj, &dev_attr_cpu_limits.attr);
|
||||
ret = sysfs_create_file(&thermal_message_dev.kobj, &dev_attr_board_sensor.attr);
|
||||
if (ret < 0)
|
||||
pr_warn("Thermal: create board sensor node failed\n");
|
||||
|
||||
ret = sysfs_create_file(&thermal_message_dev.kobj, &dev_attr_board_sensor_temp.attr);
|
||||
if (ret < 0)
|
||||
pr_warn("Thermal: create cpu limits node failed\n");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void destroy_thermal_message_node(void)
|
||||
{
|
||||
sysfs_remove_file(&thermal_message_dev.kobj, &dev_attr_cpu_limits.attr);
|
||||
sysfs_remove_file(&thermal_message_dev.kobj, &dev_attr_temp_state.attr);
|
||||
sysfs_remove_file(&thermal_message_dev.kobj, &dev_attr_boost.attr);
|
||||
sysfs_remove_file(&thermal_message_dev.kobj, &dev_attr_sconfig.attr);
|
||||
sysfs_remove_file(&thermal_message_dev.kobj, &dev_attr_board_sensor_temp.attr);
|
||||
sysfs_remove_file(&thermal_message_dev.kobj, &dev_attr_board_sensor.attr);
|
||||
#ifdef CONFIG_DRM
|
||||
sysfs_remove_file(&thermal_message_dev.kobj, &dev_attr_screen_state.attr);
|
||||
#endif
|
||||
device_unregister(&thermal_message_dev);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DRM
|
||||
static int screen_state_for_thermal_callback(struct notifier_block *nb, unsigned long val, void *data)
|
||||
{
|
||||
struct drm_notify_data *evdata = data;
|
||||
unsigned int blank;
|
||||
|
||||
if (val != DRM_EVENT_BLANK || !evdata || !evdata->data)
|
||||
return 0;
|
||||
|
||||
blank = *(int *)(evdata->data);
|
||||
switch (blank) {
|
||||
case DRM_BLANK_LP1:
|
||||
pr_warn("%s: DRM_BLANK_LP1\n", __func__);
|
||||
case DRM_BLANK_LP2:
|
||||
pr_warn("%s: DRM_BLANK_LP2\n", __func__);
|
||||
case DRM_BLANK_POWERDOWN:
|
||||
sm.screen_state = 0;
|
||||
pr_warn("%s: DRM_BLANK_POWERDOWN\n", __func__);
|
||||
break;
|
||||
case DRM_BLANK_UNBLANK:
|
||||
sm.screen_state = 1;
|
||||
pr_warn("%s: DRM_BLANK_UNBLANK\n", __func__);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
sysfs_notify(&thermal_message_dev.kobj, NULL, "screen_state");
|
||||
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int of_parse_thermal_message(void)
|
||||
{
|
||||
struct device_node *np;
|
||||
|
||||
np = of_find_node_by_name(NULL, "thermal-message");
|
||||
if (!np)
|
||||
return -EINVAL;
|
||||
|
||||
if (of_property_read_string(np, "board-sensor", &board_sensor))
|
||||
return -EINVAL;
|
||||
|
||||
pr_info("%s board sensor: %s\n", __func__, board_sensor);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init thermal_init(void)
|
||||
{
|
||||
int result;
|
||||
|
@ -1689,6 +1952,22 @@ static int __init thermal_init(void)
|
|||
pr_warn("Thermal: Can not register suspend notifier, return %d\n",
|
||||
result);
|
||||
|
||||
result = create_thermal_message_node();
|
||||
if (result)
|
||||
pr_warn("Thermal: create thermal message node failed, return %d\n",
|
||||
result);
|
||||
result = of_parse_thermal_message();
|
||||
if (result)
|
||||
pr_warn("Thermal: Can not parse thermal message node, return %d\n",
|
||||
result);
|
||||
|
||||
#ifdef CONFIG_DRM
|
||||
sm.thermal_notifier.notifier_call = screen_state_for_thermal_callback;
|
||||
if (drm_register_client(&sm.thermal_notifier) < 0) {
|
||||
pr_warn("Thermal: register screen state callback failed\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
||||
exit_zone_parse:
|
||||
|
@ -1708,10 +1987,14 @@ static int __init thermal_init(void)
|
|||
|
||||
static void thermal_exit(void)
|
||||
{
|
||||
#ifdef CONFIG_DRM
|
||||
drm_unregister_client(&sm.thermal_notifier);
|
||||
#endif
|
||||
unregister_pm_notifier(&thermal_pm_nb);
|
||||
of_thermal_destroy_zones();
|
||||
destroy_workqueue(thermal_passive_wq);
|
||||
genetlink_exit();
|
||||
destroy_thermal_message_node();
|
||||
class_unregister(&thermal_class);
|
||||
thermal_unregister_governors();
|
||||
ida_destroy(&thermal_tz_ida);
|
||||
|
|
|
@ -903,7 +903,7 @@ void thermal_cooling_device_stats_update(struct thermal_cooling_device *cdev,
|
|||
|
||||
spin_lock(&stats->lock);
|
||||
|
||||
if (stats->state == new_state)
|
||||
if (stats->state == new_state || new_state >= stats->max_states)
|
||||
goto unlock;
|
||||
|
||||
update_time_in_state(stats);
|
||||
|
|
|
@ -56,6 +56,8 @@ struct thermal_cooling_device *
|
|||
cpufreq_platform_cooling_register(struct cpufreq_policy *policy,
|
||||
struct cpu_cooling_ops *ops);
|
||||
|
||||
void cpu_limits_set_level(unsigned int cpu, unsigned int max_freq);
|
||||
|
||||
/**
|
||||
* cpufreq_cooling_unregister - function to remove cpufreq cooling device.
|
||||
* @cdev: thermal cooling device pointer.
|
||||
|
|
Loading…
Add table
Reference in a new issue