diff options
Diffstat (limited to 'drivers/thermal/imx_thermal.c')
-rw-r--r-- | drivers/thermal/imx_thermal.c | 74 |
1 files changed, 33 insertions, 41 deletions
diff --git a/drivers/thermal/imx_thermal.c b/drivers/thermal/imx_thermal.c index e7d4ffc3de7f..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 @@ -347,78 +343,74 @@ 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; + int 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; } /* - * 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.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 + * + * 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 = val >> 20; - t1 = 25; /* t1 always 25C */ + n1 = ocotp_ana1 >> 20; - /* - * 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; - do_div(temp64, FACTOR1 * n1 - FACTOR2); + temp64 = 10000000; /* use 10^7 as fixed point constant for values in formula */ + temp64 *= 1000; /* to get result in °mC */ + do_div(temp64, 15423 * n1 - 4148468); data->c1 = temp64; - data->c2 = n1 * data->c1 + 1000 * t1; + data->c2 = n1 * data->c1 + 28581; 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) { - case 0: /* Commercial (0 to 95C) */ + switch ((ocotp_mem0 >> 6) & 0x3) { + 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); |