diff options
author | Guenter Roeck <linux@roeck-us.net> | 2013-03-16 13:25:04 -0400 |
---|---|---|
committer | Guenter Roeck <linux@roeck-us.net> | 2013-10-18 12:12:02 -0400 |
commit | c8ccab7ab5c71b4fab274bfd18425503a4dcc288 (patch) | |
tree | 2855cfb80fa9c3afe7baedb5f2e827f09d139f56 /drivers/hwmon/pmbus | |
parent | 84fb029faa05e1de229a68829cca5dcf85c79894 (diff) |
hwmon: (pmbus/lm25066) Add support for LM25063
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Diffstat (limited to 'drivers/hwmon/pmbus')
-rw-r--r-- | drivers/hwmon/pmbus/lm25066.c | 91 |
1 files changed, 82 insertions, 9 deletions
diff --git a/drivers/hwmon/pmbus/lm25066.c b/drivers/hwmon/pmbus/lm25066.c index 6a9d6edaacb3..a26b1d1d9514 100644 --- a/drivers/hwmon/pmbus/lm25066.c +++ b/drivers/hwmon/pmbus/lm25066.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Hardware monitoring driver for LM25056 / LM25066 / LM5064 / LM5066 | 2 | * Hardware monitoring driver for LM25056 / LM25063 / 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 { lm25056, lm25066, lm5064, lm5066 }; | 30 | enum chips { lm25056, lm25063, 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 |
@@ -52,6 +52,11 @@ enum chips { lm25056, lm25066, lm5064, lm5066 }; | |||
52 | #define LM25056_MFR_STS_VAUX_OV_WARN (1 << 1) | 52 | #define LM25056_MFR_STS_VAUX_OV_WARN (1 << 1) |
53 | #define LM25056_MFR_STS_VAUX_UV_WARN (1 << 0) | 53 | #define LM25056_MFR_STS_VAUX_UV_WARN (1 << 0) |
54 | 54 | ||
55 | /* LM25063 only */ | ||
56 | |||
57 | #define LM25063_READ_VOUT_MAX 0xe5 | ||
58 | #define LM25063_READ_VOUT_MIN 0xe6 | ||
59 | |||
55 | struct __coeff { | 60 | struct __coeff { |
56 | short m, b, R; | 61 | short m, b, R; |
57 | }; | 62 | }; |
@@ -59,7 +64,7 @@ struct __coeff { | |||
59 | #define PSC_CURRENT_IN_L (PSC_NUM_CLASSES) | 64 | #define PSC_CURRENT_IN_L (PSC_NUM_CLASSES) |
60 | #define PSC_POWER_L (PSC_NUM_CLASSES + 1) | 65 | #define PSC_POWER_L (PSC_NUM_CLASSES + 1) |
61 | 66 | ||
62 | static struct __coeff lm25066_coeff[4][PSC_NUM_CLASSES + 2] = { | 67 | static struct __coeff lm25066_coeff[5][PSC_NUM_CLASSES + 2] = { |
63 | [lm25056] = { | 68 | [lm25056] = { |
64 | [PSC_VOLTAGE_IN] = { | 69 | [PSC_VOLTAGE_IN] = { |
65 | .m = 16296, | 70 | .m = 16296, |
@@ -116,6 +121,36 @@ static struct __coeff lm25066_coeff[4][PSC_NUM_CLASSES + 2] = { | |||
116 | .m = 16, | 121 | .m = 16, |
117 | }, | 122 | }, |
118 | }, | 123 | }, |
124 | [lm25063] = { | ||
125 | [PSC_VOLTAGE_IN] = { | ||
126 | .m = 16000, | ||
127 | .R = -2, | ||
128 | }, | ||
129 | [PSC_VOLTAGE_OUT] = { | ||
130 | .m = 16000, | ||
131 | .R = -2, | ||
132 | }, | ||
133 | [PSC_CURRENT_IN] = { | ||
134 | .m = 10000, | ||
135 | .R = -2, | ||
136 | }, | ||
137 | [PSC_CURRENT_IN_L] = { | ||
138 | .m = 10000, | ||
139 | .R = -2, | ||
140 | }, | ||
141 | [PSC_POWER] = { | ||
142 | .m = 5000, | ||
143 | .R = -3, | ||
144 | }, | ||
145 | [PSC_POWER_L] = { | ||
146 | .m = 5000, | ||
147 | .R = -3, | ||
148 | }, | ||
149 | [PSC_TEMPERATURE] = { | ||
150 | .m = 15596, | ||
151 | .R = -3, | ||
152 | }, | ||
153 | }, | ||
119 | [lm5064] = { | 154 | [lm5064] = { |
120 | [PSC_VOLTAGE_IN] = { | 155 | [PSC_VOLTAGE_IN] = { |
121 | .m = 4611, | 156 | .m = 4611, |
@@ -178,6 +213,7 @@ static struct __coeff lm25066_coeff[4][PSC_NUM_CLASSES + 2] = { | |||
178 | 213 | ||
179 | struct lm25066_data { | 214 | struct lm25066_data { |
180 | int id; | 215 | int id; |
216 | u16 rlimit; /* Maximum register value */ | ||
181 | struct pmbus_driver_info info; | 217 | struct pmbus_driver_info info; |
182 | }; | 218 | }; |
183 | 219 | ||
@@ -200,6 +236,10 @@ static int lm25066_read_word_data(struct i2c_client *client, int page, int reg) | |||
200 | /* VIN: 6.14 mV VAUX: 293 uV LSB */ | 236 | /* VIN: 6.14 mV VAUX: 293 uV LSB */ |
201 | ret = DIV_ROUND_CLOSEST(ret * 293, 6140); | 237 | ret = DIV_ROUND_CLOSEST(ret * 293, 6140); |
202 | break; | 238 | break; |
239 | case lm25063: | ||
240 | /* VIN: 6.25 mV VAUX: 200.0 uV LSB */ | ||
241 | ret = DIV_ROUND_CLOSEST(ret * 20, 625); | ||
242 | break; | ||
203 | case lm25066: | 243 | case lm25066: |
204 | /* VIN: 4.54 mV VAUX: 283.2 uV LSB */ | 244 | /* VIN: 4.54 mV VAUX: 283.2 uV LSB */ |
205 | ret = DIV_ROUND_CLOSEST(ret * 2832, 45400); | 245 | ret = DIV_ROUND_CLOSEST(ret * 2832, 45400); |
@@ -253,6 +293,24 @@ static int lm25066_read_word_data(struct i2c_client *client, int page, int reg) | |||
253 | return ret; | 293 | return ret; |
254 | } | 294 | } |
255 | 295 | ||
296 | static int lm25063_read_word_data(struct i2c_client *client, int page, int reg) | ||
297 | { | ||
298 | int ret; | ||
299 | |||
300 | switch (reg) { | ||
301 | case PMBUS_VIRT_READ_VOUT_MAX: | ||
302 | ret = pmbus_read_word_data(client, 0, LM25063_READ_VOUT_MAX); | ||
303 | break; | ||
304 | case PMBUS_VIRT_READ_VOUT_MIN: | ||
305 | ret = pmbus_read_word_data(client, 0, LM25063_READ_VOUT_MIN); | ||
306 | break; | ||
307 | default: | ||
308 | ret = lm25066_read_word_data(client, page, reg); | ||
309 | break; | ||
310 | } | ||
311 | return ret; | ||
312 | } | ||
313 | |||
256 | static int lm25056_read_word_data(struct i2c_client *client, int page, int reg) | 314 | static int lm25056_read_word_data(struct i2c_client *client, int page, int reg) |
257 | { | 315 | { |
258 | int ret; | 316 | int ret; |
@@ -308,27 +366,34 @@ static int lm25056_read_byte_data(struct i2c_client *client, int page, int reg) | |||
308 | static int lm25066_write_word_data(struct i2c_client *client, int page, int reg, | 366 | static int lm25066_write_word_data(struct i2c_client *client, int page, int reg, |
309 | u16 word) | 367 | u16 word) |
310 | { | 368 | { |
369 | const struct pmbus_driver_info *info = pmbus_get_driver_info(client); | ||
370 | const struct lm25066_data *data = to_lm25066_data(info); | ||
311 | int ret; | 371 | int ret; |
312 | 372 | ||
313 | switch (reg) { | 373 | switch (reg) { |
374 | case PMBUS_POUT_OP_FAULT_LIMIT: | ||
375 | case PMBUS_POUT_OP_WARN_LIMIT: | ||
314 | case PMBUS_VOUT_UV_WARN_LIMIT: | 376 | case PMBUS_VOUT_UV_WARN_LIMIT: |
315 | case PMBUS_OT_FAULT_LIMIT: | 377 | case PMBUS_OT_FAULT_LIMIT: |
316 | case PMBUS_OT_WARN_LIMIT: | 378 | case PMBUS_OT_WARN_LIMIT: |
379 | case PMBUS_IIN_OC_FAULT_LIMIT: | ||
317 | case PMBUS_VIN_UV_WARN_LIMIT: | 380 | case PMBUS_VIN_UV_WARN_LIMIT: |
381 | case PMBUS_VIN_UV_FAULT_LIMIT: | ||
382 | case PMBUS_VIN_OV_FAULT_LIMIT: | ||
318 | case PMBUS_VIN_OV_WARN_LIMIT: | 383 | case PMBUS_VIN_OV_WARN_LIMIT: |
319 | word = ((s16)word < 0) ? 0 : clamp_val(word, 0, 0x0fff); | 384 | word = ((s16)word < 0) ? 0 : clamp_val(word, 0, data->rlimit); |
320 | ret = pmbus_write_word_data(client, 0, reg, word); | 385 | ret = pmbus_write_word_data(client, 0, reg, word); |
321 | pmbus_clear_cache(client); | 386 | pmbus_clear_cache(client); |
322 | break; | 387 | break; |
323 | case PMBUS_IIN_OC_WARN_LIMIT: | 388 | case PMBUS_IIN_OC_WARN_LIMIT: |
324 | word = ((s16)word < 0) ? 0 : clamp_val(word, 0, 0x0fff); | 389 | word = ((s16)word < 0) ? 0 : clamp_val(word, 0, data->rlimit); |
325 | ret = pmbus_write_word_data(client, 0, | 390 | ret = pmbus_write_word_data(client, 0, |
326 | LM25066_MFR_IIN_OC_WARN_LIMIT, | 391 | LM25066_MFR_IIN_OC_WARN_LIMIT, |
327 | word); | 392 | word); |
328 | pmbus_clear_cache(client); | 393 | pmbus_clear_cache(client); |
329 | break; | 394 | break; |
330 | case PMBUS_PIN_OP_WARN_LIMIT: | 395 | case PMBUS_PIN_OP_WARN_LIMIT: |
331 | word = ((s16)word < 0) ? 0 : clamp_val(word, 0, 0x0fff); | 396 | word = ((s16)word < 0) ? 0 : clamp_val(word, 0, data->rlimit); |
332 | ret = pmbus_write_word_data(client, 0, | 397 | ret = pmbus_write_word_data(client, 0, |
333 | LM25066_MFR_PIN_OP_WARN_LIMIT, | 398 | LM25066_MFR_PIN_OP_WARN_LIMIT, |
334 | word); | 399 | word); |
@@ -337,7 +402,7 @@ static int lm25066_write_word_data(struct i2c_client *client, int page, int reg, | |||
337 | case PMBUS_VIRT_VMON_UV_WARN_LIMIT: | 402 | case PMBUS_VIRT_VMON_UV_WARN_LIMIT: |
338 | /* Adjust from VIN coefficients (for LM25056) */ | 403 | /* Adjust from VIN coefficients (for LM25056) */ |
339 | word = DIV_ROUND_CLOSEST((int)word * 6140, 293); | 404 | word = DIV_ROUND_CLOSEST((int)word * 6140, 293); |
340 | word = ((s16)word < 0) ? 0 : clamp_val(word, 0, 0x0fff); | 405 | word = ((s16)word < 0) ? 0 : clamp_val(word, 0, data->rlimit); |
341 | ret = pmbus_write_word_data(client, 0, | 406 | ret = pmbus_write_word_data(client, 0, |
342 | LM25056_VAUX_UV_WARN_LIMIT, word); | 407 | LM25056_VAUX_UV_WARN_LIMIT, word); |
343 | pmbus_clear_cache(client); | 408 | pmbus_clear_cache(client); |
@@ -345,7 +410,7 @@ static int lm25066_write_word_data(struct i2c_client *client, int page, int reg, | |||
345 | case PMBUS_VIRT_VMON_OV_WARN_LIMIT: | 410 | case PMBUS_VIRT_VMON_OV_WARN_LIMIT: |
346 | /* Adjust from VIN coefficients (for LM25056) */ | 411 | /* Adjust from VIN coefficients (for LM25056) */ |
347 | word = DIV_ROUND_CLOSEST((int)word * 6140, 293); | 412 | word = DIV_ROUND_CLOSEST((int)word * 6140, 293); |
348 | word = ((s16)word < 0) ? 0 : clamp_val(word, 0, 0x0fff); | 413 | word = ((s16)word < 0) ? 0 : clamp_val(word, 0, data->rlimit); |
349 | ret = pmbus_write_word_data(client, 0, | 414 | ret = pmbus_write_word_data(client, 0, |
350 | LM25056_VAUX_OV_WARN_LIMIT, word); | 415 | LM25056_VAUX_OV_WARN_LIMIT, word); |
351 | pmbus_clear_cache(client); | 416 | pmbus_clear_cache(client); |
@@ -399,9 +464,16 @@ static int lm25066_probe(struct i2c_client *client, | |||
399 | info->func[0] |= PMBUS_HAVE_STATUS_VMON; | 464 | info->func[0] |= PMBUS_HAVE_STATUS_VMON; |
400 | info->read_word_data = lm25056_read_word_data; | 465 | info->read_word_data = lm25056_read_word_data; |
401 | info->read_byte_data = lm25056_read_byte_data; | 466 | info->read_byte_data = lm25056_read_byte_data; |
467 | data->rlimit = 0x0fff; | ||
468 | } else if (data->id == lm25063) { | ||
469 | info->func[0] |= PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT | ||
470 | | PMBUS_HAVE_POUT; | ||
471 | info->read_word_data = lm25063_read_word_data; | ||
472 | data->rlimit = 0xffff; | ||
402 | } else { | 473 | } else { |
403 | info->func[0] |= PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT; | 474 | info->func[0] |= PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT; |
404 | info->read_word_data = lm25066_read_word_data; | 475 | info->read_word_data = lm25066_read_word_data; |
476 | data->rlimit = 0x0fff; | ||
405 | } | 477 | } |
406 | info->write_word_data = lm25066_write_word_data; | 478 | info->write_word_data = lm25066_write_word_data; |
407 | 479 | ||
@@ -432,6 +504,7 @@ static int lm25066_probe(struct i2c_client *client, | |||
432 | 504 | ||
433 | static const struct i2c_device_id lm25066_id[] = { | 505 | static const struct i2c_device_id lm25066_id[] = { |
434 | {"lm25056", lm25056}, | 506 | {"lm25056", lm25056}, |
507 | {"lm25063", lm25063}, | ||
435 | {"lm25066", lm25066}, | 508 | {"lm25066", lm25066}, |
436 | {"lm5064", lm5064}, | 509 | {"lm5064", lm5064}, |
437 | {"lm5066", lm5066}, | 510 | {"lm5066", lm5066}, |
@@ -453,5 +526,5 @@ static struct i2c_driver lm25066_driver = { | |||
453 | module_i2c_driver(lm25066_driver); | 526 | module_i2c_driver(lm25066_driver); |
454 | 527 | ||
455 | MODULE_AUTHOR("Guenter Roeck"); | 528 | MODULE_AUTHOR("Guenter Roeck"); |
456 | MODULE_DESCRIPTION("PMBus driver for LM25056/LM25066/LM5064/LM5066"); | 529 | MODULE_DESCRIPTION("PMBus driver for LM25066 and compatible chips"); |
457 | MODULE_LICENSE("GPL"); | 530 | MODULE_LICENSE("GPL"); |