1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* tmp421.c |
3 | * |
4 | * Copyright (C) 2009 Andre Prendel <andre.prendel@gmx.de> |
5 | * Preliminary support by: |
6 | * Melvin Rook, Raymond Ng |
7 | */ |
8 | |
9 | /* |
10 | * Driver for the Texas Instruments TMP421 SMBus temperature sensor IC. |
11 | * Supported models: TMP421, TMP422, TMP423, TMP441, TMP442 |
12 | */ |
13 | |
14 | #include <linux/module.h> |
15 | #include <linux/init.h> |
16 | #include <linux/slab.h> |
17 | #include <linux/jiffies.h> |
18 | #include <linux/i2c.h> |
19 | #include <linux/hwmon.h> |
20 | #include <linux/hwmon-sysfs.h> |
21 | #include <linux/err.h> |
22 | #include <linux/mutex.h> |
23 | #include <linux/of.h> |
24 | #include <linux/sysfs.h> |
25 | |
26 | /* Addresses to scan */ |
27 | static const unsigned short normal_i2c[] = { 0x2a, 0x4c, 0x4d, 0x4e, 0x4f, |
28 | I2C_CLIENT_END }; |
29 | |
30 | enum chips { tmp421, tmp422, tmp423, tmp441, tmp442 }; |
31 | |
32 | #define MAX_CHANNELS 4 |
33 | /* The TMP421 registers */ |
34 | #define TMP421_STATUS_REG 0x08 |
35 | #define TMP421_CONFIG_REG_1 0x09 |
36 | #define TMP421_CONFIG_REG_2 0x0A |
37 | #define TMP421_CONFIG_REG_REN(x) (BIT(3 + (x))) |
38 | #define TMP421_CONFIG_REG_REN_MASK GENMASK(6, 3) |
39 | #define TMP421_CONVERSION_RATE_REG 0x0B |
40 | #define TMP421_N_FACTOR_REG_1 0x21 |
41 | #define TMP421_MANUFACTURER_ID_REG 0xFE |
42 | #define TMP421_DEVICE_ID_REG 0xFF |
43 | |
44 | static const u8 TMP421_TEMP_MSB[MAX_CHANNELS] = { 0x00, 0x01, 0x02, 0x03 }; |
45 | static const u8 TMP421_TEMP_LSB[MAX_CHANNELS] = { 0x10, 0x11, 0x12, 0x13 }; |
46 | |
47 | /* Flags */ |
48 | #define TMP421_CONFIG_SHUTDOWN 0x40 |
49 | #define TMP421_CONFIG_RANGE 0x04 |
50 | |
51 | /* Manufacturer / Device ID's */ |
52 | #define TMP421_MANUFACTURER_ID 0x55 |
53 | #define TMP421_DEVICE_ID 0x21 |
54 | #define TMP422_DEVICE_ID 0x22 |
55 | #define TMP423_DEVICE_ID 0x23 |
56 | #define TMP441_DEVICE_ID 0x41 |
57 | #define TMP442_DEVICE_ID 0x42 |
58 | |
59 | static const struct i2c_device_id tmp421_id[] = { |
60 | { "tmp421" , 2 }, |
61 | { "tmp422" , 3 }, |
62 | { "tmp423" , 4 }, |
63 | { "tmp441" , 2 }, |
64 | { "tmp442" , 3 }, |
65 | { } |
66 | }; |
67 | MODULE_DEVICE_TABLE(i2c, tmp421_id); |
68 | |
69 | static const struct of_device_id __maybe_unused tmp421_of_match[] = { |
70 | { |
71 | .compatible = "ti,tmp421" , |
72 | .data = (void *)2 |
73 | }, |
74 | { |
75 | .compatible = "ti,tmp422" , |
76 | .data = (void *)3 |
77 | }, |
78 | { |
79 | .compatible = "ti,tmp423" , |
80 | .data = (void *)4 |
81 | }, |
82 | { |
83 | .compatible = "ti,tmp441" , |
84 | .data = (void *)2 |
85 | }, |
86 | { |
87 | .compatible = "ti,tmp442" , |
88 | .data = (void *)3 |
89 | }, |
90 | { }, |
91 | }; |
92 | MODULE_DEVICE_TABLE(of, tmp421_of_match); |
93 | |
94 | struct tmp421_channel { |
95 | const char *label; |
96 | bool enabled; |
97 | s16 temp; |
98 | }; |
99 | |
100 | struct tmp421_data { |
101 | struct i2c_client *client; |
102 | struct mutex update_lock; |
103 | u32 temp_config[MAX_CHANNELS + 1]; |
104 | struct hwmon_channel_info temp_info; |
105 | const struct hwmon_channel_info *info[2]; |
106 | struct hwmon_chip_info chip; |
107 | bool valid; |
108 | unsigned long last_updated; |
109 | unsigned long channels; |
110 | u8 config; |
111 | struct tmp421_channel channel[MAX_CHANNELS]; |
112 | }; |
113 | |
114 | static int temp_from_raw(u16 reg, bool extended) |
115 | { |
116 | /* Mask out status bits */ |
117 | int temp = reg & ~0xf; |
118 | |
119 | if (extended) |
120 | temp = temp - 64 * 256; |
121 | else |
122 | temp = (s16)temp; |
123 | |
124 | return DIV_ROUND_CLOSEST(temp * 1000, 256); |
125 | } |
126 | |
127 | static int tmp421_update_device(struct tmp421_data *data) |
128 | { |
129 | struct i2c_client *client = data->client; |
130 | int ret = 0; |
131 | int i; |
132 | |
133 | mutex_lock(&data->update_lock); |
134 | |
135 | if (time_after(jiffies, data->last_updated + (HZ / 2)) || |
136 | !data->valid) { |
137 | ret = i2c_smbus_read_byte_data(client, TMP421_CONFIG_REG_1); |
138 | if (ret < 0) |
139 | goto exit; |
140 | data->config = ret; |
141 | |
142 | for (i = 0; i < data->channels; i++) { |
143 | ret = i2c_smbus_read_byte_data(client, command: TMP421_TEMP_MSB[i]); |
144 | if (ret < 0) |
145 | goto exit; |
146 | data->channel[i].temp = ret << 8; |
147 | |
148 | ret = i2c_smbus_read_byte_data(client, command: TMP421_TEMP_LSB[i]); |
149 | if (ret < 0) |
150 | goto exit; |
151 | data->channel[i].temp |= ret; |
152 | } |
153 | data->last_updated = jiffies; |
154 | data->valid = true; |
155 | } |
156 | |
157 | exit: |
158 | mutex_unlock(lock: &data->update_lock); |
159 | |
160 | if (ret < 0) { |
161 | data->valid = false; |
162 | return ret; |
163 | } |
164 | |
165 | return 0; |
166 | } |
167 | |
168 | static int tmp421_enable_channels(struct tmp421_data *data) |
169 | { |
170 | int err; |
171 | struct i2c_client *client = data->client; |
172 | struct device *dev = &client->dev; |
173 | int old = i2c_smbus_read_byte_data(client, TMP421_CONFIG_REG_2); |
174 | int new, i; |
175 | |
176 | if (old < 0) { |
177 | dev_err(dev, "error reading register, can't disable channels\n" ); |
178 | return old; |
179 | } |
180 | |
181 | new = old & ~TMP421_CONFIG_REG_REN_MASK; |
182 | for (i = 0; i < data->channels; i++) |
183 | if (data->channel[i].enabled) |
184 | new |= TMP421_CONFIG_REG_REN(i); |
185 | |
186 | if (new == old) |
187 | return 0; |
188 | |
189 | err = i2c_smbus_write_byte_data(client, TMP421_CONFIG_REG_2, value: new); |
190 | if (err < 0) |
191 | dev_err(dev, "error writing register, can't disable channels\n" ); |
192 | |
193 | return err; |
194 | } |
195 | |
196 | static int tmp421_read(struct device *dev, enum hwmon_sensor_types type, |
197 | u32 attr, int channel, long *val) |
198 | { |
199 | struct tmp421_data *tmp421 = dev_get_drvdata(dev); |
200 | int ret = 0; |
201 | |
202 | ret = tmp421_update_device(data: tmp421); |
203 | if (ret) |
204 | return ret; |
205 | |
206 | switch (attr) { |
207 | case hwmon_temp_input: |
208 | if (!tmp421->channel[channel].enabled) |
209 | return -ENODATA; |
210 | *val = temp_from_raw(reg: tmp421->channel[channel].temp, |
211 | extended: tmp421->config & TMP421_CONFIG_RANGE); |
212 | return 0; |
213 | case hwmon_temp_fault: |
214 | if (!tmp421->channel[channel].enabled) |
215 | return -ENODATA; |
216 | /* |
217 | * Any of OPEN or /PVLD bits indicate a hardware mulfunction |
218 | * and the conversion result may be incorrect |
219 | */ |
220 | *val = !!(tmp421->channel[channel].temp & 0x03); |
221 | return 0; |
222 | case hwmon_temp_enable: |
223 | *val = tmp421->channel[channel].enabled; |
224 | return 0; |
225 | default: |
226 | return -EOPNOTSUPP; |
227 | } |
228 | |
229 | } |
230 | |
231 | static int tmp421_read_string(struct device *dev, enum hwmon_sensor_types type, |
232 | u32 attr, int channel, const char **str) |
233 | { |
234 | struct tmp421_data *data = dev_get_drvdata(dev); |
235 | |
236 | *str = data->channel[channel].label; |
237 | |
238 | return 0; |
239 | } |
240 | |
241 | static int tmp421_write(struct device *dev, enum hwmon_sensor_types type, |
242 | u32 attr, int channel, long val) |
243 | { |
244 | struct tmp421_data *data = dev_get_drvdata(dev); |
245 | int ret; |
246 | |
247 | switch (attr) { |
248 | case hwmon_temp_enable: |
249 | data->channel[channel].enabled = val; |
250 | ret = tmp421_enable_channels(data); |
251 | break; |
252 | default: |
253 | ret = -EOPNOTSUPP; |
254 | } |
255 | |
256 | return ret; |
257 | } |
258 | |
259 | static umode_t tmp421_is_visible(const void *data, enum hwmon_sensor_types type, |
260 | u32 attr, int channel) |
261 | { |
262 | switch (attr) { |
263 | case hwmon_temp_fault: |
264 | case hwmon_temp_input: |
265 | return 0444; |
266 | case hwmon_temp_label: |
267 | return 0444; |
268 | case hwmon_temp_enable: |
269 | return 0644; |
270 | default: |
271 | return 0; |
272 | } |
273 | } |
274 | |
275 | static int tmp421_init_client(struct tmp421_data *data) |
276 | { |
277 | int config, config_orig; |
278 | struct i2c_client *client = data->client; |
279 | |
280 | /* Set the conversion rate to 2 Hz */ |
281 | i2c_smbus_write_byte_data(client, TMP421_CONVERSION_RATE_REG, value: 0x05); |
282 | |
283 | /* Start conversions (disable shutdown if necessary) */ |
284 | config = i2c_smbus_read_byte_data(client, TMP421_CONFIG_REG_1); |
285 | if (config < 0) { |
286 | dev_err(&client->dev, |
287 | "Could not read configuration register (%d)\n" , config); |
288 | return config; |
289 | } |
290 | |
291 | config_orig = config; |
292 | config &= ~TMP421_CONFIG_SHUTDOWN; |
293 | |
294 | if (config != config_orig) { |
295 | dev_info(&client->dev, "Enable monitoring chip\n" ); |
296 | i2c_smbus_write_byte_data(client, TMP421_CONFIG_REG_1, value: config); |
297 | } |
298 | |
299 | return tmp421_enable_channels(data); |
300 | } |
301 | |
302 | static int tmp421_detect(struct i2c_client *client, |
303 | struct i2c_board_info *info) |
304 | { |
305 | enum chips kind; |
306 | struct i2c_adapter *adapter = client->adapter; |
307 | static const char * const names[] = { |
308 | "TMP421" , "TMP422" , "TMP423" , |
309 | "TMP441" , "TMP442" |
310 | }; |
311 | int addr = client->addr; |
312 | u8 reg; |
313 | |
314 | if (!i2c_check_functionality(adap: adapter, I2C_FUNC_SMBUS_BYTE_DATA)) |
315 | return -ENODEV; |
316 | |
317 | reg = i2c_smbus_read_byte_data(client, TMP421_MANUFACTURER_ID_REG); |
318 | if (reg != TMP421_MANUFACTURER_ID) |
319 | return -ENODEV; |
320 | |
321 | reg = i2c_smbus_read_byte_data(client, TMP421_CONVERSION_RATE_REG); |
322 | if (reg & 0xf8) |
323 | return -ENODEV; |
324 | |
325 | reg = i2c_smbus_read_byte_data(client, TMP421_STATUS_REG); |
326 | if (reg & 0x7f) |
327 | return -ENODEV; |
328 | |
329 | reg = i2c_smbus_read_byte_data(client, TMP421_DEVICE_ID_REG); |
330 | switch (reg) { |
331 | case TMP421_DEVICE_ID: |
332 | kind = tmp421; |
333 | break; |
334 | case TMP422_DEVICE_ID: |
335 | if (addr == 0x2a) |
336 | return -ENODEV; |
337 | kind = tmp422; |
338 | break; |
339 | case TMP423_DEVICE_ID: |
340 | if (addr != 0x4c && addr != 0x4d) |
341 | return -ENODEV; |
342 | kind = tmp423; |
343 | break; |
344 | case TMP441_DEVICE_ID: |
345 | kind = tmp441; |
346 | break; |
347 | case TMP442_DEVICE_ID: |
348 | if (addr != 0x4c && addr != 0x4d) |
349 | return -ENODEV; |
350 | kind = tmp442; |
351 | break; |
352 | default: |
353 | return -ENODEV; |
354 | } |
355 | |
356 | strscpy(p: info->type, q: tmp421_id[kind].name, I2C_NAME_SIZE); |
357 | dev_info(&adapter->dev, "Detected TI %s chip at 0x%02x\n" , |
358 | names[kind], client->addr); |
359 | |
360 | return 0; |
361 | } |
362 | |
363 | static int tmp421_probe_child_from_dt(struct i2c_client *client, |
364 | struct device_node *child, |
365 | struct tmp421_data *data) |
366 | |
367 | { |
368 | struct device *dev = &client->dev; |
369 | u32 i; |
370 | s32 val; |
371 | int err; |
372 | |
373 | err = of_property_read_u32(np: child, propname: "reg" , out_value: &i); |
374 | if (err) { |
375 | dev_err(dev, "missing reg property of %pOFn\n" , child); |
376 | return err; |
377 | } |
378 | |
379 | if (i >= data->channels) { |
380 | dev_err(dev, "invalid reg %d of %pOFn\n" , i, child); |
381 | return -EINVAL; |
382 | } |
383 | |
384 | of_property_read_string(np: child, propname: "label" , out_string: &data->channel[i].label); |
385 | if (data->channel[i].label) |
386 | data->temp_config[i] |= HWMON_T_LABEL; |
387 | |
388 | data->channel[i].enabled = of_device_is_available(device: child); |
389 | |
390 | err = of_property_read_s32(np: child, propname: "ti,n-factor" , out_value: &val); |
391 | if (!err) { |
392 | if (i == 0) { |
393 | dev_err(dev, "n-factor can't be set for internal channel\n" ); |
394 | return -EINVAL; |
395 | } |
396 | |
397 | if (val > 127 || val < -128) { |
398 | dev_err(dev, "n-factor for channel %d invalid (%d)\n" , |
399 | i, val); |
400 | return -EINVAL; |
401 | } |
402 | i2c_smbus_write_byte_data(client, TMP421_N_FACTOR_REG_1 + i - 1, |
403 | value: val); |
404 | } |
405 | |
406 | return 0; |
407 | } |
408 | |
409 | static int tmp421_probe_from_dt(struct i2c_client *client, struct tmp421_data *data) |
410 | { |
411 | struct device *dev = &client->dev; |
412 | const struct device_node *np = dev->of_node; |
413 | struct device_node *child; |
414 | int err; |
415 | |
416 | for_each_child_of_node(np, child) { |
417 | if (strcmp(child->name, "channel" )) |
418 | continue; |
419 | |
420 | err = tmp421_probe_child_from_dt(client, child, data); |
421 | if (err) { |
422 | of_node_put(node: child); |
423 | return err; |
424 | } |
425 | } |
426 | |
427 | return 0; |
428 | } |
429 | |
430 | static const struct hwmon_ops tmp421_ops = { |
431 | .is_visible = tmp421_is_visible, |
432 | .read = tmp421_read, |
433 | .read_string = tmp421_read_string, |
434 | .write = tmp421_write, |
435 | }; |
436 | |
437 | static int tmp421_probe(struct i2c_client *client) |
438 | { |
439 | struct device *dev = &client->dev; |
440 | struct device *hwmon_dev; |
441 | struct tmp421_data *data; |
442 | int i, err; |
443 | |
444 | data = devm_kzalloc(dev, size: sizeof(struct tmp421_data), GFP_KERNEL); |
445 | if (!data) |
446 | return -ENOMEM; |
447 | |
448 | mutex_init(&data->update_lock); |
449 | if (client->dev.of_node) |
450 | data->channels = (unsigned long) |
451 | of_device_get_match_data(dev: &client->dev); |
452 | else |
453 | data->channels = i2c_match_id(id: tmp421_id, client)->driver_data; |
454 | data->client = client; |
455 | |
456 | for (i = 0; i < data->channels; i++) { |
457 | data->temp_config[i] = HWMON_T_INPUT | HWMON_T_FAULT | HWMON_T_ENABLE; |
458 | data->channel[i].enabled = true; |
459 | } |
460 | |
461 | err = tmp421_probe_from_dt(client, data); |
462 | if (err) |
463 | return err; |
464 | |
465 | err = tmp421_init_client(data); |
466 | if (err) |
467 | return err; |
468 | |
469 | data->chip.ops = &tmp421_ops; |
470 | data->chip.info = data->info; |
471 | |
472 | data->info[0] = &data->temp_info; |
473 | |
474 | data->temp_info.type = hwmon_temp; |
475 | data->temp_info.config = data->temp_config; |
476 | |
477 | hwmon_dev = devm_hwmon_device_register_with_info(dev, name: client->name, |
478 | drvdata: data, |
479 | info: &data->chip, |
480 | NULL); |
481 | return PTR_ERR_OR_ZERO(ptr: hwmon_dev); |
482 | } |
483 | |
484 | static struct i2c_driver tmp421_driver = { |
485 | .class = I2C_CLASS_HWMON, |
486 | .driver = { |
487 | .name = "tmp421" , |
488 | .of_match_table = of_match_ptr(tmp421_of_match), |
489 | }, |
490 | .probe = tmp421_probe, |
491 | .id_table = tmp421_id, |
492 | .detect = tmp421_detect, |
493 | .address_list = normal_i2c, |
494 | }; |
495 | |
496 | module_i2c_driver(tmp421_driver); |
497 | |
498 | MODULE_AUTHOR("Andre Prendel <andre.prendel@gmx.de>" ); |
499 | MODULE_DESCRIPTION("Texas Instruments TMP421/422/423/441/442 temperature sensor driver" ); |
500 | MODULE_LICENSE("GPL" ); |
501 | |