xref: /openbmc/linux/drivers/hwmon/pmbus/max8688.c (revision 2612e3bbc0386368a850140a6c9b990cd496a5ec)
1  // SPDX-License-Identifier: GPL-2.0-or-later
2  /*
3   * Hardware monitoring driver for Maxim MAX8688
4   *
5   * Copyright (c) 2011 Ericsson AB.
6   */
7  
8  #include <linux/bitops.h>
9  #include <linux/kernel.h>
10  #include <linux/module.h>
11  #include <linux/init.h>
12  #include <linux/err.h>
13  #include <linux/i2c.h>
14  #include "pmbus.h"
15  
16  #define MAX8688_MFR_VOUT_PEAK		0xd4
17  #define MAX8688_MFR_IOUT_PEAK		0xd5
18  #define MAX8688_MFR_TEMPERATURE_PEAK	0xd6
19  #define MAX8688_MFG_STATUS		0xd8
20  
21  #define MAX8688_STATUS_OC_FAULT		BIT(4)
22  #define MAX8688_STATUS_OV_FAULT		BIT(5)
23  #define MAX8688_STATUS_OV_WARNING	BIT(8)
24  #define MAX8688_STATUS_UV_FAULT		BIT(9)
25  #define MAX8688_STATUS_UV_WARNING	BIT(10)
26  #define MAX8688_STATUS_UC_FAULT		BIT(11)
27  #define MAX8688_STATUS_OC_WARNING	BIT(12)
28  #define MAX8688_STATUS_OT_FAULT		BIT(13)
29  #define MAX8688_STATUS_OT_WARNING	BIT(14)
30  
max8688_read_word_data(struct i2c_client * client,int page,int phase,int reg)31  static int max8688_read_word_data(struct i2c_client *client, int page,
32  				  int phase, int reg)
33  {
34  	int ret;
35  
36  	if (page > 0)
37  		return -ENXIO;
38  
39  	switch (reg) {
40  	case PMBUS_VIRT_READ_VOUT_MAX:
41  		ret = pmbus_read_word_data(client, 0, 0xff,
42  					   MAX8688_MFR_VOUT_PEAK);
43  		break;
44  	case PMBUS_VIRT_READ_IOUT_MAX:
45  		ret = pmbus_read_word_data(client, 0, 0xff,
46  					   MAX8688_MFR_IOUT_PEAK);
47  		break;
48  	case PMBUS_VIRT_READ_TEMP_MAX:
49  		ret = pmbus_read_word_data(client, 0, 0xff,
50  					   MAX8688_MFR_TEMPERATURE_PEAK);
51  		break;
52  	case PMBUS_VIRT_RESET_VOUT_HISTORY:
53  	case PMBUS_VIRT_RESET_IOUT_HISTORY:
54  	case PMBUS_VIRT_RESET_TEMP_HISTORY:
55  		ret = 0;
56  		break;
57  	default:
58  		ret = -ENODATA;
59  		break;
60  	}
61  	return ret;
62  }
63  
max8688_write_word_data(struct i2c_client * client,int page,int reg,u16 word)64  static int max8688_write_word_data(struct i2c_client *client, int page, int reg,
65  				   u16 word)
66  {
67  	int ret;
68  
69  	switch (reg) {
70  	case PMBUS_VIRT_RESET_VOUT_HISTORY:
71  		ret = pmbus_write_word_data(client, 0, MAX8688_MFR_VOUT_PEAK,
72  					    0);
73  		break;
74  	case PMBUS_VIRT_RESET_IOUT_HISTORY:
75  		ret = pmbus_write_word_data(client, 0, MAX8688_MFR_IOUT_PEAK,
76  					    0);
77  		break;
78  	case PMBUS_VIRT_RESET_TEMP_HISTORY:
79  		ret = pmbus_write_word_data(client, 0,
80  					    MAX8688_MFR_TEMPERATURE_PEAK,
81  					    0xffff);
82  		break;
83  	default:
84  		ret = -ENODATA;
85  		break;
86  	}
87  	return ret;
88  }
89  
max8688_read_byte_data(struct i2c_client * client,int page,int reg)90  static int max8688_read_byte_data(struct i2c_client *client, int page, int reg)
91  {
92  	int ret = 0;
93  	int mfg_status;
94  
95  	if (page > 0)
96  		return -ENXIO;
97  
98  	switch (reg) {
99  	case PMBUS_STATUS_VOUT:
100  		mfg_status = pmbus_read_word_data(client, 0, 0xff,
101  						  MAX8688_MFG_STATUS);
102  		if (mfg_status < 0)
103  			return mfg_status;
104  		if (mfg_status & MAX8688_STATUS_UV_WARNING)
105  			ret |= PB_VOLTAGE_UV_WARNING;
106  		if (mfg_status & MAX8688_STATUS_UV_FAULT)
107  			ret |= PB_VOLTAGE_UV_FAULT;
108  		if (mfg_status & MAX8688_STATUS_OV_WARNING)
109  			ret |= PB_VOLTAGE_OV_WARNING;
110  		if (mfg_status & MAX8688_STATUS_OV_FAULT)
111  			ret |= PB_VOLTAGE_OV_FAULT;
112  		break;
113  	case PMBUS_STATUS_IOUT:
114  		mfg_status = pmbus_read_word_data(client, 0, 0xff,
115  						  MAX8688_MFG_STATUS);
116  		if (mfg_status < 0)
117  			return mfg_status;
118  		if (mfg_status & MAX8688_STATUS_UC_FAULT)
119  			ret |= PB_IOUT_UC_FAULT;
120  		if (mfg_status & MAX8688_STATUS_OC_WARNING)
121  			ret |= PB_IOUT_OC_WARNING;
122  		if (mfg_status & MAX8688_STATUS_OC_FAULT)
123  			ret |= PB_IOUT_OC_FAULT;
124  		break;
125  	case PMBUS_STATUS_TEMPERATURE:
126  		mfg_status = pmbus_read_word_data(client, 0, 0xff,
127  						  MAX8688_MFG_STATUS);
128  		if (mfg_status < 0)
129  			return mfg_status;
130  		if (mfg_status & MAX8688_STATUS_OT_WARNING)
131  			ret |= PB_TEMP_OT_WARNING;
132  		if (mfg_status & MAX8688_STATUS_OT_FAULT)
133  			ret |= PB_TEMP_OT_FAULT;
134  		break;
135  	default:
136  		ret = -ENODATA;
137  		break;
138  	}
139  	return ret;
140  }
141  
142  static struct pmbus_driver_info max8688_info = {
143  	.pages = 1,
144  	.format[PSC_VOLTAGE_IN] = direct,
145  	.format[PSC_VOLTAGE_OUT] = direct,
146  	.format[PSC_TEMPERATURE] = direct,
147  	.format[PSC_CURRENT_OUT] = direct,
148  	.m[PSC_VOLTAGE_IN] = 19995,
149  	.b[PSC_VOLTAGE_IN] = 0,
150  	.R[PSC_VOLTAGE_IN] = -1,
151  	.m[PSC_VOLTAGE_OUT] = 19995,
152  	.b[PSC_VOLTAGE_OUT] = 0,
153  	.R[PSC_VOLTAGE_OUT] = -1,
154  	.m[PSC_CURRENT_OUT] = 23109,
155  	.b[PSC_CURRENT_OUT] = 0,
156  	.R[PSC_CURRENT_OUT] = -2,
157  	.m[PSC_TEMPERATURE] = -7612,
158  	.b[PSC_TEMPERATURE] = 335,
159  	.R[PSC_TEMPERATURE] = -3,
160  	.func[0] = PMBUS_HAVE_VOUT | PMBUS_HAVE_IOUT | PMBUS_HAVE_TEMP
161  		| PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_STATUS_IOUT
162  		| PMBUS_HAVE_STATUS_TEMP,
163  	.read_byte_data = max8688_read_byte_data,
164  	.read_word_data = max8688_read_word_data,
165  	.write_word_data = max8688_write_word_data,
166  };
167  
max8688_probe(struct i2c_client * client)168  static int max8688_probe(struct i2c_client *client)
169  {
170  	return pmbus_do_probe(client, &max8688_info);
171  }
172  
173  static const struct i2c_device_id max8688_id[] = {
174  	{"max8688", 0},
175  	{ }
176  };
177  
178  MODULE_DEVICE_TABLE(i2c, max8688_id);
179  
180  /* This is the driver that will be inserted */
181  static struct i2c_driver max8688_driver = {
182  	.driver = {
183  		   .name = "max8688",
184  		   },
185  	.probe = max8688_probe,
186  	.id_table = max8688_id,
187  };
188  
189  module_i2c_driver(max8688_driver);
190  
191  MODULE_AUTHOR("Guenter Roeck");
192  MODULE_DESCRIPTION("PMBus driver for Maxim MAX8688");
193  MODULE_LICENSE("GPL");
194  MODULE_IMPORT_NS(PMBUS);
195