summaryrefslogtreecommitdiff
path: root/driver/temp_sensor
diff options
context:
space:
mode:
authorWonjoon Lee <woojoo.lee@samsung.com>2015-09-01 21:33:56 +0900
committerchrome-bot <chrome-bot@chromium.org>2015-09-11 00:45:37 -0700
commit502dc50f04c5df787e95982cef4971b20e501cba (patch)
treec5b9b550600e72f5d4bc0cd3a1000fa0d0093ee5 /driver/temp_sensor
parent3f2dc44158630f0ce93633c21df8daaddb2b7324 (diff)
downloadchrome-ec-502dc50f04c5df787e95982cef4971b20e501cba.tar.gz
temp_sensor: Separate ADC interface and thermistor maths
Separate the bd99992gw ADC interface from the NCP15WB thermistor adc-to-temp maths so that the thermistor can be used with various other interfaces. BUG=chrome-os-partner:44764 TEST=make buildall -j Manual on Glados. Boot to S0, run "temps". Verify that temperatures start around 28C and begin to increase after system is powered-on for a long duration. BRANCH=None Change-Id: I3e72e9f390feebaac2440dbe722485f8d1cf8c56 Signed-off-by: Wonjoon Lee <woojoo.lee@samsung.com> Reviewed-on: https://chromium-review.googlesource.com/296871 Reviewed-by: Shawn N <shawnn@chromium.org>
Diffstat (limited to 'driver/temp_sensor')
-rw-r--r--driver/temp_sensor/bd99992gw.c96
-rw-r--r--driver/temp_sensor/thermistor.h20
-rw-r--r--driver/temp_sensor/thermistor_ncp15wb.c100
3 files changed, 128 insertions, 88 deletions
diff --git a/driver/temp_sensor/bd99992gw.c b/driver/temp_sensor/bd99992gw.c
index b46d8512fe..f2a48eb2d5 100644
--- a/driver/temp_sensor/bd99992gw.c
+++ b/driver/temp_sensor/bd99992gw.c
@@ -17,6 +17,7 @@
#include "hooks.h"
#include "i2c.h"
#include "temp_sensor.h"
+#include "thermistor.h"
#include "timer.h"
#include "util.h"
@@ -35,46 +36,6 @@ static enum bd99992gw_adc_channel
*/
#define ADC_LOOP_PERIOD BD99992GW_ADC1CNTL1_SLP27MS
-/*
- * ADC-to-temp conversion assumes recommended thermistor / resistor
- * configuration specified in datasheet (NCP15WB* / 24.9K).
- * For 50C through 100C, use linear interpolation from discreet points
- * in table below. For temps < 50C, use a simplified linear function.
- */
-#define ADC_DISCREET_RANGE_START_TEMP 50
-/* 10 bit ADC result corresponding to START_TEMP */
-#define ADC_DISCREET_RANGE_START_RESULT 407
-
-#define ADC_DISCREET_RANGE_LIMIT_TEMP 100
-/* 10 bit ADC result corresponding to LIMIT_TEMP */
-#define ADC_DISCREET_RANGE_LIMIT_RESULT 107
-
-/* Table entries in steppings of 5C */
-#define ADC_DISCREET_RANGE_STEP 5
-
-/* Discreet range ADC results (9 bit) per temperature, in 5 degree steps */
-static const uint8_t adc_result[] = {
- 203, /* 50 C */
- 178, /* 55 C */
- 157, /* 60 C */
- 138, /* 65 C */
- 121, /* 70 C */
- 106, /* 75 C */
- 93, /* 80 C */
- 81, /* 85 C */
- 70, /* 90 C */
- 61, /* 95 C */
- 53, /* 100 C */
-};
-
-/*
- * From 20C (reasonable lower limit of temperatures we care about accuracy)
- * to 50C, the temperature curve is roughly linear, so we don't need to include
- * data points in our table.
- */
-#define adc_to_temp(result) (ADC_DISCREET_RANGE_START_TEMP - \
- (((result) - ADC_DISCREET_RANGE_START_RESULT) * 3 + 16) / 32)
-
static int raw_read8(const int offset, int *data_ptr)
{
int ret;
@@ -143,55 +104,14 @@ DECLARE_HOOK(HOOK_INIT, bd99992gw_init, HOOK_PRIO_DEFAULT);
DECLARE_HOOK(HOOK_CHIPSET_RESUME, bd99992gw_init, HOOK_PRIO_DEFAULT);
/* Convert ADC result to temperature in celsius */
-test_export_static int bd99992gw_get_temp(uint16_t adc)
+static int bd99992gw_get_temp(uint16_t adc)
{
- int temp;
- int head, tail, mid;
- uint8_t delta, step;
-
- /* Is ADC result in linear range? */
- if (adc >= ADC_DISCREET_RANGE_START_RESULT) {
- temp = adc_to_temp(adc);
- }
- /* Hotter than our discreet range limit? */
- else if (adc <= ADC_DISCREET_RANGE_LIMIT_RESULT) {
- temp = ADC_DISCREET_RANGE_LIMIT_TEMP;
- }
- /* We're in the discreet range */
- else {
- /* Table uses 9 bit ADC values */
- adc /= 2;
-
- /* Binary search to find proper table entry */
- head = 0;
- tail = ARRAY_SIZE(adc_result) - 1;
- while (head != tail) {
- mid = (head + tail) / 2;
- if (adc_result[mid] >= adc &&
- adc_result[mid+1] < adc)
- break;
- if (adc_result[mid] > adc)
- head = mid + 1;
- else
- tail = mid;
- }
-
- /* Now fit between table entries using linear interpolation. */
- if (head != tail) {
- delta = adc_result[mid] - adc_result[mid + 1];
- step = ((adc_result[mid] - adc) *
- ADC_DISCREET_RANGE_STEP + delta / 2) / delta;
- } else {
- /* Edge case where adc = max */
- mid = head;
- step = 0;
- }
-
- temp = ADC_DISCREET_RANGE_START_TEMP +
- ADC_DISCREET_RANGE_STEP * mid + step;
- }
-
- return temp;
+#ifdef CONFIG_THERMISTOR_NCP15WB
+ return ncp15wb_calculate_temp(adc);
+#else
+#error "Unknown thermistor for bd99992gw"
+ return 0;
+#endif
}
/* Get temperature from requested sensor */
diff --git a/driver/temp_sensor/thermistor.h b/driver/temp_sensor/thermistor.h
new file mode 100644
index 0000000000..3bb5335ddd
--- /dev/null
+++ b/driver/temp_sensor/thermistor.h
@@ -0,0 +1,20 @@
+/* Copyright 2015 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/* Thermistor module for Chrome EC */
+
+#ifndef __CROS_EC_TEMP_SENSOR_THERMISTOR_H
+#define __CROS_EC_TEMP_SENSOR_THERMISTOR_H
+
+/**
+ * ncp15wb temperature conversion routine.
+ *
+ * @param adc 10bit raw data on adc.
+ *
+ * @return temperature in C.
+ */
+int ncp15wb_calculate_temp(uint16_t adc);
+
+#endif /* __CROS_EC_TEMP_SENSOR_THERMISTOR_NCP15WB_H */
diff --git a/driver/temp_sensor/thermistor_ncp15wb.c b/driver/temp_sensor/thermistor_ncp15wb.c
new file mode 100644
index 0000000000..51e884ed35
--- /dev/null
+++ b/driver/temp_sensor/thermistor_ncp15wb.c
@@ -0,0 +1,100 @@
+/* Copyright 2015 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/* NCP15WB thermistor module for Chrome EC */
+
+#include "common.h"
+#include "thermistor.h"
+#include "util.h"
+
+/*
+ * ADC-to-temp conversion assumes recommended thermistor / resistor
+ * configuration (NCP15WB* / 24.9K) with a 10-bit ADC.
+ * For 50C through 100C, use linear interpolation from discreet points
+ * in table below. For temps < 50C, use a simplified linear function.
+ */
+#define ADC_DISCREET_RANGE_START_TEMP 50
+/* 10 bit ADC result corresponding to START_TEMP */
+#define ADC_DISCREET_RANGE_START_RESULT 407
+
+#define ADC_DISCREET_RANGE_LIMIT_TEMP 100
+/* 10 bit ADC result corresponding to LIMIT_TEMP */
+#define ADC_DISCREET_RANGE_LIMIT_RESULT 107
+
+/* Table entries in steppings of 5C */
+#define ADC_DISCREET_RANGE_STEP 5
+
+/* Discreet range ADC results (9 bit) per temperature, in 5 degree steps */
+static const uint8_t adc_result[] = {
+ 203, /* 50 C */
+ 178, /* 55 C */
+ 157, /* 60 C */
+ 138, /* 65 C */
+ 121, /* 70 C */
+ 106, /* 75 C */
+ 93, /* 80 C */
+ 81, /* 85 C */
+ 70, /* 90 C */
+ 61, /* 95 C */
+ 53, /* 100 C */
+};
+
+/*
+ * From 20C (reasonable lower limit of temperatures we care about accuracy)
+ * to 50C, the temperature curve is roughly linear, so we don't need to include
+ * data points in our table.
+ */
+#define adc_to_temp(result) (ADC_DISCREET_RANGE_START_TEMP - \
+ (((result) - ADC_DISCREET_RANGE_START_RESULT) * 3 + 16) / 32)
+
+/* Convert ADC result (10 bit) to temperature in celsius */
+int ncp15wb_calculate_temp(uint16_t adc)
+{
+ int temp;
+ int head, tail, mid;
+ uint8_t delta, step;
+
+ /* Is ADC result in linear range? */
+ if (adc >= ADC_DISCREET_RANGE_START_RESULT)
+ temp = adc_to_temp(adc);
+ /* Hotter than our discreet range limit? */
+ else if (adc <= ADC_DISCREET_RANGE_LIMIT_RESULT)
+ temp = ADC_DISCREET_RANGE_LIMIT_TEMP;
+ /* We're in the discreet range */
+ else {
+ /* Table uses 9 bit ADC values */
+ adc /= 2;
+
+ /* Binary search to find proper table entry */
+ head = 0;
+ tail = ARRAY_SIZE(adc_result) - 1;
+ while (head != tail) {
+ mid = (head + tail) / 2;
+ if (adc_result[mid] >= adc &&
+ adc_result[mid+1] < adc)
+ break;
+ if (adc_result[mid] > adc)
+ head = mid + 1;
+ else
+ tail = mid;
+ }
+
+ /* Now fit between table entries using linear interpolation. */
+ if (head != tail) {
+ delta = adc_result[mid] - adc_result[mid + 1];
+ step = ((adc_result[mid] - adc) *
+ ADC_DISCREET_RANGE_STEP + delta / 2) / delta;
+ } else {
+ /* Edge case where adc = max */
+ mid = head;
+ step = 0;
+ }
+
+ temp = ADC_DISCREET_RANGE_START_TEMP +
+ ADC_DISCREET_RANGE_STEP * mid + step;
+ }
+
+ return temp;
+}