]>
Commit | Line | Data |
---|---|---|
fffd80cc AS |
1 | /* |
2 | * Copyright (C) 2011 Alexander Stein <alexander.stein@systec-electronic.com> | |
3 | * | |
162a8dfe | 4 | * The LM95245 is a sensor chip made by TI / National Semiconductor. |
fffd80cc | 5 | * It reports up to two temperatures (its own plus an external one). |
fffd80cc AS |
6 | * |
7 | * This driver is based on lm95241.c | |
8 | * | |
9 | * This program is free software; you can redistribute it and/or modify | |
10 | * it under the terms of the GNU General Public License as published by | |
11 | * the Free Software Foundation; either version 2 of the License, or | |
12 | * (at your option) any later version. | |
13 | * | |
14 | * This program is distributed in the hope that it will be useful, | |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 | * GNU General Public License for more details. | |
fffd80cc AS |
18 | */ |
19 | ||
c0a4b9ec | 20 | #include <linux/err.h> |
fffd80cc | 21 | #include <linux/init.h> |
fffd80cc | 22 | #include <linux/hwmon.h> |
c0a4b9ec GR |
23 | #include <linux/i2c.h> |
24 | #include <linux/module.h> | |
fffd80cc | 25 | #include <linux/mutex.h> |
c0a4b9ec GR |
26 | #include <linux/regmap.h> |
27 | #include <linux/slab.h> | |
fffd80cc | 28 | |
fffd80cc AS |
29 | static const unsigned short normal_i2c[] = { |
30 | 0x18, 0x19, 0x29, 0x4c, 0x4d, I2C_CLIENT_END }; | |
31 | ||
32 | /* LM95245 registers */ | |
33 | /* general registers */ | |
34 | #define LM95245_REG_RW_CONFIG1 0x03 | |
35 | #define LM95245_REG_RW_CONVERS_RATE 0x04 | |
36 | #define LM95245_REG_W_ONE_SHOT 0x0F | |
37 | ||
38 | /* diode configuration */ | |
39 | #define LM95245_REG_RW_CONFIG2 0xBF | |
40 | #define LM95245_REG_RW_REMOTE_OFFH 0x11 | |
41 | #define LM95245_REG_RW_REMOTE_OFFL 0x12 | |
42 | ||
43 | /* status registers */ | |
44 | #define LM95245_REG_R_STATUS1 0x02 | |
45 | #define LM95245_REG_R_STATUS2 0x33 | |
46 | ||
47 | /* limit registers */ | |
48 | #define LM95245_REG_RW_REMOTE_OS_LIMIT 0x07 | |
49 | #define LM95245_REG_RW_LOCAL_OS_TCRIT_LIMIT 0x20 | |
50 | #define LM95245_REG_RW_REMOTE_TCRIT_LIMIT 0x19 | |
51 | #define LM95245_REG_RW_COMMON_HYSTERESIS 0x21 | |
52 | ||
53 | /* temperature signed */ | |
54 | #define LM95245_REG_R_LOCAL_TEMPH_S 0x00 | |
55 | #define LM95245_REG_R_LOCAL_TEMPL_S 0x30 | |
56 | #define LM95245_REG_R_REMOTE_TEMPH_S 0x01 | |
57 | #define LM95245_REG_R_REMOTE_TEMPL_S 0x10 | |
58 | /* temperature unsigned */ | |
59 | #define LM95245_REG_R_REMOTE_TEMPH_U 0x31 | |
60 | #define LM95245_REG_R_REMOTE_TEMPL_U 0x32 | |
61 | ||
62 | /* id registers */ | |
63 | #define LM95245_REG_R_MAN_ID 0xFE | |
64 | #define LM95245_REG_R_CHIP_ID 0xFF | |
65 | ||
66 | /* LM95245 specific bitfields */ | |
67 | #define CFG_STOP 0x40 | |
68 | #define CFG_REMOTE_TCRIT_MASK 0x10 | |
69 | #define CFG_REMOTE_OS_MASK 0x08 | |
70 | #define CFG_LOCAL_TCRIT_MASK 0x04 | |
71 | #define CFG_LOCAL_OS_MASK 0x02 | |
72 | ||
73 | #define CFG2_OS_A0 0x40 | |
74 | #define CFG2_DIODE_FAULT_OS 0x20 | |
75 | #define CFG2_DIODE_FAULT_TCRIT 0x10 | |
76 | #define CFG2_REMOTE_TT 0x08 | |
77 | #define CFG2_REMOTE_FILTER_DIS 0x00 | |
78 | #define CFG2_REMOTE_FILTER_EN 0x06 | |
79 | ||
80 | /* conversation rate in ms */ | |
81 | #define RATE_CR0063 0x00 | |
82 | #define RATE_CR0364 0x01 | |
83 | #define RATE_CR1000 0x02 | |
84 | #define RATE_CR2500 0x03 | |
85 | ||
c0a4b9ec | 86 | #define STATUS1_ROS 0x10 |
fffd80cc AS |
87 | #define STATUS1_DIODE_FAULT 0x04 |
88 | #define STATUS1_RTCRIT 0x02 | |
89 | #define STATUS1_LOC 0x01 | |
90 | ||
91 | #define MANUFACTURER_ID 0x01 | |
162a8dfe GR |
92 | #define LM95235_REVISION 0xB1 |
93 | #define LM95245_REVISION 0xB3 | |
fffd80cc AS |
94 | |
95 | static const u8 lm95245_reg_address[] = { | |
96 | LM95245_REG_R_LOCAL_TEMPH_S, | |
97 | LM95245_REG_R_LOCAL_TEMPL_S, | |
98 | LM95245_REG_R_REMOTE_TEMPH_S, | |
99 | LM95245_REG_R_REMOTE_TEMPL_S, | |
100 | LM95245_REG_R_REMOTE_TEMPH_U, | |
101 | LM95245_REG_R_REMOTE_TEMPL_U, | |
102 | LM95245_REG_RW_LOCAL_OS_TCRIT_LIMIT, | |
103 | LM95245_REG_RW_REMOTE_TCRIT_LIMIT, | |
104 | LM95245_REG_RW_COMMON_HYSTERESIS, | |
105 | LM95245_REG_R_STATUS1, | |
106 | }; | |
107 | ||
108 | /* Client data (each client gets its own) */ | |
109 | struct lm95245_data { | |
c0a4b9ec | 110 | struct regmap *regmap; |
fffd80cc | 111 | struct mutex update_lock; |
c0a4b9ec | 112 | int interval; /* in msecs */ |
fffd80cc AS |
113 | }; |
114 | ||
115 | /* Conversions */ | |
116 | static int temp_from_reg_unsigned(u8 val_h, u8 val_l) | |
117 | { | |
118 | return val_h * 1000 + val_l * 1000 / 256; | |
119 | } | |
120 | ||
121 | static int temp_from_reg_signed(u8 val_h, u8 val_l) | |
122 | { | |
123 | if (val_h & 0x80) | |
124 | return (val_h - 0x100) * 1000; | |
125 | return temp_from_reg_unsigned(val_h, val_l); | |
126 | } | |
127 | ||
c0a4b9ec | 128 | static int lm95245_read_conversion_rate(struct lm95245_data *data) |
fffd80cc | 129 | { |
c0a4b9ec GR |
130 | unsigned int rate; |
131 | int ret; | |
fffd80cc | 132 | |
c0a4b9ec GR |
133 | ret = regmap_read(data->regmap, LM95245_REG_RW_CONVERS_RATE, &rate); |
134 | if (ret < 0) | |
135 | return ret; | |
fffd80cc AS |
136 | |
137 | switch (rate) { | |
138 | case RATE_CR0063: | |
c0a4b9ec | 139 | data->interval = 63; |
fffd80cc AS |
140 | break; |
141 | case RATE_CR0364: | |
c0a4b9ec | 142 | data->interval = 364; |
fffd80cc AS |
143 | break; |
144 | case RATE_CR1000: | |
c0a4b9ec | 145 | data->interval = 1000; |
fffd80cc AS |
146 | break; |
147 | case RATE_CR2500: | |
148 | default: | |
c0a4b9ec | 149 | data->interval = 2500; |
fffd80cc AS |
150 | break; |
151 | } | |
c0a4b9ec | 152 | return 0; |
fffd80cc AS |
153 | } |
154 | ||
c0a4b9ec | 155 | static int lm95245_set_conversion_rate(struct lm95245_data *data, long interval) |
fffd80cc | 156 | { |
c0a4b9ec | 157 | int ret, rate; |
fffd80cc AS |
158 | |
159 | if (interval <= 63) { | |
160 | interval = 63; | |
161 | rate = RATE_CR0063; | |
162 | } else if (interval <= 364) { | |
163 | interval = 364; | |
164 | rate = RATE_CR0364; | |
165 | } else if (interval <= 1000) { | |
166 | interval = 1000; | |
167 | rate = RATE_CR1000; | |
168 | } else { | |
169 | interval = 2500; | |
170 | rate = RATE_CR2500; | |
171 | } | |
172 | ||
c0a4b9ec GR |
173 | ret = regmap_write(data->regmap, LM95245_REG_RW_CONVERS_RATE, rate); |
174 | if (ret < 0) | |
175 | return ret; | |
fffd80cc | 176 | |
c0a4b9ec GR |
177 | data->interval = interval; |
178 | return 0; | |
fffd80cc AS |
179 | } |
180 | ||
c0a4b9ec GR |
181 | static int lm95245_read_temp(struct device *dev, u32 attr, int channel, |
182 | long *val) | |
fffd80cc | 183 | { |
7276d55e | 184 | struct lm95245_data *data = dev_get_drvdata(dev); |
c0a4b9ec GR |
185 | struct regmap *regmap = data->regmap; |
186 | int ret, regl, regh, regvall, regvalh; | |
187 | ||
188 | switch (attr) { | |
189 | case hwmon_temp_input: | |
190 | regl = channel ? LM95245_REG_R_REMOTE_TEMPL_S : | |
191 | LM95245_REG_R_LOCAL_TEMPL_S; | |
192 | regh = channel ? LM95245_REG_R_REMOTE_TEMPH_S : | |
193 | LM95245_REG_R_LOCAL_TEMPH_S; | |
194 | ret = regmap_read(regmap, regl, ®vall); | |
195 | if (ret < 0) | |
196 | return ret; | |
197 | ret = regmap_read(regmap, regh, ®valh); | |
198 | if (ret < 0) | |
199 | return ret; | |
200 | /* | |
201 | * Local temp is always signed. | |
202 | * Remote temp has both signed and unsigned data. | |
203 | * Use signed calculation for remote if signed bit is set | |
204 | * or if reported temperature is below signed limit. | |
205 | */ | |
206 | if (!channel || (regvalh & 0x80) || regvalh < 0x7f) { | |
207 | *val = temp_from_reg_signed(regvalh, regvall); | |
208 | return 0; | |
209 | } | |
210 | ret = regmap_read(regmap, LM95245_REG_R_REMOTE_TEMPL_U, | |
211 | ®vall); | |
212 | if (ret < 0) | |
213 | return ret; | |
214 | ret = regmap_read(regmap, LM95245_REG_R_REMOTE_TEMPH_U, | |
215 | ®valh); | |
216 | if (ret < 0) | |
217 | return ret; | |
218 | *val = temp_from_reg_unsigned(regvalh, regvall); | |
219 | return 0; | |
220 | case hwmon_temp_max: | |
221 | ret = regmap_read(regmap, LM95245_REG_RW_REMOTE_OS_LIMIT, | |
222 | ®valh); | |
223 | if (ret < 0) | |
224 | return ret; | |
225 | *val = regvalh * 1000; | |
226 | return 0; | |
227 | case hwmon_temp_crit: | |
228 | regh = channel ? LM95245_REG_RW_REMOTE_TCRIT_LIMIT : | |
229 | LM95245_REG_RW_LOCAL_OS_TCRIT_LIMIT; | |
230 | ret = regmap_read(regmap, regh, ®valh); | |
231 | if (ret < 0) | |
232 | return ret; | |
233 | *val = regvalh * 1000; | |
234 | return 0; | |
235 | case hwmon_temp_max_hyst: | |
236 | ret = regmap_read(regmap, LM95245_REG_RW_REMOTE_OS_LIMIT, | |
237 | ®valh); | |
238 | if (ret < 0) | |
239 | return ret; | |
240 | ret = regmap_read(regmap, LM95245_REG_RW_COMMON_HYSTERESIS, | |
241 | ®vall); | |
242 | if (ret < 0) | |
243 | return ret; | |
244 | *val = (regvalh - regvall) * 1000; | |
245 | return 0; | |
246 | case hwmon_temp_crit_hyst: | |
247 | regh = channel ? LM95245_REG_RW_REMOTE_TCRIT_LIMIT : | |
248 | LM95245_REG_RW_LOCAL_OS_TCRIT_LIMIT; | |
249 | ret = regmap_read(regmap, regh, ®valh); | |
250 | if (ret < 0) | |
251 | return ret; | |
252 | ret = regmap_read(regmap, LM95245_REG_RW_COMMON_HYSTERESIS, | |
253 | ®vall); | |
254 | if (ret < 0) | |
255 | return ret; | |
256 | *val = (regvalh - regvall) * 1000; | |
257 | return 0; | |
258 | case hwmon_temp_type: | |
259 | ret = regmap_read(regmap, LM95245_REG_RW_CONFIG2, ®valh); | |
260 | if (ret < 0) | |
261 | return ret; | |
262 | *val = (regvalh & CFG2_REMOTE_TT) ? 1 : 2; | |
263 | return 0; | |
264 | case hwmon_temp_offset: | |
265 | ret = regmap_read(regmap, LM95245_REG_RW_REMOTE_OFFL, | |
266 | ®vall); | |
267 | if (ret < 0) | |
268 | return ret; | |
269 | ret = regmap_read(regmap, LM95245_REG_RW_REMOTE_OFFH, | |
270 | ®valh); | |
271 | if (ret < 0) | |
272 | return ret; | |
273 | *val = temp_from_reg_signed(regvalh, regvall); | |
274 | return 0; | |
275 | case hwmon_temp_max_alarm: | |
276 | ret = regmap_read(regmap, LM95245_REG_R_STATUS1, ®valh); | |
277 | if (ret < 0) | |
278 | return ret; | |
279 | *val = !!(regvalh & STATUS1_ROS); | |
280 | return 0; | |
281 | case hwmon_temp_crit_alarm: | |
282 | ret = regmap_read(regmap, LM95245_REG_R_STATUS1, ®valh); | |
283 | if (ret < 0) | |
284 | return ret; | |
285 | *val = !!(regvalh & (channel ? STATUS1_RTCRIT : STATUS1_LOC)); | |
286 | return 0; | |
287 | case hwmon_temp_fault: | |
288 | ret = regmap_read(regmap, LM95245_REG_R_STATUS1, ®valh); | |
289 | if (ret < 0) | |
290 | return ret; | |
291 | *val = !!(regvalh & STATUS1_DIODE_FAULT); | |
292 | return 0; | |
293 | default: | |
294 | return -EOPNOTSUPP; | |
295 | } | |
fffd80cc AS |
296 | } |
297 | ||
c0a4b9ec GR |
298 | static int lm95245_write_temp(struct device *dev, u32 attr, int channel, |
299 | long val) | |
408c15ea | 300 | { |
c0a4b9ec GR |
301 | struct lm95245_data *data = dev_get_drvdata(dev); |
302 | struct regmap *regmap = data->regmap; | |
303 | unsigned int regval; | |
304 | int ret, reg; | |
305 | ||
306 | switch (attr) { | |
307 | case hwmon_temp_max: | |
308 | val = clamp_val(val / 1000, 0, 255); | |
309 | ret = regmap_write(regmap, LM95245_REG_RW_REMOTE_OS_LIMIT, val); | |
310 | return ret; | |
311 | case hwmon_temp_crit: | |
312 | reg = channel ? LM95245_REG_RW_REMOTE_TCRIT_LIMIT : | |
313 | LM95245_REG_RW_LOCAL_OS_TCRIT_LIMIT; | |
314 | val = clamp_val(val / 1000, 0, channel ? 255 : 127); | |
315 | ret = regmap_write(regmap, reg, val); | |
316 | return ret; | |
317 | case hwmon_temp_crit_hyst: | |
318 | mutex_lock(&data->update_lock); | |
319 | ret = regmap_read(regmap, LM95245_REG_RW_LOCAL_OS_TCRIT_LIMIT, | |
320 | ®val); | |
321 | if (ret < 0) { | |
322 | mutex_unlock(&data->update_lock); | |
323 | return ret; | |
324 | } | |
325 | /* Clamp to reasonable range to prevent overflow */ | |
326 | val = clamp_val(val, -1000000, 1000000); | |
327 | val = regval - val / 1000; | |
328 | val = clamp_val(val, 0, 31); | |
329 | ret = regmap_write(regmap, LM95245_REG_RW_COMMON_HYSTERESIS, | |
330 | val); | |
331 | mutex_unlock(&data->update_lock); | |
332 | return ret; | |
333 | case hwmon_temp_offset: | |
334 | val = clamp_val(val, -128000, 127875); | |
335 | val = val * 256 / 1000; | |
336 | mutex_lock(&data->update_lock); | |
337 | ret = regmap_write(regmap, LM95245_REG_RW_REMOTE_OFFL, | |
338 | val & 0xe0); | |
339 | if (ret < 0) { | |
340 | mutex_unlock(&data->update_lock); | |
341 | return ret; | |
342 | } | |
343 | ret = regmap_write(regmap, LM95245_REG_RW_REMOTE_OFFH, | |
344 | (val >> 8) & 0xff); | |
345 | mutex_unlock(&data->update_lock); | |
346 | return ret; | |
347 | case hwmon_temp_type: | |
348 | if (val != 1 && val != 2) | |
349 | return -EINVAL; | |
350 | ret = regmap_update_bits(regmap, LM95245_REG_RW_CONFIG2, | |
351 | CFG2_REMOTE_TT, | |
352 | val == 1 ? CFG2_REMOTE_TT : 0); | |
353 | return ret; | |
354 | default: | |
355 | return -EOPNOTSUPP; | |
356 | } | |
408c15ea GR |
357 | } |
358 | ||
c0a4b9ec GR |
359 | static int lm95245_read_chip(struct device *dev, u32 attr, int channel, |
360 | long *val) | |
fffd80cc | 361 | { |
7276d55e | 362 | struct lm95245_data *data = dev_get_drvdata(dev); |
fffd80cc | 363 | |
c0a4b9ec GR |
364 | switch (attr) { |
365 | case hwmon_chip_update_interval: | |
366 | *val = data->interval; | |
367 | return 0; | |
368 | default: | |
369 | return -EOPNOTSUPP; | |
370 | } | |
fffd80cc AS |
371 | } |
372 | ||
c0a4b9ec GR |
373 | static int lm95245_write_chip(struct device *dev, u32 attr, int channel, |
374 | long val) | |
fffd80cc | 375 | { |
7276d55e | 376 | struct lm95245_data *data = dev_get_drvdata(dev); |
c0a4b9ec GR |
377 | int ret; |
378 | ||
379 | switch (attr) { | |
380 | case hwmon_chip_update_interval: | |
381 | mutex_lock(&data->update_lock); | |
382 | ret = lm95245_set_conversion_rate(data, val); | |
383 | mutex_unlock(&data->update_lock); | |
384 | return ret; | |
385 | default: | |
386 | return -EOPNOTSUPP; | |
387 | } | |
fffd80cc AS |
388 | } |
389 | ||
c0a4b9ec GR |
390 | static int lm95245_read(struct device *dev, enum hwmon_sensor_types type, |
391 | u32 attr, int channel, long *val) | |
fffd80cc | 392 | { |
c0a4b9ec GR |
393 | switch (type) { |
394 | case hwmon_chip: | |
395 | return lm95245_read_chip(dev, attr, channel, val); | |
396 | case hwmon_temp: | |
397 | return lm95245_read_temp(dev, attr, channel, val); | |
398 | default: | |
399 | return -EOPNOTSUPP; | |
400 | } | |
fffd80cc AS |
401 | } |
402 | ||
c0a4b9ec GR |
403 | static int lm95245_write(struct device *dev, enum hwmon_sensor_types type, |
404 | u32 attr, int channel, long val) | |
fffd80cc | 405 | { |
c0a4b9ec GR |
406 | switch (type) { |
407 | case hwmon_chip: | |
408 | return lm95245_write_chip(dev, attr, channel, val); | |
409 | case hwmon_temp: | |
410 | return lm95245_write_temp(dev, attr, channel, val); | |
411 | default: | |
412 | return -EOPNOTSUPP; | |
413 | } | |
fffd80cc AS |
414 | } |
415 | ||
c0a4b9ec | 416 | static umode_t lm95245_temp_is_visible(const void *data, u32 attr, int channel) |
fffd80cc | 417 | { |
c0a4b9ec GR |
418 | switch (attr) { |
419 | case hwmon_temp_input: | |
420 | case hwmon_temp_max_alarm: | |
421 | case hwmon_temp_max_hyst: | |
422 | case hwmon_temp_crit_alarm: | |
423 | case hwmon_temp_fault: | |
424 | return S_IRUGO; | |
425 | case hwmon_temp_type: | |
426 | case hwmon_temp_max: | |
427 | case hwmon_temp_crit: | |
428 | case hwmon_temp_offset: | |
429 | return S_IRUGO | S_IWUSR; | |
430 | case hwmon_temp_crit_hyst: | |
431 | return (channel == 0) ? S_IRUGO | S_IWUSR : S_IRUGO; | |
432 | default: | |
433 | return 0; | |
434 | } | |
fffd80cc AS |
435 | } |
436 | ||
c0a4b9ec GR |
437 | static umode_t lm95245_is_visible(const void *data, |
438 | enum hwmon_sensor_types type, | |
439 | u32 attr, int channel) | |
fffd80cc | 440 | { |
c0a4b9ec GR |
441 | switch (type) { |
442 | case hwmon_chip: | |
443 | switch (attr) { | |
444 | case hwmon_chip_update_interval: | |
445 | return S_IRUGO | S_IWUSR; | |
446 | default: | |
447 | return 0; | |
448 | } | |
449 | case hwmon_temp: | |
450 | return lm95245_temp_is_visible(data, attr, channel); | |
451 | default: | |
452 | return 0; | |
453 | } | |
fffd80cc AS |
454 | } |
455 | ||
fffd80cc AS |
456 | /* Return 0 if detection is successful, -ENODEV otherwise */ |
457 | static int lm95245_detect(struct i2c_client *new_client, | |
458 | struct i2c_board_info *info) | |
459 | { | |
460 | struct i2c_adapter *adapter = new_client->adapter; | |
162a8dfe GR |
461 | int address = new_client->addr; |
462 | const char *name; | |
463 | int rev, id; | |
fffd80cc AS |
464 | |
465 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | |
466 | return -ENODEV; | |
467 | ||
162a8dfe GR |
468 | id = i2c_smbus_read_byte_data(new_client, LM95245_REG_R_MAN_ID); |
469 | if (id != MANUFACTURER_ID) | |
fffd80cc AS |
470 | return -ENODEV; |
471 | ||
162a8dfe GR |
472 | rev = i2c_smbus_read_byte_data(new_client, LM95245_REG_R_CHIP_ID); |
473 | switch (rev) { | |
474 | case LM95235_REVISION: | |
475 | if (address != 0x18 && address != 0x29 && address != 0x4c) | |
476 | return -ENODEV; | |
477 | name = "lm95235"; | |
478 | break; | |
479 | case LM95245_REVISION: | |
480 | name = "lm95245"; | |
481 | break; | |
482 | default: | |
483 | return -ENODEV; | |
484 | } | |
485 | ||
486 | strlcpy(info->type, name, I2C_NAME_SIZE); | |
fffd80cc AS |
487 | return 0; |
488 | } | |
489 | ||
c0a4b9ec | 490 | static int lm95245_init_client(struct lm95245_data *data) |
fffd80cc | 491 | { |
c0a4b9ec GR |
492 | int ret; |
493 | ||
494 | ret = lm95245_read_conversion_rate(data); | |
495 | if (ret < 0) | |
496 | return ret; | |
497 | ||
498 | return regmap_update_bits(data->regmap, LM95245_REG_RW_CONFIG1, | |
499 | CFG_STOP, 0); | |
500 | } | |
501 | ||
502 | static bool lm95245_is_writeable_reg(struct device *dev, unsigned int reg) | |
503 | { | |
504 | switch (reg) { | |
505 | case LM95245_REG_RW_CONFIG1: | |
506 | case LM95245_REG_RW_CONVERS_RATE: | |
507 | case LM95245_REG_W_ONE_SHOT: | |
508 | case LM95245_REG_RW_CONFIG2: | |
509 | case LM95245_REG_RW_REMOTE_OFFH: | |
510 | case LM95245_REG_RW_REMOTE_OFFL: | |
511 | case LM95245_REG_RW_REMOTE_OS_LIMIT: | |
512 | case LM95245_REG_RW_LOCAL_OS_TCRIT_LIMIT: | |
513 | case LM95245_REG_RW_REMOTE_TCRIT_LIMIT: | |
514 | case LM95245_REG_RW_COMMON_HYSTERESIS: | |
515 | return true; | |
516 | default: | |
517 | return false; | |
518 | } | |
519 | } | |
520 | ||
521 | static bool lm95245_is_volatile_reg(struct device *dev, unsigned int reg) | |
522 | { | |
523 | switch (reg) { | |
524 | case LM95245_REG_R_STATUS1: | |
525 | case LM95245_REG_R_STATUS2: | |
526 | case LM95245_REG_R_LOCAL_TEMPH_S: | |
527 | case LM95245_REG_R_LOCAL_TEMPL_S: | |
528 | case LM95245_REG_R_REMOTE_TEMPH_S: | |
529 | case LM95245_REG_R_REMOTE_TEMPL_S: | |
530 | case LM95245_REG_R_REMOTE_TEMPH_U: | |
531 | case LM95245_REG_R_REMOTE_TEMPL_U: | |
532 | return true; | |
533 | default: | |
534 | return false; | |
fffd80cc AS |
535 | } |
536 | } | |
537 | ||
c0a4b9ec GR |
538 | static const struct regmap_config lm95245_regmap_config = { |
539 | .reg_bits = 8, | |
540 | .val_bits = 8, | |
541 | .writeable_reg = lm95245_is_writeable_reg, | |
542 | .volatile_reg = lm95245_is_volatile_reg, | |
543 | .cache_type = REGCACHE_RBTREE, | |
544 | .use_single_rw = true, | |
545 | }; | |
546 | ||
547 | static const u32 lm95245_chip_config[] = { | |
548 | HWMON_C_UPDATE_INTERVAL, | |
549 | 0 | |
550 | }; | |
551 | ||
552 | static const struct hwmon_channel_info lm95245_chip = { | |
553 | .type = hwmon_chip, | |
554 | .config = lm95245_chip_config, | |
555 | }; | |
556 | ||
557 | static const u32 lm95245_temp_config[] = { | |
558 | HWMON_T_INPUT | HWMON_T_CRIT | HWMON_T_CRIT_HYST | HWMON_T_CRIT_ALARM, | |
559 | HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_MAX_HYST | HWMON_T_CRIT | | |
560 | HWMON_T_CRIT_HYST | HWMON_T_FAULT | HWMON_T_MAX_ALARM | | |
561 | HWMON_T_CRIT_ALARM | HWMON_T_TYPE | HWMON_T_OFFSET, | |
562 | 0 | |
563 | }; | |
564 | ||
565 | static const struct hwmon_channel_info lm95245_temp = { | |
566 | .type = hwmon_temp, | |
567 | .config = lm95245_temp_config, | |
568 | }; | |
569 | ||
570 | static const struct hwmon_channel_info *lm95245_info[] = { | |
571 | &lm95245_chip, | |
572 | &lm95245_temp, | |
573 | NULL | |
574 | }; | |
575 | ||
576 | static const struct hwmon_ops lm95245_hwmon_ops = { | |
577 | .is_visible = lm95245_is_visible, | |
578 | .read = lm95245_read, | |
579 | .write = lm95245_write, | |
580 | }; | |
581 | ||
582 | static const struct hwmon_chip_info lm95245_chip_info = { | |
583 | .ops = &lm95245_hwmon_ops, | |
584 | .info = lm95245_info, | |
585 | }; | |
586 | ||
7276d55e | 587 | static int lm95245_probe(struct i2c_client *client, |
fffd80cc AS |
588 | const struct i2c_device_id *id) |
589 | { | |
7276d55e | 590 | struct device *dev = &client->dev; |
fffd80cc | 591 | struct lm95245_data *data; |
7276d55e | 592 | struct device *hwmon_dev; |
c0a4b9ec | 593 | int ret; |
fffd80cc | 594 | |
7276d55e | 595 | data = devm_kzalloc(dev, sizeof(struct lm95245_data), GFP_KERNEL); |
a8dd946c GR |
596 | if (!data) |
597 | return -ENOMEM; | |
fffd80cc | 598 | |
c0a4b9ec GR |
599 | data->regmap = devm_regmap_init_i2c(client, &lm95245_regmap_config); |
600 | if (IS_ERR(data->regmap)) | |
601 | return PTR_ERR(data->regmap); | |
602 | ||
fffd80cc AS |
603 | mutex_init(&data->update_lock); |
604 | ||
605 | /* Initialize the LM95245 chip */ | |
c0a4b9ec GR |
606 | ret = lm95245_init_client(data); |
607 | if (ret < 0) | |
608 | return ret; | |
609 | ||
610 | hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name, | |
611 | data, | |
612 | &lm95245_chip_info, | |
613 | NULL); | |
7276d55e | 614 | return PTR_ERR_OR_ZERO(hwmon_dev); |
fffd80cc AS |
615 | } |
616 | ||
617 | /* Driver data (common to all clients) */ | |
618 | static const struct i2c_device_id lm95245_id[] = { | |
162a8dfe GR |
619 | { "lm95235", 0 }, |
620 | { "lm95245", 0 }, | |
fffd80cc AS |
621 | { } |
622 | }; | |
623 | MODULE_DEVICE_TABLE(i2c, lm95245_id); | |
624 | ||
5ada7055 JMC |
625 | static const struct of_device_id lm95245_of_match[] = { |
626 | { .compatible = "national,lm95235" }, | |
627 | { .compatible = "national,lm95245" }, | |
628 | { }, | |
629 | }; | |
630 | MODULE_DEVICE_TABLE(of, lm95245_of_match); | |
631 | ||
fffd80cc AS |
632 | static struct i2c_driver lm95245_driver = { |
633 | .class = I2C_CLASS_HWMON, | |
634 | .driver = { | |
162a8dfe | 635 | .name = "lm95245", |
5ada7055 | 636 | .of_match_table = of_match_ptr(lm95245_of_match), |
fffd80cc AS |
637 | }, |
638 | .probe = lm95245_probe, | |
fffd80cc AS |
639 | .id_table = lm95245_id, |
640 | .detect = lm95245_detect, | |
641 | .address_list = normal_i2c, | |
642 | }; | |
643 | ||
f0967eea | 644 | module_i2c_driver(lm95245_driver); |
fffd80cc AS |
645 | |
646 | MODULE_AUTHOR("Alexander Stein <alexander.stein@systec-electronic.com>"); | |
162a8dfe | 647 | MODULE_DESCRIPTION("LM95235/LM95245 sensor driver"); |
fffd80cc | 648 | MODULE_LICENSE("GPL"); |