From b58c886b7219ade03de6996c506c1faecc583af5 Mon Sep 17 00:00:00 2001 From: Hyeonseong Gil Date: Tue, 15 Nov 2016 11:02:45 +0900 Subject: [PATCH] [COMMON] thermal: samsung: Introduce balance mode for DTM v0.2.2 Resolved migration conflicts from kernel 4.9 to 4.14. - Move sysfs attrs to thermal_sysfs.c Change-Id: I100b28897f45e00c8d1b8bc4d62949ac5d1ddb03 Signed-off-by: Hyeonseong Gil --- drivers/thermal/samsung/exynos_tmu.c | 167 +++++++++++++++++++++++++++ drivers/thermal/samsung/exynos_tmu.h | 3 + drivers/thermal/thermal_sysfs.c | 2 + 3 files changed, 172 insertions(+) diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c index e3af8479ff5f..5767be2e60f1 100644 --- a/drivers/thermal/samsung/exynos_tmu.c +++ b/drivers/thermal/samsung/exynos_tmu.c @@ -141,6 +141,7 @@ #define EXYNOS_TMU_NUM_PROBE_MASK (0x7) #define TOTAL_SENSORS 8 +#define DEFAULT_BALANCE_OFFSET 20 static bool suspended; static bool is_cpu_hotplugged_out; @@ -886,6 +887,15 @@ static int exynos8895_tmu_read(struct exynos_tmu_data *data) break; case MIN : result = result < temp_cel ? result : temp_cel; break; + case BALANCE: + if (data->sensor_info[i].sensor_num != 0) { + if (temp_cel >= data->balance_offset) + temp_cel = temp_cel - data->balance_offset; + else + temp_cel = 0; + } + result = result > temp_cel ? result : temp_cel; + break; default : result = temp_cel; break; } @@ -899,6 +909,7 @@ static int exynos8895_tmu_read(struct exynos_tmu_data *data) break; case MAX : case MIN : + case BALANCE: default : break; } @@ -1108,6 +1119,8 @@ static int exynos_map_dt_data(struct platform_device *pdev) data->sensing_mode = i; } + data->balance_offset = DEFAULT_BALANCE_OFFSET; + data->hotplug_enable = of_property_read_bool(pdev->dev.of_node, "hotplug_enable"); if (data->hotplug_enable) { dev_info(&pdev->dev, "thermal zone use hotplug function \n"); @@ -1419,6 +1432,156 @@ static int exynos_isp_cooling_register(struct exynos_tmu_data *data) static int exynos_isp_cooling_register(struct exynos_tmu_data *data) {return 0;} #endif +static ssize_t +balance_offset_show(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + struct platform_device *pdev = to_platform_device(dev); + struct exynos_tmu_data *data = platform_get_drvdata(pdev); + + return snprintf(buf, PAGE_SIZE, "%d\n", data->balance_offset); +} + +static ssize_t +balance_offset_store(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + struct platform_device *pdev = to_platform_device(dev); + struct exynos_tmu_data *data = platform_get_drvdata(pdev); + int balance_offset = 0; + + mutex_lock(&data->lock); + + if (kstrtos32(buf, 10, &balance_offset)) { + mutex_unlock(&data->lock); + return -EINVAL; + } + + data->balance_offset = balance_offset; + + mutex_unlock(&data->lock); + + return count; +} + +static ssize_t +all_temp_show(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + struct platform_device *pdev = to_platform_device(dev); + struct exynos_tmu_data *data = platform_get_drvdata(pdev); + int i, len = 0; + u32 reg_offset, bit_offset; + u32 temp_code, temp_cel; + + for (i = 0; i < data->num_of_sensors; i++) { + if (data->sensor_info[i].sensor_num < 2) { + reg_offset = 0; + bit_offset = EXYNOS_TMU_TEMP_SHIFT * data->sensor_info[i].sensor_num; + } else { + reg_offset = ((data->sensor_info[i].sensor_num - 2) / 3 + 1) * 4; + bit_offset = EXYNOS_TMU_TEMP_SHIFT * ((data->sensor_info[i].sensor_num - 2) % 3); + } + + temp_code = (readl(data->base + EXYNOS_TMU_REG_CURRENT_TEMP1_0 + reg_offset) + >> bit_offset) & EXYNOS_TMU_TEMP_MASK; + temp_cel = code_to_temp_with_sensorinfo(data, temp_code, &data->sensor_info[i]); + + len += snprintf(&buf[len], PAGE_SIZE, "%u, ", temp_cel); + } + + len += snprintf(&buf[len], PAGE_SIZE, "\n"); + + return len; +} + +static ssize_t +hotplug_out_temp_show(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + struct platform_device *pdev = to_platform_device(dev); + struct exynos_tmu_data *data = platform_get_drvdata(pdev); + + return snprintf(buf, PAGE_SIZE, "%d\n", data->hotplug_out_threshold); +} + +static ssize_t +hotplug_out_temp_store(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + struct platform_device *pdev = to_platform_device(dev); + struct exynos_tmu_data *data = platform_get_drvdata(pdev); + int hotplug_out = 0; + + mutex_lock(&data->lock); + + if (kstrtos32(buf, 10, &hotplug_out)) { + mutex_unlock(&data->lock); + return -EINVAL; + } + + data->hotplug_out_threshold = hotplug_out; + + mutex_unlock(&data->lock); + + return count; +} + +static ssize_t +hotplug_in_temp_show(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + struct platform_device *pdev = to_platform_device(dev); + struct exynos_tmu_data *data = platform_get_drvdata(pdev); + + return snprintf(buf, PAGE_SIZE, "%d\n", data->hotplug_in_threshold); +} + +static ssize_t +hotplug_in_temp_store(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + struct platform_device *pdev = to_platform_device(dev); + struct exynos_tmu_data *data = platform_get_drvdata(pdev); + int hotplug_in = 0; + + mutex_lock(&data->lock); + + if (kstrtos32(buf, 10, &hotplug_in)) { + mutex_unlock(&data->lock); + return -EINVAL; + } + + data->hotplug_in_threshold = hotplug_in; + + mutex_unlock(&data->lock); + + return count; +} + +static DEVICE_ATTR(balance_offset, S_IWUSR | S_IRUGO, balance_offset_show, + balance_offset_store); + +static DEVICE_ATTR(all_temp, S_IRUGO, all_temp_show, NULL); + +static DEVICE_ATTR(hotplug_out_temp, S_IWUSR | S_IRUGO, hotplug_out_temp_show, + hotplug_out_temp_store); + +static DEVICE_ATTR(hotplug_in_temp, S_IWUSR | S_IRUGO, hotplug_in_temp_show, + hotplug_in_temp_store); + +static struct attribute *exynos_tmu_attrs[] = { + &dev_attr_balance_offset.attr, + &dev_attr_all_temp.attr, + &dev_attr_hotplug_out_temp.attr, + &dev_attr_hotplug_in_temp.attr, + NULL, +}; + +static const struct attribute_group exynos_tmu_attr_group = { + .attrs = exynos_tmu_attrs, +}; + static int exynos_tmu_probe(struct platform_device *pdev) { struct exynos_tmu_data *data; @@ -1507,6 +1670,10 @@ static int exynos_tmu_probe(struct platform_device *pdev) exynos_tmu_control(pdev, true); + ret = sysfs_create_group(&pdev->dev.kobj, &exynos_tmu_attr_group); + if (ret) + dev_err(&pdev->dev, "cannot create exynos tmu attr group"); + mutex_lock(&data->lock); list_add_tail(&data->node, &dtm_dev_list); mutex_unlock(&data->lock); diff --git a/drivers/thermal/samsung/exynos_tmu.h b/drivers/thermal/samsung/exynos_tmu.h index d5142e2255f1..f541f6b83067 100644 --- a/drivers/thermal/samsung/exynos_tmu.h +++ b/drivers/thermal/samsung/exynos_tmu.h @@ -71,6 +71,7 @@ enum sensing_type { AVG = 0, MAX, MIN, + BALANCE, END_OF_TYPE, }; @@ -78,6 +79,7 @@ static const char * const sensing_method[] = { [AVG] = "avg", [MAX] = "max", [MIN] = "min", + [BALANCE] = "balance", }; enum thermal_zone_name { @@ -154,6 +156,7 @@ struct exynos_tmu_data { int sensing_mode; char tmu_name[THERMAL_NAME_LENGTH]; struct device_node *np; + int balance_offset; int (*tmu_initialize)(struct platform_device *pdev); void (*tmu_control)(struct platform_device *pdev, bool on); diff --git a/drivers/thermal/thermal_sysfs.c b/drivers/thermal/thermal_sysfs.c index fb80c96d8f73..f76446e3f7a7 100644 --- a/drivers/thermal/thermal_sysfs.c +++ b/drivers/thermal/thermal_sysfs.c @@ -389,6 +389,7 @@ create_s32_tzp_attr(k_d); create_s32_tzp_attr(integral_cutoff); create_s32_tzp_attr(slope); create_s32_tzp_attr(offset); +create_s32_tzp_attr(integral_max); #undef create_s32_tzp_attr /* @@ -424,6 +425,7 @@ static struct attribute *thermal_zone_dev_attrs[] = { &dev_attr_integral_cutoff.attr, &dev_attr_slope.attr, &dev_attr_offset.attr, + &dev_attr_integral_max.attr, NULL, }; -- 2.20.1