aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon/pmbus/max34440.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hwmon/pmbus/max34440.c')
-rw-r--r--drivers/hwmon/pmbus/max34440.c139
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
28enum chips { max34440, max34441 }; 28enum 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
45struct 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
39static int max34440_read_word_data(struct i2c_client *client, int page, int reg) 52static 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)
68static int max34440_write_word_data(struct i2c_client *client, int page, 116static 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
221static int max34440_probe(struct i2c_client *client, 327static 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
227static 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
233static const struct i2c_device_id max34440_id[] = { 342static 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
239MODULE_DEVICE_TABLE(i2c, max34440_id); 348MODULE_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
251static int __init max34440_init(void) 360module_i2c_driver(max34440_driver);
252{
253 return i2c_add_driver(&max34440_driver);
254}
255
256static void __exit max34440_exit(void)
257{
258 i2c_del_driver(&max34440_driver);
259}
260 361
261MODULE_AUTHOR("Guenter Roeck"); 362MODULE_AUTHOR("Guenter Roeck");
262MODULE_DESCRIPTION("PMBus driver for Maxim MAX34440/MAX34441"); 363MODULE_DESCRIPTION("PMBus driver for Maxim MAX34440/MAX34441");
263MODULE_LICENSE("GPL"); 364MODULE_LICENSE("GPL");
264module_init(max34440_init);
265module_exit(max34440_exit);