xref: /linux/drivers/regulator/ab8500-ext.c (revision d1a820011b2fbc11d5af80d1a961fe66c613fa4b)
1*d1a82001SLee Jones /*
2*d1a82001SLee Jones  * Copyright (C) ST-Ericsson SA 2010
3*d1a82001SLee Jones  *
4*d1a82001SLee Jones  * License Terms: GNU General Public License v2
5*d1a82001SLee Jones  *
6*d1a82001SLee Jones  * Authors: Bengt Jonsson <bengt.g.jonsson@stericsson.com>
7*d1a82001SLee Jones  *
8*d1a82001SLee Jones  * This file is based on drivers/regulator/ab8500.c
9*d1a82001SLee Jones  *
10*d1a82001SLee Jones  * AB8500 external regulators
11*d1a82001SLee Jones  *
12*d1a82001SLee Jones  * ab8500-ext supports the following regulators:
13*d1a82001SLee Jones  * - VextSupply3
14*d1a82001SLee Jones  */
15*d1a82001SLee Jones #include <linux/init.h>
16*d1a82001SLee Jones #include <linux/kernel.h>
17*d1a82001SLee Jones #include <linux/err.h>
18*d1a82001SLee Jones #include <linux/module.h>
19*d1a82001SLee Jones #include <linux/platform_device.h>
20*d1a82001SLee Jones #include <linux/regulator/driver.h>
21*d1a82001SLee Jones #include <linux/regulator/machine.h>
22*d1a82001SLee Jones #include <linux/mfd/abx500.h>
23*d1a82001SLee Jones #include <linux/mfd/abx500/ab8500.h>
24*d1a82001SLee Jones #include <linux/regulator/ab8500.h>
25*d1a82001SLee Jones 
26*d1a82001SLee Jones /**
27*d1a82001SLee Jones  * struct ab8500_ext_regulator_info - ab8500 regulator information
28*d1a82001SLee Jones  * @dev: device pointer
29*d1a82001SLee Jones  * @desc: regulator description
30*d1a82001SLee Jones  * @rdev: regulator device
31*d1a82001SLee Jones  * @is_enabled: status of regulator (on/off)
32*d1a82001SLee Jones  * @update_bank: bank to control on/off
33*d1a82001SLee Jones  * @update_reg: register to control on/off
34*d1a82001SLee Jones  * @update_mask: mask to enable/disable and set mode of regulator
35*d1a82001SLee Jones  * @update_val: bits holding the regulator current mode
36*d1a82001SLee Jones  * @update_val_en: bits to set EN pin active (LPn pin deactive)
37*d1a82001SLee Jones  *                 normally this means high power mode
38*d1a82001SLee Jones  * @update_val_en_lp: bits to set EN pin active and LPn pin active
39*d1a82001SLee Jones  *                    normally this means low power mode
40*d1a82001SLee Jones  * @delay: startup delay in ms
41*d1a82001SLee Jones  */
42*d1a82001SLee Jones struct ab8500_ext_regulator_info {
43*d1a82001SLee Jones 	struct device *dev;
44*d1a82001SLee Jones 	struct regulator_desc desc;
45*d1a82001SLee Jones 	struct regulator_dev *rdev;
46*d1a82001SLee Jones 	bool is_enabled;
47*d1a82001SLee Jones 	u8 update_bank;
48*d1a82001SLee Jones 	u8 update_reg;
49*d1a82001SLee Jones 	u8 update_mask;
50*d1a82001SLee Jones 	u8 update_val;
51*d1a82001SLee Jones 	u8 update_val_en;
52*d1a82001SLee Jones 	u8 update_val_en_lp;
53*d1a82001SLee Jones };
54*d1a82001SLee Jones 
55*d1a82001SLee Jones static int ab8500_ext_regulator_enable(struct regulator_dev *rdev)
56*d1a82001SLee Jones {
57*d1a82001SLee Jones 	int ret;
58*d1a82001SLee Jones 	struct ab8500_ext_regulator_info *info = rdev_get_drvdata(rdev);
59*d1a82001SLee Jones 
60*d1a82001SLee Jones 	if (info == NULL) {
61*d1a82001SLee Jones 		dev_err(rdev_get_dev(rdev), "regulator info null pointer\n");
62*d1a82001SLee Jones 		return -EINVAL;
63*d1a82001SLee Jones 	}
64*d1a82001SLee Jones 
65*d1a82001SLee Jones 	ret = abx500_mask_and_set_register_interruptible(info->dev,
66*d1a82001SLee Jones 		info->update_bank, info->update_reg,
67*d1a82001SLee Jones 		info->update_mask, info->update_val);
68*d1a82001SLee Jones 	if (ret < 0)
69*d1a82001SLee Jones 		dev_err(rdev_get_dev(info->rdev),
70*d1a82001SLee Jones 			"couldn't set enable bits for regulator\n");
71*d1a82001SLee Jones 
72*d1a82001SLee Jones 	info->is_enabled = true;
73*d1a82001SLee Jones 
74*d1a82001SLee Jones 	dev_dbg(rdev_get_dev(rdev), "%s-enable (bank, reg, mask, value):"
75*d1a82001SLee Jones 		" 0x%02x, 0x%02x, 0x%02x, 0x%02x\n",
76*d1a82001SLee Jones 		info->desc.name, info->update_bank, info->update_reg,
77*d1a82001SLee Jones 		info->update_mask, info->update_val);
78*d1a82001SLee Jones 
79*d1a82001SLee Jones 	return ret;
80*d1a82001SLee Jones }
81*d1a82001SLee Jones 
82*d1a82001SLee Jones static int ab8500_ext_regulator_disable(struct regulator_dev *rdev)
83*d1a82001SLee Jones {
84*d1a82001SLee Jones 	int ret;
85*d1a82001SLee Jones 	struct ab8500_ext_regulator_info *info = rdev_get_drvdata(rdev);
86*d1a82001SLee Jones 
87*d1a82001SLee Jones 	if (info == NULL) {
88*d1a82001SLee Jones 		dev_err(rdev_get_dev(rdev), "regulator info null pointer\n");
89*d1a82001SLee Jones 		return -EINVAL;
90*d1a82001SLee Jones 	}
91*d1a82001SLee Jones 
92*d1a82001SLee Jones 	ret = abx500_mask_and_set_register_interruptible(info->dev,
93*d1a82001SLee Jones 		info->update_bank, info->update_reg,
94*d1a82001SLee Jones 		info->update_mask, 0x0);
95*d1a82001SLee Jones 	if (ret < 0)
96*d1a82001SLee Jones 		dev_err(rdev_get_dev(info->rdev),
97*d1a82001SLee Jones 			"couldn't set disable bits for regulator\n");
98*d1a82001SLee Jones 
99*d1a82001SLee Jones 	info->is_enabled = false;
100*d1a82001SLee Jones 
101*d1a82001SLee Jones 	dev_dbg(rdev_get_dev(rdev), "%s-disable (bank, reg, mask, value):"
102*d1a82001SLee Jones 		" 0x%02x, 0x%02x, 0x%02x, 0x%02x\n",
103*d1a82001SLee Jones 		info->desc.name, info->update_bank, info->update_reg,
104*d1a82001SLee Jones 		info->update_mask, 0x0);
105*d1a82001SLee Jones 
106*d1a82001SLee Jones 	return ret;
107*d1a82001SLee Jones }
108*d1a82001SLee Jones 
109*d1a82001SLee Jones static int ab8500_ext_regulator_is_enabled(struct regulator_dev *rdev)
110*d1a82001SLee Jones {
111*d1a82001SLee Jones 	int ret;
112*d1a82001SLee Jones 	struct ab8500_ext_regulator_info *info = rdev_get_drvdata(rdev);
113*d1a82001SLee Jones 	u8 regval;
114*d1a82001SLee Jones 
115*d1a82001SLee Jones 	if (info == NULL) {
116*d1a82001SLee Jones 		dev_err(rdev_get_dev(rdev), "regulator info null pointer\n");
117*d1a82001SLee Jones 		return -EINVAL;
118*d1a82001SLee Jones 	}
119*d1a82001SLee Jones 
120*d1a82001SLee Jones 	ret = abx500_get_register_interruptible(info->dev,
121*d1a82001SLee Jones 		info->update_bank, info->update_reg, &regval);
122*d1a82001SLee Jones 	if (ret < 0) {
123*d1a82001SLee Jones 		dev_err(rdev_get_dev(rdev),
124*d1a82001SLee Jones 			"couldn't read 0x%x register\n", info->update_reg);
125*d1a82001SLee Jones 		return ret;
126*d1a82001SLee Jones 	}
127*d1a82001SLee Jones 
128*d1a82001SLee Jones 	dev_dbg(rdev_get_dev(rdev), "%s-is_enabled (bank, reg, mask, value):"
129*d1a82001SLee Jones 		" 0x%02x, 0x%02x, 0x%02x, 0x%02x\n",
130*d1a82001SLee Jones 		info->desc.name, info->update_bank, info->update_reg,
131*d1a82001SLee Jones 		info->update_mask, regval);
132*d1a82001SLee Jones 
133*d1a82001SLee Jones 	if (regval & info->update_mask)
134*d1a82001SLee Jones 		info->is_enabled = true;
135*d1a82001SLee Jones 	else
136*d1a82001SLee Jones 		info->is_enabled = false;
137*d1a82001SLee Jones 
138*d1a82001SLee Jones 	return info->is_enabled;
139*d1a82001SLee Jones }
140*d1a82001SLee Jones 
141*d1a82001SLee Jones static int ab8500_ext_regulator_set_mode(struct regulator_dev *rdev,
142*d1a82001SLee Jones 					 unsigned int mode)
143*d1a82001SLee Jones {
144*d1a82001SLee Jones 	int ret = 0;
145*d1a82001SLee Jones 	struct ab8500_ext_regulator_info *info = rdev_get_drvdata(rdev);
146*d1a82001SLee Jones 
147*d1a82001SLee Jones 	if (info == NULL) {
148*d1a82001SLee Jones 		dev_err(rdev_get_dev(rdev), "regulator info null pointer\n");
149*d1a82001SLee Jones 		return -EINVAL;
150*d1a82001SLee Jones 	}
151*d1a82001SLee Jones 
152*d1a82001SLee Jones 	switch (mode) {
153*d1a82001SLee Jones 	case REGULATOR_MODE_NORMAL:
154*d1a82001SLee Jones 		info->update_val = info->update_val_hp;
155*d1a82001SLee Jones 		break;
156*d1a82001SLee Jones 	case REGULATOR_MODE_IDLE:
157*d1a82001SLee Jones 		info->update_val = info->update_val_lp;
158*d1a82001SLee Jones 		break;
159*d1a82001SLee Jones 
160*d1a82001SLee Jones 	default:
161*d1a82001SLee Jones 		return -EINVAL;
162*d1a82001SLee Jones 	}
163*d1a82001SLee Jones 
164*d1a82001SLee Jones 	if (info->is_enabled) {
165*d1a82001SLee Jones 		u8 regval;
166*d1a82001SLee Jones 
167*d1a82001SLee Jones 		ret = enable(info, &regval);
168*d1a82001SLee Jones 		if (ret < 0)
169*d1a82001SLee Jones 			dev_err(rdev_get_dev(rdev),
170*d1a82001SLee Jones 				"Could not set regulator mode.\n");
171*d1a82001SLee Jones 
172*d1a82001SLee Jones 		dev_dbg(rdev_get_dev(rdev),
173*d1a82001SLee Jones 			"%s-set_mode (bank, reg, mask, value): "
174*d1a82001SLee Jones 			"0x%x, 0x%x, 0x%x, 0x%x\n",
175*d1a82001SLee Jones 			info->desc.name, info->update_bank, info->update_reg,
176*d1a82001SLee Jones 			info->update_mask, regval);
177*d1a82001SLee Jones 	}
178*d1a82001SLee Jones 
179*d1a82001SLee Jones 	return ret;
180*d1a82001SLee Jones }
181*d1a82001SLee Jones 
182*d1a82001SLee Jones static unsigned int ab8500_ext_regulator_get_mode(struct regulator_dev *rdev)
183*d1a82001SLee Jones {
184*d1a82001SLee Jones 	struct ab8500_ext_regulator_info *info = rdev_get_drvdata(rdev);
185*d1a82001SLee Jones 	int ret;
186*d1a82001SLee Jones 
187*d1a82001SLee Jones 	if (info == NULL) {
188*d1a82001SLee Jones 		dev_err(rdev_get_dev(rdev), "regulator info null pointer\n");
189*d1a82001SLee Jones 		return -EINVAL;
190*d1a82001SLee Jones 	}
191*d1a82001SLee Jones 
192*d1a82001SLee Jones 	if (info->update_val == info->update_val_hp)
193*d1a82001SLee Jones 		ret = REGULATOR_MODE_NORMAL;
194*d1a82001SLee Jones 	else if (info->update_val == info->update_val_lp)
195*d1a82001SLee Jones 		ret = REGULATOR_MODE_IDLE;
196*d1a82001SLee Jones 	else
197*d1a82001SLee Jones 		ret = -EINVAL;
198*d1a82001SLee Jones 
199*d1a82001SLee Jones 	return ret;
200*d1a82001SLee Jones }
201*d1a82001SLee Jones 
202*d1a82001SLee Jones static int ab8500_ext_fixed_get_voltage(struct regulator_dev *rdev)
203*d1a82001SLee Jones {
204*d1a82001SLee Jones 	struct regulation_constraints *regu_constraints = rdev->constraints;
205*d1a82001SLee Jones 
206*d1a82001SLee Jones 	if (regu_constraints == NULL) {
207*d1a82001SLee Jones 		dev_err(rdev_get_dev(rdev), "regulator constraints null pointer\n");
208*d1a82001SLee Jones 		return -EINVAL;
209*d1a82001SLee Jones 	}
210*d1a82001SLee Jones 	if (regu_constraints->min_uV && regu_constraints->max_uV) {
211*d1a82001SLee Jones 		if (regu_constraints->min_uV == regu_constraints->max_uV)
212*d1a82001SLee Jones 			return regu_constraints->min_uV;
213*d1a82001SLee Jones 	}
214*d1a82001SLee Jones 	return -EINVAL;
215*d1a82001SLee Jones }
216*d1a82001SLee Jones 
217*d1a82001SLee Jones static int ab8500_ext_list_voltage(struct regulator_dev *rdev,
218*d1a82001SLee Jones 				   unsigned selector)
219*d1a82001SLee Jones {
220*d1a82001SLee Jones 	struct regulation_constraints *regu_constraints = rdev->constraints;
221*d1a82001SLee Jones 
222*d1a82001SLee Jones 	if (regu_constraints == NULL) {
223*d1a82001SLee Jones 		dev_err(rdev_get_dev(rdev), "regulator constraints null pointer\n");
224*d1a82001SLee Jones 		return -EINVAL;
225*d1a82001SLee Jones 	}
226*d1a82001SLee Jones 	/* return the uV for the fixed regulators */
227*d1a82001SLee Jones 	if (regu_constraints->min_uV && regu_constraints->max_uV) {
228*d1a82001SLee Jones 		if (regu_constraints->min_uV == regu_constraints->max_uV)
229*d1a82001SLee Jones 			return regu_constraints->min_uV;
230*d1a82001SLee Jones 	}
231*d1a82001SLee Jones 	return -EINVAL;
232*d1a82001SLee Jones }
233*d1a82001SLee Jones 
234*d1a82001SLee Jones static struct regulator_ops ab8500_ext_regulator_ops = {
235*d1a82001SLee Jones 	.enable			= ab8500_ext_regulator_enable,
236*d1a82001SLee Jones 	.disable		= ab8500_ext_regulator_disable,
237*d1a82001SLee Jones 	.is_enabled		= ab8500_ext_regulator_is_enabled,
238*d1a82001SLee Jones 	.set_mode		= ab8500_ext_regulator_set_mode,
239*d1a82001SLee Jones 	.get_mode		= ab8500_ext_regulator_get_mode,
240*d1a82001SLee Jones 	.get_voltage		= ab8500_ext_fixed_get_voltage,
241*d1a82001SLee Jones 	.list_voltage		= ab8500_ext_list_voltage,
242*d1a82001SLee Jones };
243*d1a82001SLee Jones 
244*d1a82001SLee Jones 
245*d1a82001SLee Jones static struct ab8500_ext_regulator_info
246*d1a82001SLee Jones 		ab8500_ext_regulator_info[AB8500_NUM_EXT_REGULATORS] = {
247*d1a82001SLee Jones 	[AB8500_EXT_SUPPLY1] = {
248*d1a82001SLee Jones 		.desc = {
249*d1a82001SLee Jones 			.name		= "VEXTSUPPLY1",
250*d1a82001SLee Jones 			.ops		= &ab8500_ext_regulator_ops,
251*d1a82001SLee Jones 			.type		= REGULATOR_VOLTAGE,
252*d1a82001SLee Jones 			.id		= AB8500_EXT_SUPPLY1,
253*d1a82001SLee Jones 			.owner		= THIS_MODULE,
254*d1a82001SLee Jones 			.n_voltages	= 1,
255*d1a82001SLee Jones 		},
256*d1a82001SLee Jones 		.update_bank		= 0x04,
257*d1a82001SLee Jones 		.update_reg		= 0x08,
258*d1a82001SLee Jones 		.update_mask		= 0x03,
259*d1a82001SLee Jones 		.update_val		= 0x01,
260*d1a82001SLee Jones 		.update_val_hp		= 0x01,
261*d1a82001SLee Jones 		.update_val_lp		= 0x03,
262*d1a82001SLee Jones 		.update_val_hw		= 0x02,
263*d1a82001SLee Jones 	},
264*d1a82001SLee Jones 	[AB8500_EXT_SUPPLY2] = {
265*d1a82001SLee Jones 		.desc = {
266*d1a82001SLee Jones 			.name		= "VEXTSUPPLY2",
267*d1a82001SLee Jones 			.ops		= &ab8500_ext_regulator_ops,
268*d1a82001SLee Jones 			.type		= REGULATOR_VOLTAGE,
269*d1a82001SLee Jones 			.id		= AB8500_EXT_SUPPLY2,
270*d1a82001SLee Jones 			.owner		= THIS_MODULE,
271*d1a82001SLee Jones 			.n_voltages	= 1,
272*d1a82001SLee Jones 		},
273*d1a82001SLee Jones 		.update_bank		= 0x04,
274*d1a82001SLee Jones 		.update_reg		= 0x08,
275*d1a82001SLee Jones 		.update_mask		= 0x0c,
276*d1a82001SLee Jones 		.update_val		= 0x04,
277*d1a82001SLee Jones 		.update_val_hp		= 0x04,
278*d1a82001SLee Jones 		.update_val_lp		= 0x0c,
279*d1a82001SLee Jones 		.update_val_hw		= 0x08,
280*d1a82001SLee Jones 	},
281*d1a82001SLee Jones 	[AB8500_EXT_SUPPLY3] = {
282*d1a82001SLee Jones 		.desc = {
283*d1a82001SLee Jones 			.name		= "VEXTSUPPLY3",
284*d1a82001SLee Jones 			.ops		= &ab8500_ext_regulator_ops,
285*d1a82001SLee Jones 			.type		= REGULATOR_VOLTAGE,
286*d1a82001SLee Jones 			.id		= AB8500_EXT_SUPPLY3,
287*d1a82001SLee Jones 			.owner		= THIS_MODULE,
288*d1a82001SLee Jones 			.n_voltages	= 1,
289*d1a82001SLee Jones 		},
290*d1a82001SLee Jones 		.update_bank		= 0x04,
291*d1a82001SLee Jones 		.update_reg		= 0x08,
292*d1a82001SLee Jones 		.update_mask		= 0x30,
293*d1a82001SLee Jones 		.update_val		= 0x10,
294*d1a82001SLee Jones 		.update_val_en		= 0x10,
295*d1a82001SLee Jones 		.update_val_en_lp	= 0x30,
296*d1a82001SLee Jones 	},
297*d1a82001SLee Jones };
298*d1a82001SLee Jones 
299*d1a82001SLee Jones int ab8500_ext_regulator_init(struct platform_device *pdev)
300*d1a82001SLee Jones {
301*d1a82001SLee Jones 	struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent);
302*d1a82001SLee Jones 	struct ab8500_platform_data *ppdata;
303*d1a82001SLee Jones 	struct ab8500_regulator_platform_data *pdata;
304*d1a82001SLee Jones 	struct regulator_config config = { };
305*d1a82001SLee Jones 	int i, err;
306*d1a82001SLee Jones 
307*d1a82001SLee Jones 	if (!ab8500) {
308*d1a82001SLee Jones 		dev_err(&pdev->dev, "null mfd parent\n");
309*d1a82001SLee Jones 		return -EINVAL;
310*d1a82001SLee Jones 	}
311*d1a82001SLee Jones 	ppdata = dev_get_platdata(ab8500->dev);
312*d1a82001SLee Jones 	if (!ppdata) {
313*d1a82001SLee Jones 		dev_err(&pdev->dev, "null parent pdata\n");
314*d1a82001SLee Jones 		return -EINVAL;
315*d1a82001SLee Jones 	}
316*d1a82001SLee Jones 
317*d1a82001SLee Jones 	pdata = ppdata->regulator;
318*d1a82001SLee Jones 	if (!pdata) {
319*d1a82001SLee Jones 		dev_err(&pdev->dev, "null pdata\n");
320*d1a82001SLee Jones 		return -EINVAL;
321*d1a82001SLee Jones 	}
322*d1a82001SLee Jones 
323*d1a82001SLee Jones 	/* make sure the platform data has the correct size */
324*d1a82001SLee Jones 	if (pdata->num_ext_regulator != ARRAY_SIZE(ab8500_ext_regulator_info)) {
325*d1a82001SLee Jones 		dev_err(&pdev->dev, "Configuration error: size mismatch.\n");
326*d1a82001SLee Jones 		return -EINVAL;
327*d1a82001SLee Jones 	}
328*d1a82001SLee Jones 
329*d1a82001SLee Jones 	/* check for AB8500 2.x */
330*d1a82001SLee Jones 	if (abx500_get_chip_id(&pdev->dev) < 0x30) {
331*d1a82001SLee Jones 		struct ab8500_ext_regulator_info *info;
332*d1a82001SLee Jones 
333*d1a82001SLee Jones 		/* VextSupply3LPn is inverted on AB8500 2.x */
334*d1a82001SLee Jones 		info = &ab8500_ext_regulator_info[AB8500_EXT_SUPPLY3];
335*d1a82001SLee Jones 		info->update_val = 0x30;
336*d1a82001SLee Jones 		info->update_val_en = 0x30;
337*d1a82001SLee Jones 		info->update_val_en_lp = 0x10;
338*d1a82001SLee Jones 	}
339*d1a82001SLee Jones 
340*d1a82001SLee Jones 	/* register all regulators */
341*d1a82001SLee Jones 	for (i = 0; i < ARRAY_SIZE(ab8500_ext_regulator_info); i++) {
342*d1a82001SLee Jones 		struct ab8500_ext_regulator_info *info = NULL;
343*d1a82001SLee Jones 
344*d1a82001SLee Jones 		/* assign per-regulator data */
345*d1a82001SLee Jones 		info = &ab8500_ext_regulator_info[i];
346*d1a82001SLee Jones 		info->dev = &pdev->dev;
347*d1a82001SLee Jones 
348*d1a82001SLee Jones 		config.dev = &pdev->dev;
349*d1a82001SLee Jones 		config.init_data = &pdata->ext_regulator[i];
350*d1a82001SLee Jones 		config.driver_data = info;
351*d1a82001SLee Jones 
352*d1a82001SLee Jones 		/* register regulator with framework */
353*d1a82001SLee Jones 		info->rdev = regulator_register(&info->desc, &config);
354*d1a82001SLee Jones 
355*d1a82001SLee Jones 		if (IS_ERR(info->rdev)) {
356*d1a82001SLee Jones 			err = PTR_ERR(info->rdev);
357*d1a82001SLee Jones 			dev_err(&pdev->dev, "failed to register regulator %s\n",
358*d1a82001SLee Jones 					info->desc.name);
359*d1a82001SLee Jones 			/* when we fail, un-register all earlier regulators */
360*d1a82001SLee Jones 			while (--i >= 0) {
361*d1a82001SLee Jones 				info = &ab8500_ext_regulator_info[i];
362*d1a82001SLee Jones 				regulator_unregister(info->rdev);
363*d1a82001SLee Jones 			}
364*d1a82001SLee Jones 			return err;
365*d1a82001SLee Jones 		}
366*d1a82001SLee Jones 
367*d1a82001SLee Jones 		dev_dbg(rdev_get_dev(info->rdev),
368*d1a82001SLee Jones 			"%s-probed\n", info->desc.name);
369*d1a82001SLee Jones 	}
370*d1a82001SLee Jones 
371*d1a82001SLee Jones 	return 0;
372*d1a82001SLee Jones }
373*d1a82001SLee Jones 
374*d1a82001SLee Jones int ab8500_ext_regulator_exit(struct platform_device *pdev)
375*d1a82001SLee Jones {
376*d1a82001SLee Jones 	int i;
377*d1a82001SLee Jones 
378*d1a82001SLee Jones 	for (i = 0; i < ARRAY_SIZE(ab8500_ext_regulator_info); i++) {
379*d1a82001SLee Jones 		struct ab8500_ext_regulator_info *info = NULL;
380*d1a82001SLee Jones 		info = &ab8500_ext_regulator_info[i];
381*d1a82001SLee Jones 
382*d1a82001SLee Jones 		dev_vdbg(rdev_get_dev(info->rdev),
383*d1a82001SLee Jones 			"%s-remove\n", info->desc.name);
384*d1a82001SLee Jones 
385*d1a82001SLee Jones 		regulator_unregister(info->rdev);
386*d1a82001SLee Jones 	}
387*d1a82001SLee Jones 
388*d1a82001SLee Jones 	return 0;
389*d1a82001SLee Jones }
390*d1a82001SLee Jones 
391*d1a82001SLee Jones MODULE_LICENSE("GPL v2");
392*d1a82001SLee Jones MODULE_AUTHOR("Bengt Jonsson <bengt.g.jonsson@stericsson.com>");
393*d1a82001SLee Jones MODULE_DESCRIPTION("AB8500 external regulator driver");
394*d1a82001SLee Jones MODULE_ALIAS("platform:ab8500-ext-regulator");
395