1/*
2 * Hardware monitoring driver for Maxim MAX34440/MAX34441
3 *
4 * Copyright (c) 2011 Ericsson AB.
5 * Copyright (c) 2012 Guenter Roeck
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22#include <linux/kernel.h>
23#include <linux/module.h>
24#include <linux/init.h>
25#include <linux/err.h>
26#include <linux/i2c.h>
27#include "pmbus.h"
28
29enum chips { max34440, max34441, max34446, max34460, max34461 };
30
31#define MAX34440_MFR_VOUT_PEAK		0xd4
32#define MAX34440_MFR_IOUT_PEAK		0xd5
33#define MAX34440_MFR_TEMPERATURE_PEAK	0xd6
34#define MAX34440_MFR_VOUT_MIN		0xd7
35
36#define MAX34446_MFR_POUT_PEAK		0xe0
37#define MAX34446_MFR_POUT_AVG		0xe1
38#define MAX34446_MFR_IOUT_AVG		0xe2
39#define MAX34446_MFR_TEMPERATURE_AVG	0xe3
40
41#define MAX34440_STATUS_OC_WARN		(1 << 0)
42#define MAX34440_STATUS_OC_FAULT	(1 << 1)
43#define MAX34440_STATUS_OT_FAULT	(1 << 5)
44#define MAX34440_STATUS_OT_WARN		(1 << 6)
45
46struct max34440_data {
47	int id;
48	struct pmbus_driver_info info;
49};
50
51#define to_max34440_data(x)  container_of(x, struct max34440_data, info)
52
53static int max34440_read_word_data(struct i2c_client *client, int page, int reg)
54{
55	int ret;
56	const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
57	const struct max34440_data *data = to_max34440_data(info);
58
59	switch (reg) {
60	case PMBUS_VIRT_READ_VOUT_MIN:
61		ret = pmbus_read_word_data(client, page,
62					   MAX34440_MFR_VOUT_MIN);
63		break;
64	case PMBUS_VIRT_READ_VOUT_MAX:
65		ret = pmbus_read_word_data(client, page,
66					   MAX34440_MFR_VOUT_PEAK);
67		break;
68	case PMBUS_VIRT_READ_IOUT_AVG:
69		if (data->id != max34446)
70			return -ENXIO;
71		ret = pmbus_read_word_data(client, page,
72					   MAX34446_MFR_IOUT_AVG);
73		break;
74	case PMBUS_VIRT_READ_IOUT_MAX:
75		ret = pmbus_read_word_data(client, page,
76					   MAX34440_MFR_IOUT_PEAK);
77		break;
78	case PMBUS_VIRT_READ_POUT_AVG:
79		if (data->id != max34446)
80			return -ENXIO;
81		ret = pmbus_read_word_data(client, page,
82					   MAX34446_MFR_POUT_AVG);
83		break;
84	case PMBUS_VIRT_READ_POUT_MAX:
85		if (data->id != max34446)
86			return -ENXIO;
87		ret = pmbus_read_word_data(client, page,
88					   MAX34446_MFR_POUT_PEAK);
89		break;
90	case PMBUS_VIRT_READ_TEMP_AVG:
91		if (data->id != max34446 && data->id != max34460 &&
92		    data->id != max34461)
93			return -ENXIO;
94		ret = pmbus_read_word_data(client, page,
95					   MAX34446_MFR_TEMPERATURE_AVG);
96		break;
97	case PMBUS_VIRT_READ_TEMP_MAX:
98		ret = pmbus_read_word_data(client, page,
99					   MAX34440_MFR_TEMPERATURE_PEAK);
100		break;
101	case PMBUS_VIRT_RESET_POUT_HISTORY:
102		if (data->id != max34446)
103			return -ENXIO;
104		ret = 0;
105		break;
106	case PMBUS_VIRT_RESET_VOUT_HISTORY:
107	case PMBUS_VIRT_RESET_IOUT_HISTORY:
108	case PMBUS_VIRT_RESET_TEMP_HISTORY:
109		ret = 0;
110		break;
111	default:
112		ret = -ENODATA;
113		break;
114	}
115	return ret;
116}
117
118static int max34440_write_word_data(struct i2c_client *client, int page,
119				    int reg, u16 word)
120{
121	const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
122	const struct max34440_data *data = to_max34440_data(info);
123	int ret;
124
125	switch (reg) {
126	case PMBUS_VIRT_RESET_POUT_HISTORY:
127		ret = pmbus_write_word_data(client, page,
128					    MAX34446_MFR_POUT_PEAK, 0);
129		if (ret)
130			break;
131		ret = pmbus_write_word_data(client, page,
132					    MAX34446_MFR_POUT_AVG, 0);
133		break;
134	case PMBUS_VIRT_RESET_VOUT_HISTORY:
135		ret = pmbus_write_word_data(client, page,
136					    MAX34440_MFR_VOUT_MIN, 0x7fff);
137		if (ret)
138			break;
139		ret = pmbus_write_word_data(client, page,
140					    MAX34440_MFR_VOUT_PEAK, 0);
141		break;
142	case PMBUS_VIRT_RESET_IOUT_HISTORY:
143		ret = pmbus_write_word_data(client, page,
144					    MAX34440_MFR_IOUT_PEAK, 0);
145		if (!ret && data->id == max34446)
146			ret = pmbus_write_word_data(client, page,
147					MAX34446_MFR_IOUT_AVG, 0);
148
149		break;
150	case PMBUS_VIRT_RESET_TEMP_HISTORY:
151		ret = pmbus_write_word_data(client, page,
152					    MAX34440_MFR_TEMPERATURE_PEAK,
153					    0x8000);
154		if (!ret && data->id == max34446)
155			ret = pmbus_write_word_data(client, page,
156					MAX34446_MFR_TEMPERATURE_AVG, 0);
157		break;
158	default:
159		ret = -ENODATA;
160		break;
161	}
162	return ret;
163}
164
165static int max34440_read_byte_data(struct i2c_client *client, int page, int reg)
166{
167	int ret = 0;
168	int mfg_status;
169
170	if (page >= 0) {
171		ret = pmbus_set_page(client, page);
172		if (ret < 0)
173			return ret;
174	}
175
176	switch (reg) {
177	case PMBUS_STATUS_IOUT:
178		mfg_status = pmbus_read_word_data(client, 0,
179						  PMBUS_STATUS_MFR_SPECIFIC);
180		if (mfg_status < 0)
181			return mfg_status;
182		if (mfg_status & MAX34440_STATUS_OC_WARN)
183			ret |= PB_IOUT_OC_WARNING;
184		if (mfg_status & MAX34440_STATUS_OC_FAULT)
185			ret |= PB_IOUT_OC_FAULT;
186		break;
187	case PMBUS_STATUS_TEMPERATURE:
188		mfg_status = pmbus_read_word_data(client, 0,
189						  PMBUS_STATUS_MFR_SPECIFIC);
190		if (mfg_status < 0)
191			return mfg_status;
192		if (mfg_status & MAX34440_STATUS_OT_WARN)
193			ret |= PB_TEMP_OT_WARNING;
194		if (mfg_status & MAX34440_STATUS_OT_FAULT)
195			ret |= PB_TEMP_OT_FAULT;
196		break;
197	default:
198		ret = -ENODATA;
199		break;
200	}
201	return ret;
202}
203
204static struct pmbus_driver_info max34440_info[] = {
205	[max34440] = {
206		.pages = 14,
207		.format[PSC_VOLTAGE_IN] = direct,
208		.format[PSC_VOLTAGE_OUT] = direct,
209		.format[PSC_TEMPERATURE] = direct,
210		.format[PSC_CURRENT_OUT] = direct,
211		.m[PSC_VOLTAGE_IN] = 1,
212		.b[PSC_VOLTAGE_IN] = 0,
213		.R[PSC_VOLTAGE_IN] = 3,	    /* R = 0 in datasheet reflects mV */
214		.m[PSC_VOLTAGE_OUT] = 1,
215		.b[PSC_VOLTAGE_OUT] = 0,
216		.R[PSC_VOLTAGE_OUT] = 3,    /* R = 0 in datasheet reflects mV */
217		.m[PSC_CURRENT_OUT] = 1,
218		.b[PSC_CURRENT_OUT] = 0,
219		.R[PSC_CURRENT_OUT] = 3,    /* R = 0 in datasheet reflects mA */
220		.m[PSC_TEMPERATURE] = 1,
221		.b[PSC_TEMPERATURE] = 0,
222		.R[PSC_TEMPERATURE] = 2,
223		.func[0] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
224		  | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT,
225		.func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
226		  | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT,
227		.func[2] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
228		  | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT,
229		.func[3] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
230		  | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT,
231		.func[4] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
232		  | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT,
233		.func[5] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
234		  | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT,
235		.func[6] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
236		.func[7] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
237		.func[8] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
238		.func[9] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
239		.func[10] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
240		.func[11] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
241		.func[12] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
242		.func[13] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
243		.read_byte_data = max34440_read_byte_data,
244		.read_word_data = max34440_read_word_data,
245		.write_word_data = max34440_write_word_data,
246	},
247	[max34441] = {
248		.pages = 12,
249		.format[PSC_VOLTAGE_IN] = direct,
250		.format[PSC_VOLTAGE_OUT] = direct,
251		.format[PSC_TEMPERATURE] = direct,
252		.format[PSC_CURRENT_OUT] = direct,
253		.format[PSC_FAN] = direct,
254		.m[PSC_VOLTAGE_IN] = 1,
255		.b[PSC_VOLTAGE_IN] = 0,
256		.R[PSC_VOLTAGE_IN] = 3,
257		.m[PSC_VOLTAGE_OUT] = 1,
258		.b[PSC_VOLTAGE_OUT] = 0,
259		.R[PSC_VOLTAGE_OUT] = 3,
260		.m[PSC_CURRENT_OUT] = 1,
261		.b[PSC_CURRENT_OUT] = 0,
262		.R[PSC_CURRENT_OUT] = 3,
263		.m[PSC_TEMPERATURE] = 1,
264		.b[PSC_TEMPERATURE] = 0,
265		.R[PSC_TEMPERATURE] = 2,
266		.m[PSC_FAN] = 1,
267		.b[PSC_FAN] = 0,
268		.R[PSC_FAN] = 0,
269		.func[0] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
270		  | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT,
271		.func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
272		  | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT,
273		.func[2] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
274		  | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT,
275		.func[3] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
276		  | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT,
277		.func[4] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
278		  | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT,
279		.func[5] = PMBUS_HAVE_FAN12 | PMBUS_HAVE_STATUS_FAN12,
280		.func[6] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
281		.func[7] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
282		.func[8] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
283		.func[9] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
284		.func[10] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
285		.func[11] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
286		.read_byte_data = max34440_read_byte_data,
287		.read_word_data = max34440_read_word_data,
288		.write_word_data = max34440_write_word_data,
289	},
290	[max34446] = {
291		.pages = 7,
292		.format[PSC_VOLTAGE_IN] = direct,
293		.format[PSC_VOLTAGE_OUT] = direct,
294		.format[PSC_TEMPERATURE] = direct,
295		.format[PSC_CURRENT_OUT] = direct,
296		.format[PSC_POWER] = direct,
297		.m[PSC_VOLTAGE_IN] = 1,
298		.b[PSC_VOLTAGE_IN] = 0,
299		.R[PSC_VOLTAGE_IN] = 3,
300		.m[PSC_VOLTAGE_OUT] = 1,
301		.b[PSC_VOLTAGE_OUT] = 0,
302		.R[PSC_VOLTAGE_OUT] = 3,
303		.m[PSC_CURRENT_OUT] = 1,
304		.b[PSC_CURRENT_OUT] = 0,
305		.R[PSC_CURRENT_OUT] = 3,
306		.m[PSC_POWER] = 1,
307		.b[PSC_POWER] = 0,
308		.R[PSC_POWER] = 3,
309		.m[PSC_TEMPERATURE] = 1,
310		.b[PSC_TEMPERATURE] = 0,
311		.R[PSC_TEMPERATURE] = 2,
312		.func[0] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
313		  | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT | PMBUS_HAVE_POUT,
314		.func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
315		  | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT,
316		.func[2] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
317		  | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT | PMBUS_HAVE_POUT,
318		.func[3] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
319		  | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT,
320		.func[4] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
321		.func[5] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
322		.func[6] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
323		.read_byte_data = max34440_read_byte_data,
324		.read_word_data = max34440_read_word_data,
325		.write_word_data = max34440_write_word_data,
326	},
327	[max34460] = {
328		.pages = 18,
329		.format[PSC_VOLTAGE_OUT] = direct,
330		.format[PSC_TEMPERATURE] = direct,
331		.m[PSC_VOLTAGE_OUT] = 1,
332		.b[PSC_VOLTAGE_OUT] = 0,
333		.R[PSC_VOLTAGE_OUT] = 3,
334		.m[PSC_TEMPERATURE] = 1,
335		.b[PSC_TEMPERATURE] = 0,
336		.R[PSC_TEMPERATURE] = 2,
337		.func[0] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
338		.func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
339		.func[2] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
340		.func[3] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
341		.func[4] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
342		.func[5] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
343		.func[6] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
344		.func[7] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
345		.func[8] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
346		.func[9] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
347		.func[10] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
348		.func[11] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
349		.func[13] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
350		.func[14] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
351		.func[15] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
352		.func[16] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
353		.func[17] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
354		.read_byte_data = max34440_read_byte_data,
355		.read_word_data = max34440_read_word_data,
356		.write_word_data = max34440_write_word_data,
357	},
358	[max34461] = {
359		.pages = 23,
360		.format[PSC_VOLTAGE_OUT] = direct,
361		.format[PSC_TEMPERATURE] = direct,
362		.m[PSC_VOLTAGE_OUT] = 1,
363		.b[PSC_VOLTAGE_OUT] = 0,
364		.R[PSC_VOLTAGE_OUT] = 3,
365		.m[PSC_TEMPERATURE] = 1,
366		.b[PSC_TEMPERATURE] = 0,
367		.R[PSC_TEMPERATURE] = 2,
368		.func[0] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
369		.func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
370		.func[2] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
371		.func[3] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
372		.func[4] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
373		.func[5] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
374		.func[6] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
375		.func[7] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
376		.func[8] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
377		.func[9] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
378		.func[10] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
379		.func[11] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
380		.func[12] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
381		.func[13] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
382		.func[14] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
383		.func[15] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
384		/* page 16 is reserved */
385		.func[17] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
386		.func[18] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
387		.func[19] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
388		.func[20] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
389		.func[21] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
390		.read_byte_data = max34440_read_byte_data,
391		.read_word_data = max34440_read_word_data,
392		.write_word_data = max34440_write_word_data,
393	},
394};
395
396static int max34440_probe(struct i2c_client *client,
397			  const struct i2c_device_id *id)
398{
399	struct max34440_data *data;
400
401	data = devm_kzalloc(&client->dev, sizeof(struct max34440_data),
402			    GFP_KERNEL);
403	if (!data)
404		return -ENOMEM;
405	data->id = id->driver_data;
406	data->info = max34440_info[id->driver_data];
407
408	return pmbus_do_probe(client, id, &data->info);
409}
410
411static const struct i2c_device_id max34440_id[] = {
412	{"max34440", max34440},
413	{"max34441", max34441},
414	{"max34446", max34446},
415	{"max34460", max34460},
416	{"max34461", max34461},
417	{}
418};
419MODULE_DEVICE_TABLE(i2c, max34440_id);
420
421/* This is the driver that will be inserted */
422static struct i2c_driver max34440_driver = {
423	.driver = {
424		   .name = "max34440",
425		   },
426	.probe = max34440_probe,
427	.remove = pmbus_do_remove,
428	.id_table = max34440_id,
429};
430
431module_i2c_driver(max34440_driver);
432
433MODULE_AUTHOR("Guenter Roeck");
434MODULE_DESCRIPTION("PMBus driver for Maxim MAX34440/MAX34441");
435MODULE_LICENSE("GPL");
436