diff options
author | Alexander Stein <alexander.stein@systec-electronic.com> | 2011-06-28 11:11:23 -0400 |
---|---|---|
committer | Guenter Roeck <guenter.roeck@ericsson.com> | 2011-07-28 03:17:35 -0400 |
commit | fffd80ccc1e6c7e5f13741e17a7d80582ae21fcc (patch) | |
tree | 6c3b9d74a4f1cc21a2f60ac022e115c833b8ba78 /drivers/hwmon | |
parent | 2ef017935d698b1c7c7421a7ebe20579d8f904dd (diff) |
hwmon: LM95245 driver
A hwmon driver for the National Semiconductor LM95245 dual temperature
sensors chip.
Signed-off-by: Alexander Stein <alexander.stein@systec-electronic.com>
Signed-off-by: Guenter Roeck <guenter.roeck@ericsson.com>
Diffstat (limited to 'drivers/hwmon')
-rw-r--r-- | drivers/hwmon/Kconfig | 9 | ||||
-rw-r--r-- | drivers/hwmon/Makefile | 1 | ||||
-rw-r--r-- | drivers/hwmon/lm95245.c | 543 |
3 files changed, 553 insertions, 0 deletions
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 1396290a31a4..166889b326ff 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig | |||
@@ -702,6 +702,15 @@ config SENSORS_LM95241 | |||
702 | This driver can also be built as a module. If so, the module | 702 | This driver can also be built as a module. If so, the module |
703 | will be called lm95241. | 703 | will be called lm95241. |
704 | 704 | ||
705 | config SENSORS_LM95245 | ||
706 | tristate "National Semiconductor LM95245 sensor chip" | ||
707 | depends on I2C && EXPERIMENTAL | ||
708 | help | ||
709 | If you say yes here you get support for LM95245 sensor chip. | ||
710 | |||
711 | This driver can also be built as a module. If so, the module | ||
712 | will be called lm95245. | ||
713 | |||
705 | config SENSORS_MAX1111 | 714 | config SENSORS_MAX1111 |
706 | tristate "Maxim MAX1111 Multichannel, Serial 8-bit ADC chip" | 715 | tristate "Maxim MAX1111 Multichannel, Serial 8-bit ADC chip" |
707 | depends on SPI_MASTER | 716 | depends on SPI_MASTER |
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index 1b7dc770aa60..9a4473993845 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile | |||
@@ -80,6 +80,7 @@ obj-$(CONFIG_SENSORS_LM90) += lm90.o | |||
80 | obj-$(CONFIG_SENSORS_LM92) += lm92.o | 80 | obj-$(CONFIG_SENSORS_LM92) += lm92.o |
81 | obj-$(CONFIG_SENSORS_LM93) += lm93.o | 81 | obj-$(CONFIG_SENSORS_LM93) += lm93.o |
82 | obj-$(CONFIG_SENSORS_LM95241) += lm95241.o | 82 | obj-$(CONFIG_SENSORS_LM95241) += lm95241.o |
83 | obj-$(CONFIG_SENSORS_LM95245) += lm95245.o | ||
83 | obj-$(CONFIG_SENSORS_LTC4151) += ltc4151.o | 84 | obj-$(CONFIG_SENSORS_LTC4151) += ltc4151.o |
84 | obj-$(CONFIG_SENSORS_LTC4215) += ltc4215.o | 85 | obj-$(CONFIG_SENSORS_LTC4215) += ltc4215.o |
85 | obj-$(CONFIG_SENSORS_LTC4245) += ltc4245.o | 86 | obj-$(CONFIG_SENSORS_LTC4245) += ltc4245.o |
diff --git a/drivers/hwmon/lm95245.c b/drivers/hwmon/lm95245.c new file mode 100644 index 000000000000..dce9e68241e6 --- /dev/null +++ b/drivers/hwmon/lm95245.c | |||
@@ -0,0 +1,543 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2011 Alexander Stein <alexander.stein@systec-electronic.com> | ||
3 | * | ||
4 | * The LM95245 is a sensor chip made by National Semiconductors. | ||
5 | * It reports up to two temperatures (its own plus an external one). | ||
6 | * Complete datasheet can be obtained from National's website at: | ||
7 | * http://www.national.com/ds.cgi/LM/LM95245.pdf | ||
8 | * | ||
9 | * This driver is based on lm95241.c | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License as published by | ||
13 | * the Free Software Foundation; either version 2 of the License, or | ||
14 | * (at your option) any later version. | ||
15 | * | ||
16 | * This program is distributed in the hope that it will be useful, | ||
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
19 | * GNU General Public License for more details. | ||
20 | * | ||
21 | * You should have received a copy of the GNU General Public License | ||
22 | * along with this program; if not, write to the Free Software | ||
23 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
24 | */ | ||
25 | |||
26 | #include <linux/module.h> | ||
27 | #include <linux/init.h> | ||
28 | #include <linux/slab.h> | ||
29 | #include <linux/jiffies.h> | ||
30 | #include <linux/i2c.h> | ||
31 | #include <linux/hwmon.h> | ||
32 | #include <linux/hwmon-sysfs.h> | ||
33 | #include <linux/err.h> | ||
34 | #include <linux/mutex.h> | ||
35 | #include <linux/sysfs.h> | ||
36 | |||
37 | #define DEVNAME "lm95245" | ||
38 | |||
39 | static const unsigned short normal_i2c[] = { | ||
40 | 0x18, 0x19, 0x29, 0x4c, 0x4d, I2C_CLIENT_END }; | ||
41 | |||
42 | /* LM95245 registers */ | ||
43 | /* general registers */ | ||
44 | #define LM95245_REG_RW_CONFIG1 0x03 | ||
45 | #define LM95245_REG_RW_CONVERS_RATE 0x04 | ||
46 | #define LM95245_REG_W_ONE_SHOT 0x0F | ||
47 | |||
48 | /* diode configuration */ | ||
49 | #define LM95245_REG_RW_CONFIG2 0xBF | ||
50 | #define LM95245_REG_RW_REMOTE_OFFH 0x11 | ||
51 | #define LM95245_REG_RW_REMOTE_OFFL 0x12 | ||
52 | |||
53 | /* status registers */ | ||
54 | #define LM95245_REG_R_STATUS1 0x02 | ||
55 | #define LM95245_REG_R_STATUS2 0x33 | ||
56 | |||
57 | /* limit registers */ | ||
58 | #define LM95245_REG_RW_REMOTE_OS_LIMIT 0x07 | ||
59 | #define LM95245_REG_RW_LOCAL_OS_TCRIT_LIMIT 0x20 | ||
60 | #define LM95245_REG_RW_REMOTE_TCRIT_LIMIT 0x19 | ||
61 | #define LM95245_REG_RW_COMMON_HYSTERESIS 0x21 | ||
62 | |||
63 | /* temperature signed */ | ||
64 | #define LM95245_REG_R_LOCAL_TEMPH_S 0x00 | ||
65 | #define LM95245_REG_R_LOCAL_TEMPL_S 0x30 | ||
66 | #define LM95245_REG_R_REMOTE_TEMPH_S 0x01 | ||
67 | #define LM95245_REG_R_REMOTE_TEMPL_S 0x10 | ||
68 | /* temperature unsigned */ | ||
69 | #define LM95245_REG_R_REMOTE_TEMPH_U 0x31 | ||
70 | #define LM95245_REG_R_REMOTE_TEMPL_U 0x32 | ||
71 | |||
72 | /* id registers */ | ||
73 | #define LM95245_REG_R_MAN_ID 0xFE | ||
74 | #define LM95245_REG_R_CHIP_ID 0xFF | ||
75 | |||
76 | /* LM95245 specific bitfields */ | ||
77 | #define CFG_STOP 0x40 | ||
78 | #define CFG_REMOTE_TCRIT_MASK 0x10 | ||
79 | #define CFG_REMOTE_OS_MASK 0x08 | ||
80 | #define CFG_LOCAL_TCRIT_MASK 0x04 | ||
81 | #define CFG_LOCAL_OS_MASK 0x02 | ||
82 | |||
83 | #define CFG2_OS_A0 0x40 | ||
84 | #define CFG2_DIODE_FAULT_OS 0x20 | ||
85 | #define CFG2_DIODE_FAULT_TCRIT 0x10 | ||
86 | #define CFG2_REMOTE_TT 0x08 | ||
87 | #define CFG2_REMOTE_FILTER_DIS 0x00 | ||
88 | #define CFG2_REMOTE_FILTER_EN 0x06 | ||
89 | |||
90 | /* conversation rate in ms */ | ||
91 | #define RATE_CR0063 0x00 | ||
92 | #define RATE_CR0364 0x01 | ||
93 | #define RATE_CR1000 0x02 | ||
94 | #define RATE_CR2500 0x03 | ||
95 | |||
96 | #define STATUS1_DIODE_FAULT 0x04 | ||
97 | #define STATUS1_RTCRIT 0x02 | ||
98 | #define STATUS1_LOC 0x01 | ||
99 | |||
100 | #define MANUFACTURER_ID 0x01 | ||
101 | #define DEFAULT_REVISION 0xB3 | ||
102 | |||
103 | static const u8 lm95245_reg_address[] = { | ||
104 | LM95245_REG_R_LOCAL_TEMPH_S, | ||
105 | LM95245_REG_R_LOCAL_TEMPL_S, | ||
106 | LM95245_REG_R_REMOTE_TEMPH_S, | ||
107 | LM95245_REG_R_REMOTE_TEMPL_S, | ||
108 | LM95245_REG_R_REMOTE_TEMPH_U, | ||
109 | LM95245_REG_R_REMOTE_TEMPL_U, | ||
110 | LM95245_REG_RW_LOCAL_OS_TCRIT_LIMIT, | ||
111 | LM95245_REG_RW_REMOTE_TCRIT_LIMIT, | ||
112 | LM95245_REG_RW_COMMON_HYSTERESIS, | ||
113 | LM95245_REG_R_STATUS1, | ||
114 | }; | ||
115 | |||
116 | /* Client data (each client gets its own) */ | ||
117 | struct lm95245_data { | ||
118 | struct device *hwmon_dev; | ||
119 | struct mutex update_lock; | ||
120 | unsigned long last_updated; /* in jiffies */ | ||
121 | unsigned long interval; /* in msecs */ | ||
122 | bool valid; /* zero until following fields are valid */ | ||
123 | /* registers values */ | ||
124 | u8 regs[ARRAY_SIZE(lm95245_reg_address)]; | ||
125 | u8 config1, config2; | ||
126 | }; | ||
127 | |||
128 | /* Conversions */ | ||
129 | static int temp_from_reg_unsigned(u8 val_h, u8 val_l) | ||
130 | { | ||
131 | return val_h * 1000 + val_l * 1000 / 256; | ||
132 | } | ||
133 | |||
134 | static int temp_from_reg_signed(u8 val_h, u8 val_l) | ||
135 | { | ||
136 | if (val_h & 0x80) | ||
137 | return (val_h - 0x100) * 1000; | ||
138 | return temp_from_reg_unsigned(val_h, val_l); | ||
139 | } | ||
140 | |||
141 | static struct lm95245_data *lm95245_update_device(struct device *dev) | ||
142 | { | ||
143 | struct i2c_client *client = to_i2c_client(dev); | ||
144 | struct lm95245_data *data = i2c_get_clientdata(client); | ||
145 | |||
146 | mutex_lock(&data->update_lock); | ||
147 | |||
148 | if (time_after(jiffies, data->last_updated | ||
149 | + msecs_to_jiffies(data->interval)) || !data->valid) { | ||
150 | int i; | ||
151 | |||
152 | dev_dbg(&client->dev, "Updating lm95245 data.\n"); | ||
153 | for (i = 0; i < ARRAY_SIZE(lm95245_reg_address); i++) | ||
154 | data->regs[i] | ||
155 | = i2c_smbus_read_byte_data(client, | ||
156 | lm95245_reg_address[i]); | ||
157 | data->last_updated = jiffies; | ||
158 | data->valid = 1; | ||
159 | } | ||
160 | |||
161 | mutex_unlock(&data->update_lock); | ||
162 | |||
163 | return data; | ||
164 | } | ||
165 | |||
166 | static unsigned long lm95245_read_conversion_rate(struct i2c_client *client) | ||
167 | { | ||
168 | int rate; | ||
169 | unsigned long interval; | ||
170 | |||
171 | rate = i2c_smbus_read_byte_data(client, LM95245_REG_RW_CONVERS_RATE); | ||
172 | |||
173 | switch (rate) { | ||
174 | case RATE_CR0063: | ||
175 | interval = 63; | ||
176 | break; | ||
177 | case RATE_CR0364: | ||
178 | interval = 364; | ||
179 | break; | ||
180 | case RATE_CR1000: | ||
181 | interval = 1000; | ||
182 | break; | ||
183 | case RATE_CR2500: | ||
184 | default: | ||
185 | interval = 2500; | ||
186 | break; | ||
187 | } | ||
188 | |||
189 | return interval; | ||
190 | } | ||
191 | |||
192 | static unsigned long lm95245_set_conversion_rate(struct i2c_client *client, | ||
193 | unsigned long interval) | ||
194 | { | ||
195 | int rate; | ||
196 | |||
197 | if (interval <= 63) { | ||
198 | interval = 63; | ||
199 | rate = RATE_CR0063; | ||
200 | } else if (interval <= 364) { | ||
201 | interval = 364; | ||
202 | rate = RATE_CR0364; | ||
203 | } else if (interval <= 1000) { | ||
204 | interval = 1000; | ||
205 | rate = RATE_CR1000; | ||
206 | } else { | ||
207 | interval = 2500; | ||
208 | rate = RATE_CR2500; | ||
209 | } | ||
210 | |||
211 | i2c_smbus_write_byte_data(client, LM95245_REG_RW_CONVERS_RATE, rate); | ||
212 | |||
213 | return interval; | ||
214 | } | ||
215 | |||
216 | /* Sysfs stuff */ | ||
217 | static ssize_t show_input(struct device *dev, struct device_attribute *attr, | ||
218 | char *buf) | ||
219 | { | ||
220 | struct lm95245_data *data = lm95245_update_device(dev); | ||
221 | int temp; | ||
222 | int index = to_sensor_dev_attr(attr)->index; | ||
223 | |||
224 | /* | ||
225 | * Index 0 (Local temp) is always signed | ||
226 | * Index 2 (Remote temp) has both signed and unsigned data | ||
227 | * use signed calculation for remote if signed bit is set | ||
228 | */ | ||
229 | if (index == 0 || data->regs[index] & 0x80) | ||
230 | temp = temp_from_reg_signed(data->regs[index], | ||
231 | data->regs[index + 1]); | ||
232 | else | ||
233 | temp = temp_from_reg_unsigned(data->regs[index + 2], | ||
234 | data->regs[index + 3]); | ||
235 | |||
236 | return snprintf(buf, PAGE_SIZE - 1, "%d\n", temp); | ||
237 | } | ||
238 | |||
239 | static ssize_t show_limit(struct device *dev, struct device_attribute *attr, | ||
240 | char *buf) | ||
241 | { | ||
242 | struct lm95245_data *data = lm95245_update_device(dev); | ||
243 | int index = to_sensor_dev_attr(attr)->index; | ||
244 | |||
245 | return snprintf(buf, PAGE_SIZE - 1, "%d\n", | ||
246 | data->regs[index] * 1000); | ||
247 | } | ||
248 | |||
249 | static ssize_t set_limit(struct device *dev, struct device_attribute *attr, | ||
250 | const char *buf, size_t count) | ||
251 | { | ||
252 | struct i2c_client *client = to_i2c_client(dev); | ||
253 | struct lm95245_data *data = i2c_get_clientdata(client); | ||
254 | int index = to_sensor_dev_attr(attr)->index; | ||
255 | unsigned long val; | ||
256 | |||
257 | if (strict_strtoul(buf, 10, &val) < 0) | ||
258 | return -EINVAL; | ||
259 | |||
260 | val /= 1000; | ||
261 | |||
262 | val = SENSORS_LIMIT(val, 0, (index == 6 ? 127 : 255)); | ||
263 | |||
264 | mutex_lock(&data->update_lock); | ||
265 | |||
266 | data->valid = 0; | ||
267 | |||
268 | i2c_smbus_write_byte_data(client, lm95245_reg_address[index], val); | ||
269 | |||
270 | mutex_unlock(&data->update_lock); | ||
271 | |||
272 | return count; | ||
273 | } | ||
274 | |||
275 | static ssize_t set_crit_hyst(struct device *dev, struct device_attribute *attr, | ||
276 | const char *buf, size_t count) | ||
277 | { | ||
278 | struct i2c_client *client = to_i2c_client(dev); | ||
279 | struct lm95245_data *data = i2c_get_clientdata(client); | ||
280 | unsigned long val; | ||
281 | |||
282 | if (strict_strtoul(buf, 10, &val) < 0) | ||
283 | return -EINVAL; | ||
284 | |||
285 | val /= 1000; | ||
286 | |||
287 | val = SENSORS_LIMIT(val, 0, 31); | ||
288 | |||
289 | mutex_lock(&data->update_lock); | ||
290 | |||
291 | data->valid = 0; | ||
292 | |||
293 | /* shared crit hysteresis */ | ||
294 | i2c_smbus_write_byte_data(client, LM95245_REG_RW_COMMON_HYSTERESIS, | ||
295 | val); | ||
296 | |||
297 | mutex_unlock(&data->update_lock); | ||
298 | |||
299 | return count; | ||
300 | } | ||
301 | |||
302 | static ssize_t show_type(struct device *dev, struct device_attribute *attr, | ||
303 | char *buf) | ||
304 | { | ||
305 | struct i2c_client *client = to_i2c_client(dev); | ||
306 | struct lm95245_data *data = i2c_get_clientdata(client); | ||
307 | |||
308 | return snprintf(buf, PAGE_SIZE - 1, | ||
309 | data->config2 & CFG2_REMOTE_TT ? "1\n" : "2\n"); | ||
310 | } | ||
311 | |||
312 | static ssize_t set_type(struct device *dev, struct device_attribute *attr, | ||
313 | const char *buf, size_t count) | ||
314 | { | ||
315 | struct i2c_client *client = to_i2c_client(dev); | ||
316 | struct lm95245_data *data = i2c_get_clientdata(client); | ||
317 | unsigned long val; | ||
318 | |||
319 | if (strict_strtoul(buf, 10, &val) < 0) | ||
320 | return -EINVAL; | ||
321 | if (val != 1 && val != 2) | ||
322 | return -EINVAL; | ||
323 | |||
324 | mutex_lock(&data->update_lock); | ||
325 | |||
326 | if (val == 1) | ||
327 | data->config2 |= CFG2_REMOTE_TT; | ||
328 | else | ||
329 | data->config2 &= ~CFG2_REMOTE_TT; | ||
330 | |||
331 | data->valid = 0; | ||
332 | |||
333 | i2c_smbus_write_byte_data(client, LM95245_REG_RW_CONFIG2, | ||
334 | data->config2); | ||
335 | |||
336 | mutex_unlock(&data->update_lock); | ||
337 | |||
338 | return count; | ||
339 | } | ||
340 | |||
341 | static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, | ||
342 | char *buf) | ||
343 | { | ||
344 | struct lm95245_data *data = lm95245_update_device(dev); | ||
345 | int index = to_sensor_dev_attr(attr)->index; | ||
346 | |||
347 | return snprintf(buf, PAGE_SIZE - 1, "%d\n", | ||
348 | !!(data->regs[9] & index)); | ||
349 | } | ||
350 | |||
351 | static ssize_t show_interval(struct device *dev, struct device_attribute *attr, | ||
352 | char *buf) | ||
353 | { | ||
354 | struct lm95245_data *data = lm95245_update_device(dev); | ||
355 | |||
356 | return snprintf(buf, PAGE_SIZE - 1, "%lu\n", data->interval); | ||
357 | } | ||
358 | |||
359 | static ssize_t set_interval(struct device *dev, struct device_attribute *attr, | ||
360 | const char *buf, size_t count) | ||
361 | { | ||
362 | struct i2c_client *client = to_i2c_client(dev); | ||
363 | struct lm95245_data *data = i2c_get_clientdata(client); | ||
364 | unsigned long val; | ||
365 | |||
366 | if (strict_strtoul(buf, 10, &val) < 0) | ||
367 | return -EINVAL; | ||
368 | |||
369 | mutex_lock(&data->update_lock); | ||
370 | |||
371 | data->interval = lm95245_set_conversion_rate(client, val); | ||
372 | |||
373 | mutex_unlock(&data->update_lock); | ||
374 | |||
375 | return count; | ||
376 | } | ||
377 | |||
378 | static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_input, NULL, 0); | ||
379 | static SENSOR_DEVICE_ATTR(temp1_crit, S_IWUSR | S_IRUGO, show_limit, | ||
380 | set_limit, 6); | ||
381 | static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IWUSR | S_IRUGO, show_limit, | ||
382 | set_crit_hyst, 8); | ||
383 | static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, | ||
384 | STATUS1_LOC); | ||
385 | |||
386 | static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_input, NULL, 2); | ||
387 | static SENSOR_DEVICE_ATTR(temp2_crit, S_IWUSR | S_IRUGO, show_limit, | ||
388 | set_limit, 7); | ||
389 | static SENSOR_DEVICE_ATTR(temp2_crit_hyst, S_IWUSR | S_IRUGO, show_limit, | ||
390 | set_crit_hyst, 8); | ||
391 | static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, show_alarm, NULL, | ||
392 | STATUS1_RTCRIT); | ||
393 | static SENSOR_DEVICE_ATTR(temp2_type, S_IWUSR | S_IRUGO, show_type, | ||
394 | set_type, 0); | ||
395 | static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_alarm, NULL, | ||
396 | STATUS1_DIODE_FAULT); | ||
397 | |||
398 | static DEVICE_ATTR(update_interval, S_IWUSR | S_IRUGO, show_interval, | ||
399 | set_interval); | ||
400 | |||
401 | static struct attribute *lm95245_attributes[] = { | ||
402 | &sensor_dev_attr_temp1_input.dev_attr.attr, | ||
403 | &sensor_dev_attr_temp1_crit.dev_attr.attr, | ||
404 | &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr, | ||
405 | &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr, | ||
406 | &sensor_dev_attr_temp2_input.dev_attr.attr, | ||
407 | &sensor_dev_attr_temp2_crit.dev_attr.attr, | ||
408 | &sensor_dev_attr_temp2_crit_hyst.dev_attr.attr, | ||
409 | &sensor_dev_attr_temp2_crit_alarm.dev_attr.attr, | ||
410 | &sensor_dev_attr_temp2_type.dev_attr.attr, | ||
411 | &sensor_dev_attr_temp2_fault.dev_attr.attr, | ||
412 | &dev_attr_update_interval.attr, | ||
413 | NULL | ||
414 | }; | ||
415 | |||
416 | static const struct attribute_group lm95245_group = { | ||
417 | .attrs = lm95245_attributes, | ||
418 | }; | ||
419 | |||
420 | /* Return 0 if detection is successful, -ENODEV otherwise */ | ||
421 | static int lm95245_detect(struct i2c_client *new_client, | ||
422 | struct i2c_board_info *info) | ||
423 | { | ||
424 | struct i2c_adapter *adapter = new_client->adapter; | ||
425 | |||
426 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | ||
427 | return -ENODEV; | ||
428 | |||
429 | if (i2c_smbus_read_byte_data(new_client, LM95245_REG_R_MAN_ID) | ||
430 | != MANUFACTURER_ID | ||
431 | || i2c_smbus_read_byte_data(new_client, LM95245_REG_R_CHIP_ID) | ||
432 | != DEFAULT_REVISION) | ||
433 | return -ENODEV; | ||
434 | |||
435 | strlcpy(info->type, DEVNAME, I2C_NAME_SIZE); | ||
436 | return 0; | ||
437 | } | ||
438 | |||
439 | static void lm95245_init_client(struct i2c_client *client) | ||
440 | { | ||
441 | struct lm95245_data *data = i2c_get_clientdata(client); | ||
442 | |||
443 | data->valid = 0; | ||
444 | data->interval = lm95245_read_conversion_rate(client); | ||
445 | |||
446 | data->config1 = i2c_smbus_read_byte_data(client, | ||
447 | LM95245_REG_RW_CONFIG1); | ||
448 | data->config2 = i2c_smbus_read_byte_data(client, | ||
449 | LM95245_REG_RW_CONFIG2); | ||
450 | |||
451 | if (data->config1 & CFG_STOP) { | ||
452 | /* Clear the standby bit */ | ||
453 | data->config1 &= ~CFG_STOP; | ||
454 | i2c_smbus_write_byte_data(client, LM95245_REG_RW_CONFIG1, | ||
455 | data->config1); | ||
456 | } | ||
457 | } | ||
458 | |||
459 | static int lm95245_probe(struct i2c_client *new_client, | ||
460 | const struct i2c_device_id *id) | ||
461 | { | ||
462 | struct lm95245_data *data; | ||
463 | int err; | ||
464 | |||
465 | data = kzalloc(sizeof(struct lm95245_data), GFP_KERNEL); | ||
466 | if (!data) { | ||
467 | err = -ENOMEM; | ||
468 | goto exit; | ||
469 | } | ||
470 | |||
471 | i2c_set_clientdata(new_client, data); | ||
472 | mutex_init(&data->update_lock); | ||
473 | |||
474 | /* Initialize the LM95245 chip */ | ||
475 | lm95245_init_client(new_client); | ||
476 | |||
477 | /* Register sysfs hooks */ | ||
478 | err = sysfs_create_group(&new_client->dev.kobj, &lm95245_group); | ||
479 | if (err) | ||
480 | goto exit_free; | ||
481 | |||
482 | data->hwmon_dev = hwmon_device_register(&new_client->dev); | ||
483 | if (IS_ERR(data->hwmon_dev)) { | ||
484 | err = PTR_ERR(data->hwmon_dev); | ||
485 | goto exit_remove_files; | ||
486 | } | ||
487 | |||
488 | return 0; | ||
489 | |||
490 | exit_remove_files: | ||
491 | sysfs_remove_group(&new_client->dev.kobj, &lm95245_group); | ||
492 | exit_free: | ||
493 | kfree(data); | ||
494 | exit: | ||
495 | return err; | ||
496 | } | ||
497 | |||
498 | static int lm95245_remove(struct i2c_client *client) | ||
499 | { | ||
500 | struct lm95245_data *data = i2c_get_clientdata(client); | ||
501 | |||
502 | hwmon_device_unregister(data->hwmon_dev); | ||
503 | sysfs_remove_group(&client->dev.kobj, &lm95245_group); | ||
504 | |||
505 | kfree(data); | ||
506 | return 0; | ||
507 | } | ||
508 | |||
509 | /* Driver data (common to all clients) */ | ||
510 | static const struct i2c_device_id lm95245_id[] = { | ||
511 | { DEVNAME, 0 }, | ||
512 | { } | ||
513 | }; | ||
514 | MODULE_DEVICE_TABLE(i2c, lm95245_id); | ||
515 | |||
516 | static struct i2c_driver lm95245_driver = { | ||
517 | .class = I2C_CLASS_HWMON, | ||
518 | .driver = { | ||
519 | .name = DEVNAME, | ||
520 | }, | ||
521 | .probe = lm95245_probe, | ||
522 | .remove = lm95245_remove, | ||
523 | .id_table = lm95245_id, | ||
524 | .detect = lm95245_detect, | ||
525 | .address_list = normal_i2c, | ||
526 | }; | ||
527 | |||
528 | static int __init sensors_lm95245_init(void) | ||
529 | { | ||
530 | return i2c_add_driver(&lm95245_driver); | ||
531 | } | ||
532 | |||
533 | static void __exit sensors_lm95245_exit(void) | ||
534 | { | ||
535 | i2c_del_driver(&lm95245_driver); | ||
536 | } | ||
537 | |||
538 | MODULE_AUTHOR("Alexander Stein <alexander.stein@systec-electronic.com>"); | ||
539 | MODULE_DESCRIPTION("LM95245 sensor driver"); | ||
540 | MODULE_LICENSE("GPL"); | ||
541 | |||
542 | module_init(sensors_lm95245_init); | ||
543 | module_exit(sensors_lm95245_exit); | ||