summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoshua Primero <jprimero@nvidia.com>2011-09-16 11:49:05 -0700
committerRohan Somvanshi <rsomvanshi@nvidia.com>2011-09-21 00:00:32 -0700
commit8ccc1756061c64a0fe113eddef2e3945a09e8795 (patch)
tree53c5a50ea3ea4babeb27c156c9fd2ac5ca0e906a
parent21e30b0910d6ee38eb7f1e68e21507a80758c74d (diff)
arm: tegra: power: Improved thermal accuracy
Instead of rounding up when measuring temperature in celsius, report back temperature in millicelsius. Change-Id: I5b99dd9f1c41e929d83a42662d693fe31a779a52 Reviewed-on: http://git-master/r/52953 Reviewed-by: Joshua Primero <jprimero@nvidia.com> Tested-by: Joshua Primero <jprimero@nvidia.com> Reviewed-by: Diwakar Tundlam <dtundlam@nvidia.com>
-rw-r--r--drivers/misc/nct1008.c89
1 files changed, 52 insertions, 37 deletions
diff --git a/drivers/misc/nct1008.c b/drivers/misc/nct1008.c
index d8323d7b1e67..7ba70c35021b 100644
--- a/drivers/misc/nct1008.c
+++ b/drivers/misc/nct1008.c
@@ -75,6 +75,9 @@
#define MAX_STR_PRINT 50
+#define CELSIUS_TO_MILLICELSIUS(x) ((x)*1000)
+#define MILLICELSIUS_TO_CELSIUS(x) ((x)/1000)
+
struct nct1008_data {
struct work_struct work;
struct i2c_client *client;
@@ -97,33 +100,41 @@ static inline u8 temperature_to_value(bool extended, s8 temp)
return extended ? (u8)(temp + EXTENDED_RANGE_OFFSET) : (u8)temp;
}
-static int nct1008_get_temp(struct device *dev, u8 *pTemp)
+static int nct1008_get_temp(struct device *dev, long *pTemp)
{
struct i2c_client *client = to_i2c_client(dev);
struct nct1008_platform_data *pdata = client->dev.platform_data;
- s8 temp1;
- u8 temp2;
- s8 temp;
- int value;
+ s8 temp_local;
+ u8 temp_ext_lo;
+ s8 temp_ext_hi;
+ long temp_ext_milli;
+ long temp_local_milli;
+ u8 value;
+
+ /* Read Local Temp */
value = i2c_smbus_read_byte_data(client, LOCAL_TEMP_RD);
if (value < 0)
goto error;
- temp1 = value_to_temperature(pdata->ext_range, value);
+ temp_local = value_to_temperature(pdata->ext_range, value);
+ temp_local_milli = CELSIUS_TO_MILLICELSIUS(temp_local);
+ /* Read External Temp */
value = i2c_smbus_read_byte_data(client, EXT_TEMP_RD_LO);
if (value < 0)
goto error;
- temp2 = (value >> 6);
+ temp_ext_lo = (value >> 6);
+
value = i2c_smbus_read_byte_data(client, EXT_TEMP_RD_HI);
if (value < 0)
goto error;
- temp = value_to_temperature(pdata->ext_range, value);
- if (temp2 > 0)
- *pTemp = max((int)temp1, (int)temp + 1);
- else
- *pTemp = max(temp1, temp);
+ temp_ext_hi = value_to_temperature(pdata->ext_range, value);
+
+ temp_ext_milli = CELSIUS_TO_MILLICELSIUS(temp_ext_hi) + temp_ext_lo * 250;
- dev_dbg(dev, "\n %s: ret temp=%dC ", __func__, *pTemp);
+ /* Return max between Local and External Temp */
+ *pTemp = max(temp_local_milli, temp_ext_milli);
+
+ dev_dbg(dev, "\n %s: ret temp=%ldC ", __func__, *pTemp);
return 0;
error:
dev_err(&client->dev, "\n error in file=: %s %s() line=%d: "
@@ -201,7 +212,7 @@ static ssize_t nct1008_set_temp_overheat(struct device *dev,
long int num;
int err;
u8 temp;
- u8 currTemp;
+ long currTemp;
struct i2c_client *client = to_i2c_client(dev);
struct nct1008_platform_data *pdata = client->dev.platform_data;
char bufTemp[MAX_STR_PRINT];
@@ -223,12 +234,14 @@ static ssize_t nct1008_set_temp_overheat(struct device *dev,
if (err)
goto error;
+ currTemp = MILLICELSIUS_TO_CELSIUS(currTemp);
+
if (currTemp >= (int)num) {
ret = nct1008_show_temp(dev, attr, bufTemp);
ret = nct1008_show_temp_overheat(dev, attr, bufOverheat);
dev_err(dev, "\nCurrent temp: %s ", bufTemp);
dev_err(dev, "\nOld overheat limit: %s ", bufOverheat);
- dev_err(dev, "\nReset from overheat: curr temp=%d, "
+ dev_err(dev, "\nReset from overheat: curr temp=%ld, "
"new overheat temp=%d\n\n", currTemp, (int)num);
}
@@ -537,30 +550,31 @@ static void nct1008_work_func(struct work_struct *work)
struct nct1008_data *data = container_of(work, struct nct1008_data,
work);
bool extended_range = data->plat_data.ext_range;
- u8 temperature, value;
+ long temp_milli;
+ u8 value;
int err = 0, i;
int hysteresis;
int nentries = data->limits_sz;
int lo_limit = 0, hi_limit = 0;
- int intr_status;
+ long throttling_ext_limit_milli;
+ int intr_status = i2c_smbus_read_byte_data(data->client, STATUS_RD);
- intr_status = i2c_smbus_read_byte_data(data->client, STATUS_RD);
if (intr_status < 0) {
pr_err("%s, line=%d, i2c read error=%d\n",
__func__, __LINE__, intr_status);
return;
}
- err = nct1008_get_temp(&data->client->dev, &temperature);
+ intr_status &= (BIT(3) | BIT(4));
+ if (!intr_status)
+ return;
+
+ err = nct1008_get_temp(&data->client->dev, &temp_milli);
if (err) {
pr_err("%s: get temp fail(%d)", __func__, err);
return;
}
- intr_status &= (BIT(3) | BIT(4));
- if (!intr_status)
- return;
-
err = nct1008_disable_alert(data);
if (err) {
pr_err("%s: disable alert fail(error=%d)\n",
@@ -568,30 +582,31 @@ static void nct1008_work_func(struct work_struct *work)
return;
}
-
hysteresis = ALERT_HYSTERESIS_EDP;
+ throttling_ext_limit_milli =
+ CELSIUS_TO_MILLICELSIUS(data->plat_data.throttling_ext_limit);
- if (temperature >= data->plat_data.throttling_ext_limit) {
+ if (temp_milli >= throttling_ext_limit_milli) {
/* start throttling */
therm_throttle(data, true);
hysteresis = ALERT_HYSTERESIS_THROTTLE;
- } else if (temperature <=
- (data->plat_data.throttling_ext_limit -
+ } else if (temp_milli <=
+ (throttling_ext_limit_milli -
ALERT_HYSTERESIS_THROTTLE)) {
/* switch off throttling */
therm_throttle(data, false);
}
- if (temperature < data->limits[0]) {
+ if (temp_milli < CELSIUS_TO_MILLICELSIUS(data->limits[0])) {
lo_limit = 0;
hi_limit = data->limits[0];
- } else if (temperature >= data->limits[nentries-1]) {
+ } else if (temp_milli >= CELSIUS_TO_MILLICELSIUS(data->limits[nentries-1])) {
lo_limit = data->limits[nentries-1] - hysteresis;
hi_limit = data->plat_data.shutdown_ext_limit;
} else {
for (i = 0; (i + 1) < nentries; i++) {
- if (temperature >= data->limits[i] &&
- temperature < data->limits[i + 1]) {
+ if (temp_milli >= CELSIUS_TO_MILLICELSIUS(data->limits[i]) &&
+ temp_milli < CELSIUS_TO_MILLICELSIUS(data->limits[i + 1])) {
lo_limit = data->limits[i] - hysteresis;
hi_limit = data->limits[i + 1];
break;
@@ -630,14 +645,14 @@ static void nct1008_work_func(struct work_struct *work)
}
/* inform edp governor */
- if (edp_thermal_zone_val != temperature)
+ if (edp_thermal_zone_val != temp_milli)
/*
* FIXME: Move this direct tegra_ function call to be called
* via a pointer in 'struct nct1008_data' (like 'alarm_fn')
*/
- tegra_edp_update_thermal_zone(temperature);
+ tegra_edp_update_thermal_zone(MILLICELSIUS_TO_CELSIUS(temp_milli));
- edp_thermal_zone_val = temperature;
+ edp_thermal_zone_val = temp_milli;
out:
nct1008_enable_alert(data);
@@ -874,7 +889,7 @@ static int __devinit nct1008_probe(struct i2c_client *client,
{
struct nct1008_data *data;
int err;
- u8 temperature;
+ long temp_milli;
unsigned int delay;
data = kzalloc(sizeof(struct nct1008_data), GFP_KERNEL);
@@ -919,13 +934,13 @@ static int __devinit nct1008_probe(struct i2c_client *client,
data->plat_data.conv_rate);
msleep(delay); /* 63msec for default conv rate 0x8 */
}
- err = nct1008_get_temp(&data->client->dev, &temperature);
+ err = nct1008_get_temp(&data->client->dev, &temp_milli);
if (err) {
pr_err("%s: get temp fail(%d)", __func__, err);
return 0; /*do not fail init on the 1st read */
}
- tegra_edp_update_thermal_zone(temperature);
+ tegra_edp_update_thermal_zone(MILLICELSIUS_TO_CELSIUS(temp_milli));
return 0;
error: