diff options
author | Bitan Biswas <bbiswas@nvidia.com> | 2011-10-18 13:57:49 +0530 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2011-11-30 21:49:51 -0800 |
commit | b1f6fb0cc693811e406b53f6796d731a36f532d7 (patch) | |
tree | 99bde29b77c7d14cd6849c2d8de35d78a8a9af1b /drivers/misc | |
parent | cc9368c0da2f333e00cb1592b5c3976a9a957aa3 (diff) |
misc: nct1008: idle read temperature
Check for nct1008 status busy bit before reading temperature
Reviewed-on: http://git-master/r/#change,56945
(cherry picked from commit 5a258b6567797bb402fe65ae01770bd593420431)
Reviewed-on: http://git-master/r/61750
(cherry picked from commit 20706ea39f7793567230faab86cbc4dcb107d1aa)
Change-Id: If275f8f4449cc39c73b7d9fa4b9b610db8d0fa7b
Reviewed-on: http://git-master/r/62327
Reviewed-by: Lokesh Pathak <lpathak@nvidia.com>
Tested-by: Lokesh Pathak <lpathak@nvidia.com>
Rebase-Id: Rbdc6b7f88fcb59ec3928505a4446a32c13ed683b
Diffstat (limited to 'drivers/misc')
-rw-r--r-- | drivers/misc/nct1008.c | 60 |
1 files changed, 58 insertions, 2 deletions
diff --git a/drivers/misc/nct1008.c b/drivers/misc/nct1008.c index 54c8c43d2330..f1690315f5d1 100644 --- a/drivers/misc/nct1008.c +++ b/drivers/misc/nct1008.c @@ -65,6 +65,12 @@ #define STANDBY_BIT BIT(6) #define ALERT_BIT BIT(7) +/* Status register bits */ +#define STATUS_BUSY BIT(7) + +/* Worst-case wait when nct1008 is busy */ +#define BUSY_TIMEOUT_MSEC 1000 + /* Max Temperature Measurements */ #define EXTENDED_RANGE_OFFSET 64U #define STANDARD_RANGE_MAX 127U @@ -75,6 +81,8 @@ #define MAX_STR_PRINT 50 +#define MIN_SLEEP_MSEC 20 + struct nct1008_data { struct work_struct work; struct i2c_client *client; @@ -98,6 +106,41 @@ static inline u8 temperature_to_value(bool extended, s8 temp) return extended ? (u8)(temp + EXTENDED_RANGE_OFFSET) : (u8)temp; } +/* Wait with timeout if busy */ +static int nct1008_wait_till_busy(struct i2c_client *client) +{ + int intr_status; + int msec_left = BUSY_TIMEOUT_MSEC; + bool is_busy; + + do { + intr_status = i2c_smbus_read_byte_data(client, STATUS_RD); + + if (intr_status < 0) { + dev_err(&client->dev, "%s, line=%d, i2c read error=%d\n" + , __func__, __LINE__, intr_status); + return intr_status; + } + + /* check for busy bit */ + is_busy = (intr_status & STATUS_BUSY) ? true : false; + if (is_busy) { + /* fastest nct1008 conversion rate ~15msec */ + /* using 20msec since msleep below 20 is not + * guaranteed to complete in specified duration */ + msleep(MIN_SLEEP_MSEC); + msec_left -= MIN_SLEEP_MSEC; + } + } while ((is_busy) && (msec_left > 0)); + + if (msec_left <= 0) { + dev_err(&client->dev, "error: nct1008 busy timed out\n"); + return -ETIMEDOUT; + } + + return 0; +} + static int nct1008_get_temp(struct device *dev, u8 *pTemp) { struct i2c_client *client = to_i2c_client(dev); @@ -106,6 +149,11 @@ static int nct1008_get_temp(struct device *dev, u8 *pTemp) u8 temp2; s8 temp; int value; + + value = nct1008_wait_till_busy(client); + if (value < 0) + goto error; + value = i2c_smbus_read_byte_data(client, LOCAL_TEMP_RD); if (value < 0) goto error; @@ -145,6 +193,10 @@ static ssize_t nct1008_show_temp(struct device *dev, if (!dev || !buf || !attr) return -EINVAL; + value = nct1008_wait_till_busy(client); + if (value < 0) + goto error; + value = i2c_smbus_read_byte_data(client, LOCAL_TEMP_RD); if (value < 0) goto error; @@ -330,6 +382,10 @@ static ssize_t nct1008_show_ext_temp(struct device *dev, if (!dev || !buf || !attr) return -EINVAL; + data = nct1008_wait_till_busy(client); + if (data < 0) + goto error; + /* When reading the full external temperature value, read the * LSB first. This causes the MSB to be locked (that is, the * ADC does not write to it) until it is read */ @@ -591,8 +647,8 @@ static void nct1008_work_func(struct work_struct *work) err = nct1008_disable_alert(data); if (err) { - dev_err(&data->client->dev, "%s: disable alert fail(error=%d)\n", - __func__, err); + dev_err(&data->client->dev, "%s: disable alert fail(error=%d)\n" + , __func__, err); return; } |