summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--board/bds/board_temp_sensor.c2
-rw-r--r--board/link/board_temp_sensor.c8
-rw-r--r--common/temp_sensor.c112
-rw-r--r--include/temp_sensor.h7
4 files changed, 121 insertions, 8 deletions
diff --git a/board/bds/board_temp_sensor.c b/board/bds/board_temp_sensor.c
index 709ca8226a..65b73005a1 100644
--- a/board/bds/board_temp_sensor.c
+++ b/board/bds/board_temp_sensor.c
@@ -18,5 +18,5 @@ const struct temp_sensor_t temp_sensors[TEMP_SENSOR_COUNT] = {
{"ECInternal", TEMP_SENSOR_EC_INTERNAL, TEMP_SENSOR_NO_ADDR,
chip_temp_sensor_read, TEMP_SENSOR_NO_PRINT},
{"CaseDie", TEMP_SENSOR_CASE_DIE, TEMP_CASE_DIE_ADDR,
- temp_sensor_tmp006_read, temp_sensor_tmp006_print}
+ temp_sensor_tmp006_read_die_temp, temp_sensor_tmp006_print}
};
diff --git a/board/link/board_temp_sensor.c b/board/link/board_temp_sensor.c
index f04754f2bd..4a937c9bf3 100644
--- a/board/link/board_temp_sensor.c
+++ b/board/link/board_temp_sensor.c
@@ -25,13 +25,13 @@
*/
const struct temp_sensor_t temp_sensors[TEMP_SENSOR_COUNT] = {
{"CPU", TEMP_SENSOR_I2C_DIE_NEAR_CPU, TEMP_CPU_ADDR,
- temp_sensor_tmp006_read, temp_sensor_tmp006_print},
+ temp_sensor_tmp006_read_die_temp, temp_sensor_tmp006_print},
{"PCH", TEMP_SENSOR_I2C_DIE_NEAR_PCH, TEMP_PCH_ADDR,
- temp_sensor_tmp006_read, temp_sensor_tmp006_print},
+ temp_sensor_tmp006_read_die_temp, temp_sensor_tmp006_print},
{"DDR", TEMP_SENSOR_I2C_DIE_NEAR_DDR, TEMP_DDR_ADDR,
- temp_sensor_tmp006_read, temp_sensor_tmp006_print},
+ temp_sensor_tmp006_read_die_temp, temp_sensor_tmp006_print},
{"Charger", TEMP_SENSOR_I2C_DIE_NEAR_CHARGER, TEMP_CHARGER_ADDR,
- temp_sensor_tmp006_read, temp_sensor_tmp006_print},
+ temp_sensor_tmp006_read_die_temp, temp_sensor_tmp006_print},
{"ECInternal", TEMP_SENSOR_EC_INTERNAL, TEMP_SENSOR_NO_ADDR,
chip_temp_sensor_read, TEMP_SENSOR_NO_PRINT},
};
diff --git a/common/temp_sensor.c b/common/temp_sensor.c
index a517636ea2..d4285653ed 100644
--- a/common/temp_sensor.c
+++ b/common/temp_sensor.c
@@ -27,7 +27,7 @@ int temp_sensor_read(enum temp_sensor_id id)
return sensor->read(sensor);
}
-int temp_sensor_tmp006_read(const struct temp_sensor_t* sensor)
+int temp_sensor_tmp006_read_die_temp(const struct temp_sensor_t* sensor)
{
int traw, t;
int rv;
@@ -40,6 +40,78 @@ int temp_sensor_tmp006_read(const struct temp_sensor_t* sensor)
return t + 273;
}
+/* Calculate the remote object temperature.
+ * Parameters:
+ * Tdie: Die temperature in 1/100 K.
+ * Vobj: Voltage read from register 0. In nV.
+ * S0: Sensitivity factor in 1/1000.
+ * Return:
+ * Object temperature in 1/100 K.
+ */
+int temp_sensor_tmp006_calculate_object_temp(int Tdie, int Vobj, int S0)
+{
+ int32_t Tx, S19, Vos, Vx, fv9, ub, lb;
+
+ /* Calculate according to TMP006 users guide.
+ * Division is delayed when possible to preserve precision, but should
+ * not cause overflow.
+ * Assuming Tdie is between 200K and 400K, and S0 between 3e-14 and
+ * 9e-14, the maximum value during the calculation should be less than
+ * (1 << 30), which fits in int32_t.
+ */
+ Tx = Tdie - 29815;
+ /* S19 is the sensitivity multipled by 1e19 */
+ S19 = S0 * (100000 + 175 * Tx / 100 -
+ 1678 * Tx / 100 * Tx / 100000) / 1000;
+ /* Vos is the offset voltage in nV */
+ Vos = -29400 - 570 * Tx / 100 + 463 * Tx / 100 * Tx / 10000;
+ Vx = Vobj - Vos;
+ /* fv9 is Seebeck coefficient f(Vobj) multipled by 1e9 */
+ fv9 = Vx + 134 * Vx / 100000 * Vx / 100000;
+
+ /* The last step in the calculation involves square root, so we use
+ * binary search.
+ * Assuming the object temperature is between 200K and 400K, the search
+ * should take at most 14 iterations.
+ */
+ ub = 40000;
+ lb = 20000;
+ while (lb != ub) {
+ int32_t t, rhs, lhs;
+
+ t = (ub + lb) / 2;
+ lhs = t / 100 * t / 10000 * t / 10000 * (S19/100) / 1000 * t;
+ rhs = Tdie / 100 * Tdie / 10000 * Tdie / 10000 * (S19/100) / 1000 *
+ Tdie + fv9 * 1000;
+ if (lhs > rhs)
+ ub = t;
+ else
+ lb = t + 1;
+ }
+
+ return ub;
+}
+
+int temp_sensor_tmp006_read_object_temp(const struct temp_sensor_t* sensor)
+{
+ int traw, t;
+ int vraw, v;
+ int rv;
+ int addr = sensor->addr;
+
+ rv = i2c_read16(TMP006_PORT(addr), TMP006_REG(addr), 0x01, &traw);
+ if (rv)
+ return -1;
+ t = (int)(int16_t)traw / 128 + 273;
+
+ rv = i2c_read16(TMP006_PORT(addr), TMP006_REG(addr), 0x00, &vraw);
+ if (rv)
+ return -1;
+ v = ((int)(int16_t)vraw * 15625) / 100;
+
+ return temp_sensor_tmp006_calculate_object_temp(t * 100, v, 6400);
+}
+
void temp_sensor_tmp006_config(const struct temp_sensor_t* sensor)
{
int addr = sensor->addr;
@@ -132,6 +204,44 @@ static int command_sensor_info(int argc, char ** argv)
}
DECLARE_CONSOLE_COMMAND(tempsinfo, command_sensor_info);
+/* TMP006 object temperature calculation command.
+ * TODO: This command is only for debugging. Remove it when temporal correciton
+ * is done.
+ */
+static int command_sensor_remote(int argc, char **argv)
+{
+ char *e;
+ int32_t Td2, Vobj9, Sm03;
+
+ if (argc != 4) {
+ uart_puts("Usage: tempcorrect <Tdie*100> <Vobj*10^9> <S0*10^11>\n");
+ return EC_ERROR_UNKNOWN;
+ }
+
+ Td2 = strtoi(argv[1], &e, 0);
+ if (e && *e) {
+ uart_puts("Bad Tdie.\n");
+ return EC_ERROR_UNKNOWN;
+ }
+
+ Vobj9 = strtoi(argv[2], &e, 0);
+ if (e && *e) {
+ uart_puts("Bad Vobj.\n");
+ return EC_ERROR_UNKNOWN;
+ }
+
+ Sm03 = strtoi(argv[3], &e, 0);
+ if (e && *e) {
+ uart_puts("Bad S0.\n");
+ return EC_ERROR_UNKNOWN;
+ }
+
+ uart_printf("%d\n",
+ temp_sensor_tmp006_calculate_object_temp(Td2, Vobj9, Sm03));
+
+ return EC_SUCCESS;
+}
+DECLARE_CONSOLE_COMMAND(tempremote, command_sensor_remote);
/*****************************************************************************/
/* Initialization */
diff --git a/include/temp_sensor.h b/include/temp_sensor.h
index df937112e1..a89dbe7e5a 100644
--- a/include/temp_sensor.h
+++ b/include/temp_sensor.h
@@ -45,8 +45,11 @@ int temp_sensor_read(enum temp_sensor_id id);
#define TMP006_PORT(ADDR) (ADDR >> 16)
#define TMP006_REG(ADDR) (ADDR & 0xffff)
-/* Read TI TMP006 temperature sensor. Return temperature in K. */
-int temp_sensor_tmp006_read(const struct temp_sensor_t* sensor);
+/* Read TI TMP006 die temperature sensor. Return temperature in K. */
+int temp_sensor_tmp006_read_die_temp(const struct temp_sensor_t* sensor);
+
+/* Read TI TMP006 object temperature sensor. Return temperature in K. */
+int temp_sensor_tmp006_read_object_temp(const struct temp_sensor_t* sensor);
/* Configure TMP006 DRDY pin. */
void temp_sensor_tmp006_config(const struct temp_sensor_t* sensor);