]>
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 */ | |
90 | static int lm95241_attach_adapter(struct i2c_adapter *adapter); | |
91 | static int lm95241_detect(struct i2c_adapter *adapter, int address, | |
92 | int kind); | |
93 | static void lm95241_init_client(struct i2c_client *client); | |
94 | static int lm95241_detach_client(struct i2c_client *client); | |
95 | static struct lm95241_data *lm95241_update_device(struct device *dev); | |
96 | ||
97 | /* Driver data (common to all clients) */ | |
98 | static struct i2c_driver lm95241_driver = { | |
99 | .driver = { | |
100 | .name = "lm95241", | |
101 | }, | |
102 | .attach_adapter = lm95241_attach_adapter, | |
103 | .detach_client = lm95241_detach_client, | |
104 | }; | |
105 | ||
106 | /* Client data (each client gets its own) */ | |
107 | struct lm95241_data { | |
108 | struct i2c_client client; | |
109 | struct device *hwmon_dev; | |
110 | struct mutex update_lock; | |
111 | unsigned long last_updated, rate; /* in jiffies */ | |
112 | char valid; /* zero until following fields are valid */ | |
113 | /* registers values */ | |
114 | u8 local_h, local_l; /* local */ | |
115 | u8 remote1_h, remote1_l; /* remote1 */ | |
116 | u8 remote2_h, remote2_l; /* remote2 */ | |
117 | u8 config, model, trutherm; | |
118 | }; | |
119 | ||
120 | /* Sysfs stuff */ | |
121 | #define show_temp(value) \ | |
122 | static ssize_t show_##value(struct device *dev, \ | |
123 | struct device_attribute *attr, char *buf) \ | |
124 | { \ | |
125 | struct lm95241_data *data = lm95241_update_device(dev); \ | |
126 | snprintf(buf, PAGE_SIZE - 1, "%d\n", \ | |
127 | TEMP_FROM_REG(data->value##_h, data->value##_l)); \ | |
128 | return strlen(buf); \ | |
129 | } | |
130 | show_temp(local); | |
131 | show_temp(remote1); | |
132 | show_temp(remote2); | |
133 | ||
134 | static ssize_t show_rate(struct device *dev, struct device_attribute *attr, | |
135 | char *buf) | |
136 | { | |
137 | struct lm95241_data *data = lm95241_update_device(dev); | |
138 | ||
139 | snprintf(buf, PAGE_SIZE - 1, "%lu\n", 1000 * data->rate / HZ); | |
140 | return strlen(buf); | |
141 | } | |
142 | ||
143 | static ssize_t set_rate(struct device *dev, struct device_attribute *attr, | |
144 | const char *buf, size_t count) | |
145 | { | |
146 | struct i2c_client *client = to_i2c_client(dev); | |
147 | struct lm95241_data *data = i2c_get_clientdata(client); | |
148 | ||
149 | strict_strtol(buf, 10, &data->rate); | |
150 | data->rate = data->rate * HZ / 1000; | |
151 | ||
152 | return count; | |
153 | } | |
154 | ||
155 | #define show_type(flag) \ | |
156 | static ssize_t show_type##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->model & R##flag##MS_MASK ? "1\n" : "2\n"); \ | |
164 | return strlen(buf); \ | |
165 | } | |
166 | show_type(1); | |
167 | show_type(2); | |
168 | ||
169 | #define show_min(flag) \ | |
170 | static ssize_t show_min##flag(struct device *dev, \ | |
171 | struct device_attribute *attr, char *buf) \ | |
172 | { \ | |
173 | struct i2c_client *client = to_i2c_client(dev); \ | |
174 | struct lm95241_data *data = i2c_get_clientdata(client); \ | |
175 | \ | |
176 | snprintf(buf, PAGE_SIZE - 1, \ | |
177 | data->config & R##flag##DF_MASK ? \ | |
178 | "-127000\n" : "0\n"); \ | |
179 | return strlen(buf); \ | |
180 | } | |
181 | show_min(1); | |
182 | show_min(2); | |
183 | ||
184 | #define show_max(flag) \ | |
185 | static ssize_t show_max##flag(struct device *dev, \ | |
186 | struct device_attribute *attr, char *buf) \ | |
187 | { \ | |
188 | struct i2c_client *client = to_i2c_client(dev); \ | |
189 | struct lm95241_data *data = i2c_get_clientdata(client); \ | |
190 | \ | |
191 | snprintf(buf, PAGE_SIZE - 1, \ | |
192 | data->config & R##flag##DF_MASK ? \ | |
193 | "127000\n" : "255000\n"); \ | |
194 | return strlen(buf); \ | |
195 | } | |
196 | show_max(1); | |
197 | show_max(2); | |
198 | ||
199 | #define set_type(flag) \ | |
200 | static ssize_t set_type##flag(struct device *dev, \ | |
201 | struct device_attribute *attr, \ | |
202 | const char *buf, size_t count) \ | |
203 | { \ | |
204 | struct i2c_client *client = to_i2c_client(dev); \ | |
205 | struct lm95241_data *data = i2c_get_clientdata(client); \ | |
206 | \ | |
207 | long val; \ | |
208 | strict_strtol(buf, 10, &val); \ | |
209 | \ | |
210 | if ((val == 1) || (val == 2)) { \ | |
211 | \ | |
212 | mutex_lock(&data->update_lock); \ | |
213 | \ | |
214 | data->trutherm &= ~(TT_MASK << TT##flag##_SHIFT); \ | |
215 | if (val == 1) { \ | |
216 | data->model |= R##flag##MS_MASK; \ | |
217 | data->trutherm |= (TT_ON << TT##flag##_SHIFT); \ | |
218 | } \ | |
219 | else { \ | |
220 | data->model &= ~R##flag##MS_MASK; \ | |
221 | data->trutherm |= (TT_OFF << TT##flag##_SHIFT); \ | |
222 | } \ | |
223 | \ | |
224 | data->valid = 0; \ | |
225 | \ | |
226 | i2c_smbus_write_byte_data(client, LM95241_REG_RW_REMOTE_MODEL, \ | |
227 | data->model); \ | |
228 | i2c_smbus_write_byte_data(client, LM95241_REG_RW_TRUTHERM, \ | |
229 | data->trutherm); \ | |
230 | \ | |
231 | mutex_unlock(&data->update_lock); \ | |
232 | \ | |
233 | } \ | |
234 | return count; \ | |
235 | } | |
236 | set_type(1); | |
237 | set_type(2); | |
238 | ||
239 | #define set_min(flag) \ | |
240 | static ssize_t set_min##flag(struct device *dev, \ | |
241 | struct device_attribute *devattr, const char *buf, size_t count) \ | |
242 | { \ | |
243 | struct i2c_client *client = to_i2c_client(dev); \ | |
244 | struct lm95241_data *data = i2c_get_clientdata(client); \ | |
245 | \ | |
246 | long val; \ | |
247 | strict_strtol(buf, 10, &val); \ | |
248 | \ | |
249 | mutex_lock(&data->update_lock); \ | |
250 | \ | |
251 | if (val < 0) \ | |
252 | data->config |= R##flag##DF_MASK; \ | |
253 | else \ | |
254 | data->config &= ~R##flag##DF_MASK; \ | |
255 | \ | |
256 | data->valid = 0; \ | |
257 | \ | |
258 | i2c_smbus_write_byte_data(client, LM95241_REG_RW_CONFIG, \ | |
259 | data->config); \ | |
260 | \ | |
261 | mutex_unlock(&data->update_lock); \ | |
262 | \ | |
263 | return count; \ | |
264 | } | |
265 | set_min(1); | |
266 | set_min(2); | |
267 | ||
268 | #define set_max(flag) \ | |
269 | static ssize_t set_max##flag(struct device *dev, \ | |
270 | struct device_attribute *devattr, const char *buf, size_t count) \ | |
271 | { \ | |
272 | struct i2c_client *client = to_i2c_client(dev); \ | |
273 | struct lm95241_data *data = i2c_get_clientdata(client); \ | |
274 | \ | |
275 | long val; \ | |
276 | strict_strtol(buf, 10, &val); \ | |
277 | \ | |
278 | mutex_lock(&data->update_lock); \ | |
279 | \ | |
280 | if (val <= 127000) \ | |
281 | data->config |= R##flag##DF_MASK; \ | |
282 | else \ | |
283 | data->config &= ~R##flag##DF_MASK; \ | |
284 | \ | |
285 | data->valid = 0; \ | |
286 | \ | |
287 | i2c_smbus_write_byte_data(client, LM95241_REG_RW_CONFIG, \ | |
288 | data->config); \ | |
289 | \ | |
290 | mutex_unlock(&data->update_lock); \ | |
291 | \ | |
292 | return count; \ | |
293 | } | |
294 | set_max(1); | |
295 | set_max(2); | |
296 | ||
297 | static DEVICE_ATTR(temp1_input, S_IRUGO, show_local, NULL); | |
298 | static DEVICE_ATTR(temp2_input, S_IRUGO, show_remote1, NULL); | |
299 | static DEVICE_ATTR(temp3_input, S_IRUGO, show_remote2, NULL); | |
300 | static DEVICE_ATTR(temp2_type, S_IWUSR | S_IRUGO, show_type1, set_type1); | |
301 | static DEVICE_ATTR(temp3_type, S_IWUSR | S_IRUGO, show_type2, set_type2); | |
302 | static DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_min1, set_min1); | |
303 | static DEVICE_ATTR(temp3_min, S_IWUSR | S_IRUGO, show_min2, set_min2); | |
304 | static DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_max1, set_max1); | |
305 | static DEVICE_ATTR(temp3_max, S_IWUSR | S_IRUGO, show_max2, set_max2); | |
306 | static DEVICE_ATTR(rate, S_IWUSR | S_IRUGO, show_rate, set_rate); | |
307 | ||
308 | static struct attribute *lm95241_attributes[] = { | |
309 | &dev_attr_temp1_input.attr, | |
310 | &dev_attr_temp2_input.attr, | |
311 | &dev_attr_temp3_input.attr, | |
312 | &dev_attr_temp2_type.attr, | |
313 | &dev_attr_temp3_type.attr, | |
314 | &dev_attr_temp2_min.attr, | |
315 | &dev_attr_temp3_min.attr, | |
316 | &dev_attr_temp2_max.attr, | |
317 | &dev_attr_temp3_max.attr, | |
318 | &dev_attr_rate.attr, | |
319 | NULL | |
320 | }; | |
321 | ||
322 | static const struct attribute_group lm95241_group = { | |
323 | .attrs = lm95241_attributes, | |
324 | }; | |
325 | ||
326 | /* Init/exit code */ | |
327 | static int lm95241_attach_adapter(struct i2c_adapter *adapter) | |
328 | { | |
329 | if (!(adapter->class & I2C_CLASS_HWMON)) | |
330 | return 0; | |
331 | return i2c_probe(adapter, &addr_data, lm95241_detect); | |
332 | } | |
333 | ||
334 | /* | |
335 | * The following function does more than just detection. If detection | |
336 | * succeeds, it also registers the new chip. | |
337 | */ | |
338 | static int lm95241_detect(struct i2c_adapter *adapter, int address, int kind) | |
339 | { | |
340 | struct i2c_client *new_client; | |
341 | struct lm95241_data *data; | |
342 | int err = 0; | |
343 | const char *name = ""; | |
344 | ||
345 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | |
346 | goto exit; | |
347 | ||
348 | data = kzalloc(sizeof(struct lm95241_data), GFP_KERNEL); | |
349 | if (!data) { | |
350 | err = -ENOMEM; | |
351 | goto exit; | |
352 | } | |
353 | ||
354 | /* The common I2C client data is placed right before the | |
355 | LM95241-specific data. */ | |
356 | new_client = &data->client; | |
357 | i2c_set_clientdata(new_client, data); | |
358 | new_client->addr = address; | |
359 | new_client->adapter = adapter; | |
360 | new_client->driver = &lm95241_driver; | |
361 | new_client->flags = 0; | |
362 | ||
363 | /* | |
364 | * Now we do the remaining detection. A negative kind means that | |
365 | * the driver was loaded with no force parameter (default), so we | |
366 | * must both detect and identify the chip. A zero kind means that | |
367 | * the driver was loaded with the force parameter, the detection | |
368 | * step shall be skipped. A positive kind means that the driver | |
369 | * was loaded with the force parameter and a given kind of chip is | |
370 | * requested, so both the detection and the identification steps | |
371 | * are skipped. | |
372 | */ | |
373 | if (kind < 0) { /* detection */ | |
374 | if ((i2c_smbus_read_byte_data(new_client, LM95241_REG_R_MAN_ID) | |
375 | != MANUFACTURER_ID) | |
376 | || (i2c_smbus_read_byte_data(new_client, LM95241_REG_R_CHIP_ID) | |
377 | < DEFAULT_REVISION)) { | |
378 | dev_dbg(&adapter->dev, | |
379 | "LM95241 detection failed at 0x%02x.\n", | |
380 | address); | |
381 | goto exit_free; | |
382 | } | |
383 | } | |
384 | ||
385 | if (kind <= 0) { /* identification */ | |
386 | if ((i2c_smbus_read_byte_data(new_client, LM95241_REG_R_MAN_ID) | |
387 | == MANUFACTURER_ID) | |
388 | && (i2c_smbus_read_byte_data(new_client, LM95241_REG_R_CHIP_ID) | |
389 | >= DEFAULT_REVISION)) { | |
390 | ||
391 | kind = lm95241; | |
392 | ||
393 | if (kind <= 0) { /* identification failed */ | |
394 | dev_info(&adapter->dev, "Unsupported chip\n"); | |
395 | goto exit_free; | |
396 | } | |
397 | } | |
398 | } | |
399 | ||
400 | if (kind == lm95241) | |
401 | name = "lm95241"; | |
402 | ||
403 | /* We can fill in the remaining client fields */ | |
404 | strlcpy(new_client->name, name, I2C_NAME_SIZE); | |
405 | data->valid = 0; | |
406 | mutex_init(&data->update_lock); | |
407 | ||
408 | /* Tell the I2C layer a new client has arrived */ | |
409 | err = i2c_attach_client(new_client); | |
410 | if (err) | |
411 | goto exit_free; | |
412 | ||
413 | /* Initialize the LM95241 chip */ | |
414 | lm95241_init_client(new_client); | |
415 | ||
416 | /* Register sysfs hooks */ | |
417 | err = sysfs_create_group(&new_client->dev.kobj, &lm95241_group); | |
418 | if (err) | |
419 | goto exit_detach; | |
420 | ||
421 | data->hwmon_dev = hwmon_device_register(&new_client->dev); | |
422 | if (IS_ERR(data->hwmon_dev)) { | |
423 | err = PTR_ERR(data->hwmon_dev); | |
424 | goto exit_remove_files; | |
425 | } | |
426 | ||
427 | return 0; | |
428 | ||
429 | exit_remove_files: | |
430 | sysfs_remove_group(&new_client->dev.kobj, &lm95241_group); | |
431 | exit_detach: | |
432 | i2c_detach_client(new_client); | |
433 | exit_free: | |
434 | kfree(data); | |
435 | exit: | |
436 | return err; | |
437 | } | |
438 | ||
439 | static void lm95241_init_client(struct i2c_client *client) | |
440 | { | |
441 | struct lm95241_data *data = i2c_get_clientdata(client); | |
442 | ||
443 | data->rate = HZ; /* 1 sec default */ | |
444 | data->valid = 0; | |
445 | data->config = CFG_CR0076; | |
446 | data->model = 0; | |
447 | data->trutherm = (TT_OFF << TT1_SHIFT) | (TT_OFF << TT2_SHIFT); | |
448 | ||
449 | i2c_smbus_write_byte_data(client, LM95241_REG_RW_CONFIG, | |
450 | data->config); | |
451 | i2c_smbus_write_byte_data(client, LM95241_REG_RW_REM_FILTER, | |
452 | R1FE_MASK | R2FE_MASK); | |
453 | i2c_smbus_write_byte_data(client, LM95241_REG_RW_TRUTHERM, | |
454 | data->trutherm); | |
455 | i2c_smbus_write_byte_data(client, LM95241_REG_RW_REMOTE_MODEL, | |
456 | data->model); | |
457 | } | |
458 | ||
459 | static int lm95241_detach_client(struct i2c_client *client) | |
460 | { | |
461 | struct lm95241_data *data = i2c_get_clientdata(client); | |
462 | int err; | |
463 | ||
464 | hwmon_device_unregister(data->hwmon_dev); | |
465 | sysfs_remove_group(&client->dev.kobj, &lm95241_group); | |
466 | ||
467 | err = i2c_detach_client(client); | |
468 | if (err) | |
469 | return err; | |
470 | ||
471 | kfree(data); | |
472 | return 0; | |
473 | } | |
474 | ||
475 | static struct lm95241_data *lm95241_update_device(struct device *dev) | |
476 | { | |
477 | struct i2c_client *client = to_i2c_client(dev); | |
478 | struct lm95241_data *data = i2c_get_clientdata(client); | |
479 | ||
480 | mutex_lock(&data->update_lock); | |
481 | ||
482 | if (time_after(jiffies, data->last_updated + data->rate) || | |
483 | !data->valid) { | |
484 | dev_dbg(&client->dev, "Updating lm95241 data.\n"); | |
485 | data->local_h = | |
486 | i2c_smbus_read_byte_data(client, | |
487 | LM95241_REG_R_LOCAL_TEMPH); | |
488 | data->local_l = | |
489 | i2c_smbus_read_byte_data(client, | |
490 | LM95241_REG_R_LOCAL_TEMPL); | |
491 | data->remote1_h = | |
492 | i2c_smbus_read_byte_data(client, | |
493 | LM95241_REG_R_REMOTE1_TEMPH); | |
494 | data->remote1_l = | |
495 | i2c_smbus_read_byte_data(client, | |
496 | LM95241_REG_R_REMOTE1_TEMPL); | |
497 | data->remote2_h = | |
498 | i2c_smbus_read_byte_data(client, | |
499 | LM95241_REG_R_REMOTE2_TEMPH); | |
500 | data->remote2_l = | |
501 | i2c_smbus_read_byte_data(client, | |
502 | LM95241_REG_R_REMOTE2_TEMPL); | |
503 | data->last_updated = jiffies; | |
504 | data->valid = 1; | |
505 | } | |
506 | ||
507 | mutex_unlock(&data->update_lock); | |
508 | ||
509 | return data; | |
510 | } | |
511 | ||
512 | static int __init sensors_lm95241_init(void) | |
513 | { | |
514 | return i2c_add_driver(&lm95241_driver); | |
515 | } | |
516 | ||
517 | static void __exit sensors_lm95241_exit(void) | |
518 | { | |
519 | i2c_del_driver(&lm95241_driver); | |
520 | } | |
521 | ||
522 | MODULE_AUTHOR("Davide Rizzo <elpa-rizzo@gmail.com>"); | |
523 | MODULE_DESCRIPTION("LM95241 sensor driver"); | |
524 | MODULE_LICENSE("GPL"); | |
525 | ||
526 | module_init(sensors_lm95241_init); | |
527 | module_exit(sensors_lm95241_exit); |