diff options
author | Guenter Roeck <linux@roeck-us.net> | 2016-06-19 23:34:57 -0400 |
---|---|---|
committer | Guenter Roeck <linux@roeck-us.net> | 2016-07-12 17:23:57 -0400 |
commit | 3d8f7a89a1979be7f631cf06e02f882adf144885 (patch) | |
tree | 4a041c0a793a9e20a80d9b6d5b70a7d008a2da01 | |
parent | 589f707c72426793a0f537592098a5a2a3117dc0 (diff) |
hwmon: (tmp102) Improve handling of initial read delay
If the chip was in shutdown mode when the driver was loaded, the first
conversion is ready no more than 35 milli-seconds after the chip was
taken out of shutdown. The driver delay was so far set to 333 ms (HZ / 3),
which is much higher than the maximum time needed by the chip.
Reduce the time to 35 milli-seconds.
Introduce a 'valid' flag to ensure that sensor data is actually read
even if requested less than 333 ms after the driver was loaded.
Acked-by: Nishanth Menon <nm@ti.com>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
-rw-r--r-- | drivers/hwmon/tmp102.c | 44 |
1 files changed, 30 insertions, 14 deletions
diff --git a/drivers/hwmon/tmp102.c b/drivers/hwmon/tmp102.c index 5bdf262e6a0e..fd4a4515692a 100644 --- a/drivers/hwmon/tmp102.c +++ b/drivers/hwmon/tmp102.c | |||
@@ -13,6 +13,7 @@ | |||
13 | * GNU General Public License for more details. | 13 | * GNU General Public License for more details. |
14 | */ | 14 | */ |
15 | 15 | ||
16 | #include <linux/delay.h> | ||
16 | #include <linux/module.h> | 17 | #include <linux/module.h> |
17 | #include <linux/init.h> | 18 | #include <linux/init.h> |
18 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
@@ -46,13 +47,16 @@ | |||
46 | #define TMP102_TLOW_REG 0x02 | 47 | #define TMP102_TLOW_REG 0x02 |
47 | #define TMP102_THIGH_REG 0x03 | 48 | #define TMP102_THIGH_REG 0x03 |
48 | 49 | ||
50 | #define CONVERSION_TIME_MS 35 /* in milli-seconds */ | ||
51 | |||
49 | struct tmp102 { | 52 | struct tmp102 { |
50 | struct i2c_client *client; | 53 | struct i2c_client *client; |
51 | struct mutex lock; | 54 | struct mutex lock; |
52 | u16 config_orig; | 55 | u16 config_orig; |
53 | unsigned long last_update; | 56 | unsigned long last_update; |
57 | unsigned long ready_time; | ||
58 | bool valid; | ||
54 | int temp[3]; | 59 | int temp[3]; |
55 | bool first_time; | ||
56 | }; | 60 | }; |
57 | 61 | ||
58 | /* convert left adjusted 13-bit TMP102 register value to milliCelsius */ | 62 | /* convert left adjusted 13-bit TMP102 register value to milliCelsius */ |
@@ -73,13 +77,14 @@ static const u8 tmp102_reg[] = { | |||
73 | TMP102_THIGH_REG, | 77 | TMP102_THIGH_REG, |
74 | }; | 78 | }; |
75 | 79 | ||
76 | static struct tmp102 *tmp102_update_device(struct device *dev) | 80 | static void tmp102_update_device(struct device *dev) |
77 | { | 81 | { |
78 | struct tmp102 *tmp102 = dev_get_drvdata(dev); | 82 | struct tmp102 *tmp102 = dev_get_drvdata(dev); |
79 | struct i2c_client *client = tmp102->client; | 83 | struct i2c_client *client = tmp102->client; |
80 | 84 | ||
81 | mutex_lock(&tmp102->lock); | 85 | mutex_lock(&tmp102->lock); |
82 | if (time_after(jiffies, tmp102->last_update + HZ / 3)) { | 86 | if (!tmp102->valid || |
87 | time_after(jiffies, tmp102->last_update + HZ / 3)) { | ||
83 | int i; | 88 | int i; |
84 | for (i = 0; i < ARRAY_SIZE(tmp102->temp); ++i) { | 89 | for (i = 0; i < ARRAY_SIZE(tmp102->temp); ++i) { |
85 | int status = i2c_smbus_read_word_swapped(client, | 90 | int status = i2c_smbus_read_word_swapped(client, |
@@ -88,22 +93,22 @@ static struct tmp102 *tmp102_update_device(struct device *dev) | |||
88 | tmp102->temp[i] = tmp102_reg_to_mC(status); | 93 | tmp102->temp[i] = tmp102_reg_to_mC(status); |
89 | } | 94 | } |
90 | tmp102->last_update = jiffies; | 95 | tmp102->last_update = jiffies; |
91 | tmp102->first_time = false; | 96 | tmp102->valid = true; |
92 | } | 97 | } |
93 | mutex_unlock(&tmp102->lock); | 98 | mutex_unlock(&tmp102->lock); |
94 | return tmp102; | ||
95 | } | 99 | } |
96 | 100 | ||
97 | static int tmp102_read_temp(void *dev, int *temp) | 101 | static int tmp102_read_temp(void *dev, int *temp) |
98 | { | 102 | { |
99 | struct tmp102 *tmp102 = tmp102_update_device(dev); | 103 | struct tmp102 *tmp102 = dev_get_drvdata(dev); |
100 | 104 | ||
101 | /* Is it too early even to return a conversion? */ | 105 | if (time_before(jiffies, tmp102->ready_time)) { |
102 | if (tmp102->first_time) { | ||
103 | dev_dbg(dev, "%s: Conversion not ready yet..\n", __func__); | 106 | dev_dbg(dev, "%s: Conversion not ready yet..\n", __func__); |
104 | return -EAGAIN; | 107 | return -EAGAIN; |
105 | } | 108 | } |
106 | 109 | ||
110 | tmp102_update_device(dev); | ||
111 | |||
107 | *temp = tmp102->temp[0]; | 112 | *temp = tmp102->temp[0]; |
108 | 113 | ||
109 | return 0; | 114 | return 0; |
@@ -114,12 +119,13 @@ static ssize_t tmp102_show_temp(struct device *dev, | |||
114 | char *buf) | 119 | char *buf) |
115 | { | 120 | { |
116 | struct sensor_device_attribute *sda = to_sensor_dev_attr(attr); | 121 | struct sensor_device_attribute *sda = to_sensor_dev_attr(attr); |
117 | struct tmp102 *tmp102 = tmp102_update_device(dev); | 122 | struct tmp102 *tmp102 = dev_get_drvdata(dev); |
118 | 123 | ||
119 | /* Is it too early even to return a read? */ | 124 | if (time_before(jiffies, tmp102->ready_time)) |
120 | if (tmp102->first_time) | ||
121 | return -EAGAIN; | 125 | return -EAGAIN; |
122 | 126 | ||
127 | tmp102_update_device(dev); | ||
128 | |||
123 | return sprintf(buf, "%d\n", tmp102->temp[sda->index]); | 129 | return sprintf(buf, "%d\n", tmp102->temp[sda->index]); |
124 | } | 130 | } |
125 | 131 | ||
@@ -224,11 +230,18 @@ static int tmp102_probe(struct i2c_client *client, | |||
224 | dev_err(dev, "config settings did not stick\n"); | 230 | dev_err(dev, "config settings did not stick\n"); |
225 | return -ENODEV; | 231 | return -ENODEV; |
226 | } | 232 | } |
227 | tmp102->last_update = jiffies; | 233 | |
228 | /* Mark that we are not ready with data until conversion is complete */ | ||
229 | tmp102->first_time = true; | ||
230 | mutex_init(&tmp102->lock); | 234 | mutex_init(&tmp102->lock); |
231 | 235 | ||
236 | tmp102->ready_time = jiffies; | ||
237 | if (tmp102->config_orig & TMP102_CONF_SD) { | ||
238 | /* | ||
239 | * Mark that we are not ready with data until the first | ||
240 | * conversion is complete | ||
241 | */ | ||
242 | tmp102->ready_time += msecs_to_jiffies(CONVERSION_TIME_MS); | ||
243 | } | ||
244 | |||
232 | hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, | 245 | hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, |
233 | tmp102, | 246 | tmp102, |
234 | tmp102_groups); | 247 | tmp102_groups); |
@@ -261,12 +274,15 @@ static int tmp102_suspend(struct device *dev) | |||
261 | static int tmp102_resume(struct device *dev) | 274 | static int tmp102_resume(struct device *dev) |
262 | { | 275 | { |
263 | struct i2c_client *client = to_i2c_client(dev); | 276 | struct i2c_client *client = to_i2c_client(dev); |
277 | struct tmp102 *tmp102 = i2c_get_clientdata(client); | ||
264 | int config; | 278 | int config; |
265 | 279 | ||
266 | config = i2c_smbus_read_word_swapped(client, TMP102_CONF_REG); | 280 | config = i2c_smbus_read_word_swapped(client, TMP102_CONF_REG); |
267 | if (config < 0) | 281 | if (config < 0) |
268 | return config; | 282 | return config; |
269 | 283 | ||
284 | tmp102->ready_time = jiffies + msecs_to_jiffies(CONVERSION_TIME_MS); | ||
285 | |||
270 | config &= ~TMP102_CONF_SD; | 286 | config &= ~TMP102_CONF_SD; |
271 | return i2c_smbus_write_word_swapped(client, TMP102_CONF_REG, config); | 287 | return i2c_smbus_write_word_swapped(client, TMP102_CONF_REG, config); |
272 | } | 288 | } |