xref: /openbmc/linux/drivers/regulator/bcm590xx-regulator.c (revision 1ac731c529cd4d6adbce134754b51ff7d822b145)
12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2462c9fc5SMatt Porter /*
3462c9fc5SMatt Porter  * Broadcom BCM590xx regulator driver
4462c9fc5SMatt Porter  *
5462c9fc5SMatt Porter  * Copyright 2014 Linaro Limited
6462c9fc5SMatt Porter  * Author: Matt Porter <mporter@linaro.org>
7462c9fc5SMatt Porter  */
8462c9fc5SMatt Porter 
9462c9fc5SMatt Porter #include <linux/err.h>
10462c9fc5SMatt Porter #include <linux/init.h>
11462c9fc5SMatt Porter #include <linux/kernel.h>
12462c9fc5SMatt Porter #include <linux/mfd/bcm590xx.h>
13462c9fc5SMatt Porter #include <linux/module.h>
14462c9fc5SMatt Porter #include <linux/of.h>
15462c9fc5SMatt Porter #include <linux/platform_device.h>
16462c9fc5SMatt Porter #include <linux/regulator/driver.h>
17462c9fc5SMatt Porter #include <linux/regulator/machine.h>
18462c9fc5SMatt Porter #include <linux/regulator/of_regulator.h>
19462c9fc5SMatt Porter #include <linux/slab.h>
20462c9fc5SMatt Porter 
21c6466950SMatt Porter /* I2C slave 0 registers */
22462c9fc5SMatt Porter #define BCM590XX_RFLDOPMCTRL1	0x60
23462c9fc5SMatt Porter #define BCM590XX_IOSR1PMCTRL1	0x7a
24462c9fc5SMatt Porter #define BCM590XX_IOSR2PMCTRL1	0x7c
25462c9fc5SMatt Porter #define BCM590XX_CSRPMCTRL1	0x7e
26462c9fc5SMatt Porter #define BCM590XX_SDSR1PMCTRL1	0x82
27462c9fc5SMatt Porter #define BCM590XX_SDSR2PMCTRL1	0x86
28462c9fc5SMatt Porter #define BCM590XX_MSRPMCTRL1	0x8a
29462c9fc5SMatt Porter #define BCM590XX_VSRPMCTRL1	0x8e
30462c9fc5SMatt Porter #define BCM590XX_RFLDOCTRL	0x96
31462c9fc5SMatt Porter #define BCM590XX_CSRVOUT1	0xc0
32c6466950SMatt Porter 
33c6466950SMatt Porter /* I2C slave 1 registers */
34c6466950SMatt Porter #define BCM590XX_GPLDO5PMCTRL1	0x16
35c6466950SMatt Porter #define BCM590XX_GPLDO6PMCTRL1	0x18
36c6466950SMatt Porter #define BCM590XX_GPLDO1CTRL	0x1a
37c6466950SMatt Porter #define BCM590XX_GPLDO2CTRL	0x1b
38c6466950SMatt Porter #define BCM590XX_GPLDO3CTRL	0x1c
39c6466950SMatt Porter #define BCM590XX_GPLDO4CTRL	0x1d
40c6466950SMatt Porter #define BCM590XX_GPLDO5CTRL	0x1e
41c6466950SMatt Porter #define BCM590XX_GPLDO6CTRL	0x1f
42c6466950SMatt Porter #define BCM590XX_OTG_CTRL	0x40
43c6466950SMatt Porter #define BCM590XX_GPLDO1PMCTRL1	0x57
44c6466950SMatt Porter #define BCM590XX_GPLDO2PMCTRL1	0x59
45c6466950SMatt Porter #define BCM590XX_GPLDO3PMCTRL1	0x5b
46c6466950SMatt Porter #define BCM590XX_GPLDO4PMCTRL1	0x5d
47c6466950SMatt Porter 
48c6466950SMatt Porter #define BCM590XX_REG_ENABLE	BIT(7)
49c6466950SMatt Porter #define BCM590XX_VBUS_ENABLE	BIT(2)
50462c9fc5SMatt Porter #define BCM590XX_LDO_VSEL_MASK	GENMASK(5, 3)
51462c9fc5SMatt Porter #define BCM590XX_SR_VSEL_MASK	GENMASK(5, 0)
52462c9fc5SMatt Porter 
53c6466950SMatt Porter /*
54c6466950SMatt Porter  * RFLDO to VSR regulators are
55c6466950SMatt Porter  * accessed via I2C slave 0
56c6466950SMatt Porter  */
57c6466950SMatt Porter 
58462c9fc5SMatt Porter /* LDO regulator IDs */
59462c9fc5SMatt Porter #define BCM590XX_REG_RFLDO	0
60462c9fc5SMatt Porter #define BCM590XX_REG_CAMLDO1	1
61462c9fc5SMatt Porter #define BCM590XX_REG_CAMLDO2	2
62462c9fc5SMatt Porter #define BCM590XX_REG_SIMLDO1	3
63462c9fc5SMatt Porter #define BCM590XX_REG_SIMLDO2	4
64462c9fc5SMatt Porter #define BCM590XX_REG_SDLDO	5
65462c9fc5SMatt Porter #define BCM590XX_REG_SDXLDO	6
66462c9fc5SMatt Porter #define BCM590XX_REG_MMCLDO1	7
67462c9fc5SMatt Porter #define BCM590XX_REG_MMCLDO2	8
68462c9fc5SMatt Porter #define BCM590XX_REG_AUDLDO	9
69462c9fc5SMatt Porter #define BCM590XX_REG_MICLDO	10
70462c9fc5SMatt Porter #define BCM590XX_REG_USBLDO	11
71462c9fc5SMatt Porter #define BCM590XX_REG_VIBLDO	12
72462c9fc5SMatt Porter 
73462c9fc5SMatt Porter /* DCDC regulator IDs */
74462c9fc5SMatt Porter #define BCM590XX_REG_CSR	13
75462c9fc5SMatt Porter #define BCM590XX_REG_IOSR1	14
76462c9fc5SMatt Porter #define BCM590XX_REG_IOSR2	15
77462c9fc5SMatt Porter #define BCM590XX_REG_MSR	16
78462c9fc5SMatt Porter #define BCM590XX_REG_SDSR1	17
79462c9fc5SMatt Porter #define BCM590XX_REG_SDSR2	18
80462c9fc5SMatt Porter #define BCM590XX_REG_VSR	19
81462c9fc5SMatt Porter 
82c6466950SMatt Porter /*
83c6466950SMatt Porter  * GPLDO1 to VBUS regulators are
84c6466950SMatt Porter  * accessed via I2C slave 1
85c6466950SMatt Porter  */
86c6466950SMatt Porter 
87c6466950SMatt Porter #define BCM590XX_REG_GPLDO1	20
88c6466950SMatt Porter #define BCM590XX_REG_GPLDO2	21
89c6466950SMatt Porter #define BCM590XX_REG_GPLDO3	22
90c6466950SMatt Porter #define BCM590XX_REG_GPLDO4	23
91c6466950SMatt Porter #define BCM590XX_REG_GPLDO5	24
92c6466950SMatt Porter #define BCM590XX_REG_GPLDO6	25
93c6466950SMatt Porter #define BCM590XX_REG_VBUS	26
94c6466950SMatt Porter 
95c6466950SMatt Porter #define BCM590XX_NUM_REGS	27
96462c9fc5SMatt Porter 
97462c9fc5SMatt Porter #define BCM590XX_REG_IS_LDO(n)	(n < BCM590XX_REG_CSR)
98c6466950SMatt Porter #define BCM590XX_REG_IS_GPLDO(n) \
99c6466950SMatt Porter 	((n > BCM590XX_REG_VSR) && (n < BCM590XX_REG_VBUS))
100c6466950SMatt Porter #define BCM590XX_REG_IS_VBUS(n)	(n == BCM590XX_REG_VBUS)
101462c9fc5SMatt Porter 
102462c9fc5SMatt Porter /* LDO group A: supported voltages in microvolts */
103462c9fc5SMatt Porter static const unsigned int ldo_a_table[] = {
104462c9fc5SMatt Porter 	1200000, 1800000, 2500000, 2700000, 2800000,
105462c9fc5SMatt Porter 	2900000, 3000000, 3300000,
106462c9fc5SMatt Porter };
107462c9fc5SMatt Porter 
108462c9fc5SMatt Porter /* LDO group C: supported voltages in microvolts */
109462c9fc5SMatt Porter static const unsigned int ldo_c_table[] = {
110462c9fc5SMatt Porter 	3100000, 1800000, 2500000, 2700000, 2800000,
111462c9fc5SMatt Porter 	2900000, 3000000, 3300000,
112462c9fc5SMatt Porter };
113462c9fc5SMatt Porter 
114636f4a31SGraham Williams static const unsigned int ldo_vbus[] = {
115636f4a31SGraham Williams 	5000000,
116636f4a31SGraham Williams };
117636f4a31SGraham Williams 
118462c9fc5SMatt Porter /* DCDC group CSR: supported voltages in microvolts */
11960ab7f41SMatti Vaittinen static const struct linear_range dcdc_csr_ranges[] = {
120462c9fc5SMatt Porter 	REGULATOR_LINEAR_RANGE(860000, 2, 50, 10000),
121462c9fc5SMatt Porter 	REGULATOR_LINEAR_RANGE(1360000, 51, 55, 20000),
122462c9fc5SMatt Porter 	REGULATOR_LINEAR_RANGE(900000, 56, 63, 0),
123462c9fc5SMatt Porter };
124462c9fc5SMatt Porter 
125462c9fc5SMatt Porter /* DCDC group IOSR1: supported voltages in microvolts */
12660ab7f41SMatti Vaittinen static const struct linear_range dcdc_iosr1_ranges[] = {
127462c9fc5SMatt Porter 	REGULATOR_LINEAR_RANGE(860000, 2, 51, 10000),
128462c9fc5SMatt Porter 	REGULATOR_LINEAR_RANGE(1500000, 52, 52, 0),
129462c9fc5SMatt Porter 	REGULATOR_LINEAR_RANGE(1800000, 53, 53, 0),
130462c9fc5SMatt Porter 	REGULATOR_LINEAR_RANGE(900000, 54, 63, 0),
131462c9fc5SMatt Porter };
132462c9fc5SMatt Porter 
133462c9fc5SMatt Porter /* DCDC group SDSR1: supported voltages in microvolts */
13460ab7f41SMatti Vaittinen static const struct linear_range dcdc_sdsr1_ranges[] = {
135462c9fc5SMatt Porter 	REGULATOR_LINEAR_RANGE(860000, 2, 50, 10000),
136462c9fc5SMatt Porter 	REGULATOR_LINEAR_RANGE(1340000, 51, 51, 0),
137462c9fc5SMatt Porter 	REGULATOR_LINEAR_RANGE(900000, 52, 63, 0),
138462c9fc5SMatt Porter };
139462c9fc5SMatt Porter 
140462c9fc5SMatt Porter struct bcm590xx_info {
141462c9fc5SMatt Porter 	const char *name;
142462c9fc5SMatt Porter 	const char *vin_name;
143462c9fc5SMatt Porter 	u8 n_voltages;
144462c9fc5SMatt Porter 	const unsigned int *volt_table;
145462c9fc5SMatt Porter 	u8 n_linear_ranges;
14660ab7f41SMatti Vaittinen 	const struct linear_range *linear_ranges;
147462c9fc5SMatt Porter };
148462c9fc5SMatt Porter 
149462c9fc5SMatt Porter #define BCM590XX_REG_TABLE(_name, _table) \
150462c9fc5SMatt Porter 	{ \
151462c9fc5SMatt Porter 		.name = #_name, \
152462c9fc5SMatt Porter 		.n_voltages = ARRAY_SIZE(_table), \
153462c9fc5SMatt Porter 		.volt_table = _table, \
154462c9fc5SMatt Porter 	}
155462c9fc5SMatt Porter 
156462c9fc5SMatt Porter #define BCM590XX_REG_RANGES(_name, _ranges) \
157462c9fc5SMatt Porter 	{ \
158462c9fc5SMatt Porter 		.name = #_name, \
1591e791405STim Kryger 		.n_voltages = 64, \
160462c9fc5SMatt Porter 		.n_linear_ranges = ARRAY_SIZE(_ranges), \
161462c9fc5SMatt Porter 		.linear_ranges = _ranges, \
162462c9fc5SMatt Porter 	}
163462c9fc5SMatt Porter 
164462c9fc5SMatt Porter static struct bcm590xx_info bcm590xx_regs[] = {
165462c9fc5SMatt Porter 	BCM590XX_REG_TABLE(rfldo, ldo_a_table),
166462c9fc5SMatt Porter 	BCM590XX_REG_TABLE(camldo1, ldo_c_table),
167462c9fc5SMatt Porter 	BCM590XX_REG_TABLE(camldo2, ldo_c_table),
168462c9fc5SMatt Porter 	BCM590XX_REG_TABLE(simldo1, ldo_a_table),
169462c9fc5SMatt Porter 	BCM590XX_REG_TABLE(simldo2, ldo_a_table),
170462c9fc5SMatt Porter 	BCM590XX_REG_TABLE(sdldo, ldo_c_table),
171462c9fc5SMatt Porter 	BCM590XX_REG_TABLE(sdxldo, ldo_a_table),
172462c9fc5SMatt Porter 	BCM590XX_REG_TABLE(mmcldo1, ldo_a_table),
173462c9fc5SMatt Porter 	BCM590XX_REG_TABLE(mmcldo2, ldo_a_table),
174462c9fc5SMatt Porter 	BCM590XX_REG_TABLE(audldo, ldo_a_table),
175462c9fc5SMatt Porter 	BCM590XX_REG_TABLE(micldo, ldo_a_table),
176462c9fc5SMatt Porter 	BCM590XX_REG_TABLE(usbldo, ldo_a_table),
177462c9fc5SMatt Porter 	BCM590XX_REG_TABLE(vibldo, ldo_c_table),
178462c9fc5SMatt Porter 	BCM590XX_REG_RANGES(csr, dcdc_csr_ranges),
179462c9fc5SMatt Porter 	BCM590XX_REG_RANGES(iosr1, dcdc_iosr1_ranges),
180462c9fc5SMatt Porter 	BCM590XX_REG_RANGES(iosr2, dcdc_iosr1_ranges),
181462c9fc5SMatt Porter 	BCM590XX_REG_RANGES(msr, dcdc_iosr1_ranges),
182462c9fc5SMatt Porter 	BCM590XX_REG_RANGES(sdsr1, dcdc_sdsr1_ranges),
183462c9fc5SMatt Porter 	BCM590XX_REG_RANGES(sdsr2, dcdc_iosr1_ranges),
184462c9fc5SMatt Porter 	BCM590XX_REG_RANGES(vsr, dcdc_iosr1_ranges),
185c6466950SMatt Porter 	BCM590XX_REG_TABLE(gpldo1, ldo_a_table),
186c6466950SMatt Porter 	BCM590XX_REG_TABLE(gpldo2, ldo_a_table),
187c6466950SMatt Porter 	BCM590XX_REG_TABLE(gpldo3, ldo_a_table),
188c6466950SMatt Porter 	BCM590XX_REG_TABLE(gpldo4, ldo_a_table),
189c6466950SMatt Porter 	BCM590XX_REG_TABLE(gpldo5, ldo_a_table),
190c6466950SMatt Porter 	BCM590XX_REG_TABLE(gpldo6, ldo_a_table),
191636f4a31SGraham Williams 	BCM590XX_REG_TABLE(vbus, ldo_vbus),
192462c9fc5SMatt Porter };
193462c9fc5SMatt Porter 
194462c9fc5SMatt Porter struct bcm590xx_reg {
195462c9fc5SMatt Porter 	struct regulator_desc *desc;
196462c9fc5SMatt Porter 	struct bcm590xx *mfd;
197462c9fc5SMatt Porter };
198462c9fc5SMatt Porter 
bcm590xx_get_vsel_register(int id)199462c9fc5SMatt Porter static int bcm590xx_get_vsel_register(int id)
200462c9fc5SMatt Porter {
201462c9fc5SMatt Porter 	if (BCM590XX_REG_IS_LDO(id))
202462c9fc5SMatt Porter 		return BCM590XX_RFLDOCTRL + id;
203c6466950SMatt Porter 	else if (BCM590XX_REG_IS_GPLDO(id))
204c6466950SMatt Porter 		return BCM590XX_GPLDO1CTRL + id;
205462c9fc5SMatt Porter 	else
206462c9fc5SMatt Porter 		return BCM590XX_CSRVOUT1 + (id - BCM590XX_REG_CSR) * 3;
207462c9fc5SMatt Porter }
208462c9fc5SMatt Porter 
bcm590xx_get_enable_register(int id)209462c9fc5SMatt Porter static int bcm590xx_get_enable_register(int id)
210462c9fc5SMatt Porter {
211462c9fc5SMatt Porter 	int reg = 0;
212462c9fc5SMatt Porter 
213462c9fc5SMatt Porter 	if (BCM590XX_REG_IS_LDO(id))
214462c9fc5SMatt Porter 		reg = BCM590XX_RFLDOPMCTRL1 + id * 2;
215c6466950SMatt Porter 	else if (BCM590XX_REG_IS_GPLDO(id))
216c6466950SMatt Porter 		reg = BCM590XX_GPLDO1PMCTRL1 + id * 2;
217462c9fc5SMatt Porter 	else
218462c9fc5SMatt Porter 		switch (id) {
219462c9fc5SMatt Porter 		case BCM590XX_REG_CSR:
220462c9fc5SMatt Porter 			reg = BCM590XX_CSRPMCTRL1;
221462c9fc5SMatt Porter 			break;
222462c9fc5SMatt Porter 		case BCM590XX_REG_IOSR1:
223462c9fc5SMatt Porter 			reg = BCM590XX_IOSR1PMCTRL1;
224462c9fc5SMatt Porter 			break;
225462c9fc5SMatt Porter 		case BCM590XX_REG_IOSR2:
226462c9fc5SMatt Porter 			reg = BCM590XX_IOSR2PMCTRL1;
227462c9fc5SMatt Porter 			break;
228462c9fc5SMatt Porter 		case BCM590XX_REG_MSR:
229462c9fc5SMatt Porter 			reg = BCM590XX_MSRPMCTRL1;
230462c9fc5SMatt Porter 			break;
231462c9fc5SMatt Porter 		case BCM590XX_REG_SDSR1:
232462c9fc5SMatt Porter 			reg = BCM590XX_SDSR1PMCTRL1;
233462c9fc5SMatt Porter 			break;
234462c9fc5SMatt Porter 		case BCM590XX_REG_SDSR2:
235462c9fc5SMatt Porter 			reg = BCM590XX_SDSR2PMCTRL1;
236462c9fc5SMatt Porter 			break;
237d6afa2beSAxel Lin 		case BCM590XX_REG_VSR:
238d6afa2beSAxel Lin 			reg = BCM590XX_VSRPMCTRL1;
239d6afa2beSAxel Lin 			break;
240c6466950SMatt Porter 		case BCM590XX_REG_VBUS:
241c6466950SMatt Porter 			reg = BCM590XX_OTG_CTRL;
242d6afa2beSAxel Lin 			break;
243f3f400e7SJavier Martinez Canillas 		}
244462c9fc5SMatt Porter 
245c6466950SMatt Porter 
246462c9fc5SMatt Porter 	return reg;
247462c9fc5SMatt Porter }
248462c9fc5SMatt Porter 
24920f860c1SBhumika Goyal static const struct regulator_ops bcm590xx_ops_ldo = {
250462c9fc5SMatt Porter 	.is_enabled		= regulator_is_enabled_regmap,
251462c9fc5SMatt Porter 	.enable			= regulator_enable_regmap,
252462c9fc5SMatt Porter 	.disable		= regulator_disable_regmap,
253462c9fc5SMatt Porter 	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
254462c9fc5SMatt Porter 	.set_voltage_sel	= regulator_set_voltage_sel_regmap,
255462c9fc5SMatt Porter 	.list_voltage		= regulator_list_voltage_table,
256462c9fc5SMatt Porter 	.map_voltage		= regulator_map_voltage_iterate,
257462c9fc5SMatt Porter };
258462c9fc5SMatt Porter 
25920f860c1SBhumika Goyal static const struct regulator_ops bcm590xx_ops_dcdc = {
260462c9fc5SMatt Porter 	.is_enabled		= regulator_is_enabled_regmap,
261462c9fc5SMatt Porter 	.enable			= regulator_enable_regmap,
262462c9fc5SMatt Porter 	.disable		= regulator_disable_regmap,
263462c9fc5SMatt Porter 	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
264462c9fc5SMatt Porter 	.set_voltage_sel	= regulator_set_voltage_sel_regmap,
265462c9fc5SMatt Porter 	.list_voltage		= regulator_list_voltage_linear_range,
266462c9fc5SMatt Porter 	.map_voltage		= regulator_map_voltage_linear_range,
267462c9fc5SMatt Porter };
268462c9fc5SMatt Porter 
26920f860c1SBhumika Goyal static const struct regulator_ops bcm590xx_ops_vbus = {
270c6466950SMatt Porter 	.is_enabled		= regulator_is_enabled_regmap,
271c6466950SMatt Porter 	.enable			= regulator_enable_regmap,
272c6466950SMatt Porter 	.disable		= regulator_disable_regmap,
273c6466950SMatt Porter };
274c6466950SMatt Porter 
bcm590xx_probe(struct platform_device * pdev)275462c9fc5SMatt Porter static int bcm590xx_probe(struct platform_device *pdev)
276462c9fc5SMatt Porter {
277462c9fc5SMatt Porter 	struct bcm590xx *bcm590xx = dev_get_drvdata(pdev->dev.parent);
278462c9fc5SMatt Porter 	struct bcm590xx_reg *pmu;
279462c9fc5SMatt Porter 	struct regulator_config config = { };
280462c9fc5SMatt Porter 	struct bcm590xx_info *info;
281462c9fc5SMatt Porter 	struct regulator_dev *rdev;
282462c9fc5SMatt Porter 	int i;
283462c9fc5SMatt Porter 
284462c9fc5SMatt Porter 	pmu = devm_kzalloc(&pdev->dev, sizeof(*pmu), GFP_KERNEL);
285c969faadSJingoo Han 	if (!pmu)
286462c9fc5SMatt Porter 		return -ENOMEM;
287462c9fc5SMatt Porter 
288462c9fc5SMatt Porter 	pmu->mfd = bcm590xx;
289462c9fc5SMatt Porter 
290462c9fc5SMatt Porter 	platform_set_drvdata(pdev, pmu);
291462c9fc5SMatt Porter 
292a86854d0SKees Cook 	pmu->desc = devm_kcalloc(&pdev->dev,
293a86854d0SKees Cook 				 BCM590XX_NUM_REGS,
294a86854d0SKees Cook 				 sizeof(struct regulator_desc),
295a86854d0SKees Cook 				 GFP_KERNEL);
296c969faadSJingoo Han 	if (!pmu->desc)
297462c9fc5SMatt Porter 		return -ENOMEM;
298462c9fc5SMatt Porter 
299462c9fc5SMatt Porter 	info = bcm590xx_regs;
300462c9fc5SMatt Porter 
301462c9fc5SMatt Porter 	for (i = 0; i < BCM590XX_NUM_REGS; i++, info++) {
302462c9fc5SMatt Porter 		/* Register the regulators */
303462c9fc5SMatt Porter 		pmu->desc[i].name = info->name;
304a4e73625SAxel Lin 		pmu->desc[i].of_match = of_match_ptr(info->name);
305a4e73625SAxel Lin 		pmu->desc[i].regulators_node = of_match_ptr("regulators");
306462c9fc5SMatt Porter 		pmu->desc[i].supply_name = info->vin_name;
307462c9fc5SMatt Porter 		pmu->desc[i].id = i;
308462c9fc5SMatt Porter 		pmu->desc[i].volt_table = info->volt_table;
309462c9fc5SMatt Porter 		pmu->desc[i].n_voltages = info->n_voltages;
310462c9fc5SMatt Porter 		pmu->desc[i].linear_ranges = info->linear_ranges;
311462c9fc5SMatt Porter 		pmu->desc[i].n_linear_ranges = info->n_linear_ranges;
312462c9fc5SMatt Porter 
313c6466950SMatt Porter 		if ((BCM590XX_REG_IS_LDO(i)) || (BCM590XX_REG_IS_GPLDO(i))) {
314462c9fc5SMatt Porter 			pmu->desc[i].ops = &bcm590xx_ops_ldo;
315462c9fc5SMatt Porter 			pmu->desc[i].vsel_mask = BCM590XX_LDO_VSEL_MASK;
316c6466950SMatt Porter 		} else if (BCM590XX_REG_IS_VBUS(i))
317c6466950SMatt Porter 			pmu->desc[i].ops = &bcm590xx_ops_vbus;
318c6466950SMatt Porter 		else {
319462c9fc5SMatt Porter 			pmu->desc[i].ops = &bcm590xx_ops_dcdc;
320462c9fc5SMatt Porter 			pmu->desc[i].vsel_mask = BCM590XX_SR_VSEL_MASK;
321462c9fc5SMatt Porter 		}
322462c9fc5SMatt Porter 
323c6466950SMatt Porter 		if (BCM590XX_REG_IS_VBUS(i))
324c6466950SMatt Porter 			pmu->desc[i].enable_mask = BCM590XX_VBUS_ENABLE;
325c6466950SMatt Porter 		else {
326462c9fc5SMatt Porter 			pmu->desc[i].vsel_reg = bcm590xx_get_vsel_register(i);
327462c9fc5SMatt Porter 			pmu->desc[i].enable_is_inverted = true;
328462c9fc5SMatt Porter 			pmu->desc[i].enable_mask = BCM590XX_REG_ENABLE;
329c6466950SMatt Porter 		}
330462c9fc5SMatt Porter 		pmu->desc[i].enable_reg = bcm590xx_get_enable_register(i);
331462c9fc5SMatt Porter 		pmu->desc[i].type = REGULATOR_VOLTAGE;
332462c9fc5SMatt Porter 		pmu->desc[i].owner = THIS_MODULE;
333462c9fc5SMatt Porter 
334462c9fc5SMatt Porter 		config.dev = bcm590xx->dev;
335462c9fc5SMatt Porter 		config.driver_data = pmu;
336c6466950SMatt Porter 		if (BCM590XX_REG_IS_GPLDO(i) || BCM590XX_REG_IS_VBUS(i))
337c6466950SMatt Porter 			config.regmap = bcm590xx->regmap_sec;
338c6466950SMatt Porter 		else
339c6466950SMatt Porter 			config.regmap = bcm590xx->regmap_pri;
340462c9fc5SMatt Porter 
341462c9fc5SMatt Porter 		rdev = devm_regulator_register(&pdev->dev, &pmu->desc[i],
342462c9fc5SMatt Porter 					       &config);
343462c9fc5SMatt Porter 		if (IS_ERR(rdev)) {
344462c9fc5SMatt Porter 			dev_err(bcm590xx->dev,
345462c9fc5SMatt Porter 				"failed to register %s regulator\n",
346462c9fc5SMatt Porter 				pdev->name);
347462c9fc5SMatt Porter 			return PTR_ERR(rdev);
348462c9fc5SMatt Porter 		}
349462c9fc5SMatt Porter 	}
350462c9fc5SMatt Porter 
351462c9fc5SMatt Porter 	return 0;
352462c9fc5SMatt Porter }
353462c9fc5SMatt Porter 
354462c9fc5SMatt Porter static struct platform_driver bcm590xx_regulator_driver = {
355462c9fc5SMatt Porter 	.driver = {
356462c9fc5SMatt Porter 		.name = "bcm590xx-vregs",
357*259b93b2SDouglas Anderson 		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
358462c9fc5SMatt Porter 	},
359462c9fc5SMatt Porter 	.probe = bcm590xx_probe,
360462c9fc5SMatt Porter };
361462c9fc5SMatt Porter module_platform_driver(bcm590xx_regulator_driver);
362462c9fc5SMatt Porter 
363462c9fc5SMatt Porter MODULE_AUTHOR("Matt Porter <mporter@linaro.org>");
364462c9fc5SMatt Porter MODULE_DESCRIPTION("BCM590xx voltage regulator driver");
365462c9fc5SMatt Porter MODULE_LICENSE("GPL v2");
366c9347431SAxel Lin MODULE_ALIAS("platform:bcm590xx-vregs");
367