diff options
Diffstat (limited to 'drivers/regulator/tps6586x-regulator.c')
| -rw-r--r-- | drivers/regulator/tps6586x-regulator.c | 560 | 
1 files changed, 351 insertions, 209 deletions
diff --git a/drivers/regulator/tps6586x-regulator.c b/drivers/regulator/tps6586x-regulator.c index 51237fbb1bb..0a3bb3aecd9 100644 --- a/drivers/regulator/tps6586x-regulator.c +++ b/drivers/regulator/tps6586x-regulator.c @@ -14,12 +14,15 @@   */  #include <linux/kernel.h> +#include <linux/module.h>  #include <linux/init.h>  #include <linux/err.h> +#include <linux/of.h>  #include <linux/slab.h>  #include <linux/platform_device.h>  #include <linux/regulator/driver.h>  #include <linux/regulator/machine.h> +#include <linux/regulator/of_regulator.h>  #include <linux/mfd/tps6586x.h>  /* supply control and voltage setting  */ @@ -56,227 +59,200 @@  struct tps6586x_regulator {  	struct regulator_desc desc; -	int volt_reg; -	int volt_shift; -	int volt_nbits;  	int enable_bit[2];  	int enable_reg[2]; - -	int *voltages; - -	/* for DVM regulators */ -	int go_reg; -	int go_bit;  }; -static inline struct device *to_tps6586x_dev(struct regulator_dev *rdev) -{ -	return rdev_get_dev(rdev)->parent->parent; -} - -static int tps6586x_ldo_list_voltage(struct regulator_dev *rdev, -				     unsigned selector) -{ -	struct tps6586x_regulator *info = rdev_get_drvdata(rdev); - -	return info->voltages[selector] * 1000; -} - - -static int __tps6586x_ldo_set_voltage(struct device *parent, -				      struct tps6586x_regulator *ri, -				      int min_uV, int max_uV) -{ -	int val, uV; -	uint8_t mask; - -	for (val = 0; val < ri->desc.n_voltages; val++) { -		uV = ri->voltages[val] * 1000; - -		/* LDO0 has minimal voltage 1.2 rather than 1.25 */ -		if (ri->desc.id == TPS6586X_ID_LDO_0 && val == 0) -			uV -= 50 * 1000; - -		/* use the first in-range value */ -		if (min_uV <= uV && uV <= max_uV) { - -			val <<= ri->volt_shift; -			mask = ((1 << ri->volt_nbits) - 1) << ri->volt_shift; - -			return tps6586x_update(parent, ri->volt_reg, val, mask); -		} -	} - -	return -EINVAL; -} - -static int tps6586x_ldo_set_voltage(struct regulator_dev *rdev, -				    int min_uV, int max_uV) -{ -	struct tps6586x_regulator *ri = rdev_get_drvdata(rdev); -	struct device *parent = to_tps6586x_dev(rdev); - -	return __tps6586x_ldo_set_voltage(parent, ri, min_uV, max_uV); -} - -static int tps6586x_ldo_get_voltage(struct regulator_dev *rdev) -{ -	struct tps6586x_regulator *ri = rdev_get_drvdata(rdev); -	struct device *parent = to_tps6586x_dev(rdev); -	uint8_t val, mask; -	int ret; - -	ret = tps6586x_read(parent, ri->volt_reg, &val); -	if (ret) -		return ret; - -	mask = ((1 << ri->volt_nbits) - 1) << ri->volt_shift; -	val = (val & mask) >> ri->volt_shift; - -	if (val >= ri->desc.n_voltages) -		BUG(); - -	return ri->voltages[val] * 1000; -} +static struct regulator_ops tps6586x_rw_regulator_ops = { +	.list_voltage = regulator_list_voltage_table, +	.map_voltage = regulator_map_voltage_ascend, +	.get_voltage_sel = regulator_get_voltage_sel_regmap, +	.set_voltage_sel = regulator_set_voltage_sel_regmap, -static int tps6586x_dvm_set_voltage(struct regulator_dev *rdev, -				    int min_uV, int max_uV) -{ -	struct tps6586x_regulator *ri = rdev_get_drvdata(rdev); -	struct device *parent = to_tps6586x_dev(rdev); -	int ret; - -	ret = __tps6586x_ldo_set_voltage(parent, ri, min_uV, max_uV); -	if (ret) -		return ret; - -	return tps6586x_set_bits(parent, ri->go_reg, 1 << ri->go_bit); -} - -static int tps6586x_regulator_enable(struct regulator_dev *rdev) -{ -	struct tps6586x_regulator *ri = rdev_get_drvdata(rdev); -	struct device *parent = to_tps6586x_dev(rdev); - -	return tps6586x_set_bits(parent, ri->enable_reg[0], -				 1 << ri->enable_bit[0]); -} +	.is_enabled = regulator_is_enabled_regmap, +	.enable = regulator_enable_regmap, +	.disable = regulator_disable_regmap, +}; -static int tps6586x_regulator_disable(struct regulator_dev *rdev) -{ -	struct tps6586x_regulator *ri = rdev_get_drvdata(rdev); -	struct device *parent = to_tps6586x_dev(rdev); +static struct regulator_ops tps6586x_ro_regulator_ops = { +	.list_voltage = regulator_list_voltage_table, +	.map_voltage = regulator_map_voltage_ascend, +	.get_voltage_sel = regulator_get_voltage_sel_regmap, -	return tps6586x_clr_bits(parent, ri->enable_reg[0], -				 1 << ri->enable_bit[0]); -} +	.is_enabled = regulator_is_enabled_regmap, +	.enable = regulator_enable_regmap, +	.disable = regulator_disable_regmap, +}; -static int tps6586x_regulator_is_enabled(struct regulator_dev *rdev) -{ -	struct tps6586x_regulator *ri = rdev_get_drvdata(rdev); -	struct device *parent = to_tps6586x_dev(rdev); -	uint8_t reg_val; -	int ret; +static struct regulator_ops tps6586x_sys_regulator_ops = { +}; -	ret = tps6586x_read(parent, ri->enable_reg[0], ®_val); -	if (ret) -		return ret; +static const unsigned int tps6586x_ldo0_voltages[] = { +	1200000, 1500000, 1800000, 2500000, 2700000, 2850000, 3100000, 3300000, +}; -	return !!(reg_val & (1 << ri->enable_bit[0])); -} +static const unsigned int tps6586x_ldo4_voltages[] = { +	1700000, 1725000, 1750000, 1775000, 1800000, 1825000, 1850000, 1875000, +	1900000, 1925000, 1950000, 1975000, 2000000, 2025000, 2050000, 2075000, +	2100000, 2125000, 2150000, 2175000, 2200000, 2225000, 2250000, 2275000, +	2300000, 2325000, 2350000, 2375000, 2400000, 2425000, 2450000, 2475000, +}; -static struct regulator_ops tps6586x_regulator_ldo_ops = { -	.list_voltage = tps6586x_ldo_list_voltage, -	.get_voltage = tps6586x_ldo_get_voltage, -	.set_voltage = tps6586x_ldo_set_voltage, +#define tps658623_sm2_voltages tps6586x_ldo4_voltages -	.is_enabled = tps6586x_regulator_is_enabled, -	.enable = tps6586x_regulator_enable, -	.disable = tps6586x_regulator_disable, +static const unsigned int tps6586x_ldo_voltages[] = { +	1250000, 1500000, 1800000, 2500000, 2700000, 2850000, 3100000, 3300000,  }; -static struct regulator_ops tps6586x_regulator_dvm_ops = { -	.list_voltage = tps6586x_ldo_list_voltage, -	.get_voltage = tps6586x_ldo_get_voltage, -	.set_voltage = tps6586x_dvm_set_voltage, - -	.is_enabled = tps6586x_regulator_is_enabled, -	.enable = tps6586x_regulator_enable, -	.disable = tps6586x_regulator_disable, +static const unsigned int tps6586x_sm2_voltages[] = { +	3000000, 3050000, 3100000, 3150000, 3200000, 3250000, 3300000, 3350000, +	3400000, 3450000, 3500000, 3550000, 3600000, 3650000, 3700000, 3750000, +	3800000, 3850000, 3900000, 3950000, 4000000, 4050000, 4100000, 4150000, +	4200000, 4250000, 4300000, 4350000, 4400000, 4450000, 4500000, 4550000,  }; -static int tps6586x_ldo_voltages[] = { -	1250, 1500, 1800, 2500, 2700, 2850, 3100, 3300, +static int tps658640_sm2_voltages[] = { +	2150000, 2200000, 2250000, 2300000, 2350000, 2400000, 2450000, 2500000, +	2550000, 2600000, 2650000, 2700000, 2750000, 2800000, 2850000, 2900000, +	2950000, 3000000, 3050000, 3100000, 3150000, 3200000, 3250000, 3300000, +	3350000, 3400000, 3450000, 3500000, 3550000, 3600000, 3650000, 3700000,  }; -static int tps6586x_ldo4_voltages[] = { -	1700, 1725, 1750, 1775, 1800, 1825, 1850, 1875, -	1900, 1925, 1950, 1975, 2000, 2025, 2050, 2075, -	2100, 2125, 2150, 2175, 2200, 2225, 2250, 2275, -	2300, 2325, 2350, 2375, 2400, 2425, 2450, 2475, +static const unsigned int tps658643_sm2_voltages[] = { +	1025000, 1050000, 1075000, 1100000, 1125000, 1150000, 1175000, 1200000, +	1225000, 1250000, 1275000, 1300000, 1325000, 1350000, 1375000, 1400000, +	1425000, 1450000, 1475000, 1500000, 1525000, 1550000, 1575000, 1600000, +	1625000, 1650000, 1675000, 1700000, 1725000, 1750000, 1775000, 1800000,  }; -static int tps6586x_sm2_voltages[] = { -	3000, 3050, 3100, 3150, 3200, 3250, 3300, 3350, -	3400, 3450, 3500, 3550, 3600, 3650, 3700, 3750, -	3800, 3850, 3900, 3950, 4000, 4050, 4100, 4150, -	4200, 4250, 4300, 4350, 4400, 4450, 4500, 4550, +static const unsigned int tps6586x_dvm_voltages[] = { +	 725000,  750000,  775000,  800000,  825000,  850000,  875000,  900000, +	 925000,  950000,  975000, 1000000, 1025000, 1050000, 1075000, 1100000, +	1125000, 1150000, 1175000, 1200000, 1225000, 1250000, 1275000, 1300000, +	1325000, 1350000, 1375000, 1400000, 1425000, 1450000, 1475000, 1500000,  }; -static int tps6586x_dvm_voltages[] = { -	 725,  750,  775,  800,  825,  850,  875,  900, -	 925,  950,  975, 1000, 1025, 1050, 1075, 1100, -	1125, 1150, 1175, 1200, 1225, 1250, 1275, 1300, -	1325, 1350, 1375, 1400, 1425, 1450, 1475, 1500, +static int tps658640_rtc_voltages[] = { +	2500000, 2850000, 3100000, 3300000,  }; -#define TPS6586X_REGULATOR(_id, vdata, _ops, vreg, shift, nbits,	\ +#define TPS6586X_REGULATOR(_id, _ops, _pin_name, vdata, vreg, shift, nbits, \  			   ereg0, ebit0, ereg1, ebit1, goreg, gobit)	\ -{									\  	.desc	= {							\ +		.supply_name = _pin_name,				\  		.name	= "REG-" #_id,					\ -		.ops	= &tps6586x_regulator_##_ops,			\ +		.ops	= &tps6586x_## _ops ## _regulator_ops,		\  		.type	= REGULATOR_VOLTAGE,				\  		.id	= TPS6586X_ID_##_id,				\ -		.n_voltages = ARRAY_SIZE(tps6586x_##vdata##_voltages),	\ +		.n_voltages = ARRAY_SIZE(vdata##_voltages),		\ +		.volt_table = vdata##_voltages,				\  		.owner	= THIS_MODULE,					\ +		.enable_reg = TPS6586X_SUPPLY##ereg0,			\ +		.enable_mask = 1 << (ebit0),				\ +		.vsel_reg = TPS6586X_##vreg,				\ +		.vsel_mask = ((1 << (nbits)) - 1) << (shift),		\ +		.apply_reg = (goreg),				\ +		.apply_bit = (gobit),				\  	},								\ -	.volt_reg	= TPS6586X_##vreg,				\ -	.volt_shift	= (shift),					\ -	.volt_nbits	= (nbits),					\  	.enable_reg[0]	= TPS6586X_SUPPLY##ereg0,			\  	.enable_bit[0]	= (ebit0),					\  	.enable_reg[1]	= TPS6586X_SUPPLY##ereg1,			\ -	.enable_bit[1]	= (ebit1),					\ -	.voltages	= tps6586x_##vdata##_voltages,			\ -} +	.enable_bit[1]	= (ebit1), -#define TPS6586X_LDO(_id, vdata, vreg, shift, nbits,			\ +#define TPS6586X_LDO(_id, _pname, vdata, vreg, shift, nbits,		\  		     ereg0, ebit0, ereg1, ebit1)			\ -	TPS6586X_REGULATOR(_id, vdata, ldo_ops, vreg, shift, nbits,	\ -			   ereg0, ebit0, ereg1, ebit1, 0, 0) +{									\ +	TPS6586X_REGULATOR(_id, rw, _pname, vdata, vreg, shift, nbits,	\ +			   ereg0, ebit0, ereg1, ebit1, 0, 0)		\ +} + +#define TPS6586X_FIXED_LDO(_id, _pname, vdata, vreg, shift, nbits,	\ +			  ereg0, ebit0, ereg1, ebit1)			\ +{									\ +	TPS6586X_REGULATOR(_id, ro, _pname, vdata, vreg, shift, nbits,	\ +			   ereg0, ebit0, ereg1, ebit1, 0, 0)		\ +} -#define TPS6586X_DVM(_id, vdata, vreg, shift, nbits,			\ +#define TPS6586X_DVM(_id, _pname, vdata, vreg, shift, nbits,		\  		     ereg0, ebit0, ereg1, ebit1, goreg, gobit)		\ -	TPS6586X_REGULATOR(_id, vdata, dvm_ops, vreg, shift, nbits,	\ -			   ereg0, ebit0, ereg1, ebit1, goreg, gobit) +{									\ +	TPS6586X_REGULATOR(_id, rw, _pname, vdata, vreg, shift, nbits,	\ +			   ereg0, ebit0, ereg1, ebit1, goreg, gobit)	\ +} + +#define TPS6586X_SYS_REGULATOR()					\ +{									\ +	.desc	= {							\ +		.supply_name = "sys",					\ +		.name	= "REG-SYS",					\ +		.ops	= &tps6586x_sys_regulator_ops,			\ +		.type	= REGULATOR_VOLTAGE,				\ +		.id	= TPS6586X_ID_SYS,				\ +		.owner	= THIS_MODULE,					\ +	},								\ +}  static struct tps6586x_regulator tps6586x_regulator[] = { -	TPS6586X_LDO(LDO_0, ldo, SUPPLYV1, 5, 3, ENC, 0, END, 0), -	TPS6586X_LDO(LDO_3, ldo, SUPPLYV4, 0, 3, ENC, 2, END, 2), -	TPS6586X_LDO(LDO_5, ldo, SUPPLYV6, 0, 3, ENE, 6, ENE, 6), -	TPS6586X_LDO(LDO_6, ldo, SUPPLYV3, 0, 3, ENC, 4, END, 4), -	TPS6586X_LDO(LDO_7, ldo, SUPPLYV3, 3, 3, ENC, 5, END, 5), -	TPS6586X_LDO(LDO_8, ldo, SUPPLYV1, 5, 3, ENC, 6, END, 6), -	TPS6586X_LDO(LDO_9, ldo, SUPPLYV6, 3, 3, ENE, 7, ENE, 7), -	TPS6586X_LDO(LDO_RTC, ldo, SUPPLYV4, 3, 3, ENE, 7, ENE, 7), -	TPS6586X_LDO(LDO_1, dvm, SUPPLYV1, 0, 5, ENC, 1, END, 1), -	TPS6586X_LDO(SM_2, sm2, SUPPLYV2, 0, 5, ENC, 1, END, 1), - -	TPS6586X_DVM(LDO_2, dvm, LDO2BV1, 0, 5, ENA, 3, ENB, 3, VCC2, 6), -	TPS6586X_DVM(LDO_4, ldo4, LDO4V1, 0, 5, ENC, 3, END, 3, VCC1, 6), -	TPS6586X_DVM(SM_0, dvm, SM0V1, 0, 5, ENA, 1, ENB, 1, VCC1, 2), -	TPS6586X_DVM(SM_1, dvm, SM1V1, 0, 5, ENA, 0, ENB, 0, VCC1, 0), +	TPS6586X_SYS_REGULATOR(), +	TPS6586X_LDO(LDO_0, "vinldo01", tps6586x_ldo0, SUPPLYV1, 5, 3, ENC, 0, +					END, 0), +	TPS6586X_LDO(LDO_3, "vinldo23", tps6586x_ldo, SUPPLYV4, 0, 3, ENC, 2, +					END, 2), +	TPS6586X_LDO(LDO_5, "REG-SYS", tps6586x_ldo, SUPPLYV6, 0, 3, ENE, 6, +					ENE, 6), +	TPS6586X_LDO(LDO_6, "vinldo678", tps6586x_ldo, SUPPLYV3, 0, 3, ENC, 4, +					END, 4), +	TPS6586X_LDO(LDO_7, "vinldo678", tps6586x_ldo, SUPPLYV3, 3, 3, ENC, 5, +					END, 5), +	TPS6586X_LDO(LDO_8, "vinldo678", tps6586x_ldo, SUPPLYV2, 5, 3, ENC, 6, +					END, 6), +	TPS6586X_LDO(LDO_9, "vinldo9", tps6586x_ldo, SUPPLYV6, 3, 3, ENE, 7, +					ENE, 7), +	TPS6586X_LDO(LDO_RTC, "REG-SYS", tps6586x_ldo, SUPPLYV4, 3, 3, V4, 7, +					V4, 7), +	TPS6586X_LDO(LDO_1, "vinldo01", tps6586x_dvm, SUPPLYV1, 0, 5, ENC, 1, +					END, 1), +	TPS6586X_LDO(SM_2, "vin-sm2", tps6586x_sm2, SUPPLYV2, 0, 5, ENC, 7, +					END, 7), + +	TPS6586X_DVM(LDO_2, "vinldo23", tps6586x_dvm, LDO2BV1, 0, 5, ENA, 3, +					ENB, 3, TPS6586X_VCC2, BIT(6)), +	TPS6586X_DVM(LDO_4, "vinldo4", tps6586x_ldo4, LDO4V1, 0, 5, ENC, 3, +					END, 3, TPS6586X_VCC1, BIT(6)), +	TPS6586X_DVM(SM_0, "vin-sm0", tps6586x_dvm, SM0V1, 0, 5, ENA, 1, +					ENB, 1, TPS6586X_VCC1, BIT(2)), +	TPS6586X_DVM(SM_1, "vin-sm1", tps6586x_dvm, SM1V1, 0, 5, ENA, 0, +					ENB, 0, TPS6586X_VCC1, BIT(0)), +}; + +static struct tps6586x_regulator tps658623_regulator[] = { +	TPS6586X_LDO(SM_2, "vin-sm2", tps658623_sm2, SUPPLYV2, 0, 5, ENC, 7, +					END, 7), +}; + +static struct tps6586x_regulator tps658640_regulator[] = { +	TPS6586X_LDO(LDO_3, "vinldo23", tps6586x_ldo0, SUPPLYV4, 0, 3, +					ENC, 2, END, 2), +	TPS6586X_LDO(LDO_5, "REG-SYS", tps6586x_ldo0, SUPPLYV6, 0, 3, +					ENE, 6, ENE, 6), +	TPS6586X_LDO(LDO_6, "vinldo678", tps6586x_ldo0, SUPPLYV3, 0, 3, +					ENC, 4, END, 4), +	TPS6586X_LDO(LDO_7, "vinldo678", tps6586x_ldo0, SUPPLYV3, 3, 3, +					ENC, 5, END, 5), +	TPS6586X_LDO(LDO_8, "vinldo678", tps6586x_ldo0, SUPPLYV2, 5, 3, +					ENC, 6, END, 6), +	TPS6586X_LDO(LDO_9, "vinldo9", tps6586x_ldo0, SUPPLYV6, 3, 3, +					ENE, 7, ENE, 7), +	TPS6586X_LDO(SM_2, "vin-sm2", tps658640_sm2, SUPPLYV2, 0, 5, +					ENC, 7, END, 7), + +	TPS6586X_FIXED_LDO(LDO_RTC, "REG-SYS", tps658640_rtc, SUPPLYV4, 3, 2, +					V4, 7, V4, 7), +}; + +static struct tps6586x_regulator tps658643_regulator[] = { +	TPS6586X_LDO(SM_2, "vin-sm2", tps658643_sm2, SUPPLYV2, 0, 5, ENC, 7, +					END, 7),  };  /* @@ -290,6 +266,10 @@ static inline int tps6586x_regulator_preinit(struct device *parent,  	uint8_t val1, val2;  	int ret; +	if (ri->enable_reg[0] == ri->enable_reg[1] && +	    ri->enable_bit[0] == ri->enable_bit[1]) +			return 0; +  	ret = tps6586x_read(parent, ri->enable_reg[0], &val1);  	if (ret)  		return ret; @@ -298,14 +278,14 @@ static inline int tps6586x_regulator_preinit(struct device *parent,  	if (ret)  		return ret; -	if (!(val2 & ri->enable_bit[1])) +	if (!(val2 & (1 << ri->enable_bit[1])))  		return 0;  	/*  	 * The regulator is on, but it's enabled with the bit we don't  	 * want to use, so we switch the enable bits  	 */ -	if (!(val1 & ri->enable_bit[0])) { +	if (!(val1 & (1 << ri->enable_bit[0]))) {  		ret = tps6586x_set_bits(parent, ri->enable_reg[0],  					1 << ri->enable_bit[0]);  		if (ret) @@ -316,11 +296,68 @@ static inline int tps6586x_regulator_preinit(struct device *parent,  				 1 << ri->enable_bit[1]);  } -static inline struct tps6586x_regulator *find_regulator_info(int id) +static int tps6586x_regulator_set_slew_rate(struct platform_device *pdev, +			int id, struct regulator_init_data *p) +{ +	struct device *parent = pdev->dev.parent; +	struct tps6586x_settings *setting = p->driver_data; +	uint8_t reg; + +	if (setting == NULL) +		return 0; + +	if (!(setting->slew_rate & TPS6586X_SLEW_RATE_SET)) +		return 0; + +	/* only SM0 and SM1 can have the slew rate settings */ +	switch (id) { +	case TPS6586X_ID_SM_0: +		reg = TPS6586X_SM0SL; +		break; +	case TPS6586X_ID_SM_1: +		reg = TPS6586X_SM1SL; +		break; +	default: +		dev_err(&pdev->dev, "Only SM0/SM1 can set slew rate\n"); +		return -EINVAL; +	} + +	return tps6586x_write(parent, reg, +			setting->slew_rate & TPS6586X_SLEW_RATE_MASK); +} + +static struct tps6586x_regulator *find_regulator_info(int id, int version)  {  	struct tps6586x_regulator *ri; +	struct tps6586x_regulator *table = NULL; +	int num;  	int i; +	switch (version) { +	case TPS658623: +		table = tps658623_regulator; +		num = ARRAY_SIZE(tps658623_regulator); +		break; +	case TPS658640: +	case TPS658640v2: +		table = tps658640_regulator; +		num = ARRAY_SIZE(tps658640_regulator); +		break; +	case TPS658643: +		table = tps658643_regulator; +		num = ARRAY_SIZE(tps658643_regulator); +		break; +	} + +	/* Search version specific table first */ +	if (table) { +		for (i = 0; i < num; i++) { +			ri = &table[i]; +			if (ri->desc.id == id) +				return ri; +		} +	} +  	for (i = 0; i < ARRAY_SIZE(tps6586x_regulator); i++) {  		ri = &tps6586x_regulator[i];  		if (ri->desc.id == id) @@ -329,43 +366,149 @@ static inline struct tps6586x_regulator *find_regulator_info(int id)  	return NULL;  } -static int __devinit tps6586x_regulator_probe(struct platform_device *pdev) +#ifdef CONFIG_OF +static struct of_regulator_match tps6586x_matches[] = { +	{ .name = "sys",     .driver_data = (void *)TPS6586X_ID_SYS     }, +	{ .name = "sm0",     .driver_data = (void *)TPS6586X_ID_SM_0    }, +	{ .name = "sm1",     .driver_data = (void *)TPS6586X_ID_SM_1    }, +	{ .name = "sm2",     .driver_data = (void *)TPS6586X_ID_SM_2    }, +	{ .name = "ldo0",    .driver_data = (void *)TPS6586X_ID_LDO_0   }, +	{ .name = "ldo1",    .driver_data = (void *)TPS6586X_ID_LDO_1   }, +	{ .name = "ldo2",    .driver_data = (void *)TPS6586X_ID_LDO_2   }, +	{ .name = "ldo3",    .driver_data = (void *)TPS6586X_ID_LDO_3   }, +	{ .name = "ldo4",    .driver_data = (void *)TPS6586X_ID_LDO_4   }, +	{ .name = "ldo5",    .driver_data = (void *)TPS6586X_ID_LDO_5   }, +	{ .name = "ldo6",    .driver_data = (void *)TPS6586X_ID_LDO_6   }, +	{ .name = "ldo7",    .driver_data = (void *)TPS6586X_ID_LDO_7   }, +	{ .name = "ldo8",    .driver_data = (void *)TPS6586X_ID_LDO_8   }, +	{ .name = "ldo9",    .driver_data = (void *)TPS6586X_ID_LDO_9   }, +	{ .name = "ldo_rtc", .driver_data = (void *)TPS6586X_ID_LDO_RTC }, +}; + +static struct tps6586x_platform_data *tps6586x_parse_regulator_dt( +		struct platform_device *pdev, +		struct of_regulator_match **tps6586x_reg_matches) +{ +	const unsigned int num = ARRAY_SIZE(tps6586x_matches); +	struct device_node *np = pdev->dev.parent->of_node; +	struct device_node *regs; +	const char *sys_rail = NULL; +	unsigned int i; +	struct tps6586x_platform_data *pdata; +	int err; + +	regs = of_get_child_by_name(np, "regulators"); +	if (!regs) { +		dev_err(&pdev->dev, "regulator node not found\n"); +		return NULL; +	} + +	err = of_regulator_match(&pdev->dev, regs, tps6586x_matches, num); +	of_node_put(regs); +	if (err < 0) { +		dev_err(&pdev->dev, "Regulator match failed, e %d\n", err); +		return NULL; +	} + +	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); +	if (!pdata) +		return NULL; + +	for (i = 0; i < num; i++) { +		int id; +		if (!tps6586x_matches[i].init_data) +			continue; + +		pdata->reg_init_data[i] = tps6586x_matches[i].init_data; +		id = (int)tps6586x_matches[i].driver_data; +		if (id == TPS6586X_ID_SYS) +			sys_rail = pdata->reg_init_data[i]->constraints.name; + +		if ((id == TPS6586X_ID_LDO_5) || (id == TPS6586X_ID_LDO_RTC)) +			pdata->reg_init_data[i]->supply_regulator = sys_rail; +	} +	*tps6586x_reg_matches = tps6586x_matches; +	return pdata; +} +#else +static struct tps6586x_platform_data *tps6586x_parse_regulator_dt( +		struct platform_device *pdev, +		struct of_regulator_match **tps6586x_reg_matches) +{ +	*tps6586x_reg_matches = NULL; +	return NULL; +} +#endif + +static int tps6586x_regulator_probe(struct platform_device *pdev)  {  	struct tps6586x_regulator *ri = NULL; +	struct regulator_config config = { };  	struct regulator_dev *rdev; -	int id = pdev->id; +	struct regulator_init_data *reg_data; +	struct tps6586x_platform_data *pdata; +	struct of_regulator_match *tps6586x_reg_matches = NULL; +	int version; +	int id;  	int err; -	dev_dbg(&pdev->dev, "Probing reulator %d\n", id); +	dev_dbg(&pdev->dev, "Probing regulator\n"); -	ri = find_regulator_info(id); -	if (ri == NULL) { -		dev_err(&pdev->dev, "invalid regulator ID specified\n"); -		return -EINVAL; +	pdata = dev_get_platdata(pdev->dev.parent); +	if ((!pdata) && (pdev->dev.parent->of_node)) +		pdata = tps6586x_parse_regulator_dt(pdev, +					&tps6586x_reg_matches); + +	if (!pdata) { +		dev_err(&pdev->dev, "Platform data not available, exiting\n"); +		return -ENODEV;  	} -	err = tps6586x_regulator_preinit(pdev->dev.parent, ri); -	if (err) -		return err; +	version = tps6586x_get_version(pdev->dev.parent); -	rdev = regulator_register(&ri->desc, &pdev->dev, -				  pdev->dev.platform_data, ri); -	if (IS_ERR(rdev)) { -		dev_err(&pdev->dev, "failed to register regulator %s\n", -				ri->desc.name); -		return PTR_ERR(rdev); -	} +	for (id = 0; id < TPS6586X_ID_MAX_REGULATOR; ++id) { +		reg_data = pdata->reg_init_data[id]; -	platform_set_drvdata(pdev, rdev); +		ri = find_regulator_info(id, version); -	return 0; -} +		if (!ri) { +			dev_err(&pdev->dev, "invalid regulator ID specified\n"); +			return -EINVAL; +		} -static int __devexit tps6586x_regulator_remove(struct platform_device *pdev) -{ -	struct regulator_dev *rdev = platform_get_drvdata(pdev); +		err = tps6586x_regulator_preinit(pdev->dev.parent, ri); +		if (err) { +			dev_err(&pdev->dev, +				"regulator %d preinit failed, e %d\n", id, err); +			return err; +		} -	regulator_unregister(rdev); +		config.dev = pdev->dev.parent; +		config.init_data = reg_data; +		config.driver_data = ri; + +		if (tps6586x_reg_matches) +			config.of_node = tps6586x_reg_matches[id].of_node; + +		rdev = devm_regulator_register(&pdev->dev, &ri->desc, &config); +		if (IS_ERR(rdev)) { +			dev_err(&pdev->dev, "failed to register regulator %s\n", +					ri->desc.name); +			return PTR_ERR(rdev); +		} + +		if (reg_data) { +			err = tps6586x_regulator_set_slew_rate(pdev, id, +					reg_data); +			if (err < 0) { +				dev_err(&pdev->dev, +					"Slew rate config failed, e %d\n", err); +				return err; +			} +		} +	} + +	platform_set_drvdata(pdev, rdev);  	return 0;  } @@ -375,7 +518,6 @@ static struct platform_driver tps6586x_regulator_driver = {  		.owner	= THIS_MODULE,  	},  	.probe		= tps6586x_regulator_probe, -	.remove		= __devexit_p(tps6586x_regulator_remove),  };  static int __init tps6586x_regulator_init(void)  | 
