aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon/pmbus
diff options
context:
space:
mode:
authorGuenter Roeck <linux@roeck-us.net>2013-03-16 13:25:04 -0400
committerGuenter Roeck <linux@roeck-us.net>2013-10-18 12:12:02 -0400
commitc8ccab7ab5c71b4fab274bfd18425503a4dcc288 (patch)
tree2855cfb80fa9c3afe7baedb5f2e827f09d139f56 /drivers/hwmon/pmbus
parent84fb029faa05e1de229a68829cca5dcf85c79894 (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.c91
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
30enum chips { lm25056, lm25066, lm5064, lm5066 }; 30enum 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
55struct __coeff { 60struct __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
62static struct __coeff lm25066_coeff[4][PSC_NUM_CLASSES + 2] = { 67static 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
179struct lm25066_data { 214struct 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
296static 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
256static int lm25056_read_word_data(struct i2c_client *client, int page, int reg) 314static 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)
308static int lm25066_write_word_data(struct i2c_client *client, int page, int reg, 366static 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
433static const struct i2c_device_id lm25066_id[] = { 505static 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 = {
453module_i2c_driver(lm25066_driver); 526module_i2c_driver(lm25066_driver);
454 527
455MODULE_AUTHOR("Guenter Roeck"); 528MODULE_AUTHOR("Guenter Roeck");
456MODULE_DESCRIPTION("PMBus driver for LM25056/LM25066/LM5064/LM5066"); 529MODULE_DESCRIPTION("PMBus driver for LM25066 and compatible chips");
457MODULE_LICENSE("GPL"); 530MODULE_LICENSE("GPL");