aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Lesiak <chris.lesiak@licor.com>2015-06-02 16:57:58 -0400
committerGuenter Roeck <linux@roeck-us.net>2015-06-03 18:25:53 -0400
commitf6725ae2f1ae266589ab177461e308bb2f86f9ee (patch)
treeb3906631816ba3048e183e0a6117fe5c3fa093ce
parent0315253b19bbc63eedad2f6125c21e280c76e29b (diff)
hwmon: (ntc_thermistor) Improve precision of resistance calculation
The function get_ohm_of_thermistor has both the measured voltage and the pullup voltage available in microvolts. But it was promptly converting both to millivolts before using them to calculate the thermistor resistance. That conversion unnecessarily hurt the precision of the calculation. For example, take the ncpXXwb473 connected to 5000 mV and pulled down through a 47000 ohm resistor. At 25 C, the resistance of the thermistor is 47000 ohms. The measured voltage will be 2500 mV. If we measure instead 2501 mV, then the calculated resistance will be 46962 ohms -- a difference of 38 ohms. So the precision of the resistance estimate could be increased by 38X by doing the calculations in microvolts. Signed-off-by: Chris Lesiak <chris.lesiak@licor.com> Signed-off-by: Guenter Roeck <linux@roeck-us.net>
-rw-r--r--drivers/hwmon/ntc_thermistor.c23
1 files changed, 10 insertions, 13 deletions
diff --git a/drivers/hwmon/ntc_thermistor.c b/drivers/hwmon/ntc_thermistor.c
index 3a2484aba57e..dc0b76c5e302 100644
--- a/drivers/hwmon/ntc_thermistor.c
+++ b/drivers/hwmon/ntc_thermistor.c
@@ -350,30 +350,27 @@ static inline u64 div64_u64_safe(u64 dividend, u64 divisor)
350static int get_ohm_of_thermistor(struct ntc_data *data, unsigned int uv) 350static int get_ohm_of_thermistor(struct ntc_data *data, unsigned int uv)
351{ 351{
352 struct ntc_thermistor_platform_data *pdata = data->pdata; 352 struct ntc_thermistor_platform_data *pdata = data->pdata;
353 u64 mv = uv / 1000; 353 u32 puv = pdata->pullup_uv;
354 u64 pmv = pdata->pullup_uv / 1000;
355 u64 n, puo, pdo; 354 u64 n, puo, pdo;
356 puo = pdata->pullup_ohm; 355 puo = pdata->pullup_ohm;
357 pdo = pdata->pulldown_ohm; 356 pdo = pdata->pulldown_ohm;
358 357
359 if (mv == 0) { 358 if (uv == 0)
360 if (pdata->connect == NTC_CONNECTED_POSITIVE) 359 return (pdata->connect == NTC_CONNECTED_POSITIVE) ?
361 return INT_MAX; 360 INT_MAX : 0;
362 return 0; 361 if (uv >= puv)
363 }
364 if (mv >= pmv)
365 return (pdata->connect == NTC_CONNECTED_POSITIVE) ? 362 return (pdata->connect == NTC_CONNECTED_POSITIVE) ?
366 0 : INT_MAX; 363 0 : INT_MAX;
367 364
368 if (pdata->connect == NTC_CONNECTED_POSITIVE && puo == 0) 365 if (pdata->connect == NTC_CONNECTED_POSITIVE && puo == 0)
369 n = div64_u64_safe(pdo * (pmv - mv), mv); 366 n = div_u64(pdo * (puv - uv), uv);
370 else if (pdata->connect == NTC_CONNECTED_GROUND && pdo == 0) 367 else if (pdata->connect == NTC_CONNECTED_GROUND && pdo == 0)
371 n = div64_u64_safe(puo * mv, pmv - mv); 368 n = div_u64(puo * uv, puv - uv);
372 else if (pdata->connect == NTC_CONNECTED_POSITIVE) 369 else if (pdata->connect == NTC_CONNECTED_POSITIVE)
373 n = div64_u64_safe(pdo * puo * (pmv - mv), 370 n = div64_u64_safe(pdo * puo * (puv - uv),
374 puo * mv - pdo * (pmv - mv)); 371 puo * uv - pdo * (puv - uv));
375 else 372 else
376 n = div64_u64_safe(pdo * puo * mv, pdo * (pmv - mv) - puo * mv); 373 n = div64_u64_safe(pdo * puo * uv, pdo * (puv - uv) - puo * uv);
377 374
378 if (n > INT_MAX) 375 if (n > INT_MAX)
379 n = INT_MAX; 376 n = INT_MAX;