aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon
diff options
context:
space:
mode:
authorNishanth Menon <nm@ti.com>2015-12-01 11:10:21 -0500
committerGuenter Roeck <linux@roeck-us.net>2015-12-10 11:14:22 -0500
commit00917b5c55aeb01322d5ab51af8c025b82959224 (patch)
treed114d06b21ed7b46b374f437f5ca82702008246c /drivers/hwmon
parent527e9316f8ec44bd53d90fb9f611fa7ffff52bb9 (diff)
hwmon: (tmp102) Force wait for conversion time for the first valid data
TMP102 works based on conversions done periodically. However, as per the TMP102 data sheet[1] the first conversion is triggered immediately after we program the configuration register. The temperature data registers do not reflect proper data until the first conversion is complete (in our case HZ/4). The driver currently sets the last_update to be jiffies - HZ, just after the configuration is complete. When TMP102 driver registers with the thermal framework, it immediately tries to read the sensor temperature data. This takes place even before the conversion on the TMP102 is complete and results in an invalid temperature read. Depending on the value read, this may cause thermal framework to assume that a critical temperature event has occurred and attempts to shutdown the system. Instead of causing an invalid mid-conversion value to be read erroneously, we mark the last_update to be in-line with the current jiffies. This allows the tmp102_update_device function to skip update until the required conversion time is complete. Further, we ensure to return -EAGAIN result instead of returning spurious temperature (such as 0C) values to the caller to prevent any wrong decisions made with such values. NOTE: this allows the read functions not to be blocking and allows the callers to make the decision if they would like to block or try again later. At least the current user(thermal) seems to handle this by retrying later. A simpler alternative approach could be to sleep in the probe for the duration required, but that will result in latency that is undesirable and delay boot sequence un-necessarily. [1] http://www.ti.com/lit/ds/symlink/tmp102.pdf Cc: Eduardo Valentin <edubezval@gmail.com> Reported-by: Aparna Balasubramanian <aparnab@ti.com> Reported-by: Elvita Lobo <elvita@ti.com> Reported-by: Yan Liu <yan-liu@ti.com> Signed-off-by: Nishanth Menon <nm@ti.com> Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Diffstat (limited to 'drivers/hwmon')
-rw-r--r--drivers/hwmon/tmp102.c16
1 files changed, 15 insertions, 1 deletions
diff --git a/drivers/hwmon/tmp102.c b/drivers/hwmon/tmp102.c
index 65482624ea2c..5289aa0980a8 100644
--- a/drivers/hwmon/tmp102.c
+++ b/drivers/hwmon/tmp102.c
@@ -58,6 +58,7 @@ struct tmp102 {
58 u16 config_orig; 58 u16 config_orig;
59 unsigned long last_update; 59 unsigned long last_update;
60 int temp[3]; 60 int temp[3];
61 bool first_time;
61}; 62};
62 63
63/* convert left adjusted 13-bit TMP102 register value to milliCelsius */ 64/* convert left adjusted 13-bit TMP102 register value to milliCelsius */
@@ -93,6 +94,7 @@ static struct tmp102 *tmp102_update_device(struct device *dev)
93 tmp102->temp[i] = tmp102_reg_to_mC(status); 94 tmp102->temp[i] = tmp102_reg_to_mC(status);
94 } 95 }
95 tmp102->last_update = jiffies; 96 tmp102->last_update = jiffies;
97 tmp102->first_time = false;
96 } 98 }
97 mutex_unlock(&tmp102->lock); 99 mutex_unlock(&tmp102->lock);
98 return tmp102; 100 return tmp102;
@@ -102,6 +104,12 @@ static int tmp102_read_temp(void *dev, int *temp)
102{ 104{
103 struct tmp102 *tmp102 = tmp102_update_device(dev); 105 struct tmp102 *tmp102 = tmp102_update_device(dev);
104 106
107 /* Is it too early even to return a conversion? */
108 if (tmp102->first_time) {
109 dev_dbg(dev, "%s: Conversion not ready yet..\n", __func__);
110 return -EAGAIN;
111 }
112
105 *temp = tmp102->temp[0]; 113 *temp = tmp102->temp[0];
106 114
107 return 0; 115 return 0;
@@ -114,6 +122,10 @@ static ssize_t tmp102_show_temp(struct device *dev,
114 struct sensor_device_attribute *sda = to_sensor_dev_attr(attr); 122 struct sensor_device_attribute *sda = to_sensor_dev_attr(attr);
115 struct tmp102 *tmp102 = tmp102_update_device(dev); 123 struct tmp102 *tmp102 = tmp102_update_device(dev);
116 124
125 /* Is it too early even to return a read? */
126 if (tmp102->first_time)
127 return -EAGAIN;
128
117 return sprintf(buf, "%d\n", tmp102->temp[sda->index]); 129 return sprintf(buf, "%d\n", tmp102->temp[sda->index]);
118} 130}
119 131
@@ -207,7 +219,9 @@ static int tmp102_probe(struct i2c_client *client,
207 status = -ENODEV; 219 status = -ENODEV;
208 goto fail_restore_config; 220 goto fail_restore_config;
209 } 221 }
210 tmp102->last_update = jiffies - HZ; 222 tmp102->last_update = jiffies;
223 /* Mark that we are not ready with data until conversion is complete */
224 tmp102->first_time = true;
211 mutex_init(&tmp102->lock); 225 mutex_init(&tmp102->lock);
212 226
213 hwmon_dev = hwmon_device_register_with_groups(dev, client->name, 227 hwmon_dev = hwmon_device_register_with_groups(dev, client->name,