From eb42612f95d41fcc7644754f60c3d2b30153bc75 Mon Sep 17 00:00:00 2001 From: Pravin Shedge Date: Wed, 6 Dec 2017 22:10:05 +0530 Subject: drivers: thermal: remove duplicate includes These duplicate includes have been found with scripts/checkincludes.pl but they have been removed manually to avoid removing false positives. Signed-off-by: Pravin Shedge Signed-off-by: Zhang Rui --- drivers/thermal/of-thermal.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/thermal') diff --git a/drivers/thermal/of-thermal.c b/drivers/thermal/of-thermal.c index d04ec3b9e5ff..e09f0354a4bc 100644 --- a/drivers/thermal/of-thermal.c +++ b/drivers/thermal/of-thermal.c @@ -30,7 +30,6 @@ #include #include #include -#include #include "thermal_core.h" -- cgit From a5de11d67dcd268b8d0beb73dc374de5e97f0caf Mon Sep 17 00:00:00 2001 From: Yi Zeng Date: Tue, 26 Dec 2017 19:22:26 +0800 Subject: thermal: power_allocator: fix one race condition issue for thermal_instances list When invoking allow_maximum_power and traverse tz->thermal_instances, we should grab thermal_zone_device->lock to avoid race condition. For example, during the system reboot, if the mali GPU device implements device shutdown callback and unregister GPU devfreq cooling device, the deleted list head may be accessed to cause panic, as the following log shows: [ 33.551070] c3 25 (kworker/3:0) Unable to handle kernel paging request at virtual address dead000000000070 [ 33.566708] c3 25 (kworker/3:0) pgd = ffffffc0ed290000 [ 33.572071] c3 25 (kworker/3:0) [dead000000000070] *pgd=00000001ed292003, *pud=00000001ed292003, *pmd=0000000000000000 [ 33.581515] c3 25 (kworker/3:0) Internal error: Oops: 96000004 [#1] PREEMPT SMP [ 33.599761] c3 25 (kworker/3:0) CPU: 3 PID: 25 Comm: kworker/3:0 Not tainted 4.4.35+ #912 [ 33.614137] c3 25 (kworker/3:0) Workqueue: events_freezable thermal_zone_device_check [ 33.620245] c3 25 (kworker/3:0) task: ffffffc0f32e4200 ti: ffffffc0f32f0000 task.ti: ffffffc0f32f0000 [ 33.629466] c3 25 (kworker/3:0) PC is at power_allocator_throttle+0x7c8/0x8a4 [ 33.636609] c3 25 (kworker/3:0) LR is at power_allocator_throttle+0x808/0x8a4 [ 33.643742] c3 25 (kworker/3:0) pc : [] lr : [] pstate: 20000145 [ 33.652874] c3 25 (kworker/3:0) sp : ffffffc0f32f3bb0 [ 34.468519] c3 25 (kworker/3:0) Process kworker/3:0 (pid: 25, stack limit = 0xffffffc0f32f0020) [ 34.477220] c3 25 (kworker/3:0) Stack: (0xffffffc0f32f3bb0 to 0xffffffc0f32f4000) [ 34.819822] c3 25 (kworker/3:0) Call trace: [ 34.824021] c3 25 (kworker/3:0) Exception stack(0xffffffc0f32f39c0 to 0xffffffc0f32f3af0) [ 34.924993] c3 25 (kworker/3:0) [] power_allocator_throttle+0x7c8/0x8a4 [ 34.933184] c3 25 (kworker/3:0) [] handle_thermal_trip.part.25+0x70/0x224 [ 34.941545] c3 25 (kworker/3:0) [] thermal_zone_device_update+0xc0/0x20c [ 34.949818] c3 25 (kworker/3:0) [] thermal_zone_device_check+0x20/0x2c [ 34.957924] c3 25 (kworker/3:0) [] process_one_work+0x168/0x458 [ 34.965414] c3 25 (kworker/3:0) [] worker_thread+0x13c/0x4b4 [ 34.972650] c3 25 (kworker/3:0) [] kthread+0xe8/0xfc [ 34.979187] c3 25 (kworker/3:0) [] ret_from_fork+0x10/0x40 [ 34.986244] c3 25 (kworker/3:0) Code: f9405e73 eb1302bf d102e273 54ffc460 (b9402a61) [ 34.994339] c3 25 (kworker/3:0) ---[ end trace 32057901e3b7e1db ]--- Signed-off-by: Yi Zeng Signed-off-by: Zhang Rui --- drivers/thermal/power_allocator.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/thermal') diff --git a/drivers/thermal/power_allocator.c b/drivers/thermal/power_allocator.c index b4d3116cfdaf..3055f9a12a17 100644 --- a/drivers/thermal/power_allocator.c +++ b/drivers/thermal/power_allocator.c @@ -523,6 +523,7 @@ static void allow_maximum_power(struct thermal_zone_device *tz) struct thermal_instance *instance; struct power_allocator_params *params = tz->governor_data; + mutex_lock(&tz->lock); list_for_each_entry(instance, &tz->thermal_instances, tz_node) { if ((instance->trip != params->trip_max_desired_temperature) || (!cdev_is_power_actor(instance->cdev))) @@ -534,6 +535,7 @@ static void allow_maximum_power(struct thermal_zone_device *tz) mutex_unlock(&instance->cdev->lock); thermal_cdev_update(instance->cdev); } + mutex_unlock(&tz->lock); } /** -- cgit From 261ac1d2d9ef9a29c57f8aff341ae3dc323a707c Mon Sep 17 00:00:00 2001 From: Brian Bian Date: Tue, 14 Nov 2017 09:36:36 -0800 Subject: thermal: int3400_thermal: Ignore Unknown Notification Codes Some BIOS implementations route ACPI codes other than 0x83 to INT3400 device. Ignore these ACPI notification codes because the INT3400 driver does not handle them. Signed-off-by: Brian Bian Signed-off-by: Zhang Rui --- drivers/thermal/int340x_thermal/int3400_thermal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/thermal') diff --git a/drivers/thermal/int340x_thermal/int3400_thermal.c b/drivers/thermal/int340x_thermal/int3400_thermal.c index 8ee38f55c7f3..c9db1c643501 100644 --- a/drivers/thermal/int340x_thermal/int3400_thermal.c +++ b/drivers/thermal/int340x_thermal/int3400_thermal.c @@ -211,7 +211,7 @@ static void int3400_notify(acpi_handle handle, thermal_prop); break; default: - dev_err(&priv->adev->dev, "Unsupported event [0x%x]\n", event); + /* Ignore unknown notification codes sent to INT3400 device */ break; } } -- cgit From d790405d1b23cf1495d22ed043a422dc44bb6848 Mon Sep 17 00:00:00 2001 From: Nicolin Chen Date: Wed, 25 Oct 2017 00:03:37 -0700 Subject: thermal: tegra: remove forward declarations This patch just simply moves tegra_thermctl_set_trip_temp() behind those function implementations so that it can remove those forward declarations. Signed-off-by: Nicolin Chen Signed-off-by: Eduardo Valentin --- drivers/thermal/tegra/soctherm.c | 103 ++++++++++++++++++--------------------- 1 file changed, 47 insertions(+), 56 deletions(-) (limited to 'drivers/thermal') diff --git a/drivers/thermal/tegra/soctherm.c b/drivers/thermal/tegra/soctherm.c index 075db1de5e53..455b58ce2652 100644 --- a/drivers/thermal/tegra/soctherm.c +++ b/drivers/thermal/tegra/soctherm.c @@ -341,62 +341,6 @@ static int tegra_thermctl_get_temp(void *data, int *out_temp) return 0; } -static int -thermtrip_program(struct device *dev, const struct tegra_tsensor_group *sg, - int trip_temp); -static int -throttrip_program(struct device *dev, const struct tegra_tsensor_group *sg, - struct soctherm_throt_cfg *stc, int trip_temp); -static struct soctherm_throt_cfg * -find_throttle_cfg_by_name(struct tegra_soctherm *ts, const char *name); - -static int tegra_thermctl_set_trip_temp(void *data, int trip, int temp) -{ - struct tegra_thermctl_zone *zone = data; - struct thermal_zone_device *tz = zone->tz; - struct tegra_soctherm *ts = zone->ts; - const struct tegra_tsensor_group *sg = zone->sg; - struct device *dev = zone->dev; - enum thermal_trip_type type; - int ret; - - if (!tz) - return -EINVAL; - - ret = tz->ops->get_trip_type(tz, trip, &type); - if (ret) - return ret; - - if (type == THERMAL_TRIP_CRITICAL) { - return thermtrip_program(dev, sg, temp); - } else if (type == THERMAL_TRIP_HOT) { - int i; - - for (i = 0; i < THROTTLE_SIZE; i++) { - struct thermal_cooling_device *cdev; - struct soctherm_throt_cfg *stc; - - if (!ts->throt_cfgs[i].init) - continue; - - cdev = ts->throt_cfgs[i].cdev; - if (get_thermal_instance(tz, cdev, trip)) - stc = find_throttle_cfg_by_name(ts, cdev->type); - else - continue; - - return throttrip_program(dev, sg, stc, temp); - } - } - - return 0; -} - -static const struct thermal_zone_of_device_ops tegra_of_thermal_ops = { - .get_temp = tegra_thermctl_get_temp, - .set_trip_temp = tegra_thermctl_set_trip_temp, -}; - /** * enforce_temp_range() - check and enforce temperature range [min, max] * @trip_temp: the trip temperature to check @@ -527,6 +471,53 @@ find_throttle_cfg_by_name(struct tegra_soctherm *ts, const char *name) return NULL; } +static int tegra_thermctl_set_trip_temp(void *data, int trip, int temp) +{ + struct tegra_thermctl_zone *zone = data; + struct thermal_zone_device *tz = zone->tz; + struct tegra_soctherm *ts = zone->ts; + const struct tegra_tsensor_group *sg = zone->sg; + struct device *dev = zone->dev; + enum thermal_trip_type type; + int ret; + + if (!tz) + return -EINVAL; + + ret = tz->ops->get_trip_type(tz, trip, &type); + if (ret) + return ret; + + if (type == THERMAL_TRIP_CRITICAL) { + return thermtrip_program(dev, sg, temp); + } else if (type == THERMAL_TRIP_HOT) { + int i; + + for (i = 0; i < THROTTLE_SIZE; i++) { + struct thermal_cooling_device *cdev; + struct soctherm_throt_cfg *stc; + + if (!ts->throt_cfgs[i].init) + continue; + + cdev = ts->throt_cfgs[i].cdev; + if (get_thermal_instance(tz, cdev, trip)) + stc = find_throttle_cfg_by_name(ts, cdev->type); + else + continue; + + return throttrip_program(dev, sg, stc, temp); + } + } + + return 0; +} + +static const struct thermal_zone_of_device_ops tegra_of_thermal_ops = { + .get_temp = tegra_thermctl_get_temp, + .set_trip_temp = tegra_thermctl_set_trip_temp, +}; + static int get_hot_temp(struct thermal_zone_device *tz, int *trip, int *temp) { int ntrips, i, ret; -- cgit From e4bb2240d4db6188f2e88610a68bda12e2bc98e1 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Thu, 30 Nov 2017 10:17:35 +0100 Subject: thermal: imx: Use better parameter names than "val" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The values passed to imx_init_calib() and imx_init_temp_grade() are read from specific OCOTP values. Use their names (in lower case) as parameter name instead of "val" to make the code easier to understand. Signed-off-by: Uwe Kleine-König Signed-off-by: Eduardo Valentin --- drivers/thermal/imx_thermal.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/thermal') diff --git a/drivers/thermal/imx_thermal.c b/drivers/thermal/imx_thermal.c index e7d4ffc3de7f..21b8c4c4da3c 100644 --- a/drivers/thermal/imx_thermal.c +++ b/drivers/thermal/imx_thermal.c @@ -347,13 +347,13 @@ static struct thermal_zone_device_ops imx_tz_ops = { .set_trip_temp = imx_set_trip_temp, }; -static int imx_init_calib(struct platform_device *pdev, u32 val) +static int imx_init_calib(struct platform_device *pdev, u32 ocotp_ana1) { struct imx_thermal_data *data = platform_get_drvdata(pdev); int t1, n1; u64 temp64; - if (val == 0 || val == ~0) { + if (ocotp_ana1 == 0 || ocotp_ana1 == ~0) { dev_err(&pdev->dev, "invalid sensor calibration data\n"); return -EINVAL; } @@ -364,7 +364,7 @@ static int imx_init_calib(struct platform_device *pdev, u32 val) * Use universal formula now and only need sensor value @ 25C * slope = 0.4297157 - (0.0015976 * 25C fuse) */ - n1 = val >> 20; + n1 = ocotp_ana1 >> 20; t1 = 25; /* t1 always 25C */ /* @@ -392,12 +392,12 @@ static int imx_init_calib(struct platform_device *pdev, u32 val) return 0; } -static void imx_init_temp_grade(struct platform_device *pdev, u32 val) +static void imx_init_temp_grade(struct platform_device *pdev, u32 ocotp_mem0) { struct imx_thermal_data *data = platform_get_drvdata(pdev); /* The maximum die temp is specified by the Temperature Grade */ - switch ((val >> 6) & 0x3) { + switch ((ocotp_mem0 >> 6) & 0x3) { case 0: /* Commercial (0 to 95C) */ data->temp_grade = "Commercial"; data->temp_max = 95000; -- cgit From c5bbdb4ba30977a30f485e66c8af9b4c44f3798e Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Thu, 30 Nov 2017 10:17:36 +0100 Subject: thermal: imx: improve comments describing algorithm for temp calculation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The description of the implemented algorithm is hardly understandable without having the right application note side-by-side to the code. Fix this by using shorter and more intuitive variable names, describe their meaning and transform a single formula instead of first talking about slope and then about "milli_Tmeas". There are no code changes. Reviewed-by: Leonard Crestez Signed-off-by: Uwe Kleine-König Signed-off-by: Eduardo Valentin --- drivers/thermal/imx_thermal.c | 42 +++++++++++++++++++----------------------- 1 file changed, 19 insertions(+), 23 deletions(-) (limited to 'drivers/thermal') diff --git a/drivers/thermal/imx_thermal.c b/drivers/thermal/imx_thermal.c index 21b8c4c4da3c..c08883dff2cb 100644 --- a/drivers/thermal/imx_thermal.c +++ b/drivers/thermal/imx_thermal.c @@ -359,32 +359,28 @@ static int imx_init_calib(struct platform_device *pdev, u32 ocotp_ana1) } /* - * Sensor data layout: - * [31:20] - sensor value @ 25C - * Use universal formula now and only need sensor value @ 25C - * slope = 0.4297157 - (0.0015976 * 25C fuse) + * The sensor is calibrated at 25 °C (aka T1) and the value measured + * (aka N1) at this temperature is provided in bits [31:20] in the + * i.MX's OCOTP value ANA1. + * To find the actual temperature T, the following formula has to be used + * when reading value n from the sensor: + * + * T = T1 + (N - N1) / (0.4297157 - 0.0015976 * N1) °C + * = [T1 - N1 / (0.4297157 - 0.0015976 * N1) °C] + N / (0.4297157 - 0.0015976 * N1) °C + * = [T1 + N1 / (0.0015976 * N1 - 0.4297157) °C] - N / (0.0015976 * N1 - 0.4297157) °C + * = c2 - c1 * N + * + * with + * + * c1 = 1 / (0.0015976 * N1 - 0.4297157) °C + * c2 = T1 + N1 / (0.0015976 * N1 - 0.4297157) °C + * = T1 + N1 * C1 */ n1 = ocotp_ana1 >> 20; - t1 = 25; /* t1 always 25C */ + t1 = 25; /* °C */ - /* - * Derived from linear interpolation: - * slope = 0.4297157 - (0.0015976 * 25C fuse) - * slope = (FACTOR2 - FACTOR1 * n1) / FACTOR0 - * (Nmeas - n1) / (Tmeas - t1) = slope - * We want to reduce this down to the minimum computation necessary - * for each temperature read. Also, we want Tmeas in millicelsius - * and we don't want to lose precision from integer division. So... - * Tmeas = (Nmeas - n1) / slope + t1 - * milli_Tmeas = 1000 * (Nmeas - n1) / slope + 1000 * t1 - * milli_Tmeas = -1000 * (n1 - Nmeas) / slope + 1000 * t1 - * Let constant c1 = (-1000 / slope) - * milli_Tmeas = (n1 - Nmeas) * c1 + 1000 * t1 - * Let constant c2 = n1 *c1 + 1000 * t1 - * milli_Tmeas = c2 - Nmeas * c1 - */ - temp64 = FACTOR0; - temp64 *= 1000; + temp64 = FACTOR0; /* 10^7 for FACTOR1 and FACTOR2 */ + temp64 *= 1000; /* to get result in °mC */ do_div(temp64, FACTOR1 * n1 - FACTOR2); data->c1 = temp64; data->c2 = n1 * data->c1 + 1000 * t1; -- cgit From 339d7492dbfd76b7ed67366ba7c062c4fb61e560 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Thu, 30 Nov 2017 10:17:37 +0100 Subject: thermal: imx: use consistent style to write temperatures MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous commit already took care to use the right notation for temperatures. Add correct units to all values representing temperatures in the right notation for the rest of the file. Signed-off-by: Uwe Kleine-König Signed-off-by: Eduardo Valentin --- drivers/thermal/imx_thermal.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/thermal') diff --git a/drivers/thermal/imx_thermal.c b/drivers/thermal/imx_thermal.c index c08883dff2cb..41e15cf5ffd7 100644 --- a/drivers/thermal/imx_thermal.c +++ b/drivers/thermal/imx_thermal.c @@ -394,27 +394,27 @@ static void imx_init_temp_grade(struct platform_device *pdev, u32 ocotp_mem0) /* The maximum die temp is specified by the Temperature Grade */ switch ((ocotp_mem0 >> 6) & 0x3) { - case 0: /* Commercial (0 to 95C) */ + case 0: /* Commercial (0 to 95 °C) */ data->temp_grade = "Commercial"; data->temp_max = 95000; break; - case 1: /* Extended Commercial (-20 to 105C) */ + case 1: /* Extended Commercial (-20 °C to 105 °C) */ data->temp_grade = "Extended Commercial"; data->temp_max = 105000; break; - case 2: /* Industrial (-40 to 105C) */ + case 2: /* Industrial (-40 °C to 105 °C) */ data->temp_grade = "Industrial"; data->temp_max = 105000; break; - case 3: /* Automotive (-40 to 125C) */ + case 3: /* Automotive (-40 °C to 125 °C) */ data->temp_grade = "Automotive"; data->temp_max = 125000; break; } /* - * Set the critical trip point at 5C under max - * Set the passive trip point at 10C under max (can change via sysfs) + * Set the critical trip point at 5 °C under max + * Set the passive trip point at 10 °C under max (changeable via sysfs) */ data->temp_critical = data->temp_max - (1000 * 5); data->temp_passive = data->temp_max - (1000 * 10); -- cgit From 4e5f61ca11e716c2a46e163bd0286cb8950dc087 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Thu, 30 Nov 2017 10:17:38 +0100 Subject: thermal: imx: update to new formula according to NXP AN5215 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to an application note from 03/2017 there is an updated formula to calculate the temperature that better matches reality. This is implemented here. While updating move the magic constants from cpp defines which are far above the explaining formula to constants in the code just under the explaining comment. Reviewed-by: Leonard Crestez Signed-off-by: Uwe Kleine-König Signed-off-by: Eduardo Valentin --- drivers/thermal/imx_thermal.c | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) (limited to 'drivers/thermal') diff --git a/drivers/thermal/imx_thermal.c b/drivers/thermal/imx_thermal.c index 41e15cf5ffd7..a67781b7a0b2 100644 --- a/drivers/thermal/imx_thermal.c +++ b/drivers/thermal/imx_thermal.c @@ -70,10 +70,6 @@ enum imx_thermal_trip { #define IMX_POLLING_DELAY 2000 /* millisecond */ #define IMX_PASSIVE_DELAY 1000 -#define FACTOR0 10000000 -#define FACTOR1 15976 -#define FACTOR2 4297157 - #define TEMPMON_IMX6Q 1 #define TEMPMON_IMX6SX 2 @@ -350,7 +346,7 @@ static struct thermal_zone_device_ops imx_tz_ops = { static int imx_init_calib(struct platform_device *pdev, u32 ocotp_ana1) { struct imx_thermal_data *data = platform_get_drvdata(pdev); - int t1, n1; + int n1; u64 temp64; if (ocotp_ana1 == 0 || ocotp_ana1 == ~0) { @@ -365,25 +361,25 @@ static int imx_init_calib(struct platform_device *pdev, u32 ocotp_ana1) * To find the actual temperature T, the following formula has to be used * when reading value n from the sensor: * - * T = T1 + (N - N1) / (0.4297157 - 0.0015976 * N1) °C - * = [T1 - N1 / (0.4297157 - 0.0015976 * N1) °C] + N / (0.4297157 - 0.0015976 * N1) °C - * = [T1 + N1 / (0.0015976 * N1 - 0.4297157) °C] - N / (0.0015976 * N1 - 0.4297157) °C + * T = T1 + (N - N1) / (0.4148468 - 0.0015423 * N1) °C + 3.580661 °C + * = [T1' - N1 / (0.4148468 - 0.0015423 * N1) °C] + N / (0.4148468 - 0.0015423 * N1) °C + * = [T1' + N1 / (0.0015423 * N1 - 0.4148468) °C] - N / (0.0015423 * N1 - 0.4148468) °C * = c2 - c1 * N * * with * - * c1 = 1 / (0.0015976 * N1 - 0.4297157) °C - * c2 = T1 + N1 / (0.0015976 * N1 - 0.4297157) °C - * = T1 + N1 * C1 + * T1' = 28.580661 °C + * c1 = 1 / (0.0015423 * N1 - 0.4297157) °C + * c2 = T1' + N1 / (0.0015423 * N1 - 0.4148468) °C + * = T1' + N1 * c1 */ n1 = ocotp_ana1 >> 20; - t1 = 25; /* °C */ - temp64 = FACTOR0; /* 10^7 for FACTOR1 and FACTOR2 */ + temp64 = 10000000; /* use 10^7 as fixed point constant for values in formula */ temp64 *= 1000; /* to get result in °mC */ - do_div(temp64, FACTOR1 * n1 - FACTOR2); + do_div(temp64, 15423 * n1 - 4148468); data->c1 = temp64; - data->c2 = n1 * data->c1 + 1000 * t1; + data->c2 = n1 * data->c1 + 28581; return 0; } -- cgit From f45ce7ee005de104519686f5fc1b3163fa7b8f8f Mon Sep 17 00:00:00 2001 From: Matthias Brugger Date: Fri, 1 Dec 2017 11:43:21 +0100 Subject: thermal: mtk: Cleanup unused defines The mtk_thermal has some defiens which are never used within the driver. This patch delets them. Signed-off-by: Matthias Brugger Acked-by: Daniel Lezcano Signed-off-by: Eduardo Valentin --- drivers/thermal/mtk_thermal.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'drivers/thermal') diff --git a/drivers/thermal/mtk_thermal.c b/drivers/thermal/mtk_thermal.c index 1e61c09153c9..c75661a3801a 100644 --- a/drivers/thermal/mtk_thermal.c +++ b/drivers/thermal/mtk_thermal.c @@ -32,15 +32,10 @@ #include /* AUXADC Registers */ -#define AUXADC_CON0_V 0x000 -#define AUXADC_CON1_V 0x004 #define AUXADC_CON1_SET_V 0x008 #define AUXADC_CON1_CLR_V 0x00c #define AUXADC_CON2_V 0x010 #define AUXADC_DATA(channel) (0x14 + (channel) * 4) -#define AUXADC_MISC_V 0x094 - -#define AUXADC_CON1_CHANNEL(x) BIT(x) #define APMIXED_SYS_TS_CON1 0x604 @@ -158,8 +153,6 @@ /* The number of sensing points per bank */ #define MT2712_NUM_SENSORS_PER_ZONE 4 -#define THERMAL_NAME "mtk-thermal" - struct mtk_thermal; struct thermal_bank_cfg { @@ -765,7 +758,7 @@ static struct platform_driver mtk_thermal_driver = { .probe = mtk_thermal_probe, .remove = mtk_thermal_remove, .driver = { - .name = THERMAL_NAME, + .name = "mtk-thermal", .of_match_table = mtk_thermal_of_match, }, }; -- cgit From 7f3be017a88a7b351def8c3e7e4cb37dea2974b7 Mon Sep 17 00:00:00 2001 From: Baruch Siach Date: Fri, 22 Dec 2017 17:14:04 +0100 Subject: thermal: armada: Use msleep for long delays Use msleep for long (> 10ms) delays, instead of the busy waiting mdelay. All delays are called from the probe routine, where scheduling is allowed. Signed-off-by: Baruch Siach Signed-off-by: Miquel Raynal Reviewed-by: Gregory CLEMENT Signed-off-by: Eduardo Valentin --- drivers/thermal/armada_thermal.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/thermal') diff --git a/drivers/thermal/armada_thermal.c b/drivers/thermal/armada_thermal.c index 706d74798cbe..6c4af2622d4f 100644 --- a/drivers/thermal/armada_thermal.c +++ b/drivers/thermal/armada_thermal.c @@ -113,7 +113,7 @@ static void armada370_init_sensor(struct platform_device *pdev, reg &= ~PMU_TDC0_START_CAL_MASK; writel(reg, priv->control); - mdelay(10); + msleep(10); } static void armada375_init_sensor(struct platform_device *pdev, @@ -127,11 +127,11 @@ static void armada375_init_sensor(struct platform_device *pdev, reg &= ~A375_HW_RESETn; writel(reg, priv->control + 4); - mdelay(20); + msleep(20); reg |= A375_HW_RESETn; writel(reg, priv->control + 4); - mdelay(50); + msleep(50); } static void armada380_init_sensor(struct platform_device *pdev, @@ -143,7 +143,7 @@ static void armada380_init_sensor(struct platform_device *pdev, if (!(reg & A380_HW_RESET)) { reg |= A380_HW_RESET; writel(reg, priv->control); - mdelay(10); + msleep(10); } } -- cgit From 27d92f27ae6c187978eb497fb5f366e7cb807d36 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Fri, 22 Dec 2017 17:14:05 +0100 Subject: thermal: armada: Simplify the check of the validity bit All Armada SoCs use one bit to declare if the sensor values are valid. This bit moves across the versions of the IP. The method until then was to do both a shift and compare with an useless flag of "0x1". It is clearer and quicker to directly save the value that must be ANDed instead of the bit position and do a single bitwise AND operation. Signed-off-by: Miquel Raynal Reviewed-by: Gregory CLEMENT Signed-off-by: Eduardo Valentin --- drivers/thermal/armada_thermal.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'drivers/thermal') diff --git a/drivers/thermal/armada_thermal.c b/drivers/thermal/armada_thermal.c index 6c4af2622d4f..f350d7efd35a 100644 --- a/drivers/thermal/armada_thermal.c +++ b/drivers/thermal/armada_thermal.c @@ -24,8 +24,6 @@ #include #include -#define THERMAL_VALID_MASK 0x1 - /* Thermal Manager Control and Status Register */ #define PMU_TDC0_SW_RST_MASK (0x1 << 1) #define PMU_TM_DISABLE_OFFS 0 @@ -67,7 +65,7 @@ struct armada_thermal_data { /* Register shift and mask to access the sensor temperature */ unsigned int temp_shift; unsigned int temp_mask; - unsigned int is_valid_shift; + u32 is_valid_bit; }; static void armadaxp_init_sensor(struct platform_device *pdev, @@ -149,9 +147,9 @@ static void armada380_init_sensor(struct platform_device *pdev, static bool armada_is_valid(struct armada_thermal_priv *priv) { - unsigned long reg = readl_relaxed(priv->sensor); + u32 reg = readl_relaxed(priv->sensor); - return (reg >> priv->data->is_valid_shift) & THERMAL_VALID_MASK; + return reg & priv->data->is_valid_bit; } static int armada_get_temp(struct thermal_zone_device *thermal, @@ -199,7 +197,7 @@ static const struct armada_thermal_data armadaxp_data = { static const struct armada_thermal_data armada370_data = { .is_valid = armada_is_valid, .init_sensor = armada370_init_sensor, - .is_valid_shift = 9, + .is_valid_bit = BIT(9), .temp_shift = 10, .temp_mask = 0x1ff, .coef_b = 3153000000UL, @@ -210,7 +208,7 @@ static const struct armada_thermal_data armada370_data = { static const struct armada_thermal_data armada375_data = { .is_valid = armada_is_valid, .init_sensor = armada375_init_sensor, - .is_valid_shift = 10, + .is_valid_bit = BIT(10), .temp_shift = 0, .temp_mask = 0x1ff, .coef_b = 3171900000UL, @@ -221,7 +219,7 @@ static const struct armada_thermal_data armada375_data = { static const struct armada_thermal_data armada380_data = { .is_valid = armada_is_valid, .init_sensor = armada380_init_sensor, - .is_valid_shift = 10, + .is_valid_bit = BIT(10), .temp_shift = 0, .temp_mask = 0x3ff, .coef_b = 1172499100UL, -- cgit From 2f28e4c24b10e29b5f737103a0a6fc77b1c0c99c Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Fri, 22 Dec 2017 17:14:06 +0100 Subject: thermal: armada: Clarify control registers accesses Bindings were incomplete for a long time by only exposing one of the two available control registers. To ease the migration to the full bindings (already in use for the Armada 375 SoC), rename the pointers for clarification. This way, it will only be needed to add another pointer to access the other control register when the time comes. This avoids dangerous situations where the offset 0 of the control area can be either one register or the other depending on the bindings used. After this change, device trees of other SoCs could be migrated to the "full" bindings if they may benefit from features from the unaccessible register, without any change in the driver. Signed-off-by: Miquel Raynal Reviewed-by: Gregory CLEMENT Tested-by: Gregory CLEMENT Signed-off-by: Eduardo Valentin --- drivers/thermal/armada_thermal.c | 76 ++++++++++++++++++++++++++++------------ 1 file changed, 54 insertions(+), 22 deletions(-) (limited to 'drivers/thermal') diff --git a/drivers/thermal/armada_thermal.c b/drivers/thermal/armada_thermal.c index f350d7efd35a..d58376eba6d9 100644 --- a/drivers/thermal/armada_thermal.c +++ b/drivers/thermal/armada_thermal.c @@ -39,12 +39,21 @@ #define A375_HW_RESETn BIT(8) #define A380_HW_RESET BIT(8) +/* Legacy bindings */ +#define LEGACY_CONTROL_MEM_LEN 0x4 + +/* Current bindings with the 2 control registers under the same memory area */ +#define LEGACY_CONTROL1_OFFSET 0x0 +#define CONTROL0_OFFSET 0x0 +#define CONTROL1_OFFSET 0x4 + struct armada_thermal_data; /* Marvell EBU Thermal Sensor Dev Structure */ struct armada_thermal_priv { void __iomem *sensor; - void __iomem *control; + void __iomem *control0; + void __iomem *control1; struct armada_thermal_data *data; }; @@ -66,27 +75,28 @@ struct armada_thermal_data { unsigned int temp_shift; unsigned int temp_mask; u32 is_valid_bit; + bool needs_control0; }; static void armadaxp_init_sensor(struct platform_device *pdev, struct armada_thermal_priv *priv) { - unsigned long reg; + u32 reg; - reg = readl_relaxed(priv->control); + reg = readl_relaxed(priv->control1); reg |= PMU_TDC0_OTF_CAL_MASK; - writel(reg, priv->control); + writel(reg, priv->control1); /* Reference calibration value */ reg &= ~PMU_TDC0_REF_CAL_CNT_MASK; reg |= (0xf1 << PMU_TDC0_REF_CAL_CNT_OFFS); - writel(reg, priv->control); + writel(reg, priv->control1); /* Reset the sensor */ - reg = readl_relaxed(priv->control); - writel((reg | PMU_TDC0_SW_RST_MASK), priv->control); + reg = readl_relaxed(priv->control1); + writel((reg | PMU_TDC0_SW_RST_MASK), priv->control1); - writel(reg, priv->control); + writel(reg, priv->control1); /* Enable the sensor */ reg = readl_relaxed(priv->sensor); @@ -97,19 +107,19 @@ static void armadaxp_init_sensor(struct platform_device *pdev, static void armada370_init_sensor(struct platform_device *pdev, struct armada_thermal_priv *priv) { - unsigned long reg; + u32 reg; - reg = readl_relaxed(priv->control); + reg = readl_relaxed(priv->control1); reg |= PMU_TDC0_OTF_CAL_MASK; - writel(reg, priv->control); + writel(reg, priv->control1); /* Reference calibration value */ reg &= ~PMU_TDC0_REF_CAL_CNT_MASK; reg |= (0xf1 << PMU_TDC0_REF_CAL_CNT_OFFS); - writel(reg, priv->control); + writel(reg, priv->control1); reg &= ~PMU_TDC0_START_CAL_MASK; - writel(reg, priv->control); + writel(reg, priv->control1); msleep(10); } @@ -117,30 +127,30 @@ static void armada370_init_sensor(struct platform_device *pdev, static void armada375_init_sensor(struct platform_device *pdev, struct armada_thermal_priv *priv) { - unsigned long reg; + u32 reg; - reg = readl(priv->control + 4); + reg = readl(priv->control1); reg &= ~(A375_UNIT_CONTROL_MASK << A375_UNIT_CONTROL_SHIFT); reg &= ~A375_READOUT_INVERT; reg &= ~A375_HW_RESETn; - writel(reg, priv->control + 4); + writel(reg, priv->control1); msleep(20); reg |= A375_HW_RESETn; - writel(reg, priv->control + 4); + writel(reg, priv->control1); msleep(50); } static void armada380_init_sensor(struct platform_device *pdev, struct armada_thermal_priv *priv) { - unsigned long reg = readl_relaxed(priv->control); + u32 reg = readl_relaxed(priv->control1); /* Reset hardware once */ if (!(reg & A380_HW_RESET)) { reg |= A380_HW_RESET; - writel(reg, priv->control); + writel(reg, priv->control1); msleep(10); } } @@ -214,6 +224,7 @@ static const struct armada_thermal_data armada375_data = { .coef_b = 3171900000UL, .coef_m = 10000000UL, .coef_div = 13616, + .needs_control0 = true, }; static const struct armada_thermal_data armada380_data = { @@ -253,6 +264,7 @@ MODULE_DEVICE_TABLE(of, armada_thermal_id_table); static int armada_thermal_probe(struct platform_device *pdev) { + void __iomem *control = NULL; struct thermal_zone_device *thermal; const struct of_device_id *match; struct armada_thermal_priv *priv; @@ -272,11 +284,31 @@ static int armada_thermal_probe(struct platform_device *pdev) return PTR_ERR(priv->sensor); res = platform_get_resource(pdev, IORESOURCE_MEM, 1); - priv->control = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(priv->control)) - return PTR_ERR(priv->control); + control = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(control)) + return PTR_ERR(control); priv->data = (struct armada_thermal_data *)match->data; + + /* + * Legacy DT bindings only described "control1" register (also referred + * as "control MSB" on old documentation). New bindings cover + * "control0/control LSB" and "control1/control MSB" registers within + * the same resource, which is then of size 8 instead of 4. + */ + if (resource_size(res) == LEGACY_CONTROL_MEM_LEN) { + /* ->control0 unavailable in this configuration */ + if (priv->data->needs_control0) { + dev_err(&pdev->dev, "No access to control0 register\n"); + return -EINVAL; + } + + priv->control1 = control + LEGACY_CONTROL1_OFFSET; + } else { + priv->control0 = control + CONTROL0_OFFSET; + priv->control1 = control + CONTROL1_OFFSET; + } + priv->data->init_sensor(pdev, priv); thermal = thermal_zone_device_register("armada_thermal", 0, 0, -- cgit From 8371b8a3324b4dcee2a51983a3309c5a8bc6cd3b Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Fri, 22 Dec 2017 17:14:07 +0100 Subject: thermal: armada: Use real status register name Three 32-bit registers are used to drive the thermal IP: control0, control1 and status. The two control registers share the same name both in the documentation and in the code, while the latter is referred as "sensor" in the code. Rename this pointer to be called "status" in order to be aligned with the documentation. Signed-off-by: Miquel Raynal Reviewed-by: Gregory CLEMENT Signed-off-by: Eduardo Valentin --- drivers/thermal/armada_thermal.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers/thermal') diff --git a/drivers/thermal/armada_thermal.c b/drivers/thermal/armada_thermal.c index d58376eba6d9..ceebabf45c53 100644 --- a/drivers/thermal/armada_thermal.c +++ b/drivers/thermal/armada_thermal.c @@ -51,7 +51,7 @@ struct armada_thermal_data; /* Marvell EBU Thermal Sensor Dev Structure */ struct armada_thermal_priv { - void __iomem *sensor; + void __iomem *status; void __iomem *control0; void __iomem *control1; struct armada_thermal_data *data; @@ -99,9 +99,9 @@ static void armadaxp_init_sensor(struct platform_device *pdev, writel(reg, priv->control1); /* Enable the sensor */ - reg = readl_relaxed(priv->sensor); + reg = readl_relaxed(priv->status); reg &= ~PMU_TM_DISABLE_MASK; - writel(reg, priv->sensor); + writel(reg, priv->status); } static void armada370_init_sensor(struct platform_device *pdev, @@ -157,7 +157,7 @@ static void armada380_init_sensor(struct platform_device *pdev, static bool armada_is_valid(struct armada_thermal_priv *priv) { - u32 reg = readl_relaxed(priv->sensor); + u32 reg = readl_relaxed(priv->status); return reg & priv->data->is_valid_bit; } @@ -176,7 +176,7 @@ static int armada_get_temp(struct thermal_zone_device *thermal, return -EIO; } - reg = readl_relaxed(priv->sensor); + reg = readl_relaxed(priv->status); reg = (reg >> priv->data->temp_shift) & priv->data->temp_mask; /* Get formula coeficients */ @@ -279,9 +279,9 @@ static int armada_thermal_probe(struct platform_device *pdev) return -ENOMEM; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - priv->sensor = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(priv->sensor)) - return PTR_ERR(priv->sensor); + priv->status = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(priv->status)) + return PTR_ERR(priv->status); res = platform_get_resource(pdev, IORESOURCE_MEM, 1); control = devm_ioremap_resource(&pdev->dev, res); -- cgit From 2ff127999289a8ed29b2dae3a15f2f484d560463 Mon Sep 17 00:00:00 2001 From: Baruch Siach Date: Fri, 22 Dec 2017 17:14:08 +0100 Subject: thermal: armada: Add support for Armada AP806 The AP806 component is integrated in the Armada 8K and 7K lines of processors. The thermal sensor sample field on the status register is a signed value. Extend armada_get_temp() and the driver structure to handle signed values. Signed-off-by: Baruch Siach [: Changes when applying over the previous patches, including the register names changes, also switched the coefficients values to s64 instead of unsigned long to deal with negative values and used do_div instead of the traditionnal '/'] Signed-off-by: Miquel Raynal Reviewed-by: Gregory CLEMENT Tested-by: Gregory CLEMENT Signed-off-by: Eduardo Valentin --- drivers/thermal/armada_thermal.c | 74 +++++++++++++++++++++++++++++++--------- 1 file changed, 58 insertions(+), 16 deletions(-) (limited to 'drivers/thermal') diff --git a/drivers/thermal/armada_thermal.c b/drivers/thermal/armada_thermal.c index ceebabf45c53..f35289b1cea9 100644 --- a/drivers/thermal/armada_thermal.c +++ b/drivers/thermal/armada_thermal.c @@ -47,6 +47,11 @@ #define CONTROL0_OFFSET 0x0 #define CONTROL1_OFFSET 0x4 +/* TSEN refers to the temperature sensors within the AP */ +#define CONTROL0_TSEN_START BIT(0) +#define CONTROL0_TSEN_RESET BIT(1) +#define CONTROL0_TSEN_ENABLE BIT(2) + struct armada_thermal_data; /* Marvell EBU Thermal Sensor Dev Structure */ @@ -66,10 +71,11 @@ struct armada_thermal_data { bool (*is_valid)(struct armada_thermal_priv *); /* Formula coeficients: temp = (b - m * reg) / div */ - unsigned long coef_b; - unsigned long coef_m; - unsigned long coef_div; + s64 coef_b; + s64 coef_m; + u32 coef_div; bool inverted; + bool signed_sample; /* Register shift and mask to access the sensor temperature */ unsigned int temp_shift; @@ -155,6 +161,18 @@ static void armada380_init_sensor(struct platform_device *pdev, } } +static void armada_ap806_init_sensor(struct platform_device *pdev, + struct armada_thermal_priv *priv) +{ + u32 reg; + + reg = readl_relaxed(priv->control0); + reg &= ~CONTROL0_TSEN_RESET; + reg |= CONTROL0_TSEN_START | CONTROL0_TSEN_ENABLE; + writel(reg, priv->control0); + msleep(10); +} + static bool armada_is_valid(struct armada_thermal_priv *priv) { u32 reg = readl_relaxed(priv->status); @@ -163,11 +181,11 @@ static bool armada_is_valid(struct armada_thermal_priv *priv) } static int armada_get_temp(struct thermal_zone_device *thermal, - int *temp) + int *temp) { struct armada_thermal_priv *priv = thermal->devdata; - unsigned long reg; - unsigned long m, b, div; + u32 reg, div; + s64 sample, b, m; /* Valid check */ if (priv->data->is_valid && !priv->data->is_valid(priv)) { @@ -178,6 +196,11 @@ static int armada_get_temp(struct thermal_zone_device *thermal, reg = readl_relaxed(priv->status); reg = (reg >> priv->data->temp_shift) & priv->data->temp_mask; + if (priv->data->signed_sample) + /* The most significant bit is the sign bit */ + sample = sign_extend32(reg, fls(priv->data->temp_mask) - 1); + else + sample = reg; /* Get formula coeficients */ b = priv->data->coef_b; @@ -185,9 +208,10 @@ static int armada_get_temp(struct thermal_zone_device *thermal, div = priv->data->coef_div; if (priv->data->inverted) - *temp = ((m * reg) - b) / div; + *temp = div_s64((m * sample) - b, div); else - *temp = (b - (m * reg)) / div; + *temp = div_s64(b - (m * sample), div); + return 0; } @@ -199,8 +223,8 @@ static const struct armada_thermal_data armadaxp_data = { .init_sensor = armadaxp_init_sensor, .temp_shift = 10, .temp_mask = 0x1ff, - .coef_b = 3153000000UL, - .coef_m = 10000000UL, + .coef_b = 3153000000ULL, + .coef_m = 10000000ULL, .coef_div = 13825, }; @@ -210,8 +234,8 @@ static const struct armada_thermal_data armada370_data = { .is_valid_bit = BIT(9), .temp_shift = 10, .temp_mask = 0x1ff, - .coef_b = 3153000000UL, - .coef_m = 10000000UL, + .coef_b = 3153000000ULL, + .coef_m = 10000000ULL, .coef_div = 13825, }; @@ -221,8 +245,8 @@ static const struct armada_thermal_data armada375_data = { .is_valid_bit = BIT(10), .temp_shift = 0, .temp_mask = 0x1ff, - .coef_b = 3171900000UL, - .coef_m = 10000000UL, + .coef_b = 3171900000ULL, + .coef_m = 10000000ULL, .coef_div = 13616, .needs_control0 = true, }; @@ -233,12 +257,26 @@ static const struct armada_thermal_data armada380_data = { .is_valid_bit = BIT(10), .temp_shift = 0, .temp_mask = 0x3ff, - .coef_b = 1172499100UL, - .coef_m = 2000096UL, + .coef_b = 1172499100ULL, + .coef_m = 2000096ULL, .coef_div = 4201, .inverted = true, }; +static const struct armada_thermal_data armada_ap806_data = { + .is_valid = armada_is_valid, + .init_sensor = armada_ap806_init_sensor, + .is_valid_bit = BIT(16), + .temp_shift = 0, + .temp_mask = 0x3ff, + .coef_b = -150000LL, + .coef_m = 423ULL, + .coef_div = 1, + .inverted = true, + .signed_sample = true, + .needs_control0 = true, +}; + static const struct of_device_id armada_thermal_id_table[] = { { .compatible = "marvell,armadaxp-thermal", @@ -256,6 +294,10 @@ static const struct of_device_id armada_thermal_id_table[] = { .compatible = "marvell,armada380-thermal", .data = &armada380_data, }, + { + .compatible = "marvell,armada-ap806-thermal", + .data = &armada_ap806_data, + }, { /* sentinel */ }, -- cgit From ccf8f522d198c0f69f343d6d6c61bcc906458818 Mon Sep 17 00:00:00 2001 From: Baruch Siach Date: Fri, 22 Dec 2017 17:14:09 +0100 Subject: thermal: armada: Add support for Armada CP110 The CP110 component is integrated in the Armada 8k and 7k lines of processors. Signed-off-by: Baruch Siach [: renamed the register pointers as well as some definitions related to the new register names and simplified the init sequence for Armada 380] Signed-off-by: Miquel Raynal Reviewed-by: Gregory CLEMENT Tested-by: Gregory CLEMENT Signed-off-by: Eduardo Valentin --- drivers/thermal/armada_thermal.c | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) (limited to 'drivers/thermal') diff --git a/drivers/thermal/armada_thermal.c b/drivers/thermal/armada_thermal.c index f35289b1cea9..f2eba2a6f1a5 100644 --- a/drivers/thermal/armada_thermal.c +++ b/drivers/thermal/armada_thermal.c @@ -37,7 +37,6 @@ #define A375_UNIT_CONTROL_MASK 0x7 #define A375_READOUT_INVERT BIT(15) #define A375_HW_RESETn BIT(8) -#define A380_HW_RESET BIT(8) /* Legacy bindings */ #define LEGACY_CONTROL_MEM_LEN 0x4 @@ -52,6 +51,10 @@ #define CONTROL0_TSEN_RESET BIT(1) #define CONTROL0_TSEN_ENABLE BIT(2) +/* EXT_TSEN refers to the external temperature sensors, out of the AP */ +#define CONTROL1_EXT_TSEN_SW_RESET BIT(7) +#define CONTROL1_EXT_TSEN_HW_RESETn BIT(8) + struct armada_thermal_data; /* Marvell EBU Thermal Sensor Dev Structure */ @@ -153,12 +156,11 @@ static void armada380_init_sensor(struct platform_device *pdev, { u32 reg = readl_relaxed(priv->control1); - /* Reset hardware once */ - if (!(reg & A380_HW_RESET)) { - reg |= A380_HW_RESET; - writel(reg, priv->control1); - msleep(10); - } + /* Disable the HW/SW reset */ + reg |= CONTROL1_EXT_TSEN_HW_RESETn; + reg &= ~CONTROL1_EXT_TSEN_SW_RESET; + writel(reg, priv->control1); + msleep(10); } static void armada_ap806_init_sensor(struct platform_device *pdev, @@ -277,6 +279,19 @@ static const struct armada_thermal_data armada_ap806_data = { .needs_control0 = true, }; +static const struct armada_thermal_data armada_cp110_data = { + .is_valid = armada_is_valid, + .init_sensor = armada380_init_sensor, + .is_valid_bit = BIT(10), + .temp_shift = 0, + .temp_mask = 0x3ff, + .coef_b = 1172499100ULL, + .coef_m = 2000096ULL, + .coef_div = 4201, + .inverted = true, + .needs_control0 = true, +}; + static const struct of_device_id armada_thermal_id_table[] = { { .compatible = "marvell,armadaxp-thermal", @@ -298,6 +313,10 @@ static const struct of_device_id armada_thermal_id_table[] = { .compatible = "marvell,armada-ap806-thermal", .data = &armada_ap806_data, }, + { + .compatible = "marvell,armada-cp110-thermal", + .data = &armada_cp110_data, + }, { /* sentinel */ }, -- cgit From a9d58a1aa35f4c01a075303b5c7dcde84e7df124 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Fri, 22 Dec 2017 17:14:10 +0100 Subject: thermal: armada: Update Kconfig and module description Update Armada thermal driver Kconfig entry as well as the driver's MODULE_DESCRIPTION content, now that 64-bit SoCs are also supported, eg. Armada 7K and Armada 8K. Use the generic term "Marvell EBU Armada SoCs" instead of listing all the supported SoCs everywhere (excepted in the Kconfig description, where it is useful to have a list). Signed-off-by: Miquel Raynal Reviewed-by: Gregory CLEMENT Signed-off-by: Eduardo Valentin --- drivers/thermal/Kconfig | 4 ++-- drivers/thermal/armada_thermal.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/thermal') diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig index 315ae2926e20..b6adc54b96f1 100644 --- a/drivers/thermal/Kconfig +++ b/drivers/thermal/Kconfig @@ -301,13 +301,13 @@ config DB8500_THERMAL thermal zone if trip points reached. config ARMADA_THERMAL - tristate "Armada 370/XP thermal management" + tristate "Marvell EBU Armada SoCs thermal management" depends on ARCH_MVEBU || COMPILE_TEST depends on HAS_IOMEM depends on OF help Enable this option if you want to have support for thermal management - controller present in Armada 370 and Armada XP SoC. + controller present in Marvell EBU Armada SoCs (370,375,XP,38x,7K,8K). config DA9062_THERMAL tristate "DA9062/DA9061 Dialog Semiconductor thermal driver" diff --git a/drivers/thermal/armada_thermal.c b/drivers/thermal/armada_thermal.c index f2eba2a6f1a5..d426b230e1c5 100644 --- a/drivers/thermal/armada_thermal.c +++ b/drivers/thermal/armada_thermal.c @@ -1,5 +1,5 @@ /* - * Marvell Armada 370/XP thermal sensor driver + * Marvell EBU Armada SoCs thermal sensor driver * * Copyright (C) 2013 Marvell * @@ -407,5 +407,5 @@ static struct platform_driver armada_thermal_driver = { module_platform_driver(armada_thermal_driver); MODULE_AUTHOR("Ezequiel Garcia "); -MODULE_DESCRIPTION("Armada 370/XP thermal driver"); +MODULE_DESCRIPTION("Marvell EBU Armada SoCs thermal driver"); MODULE_LICENSE("GPL v2"); -- cgit From 8c0b888f6610d0ebbc4bdfb52d2fef9f4a11adfc Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Fri, 22 Dec 2017 17:14:11 +0100 Subject: thermal: armada: Change sensors trim default value Errata #132698 highlights an error in the default value of Tc trim. Set this parameter to b'011. Suggested-by: David Sniatkiwicz Signed-off-by: Miquel Raynal Reviewed-by: Gregory CLEMENT Signed-off-by: Eduardo Valentin --- drivers/thermal/armada_thermal.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'drivers/thermal') diff --git a/drivers/thermal/armada_thermal.c b/drivers/thermal/armada_thermal.c index d426b230e1c5..e6025d215cb5 100644 --- a/drivers/thermal/armada_thermal.c +++ b/drivers/thermal/armada_thermal.c @@ -46,6 +46,10 @@ #define CONTROL0_OFFSET 0x0 #define CONTROL1_OFFSET 0x4 +/* Errata fields */ +#define CONTROL0_TSEN_TC_TRIM_MASK 0x7 +#define CONTROL0_TSEN_TC_TRIM_VAL 0x3 + /* TSEN refers to the temperature sensors within the AP */ #define CONTROL0_TSEN_START BIT(0) #define CONTROL0_TSEN_RESET BIT(1) @@ -161,6 +165,15 @@ static void armada380_init_sensor(struct platform_device *pdev, reg &= ~CONTROL1_EXT_TSEN_SW_RESET; writel(reg, priv->control1); msleep(10); + + /* Set Tsen Tc Trim to correct default value (errata #132698) */ + if (priv->control0) { + reg = readl_relaxed(priv->control0); + reg &= ~CONTROL0_TSEN_TC_TRIM_MASK; + reg |= CONTROL0_TSEN_TC_TRIM_VAL; + writel(reg, priv->control0); + msleep(10); + } } static void armada_ap806_init_sensor(struct platform_device *pdev, -- cgit From 64163681a25e00182f727caa3a57ffe8d70f1022 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Fri, 22 Dec 2017 17:14:12 +0100 Subject: thermal: armada: Wait sensors validity before exiting the init callback The thermal core will check for sensors validity right after the initialization callback has returned. As the initialization routine make a reset, the sensors are not ready immediately and the core spawns an error in the dmesg. Avoid this annoying situation by polling on the validity bit before exiting from these routines. This also avoid the use of blind sleeps. Suggested-by: David Sniatkiwicz Signed-off-by: Miquel Raynal Reviewed-by: Gregory CLEMENT Signed-off-by: Eduardo Valentin --- drivers/thermal/armada_thermal.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) (limited to 'drivers/thermal') diff --git a/drivers/thermal/armada_thermal.c b/drivers/thermal/armada_thermal.c index e6025d215cb5..a4befd2d683d 100644 --- a/drivers/thermal/armada_thermal.c +++ b/drivers/thermal/armada_thermal.c @@ -23,6 +23,7 @@ #include #include #include +#include /* Thermal Manager Control and Status Register */ #define PMU_TDC0_SW_RST_MASK (0x1 << 1) @@ -59,6 +60,9 @@ #define CONTROL1_EXT_TSEN_SW_RESET BIT(7) #define CONTROL1_EXT_TSEN_HW_RESETn BIT(8) +#define STATUS_POLL_PERIOD_US 1000 +#define STATUS_POLL_TIMEOUT_US 100000 + struct armada_thermal_data; /* Marvell EBU Thermal Sensor Dev Structure */ @@ -155,6 +159,16 @@ static void armada375_init_sensor(struct platform_device *pdev, msleep(50); } +static void armada_wait_sensor_validity(struct armada_thermal_priv *priv) +{ + u32 reg; + + readl_relaxed_poll_timeout(priv->status, reg, + reg & priv->data->is_valid_bit, + STATUS_POLL_PERIOD_US, + STATUS_POLL_TIMEOUT_US); +} + static void armada380_init_sensor(struct platform_device *pdev, struct armada_thermal_priv *priv) { @@ -164,7 +178,6 @@ static void armada380_init_sensor(struct platform_device *pdev, reg |= CONTROL1_EXT_TSEN_HW_RESETn; reg &= ~CONTROL1_EXT_TSEN_SW_RESET; writel(reg, priv->control1); - msleep(10); /* Set Tsen Tc Trim to correct default value (errata #132698) */ if (priv->control0) { @@ -172,8 +185,10 @@ static void armada380_init_sensor(struct platform_device *pdev, reg &= ~CONTROL0_TSEN_TC_TRIM_MASK; reg |= CONTROL0_TSEN_TC_TRIM_VAL; writel(reg, priv->control0); - msleep(10); } + + /* Wait the sensors to be valid or the core will warn the user */ + armada_wait_sensor_validity(priv); } static void armada_ap806_init_sensor(struct platform_device *pdev, @@ -185,7 +200,9 @@ static void armada_ap806_init_sensor(struct platform_device *pdev, reg &= ~CONTROL0_TSEN_RESET; reg |= CONTROL0_TSEN_START | CONTROL0_TSEN_ENABLE; writel(reg, priv->control0); - msleep(10); + + /* Wait the sensors to be valid or the core will warn the user */ + armada_wait_sensor_validity(priv); } static bool armada_is_valid(struct armada_thermal_priv *priv) -- cgit From f80ee03fe72deb702c83a353b41d0fac12ed7ded Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Fri, 22 Dec 2017 17:14:13 +0100 Subject: thermal: armada: Give meaningful names to the thermal zones After registration to the thermal core, sysfs will make one entry per instance of the driver in /sys/class/thermal_zoneX and /sys/class/hwmon/hwmonX, X being the index of the instance, all of them having the type/name "armada_thermal". Until now there was only one thermal zone per SoC but SoCs like Armada A7K and Armada A8K have respectively two and three thermal zones (one per AP and one per CP) and this number is subject to grow in the future. Use dev_name() instead of the "armada_thermal" string to get a meaningful name and be able to identify the thermal zones from userspace. Signed-off-by: Miquel Raynal Reviewed-by: Gregory CLEMENT Tested-by: Gregory CLEMENT Signed-off-by: Eduardo Valentin --- drivers/thermal/armada_thermal.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/thermal') diff --git a/drivers/thermal/armada_thermal.c b/drivers/thermal/armada_thermal.c index a4befd2d683d..4c275ec10ac5 100644 --- a/drivers/thermal/armada_thermal.c +++ b/drivers/thermal/armada_thermal.c @@ -402,8 +402,8 @@ static int armada_thermal_probe(struct platform_device *pdev) priv->data->init_sensor(pdev, priv); - thermal = thermal_zone_device_register("armada_thermal", 0, 0, - priv, &ops, NULL, 0, 0); + thermal = thermal_zone_device_register(dev_name(&pdev->dev), 0, 0, priv, + &ops, NULL, 0, 0); if (IS_ERR(thermal)) { dev_err(&pdev->dev, "Failed to register thermal zone device\n"); -- cgit From d0ecbbbe518e1b256fcda1770ec06a5a1a058567 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Sun, 19 Nov 2017 12:04:27 +0100 Subject: thermal/drivers/hisi: Remove bogus const from function return type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With gcc-4.1.2: drivers/thermal/hisi_thermal.c: In function ‘hisi_thermal_probe’: drivers/thermal/hisi_thermal.c:530: warning: type qualifiers ignored on function return type Remove the "const" keyword to fix this. Fixes: a160a465297362c5 ("thermal/drivers/hisi: Prepare to add support for other hisi platforms") Signed-off-by: Geert Uytterhoeven Signed-off-by: Eduardo Valentin --- drivers/thermal/hisi_thermal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/thermal') diff --git a/drivers/thermal/hisi_thermal.c b/drivers/thermal/hisi_thermal.c index 2d855a96cdd9..761d0559c268 100644 --- a/drivers/thermal/hisi_thermal.c +++ b/drivers/thermal/hisi_thermal.c @@ -527,7 +527,7 @@ static void hisi_thermal_toggle_sensor(struct hisi_thermal_sensor *sensor, static int hisi_thermal_probe(struct platform_device *pdev) { struct hisi_thermal_data *data; - int const (*platform_probe)(struct hisi_thermal_data *); + int (*platform_probe)(struct hisi_thermal_data *); struct device *dev = &pdev->dev; int ret; -- cgit From 0be86969ae385c5c944286bd9f66068525de15ee Mon Sep 17 00:00:00 2001 From: Alexey Khoroshilov Date: Sat, 30 Dec 2017 01:05:21 +0300 Subject: thermal: int3400_thermal: fix error handling in int3400_thermal_probe() There are resources that are not dealocated on failure path in int3400_thermal_probe(). Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov Signed-off-by: Zhang Rui --- drivers/thermal/int340x_thermal/int3400_thermal.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers/thermal') diff --git a/drivers/thermal/int340x_thermal/int3400_thermal.c b/drivers/thermal/int340x_thermal/int3400_thermal.c index c9db1c643501..e26b01c05e82 100644 --- a/drivers/thermal/int340x_thermal/int3400_thermal.c +++ b/drivers/thermal/int340x_thermal/int3400_thermal.c @@ -319,17 +319,21 @@ static int int3400_thermal_probe(struct platform_device *pdev) result = sysfs_create_group(&pdev->dev.kobj, &uuid_attribute_group); if (result) - goto free_zone; + goto free_rel_misc; result = acpi_install_notify_handler( priv->adev->handle, ACPI_DEVICE_NOTIFY, int3400_notify, (void *)priv); if (result) - goto free_zone; + goto free_sysfs; return 0; -free_zone: +free_sysfs: + sysfs_remove_group(&pdev->dev.kobj, &uuid_attribute_group); +free_rel_misc: + if (!priv->rel_misc_dev_res) + acpi_thermal_rel_misc_device_remove(priv->adev->handle); thermal_zone_device_unregister(priv->thermal); free_art_trt: kfree(priv->trts); -- cgit From e74c2d65ff2e3607e392ae3e779da47135c85966 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 2 Jan 2018 16:30:57 +0100 Subject: thermal/x86 pkg temp: Remove debugfs_create_u32() casts When exposing data access through debugfs, the correct debugfs_create_*() functions must be used, depending on data type. Remove all casts from data pointers passed to debugfs_create_*() functions, as such casts prevent the compiler from flagging bugs. Signed-off-by: Geert Uytterhoeven Signed-off-by: Zhang Rui --- drivers/thermal/x86_pkg_temp_thermal.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/thermal') diff --git a/drivers/thermal/x86_pkg_temp_thermal.c b/drivers/thermal/x86_pkg_temp_thermal.c index d93eee2f101b..1a6c88b10a39 100644 --- a/drivers/thermal/x86_pkg_temp_thermal.c +++ b/drivers/thermal/x86_pkg_temp_thermal.c @@ -96,12 +96,12 @@ static int pkg_temp_debugfs_init(void) return -ENOENT; d = debugfs_create_u32("pkg_thres_interrupt", S_IRUGO, debugfs, - (u32 *)&pkg_interrupt_cnt); + &pkg_interrupt_cnt); if (!d) goto err_out; d = debugfs_create_u32("pkg_thres_work", S_IRUGO, debugfs, - (u32 *)&pkg_work_cnt); + &pkg_work_cnt); if (!d) goto err_out; -- cgit From e782bc169cd02d3411a6db6ff0c26d7f27f8b81a Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Sat, 13 Jan 2018 12:08:49 -0200 Subject: thermal: thermal_hwmon: Convert to hwmon_device_register_with_info() Booting Linux on a mx6q based board leads to the following warning: (NULL device *): hwmon_device_register() is deprecated. Please convert the driver to use hwmon_device_register_with_info(). , so do the conversion as suggested. Also, this results in the core taking care of creating the 'name' attribute, so drop the code doing that from the thermal driver. The initial attempt to convert this driver to hwmon_device_register_with_info() caused issues on the N900 platform in commit 7611fb68062f ("thermal: thermal_hwmon: Convert to hwmon_device_register_with_info()"): bq27xxx-battery 2-0055: failed to register battery bq27xxx-battery: probe of 2-0055 failed with error -22 ... rx51-battery: probe of n900-battery failed with error -22 , leading to a revert in commit 3feb479cea37 ("Revert "thermal: thermal_hwmon: Convert to hwmon_device_register_with_info()""). The probe errors happened due to the '-' character being present in the name of the power supply devices: bq27200-0 and rx51-battery. Since commit 74d3b6419772 ("hwmon: Relax name attribute validation for new APIs") hwmon will no longer treat these names as errors, allowing the transition for hwmon_device_register_with_info() to happen in a safely manner. Cc: Pavel Machek Cc: Guenter Roeck Signed-off-by: Fabio Estevam Acked-by: Guenter Roeck Signed-off-by: Zhang Rui --- drivers/thermal/thermal_hwmon.c | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) (limited to 'drivers/thermal') diff --git a/drivers/thermal/thermal_hwmon.c b/drivers/thermal/thermal_hwmon.c index 541af5946203..c4a508a124dc 100644 --- a/drivers/thermal/thermal_hwmon.c +++ b/drivers/thermal/thermal_hwmon.c @@ -58,14 +58,6 @@ static LIST_HEAD(thermal_hwmon_list); static DEFINE_MUTEX(thermal_hwmon_list_lock); -static ssize_t -name_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct thermal_hwmon_device *hwmon = dev_get_drvdata(dev); - return sprintf(buf, "%s\n", hwmon->type); -} -static DEVICE_ATTR_RO(name); - static ssize_t temp_input_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -165,15 +157,12 @@ int thermal_add_hwmon_sysfs(struct thermal_zone_device *tz) INIT_LIST_HEAD(&hwmon->tz_list); strlcpy(hwmon->type, tz->type, THERMAL_NAME_LENGTH); - hwmon->device = hwmon_device_register(NULL); + hwmon->device = hwmon_device_register_with_info(NULL, hwmon->type, + hwmon, NULL, NULL); if (IS_ERR(hwmon->device)) { result = PTR_ERR(hwmon->device); goto free_mem; } - dev_set_drvdata(hwmon->device, hwmon); - result = device_create_file(hwmon->device, &dev_attr_name); - if (result) - goto free_mem; register_sys_interface: temp = kzalloc(sizeof(*temp), GFP_KERNEL); @@ -222,10 +211,8 @@ int thermal_add_hwmon_sysfs(struct thermal_zone_device *tz) free_temp_mem: kfree(temp); unregister_name: - if (new_hwmon_device) { - device_remove_file(hwmon->device, &dev_attr_name); + if (new_hwmon_device) hwmon_device_unregister(hwmon->device); - } free_mem: if (new_hwmon_device) kfree(hwmon); @@ -267,7 +254,6 @@ void thermal_remove_hwmon_sysfs(struct thermal_zone_device *tz) list_del(&hwmon->node); mutex_unlock(&thermal_hwmon_list_lock); - device_remove_file(hwmon->device, &dev_attr_name); hwmon_device_unregister(hwmon->device); kfree(hwmon); } -- cgit