Commit | Line | Data |
---|---|---|
06160327 DR |
1 | /* |
2 | * lm95241.c - Part of lm_sensors, Linux kernel modules for hardware | |
3 | * monitoring | |
4 | * Copyright (C) 2008 Davide Rizzo <elpa-rizzo@gmail.com> | |
5 | * | |
6 | * Based on the max1619 driver. The LM95241 is a sensor chip made by National | |
7 | * Semiconductors. | |
8 | * It reports up to three temperatures (its own plus up to | |
9 | * two external ones). Complete datasheet can be | |
10 | * obtained from National's website at: | |
11 | * http://www.national.com/ds.cgi/LM/LM95241.pdf | |
12 | * | |
13 | * This program is free software; you can redistribute it and/or modify | |
14 | * it under the terms of the GNU General Public License as published by | |
15 | * the Free Software Foundation; either version 2 of the License, or | |
16 | * (at your option) any later version. | |
17 | * | |
18 | * This program is distributed in the hope that it will be useful, | |
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
21 | * GNU General Public License for more details. | |
22 | * | |
23 | * You should have received a copy of the GNU General Public License | |
24 | * along with this program; if not, write to the Free Software | |
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
26 | */ | |
27 | ||
28 | #include <linux/module.h> | |
29 | #include <linux/init.h> | |
30 | #include <linux/slab.h> | |
31 | #include <linux/jiffies.h> | |
32 | #include <linux/i2c.h> | |
33 | #include <linux/hwmon.h> | |
34 | #include <linux/hwmon-sysfs.h> | |
35 | #include <linux/err.h> | |
36 | #include <linux/mutex.h> | |
37 | #include <linux/sysfs.h> | |
38 | ||
39 | static const unsigned short normal_i2c[] = { | |
40 | 0x19, 0x2a, 0x2b, I2C_CLIENT_END}; | |
41 | ||
42 | /* Insmod parameters */ | |
43 | I2C_CLIENT_INSMOD_1(lm95241); | |
44 | ||
45 | /* LM95241 registers */ | |
46 | #define LM95241_REG_R_MAN_ID 0xFE | |
47 | #define LM95241_REG_R_CHIP_ID 0xFF | |
48 | #define LM95241_REG_R_STATUS 0x02 | |
49 | #define LM95241_REG_RW_CONFIG 0x03 | |
50 | #define LM95241_REG_RW_REM_FILTER 0x06 | |
51 | #define LM95241_REG_RW_TRUTHERM 0x07 | |
52 | #define LM95241_REG_W_ONE_SHOT 0x0F | |
53 | #define LM95241_REG_R_LOCAL_TEMPH 0x10 | |
54 | #define LM95241_REG_R_REMOTE1_TEMPH 0x11 | |
55 | #define LM95241_REG_R_REMOTE2_TEMPH 0x12 | |
56 | #define LM95241_REG_R_LOCAL_TEMPL 0x20 | |
57 | #define LM95241_REG_R_REMOTE1_TEMPL 0x21 | |
58 | #define LM95241_REG_R_REMOTE2_TEMPL 0x22 | |
59 | #define LM95241_REG_RW_REMOTE_MODEL 0x30 | |
60 | ||
61 | /* LM95241 specific bitfields */ | |
62 | #define CFG_STOP 0x40 | |
63 | #define CFG_CR0076 0x00 | |
64 | #define CFG_CR0182 0x10 | |
65 | #define CFG_CR1000 0x20 | |
66 | #define CFG_CR2700 0x30 | |
67 | #define R1MS_SHIFT 0 | |
68 | #define R2MS_SHIFT 2 | |
69 | #define R1MS_MASK (0x01 << (R1MS_SHIFT)) | |
70 | #define R2MS_MASK (0x01 << (R2MS_SHIFT)) | |
71 | #define R1DF_SHIFT 1 | |
72 | #define R2DF_SHIFT 2 | |
73 | #define R1DF_MASK (0x01 << (R1DF_SHIFT)) | |
74 | #define R2DF_MASK (0x01 << (R2DF_SHIFT)) | |
75 | #define R1FE_MASK 0x01 | |
76 | #define R2FE_MASK 0x05 | |
77 | #define TT1_SHIFT 0 | |
78 | #define TT2_SHIFT 4 | |
79 | #define TT_OFF 0 | |
80 | #define TT_ON 1 | |
81 | #define TT_MASK 7 | |
82 | #define MANUFACTURER_ID 0x01 | |
83 | #define DEFAULT_REVISION 0xA4 | |
84 | ||
85 | /* Conversions and various macros */ | |
86 | #define TEMP_FROM_REG(val_h, val_l) (((val_h) & 0x80 ? (val_h) - 0x100 : \ | |
87 | (val_h)) * 1000 + (val_l) * 1000 / 256) | |
88 | ||
89 | /* Functions declaration */ | |
06160327 | 90 | static void lm95241_init_client(struct i2c_client *client); |
06160327 DR |
91 | static struct lm95241_data *lm95241_update_device(struct device *dev); |
92 | ||
06160327 DR |
93 | /* Client data (each client gets its own) */ |
94 | struct lm95241_data { | |
06160327 DR |
95 | struct device *hwmon_dev; |
96 | struct mutex update_lock; | |
97 | unsigned long last_updated, rate; /* in jiffies */ | |
98 | char valid; /* zero until following fields are valid */ | |
99 | /* registers values */ | |
100 | u8 local_h, local_l; /* local */ | |
101 | u8 remote1_h, remote1_l; /* remote1 */ | |
102 | u8 remote2_h, remote2_l; /* remote2 */ | |
103 | u8 config, model, trutherm; | |
104 | }; | |
105 | ||
106 | /* Sysfs stuff */ | |
107 | #define show_temp(value) \ | |
108 | static ssize_t show_##value(struct device *dev, \ | |
109 | struct device_attribute *attr, char *buf) \ | |
110 | { \ | |
111 | struct lm95241_data *data = lm95241_update_device(dev); \ | |
112 | snprintf(buf, PAGE_SIZE - 1, "%d\n", \ | |
113 | TEMP_FROM_REG(data->value##_h, data->value##_l)); \ | |
114 | return strlen(buf); \ | |
115 | } | |
116 | show_temp(local); | |
117 | show_temp(remote1); | |
118 | show_temp(remote2); | |
119 | ||
120 | static ssize_t show_rate(struct device *dev, struct device_attribute *attr, | |
121 | char *buf) | |
122 | { | |
123 | struct lm95241_data *data = lm95241_update_device(dev); | |
124 | ||
125 | snprintf(buf, PAGE_SIZE - 1, "%lu\n", 1000 * data->rate / HZ); | |
126 | return strlen(buf); | |
127 | } | |
128 | ||
129 | static ssize_t set_rate(struct device *dev, struct device_attribute *attr, | |
130 | const char *buf, size_t count) | |
131 | { | |
132 | struct i2c_client *client = to_i2c_client(dev); | |
133 | struct lm95241_data *data = i2c_get_clientdata(client); | |
134 | ||
135 | strict_strtol(buf, 10, &data->rate); | |
136 | data->rate = data->rate * HZ / 1000; | |
137 | ||
138 | return count; | |
139 | } | |
140 | ||
141 | #define show_type(flag) \ | |
142 | static ssize_t show_type##flag(struct device *dev, \ | |
143 | struct device_attribute *attr, char *buf) \ | |
144 | { \ | |
145 | struct i2c_client *client = to_i2c_client(dev); \ | |
146 | struct lm95241_data *data = i2c_get_clientdata(client); \ | |
147 | \ | |
148 | snprintf(buf, PAGE_SIZE - 1, \ | |
149 | data->model & R##flag##MS_MASK ? "1\n" : "2\n"); \ | |
150 | return strlen(buf); \ | |
151 | } | |
152 | show_type(1); | |
153 | show_type(2); | |
154 | ||
155 | #define show_min(flag) \ | |
156 | static ssize_t show_min##flag(struct device *dev, \ | |
157 | struct device_attribute *attr, char *buf) \ | |
158 | { \ | |
159 | struct i2c_client *client = to_i2c_client(dev); \ | |
160 | struct lm95241_data *data = i2c_get_clientdata(client); \ | |
161 | \ | |
162 | snprintf(buf, PAGE_SIZE - 1, \ | |
163 | data->config & R##flag##DF_MASK ? \ | |
164 | "-127000\n" : "0\n"); \ | |
165 | return strlen(buf); \ | |
166 | } | |
167 | show_min(1); | |
168 | show_min(2); | |
169 | ||
170 | #define show_max(flag) \ | |
171 | static ssize_t show_max##flag(struct device *dev, \ | |
172 | struct device_attribute *attr, char *buf) \ | |
173 | { \ | |
174 | struct i2c_client *client = to_i2c_client(dev); \ | |
175 | struct lm95241_data *data = i2c_get_clientdata(client); \ | |
176 | \ | |
177 | snprintf(buf, PAGE_SIZE - 1, \ | |
178 | data->config & R##flag##DF_MASK ? \ | |
179 | "127000\n" : "255000\n"); \ | |
180 | return strlen(buf); \ | |
181 | } | |
182 | show_max(1); | |
183 | show_max(2); | |
184 | ||
185 | #define set_type(flag) \ | |
186 | static ssize_t set_type##flag(struct device *dev, \ | |
187 | struct device_attribute *attr, \ | |
188 | const char *buf, size_t count) \ | |
189 | { \ | |
190 | struct i2c_client *client = to_i2c_client(dev); \ | |
191 | struct lm95241_data *data = i2c_get_clientdata(client); \ | |
192 | \ | |
193 | long val; \ | |
194 | strict_strtol(buf, 10, &val); \ | |
195 | \ | |
196 | if ((val == 1) || (val == 2)) { \ | |
197 | \ | |
198 | mutex_lock(&data->update_lock); \ | |
199 | \ | |
200 | data->trutherm &= ~(TT_MASK << TT##flag##_SHIFT); \ | |
201 | if (val == 1) { \ | |
202 | data->model |= R##flag##MS_MASK; \ | |
203 | data->trutherm |= (TT_ON << TT##flag##_SHIFT); \ | |
204 | } \ | |
205 | else { \ | |
206 | data->model &= ~R##flag##MS_MASK; \ | |
207 | data->trutherm |= (TT_OFF << TT##flag##_SHIFT); \ | |
208 | } \ | |
209 | \ | |
210 | data->valid = 0; \ | |
211 | \ | |
212 | i2c_smbus_write_byte_data(client, LM95241_REG_RW_REMOTE_MODEL, \ | |
213 | data->model); \ | |
214 | i2c_smbus_write_byte_data(client, LM95241_REG_RW_TRUTHERM, \ | |
215 | data->trutherm); \ | |
216 | \ | |
217 | mutex_unlock(&data->update_lock); \ | |
218 | \ | |
219 | } \ | |
220 | return count; \ | |
221 | } | |
222 | set_type(1); | |
223 | set_type(2); | |
224 | ||
225 | #define set_min(flag) \ | |
226 | static ssize_t set_min##flag(struct device *dev, \ | |
227 | struct device_attribute *devattr, const char *buf, size_t count) \ | |
228 | { \ | |
229 | struct i2c_client *client = to_i2c_client(dev); \ | |
230 | struct lm95241_data *data = i2c_get_clientdata(client); \ | |
231 | \ | |
232 | long val; \ | |
233 | strict_strtol(buf, 10, &val); \ | |
234 | \ | |
235 | mutex_lock(&data->update_lock); \ | |
236 | \ | |
237 | if (val < 0) \ | |
238 | data->config |= R##flag##DF_MASK; \ | |
239 | else \ | |
240 | data->config &= ~R##flag##DF_MASK; \ | |
241 | \ | |
242 | data->valid = 0; \ | |
243 | \ | |
244 | i2c_smbus_write_byte_data(client, LM95241_REG_RW_CONFIG, \ | |
245 | data->config); \ | |
246 | \ | |
247 | mutex_unlock(&data->update_lock); \ | |
248 | \ | |
249 | return count; \ | |
250 | } | |
251 | set_min(1); | |
252 | set_min(2); | |
253 | ||
254 | #define set_max(flag) \ | |
255 | static ssize_t set_max##flag(struct device *dev, \ | |
256 | struct device_attribute *devattr, const char *buf, size_t count) \ | |
257 | { \ | |
258 | struct i2c_client *client = to_i2c_client(dev); \ | |
259 | struct lm95241_data *data = i2c_get_clientdata(client); \ | |
260 | \ | |
261 | long val; \ | |
262 | strict_strtol(buf, 10, &val); \ | |
263 | \ | |
264 | mutex_lock(&data->update_lock); \ | |
265 | \ | |
266 | if (val <= 127000) \ | |
267 | data->config |= R##flag##DF_MASK; \ | |
268 | else \ | |
269 | data->config &= ~R##flag##DF_MASK; \ | |
270 | \ | |
271 | data->valid = 0; \ | |
272 | \ | |
273 | i2c_smbus_write_byte_data(client, LM95241_REG_RW_CONFIG, \ | |
274 | data->config); \ | |
275 | \ | |
276 | mutex_unlock(&data->update_lock); \ | |
277 | \ | |
278 | return count; \ | |
279 | } | |
280 | set_max(1); | |
281 | set_max(2); | |
282 | ||
283 | static DEVICE_ATTR(temp1_input, S_IRUGO, show_local, NULL); | |
284 | static DEVICE_ATTR(temp2_input, S_IRUGO, show_remote1, NULL); | |
285 | static DEVICE_ATTR(temp3_input, S_IRUGO, show_remote2, NULL); | |
286 | static DEVICE_ATTR(temp2_type, S_IWUSR | S_IRUGO, show_type1, set_type1); | |
287 | static DEVICE_ATTR(temp3_type, S_IWUSR | S_IRUGO, show_type2, set_type2); | |
288 | static DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_min1, set_min1); | |
289 | static DEVICE_ATTR(temp3_min, S_IWUSR | S_IRUGO, show_min2, set_min2); | |
290 | static DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_max1, set_max1); | |
291 | static DEVICE_ATTR(temp3_max, S_IWUSR | S_IRUGO, show_max2, set_max2); | |
292 | static DEVICE_ATTR(rate, S_IWUSR | S_IRUGO, show_rate, set_rate); | |
293 | ||
294 | static struct attribute *lm95241_attributes[] = { | |
295 | &dev_attr_temp1_input.attr, | |
296 | &dev_attr_temp2_input.attr, | |
297 | &dev_attr_temp3_input.attr, | |
298 | &dev_attr_temp2_type.attr, | |
299 | &dev_attr_temp3_type.attr, | |
300 | &dev_attr_temp2_min.attr, | |
301 | &dev_attr_temp3_min.attr, | |
302 | &dev_attr_temp2_max.attr, | |
303 | &dev_attr_temp3_max.attr, | |
304 | &dev_attr_rate.attr, | |
305 | NULL | |
306 | }; | |
307 | ||
308 | static const struct attribute_group lm95241_group = { | |
309 | .attrs = lm95241_attributes, | |
310 | }; | |
311 | ||
797eaa4b JD |
312 | /* Return 0 if detection is successful, -ENODEV otherwise */ |
313 | static int lm95241_detect(struct i2c_client *new_client, int kind, | |
314 | struct i2c_board_info *info) | |
06160327 | 315 | { |
797eaa4b JD |
316 | struct i2c_adapter *adapter = new_client->adapter; |
317 | int address = new_client->addr; | |
06160327 DR |
318 | const char *name = ""; |
319 | ||
320 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | |
797eaa4b | 321 | return -ENODEV; |
06160327 DR |
322 | |
323 | /* | |
324 | * Now we do the remaining detection. A negative kind means that | |
325 | * the driver was loaded with no force parameter (default), so we | |
326 | * must both detect and identify the chip. A zero kind means that | |
327 | * the driver was loaded with the force parameter, the detection | |
328 | * step shall be skipped. A positive kind means that the driver | |
329 | * was loaded with the force parameter and a given kind of chip is | |
330 | * requested, so both the detection and the identification steps | |
331 | * are skipped. | |
332 | */ | |
333 | if (kind < 0) { /* detection */ | |
334 | if ((i2c_smbus_read_byte_data(new_client, LM95241_REG_R_MAN_ID) | |
335 | != MANUFACTURER_ID) | |
336 | || (i2c_smbus_read_byte_data(new_client, LM95241_REG_R_CHIP_ID) | |
337 | < DEFAULT_REVISION)) { | |
338 | dev_dbg(&adapter->dev, | |
339 | "LM95241 detection failed at 0x%02x.\n", | |
340 | address); | |
797eaa4b | 341 | return -ENODEV; |
06160327 DR |
342 | } |
343 | } | |
344 | ||
345 | if (kind <= 0) { /* identification */ | |
346 | if ((i2c_smbus_read_byte_data(new_client, LM95241_REG_R_MAN_ID) | |
347 | == MANUFACTURER_ID) | |
348 | && (i2c_smbus_read_byte_data(new_client, LM95241_REG_R_CHIP_ID) | |
349 | >= DEFAULT_REVISION)) { | |
350 | ||
351 | kind = lm95241; | |
352 | ||
353 | if (kind <= 0) { /* identification failed */ | |
354 | dev_info(&adapter->dev, "Unsupported chip\n"); | |
797eaa4b | 355 | return -ENODEV; |
06160327 DR |
356 | } |
357 | } | |
358 | } | |
359 | ||
797eaa4b | 360 | /* Fill the i2c board info */ |
06160327 DR |
361 | if (kind == lm95241) |
362 | name = "lm95241"; | |
797eaa4b JD |
363 | strlcpy(info->type, name, I2C_NAME_SIZE); |
364 | return 0; | |
365 | } | |
06160327 | 366 | |
797eaa4b JD |
367 | static int lm95241_probe(struct i2c_client *new_client, |
368 | const struct i2c_device_id *id) | |
369 | { | |
370 | struct lm95241_data *data; | |
371 | int err; | |
06160327 | 372 | |
797eaa4b JD |
373 | data = kzalloc(sizeof(struct lm95241_data), GFP_KERNEL); |
374 | if (!data) { | |
375 | err = -ENOMEM; | |
376 | goto exit; | |
377 | } | |
378 | ||
379 | i2c_set_clientdata(new_client, data); | |
380 | mutex_init(&data->update_lock); | |
06160327 DR |
381 | |
382 | /* Initialize the LM95241 chip */ | |
383 | lm95241_init_client(new_client); | |
384 | ||
385 | /* Register sysfs hooks */ | |
386 | err = sysfs_create_group(&new_client->dev.kobj, &lm95241_group); | |
387 | if (err) | |
797eaa4b | 388 | goto exit_free; |
06160327 DR |
389 | |
390 | data->hwmon_dev = hwmon_device_register(&new_client->dev); | |
391 | if (IS_ERR(data->hwmon_dev)) { | |
392 | err = PTR_ERR(data->hwmon_dev); | |
393 | goto exit_remove_files; | |
394 | } | |
395 | ||
396 | return 0; | |
397 | ||
398 | exit_remove_files: | |
399 | sysfs_remove_group(&new_client->dev.kobj, &lm95241_group); | |
06160327 DR |
400 | exit_free: |
401 | kfree(data); | |
402 | exit: | |
403 | return err; | |
404 | } | |
405 | ||
406 | static void lm95241_init_client(struct i2c_client *client) | |
407 | { | |
408 | struct lm95241_data *data = i2c_get_clientdata(client); | |
409 | ||
410 | data->rate = HZ; /* 1 sec default */ | |
411 | data->valid = 0; | |
412 | data->config = CFG_CR0076; | |
413 | data->model = 0; | |
414 | data->trutherm = (TT_OFF << TT1_SHIFT) | (TT_OFF << TT2_SHIFT); | |
415 | ||
416 | i2c_smbus_write_byte_data(client, LM95241_REG_RW_CONFIG, | |
417 | data->config); | |
418 | i2c_smbus_write_byte_data(client, LM95241_REG_RW_REM_FILTER, | |
419 | R1FE_MASK | R2FE_MASK); | |
420 | i2c_smbus_write_byte_data(client, LM95241_REG_RW_TRUTHERM, | |
421 | data->trutherm); | |
422 | i2c_smbus_write_byte_data(client, LM95241_REG_RW_REMOTE_MODEL, | |
423 | data->model); | |
424 | } | |
425 | ||
797eaa4b | 426 | static int lm95241_remove(struct i2c_client *client) |
06160327 DR |
427 | { |
428 | struct lm95241_data *data = i2c_get_clientdata(client); | |
06160327 DR |
429 | |
430 | hwmon_device_unregister(data->hwmon_dev); | |
431 | sysfs_remove_group(&client->dev.kobj, &lm95241_group); | |
432 | ||
797eaa4b | 433 | i2c_set_clientdata(client, NULL); |
06160327 DR |
434 | kfree(data); |
435 | return 0; | |
436 | } | |
437 | ||
438 | static struct lm95241_data *lm95241_update_device(struct device *dev) | |
439 | { | |
440 | struct i2c_client *client = to_i2c_client(dev); | |
441 | struct lm95241_data *data = i2c_get_clientdata(client); | |
442 | ||
443 | mutex_lock(&data->update_lock); | |
444 | ||
445 | if (time_after(jiffies, data->last_updated + data->rate) || | |
446 | !data->valid) { | |
447 | dev_dbg(&client->dev, "Updating lm95241 data.\n"); | |
448 | data->local_h = | |
449 | i2c_smbus_read_byte_data(client, | |
450 | LM95241_REG_R_LOCAL_TEMPH); | |
451 | data->local_l = | |
452 | i2c_smbus_read_byte_data(client, | |
453 | LM95241_REG_R_LOCAL_TEMPL); | |
454 | data->remote1_h = | |
455 | i2c_smbus_read_byte_data(client, | |
456 | LM95241_REG_R_REMOTE1_TEMPH); | |
457 | data->remote1_l = | |
458 | i2c_smbus_read_byte_data(client, | |
459 | LM95241_REG_R_REMOTE1_TEMPL); | |
460 | data->remote2_h = | |
461 | i2c_smbus_read_byte_data(client, | |
462 | LM95241_REG_R_REMOTE2_TEMPH); | |
463 | data->remote2_l = | |
464 | i2c_smbus_read_byte_data(client, | |
465 | LM95241_REG_R_REMOTE2_TEMPL); | |
466 | data->last_updated = jiffies; | |
467 | data->valid = 1; | |
468 | } | |
469 | ||
470 | mutex_unlock(&data->update_lock); | |
471 | ||
472 | return data; | |
473 | } | |
474 | ||
797eaa4b JD |
475 | /* Driver data (common to all clients) */ |
476 | static const struct i2c_device_id lm95241_id[] = { | |
477 | { "lm95241", lm95241 }, | |
478 | { } | |
479 | }; | |
480 | MODULE_DEVICE_TABLE(i2c, lm95241_id); | |
481 | ||
482 | static struct i2c_driver lm95241_driver = { | |
483 | .class = I2C_CLASS_HWMON, | |
484 | .driver = { | |
485 | .name = "lm95241", | |
486 | }, | |
487 | .probe = lm95241_probe, | |
488 | .remove = lm95241_remove, | |
489 | .id_table = lm95241_id, | |
490 | .detect = lm95241_detect, | |
491 | .address_data = &addr_data, | |
492 | }; | |
493 | ||
06160327 DR |
494 | static int __init sensors_lm95241_init(void) |
495 | { | |
496 | return i2c_add_driver(&lm95241_driver); | |
497 | } | |
498 | ||
499 | static void __exit sensors_lm95241_exit(void) | |
500 | { | |
501 | i2c_del_driver(&lm95241_driver); | |
502 | } | |
503 | ||
504 | MODULE_AUTHOR("Davide Rizzo <elpa-rizzo@gmail.com>"); | |
505 | MODULE_DESCRIPTION("LM95241 sensor driver"); | |
506 | MODULE_LICENSE("GPL"); | |
507 | ||
508 | module_init(sensors_lm95241_init); | |
509 | module_exit(sensors_lm95241_exit); |