aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuenter Roeck <linux@roeck-us.net>2016-06-20 12:55:46 -0400
committerGuenter Roeck <linux@roeck-us.net>2016-07-12 17:24:14 -0400
commit28a340db9043f11dfd092c1b8ea4043f59cc0ca1 (patch)
tree01889c6f36fc6fa9537f7cc6bc4c4484ca983714
parenta9f92ccf334f7e15124193b1d7b89b7e6e6624e2 (diff)
hwmon: (tmp102) Convert to use regmap, and drop local cache
By converting the driver to regmap, we can use regmap to cache non-volatile registers. Stop caching the temperature register; while potentially reading it more often can result in reading it more often than necessary, this is offset by the gain due to not re-reading the limit registers. A positive side effect of this change is that limit registers can now be read and updated before the first temperature conversion is complete. Acked-by: Nishanth Menon <nm@ti.com> Signed-off-by: Guenter Roeck <linux@roeck-us.net>
-rw-r--r--drivers/hwmon/Kconfig1
-rw-r--r--drivers/hwmon/tmp102.c148
2 files changed, 71 insertions, 78 deletions
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index f271353b4b55..e72cd3d33d4e 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -1561,6 +1561,7 @@ config SENSORS_TMP102
1561 tristate "Texas Instruments TMP102" 1561 tristate "Texas Instruments TMP102"
1562 depends on I2C 1562 depends on I2C
1563 depends on THERMAL || !THERMAL_OF 1563 depends on THERMAL || !THERMAL_OF
1564 select REGMAP_I2C
1564 help 1565 help
1565 If you say yes here you get support for Texas Instruments TMP102 1566 If you say yes here you get support for Texas Instruments TMP102
1566 sensor chips. 1567 sensor chips.
diff --git a/drivers/hwmon/tmp102.c b/drivers/hwmon/tmp102.c
index 82a8a29af2e4..a942a2574a4d 100644
--- a/drivers/hwmon/tmp102.c
+++ b/drivers/hwmon/tmp102.c
@@ -24,6 +24,7 @@
24#include <linux/mutex.h> 24#include <linux/mutex.h>
25#include <linux/device.h> 25#include <linux/device.h>
26#include <linux/jiffies.h> 26#include <linux/jiffies.h>
27#include <linux/regmap.h>
27#include <linux/thermal.h> 28#include <linux/thermal.h>
28#include <linux/of.h> 29#include <linux/of.h>
29 30
@@ -61,13 +62,9 @@
61#define CONVERSION_TIME_MS 35 /* in milli-seconds */ 62#define CONVERSION_TIME_MS 35 /* in milli-seconds */
62 63
63struct tmp102 { 64struct tmp102 {
64 struct i2c_client *client; 65 struct regmap *regmap;
65 struct mutex lock;
66 u16 config_orig; 66 u16 config_orig;
67 unsigned long last_update;
68 unsigned long ready_time; 67 unsigned long ready_time;
69 bool valid;
70 int temp[3];
71}; 68};
72 69
73/* convert left adjusted 13-bit TMP102 register value to milliCelsius */ 70/* convert left adjusted 13-bit TMP102 register value to milliCelsius */
@@ -82,45 +79,22 @@ static inline u16 tmp102_mC_to_reg(int val)
82 return (val * 128) / 1000; 79 return (val * 128) / 1000;
83} 80}
84 81
85static const u8 tmp102_reg[] = {
86 TMP102_TEMP_REG,
87 TMP102_TLOW_REG,
88 TMP102_THIGH_REG,
89};
90
91static void tmp102_update_device(struct device *dev)
92{
93 struct tmp102 *tmp102 = dev_get_drvdata(dev);
94 struct i2c_client *client = tmp102->client;
95
96 mutex_lock(&tmp102->lock);
97 if (!tmp102->valid ||
98 time_after(jiffies, tmp102->last_update + HZ / 3)) {
99 int i;
100 for (i = 0; i < ARRAY_SIZE(tmp102->temp); ++i) {
101 int status = i2c_smbus_read_word_swapped(client,
102 tmp102_reg[i]);
103 if (status > -1)
104 tmp102->temp[i] = tmp102_reg_to_mC(status);
105 }
106 tmp102->last_update = jiffies;
107 tmp102->valid = true;
108 }
109 mutex_unlock(&tmp102->lock);
110}
111
112static int tmp102_read_temp(void *dev, int *temp) 82static int tmp102_read_temp(void *dev, int *temp)
113{ 83{
114 struct tmp102 *tmp102 = dev_get_drvdata(dev); 84 struct tmp102 *tmp102 = dev_get_drvdata(dev);
85 unsigned int reg;
86 int ret;
115 87
116 if (time_before(jiffies, tmp102->ready_time)) { 88 if (time_before(jiffies, tmp102->ready_time)) {
117 dev_dbg(dev, "%s: Conversion not ready yet..\n", __func__); 89 dev_dbg(dev, "%s: Conversion not ready yet..\n", __func__);
118 return -EAGAIN; 90 return -EAGAIN;
119 } 91 }
120 92
121 tmp102_update_device(dev); 93 ret = regmap_read(tmp102->regmap, TMP102_TEMP_REG, &reg);
94 if (ret < 0)
95 return ret;
122 96
123 *temp = tmp102->temp[0]; 97 *temp = tmp102_reg_to_mC(reg);
124 98
125 return 0; 99 return 0;
126} 100}
@@ -131,13 +105,19 @@ static ssize_t tmp102_show_temp(struct device *dev,
131{ 105{
132 struct sensor_device_attribute *sda = to_sensor_dev_attr(attr); 106 struct sensor_device_attribute *sda = to_sensor_dev_attr(attr);
133 struct tmp102 *tmp102 = dev_get_drvdata(dev); 107 struct tmp102 *tmp102 = dev_get_drvdata(dev);
108 int regaddr = sda->index;
109 unsigned int reg;
110 int err;
134 111
135 if (time_before(jiffies, tmp102->ready_time)) 112 if (regaddr == TMP102_TEMP_REG &&
113 time_before(jiffies, tmp102->ready_time))
136 return -EAGAIN; 114 return -EAGAIN;
137 115
138 tmp102_update_device(dev); 116 err = regmap_read(tmp102->regmap, regaddr, &reg);
117 if (err < 0)
118 return err;
139 119
140 return sprintf(buf, "%d\n", tmp102->temp[sda->index]); 120 return sprintf(buf, "%d\n", tmp102_reg_to_mC(reg));
141} 121}
142 122
143static ssize_t tmp102_set_temp(struct device *dev, 123static ssize_t tmp102_set_temp(struct device *dev,
@@ -146,29 +126,26 @@ static ssize_t tmp102_set_temp(struct device *dev,
146{ 126{
147 struct sensor_device_attribute *sda = to_sensor_dev_attr(attr); 127 struct sensor_device_attribute *sda = to_sensor_dev_attr(attr);
148 struct tmp102 *tmp102 = dev_get_drvdata(dev); 128 struct tmp102 *tmp102 = dev_get_drvdata(dev);
149 struct i2c_client *client = tmp102->client; 129 int reg = sda->index;
150 long val; 130 long val;
151 int status; 131 int err;
152 132
153 if (kstrtol(buf, 10, &val) < 0) 133 if (kstrtol(buf, 10, &val) < 0)
154 return -EINVAL; 134 return -EINVAL;
155 val = clamp_val(val, -256000, 255000); 135 val = clamp_val(val, -256000, 255000);
156 136
157 mutex_lock(&tmp102->lock); 137 err = regmap_write(tmp102->regmap, reg, tmp102_mC_to_reg(val));
158 tmp102->temp[sda->index] = val; 138 return err ? : count;
159 status = i2c_smbus_write_word_swapped(client, tmp102_reg[sda->index],
160 tmp102_mC_to_reg(val));
161 mutex_unlock(&tmp102->lock);
162 return status ? : count;
163} 139}
164 140
165static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, tmp102_show_temp, NULL , 0); 141static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, tmp102_show_temp, NULL,
142 TMP102_TEMP_REG);
166 143
167static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO, tmp102_show_temp, 144static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO, tmp102_show_temp,
168 tmp102_set_temp, 1); 145 tmp102_set_temp, TMP102_TLOW_REG);
169 146
170static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, tmp102_show_temp, 147static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, tmp102_show_temp,
171 tmp102_set_temp, 2); 148 tmp102_set_temp, TMP102_THIGH_REG);
172 149
173static struct attribute *tmp102_attrs[] = { 150static struct attribute *tmp102_attrs[] = {
174 &sensor_dev_attr_temp1_input.dev_attr.attr, 151 &sensor_dev_attr_temp1_input.dev_attr.attr,
@@ -185,19 +162,39 @@ static const struct thermal_zone_of_device_ops tmp102_of_thermal_ops = {
185static void tmp102_restore_config(void *data) 162static void tmp102_restore_config(void *data)
186{ 163{
187 struct tmp102 *tmp102 = data; 164 struct tmp102 *tmp102 = data;
188 struct i2c_client *client = tmp102->client;
189 165
190 i2c_smbus_write_word_swapped(client, TMP102_CONF_REG, 166 regmap_write(tmp102->regmap, TMP102_CONF_REG, tmp102->config_orig);
191 tmp102->config_orig); 167}
168
169static bool tmp102_is_writeable_reg(struct device *dev, unsigned int reg)
170{
171 return reg != TMP102_TEMP_REG;
192} 172}
193 173
174static bool tmp102_is_volatile_reg(struct device *dev, unsigned int reg)
175{
176 return reg == TMP102_TEMP_REG;
177}
178
179static const struct regmap_config tmp102_regmap_config = {
180 .reg_bits = 8,
181 .val_bits = 16,
182 .max_register = TMP102_THIGH_REG,
183 .writeable_reg = tmp102_is_writeable_reg,
184 .volatile_reg = tmp102_is_volatile_reg,
185 .val_format_endian = REGMAP_ENDIAN_BIG,
186 .cache_type = REGCACHE_RBTREE,
187 .use_single_rw = true,
188};
189
194static int tmp102_probe(struct i2c_client *client, 190static int tmp102_probe(struct i2c_client *client,
195 const struct i2c_device_id *id) 191 const struct i2c_device_id *id)
196{ 192{
197 struct device *dev = &client->dev; 193 struct device *dev = &client->dev;
198 struct device *hwmon_dev; 194 struct device *hwmon_dev;
199 struct tmp102 *tmp102; 195 struct tmp102 *tmp102;
200 int status; 196 unsigned int regval;
197 int err;
201 198
202 if (!i2c_check_functionality(client->adapter, 199 if (!i2c_check_functionality(client->adapter,
203 I2C_FUNC_SMBUS_WORD_DATA)) { 200 I2C_FUNC_SMBUS_WORD_DATA)) {
@@ -211,35 +208,36 @@ static int tmp102_probe(struct i2c_client *client,
211 return -ENOMEM; 208 return -ENOMEM;
212 209
213 i2c_set_clientdata(client, tmp102); 210 i2c_set_clientdata(client, tmp102);
214 tmp102->client = client;
215 211
216 status = i2c_smbus_read_word_swapped(client, TMP102_CONF_REG); 212 tmp102->regmap = devm_regmap_init_i2c(client, &tmp102_regmap_config);
217 if (status < 0) { 213 if (IS_ERR(tmp102->regmap))
214 return PTR_ERR(tmp102->regmap);
215
216 err = regmap_read(tmp102->regmap, TMP102_CONF_REG, &regval);
217 if (err < 0) {
218 dev_err(dev, "error reading config register\n"); 218 dev_err(dev, "error reading config register\n");
219 return status; 219 return err;
220 } 220 }
221 221
222 if ((status & ~TMP102_CONFREG_MASK) != 222 if ((regval & ~TMP102_CONFREG_MASK) !=
223 (TMP102_CONF_R0 | TMP102_CONF_R1)) { 223 (TMP102_CONF_R0 | TMP102_CONF_R1)) {
224 dev_err(dev, "unexpected config register value\n"); 224 dev_err(dev, "unexpected config register value\n");
225 return -ENODEV; 225 return -ENODEV;
226 } 226 }
227 227
228 tmp102->config_orig = status; 228 tmp102->config_orig = regval;
229 229
230 devm_add_action(dev, tmp102_restore_config, tmp102); 230 devm_add_action(dev, tmp102_restore_config, tmp102);
231 231
232 status &= ~TMP102_CONFIG_CLEAR; 232 regval &= ~TMP102_CONFIG_CLEAR;
233 status |= TMP102_CONFIG_SET; 233 regval |= TMP102_CONFIG_SET;
234 234
235 status = i2c_smbus_write_word_swapped(client, TMP102_CONF_REG, status); 235 err = regmap_write(tmp102->regmap, TMP102_CONF_REG, regval);
236 if (status < 0) { 236 if (err < 0) {
237 dev_err(dev, "error writing config register\n"); 237 dev_err(dev, "error writing config register\n");
238 return status; 238 return err;
239 } 239 }
240 240
241 mutex_init(&tmp102->lock);
242
243 tmp102->ready_time = jiffies; 241 tmp102->ready_time = jiffies;
244 if (tmp102->config_orig & TMP102_CONF_SD) { 242 if (tmp102->config_orig & TMP102_CONF_SD) {
245 /* 243 /*
@@ -268,30 +266,24 @@ static int tmp102_probe(struct i2c_client *client,
268static int tmp102_suspend(struct device *dev) 266static int tmp102_suspend(struct device *dev)
269{ 267{
270 struct i2c_client *client = to_i2c_client(dev); 268 struct i2c_client *client = to_i2c_client(dev);
271 int config; 269 struct tmp102 *tmp102 = i2c_get_clientdata(client);
272
273 config = i2c_smbus_read_word_swapped(client, TMP102_CONF_REG);
274 if (config < 0)
275 return config;
276 270
277 config |= TMP102_CONF_SD; 271 return regmap_update_bits(tmp102->regmap, TMP102_CONF_REG,
278 return i2c_smbus_write_word_swapped(client, TMP102_CONF_REG, config); 272 TMP102_CONF_SD, TMP102_CONF_SD);
279} 273}
280 274
281static int tmp102_resume(struct device *dev) 275static int tmp102_resume(struct device *dev)
282{ 276{
283 struct i2c_client *client = to_i2c_client(dev); 277 struct i2c_client *client = to_i2c_client(dev);
284 struct tmp102 *tmp102 = i2c_get_clientdata(client); 278 struct tmp102 *tmp102 = i2c_get_clientdata(client);
285 int config; 279 int err;
286 280
287 config = i2c_smbus_read_word_swapped(client, TMP102_CONF_REG); 281 err = regmap_update_bits(tmp102->regmap, TMP102_CONF_REG,
288 if (config < 0) 282 TMP102_CONF_SD, 0);
289 return config;
290 283
291 tmp102->ready_time = jiffies + msecs_to_jiffies(CONVERSION_TIME_MS); 284 tmp102->ready_time = jiffies + msecs_to_jiffies(CONVERSION_TIME_MS);
292 285
293 config &= ~TMP102_CONF_SD; 286 return err;
294 return i2c_smbus_write_word_swapped(client, TMP102_CONF_REG, config);
295} 287}
296#endif /* CONFIG_PM */ 288#endif /* CONFIG_PM */
297 289