summaryrefslogtreecommitdiff
path: root/drivers/misc
diff options
context:
space:
mode:
authorBitan Biswas <bbiswas@nvidia.com>2011-10-18 13:57:49 +0530
committerDan Willemsen <dwillemsen@nvidia.com>2011-11-30 21:49:51 -0800
commitb1f6fb0cc693811e406b53f6796d731a36f532d7 (patch)
tree99bde29b77c7d14cd6849c2d8de35d78a8a9af1b /drivers/misc
parentcc9368c0da2f333e00cb1592b5c3976a9a957aa3 (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.c60
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;
}