xref: /openbmc/linux/drivers/hwmon/pmbus/lm25066.c (revision 03e9bd8dbcee60c2e22fd54f9f28f0d32da218c3)
1*03e9bd8dSGuenter Roeck /*
2*03e9bd8dSGuenter Roeck  * Hardware monitoring driver for LM25066 / LM5064 / LM5066
3*03e9bd8dSGuenter Roeck  *
4*03e9bd8dSGuenter Roeck  * Copyright (c) 2011 Ericsson AB.
5*03e9bd8dSGuenter Roeck  *
6*03e9bd8dSGuenter Roeck  * This program is free software; you can redistribute it and/or modify
7*03e9bd8dSGuenter Roeck  * it under the terms of the GNU General Public License as published by
8*03e9bd8dSGuenter Roeck  * the Free Software Foundation; either version 2 of the License, or
9*03e9bd8dSGuenter Roeck  * (at your option) any later version.
10*03e9bd8dSGuenter Roeck  *
11*03e9bd8dSGuenter Roeck  * This program is distributed in the hope that it will be useful,
12*03e9bd8dSGuenter Roeck  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13*03e9bd8dSGuenter Roeck  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14*03e9bd8dSGuenter Roeck  * GNU General Public License for more details.
15*03e9bd8dSGuenter Roeck  *
16*03e9bd8dSGuenter Roeck  * You should have received a copy of the GNU General Public License
17*03e9bd8dSGuenter Roeck  * along with this program; if not, write to the Free Software
18*03e9bd8dSGuenter Roeck  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19*03e9bd8dSGuenter Roeck  */
20*03e9bd8dSGuenter Roeck 
21*03e9bd8dSGuenter Roeck #include <linux/kernel.h>
22*03e9bd8dSGuenter Roeck #include <linux/module.h>
23*03e9bd8dSGuenter Roeck #include <linux/init.h>
24*03e9bd8dSGuenter Roeck #include <linux/err.h>
25*03e9bd8dSGuenter Roeck #include <linux/slab.h>
26*03e9bd8dSGuenter Roeck #include <linux/i2c.h>
27*03e9bd8dSGuenter Roeck #include "pmbus.h"
28*03e9bd8dSGuenter Roeck 
29*03e9bd8dSGuenter Roeck enum chips { lm25066, lm5064, lm5066 };
30*03e9bd8dSGuenter Roeck 
31*03e9bd8dSGuenter Roeck #define LM25066_READ_VAUX		0xd0
32*03e9bd8dSGuenter Roeck #define LM25066_MFR_READ_IIN		0xd1
33*03e9bd8dSGuenter Roeck #define LM25066_MFR_READ_PIN		0xd2
34*03e9bd8dSGuenter Roeck #define LM25066_MFR_IIN_OC_WARN_LIMIT	0xd3
35*03e9bd8dSGuenter Roeck #define LM25066_MFR_PIN_OP_WARN_LIMIT	0xd4
36*03e9bd8dSGuenter Roeck #define LM25066_READ_PIN_PEAK		0xd5
37*03e9bd8dSGuenter Roeck #define LM25066_CLEAR_PIN_PEAK		0xd6
38*03e9bd8dSGuenter Roeck #define LM25066_DEVICE_SETUP		0xd9
39*03e9bd8dSGuenter Roeck #define LM25066_READ_AVG_VIN		0xdc
40*03e9bd8dSGuenter Roeck #define LM25066_READ_AVG_VOUT		0xdd
41*03e9bd8dSGuenter Roeck #define LM25066_READ_AVG_IIN		0xde
42*03e9bd8dSGuenter Roeck #define LM25066_READ_AVG_PIN		0xdf
43*03e9bd8dSGuenter Roeck 
44*03e9bd8dSGuenter Roeck #define LM25066_DEV_SETUP_CL		(1 << 4)	/* Current limit */
45*03e9bd8dSGuenter Roeck 
46*03e9bd8dSGuenter Roeck struct lm25066_data {
47*03e9bd8dSGuenter Roeck 	int id;
48*03e9bd8dSGuenter Roeck 	struct pmbus_driver_info info;
49*03e9bd8dSGuenter Roeck };
50*03e9bd8dSGuenter Roeck 
51*03e9bd8dSGuenter Roeck #define to_lm25066_data(x)  container_of(x, struct lm25066_data, info)
52*03e9bd8dSGuenter Roeck 
53*03e9bd8dSGuenter Roeck static int lm25066_read_word_data(struct i2c_client *client, int page, int reg)
54*03e9bd8dSGuenter Roeck {
55*03e9bd8dSGuenter Roeck 	const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
56*03e9bd8dSGuenter Roeck 	const struct lm25066_data *data = to_lm25066_data(info);
57*03e9bd8dSGuenter Roeck 	int ret;
58*03e9bd8dSGuenter Roeck 
59*03e9bd8dSGuenter Roeck 	if (page > 1)
60*03e9bd8dSGuenter Roeck 		return -EINVAL;
61*03e9bd8dSGuenter Roeck 
62*03e9bd8dSGuenter Roeck 	/* Map READ_VAUX into READ_VOUT register on page 1 */
63*03e9bd8dSGuenter Roeck 	if (page == 1) {
64*03e9bd8dSGuenter Roeck 		switch (reg) {
65*03e9bd8dSGuenter Roeck 		case PMBUS_READ_VOUT:
66*03e9bd8dSGuenter Roeck 			ret = pmbus_read_word_data(client, 0,
67*03e9bd8dSGuenter Roeck 						   LM25066_READ_VAUX);
68*03e9bd8dSGuenter Roeck 			if (ret < 0)
69*03e9bd8dSGuenter Roeck 				break;
70*03e9bd8dSGuenter Roeck 			/* Adjust returned value to match VOUT coefficients */
71*03e9bd8dSGuenter Roeck 			switch (data->id) {
72*03e9bd8dSGuenter Roeck 			case lm25066:
73*03e9bd8dSGuenter Roeck 				/* VOUT: 4.54 mV VAUX: 283.2 uV LSB */
74*03e9bd8dSGuenter Roeck 				ret = DIV_ROUND_CLOSEST(ret * 2832, 45400);
75*03e9bd8dSGuenter Roeck 				break;
76*03e9bd8dSGuenter Roeck 			case lm5064:
77*03e9bd8dSGuenter Roeck 				/* VOUT: 4.53 mV VAUX: 700 uV LSB */
78*03e9bd8dSGuenter Roeck 				ret = DIV_ROUND_CLOSEST(ret * 70, 453);
79*03e9bd8dSGuenter Roeck 				break;
80*03e9bd8dSGuenter Roeck 			case lm5066:
81*03e9bd8dSGuenter Roeck 				/* VOUT: 2.18 mV VAUX: 725 uV LSB */
82*03e9bd8dSGuenter Roeck 				ret = DIV_ROUND_CLOSEST(ret * 725, 2180);
83*03e9bd8dSGuenter Roeck 				break;
84*03e9bd8dSGuenter Roeck 			}
85*03e9bd8dSGuenter Roeck 			break;
86*03e9bd8dSGuenter Roeck 		default:
87*03e9bd8dSGuenter Roeck 			/* No other valid registers on page 1 */
88*03e9bd8dSGuenter Roeck 			ret = -EINVAL;
89*03e9bd8dSGuenter Roeck 			break;
90*03e9bd8dSGuenter Roeck 		}
91*03e9bd8dSGuenter Roeck 		goto done;
92*03e9bd8dSGuenter Roeck 	}
93*03e9bd8dSGuenter Roeck 
94*03e9bd8dSGuenter Roeck 	switch (reg) {
95*03e9bd8dSGuenter Roeck 	case PMBUS_READ_IIN:
96*03e9bd8dSGuenter Roeck 		ret = pmbus_read_word_data(client, 0, LM25066_MFR_READ_IIN);
97*03e9bd8dSGuenter Roeck 		break;
98*03e9bd8dSGuenter Roeck 	case PMBUS_READ_PIN:
99*03e9bd8dSGuenter Roeck 		ret = pmbus_read_word_data(client, 0, LM25066_MFR_READ_PIN);
100*03e9bd8dSGuenter Roeck 		break;
101*03e9bd8dSGuenter Roeck 	case PMBUS_IIN_OC_WARN_LIMIT:
102*03e9bd8dSGuenter Roeck 		ret = pmbus_read_word_data(client, 0,
103*03e9bd8dSGuenter Roeck 					   LM25066_MFR_IIN_OC_WARN_LIMIT);
104*03e9bd8dSGuenter Roeck 		break;
105*03e9bd8dSGuenter Roeck 	case PMBUS_PIN_OP_WARN_LIMIT:
106*03e9bd8dSGuenter Roeck 		ret = pmbus_read_word_data(client, 0,
107*03e9bd8dSGuenter Roeck 					   LM25066_MFR_PIN_OP_WARN_LIMIT);
108*03e9bd8dSGuenter Roeck 		break;
109*03e9bd8dSGuenter Roeck 	case PMBUS_VIRT_READ_VIN_AVG:
110*03e9bd8dSGuenter Roeck 		ret = pmbus_read_word_data(client, 0, LM25066_READ_AVG_VIN);
111*03e9bd8dSGuenter Roeck 		break;
112*03e9bd8dSGuenter Roeck 	case PMBUS_VIRT_READ_VOUT_AVG:
113*03e9bd8dSGuenter Roeck 		ret = pmbus_read_word_data(client, 0, LM25066_READ_AVG_VOUT);
114*03e9bd8dSGuenter Roeck 		break;
115*03e9bd8dSGuenter Roeck 	case PMBUS_VIRT_READ_IIN_AVG:
116*03e9bd8dSGuenter Roeck 		ret = pmbus_read_word_data(client, 0, LM25066_READ_AVG_IIN);
117*03e9bd8dSGuenter Roeck 		break;
118*03e9bd8dSGuenter Roeck 	case PMBUS_VIRT_READ_PIN_AVG:
119*03e9bd8dSGuenter Roeck 		ret = pmbus_read_word_data(client, 0, LM25066_READ_AVG_PIN);
120*03e9bd8dSGuenter Roeck 		break;
121*03e9bd8dSGuenter Roeck 	case PMBUS_VIRT_READ_PIN_MAX:
122*03e9bd8dSGuenter Roeck 		ret = pmbus_read_word_data(client, 0, LM25066_READ_PIN_PEAK);
123*03e9bd8dSGuenter Roeck 		break;
124*03e9bd8dSGuenter Roeck 	case PMBUS_VIRT_RESET_PIN_HISTORY:
125*03e9bd8dSGuenter Roeck 		ret = 0;
126*03e9bd8dSGuenter Roeck 		break;
127*03e9bd8dSGuenter Roeck 	default:
128*03e9bd8dSGuenter Roeck 		ret = -ENODATA;
129*03e9bd8dSGuenter Roeck 		break;
130*03e9bd8dSGuenter Roeck 	}
131*03e9bd8dSGuenter Roeck done:
132*03e9bd8dSGuenter Roeck 	return ret;
133*03e9bd8dSGuenter Roeck }
134*03e9bd8dSGuenter Roeck 
135*03e9bd8dSGuenter Roeck static int lm25066_write_word_data(struct i2c_client *client, int page, int reg,
136*03e9bd8dSGuenter Roeck 				   u16 word)
137*03e9bd8dSGuenter Roeck {
138*03e9bd8dSGuenter Roeck 	int ret;
139*03e9bd8dSGuenter Roeck 
140*03e9bd8dSGuenter Roeck 	if (page > 1)
141*03e9bd8dSGuenter Roeck 		return -EINVAL;
142*03e9bd8dSGuenter Roeck 
143*03e9bd8dSGuenter Roeck 	switch (reg) {
144*03e9bd8dSGuenter Roeck 	case PMBUS_IIN_OC_WARN_LIMIT:
145*03e9bd8dSGuenter Roeck 		ret = pmbus_write_word_data(client, 0,
146*03e9bd8dSGuenter Roeck 					    LM25066_MFR_IIN_OC_WARN_LIMIT,
147*03e9bd8dSGuenter Roeck 					    word);
148*03e9bd8dSGuenter Roeck 		break;
149*03e9bd8dSGuenter Roeck 	case PMBUS_PIN_OP_WARN_LIMIT:
150*03e9bd8dSGuenter Roeck 		ret = pmbus_write_word_data(client, 0,
151*03e9bd8dSGuenter Roeck 					    LM25066_MFR_PIN_OP_WARN_LIMIT,
152*03e9bd8dSGuenter Roeck 					    word);
153*03e9bd8dSGuenter Roeck 		break;
154*03e9bd8dSGuenter Roeck 	case PMBUS_VIRT_RESET_PIN_HISTORY:
155*03e9bd8dSGuenter Roeck 		ret = pmbus_write_byte(client, 0, LM25066_CLEAR_PIN_PEAK);
156*03e9bd8dSGuenter Roeck 		break;
157*03e9bd8dSGuenter Roeck 	default:
158*03e9bd8dSGuenter Roeck 		ret = -ENODATA;
159*03e9bd8dSGuenter Roeck 		break;
160*03e9bd8dSGuenter Roeck 	}
161*03e9bd8dSGuenter Roeck 	return ret;
162*03e9bd8dSGuenter Roeck }
163*03e9bd8dSGuenter Roeck 
164*03e9bd8dSGuenter Roeck static int lm25066_probe(struct i2c_client *client,
165*03e9bd8dSGuenter Roeck 			  const struct i2c_device_id *id)
166*03e9bd8dSGuenter Roeck {
167*03e9bd8dSGuenter Roeck 	int config;
168*03e9bd8dSGuenter Roeck 	int ret;
169*03e9bd8dSGuenter Roeck 	struct lm25066_data *data;
170*03e9bd8dSGuenter Roeck 	struct pmbus_driver_info *info;
171*03e9bd8dSGuenter Roeck 
172*03e9bd8dSGuenter Roeck 	if (!i2c_check_functionality(client->adapter,
173*03e9bd8dSGuenter Roeck 				     I2C_FUNC_SMBUS_READ_BYTE_DATA))
174*03e9bd8dSGuenter Roeck 		return -ENODEV;
175*03e9bd8dSGuenter Roeck 
176*03e9bd8dSGuenter Roeck 	data = kzalloc(sizeof(struct lm25066_data), GFP_KERNEL);
177*03e9bd8dSGuenter Roeck 	if (!data)
178*03e9bd8dSGuenter Roeck 		return -ENOMEM;
179*03e9bd8dSGuenter Roeck 
180*03e9bd8dSGuenter Roeck 	config = i2c_smbus_read_byte_data(client, LM25066_DEVICE_SETUP);
181*03e9bd8dSGuenter Roeck 	if (config < 0) {
182*03e9bd8dSGuenter Roeck 		ret = config;
183*03e9bd8dSGuenter Roeck 		goto err_mem;
184*03e9bd8dSGuenter Roeck 	}
185*03e9bd8dSGuenter Roeck 
186*03e9bd8dSGuenter Roeck 	data->id = id->driver_data;
187*03e9bd8dSGuenter Roeck 	info = &data->info;
188*03e9bd8dSGuenter Roeck 
189*03e9bd8dSGuenter Roeck 	info->pages = 2;
190*03e9bd8dSGuenter Roeck 	info->format[PSC_VOLTAGE_IN] = direct;
191*03e9bd8dSGuenter Roeck 	info->format[PSC_VOLTAGE_OUT] = direct;
192*03e9bd8dSGuenter Roeck 	info->format[PSC_CURRENT_IN] = direct;
193*03e9bd8dSGuenter Roeck 	info->format[PSC_TEMPERATURE] = direct;
194*03e9bd8dSGuenter Roeck 	info->format[PSC_POWER] = direct;
195*03e9bd8dSGuenter Roeck 
196*03e9bd8dSGuenter Roeck 	info->m[PSC_TEMPERATURE] = 16;
197*03e9bd8dSGuenter Roeck 	info->b[PSC_TEMPERATURE] = 0;
198*03e9bd8dSGuenter Roeck 	info->R[PSC_TEMPERATURE] = 0;
199*03e9bd8dSGuenter Roeck 
200*03e9bd8dSGuenter Roeck 	info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT
201*03e9bd8dSGuenter Roeck 	  | PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_PIN | PMBUS_HAVE_IIN
202*03e9bd8dSGuenter Roeck 	  | PMBUS_HAVE_STATUS_INPUT | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP;
203*03e9bd8dSGuenter Roeck 	info->func[1] = PMBUS_HAVE_VOUT;
204*03e9bd8dSGuenter Roeck 
205*03e9bd8dSGuenter Roeck 	info->read_word_data = lm25066_read_word_data;
206*03e9bd8dSGuenter Roeck 	info->write_word_data = lm25066_write_word_data;
207*03e9bd8dSGuenter Roeck 
208*03e9bd8dSGuenter Roeck 	switch (id->driver_data) {
209*03e9bd8dSGuenter Roeck 	case lm25066:
210*03e9bd8dSGuenter Roeck 		info->m[PSC_VOLTAGE_IN] = 22070;
211*03e9bd8dSGuenter Roeck 		info->b[PSC_VOLTAGE_IN] = 0;
212*03e9bd8dSGuenter Roeck 		info->R[PSC_VOLTAGE_IN] = -2;
213*03e9bd8dSGuenter Roeck 		info->m[PSC_VOLTAGE_OUT] = 22070;
214*03e9bd8dSGuenter Roeck 		info->b[PSC_VOLTAGE_OUT] = 0;
215*03e9bd8dSGuenter Roeck 		info->R[PSC_VOLTAGE_OUT] = -2;
216*03e9bd8dSGuenter Roeck 
217*03e9bd8dSGuenter Roeck 		if (config & LM25066_DEV_SETUP_CL) {
218*03e9bd8dSGuenter Roeck 			info->m[PSC_CURRENT_IN] = 6852;
219*03e9bd8dSGuenter Roeck 			info->b[PSC_CURRENT_IN] = 0;
220*03e9bd8dSGuenter Roeck 			info->R[PSC_CURRENT_IN] = -2;
221*03e9bd8dSGuenter Roeck 			info->m[PSC_POWER] = 369;
222*03e9bd8dSGuenter Roeck 			info->b[PSC_POWER] = 0;
223*03e9bd8dSGuenter Roeck 			info->R[PSC_POWER] = -2;
224*03e9bd8dSGuenter Roeck 		} else {
225*03e9bd8dSGuenter Roeck 			info->m[PSC_CURRENT_IN] = 13661;
226*03e9bd8dSGuenter Roeck 			info->b[PSC_CURRENT_IN] = 0;
227*03e9bd8dSGuenter Roeck 			info->R[PSC_CURRENT_IN] = -2;
228*03e9bd8dSGuenter Roeck 			info->m[PSC_POWER] = 736;
229*03e9bd8dSGuenter Roeck 			info->b[PSC_POWER] = 0;
230*03e9bd8dSGuenter Roeck 			info->R[PSC_POWER] = -2;
231*03e9bd8dSGuenter Roeck 		}
232*03e9bd8dSGuenter Roeck 		break;
233*03e9bd8dSGuenter Roeck 	case lm5064:
234*03e9bd8dSGuenter Roeck 		info->m[PSC_VOLTAGE_IN] = 22075;
235*03e9bd8dSGuenter Roeck 		info->b[PSC_VOLTAGE_IN] = 0;
236*03e9bd8dSGuenter Roeck 		info->R[PSC_VOLTAGE_IN] = -2;
237*03e9bd8dSGuenter Roeck 		info->m[PSC_VOLTAGE_OUT] = 22075;
238*03e9bd8dSGuenter Roeck 		info->b[PSC_VOLTAGE_OUT] = 0;
239*03e9bd8dSGuenter Roeck 		info->R[PSC_VOLTAGE_OUT] = -2;
240*03e9bd8dSGuenter Roeck 
241*03e9bd8dSGuenter Roeck 		if (config & LM25066_DEV_SETUP_CL) {
242*03e9bd8dSGuenter Roeck 			info->m[PSC_CURRENT_IN] = 6713;
243*03e9bd8dSGuenter Roeck 			info->b[PSC_CURRENT_IN] = 0;
244*03e9bd8dSGuenter Roeck 			info->R[PSC_CURRENT_IN] = -2;
245*03e9bd8dSGuenter Roeck 			info->m[PSC_POWER] = 3619;
246*03e9bd8dSGuenter Roeck 			info->b[PSC_POWER] = 0;
247*03e9bd8dSGuenter Roeck 			info->R[PSC_POWER] = -3;
248*03e9bd8dSGuenter Roeck 		} else {
249*03e9bd8dSGuenter Roeck 			info->m[PSC_CURRENT_IN] = 13426;
250*03e9bd8dSGuenter Roeck 			info->b[PSC_CURRENT_IN] = 0;
251*03e9bd8dSGuenter Roeck 			info->R[PSC_CURRENT_IN] = -2;
252*03e9bd8dSGuenter Roeck 			info->m[PSC_POWER] = 7238;
253*03e9bd8dSGuenter Roeck 			info->b[PSC_POWER] = 0;
254*03e9bd8dSGuenter Roeck 			info->R[PSC_POWER] = -3;
255*03e9bd8dSGuenter Roeck 		}
256*03e9bd8dSGuenter Roeck 		break;
257*03e9bd8dSGuenter Roeck 	case lm5066:
258*03e9bd8dSGuenter Roeck 		info->m[PSC_VOLTAGE_IN] = 4587;
259*03e9bd8dSGuenter Roeck 		info->b[PSC_VOLTAGE_IN] = 0;
260*03e9bd8dSGuenter Roeck 		info->R[PSC_VOLTAGE_IN] = -2;
261*03e9bd8dSGuenter Roeck 		info->m[PSC_VOLTAGE_OUT] = 4587;
262*03e9bd8dSGuenter Roeck 		info->b[PSC_VOLTAGE_OUT] = 0;
263*03e9bd8dSGuenter Roeck 		info->R[PSC_VOLTAGE_OUT] = -2;
264*03e9bd8dSGuenter Roeck 
265*03e9bd8dSGuenter Roeck 		if (config & LM25066_DEV_SETUP_CL) {
266*03e9bd8dSGuenter Roeck 			info->m[PSC_CURRENT_IN] = 10753;
267*03e9bd8dSGuenter Roeck 			info->b[PSC_CURRENT_IN] = 0;
268*03e9bd8dSGuenter Roeck 			info->R[PSC_CURRENT_IN] = -2;
269*03e9bd8dSGuenter Roeck 			info->m[PSC_POWER] = 1204;
270*03e9bd8dSGuenter Roeck 			info->b[PSC_POWER] = 0;
271*03e9bd8dSGuenter Roeck 			info->R[PSC_POWER] = -3;
272*03e9bd8dSGuenter Roeck 		} else {
273*03e9bd8dSGuenter Roeck 			info->m[PSC_CURRENT_IN] = 5405;
274*03e9bd8dSGuenter Roeck 			info->b[PSC_CURRENT_IN] = 0;
275*03e9bd8dSGuenter Roeck 			info->R[PSC_CURRENT_IN] = -2;
276*03e9bd8dSGuenter Roeck 			info->m[PSC_POWER] = 605;
277*03e9bd8dSGuenter Roeck 			info->b[PSC_POWER] = 0;
278*03e9bd8dSGuenter Roeck 			info->R[PSC_POWER] = -3;
279*03e9bd8dSGuenter Roeck 		}
280*03e9bd8dSGuenter Roeck 		break;
281*03e9bd8dSGuenter Roeck 	default:
282*03e9bd8dSGuenter Roeck 		ret = -ENODEV;
283*03e9bd8dSGuenter Roeck 		goto err_mem;
284*03e9bd8dSGuenter Roeck 	}
285*03e9bd8dSGuenter Roeck 
286*03e9bd8dSGuenter Roeck 	ret = pmbus_do_probe(client, id, info);
287*03e9bd8dSGuenter Roeck 	if (ret)
288*03e9bd8dSGuenter Roeck 		goto err_mem;
289*03e9bd8dSGuenter Roeck 	return 0;
290*03e9bd8dSGuenter Roeck 
291*03e9bd8dSGuenter Roeck err_mem:
292*03e9bd8dSGuenter Roeck 	kfree(data);
293*03e9bd8dSGuenter Roeck 	return ret;
294*03e9bd8dSGuenter Roeck }
295*03e9bd8dSGuenter Roeck 
296*03e9bd8dSGuenter Roeck static int lm25066_remove(struct i2c_client *client)
297*03e9bd8dSGuenter Roeck {
298*03e9bd8dSGuenter Roeck 	const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
299*03e9bd8dSGuenter Roeck 	const struct lm25066_data *data = to_lm25066_data(info);
300*03e9bd8dSGuenter Roeck 	int ret;
301*03e9bd8dSGuenter Roeck 
302*03e9bd8dSGuenter Roeck 	ret = pmbus_do_remove(client);
303*03e9bd8dSGuenter Roeck 	kfree(data);
304*03e9bd8dSGuenter Roeck 	return ret;
305*03e9bd8dSGuenter Roeck }
306*03e9bd8dSGuenter Roeck 
307*03e9bd8dSGuenter Roeck static const struct i2c_device_id lm25066_id[] = {
308*03e9bd8dSGuenter Roeck 	{"lm25066", lm25066},
309*03e9bd8dSGuenter Roeck 	{"lm5064", lm5064},
310*03e9bd8dSGuenter Roeck 	{"lm5066", lm5066},
311*03e9bd8dSGuenter Roeck 	{ }
312*03e9bd8dSGuenter Roeck };
313*03e9bd8dSGuenter Roeck 
314*03e9bd8dSGuenter Roeck MODULE_DEVICE_TABLE(i2c, lm25066_id);
315*03e9bd8dSGuenter Roeck 
316*03e9bd8dSGuenter Roeck /* This is the driver that will be inserted */
317*03e9bd8dSGuenter Roeck static struct i2c_driver lm25066_driver = {
318*03e9bd8dSGuenter Roeck 	.driver = {
319*03e9bd8dSGuenter Roeck 		   .name = "lm25066",
320*03e9bd8dSGuenter Roeck 		   },
321*03e9bd8dSGuenter Roeck 	.probe = lm25066_probe,
322*03e9bd8dSGuenter Roeck 	.remove = lm25066_remove,
323*03e9bd8dSGuenter Roeck 	.id_table = lm25066_id,
324*03e9bd8dSGuenter Roeck };
325*03e9bd8dSGuenter Roeck 
326*03e9bd8dSGuenter Roeck static int __init lm25066_init(void)
327*03e9bd8dSGuenter Roeck {
328*03e9bd8dSGuenter Roeck 	return i2c_add_driver(&lm25066_driver);
329*03e9bd8dSGuenter Roeck }
330*03e9bd8dSGuenter Roeck 
331*03e9bd8dSGuenter Roeck static void __exit lm25066_exit(void)
332*03e9bd8dSGuenter Roeck {
333*03e9bd8dSGuenter Roeck 	i2c_del_driver(&lm25066_driver);
334*03e9bd8dSGuenter Roeck }
335*03e9bd8dSGuenter Roeck 
336*03e9bd8dSGuenter Roeck MODULE_AUTHOR("Guenter Roeck");
337*03e9bd8dSGuenter Roeck MODULE_DESCRIPTION("PMBus driver for LM25066/LM5064/LM5066");
338*03e9bd8dSGuenter Roeck MODULE_LICENSE("GPL");
339*03e9bd8dSGuenter Roeck module_init(lm25066_init);
340*03e9bd8dSGuenter Roeck module_exit(lm25066_exit);
341