diff options
Diffstat (limited to 'drivers/hwmon/pmbus/max34440.c')
-rw-r--r-- | drivers/hwmon/pmbus/max34440.c | 139 |
1 files changed, 119 insertions, 20 deletions
diff --git a/drivers/hwmon/pmbus/max34440.c b/drivers/hwmon/pmbus/max34440.c index 9b97a5b3cf3d..2ada7b021fbe 100644 --- a/drivers/hwmon/pmbus/max34440.c +++ b/drivers/hwmon/pmbus/max34440.c | |||
@@ -25,34 +25,82 @@ | |||
25 | #include <linux/i2c.h> | 25 | #include <linux/i2c.h> |
26 | #include "pmbus.h" | 26 | #include "pmbus.h" |
27 | 27 | ||
28 | enum chips { max34440, max34441 }; | 28 | enum chips { max34440, max34441, max34446 }; |
29 | 29 | ||
30 | #define MAX34440_MFR_VOUT_PEAK 0xd4 | 30 | #define MAX34440_MFR_VOUT_PEAK 0xd4 |
31 | #define MAX34440_MFR_IOUT_PEAK 0xd5 | 31 | #define MAX34440_MFR_IOUT_PEAK 0xd5 |
32 | #define MAX34440_MFR_TEMPERATURE_PEAK 0xd6 | 32 | #define MAX34440_MFR_TEMPERATURE_PEAK 0xd6 |
33 | #define MAX34440_MFR_VOUT_MIN 0xd7 | ||
34 | |||
35 | #define MAX34446_MFR_POUT_PEAK 0xe0 | ||
36 | #define MAX34446_MFR_POUT_AVG 0xe1 | ||
37 | #define MAX34446_MFR_IOUT_AVG 0xe2 | ||
38 | #define MAX34446_MFR_TEMPERATURE_AVG 0xe3 | ||
33 | 39 | ||
34 | #define MAX34440_STATUS_OC_WARN (1 << 0) | 40 | #define MAX34440_STATUS_OC_WARN (1 << 0) |
35 | #define MAX34440_STATUS_OC_FAULT (1 << 1) | 41 | #define MAX34440_STATUS_OC_FAULT (1 << 1) |
36 | #define MAX34440_STATUS_OT_FAULT (1 << 5) | 42 | #define MAX34440_STATUS_OT_FAULT (1 << 5) |
37 | #define MAX34440_STATUS_OT_WARN (1 << 6) | 43 | #define MAX34440_STATUS_OT_WARN (1 << 6) |
38 | 44 | ||
45 | struct max34440_data { | ||
46 | int id; | ||
47 | struct pmbus_driver_info info; | ||
48 | }; | ||
49 | |||
50 | #define to_max34440_data(x) container_of(x, struct max34440_data, info) | ||
51 | |||
39 | static int max34440_read_word_data(struct i2c_client *client, int page, int reg) | 52 | static int max34440_read_word_data(struct i2c_client *client, int page, int reg) |
40 | { | 53 | { |
41 | int ret; | 54 | int ret; |
55 | const struct pmbus_driver_info *info = pmbus_get_driver_info(client); | ||
56 | const struct max34440_data *data = to_max34440_data(info); | ||
42 | 57 | ||
43 | switch (reg) { | 58 | switch (reg) { |
59 | case PMBUS_VIRT_READ_VOUT_MIN: | ||
60 | ret = pmbus_read_word_data(client, page, | ||
61 | MAX34440_MFR_VOUT_MIN); | ||
62 | break; | ||
44 | case PMBUS_VIRT_READ_VOUT_MAX: | 63 | case PMBUS_VIRT_READ_VOUT_MAX: |
45 | ret = pmbus_read_word_data(client, page, | 64 | ret = pmbus_read_word_data(client, page, |
46 | MAX34440_MFR_VOUT_PEAK); | 65 | MAX34440_MFR_VOUT_PEAK); |
47 | break; | 66 | break; |
67 | case PMBUS_VIRT_READ_IOUT_AVG: | ||
68 | if (data->id != max34446) | ||
69 | return -ENXIO; | ||
70 | ret = pmbus_read_word_data(client, page, | ||
71 | MAX34446_MFR_IOUT_AVG); | ||
72 | break; | ||
48 | case PMBUS_VIRT_READ_IOUT_MAX: | 73 | case PMBUS_VIRT_READ_IOUT_MAX: |
49 | ret = pmbus_read_word_data(client, page, | 74 | ret = pmbus_read_word_data(client, page, |
50 | MAX34440_MFR_IOUT_PEAK); | 75 | MAX34440_MFR_IOUT_PEAK); |
51 | break; | 76 | break; |
77 | case PMBUS_VIRT_READ_POUT_AVG: | ||
78 | if (data->id != max34446) | ||
79 | return -ENXIO; | ||
80 | ret = pmbus_read_word_data(client, page, | ||
81 | MAX34446_MFR_POUT_AVG); | ||
82 | break; | ||
83 | case PMBUS_VIRT_READ_POUT_MAX: | ||
84 | if (data->id != max34446) | ||
85 | return -ENXIO; | ||
86 | ret = pmbus_read_word_data(client, page, | ||
87 | MAX34446_MFR_POUT_PEAK); | ||
88 | break; | ||
89 | case PMBUS_VIRT_READ_TEMP_AVG: | ||
90 | if (data->id != max34446) | ||
91 | return -ENXIO; | ||
92 | ret = pmbus_read_word_data(client, page, | ||
93 | MAX34446_MFR_TEMPERATURE_AVG); | ||
94 | break; | ||
52 | case PMBUS_VIRT_READ_TEMP_MAX: | 95 | case PMBUS_VIRT_READ_TEMP_MAX: |
53 | ret = pmbus_read_word_data(client, page, | 96 | ret = pmbus_read_word_data(client, page, |
54 | MAX34440_MFR_TEMPERATURE_PEAK); | 97 | MAX34440_MFR_TEMPERATURE_PEAK); |
55 | break; | 98 | break; |
99 | case PMBUS_VIRT_RESET_POUT_HISTORY: | ||
100 | if (data->id != max34446) | ||
101 | return -ENXIO; | ||
102 | ret = 0; | ||
103 | break; | ||
56 | case PMBUS_VIRT_RESET_VOUT_HISTORY: | 104 | case PMBUS_VIRT_RESET_VOUT_HISTORY: |
57 | case PMBUS_VIRT_RESET_IOUT_HISTORY: | 105 | case PMBUS_VIRT_RESET_IOUT_HISTORY: |
58 | case PMBUS_VIRT_RESET_TEMP_HISTORY: | 106 | case PMBUS_VIRT_RESET_TEMP_HISTORY: |
@@ -68,21 +116,42 @@ static int max34440_read_word_data(struct i2c_client *client, int page, int reg) | |||
68 | static int max34440_write_word_data(struct i2c_client *client, int page, | 116 | static int max34440_write_word_data(struct i2c_client *client, int page, |
69 | int reg, u16 word) | 117 | int reg, u16 word) |
70 | { | 118 | { |
119 | const struct pmbus_driver_info *info = pmbus_get_driver_info(client); | ||
120 | const struct max34440_data *data = to_max34440_data(info); | ||
71 | int ret; | 121 | int ret; |
72 | 122 | ||
73 | switch (reg) { | 123 | switch (reg) { |
124 | case PMBUS_VIRT_RESET_POUT_HISTORY: | ||
125 | ret = pmbus_write_word_data(client, page, | ||
126 | MAX34446_MFR_POUT_PEAK, 0); | ||
127 | if (ret) | ||
128 | break; | ||
129 | ret = pmbus_write_word_data(client, page, | ||
130 | MAX34446_MFR_POUT_AVG, 0); | ||
131 | break; | ||
74 | case PMBUS_VIRT_RESET_VOUT_HISTORY: | 132 | case PMBUS_VIRT_RESET_VOUT_HISTORY: |
75 | ret = pmbus_write_word_data(client, page, | 133 | ret = pmbus_write_word_data(client, page, |
134 | MAX34440_MFR_VOUT_MIN, 0x7fff); | ||
135 | if (ret) | ||
136 | break; | ||
137 | ret = pmbus_write_word_data(client, page, | ||
76 | MAX34440_MFR_VOUT_PEAK, 0); | 138 | MAX34440_MFR_VOUT_PEAK, 0); |
77 | break; | 139 | break; |
78 | case PMBUS_VIRT_RESET_IOUT_HISTORY: | 140 | case PMBUS_VIRT_RESET_IOUT_HISTORY: |
79 | ret = pmbus_write_word_data(client, page, | 141 | ret = pmbus_write_word_data(client, page, |
80 | MAX34440_MFR_IOUT_PEAK, 0); | 142 | MAX34440_MFR_IOUT_PEAK, 0); |
143 | if (!ret && data->id == max34446) | ||
144 | ret = pmbus_write_word_data(client, page, | ||
145 | MAX34446_MFR_IOUT_AVG, 0); | ||
146 | |||
81 | break; | 147 | break; |
82 | case PMBUS_VIRT_RESET_TEMP_HISTORY: | 148 | case PMBUS_VIRT_RESET_TEMP_HISTORY: |
83 | ret = pmbus_write_word_data(client, page, | 149 | ret = pmbus_write_word_data(client, page, |
84 | MAX34440_MFR_TEMPERATURE_PEAK, | 150 | MAX34440_MFR_TEMPERATURE_PEAK, |
85 | 0x8000); | 151 | 0x8000); |
152 | if (!ret && data->id == max34446) | ||
153 | ret = pmbus_write_word_data(client, page, | ||
154 | MAX34446_MFR_TEMPERATURE_AVG, 0); | ||
86 | break; | 155 | break; |
87 | default: | 156 | default: |
88 | ret = -ENODATA; | 157 | ret = -ENODATA; |
@@ -216,26 +285,66 @@ static struct pmbus_driver_info max34440_info[] = { | |||
216 | .read_word_data = max34440_read_word_data, | 285 | .read_word_data = max34440_read_word_data, |
217 | .write_word_data = max34440_write_word_data, | 286 | .write_word_data = max34440_write_word_data, |
218 | }, | 287 | }, |
288 | [max34446] = { | ||
289 | .pages = 7, | ||
290 | .format[PSC_VOLTAGE_IN] = direct, | ||
291 | .format[PSC_VOLTAGE_OUT] = direct, | ||
292 | .format[PSC_TEMPERATURE] = direct, | ||
293 | .format[PSC_CURRENT_OUT] = direct, | ||
294 | .format[PSC_POWER] = direct, | ||
295 | .m[PSC_VOLTAGE_IN] = 1, | ||
296 | .b[PSC_VOLTAGE_IN] = 0, | ||
297 | .R[PSC_VOLTAGE_IN] = 3, | ||
298 | .m[PSC_VOLTAGE_OUT] = 1, | ||
299 | .b[PSC_VOLTAGE_OUT] = 0, | ||
300 | .R[PSC_VOLTAGE_OUT] = 3, | ||
301 | .m[PSC_CURRENT_OUT] = 1, | ||
302 | .b[PSC_CURRENT_OUT] = 0, | ||
303 | .R[PSC_CURRENT_OUT] = 3, | ||
304 | .m[PSC_POWER] = 1, | ||
305 | .b[PSC_POWER] = 0, | ||
306 | .R[PSC_POWER] = 3, | ||
307 | .m[PSC_TEMPERATURE] = 1, | ||
308 | .b[PSC_TEMPERATURE] = 0, | ||
309 | .R[PSC_TEMPERATURE] = 2, | ||
310 | .func[0] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT | ||
311 | | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT | PMBUS_HAVE_POUT, | ||
312 | .func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT | ||
313 | | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, | ||
314 | .func[2] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT | ||
315 | | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT | PMBUS_HAVE_POUT, | ||
316 | .func[3] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT | ||
317 | | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, | ||
318 | .func[4] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, | ||
319 | .func[5] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, | ||
320 | .func[6] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, | ||
321 | .read_byte_data = max34440_read_byte_data, | ||
322 | .read_word_data = max34440_read_word_data, | ||
323 | .write_word_data = max34440_write_word_data, | ||
324 | }, | ||
219 | }; | 325 | }; |
220 | 326 | ||
221 | static int max34440_probe(struct i2c_client *client, | 327 | static int max34440_probe(struct i2c_client *client, |
222 | const struct i2c_device_id *id) | 328 | const struct i2c_device_id *id) |
223 | { | 329 | { |
224 | return pmbus_do_probe(client, id, &max34440_info[id->driver_data]); | 330 | struct max34440_data *data; |
225 | } | ||
226 | 331 | ||
227 | static int max34440_remove(struct i2c_client *client) | 332 | data = devm_kzalloc(&client->dev, sizeof(struct max34440_data), |
228 | { | 333 | GFP_KERNEL); |
229 | pmbus_do_remove(client); | 334 | if (!data) |
230 | return 0; | 335 | return -ENOMEM; |
336 | data->id = id->driver_data; | ||
337 | data->info = max34440_info[id->driver_data]; | ||
338 | |||
339 | return pmbus_do_probe(client, id, &data->info); | ||
231 | } | 340 | } |
232 | 341 | ||
233 | static const struct i2c_device_id max34440_id[] = { | 342 | static const struct i2c_device_id max34440_id[] = { |
234 | {"max34440", max34440}, | 343 | {"max34440", max34440}, |
235 | {"max34441", max34441}, | 344 | {"max34441", max34441}, |
345 | {"max34446", max34446}, | ||
236 | {} | 346 | {} |
237 | }; | 347 | }; |
238 | |||
239 | MODULE_DEVICE_TABLE(i2c, max34440_id); | 348 | MODULE_DEVICE_TABLE(i2c, max34440_id); |
240 | 349 | ||
241 | /* This is the driver that will be inserted */ | 350 | /* This is the driver that will be inserted */ |
@@ -244,22 +353,12 @@ static struct i2c_driver max34440_driver = { | |||
244 | .name = "max34440", | 353 | .name = "max34440", |
245 | }, | 354 | }, |
246 | .probe = max34440_probe, | 355 | .probe = max34440_probe, |
247 | .remove = max34440_remove, | 356 | .remove = pmbus_do_remove, |
248 | .id_table = max34440_id, | 357 | .id_table = max34440_id, |
249 | }; | 358 | }; |
250 | 359 | ||
251 | static int __init max34440_init(void) | 360 | module_i2c_driver(max34440_driver); |
252 | { | ||
253 | return i2c_add_driver(&max34440_driver); | ||
254 | } | ||
255 | |||
256 | static void __exit max34440_exit(void) | ||
257 | { | ||
258 | i2c_del_driver(&max34440_driver); | ||
259 | } | ||
260 | 361 | ||
261 | MODULE_AUTHOR("Guenter Roeck"); | 362 | MODULE_AUTHOR("Guenter Roeck"); |
262 | MODULE_DESCRIPTION("PMBus driver for Maxim MAX34440/MAX34441"); | 363 | MODULE_DESCRIPTION("PMBus driver for Maxim MAX34440/MAX34441"); |
263 | MODULE_LICENSE("GPL"); | 364 | MODULE_LICENSE("GPL"); |
264 | module_init(max34440_init); | ||
265 | module_exit(max34440_exit); | ||