diff options
Diffstat (limited to 'drivers/hwmon/pmbus/adm1275.c')
-rw-r--r-- | drivers/hwmon/pmbus/adm1275.c | 141 |
1 files changed, 133 insertions, 8 deletions
diff --git a/drivers/hwmon/pmbus/adm1275.c b/drivers/hwmon/pmbus/adm1275.c index 1c19a2ee415c..188af4c89f40 100644 --- a/drivers/hwmon/pmbus/adm1275.c +++ b/drivers/hwmon/pmbus/adm1275.c | |||
@@ -24,7 +24,11 @@ | |||
24 | #include <linux/bitops.h> | 24 | #include <linux/bitops.h> |
25 | #include "pmbus.h" | 25 | #include "pmbus.h" |
26 | 26 | ||
27 | enum chips { adm1075, adm1275, adm1276 }; | 27 | enum chips { adm1075, adm1275, adm1276, adm1293, adm1294 }; |
28 | |||
29 | #define ADM1275_MFR_STATUS_IOUT_WARN2 BIT(0) | ||
30 | #define ADM1293_MFR_STATUS_VAUX_UV_WARN BIT(5) | ||
31 | #define ADM1293_MFR_STATUS_VAUX_OV_WARN BIT(6) | ||
28 | 32 | ||
29 | #define ADM1275_PEAK_IOUT 0xd0 | 33 | #define ADM1275_PEAK_IOUT 0xd0 |
30 | #define ADM1275_PEAK_VIN 0xd1 | 34 | #define ADM1275_PEAK_VIN 0xd1 |
@@ -37,18 +41,30 @@ enum chips { adm1075, adm1275, adm1276 }; | |||
37 | #define ADM1075_IRANGE_25 BIT(3) | 41 | #define ADM1075_IRANGE_25 BIT(3) |
38 | #define ADM1075_IRANGE_MASK (BIT(3) | BIT(4)) | 42 | #define ADM1075_IRANGE_MASK (BIT(3) | BIT(4)) |
39 | 43 | ||
44 | #define ADM1293_IRANGE_25 0 | ||
45 | #define ADM1293_IRANGE_50 BIT(6) | ||
46 | #define ADM1293_IRANGE_100 BIT(7) | ||
47 | #define ADM1293_IRANGE_200 (BIT(6) | BIT(7)) | ||
48 | #define ADM1293_IRANGE_MASK (BIT(6) | BIT(7)) | ||
49 | |||
50 | #define ADM1293_VIN_SEL_012 BIT(2) | ||
51 | #define ADM1293_VIN_SEL_074 BIT(3) | ||
52 | #define ADM1293_VIN_SEL_210 (BIT(2) | BIT(3)) | ||
53 | #define ADM1293_VIN_SEL_MASK (BIT(2) | BIT(3)) | ||
54 | |||
55 | #define ADM1293_VAUX_EN BIT(1) | ||
56 | |||
40 | #define ADM1275_IOUT_WARN2_LIMIT 0xd7 | 57 | #define ADM1275_IOUT_WARN2_LIMIT 0xd7 |
41 | #define ADM1275_DEVICE_CONFIG 0xd8 | 58 | #define ADM1275_DEVICE_CONFIG 0xd8 |
42 | 59 | ||
43 | #define ADM1275_IOUT_WARN2_SELECT BIT(4) | 60 | #define ADM1275_IOUT_WARN2_SELECT BIT(4) |
44 | 61 | ||
45 | #define ADM1276_PEAK_PIN 0xda | 62 | #define ADM1276_PEAK_PIN 0xda |
46 | |||
47 | #define ADM1275_MFR_STATUS_IOUT_WARN2 BIT(0) | ||
48 | |||
49 | #define ADM1075_READ_VAUX 0xdd | 63 | #define ADM1075_READ_VAUX 0xdd |
50 | #define ADM1075_VAUX_OV_WARN_LIMIT 0xde | 64 | #define ADM1075_VAUX_OV_WARN_LIMIT 0xde |
51 | #define ADM1075_VAUX_UV_WARN_LIMIT 0xdf | 65 | #define ADM1075_VAUX_UV_WARN_LIMIT 0xdf |
66 | #define ADM1293_IOUT_MIN 0xe3 | ||
67 | #define ADM1293_PIN_MIN 0xe4 | ||
52 | #define ADM1075_VAUX_STATUS 0xf6 | 68 | #define ADM1075_VAUX_STATUS 0xf6 |
53 | 69 | ||
54 | #define ADM1075_VAUX_OV_WARN BIT(7) | 70 | #define ADM1075_VAUX_OV_WARN BIT(7) |
@@ -60,6 +76,9 @@ struct adm1275_data { | |||
60 | bool have_uc_fault; | 76 | bool have_uc_fault; |
61 | bool have_vout; | 77 | bool have_vout; |
62 | bool have_vaux_status; | 78 | bool have_vaux_status; |
79 | bool have_mfr_vaux_status; | ||
80 | bool have_iout_min; | ||
81 | bool have_pin_min; | ||
63 | bool have_pin_max; | 82 | bool have_pin_max; |
64 | struct pmbus_driver_info info; | 83 | struct pmbus_driver_info info; |
65 | }; | 84 | }; |
@@ -94,6 +113,28 @@ static const struct coefficients adm1276_coefficients[] = { | |||
94 | [4] = { 2115, 0, -1 }, /* power, vrange not set */ | 113 | [4] = { 2115, 0, -1 }, /* power, vrange not set */ |
95 | }; | 114 | }; |
96 | 115 | ||
116 | static const struct coefficients adm1293_coefficients[] = { | ||
117 | [0] = { 3333, -1, 0 }, /* voltage, vrange 1.2V */ | ||
118 | [1] = { 5552, -5, -1 }, /* voltage, vrange 7.4V */ | ||
119 | [2] = { 19604, -50, -2 }, /* voltage, vrange 21V */ | ||
120 | [3] = { 8000, -100, -2 }, /* current, irange25 */ | ||
121 | [4] = { 4000, -100, -2 }, /* current, irange50 */ | ||
122 | [5] = { 20000, -1000, -3 }, /* current, irange100 */ | ||
123 | [6] = { 10000, -1000, -3 }, /* current, irange200 */ | ||
124 | [7] = { 10417, 0, -1 }, /* power, 1.2V, irange25 */ | ||
125 | [8] = { 5208, 0, -1 }, /* power, 1.2V, irange50 */ | ||
126 | [9] = { 26042, 0, -2 }, /* power, 1.2V, irange100 */ | ||
127 | [10] = { 13021, 0, -2 }, /* power, 1.2V, irange200 */ | ||
128 | [11] = { 17351, 0, -2 }, /* power, 7.4V, irange25 */ | ||
129 | [12] = { 8676, 0, -2 }, /* power, 7.4V, irange50 */ | ||
130 | [13] = { 4338, 0, -2 }, /* power, 7.4V, irange100 */ | ||
131 | [14] = { 21689, 0, -3 }, /* power, 7.4V, irange200 */ | ||
132 | [15] = { 6126, 0, -2 }, /* power, 21V, irange25 */ | ||
133 | [16] = { 30631, 0, -3 }, /* power, 21V, irange50 */ | ||
134 | [17] = { 15316, 0, -3 }, /* power, 21V, irange100 */ | ||
135 | [18] = { 7658, 0, -3 }, /* power, 21V, irange200 */ | ||
136 | }; | ||
137 | |||
97 | static int adm1275_read_word_data(struct i2c_client *client, int page, int reg) | 138 | static int adm1275_read_word_data(struct i2c_client *client, int page, int reg) |
98 | { | 139 | { |
99 | const struct pmbus_driver_info *info = pmbus_get_driver_info(client); | 140 | const struct pmbus_driver_info *info = pmbus_get_driver_info(client); |
@@ -131,6 +172,11 @@ static int adm1275_read_word_data(struct i2c_client *client, int page, int reg) | |||
131 | return -ENODATA; | 172 | return -ENODATA; |
132 | ret = pmbus_read_word_data(client, 0, ADM1075_READ_VAUX); | 173 | ret = pmbus_read_word_data(client, 0, ADM1075_READ_VAUX); |
133 | break; | 174 | break; |
175 | case PMBUS_VIRT_READ_IOUT_MIN: | ||
176 | if (!data->have_iout_min) | ||
177 | return -ENXIO; | ||
178 | ret = pmbus_read_word_data(client, 0, ADM1293_IOUT_MIN); | ||
179 | break; | ||
134 | case PMBUS_VIRT_READ_IOUT_MAX: | 180 | case PMBUS_VIRT_READ_IOUT_MAX: |
135 | ret = pmbus_read_word_data(client, 0, ADM1275_PEAK_IOUT); | 181 | ret = pmbus_read_word_data(client, 0, ADM1275_PEAK_IOUT); |
136 | break; | 182 | break; |
@@ -140,6 +186,11 @@ static int adm1275_read_word_data(struct i2c_client *client, int page, int reg) | |||
140 | case PMBUS_VIRT_READ_VIN_MAX: | 186 | case PMBUS_VIRT_READ_VIN_MAX: |
141 | ret = pmbus_read_word_data(client, 0, ADM1275_PEAK_VIN); | 187 | ret = pmbus_read_word_data(client, 0, ADM1275_PEAK_VIN); |
142 | break; | 188 | break; |
189 | case PMBUS_VIRT_READ_PIN_MIN: | ||
190 | if (!data->have_pin_min) | ||
191 | return -ENXIO; | ||
192 | ret = pmbus_read_word_data(client, 0, ADM1293_PIN_MIN); | ||
193 | break; | ||
143 | case PMBUS_VIRT_READ_PIN_MAX: | 194 | case PMBUS_VIRT_READ_PIN_MAX: |
144 | if (!data->have_pin_max) | 195 | if (!data->have_pin_max) |
145 | return -ENXIO; | 196 | return -ENXIO; |
@@ -163,6 +214,8 @@ static int adm1275_read_word_data(struct i2c_client *client, int page, int reg) | |||
163 | static int adm1275_write_word_data(struct i2c_client *client, int page, int reg, | 214 | static int adm1275_write_word_data(struct i2c_client *client, int page, int reg, |
164 | u16 word) | 215 | u16 word) |
165 | { | 216 | { |
217 | const struct pmbus_driver_info *info = pmbus_get_driver_info(client); | ||
218 | const struct adm1275_data *data = to_adm1275_data(info); | ||
166 | int ret; | 219 | int ret; |
167 | 220 | ||
168 | if (page) | 221 | if (page) |
@@ -176,6 +229,9 @@ static int adm1275_write_word_data(struct i2c_client *client, int page, int reg, | |||
176 | break; | 229 | break; |
177 | case PMBUS_VIRT_RESET_IOUT_HISTORY: | 230 | case PMBUS_VIRT_RESET_IOUT_HISTORY: |
178 | ret = pmbus_write_word_data(client, 0, ADM1275_PEAK_IOUT, 0); | 231 | ret = pmbus_write_word_data(client, 0, ADM1275_PEAK_IOUT, 0); |
232 | if (!ret && data->have_iout_min) | ||
233 | ret = pmbus_write_word_data(client, 0, | ||
234 | ADM1293_IOUT_MIN, 0); | ||
179 | break; | 235 | break; |
180 | case PMBUS_VIRT_RESET_VOUT_HISTORY: | 236 | case PMBUS_VIRT_RESET_VOUT_HISTORY: |
181 | ret = pmbus_write_word_data(client, 0, ADM1275_PEAK_VOUT, 0); | 237 | ret = pmbus_write_word_data(client, 0, ADM1275_PEAK_VOUT, 0); |
@@ -185,6 +241,9 @@ static int adm1275_write_word_data(struct i2c_client *client, int page, int reg, | |||
185 | break; | 241 | break; |
186 | case PMBUS_VIRT_RESET_PIN_HISTORY: | 242 | case PMBUS_VIRT_RESET_PIN_HISTORY: |
187 | ret = pmbus_write_word_data(client, 0, ADM1276_PEAK_PIN, 0); | 243 | ret = pmbus_write_word_data(client, 0, ADM1276_PEAK_PIN, 0); |
244 | if (!ret && data->have_pin_min) | ||
245 | ret = pmbus_write_word_data(client, 0, | ||
246 | ADM1293_PIN_MIN, 0); | ||
188 | break; | 247 | break; |
189 | default: | 248 | default: |
190 | ret = -ENODATA; | 249 | ret = -ENODATA; |
@@ -231,6 +290,15 @@ static int adm1275_read_byte_data(struct i2c_client *client, int page, int reg) | |||
231 | ret |= PB_VOLTAGE_OV_WARNING; | 290 | ret |= PB_VOLTAGE_OV_WARNING; |
232 | if (mfr_status & ADM1075_VAUX_UV_WARN) | 291 | if (mfr_status & ADM1075_VAUX_UV_WARN) |
233 | ret |= PB_VOLTAGE_UV_WARNING; | 292 | ret |= PB_VOLTAGE_UV_WARNING; |
293 | } else if (data->have_mfr_vaux_status) { | ||
294 | mfr_status = pmbus_read_byte_data(client, page, | ||
295 | PMBUS_STATUS_MFR_SPECIFIC); | ||
296 | if (mfr_status < 0) | ||
297 | return mfr_status; | ||
298 | if (mfr_status & ADM1293_MFR_STATUS_VAUX_OV_WARN) | ||
299 | ret |= PB_VOLTAGE_OV_WARNING; | ||
300 | if (mfr_status & ADM1293_MFR_STATUS_VAUX_UV_WARN) | ||
301 | ret |= PB_VOLTAGE_UV_WARNING; | ||
234 | } | 302 | } |
235 | break; | 303 | break; |
236 | default: | 304 | default: |
@@ -244,6 +312,8 @@ static const struct i2c_device_id adm1275_id[] = { | |||
244 | { "adm1075", adm1075 }, | 312 | { "adm1075", adm1075 }, |
245 | { "adm1275", adm1275 }, | 313 | { "adm1275", adm1275 }, |
246 | { "adm1276", adm1276 }, | 314 | { "adm1276", adm1276 }, |
315 | { "adm1293", adm1293 }, | ||
316 | { "adm1294", adm1294 }, | ||
247 | { } | 317 | { } |
248 | }; | 318 | }; |
249 | MODULE_DEVICE_TABLE(i2c, adm1275_id); | 319 | MODULE_DEVICE_TABLE(i2c, adm1275_id); |
@@ -258,7 +328,7 @@ static int adm1275_probe(struct i2c_client *client, | |||
258 | struct adm1275_data *data; | 328 | struct adm1275_data *data; |
259 | const struct i2c_device_id *mid; | 329 | const struct i2c_device_id *mid; |
260 | const struct coefficients *coefficients; | 330 | const struct coefficients *coefficients; |
261 | int vindex = -1, cindex = -1, pindex = -1; | 331 | int vindex = -1, voindex = -1, cindex = -1, pindex = -1; |
262 | 332 | ||
263 | if (!i2c_check_functionality(client->adapter, | 333 | if (!i2c_check_functionality(client->adapter, |
264 | I2C_FUNC_SMBUS_READ_BYTE_DATA | 334 | I2C_FUNC_SMBUS_READ_BYTE_DATA |
@@ -390,17 +460,72 @@ static int adm1275_probe(struct i2c_client *client, | |||
390 | info->func[0] |= | 460 | info->func[0] |= |
391 | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT; | 461 | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT; |
392 | break; | 462 | break; |
463 | case adm1293: | ||
464 | case adm1294: | ||
465 | data->have_iout_min = true; | ||
466 | data->have_pin_min = true; | ||
467 | data->have_pin_max = true; | ||
468 | data->have_mfr_vaux_status = true; | ||
469 | |||
470 | coefficients = adm1293_coefficients; | ||
471 | |||
472 | voindex = 0; | ||
473 | switch (config & ADM1293_VIN_SEL_MASK) { | ||
474 | case ADM1293_VIN_SEL_012: /* 1.2V */ | ||
475 | vindex = 0; | ||
476 | break; | ||
477 | case ADM1293_VIN_SEL_074: /* 7.4V */ | ||
478 | vindex = 1; | ||
479 | break; | ||
480 | case ADM1293_VIN_SEL_210: /* 21V */ | ||
481 | vindex = 2; | ||
482 | break; | ||
483 | default: /* disabled */ | ||
484 | break; | ||
485 | } | ||
486 | |||
487 | switch (config & ADM1293_IRANGE_MASK) { | ||
488 | case ADM1293_IRANGE_25: | ||
489 | cindex = 3; | ||
490 | break; | ||
491 | case ADM1293_IRANGE_50: | ||
492 | cindex = 4; | ||
493 | break; | ||
494 | case ADM1293_IRANGE_100: | ||
495 | cindex = 5; | ||
496 | break; | ||
497 | case ADM1293_IRANGE_200: | ||
498 | cindex = 6; | ||
499 | break; | ||
500 | } | ||
501 | |||
502 | if (vindex >= 0) | ||
503 | pindex = 7 + vindex * 4 + (cindex - 3); | ||
504 | |||
505 | if (config & ADM1293_VAUX_EN) | ||
506 | info->func[0] |= | ||
507 | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT; | ||
508 | |||
509 | info->func[0] |= PMBUS_HAVE_PIN | | ||
510 | PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT; | ||
511 | |||
512 | break; | ||
393 | default: | 513 | default: |
394 | dev_err(&client->dev, "Unsupported device\n"); | 514 | dev_err(&client->dev, "Unsupported device\n"); |
395 | return -ENODEV; | 515 | return -ENODEV; |
396 | } | 516 | } |
517 | |||
518 | if (voindex < 0) | ||
519 | voindex = vindex; | ||
397 | if (vindex >= 0) { | 520 | if (vindex >= 0) { |
398 | info->m[PSC_VOLTAGE_IN] = coefficients[vindex].m; | 521 | info->m[PSC_VOLTAGE_IN] = coefficients[vindex].m; |
399 | info->b[PSC_VOLTAGE_IN] = coefficients[vindex].b; | 522 | info->b[PSC_VOLTAGE_IN] = coefficients[vindex].b; |
400 | info->R[PSC_VOLTAGE_IN] = coefficients[vindex].R; | 523 | info->R[PSC_VOLTAGE_IN] = coefficients[vindex].R; |
401 | info->m[PSC_VOLTAGE_OUT] = coefficients[vindex].m; | 524 | } |
402 | info->b[PSC_VOLTAGE_OUT] = coefficients[vindex].b; | 525 | if (voindex >= 0) { |
403 | info->R[PSC_VOLTAGE_OUT] = coefficients[vindex].R; | 526 | info->m[PSC_VOLTAGE_OUT] = coefficients[voindex].m; |
527 | info->b[PSC_VOLTAGE_OUT] = coefficients[voindex].b; | ||
528 | info->R[PSC_VOLTAGE_OUT] = coefficients[voindex].R; | ||
404 | } | 529 | } |
405 | if (cindex >= 0) { | 530 | if (cindex >= 0) { |
406 | info->m[PSC_CURRENT_OUT] = coefficients[cindex].m; | 531 | info->m[PSC_CURRENT_OUT] = coefficients[cindex].m; |