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
This commit is contained in:
Vic Yang
2012-02-16 15:35:24 -08:00
parent e75a32d2e3
commit 284c2dbb89

View File

@@ -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)