diff options
author | Guenter Roeck <linux@roeck-us.net> | 2013-02-09 18:15:52 -0500 |
---|---|---|
committer | Guenter Roeck <linux@roeck-us.net> | 2013-04-08 00:16:41 -0400 |
commit | 58615a94f6a190f2fb9f9a99f1894d161c4b85b9 (patch) | |
tree | a610147e40dbe0af85e880b1ed866e91f9730bf4 /drivers/hwmon | |
parent | e53e6497fc9f071734c1794c3dc08bd5f334fa7f (diff) |
hwmon: (pmbus/lm25066) Add support for LM25056
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Diffstat (limited to 'drivers/hwmon')
-rw-r--r-- | drivers/hwmon/pmbus/Kconfig | 2 | ||||
-rw-r--r-- | drivers/hwmon/pmbus/lm25066.c | 132 |
2 files changed, 124 insertions, 10 deletions
diff --git a/drivers/hwmon/pmbus/Kconfig b/drivers/hwmon/pmbus/Kconfig index b1adad60d6ad..39cc63edfbb0 100644 --- a/drivers/hwmon/pmbus/Kconfig +++ b/drivers/hwmon/pmbus/Kconfig | |||
@@ -42,7 +42,7 @@ config SENSORS_LM25066 | |||
42 | default n | 42 | default n |
43 | help | 43 | help |
44 | If you say yes here you get hardware monitoring support for National | 44 | If you say yes here you get hardware monitoring support for National |
45 | Semiconductor LM25066, LM5064, and LM5066. | 45 | Semiconductor LM25056, LM25066, LM5064, and LM5066. |
46 | 46 | ||
47 | This driver can also be built as a module. If so, the module will | 47 | This driver can also be built as a module. If so, the module will |
48 | be called lm25066. | 48 | be called lm25066. |
diff --git a/drivers/hwmon/pmbus/lm25066.c b/drivers/hwmon/pmbus/lm25066.c index 08267149dc63..6a9d6edaacb3 100644 --- a/drivers/hwmon/pmbus/lm25066.c +++ b/drivers/hwmon/pmbus/lm25066.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Hardware monitoring driver for LM25066 / LM5064 / LM5066 | 2 | * Hardware monitoring driver for LM25056 / LM25066 / LM5064 / LM5066 |
3 | * | 3 | * |
4 | * Copyright (c) 2011 Ericsson AB. | 4 | * Copyright (c) 2011 Ericsson AB. |
5 | * Copyright (c) 2013 Guenter Roeck | 5 | * Copyright (c) 2013 Guenter Roeck |
@@ -27,7 +27,7 @@ | |||
27 | #include <linux/i2c.h> | 27 | #include <linux/i2c.h> |
28 | #include "pmbus.h" | 28 | #include "pmbus.h" |
29 | 29 | ||
30 | enum chips { lm25066, lm5064, lm5066 }; | 30 | enum chips { lm25056, lm25066, lm5064, lm5066 }; |
31 | 31 | ||
32 | #define LM25066_READ_VAUX 0xd0 | 32 | #define LM25066_READ_VAUX 0xd0 |
33 | #define LM25066_MFR_READ_IIN 0xd1 | 33 | #define LM25066_MFR_READ_IIN 0xd1 |
@@ -44,6 +44,14 @@ enum chips { lm25066, lm5064, lm5066 }; | |||
44 | 44 | ||
45 | #define LM25066_DEV_SETUP_CL (1 << 4) /* Current limit */ | 45 | #define LM25066_DEV_SETUP_CL (1 << 4) /* Current limit */ |
46 | 46 | ||
47 | /* LM25056 only */ | ||
48 | |||
49 | #define LM25056_VAUX_OV_WARN_LIMIT 0xe3 | ||
50 | #define LM25056_VAUX_UV_WARN_LIMIT 0xe4 | ||
51 | |||
52 | #define LM25056_MFR_STS_VAUX_OV_WARN (1 << 1) | ||
53 | #define LM25056_MFR_STS_VAUX_UV_WARN (1 << 0) | ||
54 | |||
47 | struct __coeff { | 55 | struct __coeff { |
48 | short m, b, R; | 56 | short m, b, R; |
49 | }; | 57 | }; |
@@ -51,7 +59,34 @@ struct __coeff { | |||
51 | #define PSC_CURRENT_IN_L (PSC_NUM_CLASSES) | 59 | #define PSC_CURRENT_IN_L (PSC_NUM_CLASSES) |
52 | #define PSC_POWER_L (PSC_NUM_CLASSES + 1) | 60 | #define PSC_POWER_L (PSC_NUM_CLASSES + 1) |
53 | 61 | ||
54 | static struct __coeff lm25066_coeff[3][PSC_NUM_CLASSES + 2] = { | 62 | static struct __coeff lm25066_coeff[4][PSC_NUM_CLASSES + 2] = { |
63 | [lm25056] = { | ||
64 | [PSC_VOLTAGE_IN] = { | ||
65 | .m = 16296, | ||
66 | .R = -2, | ||
67 | }, | ||
68 | [PSC_CURRENT_IN] = { | ||
69 | .m = 13797, | ||
70 | .R = -2, | ||
71 | }, | ||
72 | [PSC_CURRENT_IN_L] = { | ||
73 | .m = 6726, | ||
74 | .R = -2, | ||
75 | }, | ||
76 | [PSC_POWER] = { | ||
77 | .m = 5501, | ||
78 | .R = -3, | ||
79 | }, | ||
80 | [PSC_POWER_L] = { | ||
81 | .m = 26882, | ||
82 | .R = -4, | ||
83 | }, | ||
84 | [PSC_TEMPERATURE] = { | ||
85 | .m = 1580, | ||
86 | .b = -14500, | ||
87 | .R = -2, | ||
88 | }, | ||
89 | }, | ||
55 | [lm25066] = { | 90 | [lm25066] = { |
56 | [PSC_VOLTAGE_IN] = { | 91 | [PSC_VOLTAGE_IN] = { |
57 | .m = 22070, | 92 | .m = 22070, |
@@ -161,6 +196,10 @@ static int lm25066_read_word_data(struct i2c_client *client, int page, int reg) | |||
161 | break; | 196 | break; |
162 | /* Adjust returned value to match VIN coefficients */ | 197 | /* Adjust returned value to match VIN coefficients */ |
163 | switch (data->id) { | 198 | switch (data->id) { |
199 | case lm25056: | ||
200 | /* VIN: 6.14 mV VAUX: 293 uV LSB */ | ||
201 | ret = DIV_ROUND_CLOSEST(ret * 293, 6140); | ||
202 | break; | ||
164 | case lm25066: | 203 | case lm25066: |
165 | /* VIN: 4.54 mV VAUX: 283.2 uV LSB */ | 204 | /* VIN: 4.54 mV VAUX: 283.2 uV LSB */ |
166 | ret = DIV_ROUND_CLOSEST(ret * 2832, 45400); | 205 | ret = DIV_ROUND_CLOSEST(ret * 2832, 45400); |
@@ -214,6 +253,58 @@ static int lm25066_read_word_data(struct i2c_client *client, int page, int reg) | |||
214 | return ret; | 253 | return ret; |
215 | } | 254 | } |
216 | 255 | ||
256 | static int lm25056_read_word_data(struct i2c_client *client, int page, int reg) | ||
257 | { | ||
258 | int ret; | ||
259 | |||
260 | switch (reg) { | ||
261 | case PMBUS_VIRT_VMON_UV_WARN_LIMIT: | ||
262 | ret = pmbus_read_word_data(client, 0, | ||
263 | LM25056_VAUX_UV_WARN_LIMIT); | ||
264 | if (ret < 0) | ||
265 | break; | ||
266 | /* Adjust returned value to match VIN coefficients */ | ||
267 | ret = DIV_ROUND_CLOSEST(ret * 293, 6140); | ||
268 | break; | ||
269 | case PMBUS_VIRT_VMON_OV_WARN_LIMIT: | ||
270 | ret = pmbus_read_word_data(client, 0, | ||
271 | LM25056_VAUX_OV_WARN_LIMIT); | ||
272 | if (ret < 0) | ||
273 | break; | ||
274 | /* Adjust returned value to match VIN coefficients */ | ||
275 | ret = DIV_ROUND_CLOSEST(ret * 293, 6140); | ||
276 | break; | ||
277 | default: | ||
278 | ret = lm25066_read_word_data(client, page, reg); | ||
279 | break; | ||
280 | } | ||
281 | return ret; | ||
282 | } | ||
283 | |||
284 | static int lm25056_read_byte_data(struct i2c_client *client, int page, int reg) | ||
285 | { | ||
286 | int ret, s; | ||
287 | |||
288 | switch (reg) { | ||
289 | case PMBUS_VIRT_STATUS_VMON: | ||
290 | ret = pmbus_read_byte_data(client, 0, | ||
291 | PMBUS_STATUS_MFR_SPECIFIC); | ||
292 | if (ret < 0) | ||
293 | break; | ||
294 | s = 0; | ||
295 | if (ret & LM25056_MFR_STS_VAUX_UV_WARN) | ||
296 | s |= PB_VOLTAGE_UV_WARNING; | ||
297 | if (ret & LM25056_MFR_STS_VAUX_OV_WARN) | ||
298 | s |= PB_VOLTAGE_OV_WARNING; | ||
299 | ret = s; | ||
300 | break; | ||
301 | default: | ||
302 | ret = -ENODATA; | ||
303 | break; | ||
304 | } | ||
305 | return ret; | ||
306 | } | ||
307 | |||
217 | static int lm25066_write_word_data(struct i2c_client *client, int page, int reg, | 308 | static int lm25066_write_word_data(struct i2c_client *client, int page, int reg, |
218 | u16 word) | 309 | u16 word) |
219 | { | 310 | { |
@@ -243,6 +334,22 @@ static int lm25066_write_word_data(struct i2c_client *client, int page, int reg, | |||
243 | word); | 334 | word); |
244 | pmbus_clear_cache(client); | 335 | pmbus_clear_cache(client); |
245 | break; | 336 | break; |
337 | case PMBUS_VIRT_VMON_UV_WARN_LIMIT: | ||
338 | /* Adjust from VIN coefficients (for LM25056) */ | ||
339 | word = DIV_ROUND_CLOSEST((int)word * 6140, 293); | ||
340 | word = ((s16)word < 0) ? 0 : clamp_val(word, 0, 0x0fff); | ||
341 | ret = pmbus_write_word_data(client, 0, | ||
342 | LM25056_VAUX_UV_WARN_LIMIT, word); | ||
343 | pmbus_clear_cache(client); | ||
344 | break; | ||
345 | case PMBUS_VIRT_VMON_OV_WARN_LIMIT: | ||
346 | /* Adjust from VIN coefficients (for LM25056) */ | ||
347 | word = DIV_ROUND_CLOSEST((int)word * 6140, 293); | ||
348 | word = ((s16)word < 0) ? 0 : clamp_val(word, 0, 0x0fff); | ||
349 | ret = pmbus_write_word_data(client, 0, | ||
350 | LM25056_VAUX_OV_WARN_LIMIT, word); | ||
351 | pmbus_clear_cache(client); | ||
352 | break; | ||
246 | case PMBUS_VIRT_RESET_PIN_HISTORY: | 353 | case PMBUS_VIRT_RESET_PIN_HISTORY: |
247 | ret = pmbus_write_byte(client, 0, LM25066_CLEAR_PIN_PEAK); | 354 | ret = pmbus_write_byte(client, 0, LM25066_CLEAR_PIN_PEAK); |
248 | break; | 355 | break; |
@@ -284,12 +391,18 @@ static int lm25066_probe(struct i2c_client *client, | |||
284 | info->format[PSC_TEMPERATURE] = direct; | 391 | info->format[PSC_TEMPERATURE] = direct; |
285 | info->format[PSC_POWER] = direct; | 392 | info->format[PSC_POWER] = direct; |
286 | 393 | ||
394 | info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VMON | ||
395 | | PMBUS_HAVE_PIN | PMBUS_HAVE_IIN | PMBUS_HAVE_STATUS_INPUT | ||
396 | | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP; | ||
287 | 397 | ||
288 | info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VMON | PMBUS_HAVE_VOUT | 398 | if (data->id == lm25056) { |
289 | | PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_PIN | PMBUS_HAVE_IIN | 399 | info->func[0] |= PMBUS_HAVE_STATUS_VMON; |
290 | | PMBUS_HAVE_STATUS_INPUT | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP; | 400 | info->read_word_data = lm25056_read_word_data; |
291 | 401 | info->read_byte_data = lm25056_read_byte_data; | |
292 | info->read_word_data = lm25066_read_word_data; | 402 | } else { |
403 | info->func[0] |= PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT; | ||
404 | info->read_word_data = lm25066_read_word_data; | ||
405 | } | ||
293 | info->write_word_data = lm25066_write_word_data; | 406 | info->write_word_data = lm25066_write_word_data; |
294 | 407 | ||
295 | coeff = &lm25066_coeff[data->id][0]; | 408 | coeff = &lm25066_coeff[data->id][0]; |
@@ -318,6 +431,7 @@ static int lm25066_probe(struct i2c_client *client, | |||
318 | } | 431 | } |
319 | 432 | ||
320 | static const struct i2c_device_id lm25066_id[] = { | 433 | static const struct i2c_device_id lm25066_id[] = { |
434 | {"lm25056", lm25056}, | ||
321 | {"lm25066", lm25066}, | 435 | {"lm25066", lm25066}, |
322 | {"lm5064", lm5064}, | 436 | {"lm5064", lm5064}, |
323 | {"lm5066", lm5066}, | 437 | {"lm5066", lm5066}, |
@@ -339,5 +453,5 @@ static struct i2c_driver lm25066_driver = { | |||
339 | module_i2c_driver(lm25066_driver); | 453 | module_i2c_driver(lm25066_driver); |
340 | 454 | ||
341 | MODULE_AUTHOR("Guenter Roeck"); | 455 | MODULE_AUTHOR("Guenter Roeck"); |
342 | MODULE_DESCRIPTION("PMBus driver for LM25066/LM5064/LM5066"); | 456 | MODULE_DESCRIPTION("PMBus driver for LM25056/LM25066/LM5064/LM5066"); |
343 | MODULE_LICENSE("GPL"); | 457 | MODULE_LICENSE("GPL"); |