xref: /linux/drivers/regulator/tps6586x-regulator.c (revision 10835600cf8f3459cb4420fc2a6b9f57bad15307)
149610235SMike Rapoport /*
249610235SMike Rapoport  * Regulator driver for TI TPS6586x
349610235SMike Rapoport  *
449610235SMike Rapoport  * Copyright (C) 2010 Compulab Ltd.
549610235SMike Rapoport  * Author: Mike Rapoport <mike@compulab.co.il>
649610235SMike Rapoport  *
749610235SMike Rapoport  * Based on da903x
849610235SMike Rapoport  * Copyright (C) 2006-2008 Marvell International Ltd.
949610235SMike Rapoport  * Copyright (C) 2008 Compulab Ltd.
1049610235SMike Rapoport  *
1149610235SMike Rapoport  * This program is free software; you can redistribute it and/or modify
1249610235SMike Rapoport  * it under the terms of the GNU General Public License version 2 as
1349610235SMike Rapoport  * published by the Free Software Foundation.
1449610235SMike Rapoport  */
1549610235SMike Rapoport 
1649610235SMike Rapoport #include <linux/kernel.h>
1765602c32SPaul Gortmaker #include <linux/module.h>
1849610235SMike Rapoport #include <linux/init.h>
1949610235SMike Rapoport #include <linux/err.h>
2064e48160SLaxman Dewangan #include <linux/of.h>
2149610235SMike Rapoport #include <linux/slab.h>
2249610235SMike Rapoport #include <linux/platform_device.h>
2349610235SMike Rapoport #include <linux/regulator/driver.h>
2449610235SMike Rapoport #include <linux/regulator/machine.h>
2564e48160SLaxman Dewangan #include <linux/regulator/of_regulator.h>
2649610235SMike Rapoport #include <linux/mfd/tps6586x.h>
2749610235SMike Rapoport 
2849610235SMike Rapoport /* supply control and voltage setting  */
2949610235SMike Rapoport #define TPS6586X_SUPPLYENA	0x10
3049610235SMike Rapoport #define TPS6586X_SUPPLYENB	0x11
3149610235SMike Rapoport #define TPS6586X_SUPPLYENC	0x12
3249610235SMike Rapoport #define TPS6586X_SUPPLYEND	0x13
3349610235SMike Rapoport #define TPS6586X_SUPPLYENE	0x14
3449610235SMike Rapoport #define TPS6586X_VCC1		0x20
3549610235SMike Rapoport #define TPS6586X_VCC2		0x21
3649610235SMike Rapoport #define TPS6586X_SM1V1		0x23
3749610235SMike Rapoport #define TPS6586X_SM1V2		0x24
3849610235SMike Rapoport #define TPS6586X_SM1SL		0x25
3949610235SMike Rapoport #define TPS6586X_SM0V1		0x26
4049610235SMike Rapoport #define TPS6586X_SM0V2		0x27
4149610235SMike Rapoport #define TPS6586X_SM0SL		0x28
4249610235SMike Rapoport #define TPS6586X_LDO2AV1	0x29
4349610235SMike Rapoport #define TPS6586X_LDO2AV2	0x2A
4449610235SMike Rapoport #define TPS6586X_LDO2BV1	0x2F
4549610235SMike Rapoport #define TPS6586X_LDO2BV2	0x30
4649610235SMike Rapoport #define TPS6586X_LDO4V1		0x32
4749610235SMike Rapoport #define TPS6586X_LDO4V2		0x33
4849610235SMike Rapoport 
4949610235SMike Rapoport /* converter settings  */
5049610235SMike Rapoport #define TPS6586X_SUPPLYV1	0x41
5149610235SMike Rapoport #define TPS6586X_SUPPLYV2	0x42
5249610235SMike Rapoport #define TPS6586X_SUPPLYV3	0x43
5349610235SMike Rapoport #define TPS6586X_SUPPLYV4	0x44
5449610235SMike Rapoport #define TPS6586X_SUPPLYV5	0x45
5549610235SMike Rapoport #define TPS6586X_SUPPLYV6	0x46
5649610235SMike Rapoport #define TPS6586X_SMODE1		0x47
5749610235SMike Rapoport #define TPS6586X_SMODE2		0x48
5849610235SMike Rapoport 
5949610235SMike Rapoport struct tps6586x_regulator {
6049610235SMike Rapoport 	struct regulator_desc desc;
6149610235SMike Rapoport 
6249610235SMike Rapoport 	int enable_bit[2];
6349610235SMike Rapoport 	int enable_reg[2];
6449610235SMike Rapoport 
6549610235SMike Rapoport 	/* for DVM regulators */
6649610235SMike Rapoport 	int go_reg;
6749610235SMike Rapoport 	int go_bit;
6849610235SMike Rapoport };
6949610235SMike Rapoport 
7049610235SMike Rapoport static inline struct device *to_tps6586x_dev(struct regulator_dev *rdev)
7149610235SMike Rapoport {
727c7fac30SLaxman Dewangan 	return rdev_get_dev(rdev)->parent;
7349610235SMike Rapoport }
7449610235SMike Rapoport 
75eed06517SAxel Lin static int tps6586x_set_voltage_sel(struct regulator_dev *rdev,
76eed06517SAxel Lin 				    unsigned selector)
7749610235SMike Rapoport {
7849610235SMike Rapoport 	struct tps6586x_regulator *ri = rdev_get_drvdata(rdev);
7949610235SMike Rapoport 	struct device *parent = to_tps6586x_dev(rdev);
80eed06517SAxel Lin 	int ret, val, rid = rdev_get_id(rdev);
81eed06517SAxel Lin 	uint8_t mask;
8249610235SMike Rapoport 
837c7475c0SAxel Lin 	val = selector << (ffs(rdev->desc->vsel_mask) - 1);
847c7475c0SAxel Lin 	mask = rdev->desc->vsel_mask;
85eed06517SAxel Lin 
867c7475c0SAxel Lin 	ret = tps6586x_update(parent, rdev->desc->vsel_reg, val, mask);
87eed06517SAxel Lin 	if (ret)
88eed06517SAxel Lin 		return ret;
89eed06517SAxel Lin 
90eed06517SAxel Lin 	/* Update go bit for DVM regulators */
91eed06517SAxel Lin 	switch (rid) {
92eed06517SAxel Lin 	case TPS6586X_ID_LDO_2:
93eed06517SAxel Lin 	case TPS6586X_ID_LDO_4:
94eed06517SAxel Lin 	case TPS6586X_ID_SM_0:
95eed06517SAxel Lin 	case TPS6586X_ID_SM_1:
96eed06517SAxel Lin 		ret = tps6586x_set_bits(parent, ri->go_reg, 1 << ri->go_bit);
97eed06517SAxel Lin 		break;
98eed06517SAxel Lin 	}
99eed06517SAxel Lin 	return ret;
10049610235SMike Rapoport }
10149610235SMike Rapoport 
102e1816235SAxel Lin static struct regulator_ops tps6586x_regulator_ops = {
103f4647037SAxel Lin 	.list_voltage = regulator_list_voltage_table,
1047c7475c0SAxel Lin 	.get_voltage_sel = regulator_get_voltage_sel_regmap,
105eed06517SAxel Lin 	.set_voltage_sel = tps6586x_set_voltage_sel,
10649610235SMike Rapoport 
1077c7475c0SAxel Lin 	.is_enabled = regulator_is_enabled_regmap,
1087c7475c0SAxel Lin 	.enable = regulator_enable_regmap,
1097c7475c0SAxel Lin 	.disable = regulator_disable_regmap,
11049610235SMike Rapoport };
11149610235SMike Rapoport 
1129394b80cSLaxman Dewangan static struct regulator_ops tps6586x_sys_regulator_ops = {
11349610235SMike Rapoport };
11449610235SMike Rapoport 
115f4647037SAxel Lin static const unsigned int tps6586x_ldo0_voltages[] = {
116f4647037SAxel Lin 	1200000, 1500000, 1800000, 2500000, 2700000, 2850000, 3100000, 3300000,
11749610235SMike Rapoport };
11849610235SMike Rapoport 
119f4647037SAxel Lin static const unsigned int tps6586x_ldo4_voltages[] = {
120f4647037SAxel Lin 	1700000, 1725000, 1750000, 1775000, 1800000, 1825000, 1850000, 1875000,
121f4647037SAxel Lin 	1900000, 1925000, 1950000, 1975000, 2000000, 2025000, 2050000, 2075000,
122f4647037SAxel Lin 	2100000, 2125000, 2150000, 2175000, 2200000, 2225000, 2250000, 2275000,
123f4647037SAxel Lin 	2300000, 2325000, 2350000, 2375000, 2400000, 2425000, 2450000, 2475000,
12449610235SMike Rapoport };
12549610235SMike Rapoport 
126f4647037SAxel Lin static const unsigned int tps6586x_ldo_voltages[] = {
127f4647037SAxel Lin 	1250000, 1500000, 1800000, 2500000, 2700000, 2850000, 3100000, 3300000,
1284cc2e393SGary King };
1294cc2e393SGary King 
130f4647037SAxel Lin static const unsigned int tps6586x_sm2_voltages[] = {
131f4647037SAxel Lin 	3000000, 3050000, 3100000, 3150000, 3200000, 3250000, 3300000, 3350000,
132f4647037SAxel Lin 	3400000, 3450000, 3500000, 3550000, 3600000, 3650000, 3700000, 3750000,
133f4647037SAxel Lin 	3800000, 3850000, 3900000, 3950000, 4000000, 4050000, 4100000, 4150000,
134f4647037SAxel Lin 	4200000, 4250000, 4300000, 4350000, 4400000, 4450000, 4500000, 4550000,
135f4647037SAxel Lin };
136f4647037SAxel Lin 
137f4647037SAxel Lin static const unsigned int tps6586x_dvm_voltages[] = {
138f4647037SAxel Lin 	 725000,  750000,  775000,  800000,  825000,  850000,  875000,  900000,
139f4647037SAxel Lin 	 925000,  950000,  975000, 1000000, 1025000, 1050000, 1075000, 1100000,
140f4647037SAxel Lin 	1125000, 1150000, 1175000, 1200000, 1225000, 1250000, 1275000, 1300000,
141f4647037SAxel Lin 	1325000, 1350000, 1375000, 1400000, 1425000, 1450000, 1475000, 1500000,
14249610235SMike Rapoport };
14349610235SMike Rapoport 
1447c7fac30SLaxman Dewangan #define TPS6586X_REGULATOR(_id, _pin_name, vdata, vreg, shift, nbits,	\
14564db657bSDanny Huang 			   ereg0, ebit0, ereg1, ebit1)			\
14649610235SMike Rapoport 	.desc	= {							\
1477c7fac30SLaxman Dewangan 		.supply_name = _pin_name,				\
14849610235SMike Rapoport 		.name	= "REG-" #_id,					\
149e1816235SAxel Lin 		.ops	= &tps6586x_regulator_ops,			\
15049610235SMike Rapoport 		.type	= REGULATOR_VOLTAGE,				\
15149610235SMike Rapoport 		.id	= TPS6586X_ID_##_id,				\
15249610235SMike Rapoport 		.n_voltages = ARRAY_SIZE(tps6586x_##vdata##_voltages),	\
153f4647037SAxel Lin 		.volt_table = tps6586x_##vdata##_voltages,		\
15449610235SMike Rapoport 		.owner	= THIS_MODULE,					\
1557c7475c0SAxel Lin 		.enable_reg = TPS6586X_SUPPLY##ereg0,			\
1567c7475c0SAxel Lin 		.enable_mask = 1 << (ebit0),				\
1577c7475c0SAxel Lin 		.vsel_reg = TPS6586X_##vreg,				\
1587c7475c0SAxel Lin 		.vsel_mask = ((1 << (nbits)) - 1) << (shift),		\
15949610235SMike Rapoport 	},								\
16049610235SMike Rapoport 	.enable_reg[0]	= TPS6586X_SUPPLY##ereg0,			\
16149610235SMike Rapoport 	.enable_bit[0]	= (ebit0),					\
16249610235SMike Rapoport 	.enable_reg[1]	= TPS6586X_SUPPLY##ereg1,			\
163f4647037SAxel Lin 	.enable_bit[1]	= (ebit1),
16464db657bSDanny Huang 
16564db657bSDanny Huang #define TPS6586X_REGULATOR_DVM_GOREG(goreg, gobit)			\
16664db657bSDanny Huang 	.go_reg = TPS6586X_##goreg,					\
16764db657bSDanny Huang 	.go_bit = (gobit),
16849610235SMike Rapoport 
1697c7fac30SLaxman Dewangan #define TPS6586X_LDO(_id, _pname, vdata, vreg, shift, nbits,		\
17049610235SMike Rapoport 		     ereg0, ebit0, ereg1, ebit1)			\
17164db657bSDanny Huang {									\
1727c7fac30SLaxman Dewangan 	TPS6586X_REGULATOR(_id, _pname, vdata, vreg, shift, nbits,	\
17364db657bSDanny Huang 			   ereg0, ebit0, ereg1, ebit1)			\
17464db657bSDanny Huang }
17549610235SMike Rapoport 
1767c7fac30SLaxman Dewangan #define TPS6586X_DVM(_id, _pname, vdata, vreg, shift, nbits,		\
17749610235SMike Rapoport 		     ereg0, ebit0, ereg1, ebit1, goreg, gobit)		\
17864db657bSDanny Huang {									\
1797c7fac30SLaxman Dewangan 	TPS6586X_REGULATOR(_id, _pname, vdata, vreg, shift, nbits,	\
18064db657bSDanny Huang 			   ereg0, ebit0, ereg1, ebit1)			\
18164db657bSDanny Huang 	TPS6586X_REGULATOR_DVM_GOREG(goreg, gobit)			\
18264db657bSDanny Huang }
18349610235SMike Rapoport 
1849394b80cSLaxman Dewangan #define TPS6586X_SYS_REGULATOR()					\
1859394b80cSLaxman Dewangan {									\
1869394b80cSLaxman Dewangan 	.desc	= {							\
1879394b80cSLaxman Dewangan 		.supply_name = "sys",					\
1889394b80cSLaxman Dewangan 		.name	= "REG-SYS",					\
1899394b80cSLaxman Dewangan 		.ops	= &tps6586x_sys_regulator_ops,			\
1909394b80cSLaxman Dewangan 		.type	= REGULATOR_VOLTAGE,				\
1919394b80cSLaxman Dewangan 		.id	= TPS6586X_ID_SYS,				\
1929394b80cSLaxman Dewangan 		.owner	= THIS_MODULE,					\
1939394b80cSLaxman Dewangan 	},								\
1949394b80cSLaxman Dewangan }
1959394b80cSLaxman Dewangan 
19649610235SMike Rapoport static struct tps6586x_regulator tps6586x_regulator[] = {
1979394b80cSLaxman Dewangan 	TPS6586X_SYS_REGULATOR(),
1987c7fac30SLaxman Dewangan 	TPS6586X_LDO(LDO_0, "vinldo01", ldo0, SUPPLYV1, 5, 3, ENC, 0, END, 0),
1997c7fac30SLaxman Dewangan 	TPS6586X_LDO(LDO_3, "vinldo23", ldo, SUPPLYV4, 0, 3, ENC, 2, END, 2),
2009394b80cSLaxman Dewangan 	TPS6586X_LDO(LDO_5, "REG-SYS", ldo, SUPPLYV6, 0, 3, ENE, 6, ENE, 6),
2017c7fac30SLaxman Dewangan 	TPS6586X_LDO(LDO_6, "vinldo678", ldo, SUPPLYV3, 0, 3, ENC, 4, END, 4),
2027c7fac30SLaxman Dewangan 	TPS6586X_LDO(LDO_7, "vinldo678", ldo, SUPPLYV3, 3, 3, ENC, 5, END, 5),
2037c7fac30SLaxman Dewangan 	TPS6586X_LDO(LDO_8, "vinldo678", ldo, SUPPLYV2, 5, 3, ENC, 6, END, 6),
2047c7fac30SLaxman Dewangan 	TPS6586X_LDO(LDO_9, "vinldo9", ldo, SUPPLYV6, 3, 3, ENE, 7, ENE, 7),
2059394b80cSLaxman Dewangan 	TPS6586X_LDO(LDO_RTC, "REG-SYS", ldo, SUPPLYV4, 3, 3, V4, 7, V4, 7),
2067c7fac30SLaxman Dewangan 	TPS6586X_LDO(LDO_1, "vinldo01", dvm, SUPPLYV1, 0, 5, ENC, 1, END, 1),
2077f852e05SLaxman Dewangan 	TPS6586X_LDO(SM_2, "vin-sm2", sm2, SUPPLYV2, 0, 5, ENC, 7, END, 7),
20849610235SMike Rapoport 
2097c7fac30SLaxman Dewangan 	TPS6586X_DVM(LDO_2, "vinldo23", dvm, LDO2BV1, 0, 5, ENA, 3,
2107c7fac30SLaxman Dewangan 					ENB, 3, VCC2, 6),
2117c7fac30SLaxman Dewangan 	TPS6586X_DVM(LDO_4, "vinldo4", ldo4, LDO4V1, 0, 5, ENC, 3,
2127c7fac30SLaxman Dewangan 					END, 3, VCC1, 6),
2137f852e05SLaxman Dewangan 	TPS6586X_DVM(SM_0, "vin-sm0", dvm, SM0V1, 0, 5, ENA, 1,
2147f852e05SLaxman Dewangan 					ENB, 1, VCC1, 2),
2157f852e05SLaxman Dewangan 	TPS6586X_DVM(SM_1, "vin-sm1", dvm, SM1V1, 0, 5, ENA, 0,
2167f852e05SLaxman Dewangan 					ENB, 0, VCC1, 0),
21749610235SMike Rapoport };
21849610235SMike Rapoport 
21949610235SMike Rapoport /*
22049610235SMike Rapoport  * TPS6586X has 2 enable bits that are OR'ed to determine the actual
22149610235SMike Rapoport  * regulator state. Clearing one of this bits allows switching
22249610235SMike Rapoport  * regulator on and of with single register write.
22349610235SMike Rapoport  */
22449610235SMike Rapoport static inline int tps6586x_regulator_preinit(struct device *parent,
22549610235SMike Rapoport 					     struct tps6586x_regulator *ri)
22649610235SMike Rapoport {
22749610235SMike Rapoport 	uint8_t val1, val2;
22849610235SMike Rapoport 	int ret;
22949610235SMike Rapoport 
2301dbcf35cSDanny Huang 	if (ri->enable_reg[0] == ri->enable_reg[1] &&
2311dbcf35cSDanny Huang 	    ri->enable_bit[0] == ri->enable_bit[1])
2321dbcf35cSDanny Huang 			return 0;
2331dbcf35cSDanny Huang 
23449610235SMike Rapoport 	ret = tps6586x_read(parent, ri->enable_reg[0], &val1);
23549610235SMike Rapoport 	if (ret)
23649610235SMike Rapoport 		return ret;
23749610235SMike Rapoport 
23849610235SMike Rapoport 	ret = tps6586x_read(parent, ri->enable_reg[1], &val2);
23949610235SMike Rapoport 	if (ret)
24049610235SMike Rapoport 		return ret;
24149610235SMike Rapoport 
2424f586707SDanny Huang 	if (!(val2 & (1 << ri->enable_bit[1])))
24349610235SMike Rapoport 		return 0;
24449610235SMike Rapoport 
24549610235SMike Rapoport 	/*
24649610235SMike Rapoport 	 * The regulator is on, but it's enabled with the bit we don't
24749610235SMike Rapoport 	 * want to use, so we switch the enable bits
24849610235SMike Rapoport 	 */
2494f586707SDanny Huang 	if (!(val1 & (1 << ri->enable_bit[0]))) {
25049610235SMike Rapoport 		ret = tps6586x_set_bits(parent, ri->enable_reg[0],
25149610235SMike Rapoport 					1 << ri->enable_bit[0]);
25249610235SMike Rapoport 		if (ret)
25349610235SMike Rapoport 			return ret;
25449610235SMike Rapoport 	}
25549610235SMike Rapoport 
25649610235SMike Rapoport 	return tps6586x_clr_bits(parent, ri->enable_reg[1],
25749610235SMike Rapoport 				 1 << ri->enable_bit[1]);
25849610235SMike Rapoport }
25949610235SMike Rapoport 
26064e48160SLaxman Dewangan static int tps6586x_regulator_set_slew_rate(struct platform_device *pdev,
26164e48160SLaxman Dewangan 			int id, struct regulator_init_data *p)
262500c524aSXin Xie {
263500c524aSXin Xie 	struct device *parent = pdev->dev.parent;
264500c524aSXin Xie 	struct tps6586x_settings *setting = p->driver_data;
265500c524aSXin Xie 	uint8_t reg;
266500c524aSXin Xie 
267500c524aSXin Xie 	if (setting == NULL)
268500c524aSXin Xie 		return 0;
269500c524aSXin Xie 
270500c524aSXin Xie 	if (!(setting->slew_rate & TPS6586X_SLEW_RATE_SET))
271500c524aSXin Xie 		return 0;
272500c524aSXin Xie 
273500c524aSXin Xie 	/* only SM0 and SM1 can have the slew rate settings */
27464e48160SLaxman Dewangan 	switch (id) {
275500c524aSXin Xie 	case TPS6586X_ID_SM_0:
276500c524aSXin Xie 		reg = TPS6586X_SM0SL;
277500c524aSXin Xie 		break;
278500c524aSXin Xie 	case TPS6586X_ID_SM_1:
279500c524aSXin Xie 		reg = TPS6586X_SM1SL;
280500c524aSXin Xie 		break;
281500c524aSXin Xie 	default:
282500c524aSXin Xie 		dev_warn(&pdev->dev, "Only SM0/SM1 can set slew rate\n");
283500c524aSXin Xie 		return -EINVAL;
284500c524aSXin Xie 	}
285500c524aSXin Xie 
286500c524aSXin Xie 	return tps6586x_write(parent, reg,
287500c524aSXin Xie 			setting->slew_rate & TPS6586X_SLEW_RATE_MASK);
288500c524aSXin Xie }
289500c524aSXin Xie 
29049610235SMike Rapoport static inline struct tps6586x_regulator *find_regulator_info(int id)
29149610235SMike Rapoport {
29249610235SMike Rapoport 	struct tps6586x_regulator *ri;
29349610235SMike Rapoport 	int i;
29449610235SMike Rapoport 
29549610235SMike Rapoport 	for (i = 0; i < ARRAY_SIZE(tps6586x_regulator); i++) {
29649610235SMike Rapoport 		ri = &tps6586x_regulator[i];
29749610235SMike Rapoport 		if (ri->desc.id == id)
29849610235SMike Rapoport 			return ri;
29949610235SMike Rapoport 	}
30049610235SMike Rapoport 	return NULL;
30149610235SMike Rapoport }
30249610235SMike Rapoport 
30364e48160SLaxman Dewangan #ifdef CONFIG_OF
30464e48160SLaxman Dewangan static struct of_regulator_match tps6586x_matches[] = {
30564e48160SLaxman Dewangan 	{ .name = "sys",     .driver_data = (void *)TPS6586X_ID_SYS     },
30664e48160SLaxman Dewangan 	{ .name = "sm0",     .driver_data = (void *)TPS6586X_ID_SM_0    },
30764e48160SLaxman Dewangan 	{ .name = "sm1",     .driver_data = (void *)TPS6586X_ID_SM_1    },
30864e48160SLaxman Dewangan 	{ .name = "sm2",     .driver_data = (void *)TPS6586X_ID_SM_2    },
30964e48160SLaxman Dewangan 	{ .name = "ldo0",    .driver_data = (void *)TPS6586X_ID_LDO_0   },
31064e48160SLaxman Dewangan 	{ .name = "ldo1",    .driver_data = (void *)TPS6586X_ID_LDO_1   },
31164e48160SLaxman Dewangan 	{ .name = "ldo2",    .driver_data = (void *)TPS6586X_ID_LDO_2   },
31264e48160SLaxman Dewangan 	{ .name = "ldo3",    .driver_data = (void *)TPS6586X_ID_LDO_3   },
31364e48160SLaxman Dewangan 	{ .name = "ldo4",    .driver_data = (void *)TPS6586X_ID_LDO_4   },
31464e48160SLaxman Dewangan 	{ .name = "ldo5",    .driver_data = (void *)TPS6586X_ID_LDO_5   },
31564e48160SLaxman Dewangan 	{ .name = "ldo6",    .driver_data = (void *)TPS6586X_ID_LDO_6   },
31664e48160SLaxman Dewangan 	{ .name = "ldo7",    .driver_data = (void *)TPS6586X_ID_LDO_7   },
31764e48160SLaxman Dewangan 	{ .name = "ldo8",    .driver_data = (void *)TPS6586X_ID_LDO_8   },
31864e48160SLaxman Dewangan 	{ .name = "ldo9",    .driver_data = (void *)TPS6586X_ID_LDO_9   },
31964e48160SLaxman Dewangan 	{ .name = "ldo_rtc", .driver_data = (void *)TPS6586X_ID_LDO_RTC },
32064e48160SLaxman Dewangan };
32164e48160SLaxman Dewangan 
32264e48160SLaxman Dewangan static struct tps6586x_platform_data *tps6586x_parse_regulator_dt(
32364e48160SLaxman Dewangan 		struct platform_device *pdev,
32464e48160SLaxman Dewangan 		struct of_regulator_match **tps6586x_reg_matches)
32564e48160SLaxman Dewangan {
32664e48160SLaxman Dewangan 	const unsigned int num = ARRAY_SIZE(tps6586x_matches);
32764e48160SLaxman Dewangan 	struct device_node *np = pdev->dev.parent->of_node;
32864e48160SLaxman Dewangan 	struct device_node *regs;
32964e48160SLaxman Dewangan 	const char *sys_rail = NULL;
33064e48160SLaxman Dewangan 	unsigned int i;
33164e48160SLaxman Dewangan 	struct tps6586x_platform_data *pdata;
33264e48160SLaxman Dewangan 	int err;
33364e48160SLaxman Dewangan 
33464e48160SLaxman Dewangan 	regs = of_find_node_by_name(np, "regulators");
33564e48160SLaxman Dewangan 	if (!regs) {
33664e48160SLaxman Dewangan 		dev_err(&pdev->dev, "regulator node not found\n");
33764e48160SLaxman Dewangan 		return NULL;
33864e48160SLaxman Dewangan 	}
33964e48160SLaxman Dewangan 
34064e48160SLaxman Dewangan 	err = of_regulator_match(&pdev->dev, regs, tps6586x_matches, num);
34164e48160SLaxman Dewangan 	if (err < 0) {
34264e48160SLaxman Dewangan 		dev_err(&pdev->dev, "Regulator match failed, e %d\n", err);
34364e48160SLaxman Dewangan 		of_node_put(regs);
34464e48160SLaxman Dewangan 		return NULL;
34564e48160SLaxman Dewangan 	}
34664e48160SLaxman Dewangan 
34764e48160SLaxman Dewangan 	of_node_put(regs);
34864e48160SLaxman Dewangan 
34964e48160SLaxman Dewangan 	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
35064e48160SLaxman Dewangan 	if (!pdata) {
35164e48160SLaxman Dewangan 		dev_err(&pdev->dev, "Memory alloction failed\n");
35264e48160SLaxman Dewangan 		return NULL;
35364e48160SLaxman Dewangan 	}
35464e48160SLaxman Dewangan 
35564e48160SLaxman Dewangan 	for (i = 0; i < num; i++) {
35664e48160SLaxman Dewangan 		int id;
35764e48160SLaxman Dewangan 		if (!tps6586x_matches[i].init_data)
35864e48160SLaxman Dewangan 			continue;
35964e48160SLaxman Dewangan 
36064e48160SLaxman Dewangan 		pdata->reg_init_data[i] = tps6586x_matches[i].init_data;
36164e48160SLaxman Dewangan 		id = (int)tps6586x_matches[i].driver_data;
36264e48160SLaxman Dewangan 		if (id == TPS6586X_ID_SYS)
36364e48160SLaxman Dewangan 			sys_rail = pdata->reg_init_data[i]->constraints.name;
36464e48160SLaxman Dewangan 
36564e48160SLaxman Dewangan 		if ((id == TPS6586X_ID_LDO_5) || (id == TPS6586X_ID_LDO_RTC))
36664e48160SLaxman Dewangan 			pdata->reg_init_data[i]->supply_regulator = sys_rail;
36764e48160SLaxman Dewangan 	}
36864e48160SLaxman Dewangan 	*tps6586x_reg_matches = tps6586x_matches;
36964e48160SLaxman Dewangan 	return pdata;
37064e48160SLaxman Dewangan }
37164e48160SLaxman Dewangan #else
37264e48160SLaxman Dewangan static struct tps6586x_platform_data *tps6586x_parse_regulator_dt(
37364e48160SLaxman Dewangan 		struct platform_device *pdev,
37464e48160SLaxman Dewangan 		struct of_regulator_match **tps6586x_reg_matches)
37564e48160SLaxman Dewangan {
37664e48160SLaxman Dewangan 	*tps6586x_reg_matches = NULL;
37764e48160SLaxman Dewangan 	return NULL;
37864e48160SLaxman Dewangan }
37964e48160SLaxman Dewangan #endif
38064e48160SLaxman Dewangan 
38149610235SMike Rapoport static int __devinit tps6586x_regulator_probe(struct platform_device *pdev)
38249610235SMike Rapoport {
38349610235SMike Rapoport 	struct tps6586x_regulator *ri = NULL;
384c172708dSMark Brown 	struct regulator_config config = { };
38564e48160SLaxman Dewangan 	struct regulator_dev **rdev;
38664e48160SLaxman Dewangan 	struct regulator_init_data *reg_data;
38764e48160SLaxman Dewangan 	struct tps6586x_platform_data *pdata;
38864e48160SLaxman Dewangan 	struct of_regulator_match *tps6586x_reg_matches = NULL;
38964e48160SLaxman Dewangan 	int id;
39049610235SMike Rapoport 	int err;
39149610235SMike Rapoport 
392*10835600SLaxman Dewangan 	dev_dbg(&pdev->dev, "Probing regulator\n");
39349610235SMike Rapoport 
39464e48160SLaxman Dewangan 	pdata = dev_get_platdata(pdev->dev.parent);
39564e48160SLaxman Dewangan 	if ((!pdata) && (pdev->dev.parent->of_node))
39664e48160SLaxman Dewangan 		pdata = tps6586x_parse_regulator_dt(pdev,
39764e48160SLaxman Dewangan 					&tps6586x_reg_matches);
39864e48160SLaxman Dewangan 
39964e48160SLaxman Dewangan 	if (!pdata) {
40064e48160SLaxman Dewangan 		dev_err(&pdev->dev, "Platform data not available, exiting\n");
40164e48160SLaxman Dewangan 		return -ENODEV;
40264e48160SLaxman Dewangan 	}
40364e48160SLaxman Dewangan 
40464e48160SLaxman Dewangan 	rdev = devm_kzalloc(&pdev->dev, TPS6586X_ID_MAX_REGULATOR *
40564e48160SLaxman Dewangan 				sizeof(*rdev), GFP_KERNEL);
40664e48160SLaxman Dewangan 	if (!rdev) {
40764e48160SLaxman Dewangan 		dev_err(&pdev->dev, "Mmemory alloc failed\n");
40864e48160SLaxman Dewangan 		return -ENOMEM;
40964e48160SLaxman Dewangan 	}
41064e48160SLaxman Dewangan 
41164e48160SLaxman Dewangan 	for (id = 0; id < TPS6586X_ID_MAX_REGULATOR; ++id) {
41264e48160SLaxman Dewangan 		reg_data = pdata->reg_init_data[id];
41364e48160SLaxman Dewangan 
41449610235SMike Rapoport 		ri = find_regulator_info(id);
41564e48160SLaxman Dewangan 		if (!ri) {
41649610235SMike Rapoport 			dev_err(&pdev->dev, "invalid regulator ID specified\n");
41764e48160SLaxman Dewangan 			err = -EINVAL;
41864e48160SLaxman Dewangan 			goto fail;
41949610235SMike Rapoport 		}
42049610235SMike Rapoport 
42149610235SMike Rapoport 		err = tps6586x_regulator_preinit(pdev->dev.parent, ri);
42264e48160SLaxman Dewangan 		if (err) {
42364e48160SLaxman Dewangan 			dev_err(&pdev->dev,
42464e48160SLaxman Dewangan 				"regulator %d preinit failed, e %d\n", id, err);
42564e48160SLaxman Dewangan 			goto fail;
42664e48160SLaxman Dewangan 		}
42749610235SMike Rapoport 
4287c7fac30SLaxman Dewangan 		config.dev = pdev->dev.parent;
42964e48160SLaxman Dewangan 		config.init_data = reg_data;
430c172708dSMark Brown 		config.driver_data = ri;
431c172708dSMark Brown 
43264e48160SLaxman Dewangan 		if (tps6586x_reg_matches)
43364e48160SLaxman Dewangan 			config.of_node = tps6586x_reg_matches[id].of_node;
43464e48160SLaxman Dewangan 
43564e48160SLaxman Dewangan 		rdev[id] = regulator_register(&ri->desc, &config);
43664e48160SLaxman Dewangan 		if (IS_ERR(rdev[id])) {
43749610235SMike Rapoport 			dev_err(&pdev->dev, "failed to register regulator %s\n",
43849610235SMike Rapoport 					ri->desc.name);
43964e48160SLaxman Dewangan 			err = PTR_ERR(rdev[id]);
44064e48160SLaxman Dewangan 			goto fail;
44164e48160SLaxman Dewangan 		}
44264e48160SLaxman Dewangan 
44364e48160SLaxman Dewangan 		if (reg_data) {
44464e48160SLaxman Dewangan 			err = tps6586x_regulator_set_slew_rate(pdev, id,
44564e48160SLaxman Dewangan 					reg_data);
44664e48160SLaxman Dewangan 			if (err < 0) {
44764e48160SLaxman Dewangan 				dev_err(&pdev->dev,
44864e48160SLaxman Dewangan 					"Slew rate config failed, e %d\n", err);
44964e48160SLaxman Dewangan 				regulator_unregister(rdev[id]);
45064e48160SLaxman Dewangan 				goto fail;
45164e48160SLaxman Dewangan 			}
45264e48160SLaxman Dewangan 		}
45349610235SMike Rapoport 	}
45449610235SMike Rapoport 
455e7973c3cSAxel Lin 	platform_set_drvdata(pdev, rdev);
45664e48160SLaxman Dewangan 	return 0;
45749610235SMike Rapoport 
45864e48160SLaxman Dewangan fail:
45964e48160SLaxman Dewangan 	while (--id >= 0)
46064e48160SLaxman Dewangan 		regulator_unregister(rdev[id]);
46164e48160SLaxman Dewangan 	return err;
46249610235SMike Rapoport }
46349610235SMike Rapoport 
46449610235SMike Rapoport static int __devexit tps6586x_regulator_remove(struct platform_device *pdev)
46549610235SMike Rapoport {
46664e48160SLaxman Dewangan 	struct regulator_dev **rdev = platform_get_drvdata(pdev);
46764e48160SLaxman Dewangan 	int id = TPS6586X_ID_MAX_REGULATOR;
468e7973c3cSAxel Lin 
46964e48160SLaxman Dewangan 	while (--id >= 0)
47064e48160SLaxman Dewangan 		regulator_unregister(rdev[id]);
47164e48160SLaxman Dewangan 
47249610235SMike Rapoport 	return 0;
47349610235SMike Rapoport }
47449610235SMike Rapoport 
47549610235SMike Rapoport static struct platform_driver tps6586x_regulator_driver = {
47649610235SMike Rapoport 	.driver	= {
47764e48160SLaxman Dewangan 		.name	= "tps6586x-pmic",
47849610235SMike Rapoport 		.owner	= THIS_MODULE,
47949610235SMike Rapoport 	},
48049610235SMike Rapoport 	.probe		= tps6586x_regulator_probe,
48149610235SMike Rapoport 	.remove		= __devexit_p(tps6586x_regulator_remove),
48249610235SMike Rapoport };
48349610235SMike Rapoport 
48449610235SMike Rapoport static int __init tps6586x_regulator_init(void)
48549610235SMike Rapoport {
48649610235SMike Rapoport 	return platform_driver_register(&tps6586x_regulator_driver);
48749610235SMike Rapoport }
48849610235SMike Rapoport subsys_initcall(tps6586x_regulator_init);
48949610235SMike Rapoport 
49049610235SMike Rapoport static void __exit tps6586x_regulator_exit(void)
49149610235SMike Rapoport {
49249610235SMike Rapoport 	platform_driver_unregister(&tps6586x_regulator_driver);
49349610235SMike Rapoport }
49449610235SMike Rapoport module_exit(tps6586x_regulator_exit);
49549610235SMike Rapoport 
49649610235SMike Rapoport MODULE_LICENSE("GPL");
49749610235SMike Rapoport MODULE_AUTHOR("Mike Rapoport <mike@compulab.co.il>");
49849610235SMike Rapoport MODULE_DESCRIPTION("Regulator Driver for TI TPS6586X PMIC");
49949610235SMike Rapoport MODULE_ALIAS("platform:tps6586x-regulator");
500