From dba1d356246ac40d36d10edc2b699b71af0a6492 Mon Sep 17 00:00:00 2001 From: Hyeonseong Gil Date: Fri, 24 Mar 2017 11:02:47 +0900 Subject: [PATCH] [COMMON] thermal: samsung: Added ECT parsing function Resolved migration conflicts from kernel 4.9 to 4.14. Change-Id: I565316644978e42ccf1aab7532651701df915185 Signed-off-by: Hyeonseong Gil --- drivers/thermal/cpu_cooling.c | 9 ++++ drivers/thermal/gpu_cooling.c | 11 ++++- drivers/thermal/isp_cooling.c | 7 +++ drivers/thermal/of-thermal.c | 15 ++++++ drivers/thermal/samsung/exynos_tmu.c | 70 ++++++++++++++++++++++++++++ include/linux/thermal.h | 5 +- 6 files changed, 114 insertions(+), 3 deletions(-) diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c index e4b41a604124..62edf361912e 100644 --- a/drivers/thermal/cpu_cooling.c +++ b/drivers/thermal/cpu_cooling.c @@ -575,6 +575,14 @@ static int cpufreq_set_cur_state(struct thermal_cooling_device *cdev, return 0; } +static int exynos_cpufreq_cooling_get_level(struct thermal_cooling_device *cdev, + unsigned long value) +{ + struct cpufreq_cooling_device *cpufreq_cdev = cdev->devdata; + + return get_level(cpufreq_cdev, value); +} + /** * cpufreq_get_requested_power() - get the current power * @cdev: &thermal_cooling_device pointer @@ -790,6 +798,7 @@ static struct thermal_cooling_device_ops cpufreq_cooling_ops = { .get_max_state = cpufreq_get_max_state, .get_cur_state = cpufreq_get_cur_state, .set_cur_state = cpufreq_set_cur_state, + .get_cooling_level = exynos_cpufreq_cooling_get_level, }; static struct thermal_cooling_device_ops cpufreq_power_cooling_ops = { diff --git a/drivers/thermal/gpu_cooling.c b/drivers/thermal/gpu_cooling.c index d69b494a577e..e54cf71865ab 100644 --- a/drivers/thermal/gpu_cooling.c +++ b/drivers/thermal/gpu_cooling.c @@ -267,7 +267,7 @@ static u32 gpufreq_cooling_get_freq(unsigned int gpu, unsigned long level) return val; } -EXPORT_SYMBOL_GPL(gpufreq_cooling_get_level); +EXPORT_SYMBOL_GPL(gpufreq_cooling_get_freq); /** * build_dyn_power_table() - create a dynamic power to frequency table @@ -635,6 +635,12 @@ static int gpufreq_set_cur_state(struct thermal_cooling_device *cdev, return gpufreq_apply_cooling(gpufreq_cdev, state); } +static int exynos_gpufreq_cooling_get_level(struct thermal_cooling_device *cdev, + unsigned long value) +{ + return gpufreq_cooling_get_level(0, value); +} + static enum gpu_noti_state_t gpu_tstate = GPU_COLD; static int gpufreq_set_cur_temp(struct thermal_cooling_device *cdev, @@ -806,6 +812,7 @@ static struct thermal_cooling_device_ops gpufreq_cooling_ops = { .get_cur_state = gpufreq_get_cur_state, .set_cur_state = gpufreq_set_cur_state, .set_cur_temp = gpufreq_set_cur_temp, + .get_cooling_level = exynos_gpufreq_cooling_get_level, }; int exynos_gpu_add_notifier(struct notifier_block *n) @@ -1058,6 +1065,7 @@ static int gpu_cooling_table_init(void) pr_info("[GPU cooling] index : %d, frequency : %d\n", gpu_freq_table[count].driver_data, gpu_freq_table[count].frequency); + count++; } @@ -1078,7 +1086,6 @@ static int __init exynos_gpu_cooling_init(void) if (ret) { pr_err("Fail to initialize gpu_cooling_table\n"); return ret; - } np = of_find_node_by_name(NULL, "mali"); diff --git a/drivers/thermal/isp_cooling.c b/drivers/thermal/isp_cooling.c index 0df3cf1f5a5a..8f2100d0d574 100644 --- a/drivers/thermal/isp_cooling.c +++ b/drivers/thermal/isp_cooling.c @@ -217,6 +217,12 @@ unsigned long isp_cooling_get_level(unsigned int isp, unsigned int fps) } EXPORT_SYMBOL_GPL(isp_cooling_get_level); +static int exynos_isp_cooling_get_level(struct thermal_cooling_device *cdev, + unsigned long value) +{ + return isp_cooling_get_level(0, value); +} + /** * isp_cooling_get_fps - for a give isp, return the fps value corresponding to cooling level. * @isp: isp for which the level is required @@ -355,6 +361,7 @@ static struct thermal_cooling_device_ops const isp_cooling_ops = { .get_cur_state = isp_get_cur_state, .set_cur_state = isp_set_cur_state, .set_cur_temp = isp_set_cur_temp, + .get_cooling_level = exynos_isp_cooling_get_level, }; diff --git a/drivers/thermal/of-thermal.c b/drivers/thermal/of-thermal.c index 4ff9bc26970c..04c48f5512a8 100644 --- a/drivers/thermal/of-thermal.c +++ b/drivers/thermal/of-thermal.c @@ -191,6 +191,21 @@ static int of_thermal_bind(struct thermal_zone_device *thermal, if (tbp->cooling_device == cdev->np) { int ret; +#if defined(CONFIG_EXYNOS_THERMAL) + /* if governor is not power_allocator */ + if (strncasecmp(thermal->tzp->governor_name, "power_allocator", + THERMAL_NAME_LENGTH)) { + unsigned long max_level = 0, level = 0; + + cdev->ops->get_max_state(cdev, &max_level); + level = cdev->ops->get_cooling_level(cdev, tbp->value); + + if (level == THERMAL_CSTATE_INVALID) + level = max_level; + + tbp->max = level; + } +#endif ret = thermal_zone_bind_cooling_device(thermal, tbp->trip_id, cdev, tbp->max, diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c index 8ec8450f695e..f7d4a5f39c94 100644 --- a/drivers/thermal/samsung/exynos_tmu.c +++ b/drivers/thermal/samsung/exynos_tmu.c @@ -1615,6 +1615,72 @@ static const struct attribute_group exynos_tmu_attr_group = { .attrs = exynos_tmu_attrs, }; +static int exynos_tmu_parse_ect(struct exynos_tmu_data *data) +{ + struct thermal_zone_device *tz = data->tzd; + struct __thermal_zone *__tz; + void *thermal_block; + struct ect_ap_thermal_function *function; + int i, temperature; + int hotplug_threshold_temp = 0, hotplug_flag = 0; + unsigned int freq; + + if (!tz) + return -EINVAL; + + __tz = (struct __thermal_zone *)tz->devdata; + + thermal_block = ect_get_block(BLOCK_AP_THERMAL); + if (thermal_block == NULL) { + pr_err("Failed to get thermal block"); + return -EINVAL; + } + + pr_info("%s %d thermal zone_name = %s\n", __func__, __LINE__, tz->type); + + function = ect_ap_thermal_get_function(thermal_block, tz->type); + if (function == NULL) { + pr_err("Failed to get thermal block %s", tz->type); + return -EINVAL; + } + + __tz->ntrips = __tz->num_tbps = function->num_of_range; + pr_info("Trip count parsed from ECT : %d, zone : %s", function->num_of_range, tz->type); + + + for (i = 0; i < function->num_of_range; ++i) { + temperature = function->range_list[i].lower_bound_temperature; + freq = function->range_list[i].max_frequency; + __tz->trips[i].temperature = temperature * MCELSIUS; + __tz->tbps[i].value = freq; + + pr_info("Parsed From ECT : [%d] Temperature : %d, frequency : %u\n", + i, temperature, freq); + + if (function->range_list[i].flag != hotplug_flag) { + if (function->range_list[i].flag != hotplug_flag) { + hotplug_threshold_temp = temperature; + hotplug_flag = function->range_list[i].flag; + data->hotplug_out_threshold = temperature; + + if (i) + data->hotplug_in_threshold = function->range_list[i-1].lower_bound_temperature; + + pr_info("[ECT]hotplug_threshold : %d\n", hotplug_threshold_temp); + pr_info("[ECT]hotplug_in_threshold : %d\n", data->hotplug_in_threshold); + pr_info("[ECT]hotplug_out_threshold : %d\n", data->hotplug_out_threshold); + } + } + + if (hotplug_threshold_temp != 0) + data->hotplug_enable = true; + else + data->hotplug_enable = false; + + } + return 0; +}; + #ifdef CONFIG_MALI_DEBUG_KERNEL_SYSFS struct exynos_tmu_data *gpu_thermal_data; #endif @@ -1657,6 +1723,10 @@ static int exynos_tmu_probe(struct platform_device *pdev) goto err_sensor; } +#if defined(CONFIG_ECT) + exynos_tmu_parse_ect(data); +#endif + data->num_probe = (readl(data->base + EXYNOS_TMU_REG_CONTROL1) >> EXYNOS_TMU_NUM_PROBE_SHIFT) & EXYNOS_TMU_NUM_PROBE_MASK; diff --git a/include/linux/thermal.h b/include/linux/thermal.h index 1bee5d04cfce..edb4c69d8b81 100644 --- a/include/linux/thermal.h +++ b/include/linux/thermal.h @@ -144,7 +144,8 @@ struct thermal_cooling_device_ops { struct thermal_zone_device *, unsigned long, u32 *); int (*power2state)(struct thermal_cooling_device *, struct thermal_zone_device *, u32, unsigned long *); - int (*set_cur_temp) (struct thermal_cooling_device *, bool, int); + int (*set_cur_temp)(struct thermal_cooling_device *, bool, int); + int (*get_cooling_level)(struct thermal_cooling_device *, unsigned long); }; struct thermal_cooling_device { @@ -405,6 +406,7 @@ struct thermal_trip { * @usage: the percentage (from 0 to 100) of cooling contribution * @min: minimum cooling state used at this trip point * @max: maximum cooling state used at this trip point + * @value: cooling value corresponding to max state */ struct __thermal_bind_params { @@ -413,6 +415,7 @@ struct __thermal_bind_params { unsigned int usage; unsigned long min; unsigned long max; + unsigned long value; }; /** -- 2.20.1