summaryrefslogtreecommitdiff
path: root/common/temp_sensor.c
diff options
context:
space:
mode:
authorVic Yang <victoryang@chromium.org>2012-02-16 15:35:24 -0800
committerVic Yang <victoryang@chromium.org>2012-02-16 15:37:44 -0800
commit284c2dbb8980b2aaf000b552abdbaeb045d13601 (patch)
tree38340e9ba0634fe2a86b46b145dd0ef97f3c8e18 /common/temp_sensor.c
parente75a32d2e3e9b62c47f4792d9ca17fb3b70b95d4 (diff)
downloadchrome-ec-284c2dbb8980b2aaf000b552abdbaeb045d13601.tar.gz
Add fixed-point temp calculation as backup option.
We prefer to use floating-point version but we might need fixed-point version in the future if we don't have FPU support. If CONFIG_FPU flag is not set, fixed-point object temperature calculation would be used. Signed-off-by: Vic Yang <victoryang@chromium.org> BUG=chrome-os-partner:7801 TEST=none Change-Id: I69364b10bedf1351206e52266d669b4c566bd6f6
Diffstat (limited to 'common/temp_sensor.c')
-rw-r--r--common/temp_sensor.c46
1 files changed, 46 insertions, 0 deletions
diff --git a/common/temp_sensor.c b/common/temp_sensor.c
index 80b3166e32..9313623213 100644
--- a/common/temp_sensor.c
+++ b/common/temp_sensor.c
@@ -53,6 +53,7 @@ int temp_sensor_tmp006_read_die_temp(const struct temp_sensor_t* sensor)
*/
int temp_sensor_tmp006_calculate_object_temp(int Tdie_i, int Vobj_i, int S0_i)
{
+#ifdef CONFIG_FPU
float Tdie, Vobj, S0;
float Tx, S, Vos, Vx, fv, Tobj, T4;
int Tobj_i;
@@ -80,6 +81,51 @@ int temp_sensor_tmp006_calculate_object_temp(int Tdie_i, int Vobj_i, int S0_i)
disable_fpu(Tobj_i);
return Tobj_i;
+#else
+ /* This is the fixed-point version of object temperature calculation.
+ * Should be accurate but it is hard to prevent and debug
+ * overflow/underflow problem. Only use this version if there is no
+ * FPU support.
+ * 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.
+ */
+ int32_t Tx, S19, Vos, Vx, fv9, ub, lb;
+
+ 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;
+#endif
}
int temp_sensor_tmp006_read_object_temp(const struct temp_sensor_t* sensor)