xref: /openbmc/linux/drivers/regulator/tps6507x-regulator.c (revision 4ce5ba5ba2dfc8186bf31fe7f2d23ff6b5384124)
13fa5b8e0SAnuj Aggarwal /*
23fa5b8e0SAnuj Aggarwal  * tps6507x-regulator.c
33fa5b8e0SAnuj Aggarwal  *
43fa5b8e0SAnuj Aggarwal  * Regulator driver for TPS65073 PMIC
53fa5b8e0SAnuj Aggarwal  *
63fa5b8e0SAnuj Aggarwal  * Copyright (C) 2009 Texas Instrument Incorporated - http://www.ti.com/
73fa5b8e0SAnuj Aggarwal  *
83fa5b8e0SAnuj Aggarwal  * This program is free software; you can redistribute it and/or
93fa5b8e0SAnuj Aggarwal  * modify it under the terms of the GNU General Public License as
103fa5b8e0SAnuj Aggarwal  * published by the Free Software Foundation version 2.
113fa5b8e0SAnuj Aggarwal  *
123fa5b8e0SAnuj Aggarwal  * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind,
133fa5b8e0SAnuj Aggarwal  * whether express or implied; without even the implied warranty of
143fa5b8e0SAnuj Aggarwal  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
153fa5b8e0SAnuj Aggarwal  * General Public License for more details.
163fa5b8e0SAnuj Aggarwal  */
173fa5b8e0SAnuj Aggarwal 
183fa5b8e0SAnuj Aggarwal #include <linux/kernel.h>
193fa5b8e0SAnuj Aggarwal #include <linux/module.h>
203fa5b8e0SAnuj Aggarwal #include <linux/init.h>
213fa5b8e0SAnuj Aggarwal #include <linux/err.h>
223fa5b8e0SAnuj Aggarwal #include <linux/platform_device.h>
233fa5b8e0SAnuj Aggarwal #include <linux/regulator/driver.h>
243fa5b8e0SAnuj Aggarwal #include <linux/regulator/machine.h>
253fa5b8e0SAnuj Aggarwal #include <linux/i2c.h>
263fa5b8e0SAnuj Aggarwal #include <linux/delay.h>
275a0e3ad6STejun Heo #include <linux/slab.h>
28d183fcc9STodd Fischer #include <linux/mfd/tps6507x.h>
293fa5b8e0SAnuj Aggarwal 
303fa5b8e0SAnuj Aggarwal /* DCDC's */
313fa5b8e0SAnuj Aggarwal #define TPS6507X_DCDC_1				0
323fa5b8e0SAnuj Aggarwal #define TPS6507X_DCDC_2				1
333fa5b8e0SAnuj Aggarwal #define TPS6507X_DCDC_3				2
343fa5b8e0SAnuj Aggarwal /* LDOs */
353fa5b8e0SAnuj Aggarwal #define TPS6507X_LDO_1				3
363fa5b8e0SAnuj Aggarwal #define TPS6507X_LDO_2				4
373fa5b8e0SAnuj Aggarwal 
383fa5b8e0SAnuj Aggarwal #define TPS6507X_MAX_REG_ID			TPS6507X_LDO_2
393fa5b8e0SAnuj Aggarwal 
403fa5b8e0SAnuj Aggarwal /* Number of step-down converters available */
413fa5b8e0SAnuj Aggarwal #define TPS6507X_NUM_DCDC			3
423fa5b8e0SAnuj Aggarwal /* Number of LDO voltage regulators  available */
433fa5b8e0SAnuj Aggarwal #define TPS6507X_NUM_LDO			2
443fa5b8e0SAnuj Aggarwal /* Number of total regulators available */
453fa5b8e0SAnuj Aggarwal #define TPS6507X_NUM_REGULATOR		(TPS6507X_NUM_DCDC + TPS6507X_NUM_LDO)
463fa5b8e0SAnuj Aggarwal 
473fa5b8e0SAnuj Aggarwal /* Supported voltage values for regulators (in milliVolts) */
483fa5b8e0SAnuj Aggarwal static const u16 VDCDCx_VSEL_table[] = {
493fa5b8e0SAnuj Aggarwal 	725, 750, 775, 800,
503fa5b8e0SAnuj Aggarwal 	825, 850, 875, 900,
513fa5b8e0SAnuj Aggarwal 	925, 950, 975, 1000,
523fa5b8e0SAnuj Aggarwal 	1025, 1050, 1075, 1100,
533fa5b8e0SAnuj Aggarwal 	1125, 1150, 1175, 1200,
543fa5b8e0SAnuj Aggarwal 	1225, 1250, 1275, 1300,
553fa5b8e0SAnuj Aggarwal 	1325, 1350, 1375, 1400,
563fa5b8e0SAnuj Aggarwal 	1425, 1450, 1475, 1500,
573fa5b8e0SAnuj Aggarwal 	1550, 1600, 1650, 1700,
583fa5b8e0SAnuj Aggarwal 	1750, 1800, 1850, 1900,
593fa5b8e0SAnuj Aggarwal 	1950, 2000, 2050, 2100,
603fa5b8e0SAnuj Aggarwal 	2150, 2200, 2250, 2300,
613fa5b8e0SAnuj Aggarwal 	2350, 2400, 2450, 2500,
623fa5b8e0SAnuj Aggarwal 	2550, 2600, 2650, 2700,
633fa5b8e0SAnuj Aggarwal 	2750, 2800, 2850, 2900,
643fa5b8e0SAnuj Aggarwal 	3000, 3100, 3200, 3300,
653fa5b8e0SAnuj Aggarwal };
663fa5b8e0SAnuj Aggarwal 
673fa5b8e0SAnuj Aggarwal static const u16 LDO1_VSEL_table[] = {
683fa5b8e0SAnuj Aggarwal 	1000, 1100, 1200, 1250,
693fa5b8e0SAnuj Aggarwal 	1300, 1350, 1400, 1500,
703fa5b8e0SAnuj Aggarwal 	1600, 1800, 2500, 2750,
713fa5b8e0SAnuj Aggarwal 	2800, 3000, 3100, 3300,
723fa5b8e0SAnuj Aggarwal };
733fa5b8e0SAnuj Aggarwal 
743fa5b8e0SAnuj Aggarwal static const u16 LDO2_VSEL_table[] = {
753fa5b8e0SAnuj Aggarwal 	725, 750, 775, 800,
763fa5b8e0SAnuj Aggarwal 	825, 850, 875, 900,
773fa5b8e0SAnuj Aggarwal 	925, 950, 975, 1000,
783fa5b8e0SAnuj Aggarwal 	1025, 1050, 1075, 1100,
793fa5b8e0SAnuj Aggarwal 	1125, 1150, 1175, 1200,
803fa5b8e0SAnuj Aggarwal 	1225, 1250, 1275, 1300,
813fa5b8e0SAnuj Aggarwal 	1325, 1350, 1375, 1400,
823fa5b8e0SAnuj Aggarwal 	1425, 1450, 1475, 1500,
833fa5b8e0SAnuj Aggarwal 	1550, 1600, 1650, 1700,
843fa5b8e0SAnuj Aggarwal 	1750, 1800, 1850, 1900,
853fa5b8e0SAnuj Aggarwal 	1950, 2000, 2050, 2100,
863fa5b8e0SAnuj Aggarwal 	2150, 2200, 2250, 2300,
873fa5b8e0SAnuj Aggarwal 	2350, 2400, 2450, 2500,
883fa5b8e0SAnuj Aggarwal 	2550, 2600, 2650, 2700,
893fa5b8e0SAnuj Aggarwal 	2750, 2800, 2850, 2900,
903fa5b8e0SAnuj Aggarwal 	3000, 3100, 3200, 3300,
913fa5b8e0SAnuj Aggarwal };
923fa5b8e0SAnuj Aggarwal 
933fa5b8e0SAnuj Aggarwal static unsigned int num_voltages[] = {ARRAY_SIZE(VDCDCx_VSEL_table),
943fa5b8e0SAnuj Aggarwal 				ARRAY_SIZE(VDCDCx_VSEL_table),
953fa5b8e0SAnuj Aggarwal 				ARRAY_SIZE(VDCDCx_VSEL_table),
963fa5b8e0SAnuj Aggarwal 				ARRAY_SIZE(LDO1_VSEL_table),
973fa5b8e0SAnuj Aggarwal 				ARRAY_SIZE(LDO2_VSEL_table)};
983fa5b8e0SAnuj Aggarwal 
993fa5b8e0SAnuj Aggarwal struct tps_info {
1003fa5b8e0SAnuj Aggarwal 	const char *name;
1013fa5b8e0SAnuj Aggarwal 	unsigned min_uV;
1023fa5b8e0SAnuj Aggarwal 	unsigned max_uV;
1033fa5b8e0SAnuj Aggarwal 	u8 table_len;
1043fa5b8e0SAnuj Aggarwal 	const u16 *table;
1053fa5b8e0SAnuj Aggarwal };
1063fa5b8e0SAnuj Aggarwal 
107*4ce5ba5bSTodd Fischer struct tps6507x_pmic {
1083fa5b8e0SAnuj Aggarwal 	struct regulator_desc desc[TPS6507X_NUM_REGULATOR];
1093fa5b8e0SAnuj Aggarwal 	struct i2c_client *client;
1103fa5b8e0SAnuj Aggarwal 	struct regulator_dev *rdev[TPS6507X_NUM_REGULATOR];
1113fa5b8e0SAnuj Aggarwal 	const struct tps_info *info[TPS6507X_NUM_REGULATOR];
1123fa5b8e0SAnuj Aggarwal 	struct mutex io_lock;
1133fa5b8e0SAnuj Aggarwal };
1143fa5b8e0SAnuj Aggarwal 
115*4ce5ba5bSTodd Fischer static inline int tps6507x_pmic_read(struct tps6507x_pmic *tps, u8 reg)
1163fa5b8e0SAnuj Aggarwal {
1173fa5b8e0SAnuj Aggarwal 	return i2c_smbus_read_byte_data(tps->client, reg);
1183fa5b8e0SAnuj Aggarwal }
1193fa5b8e0SAnuj Aggarwal 
120*4ce5ba5bSTodd Fischer static inline int tps6507x_pmic_write(struct tps6507x_pmic *tps, u8 reg, u8 val)
1213fa5b8e0SAnuj Aggarwal {
1223fa5b8e0SAnuj Aggarwal 	return i2c_smbus_write_byte_data(tps->client, reg, val);
1233fa5b8e0SAnuj Aggarwal }
1243fa5b8e0SAnuj Aggarwal 
125*4ce5ba5bSTodd Fischer static int tps6507x_pmic_set_bits(struct tps6507x_pmic *tps, u8 reg, u8 mask)
1263fa5b8e0SAnuj Aggarwal {
1273fa5b8e0SAnuj Aggarwal 	int err, data;
1283fa5b8e0SAnuj Aggarwal 
1293fa5b8e0SAnuj Aggarwal 	mutex_lock(&tps->io_lock);
1303fa5b8e0SAnuj Aggarwal 
131*4ce5ba5bSTodd Fischer 	data = tps6507x_pmic_read(tps, reg);
1323fa5b8e0SAnuj Aggarwal 	if (data < 0) {
1333fa5b8e0SAnuj Aggarwal 		dev_err(&tps->client->dev, "Read from reg 0x%x failed\n", reg);
1343fa5b8e0SAnuj Aggarwal 		err = data;
1353fa5b8e0SAnuj Aggarwal 		goto out;
1363fa5b8e0SAnuj Aggarwal 	}
1373fa5b8e0SAnuj Aggarwal 
1383fa5b8e0SAnuj Aggarwal 	data |= mask;
139*4ce5ba5bSTodd Fischer 	err = tps6507x_pmic_write(tps, reg, data);
1403fa5b8e0SAnuj Aggarwal 	if (err)
1413fa5b8e0SAnuj Aggarwal 		dev_err(&tps->client->dev, "Write for reg 0x%x failed\n", reg);
1423fa5b8e0SAnuj Aggarwal 
1433fa5b8e0SAnuj Aggarwal out:
1443fa5b8e0SAnuj Aggarwal 	mutex_unlock(&tps->io_lock);
1453fa5b8e0SAnuj Aggarwal 	return err;
1463fa5b8e0SAnuj Aggarwal }
1473fa5b8e0SAnuj Aggarwal 
148*4ce5ba5bSTodd Fischer static int tps6507x_pmic_clear_bits(struct tps6507x_pmic *tps, u8 reg, u8 mask)
1493fa5b8e0SAnuj Aggarwal {
1503fa5b8e0SAnuj Aggarwal 	int err, data;
1513fa5b8e0SAnuj Aggarwal 
1523fa5b8e0SAnuj Aggarwal 	mutex_lock(&tps->io_lock);
1533fa5b8e0SAnuj Aggarwal 
154*4ce5ba5bSTodd Fischer 	data = tps6507x_pmic_read(tps, reg);
1553fa5b8e0SAnuj Aggarwal 	if (data < 0) {
1563fa5b8e0SAnuj Aggarwal 		dev_err(&tps->client->dev, "Read from reg 0x%x failed\n", reg);
1573fa5b8e0SAnuj Aggarwal 		err = data;
1583fa5b8e0SAnuj Aggarwal 		goto out;
1593fa5b8e0SAnuj Aggarwal 	}
1603fa5b8e0SAnuj Aggarwal 
1613fa5b8e0SAnuj Aggarwal 	data &= ~mask;
162*4ce5ba5bSTodd Fischer 	err = tps6507x_pmic_write(tps, reg, data);
1633fa5b8e0SAnuj Aggarwal 	if (err)
1643fa5b8e0SAnuj Aggarwal 		dev_err(&tps->client->dev, "Write for reg 0x%x failed\n", reg);
1653fa5b8e0SAnuj Aggarwal 
1663fa5b8e0SAnuj Aggarwal out:
1673fa5b8e0SAnuj Aggarwal 	mutex_unlock(&tps->io_lock);
1683fa5b8e0SAnuj Aggarwal 	return err;
1693fa5b8e0SAnuj Aggarwal }
1703fa5b8e0SAnuj Aggarwal 
171*4ce5ba5bSTodd Fischer static int tps6507x_pmic_reg_read(struct tps6507x_pmic *tps, u8 reg)
1723fa5b8e0SAnuj Aggarwal {
1733fa5b8e0SAnuj Aggarwal 	int data;
1743fa5b8e0SAnuj Aggarwal 
1753fa5b8e0SAnuj Aggarwal 	mutex_lock(&tps->io_lock);
1763fa5b8e0SAnuj Aggarwal 
177*4ce5ba5bSTodd Fischer 	data = tps6507x_pmic_read(tps, reg);
1783fa5b8e0SAnuj Aggarwal 	if (data < 0)
1793fa5b8e0SAnuj Aggarwal 		dev_err(&tps->client->dev, "Read from reg 0x%x failed\n", reg);
1803fa5b8e0SAnuj Aggarwal 
1813fa5b8e0SAnuj Aggarwal 	mutex_unlock(&tps->io_lock);
1823fa5b8e0SAnuj Aggarwal 	return data;
1833fa5b8e0SAnuj Aggarwal }
1843fa5b8e0SAnuj Aggarwal 
185*4ce5ba5bSTodd Fischer static int tps6507x_pmic_reg_write(struct tps6507x_pmic *tps, u8 reg, u8 val)
1863fa5b8e0SAnuj Aggarwal {
1873fa5b8e0SAnuj Aggarwal 	int err;
1883fa5b8e0SAnuj Aggarwal 
1893fa5b8e0SAnuj Aggarwal 	mutex_lock(&tps->io_lock);
1903fa5b8e0SAnuj Aggarwal 
191*4ce5ba5bSTodd Fischer 	err = tps6507x_pmic_write(tps, reg, val);
1923fa5b8e0SAnuj Aggarwal 	if (err < 0)
1933fa5b8e0SAnuj Aggarwal 		dev_err(&tps->client->dev, "Write for reg 0x%x failed\n", reg);
1943fa5b8e0SAnuj Aggarwal 
1953fa5b8e0SAnuj Aggarwal 	mutex_unlock(&tps->io_lock);
1963fa5b8e0SAnuj Aggarwal 	return err;
1973fa5b8e0SAnuj Aggarwal }
1983fa5b8e0SAnuj Aggarwal 
199*4ce5ba5bSTodd Fischer static int tps6507x_pmic_dcdc_is_enabled(struct regulator_dev *dev)
2003fa5b8e0SAnuj Aggarwal {
201*4ce5ba5bSTodd Fischer 	struct tps6507x_pmic *tps = rdev_get_drvdata(dev);
2023fa5b8e0SAnuj Aggarwal 	int data, dcdc = rdev_get_id(dev);
2033fa5b8e0SAnuj Aggarwal 	u8 shift;
2043fa5b8e0SAnuj Aggarwal 
2053fa5b8e0SAnuj Aggarwal 	if (dcdc < TPS6507X_DCDC_1 || dcdc > TPS6507X_DCDC_3)
2063fa5b8e0SAnuj Aggarwal 		return -EINVAL;
2073fa5b8e0SAnuj Aggarwal 
2083fa5b8e0SAnuj Aggarwal 	shift = TPS6507X_MAX_REG_ID - dcdc;
209*4ce5ba5bSTodd Fischer 	data = tps6507x_pmic_reg_read(tps, TPS6507X_REG_CON_CTRL1);
2103fa5b8e0SAnuj Aggarwal 
2113fa5b8e0SAnuj Aggarwal 	if (data < 0)
2123fa5b8e0SAnuj Aggarwal 		return data;
2133fa5b8e0SAnuj Aggarwal 	else
2143fa5b8e0SAnuj Aggarwal 		return (data & 1<<shift) ? 1 : 0;
2153fa5b8e0SAnuj Aggarwal }
2163fa5b8e0SAnuj Aggarwal 
217*4ce5ba5bSTodd Fischer static int tps6507x_pmic_ldo_is_enabled(struct regulator_dev *dev)
2183fa5b8e0SAnuj Aggarwal {
219*4ce5ba5bSTodd Fischer 	struct tps6507x_pmic *tps = rdev_get_drvdata(dev);
2203fa5b8e0SAnuj Aggarwal 	int data, ldo = rdev_get_id(dev);
2213fa5b8e0SAnuj Aggarwal 	u8 shift;
2223fa5b8e0SAnuj Aggarwal 
2233fa5b8e0SAnuj Aggarwal 	if (ldo < TPS6507X_LDO_1 || ldo > TPS6507X_LDO_2)
2243fa5b8e0SAnuj Aggarwal 		return -EINVAL;
2253fa5b8e0SAnuj Aggarwal 
2263fa5b8e0SAnuj Aggarwal 	shift = TPS6507X_MAX_REG_ID - ldo;
227*4ce5ba5bSTodd Fischer 	data = tps6507x_pmic_reg_read(tps, TPS6507X_REG_CON_CTRL1);
2283fa5b8e0SAnuj Aggarwal 
2293fa5b8e0SAnuj Aggarwal 	if (data < 0)
2303fa5b8e0SAnuj Aggarwal 		return data;
2313fa5b8e0SAnuj Aggarwal 	else
2323fa5b8e0SAnuj Aggarwal 		return (data & 1<<shift) ? 1 : 0;
2333fa5b8e0SAnuj Aggarwal }
2343fa5b8e0SAnuj Aggarwal 
235*4ce5ba5bSTodd Fischer static int tps6507x_pmic_dcdc_enable(struct regulator_dev *dev)
2363fa5b8e0SAnuj Aggarwal {
237*4ce5ba5bSTodd Fischer 	struct tps6507x_pmic *tps = rdev_get_drvdata(dev);
2383fa5b8e0SAnuj Aggarwal 	int dcdc = rdev_get_id(dev);
2393fa5b8e0SAnuj Aggarwal 	u8 shift;
2403fa5b8e0SAnuj Aggarwal 
2413fa5b8e0SAnuj Aggarwal 	if (dcdc < TPS6507X_DCDC_1 || dcdc > TPS6507X_DCDC_3)
2423fa5b8e0SAnuj Aggarwal 		return -EINVAL;
2433fa5b8e0SAnuj Aggarwal 
2443fa5b8e0SAnuj Aggarwal 	shift = TPS6507X_MAX_REG_ID - dcdc;
245*4ce5ba5bSTodd Fischer 	return tps6507x_pmic_set_bits(tps, TPS6507X_REG_CON_CTRL1, 1 << shift);
2463fa5b8e0SAnuj Aggarwal }
2473fa5b8e0SAnuj Aggarwal 
248*4ce5ba5bSTodd Fischer static int tps6507x_pmic_dcdc_disable(struct regulator_dev *dev)
2493fa5b8e0SAnuj Aggarwal {
250*4ce5ba5bSTodd Fischer 	struct tps6507x_pmic *tps = rdev_get_drvdata(dev);
2513fa5b8e0SAnuj Aggarwal 	int dcdc = rdev_get_id(dev);
2523fa5b8e0SAnuj Aggarwal 	u8 shift;
2533fa5b8e0SAnuj Aggarwal 
2543fa5b8e0SAnuj Aggarwal 	if (dcdc < TPS6507X_DCDC_1 || dcdc > TPS6507X_DCDC_3)
2553fa5b8e0SAnuj Aggarwal 		return -EINVAL;
2563fa5b8e0SAnuj Aggarwal 
2573fa5b8e0SAnuj Aggarwal 	shift = TPS6507X_MAX_REG_ID - dcdc;
258*4ce5ba5bSTodd Fischer 	return tps6507x_pmic_clear_bits(tps, TPS6507X_REG_CON_CTRL1,
259*4ce5ba5bSTodd Fischer 					1 << shift);
2603fa5b8e0SAnuj Aggarwal }
2613fa5b8e0SAnuj Aggarwal 
262*4ce5ba5bSTodd Fischer static int tps6507x_pmic_ldo_enable(struct regulator_dev *dev)
2633fa5b8e0SAnuj Aggarwal {
264*4ce5ba5bSTodd Fischer 	struct tps6507x_pmic *tps = rdev_get_drvdata(dev);
2653fa5b8e0SAnuj Aggarwal 	int ldo = rdev_get_id(dev);
2663fa5b8e0SAnuj Aggarwal 	u8 shift;
2673fa5b8e0SAnuj Aggarwal 
2683fa5b8e0SAnuj Aggarwal 	if (ldo < TPS6507X_LDO_1 || ldo > TPS6507X_LDO_2)
2693fa5b8e0SAnuj Aggarwal 		return -EINVAL;
2703fa5b8e0SAnuj Aggarwal 
2713fa5b8e0SAnuj Aggarwal 	shift = TPS6507X_MAX_REG_ID - ldo;
272*4ce5ba5bSTodd Fischer 	return tps6507x_pmic_set_bits(tps, TPS6507X_REG_CON_CTRL1, 1 << shift);
2733fa5b8e0SAnuj Aggarwal }
2743fa5b8e0SAnuj Aggarwal 
275*4ce5ba5bSTodd Fischer static int tps6507x_pmic_ldo_disable(struct regulator_dev *dev)
2763fa5b8e0SAnuj Aggarwal {
277*4ce5ba5bSTodd Fischer 	struct tps6507x_pmic *tps = rdev_get_drvdata(dev);
2783fa5b8e0SAnuj Aggarwal 	int ldo = rdev_get_id(dev);
2793fa5b8e0SAnuj Aggarwal 	u8 shift;
2803fa5b8e0SAnuj Aggarwal 
2813fa5b8e0SAnuj Aggarwal 	if (ldo < TPS6507X_LDO_1 || ldo > TPS6507X_LDO_2)
2823fa5b8e0SAnuj Aggarwal 		return -EINVAL;
2833fa5b8e0SAnuj Aggarwal 
2843fa5b8e0SAnuj Aggarwal 	shift = TPS6507X_MAX_REG_ID - ldo;
285*4ce5ba5bSTodd Fischer 	return tps6507x_pmic_clear_bits(tps, TPS6507X_REG_CON_CTRL1,
286*4ce5ba5bSTodd Fischer 					1 << shift);
2873fa5b8e0SAnuj Aggarwal }
2883fa5b8e0SAnuj Aggarwal 
289*4ce5ba5bSTodd Fischer static int tps6507x_pmic_dcdc_get_voltage(struct regulator_dev *dev)
2903fa5b8e0SAnuj Aggarwal {
291*4ce5ba5bSTodd Fischer 	struct tps6507x_pmic *tps = rdev_get_drvdata(dev);
2923fa5b8e0SAnuj Aggarwal 	int data, dcdc = rdev_get_id(dev);
2933fa5b8e0SAnuj Aggarwal 	u8 reg;
2943fa5b8e0SAnuj Aggarwal 
2953fa5b8e0SAnuj Aggarwal 	switch (dcdc) {
2963fa5b8e0SAnuj Aggarwal 	case TPS6507X_DCDC_1:
2973fa5b8e0SAnuj Aggarwal 		reg = TPS6507X_REG_DEFDCDC1;
2983fa5b8e0SAnuj Aggarwal 		break;
2993fa5b8e0SAnuj Aggarwal 	case TPS6507X_DCDC_2:
3003fa5b8e0SAnuj Aggarwal 		reg = TPS6507X_REG_DEFDCDC2_LOW;
3013fa5b8e0SAnuj Aggarwal 		break;
3023fa5b8e0SAnuj Aggarwal 	case TPS6507X_DCDC_3:
3033fa5b8e0SAnuj Aggarwal 		reg = TPS6507X_REG_DEFDCDC3_LOW;
3043fa5b8e0SAnuj Aggarwal 		break;
3053fa5b8e0SAnuj Aggarwal 	default:
3063fa5b8e0SAnuj Aggarwal 		return -EINVAL;
3073fa5b8e0SAnuj Aggarwal 	}
3083fa5b8e0SAnuj Aggarwal 
309*4ce5ba5bSTodd Fischer 	data = tps6507x_pmic_reg_read(tps, reg);
3103fa5b8e0SAnuj Aggarwal 	if (data < 0)
3113fa5b8e0SAnuj Aggarwal 		return data;
3123fa5b8e0SAnuj Aggarwal 
3133fa5b8e0SAnuj Aggarwal 	data &= TPS6507X_DEFDCDCX_DCDC_MASK;
3143fa5b8e0SAnuj Aggarwal 	return tps->info[dcdc]->table[data] * 1000;
3153fa5b8e0SAnuj Aggarwal }
3163fa5b8e0SAnuj Aggarwal 
317*4ce5ba5bSTodd Fischer static int tps6507x_pmic_dcdc_set_voltage(struct regulator_dev *dev,
3183fa5b8e0SAnuj Aggarwal 				int min_uV, int max_uV)
3193fa5b8e0SAnuj Aggarwal {
320*4ce5ba5bSTodd Fischer 	struct tps6507x_pmic *tps = rdev_get_drvdata(dev);
3213fa5b8e0SAnuj Aggarwal 	int data, vsel, dcdc = rdev_get_id(dev);
3223fa5b8e0SAnuj Aggarwal 	u8 reg;
3233fa5b8e0SAnuj Aggarwal 
3243fa5b8e0SAnuj Aggarwal 	switch (dcdc) {
3253fa5b8e0SAnuj Aggarwal 	case TPS6507X_DCDC_1:
3263fa5b8e0SAnuj Aggarwal 		reg = TPS6507X_REG_DEFDCDC1;
3273fa5b8e0SAnuj Aggarwal 		break;
3283fa5b8e0SAnuj Aggarwal 	case TPS6507X_DCDC_2:
3293fa5b8e0SAnuj Aggarwal 		reg = TPS6507X_REG_DEFDCDC2_LOW;
3303fa5b8e0SAnuj Aggarwal 		break;
3313fa5b8e0SAnuj Aggarwal 	case TPS6507X_DCDC_3:
3323fa5b8e0SAnuj Aggarwal 		reg = TPS6507X_REG_DEFDCDC3_LOW;
3333fa5b8e0SAnuj Aggarwal 		break;
3343fa5b8e0SAnuj Aggarwal 	default:
3353fa5b8e0SAnuj Aggarwal 		return -EINVAL;
3363fa5b8e0SAnuj Aggarwal 	}
3373fa5b8e0SAnuj Aggarwal 
3383fa5b8e0SAnuj Aggarwal 	if (min_uV < tps->info[dcdc]->min_uV
3393fa5b8e0SAnuj Aggarwal 		|| min_uV > tps->info[dcdc]->max_uV)
3403fa5b8e0SAnuj Aggarwal 		return -EINVAL;
3413fa5b8e0SAnuj Aggarwal 	if (max_uV < tps->info[dcdc]->min_uV
3423fa5b8e0SAnuj Aggarwal 		|| max_uV > tps->info[dcdc]->max_uV)
3433fa5b8e0SAnuj Aggarwal 		return -EINVAL;
3443fa5b8e0SAnuj Aggarwal 
3453fa5b8e0SAnuj Aggarwal 	for (vsel = 0; vsel < tps->info[dcdc]->table_len; vsel++) {
3463fa5b8e0SAnuj Aggarwal 		int mV = tps->info[dcdc]->table[vsel];
3473fa5b8e0SAnuj Aggarwal 		int uV = mV * 1000;
3483fa5b8e0SAnuj Aggarwal 
3493fa5b8e0SAnuj Aggarwal 		/* Break at the first in-range value */
3503fa5b8e0SAnuj Aggarwal 		if (min_uV <= uV && uV <= max_uV)
3513fa5b8e0SAnuj Aggarwal 			break;
3523fa5b8e0SAnuj Aggarwal 	}
3533fa5b8e0SAnuj Aggarwal 
3543fa5b8e0SAnuj Aggarwal 	/* write to the register in case we found a match */
3553fa5b8e0SAnuj Aggarwal 	if (vsel == tps->info[dcdc]->table_len)
3563fa5b8e0SAnuj Aggarwal 		return -EINVAL;
3573fa5b8e0SAnuj Aggarwal 
358*4ce5ba5bSTodd Fischer 	data = tps6507x_pmic_reg_read(tps, reg);
3593fa5b8e0SAnuj Aggarwal 	if (data < 0)
3603fa5b8e0SAnuj Aggarwal 		return data;
3613fa5b8e0SAnuj Aggarwal 
3623fa5b8e0SAnuj Aggarwal 	data &= ~TPS6507X_DEFDCDCX_DCDC_MASK;
3633fa5b8e0SAnuj Aggarwal 	data |= vsel;
3643fa5b8e0SAnuj Aggarwal 
365*4ce5ba5bSTodd Fischer 	return tps6507x_pmic_reg_write(tps, reg, data);
3663fa5b8e0SAnuj Aggarwal }
3673fa5b8e0SAnuj Aggarwal 
368*4ce5ba5bSTodd Fischer static int tps6507x_pmic_ldo_get_voltage(struct regulator_dev *dev)
3693fa5b8e0SAnuj Aggarwal {
370*4ce5ba5bSTodd Fischer 	struct tps6507x_pmic *tps = rdev_get_drvdata(dev);
3713fa5b8e0SAnuj Aggarwal 	int data, ldo = rdev_get_id(dev);
3723fa5b8e0SAnuj Aggarwal 	u8 reg, mask;
3733fa5b8e0SAnuj Aggarwal 
3743fa5b8e0SAnuj Aggarwal 	if (ldo < TPS6507X_LDO_1 || ldo > TPS6507X_LDO_2)
3753fa5b8e0SAnuj Aggarwal 		return -EINVAL;
3763fa5b8e0SAnuj Aggarwal 	else {
3773fa5b8e0SAnuj Aggarwal 		reg = (ldo == TPS6507X_LDO_1 ?
3783fa5b8e0SAnuj Aggarwal 			TPS6507X_REG_LDO_CTRL1 : TPS6507X_REG_DEFLDO2);
3793fa5b8e0SAnuj Aggarwal 		mask = (ldo == TPS6507X_LDO_1 ?
3803fa5b8e0SAnuj Aggarwal 			TPS6507X_REG_LDO_CTRL1_LDO1_MASK :
3813fa5b8e0SAnuj Aggarwal 				TPS6507X_REG_DEFLDO2_LDO2_MASK);
3823fa5b8e0SAnuj Aggarwal 	}
3833fa5b8e0SAnuj Aggarwal 
384*4ce5ba5bSTodd Fischer 	data = tps6507x_pmic_reg_read(tps, reg);
3853fa5b8e0SAnuj Aggarwal 	if (data < 0)
3863fa5b8e0SAnuj Aggarwal 		return data;
3873fa5b8e0SAnuj Aggarwal 
3883fa5b8e0SAnuj Aggarwal 	data &= mask;
3893fa5b8e0SAnuj Aggarwal 	return tps->info[ldo]->table[data] * 1000;
3903fa5b8e0SAnuj Aggarwal }
3913fa5b8e0SAnuj Aggarwal 
392*4ce5ba5bSTodd Fischer static int tps6507x_pmic_ldo_set_voltage(struct regulator_dev *dev,
3933fa5b8e0SAnuj Aggarwal 				int min_uV, int max_uV)
3943fa5b8e0SAnuj Aggarwal {
395*4ce5ba5bSTodd Fischer 	struct tps6507x_pmic *tps = rdev_get_drvdata(dev);
3963fa5b8e0SAnuj Aggarwal 	int data, vsel, ldo = rdev_get_id(dev);
3973fa5b8e0SAnuj Aggarwal 	u8 reg, mask;
3983fa5b8e0SAnuj Aggarwal 
3993fa5b8e0SAnuj Aggarwal 	if (ldo < TPS6507X_LDO_1 || ldo > TPS6507X_LDO_2)
4003fa5b8e0SAnuj Aggarwal 		return -EINVAL;
4013fa5b8e0SAnuj Aggarwal 	else {
4023fa5b8e0SAnuj Aggarwal 		reg = (ldo == TPS6507X_LDO_1 ?
4033fa5b8e0SAnuj Aggarwal 			TPS6507X_REG_LDO_CTRL1 : TPS6507X_REG_DEFLDO2);
4043fa5b8e0SAnuj Aggarwal 		mask = (ldo == TPS6507X_LDO_1 ?
4053fa5b8e0SAnuj Aggarwal 			TPS6507X_REG_LDO_CTRL1_LDO1_MASK :
4063fa5b8e0SAnuj Aggarwal 				TPS6507X_REG_DEFLDO2_LDO2_MASK);
4073fa5b8e0SAnuj Aggarwal 	}
4083fa5b8e0SAnuj Aggarwal 
4093fa5b8e0SAnuj Aggarwal 	if (min_uV < tps->info[ldo]->min_uV || min_uV > tps->info[ldo]->max_uV)
4103fa5b8e0SAnuj Aggarwal 		return -EINVAL;
4113fa5b8e0SAnuj Aggarwal 	if (max_uV < tps->info[ldo]->min_uV || max_uV > tps->info[ldo]->max_uV)
4123fa5b8e0SAnuj Aggarwal 		return -EINVAL;
4133fa5b8e0SAnuj Aggarwal 
4143fa5b8e0SAnuj Aggarwal 	for (vsel = 0; vsel < tps->info[ldo]->table_len; vsel++) {
4153fa5b8e0SAnuj Aggarwal 		int mV = tps->info[ldo]->table[vsel];
4163fa5b8e0SAnuj Aggarwal 		int uV = mV * 1000;
4173fa5b8e0SAnuj Aggarwal 
4183fa5b8e0SAnuj Aggarwal 		/* Break at the first in-range value */
4193fa5b8e0SAnuj Aggarwal 		if (min_uV <= uV && uV <= max_uV)
4203fa5b8e0SAnuj Aggarwal 			break;
4213fa5b8e0SAnuj Aggarwal 	}
4223fa5b8e0SAnuj Aggarwal 
4233fa5b8e0SAnuj Aggarwal 	if (vsel == tps->info[ldo]->table_len)
4243fa5b8e0SAnuj Aggarwal 		return -EINVAL;
4253fa5b8e0SAnuj Aggarwal 
426*4ce5ba5bSTodd Fischer 	data = tps6507x_pmic_reg_read(tps, reg);
4273fa5b8e0SAnuj Aggarwal 	if (data < 0)
4283fa5b8e0SAnuj Aggarwal 		return data;
4293fa5b8e0SAnuj Aggarwal 
4303fa5b8e0SAnuj Aggarwal 	data &= ~mask;
4313fa5b8e0SAnuj Aggarwal 	data |= vsel;
4323fa5b8e0SAnuj Aggarwal 
433*4ce5ba5bSTodd Fischer 	return tps6507x_pmic_reg_write(tps, reg, data);
4343fa5b8e0SAnuj Aggarwal }
4353fa5b8e0SAnuj Aggarwal 
436*4ce5ba5bSTodd Fischer static int tps6507x_pmic_dcdc_list_voltage(struct regulator_dev *dev,
4373fa5b8e0SAnuj Aggarwal 					unsigned selector)
4383fa5b8e0SAnuj Aggarwal {
439*4ce5ba5bSTodd Fischer 	struct tps6507x_pmic *tps = rdev_get_drvdata(dev);
4403fa5b8e0SAnuj Aggarwal 	int dcdc = rdev_get_id(dev);
4413fa5b8e0SAnuj Aggarwal 
4423fa5b8e0SAnuj Aggarwal 	if (dcdc < TPS6507X_DCDC_1 || dcdc > TPS6507X_DCDC_3)
4433fa5b8e0SAnuj Aggarwal 		return -EINVAL;
4443fa5b8e0SAnuj Aggarwal 
4453fa5b8e0SAnuj Aggarwal 	if (selector >= tps->info[dcdc]->table_len)
4463fa5b8e0SAnuj Aggarwal 		return -EINVAL;
4473fa5b8e0SAnuj Aggarwal 	else
4483fa5b8e0SAnuj Aggarwal 		return tps->info[dcdc]->table[selector] * 1000;
4493fa5b8e0SAnuj Aggarwal }
4503fa5b8e0SAnuj Aggarwal 
451*4ce5ba5bSTodd Fischer static int tps6507x_pmic_ldo_list_voltage(struct regulator_dev *dev,
4523fa5b8e0SAnuj Aggarwal 					unsigned selector)
4533fa5b8e0SAnuj Aggarwal {
454*4ce5ba5bSTodd Fischer 	struct tps6507x_pmic *tps = rdev_get_drvdata(dev);
4553fa5b8e0SAnuj Aggarwal 	int ldo = rdev_get_id(dev);
4563fa5b8e0SAnuj Aggarwal 
4573fa5b8e0SAnuj Aggarwal 	if (ldo < TPS6507X_LDO_1 || ldo > TPS6507X_LDO_2)
4583fa5b8e0SAnuj Aggarwal 		return -EINVAL;
4593fa5b8e0SAnuj Aggarwal 
4603fa5b8e0SAnuj Aggarwal 	if (selector >= tps->info[ldo]->table_len)
4613fa5b8e0SAnuj Aggarwal 		return -EINVAL;
4623fa5b8e0SAnuj Aggarwal 	else
4633fa5b8e0SAnuj Aggarwal 		return tps->info[ldo]->table[selector] * 1000;
4643fa5b8e0SAnuj Aggarwal }
4653fa5b8e0SAnuj Aggarwal 
4663fa5b8e0SAnuj Aggarwal /* Operations permitted on VDCDCx */
467*4ce5ba5bSTodd Fischer static struct regulator_ops tps6507x_pmic_dcdc_ops = {
468*4ce5ba5bSTodd Fischer 	.is_enabled = tps6507x_pmic_dcdc_is_enabled,
469*4ce5ba5bSTodd Fischer 	.enable = tps6507x_pmic_dcdc_enable,
470*4ce5ba5bSTodd Fischer 	.disable = tps6507x_pmic_dcdc_disable,
471*4ce5ba5bSTodd Fischer 	.get_voltage = tps6507x_pmic_dcdc_get_voltage,
472*4ce5ba5bSTodd Fischer 	.set_voltage = tps6507x_pmic_dcdc_set_voltage,
473*4ce5ba5bSTodd Fischer 	.list_voltage = tps6507x_pmic_dcdc_list_voltage,
4743fa5b8e0SAnuj Aggarwal };
4753fa5b8e0SAnuj Aggarwal 
4763fa5b8e0SAnuj Aggarwal /* Operations permitted on LDOx */
477*4ce5ba5bSTodd Fischer static struct regulator_ops tps6507x_pmic_ldo_ops = {
478*4ce5ba5bSTodd Fischer 	.is_enabled = tps6507x_pmic_ldo_is_enabled,
479*4ce5ba5bSTodd Fischer 	.enable = tps6507x_pmic_ldo_enable,
480*4ce5ba5bSTodd Fischer 	.disable = tps6507x_pmic_ldo_disable,
481*4ce5ba5bSTodd Fischer 	.get_voltage = tps6507x_pmic_ldo_get_voltage,
482*4ce5ba5bSTodd Fischer 	.set_voltage = tps6507x_pmic_ldo_set_voltage,
483*4ce5ba5bSTodd Fischer 	.list_voltage = tps6507x_pmic_ldo_list_voltage,
4843fa5b8e0SAnuj Aggarwal };
4853fa5b8e0SAnuj Aggarwal 
486*4ce5ba5bSTodd Fischer static int __devinit tps6507x_pmic_probe(struct i2c_client *client,
48756c23492SDmitry Torokhov 				     const struct i2c_device_id *id)
4883fa5b8e0SAnuj Aggarwal {
4893fa5b8e0SAnuj Aggarwal 	static int desc_id;
4903fa5b8e0SAnuj Aggarwal 	const struct tps_info *info = (void *)id->driver_data;
4913fa5b8e0SAnuj Aggarwal 	struct regulator_init_data *init_data;
4923fa5b8e0SAnuj Aggarwal 	struct regulator_dev *rdev;
493*4ce5ba5bSTodd Fischer 	struct tps6507x_pmic *tps;
4940bc20bbaSTodd Fischer 	struct tps6507x_board *tps_board;
4953fa5b8e0SAnuj Aggarwal 	int i;
49656c23492SDmitry Torokhov 	int error;
4973fa5b8e0SAnuj Aggarwal 
4983fa5b8e0SAnuj Aggarwal 	if (!i2c_check_functionality(client->adapter,
4993fa5b8e0SAnuj Aggarwal 				I2C_FUNC_SMBUS_BYTE_DATA))
5003fa5b8e0SAnuj Aggarwal 		return -EIO;
5013fa5b8e0SAnuj Aggarwal 
5023fa5b8e0SAnuj Aggarwal 	/**
5030bc20bbaSTodd Fischer 	 * tps_board points to pmic related constants
5040bc20bbaSTodd Fischer 	 * coming from the board-evm file.
5050bc20bbaSTodd Fischer 	 */
5060bc20bbaSTodd Fischer 
5070bc20bbaSTodd Fischer 	tps_board = dev_get_platdata(&client->dev);
5080bc20bbaSTodd Fischer 	if (!tps_board)
5090bc20bbaSTodd Fischer 		return -EINVAL;
5100bc20bbaSTodd Fischer 
5110bc20bbaSTodd Fischer 	/**
5123fa5b8e0SAnuj Aggarwal 	 * init_data points to array of regulator_init structures
5133fa5b8e0SAnuj Aggarwal 	 * coming from the board-evm file.
5143fa5b8e0SAnuj Aggarwal 	 */
5150bc20bbaSTodd Fischer 	init_data = tps_board->tps6507x_pmic_init_data;
5163fa5b8e0SAnuj Aggarwal 	if (!init_data)
5170bc20bbaSTodd Fischer 		return -EINVAL;
5183fa5b8e0SAnuj Aggarwal 
5193fa5b8e0SAnuj Aggarwal 	tps = kzalloc(sizeof(*tps), GFP_KERNEL);
5203fa5b8e0SAnuj Aggarwal 	if (!tps)
5213fa5b8e0SAnuj Aggarwal 		return -ENOMEM;
5223fa5b8e0SAnuj Aggarwal 
5233fa5b8e0SAnuj Aggarwal 	mutex_init(&tps->io_lock);
5243fa5b8e0SAnuj Aggarwal 
5253fa5b8e0SAnuj Aggarwal 	/* common for all regulators */
5263fa5b8e0SAnuj Aggarwal 	tps->client = client;
5273fa5b8e0SAnuj Aggarwal 
5283fa5b8e0SAnuj Aggarwal 	for (i = 0; i < TPS6507X_NUM_REGULATOR; i++, info++, init_data++) {
5293fa5b8e0SAnuj Aggarwal 		/* Register the regulators */
5303fa5b8e0SAnuj Aggarwal 		tps->info[i] = info;
5313fa5b8e0SAnuj Aggarwal 		tps->desc[i].name = info->name;
5323fa5b8e0SAnuj Aggarwal 		tps->desc[i].id = desc_id++;
5333fa5b8e0SAnuj Aggarwal 		tps->desc[i].n_voltages = num_voltages[i];
5343fa5b8e0SAnuj Aggarwal 		tps->desc[i].ops = (i > TPS6507X_DCDC_3 ?
535*4ce5ba5bSTodd Fischer 		&tps6507x_pmic_ldo_ops : &tps6507x_pmic_dcdc_ops);
5363fa5b8e0SAnuj Aggarwal 		tps->desc[i].type = REGULATOR_VOLTAGE;
5373fa5b8e0SAnuj Aggarwal 		tps->desc[i].owner = THIS_MODULE;
5383fa5b8e0SAnuj Aggarwal 
5393fa5b8e0SAnuj Aggarwal 		rdev = regulator_register(&tps->desc[i],
5403fa5b8e0SAnuj Aggarwal 					&client->dev, init_data, tps);
5413fa5b8e0SAnuj Aggarwal 		if (IS_ERR(rdev)) {
5423fa5b8e0SAnuj Aggarwal 			dev_err(&client->dev, "failed to register %s\n",
5433fa5b8e0SAnuj Aggarwal 				id->name);
54456c23492SDmitry Torokhov 			error = PTR_ERR(rdev);
54556c23492SDmitry Torokhov 			goto fail;
5463fa5b8e0SAnuj Aggarwal 		}
5473fa5b8e0SAnuj Aggarwal 
5483fa5b8e0SAnuj Aggarwal 		/* Save regulator for cleanup */
5493fa5b8e0SAnuj Aggarwal 		tps->rdev[i] = rdev;
5503fa5b8e0SAnuj Aggarwal 	}
5513fa5b8e0SAnuj Aggarwal 
5523fa5b8e0SAnuj Aggarwal 	i2c_set_clientdata(client, tps);
5533fa5b8e0SAnuj Aggarwal 
5543fa5b8e0SAnuj Aggarwal 	return 0;
55556c23492SDmitry Torokhov 
55656c23492SDmitry Torokhov fail:
55756c23492SDmitry Torokhov 	while (--i >= 0)
55856c23492SDmitry Torokhov 		regulator_unregister(tps->rdev[i]);
55956c23492SDmitry Torokhov 
56056c23492SDmitry Torokhov 	kfree(tps);
56156c23492SDmitry Torokhov 	return error;
5623fa5b8e0SAnuj Aggarwal }
5633fa5b8e0SAnuj Aggarwal 
5643fa5b8e0SAnuj Aggarwal /**
565*4ce5ba5bSTodd Fischer  * tps6507x_remove - TPS6507x driver i2c remove handler
5663fa5b8e0SAnuj Aggarwal  * @client: i2c driver client device structure
5673fa5b8e0SAnuj Aggarwal  *
5683fa5b8e0SAnuj Aggarwal  * Unregister TPS driver as an i2c client device driver
5693fa5b8e0SAnuj Aggarwal  */
570*4ce5ba5bSTodd Fischer static int __devexit tps6507x_pmic_remove(struct i2c_client *client)
5713fa5b8e0SAnuj Aggarwal {
572*4ce5ba5bSTodd Fischer 	struct tps6507x_pmic *tps = i2c_get_clientdata(client);
5733fa5b8e0SAnuj Aggarwal 	int i;
5743fa5b8e0SAnuj Aggarwal 
57556c23492SDmitry Torokhov 	/* clear the client data in i2c */
57656c23492SDmitry Torokhov 	i2c_set_clientdata(client, NULL);
57756c23492SDmitry Torokhov 
5783fa5b8e0SAnuj Aggarwal 	for (i = 0; i < TPS6507X_NUM_REGULATOR; i++)
5793fa5b8e0SAnuj Aggarwal 		regulator_unregister(tps->rdev[i]);
5803fa5b8e0SAnuj Aggarwal 
5813fa5b8e0SAnuj Aggarwal 	kfree(tps);
5823fa5b8e0SAnuj Aggarwal 
5833fa5b8e0SAnuj Aggarwal 	return 0;
5843fa5b8e0SAnuj Aggarwal }
5853fa5b8e0SAnuj Aggarwal 
586*4ce5ba5bSTodd Fischer static const struct tps_info tps6507x_pmic_regs[] = {
5873fa5b8e0SAnuj Aggarwal 	{
5883fa5b8e0SAnuj Aggarwal 		.name = "VDCDC1",
5893fa5b8e0SAnuj Aggarwal 		.min_uV = 725000,
5903fa5b8e0SAnuj Aggarwal 		.max_uV = 3300000,
5913fa5b8e0SAnuj Aggarwal 		.table_len = ARRAY_SIZE(VDCDCx_VSEL_table),
5923fa5b8e0SAnuj Aggarwal 		.table = VDCDCx_VSEL_table,
5933fa5b8e0SAnuj Aggarwal 	},
5943fa5b8e0SAnuj Aggarwal 	{
5953fa5b8e0SAnuj Aggarwal 		.name = "VDCDC2",
5963fa5b8e0SAnuj Aggarwal 		.min_uV = 725000,
5973fa5b8e0SAnuj Aggarwal 		.max_uV = 3300000,
5983fa5b8e0SAnuj Aggarwal 		.table_len = ARRAY_SIZE(VDCDCx_VSEL_table),
5993fa5b8e0SAnuj Aggarwal 		.table = VDCDCx_VSEL_table,
6003fa5b8e0SAnuj Aggarwal 	},
6013fa5b8e0SAnuj Aggarwal 	{
6023fa5b8e0SAnuj Aggarwal 		.name = "VDCDC3",
6033fa5b8e0SAnuj Aggarwal 		.min_uV = 725000,
6043fa5b8e0SAnuj Aggarwal 		.max_uV = 3300000,
6053fa5b8e0SAnuj Aggarwal 		.table_len = ARRAY_SIZE(VDCDCx_VSEL_table),
6063fa5b8e0SAnuj Aggarwal 		.table = VDCDCx_VSEL_table,
6073fa5b8e0SAnuj Aggarwal 	},
6083fa5b8e0SAnuj Aggarwal 	{
6093fa5b8e0SAnuj Aggarwal 		.name = "LDO1",
6103fa5b8e0SAnuj Aggarwal 		.min_uV = 1000000,
6113fa5b8e0SAnuj Aggarwal 		.max_uV = 3300000,
6123fa5b8e0SAnuj Aggarwal 		.table_len = ARRAY_SIZE(LDO1_VSEL_table),
6133fa5b8e0SAnuj Aggarwal 		.table = LDO1_VSEL_table,
6143fa5b8e0SAnuj Aggarwal 	},
6153fa5b8e0SAnuj Aggarwal 	{
6163fa5b8e0SAnuj Aggarwal 		.name = "LDO2",
6173fa5b8e0SAnuj Aggarwal 		.min_uV = 725000,
6183fa5b8e0SAnuj Aggarwal 		.max_uV = 3300000,
6193fa5b8e0SAnuj Aggarwal 		.table_len = ARRAY_SIZE(LDO2_VSEL_table),
6203fa5b8e0SAnuj Aggarwal 		.table = LDO2_VSEL_table,
6213fa5b8e0SAnuj Aggarwal 	},
6223fa5b8e0SAnuj Aggarwal };
6233fa5b8e0SAnuj Aggarwal 
624*4ce5ba5bSTodd Fischer static const struct i2c_device_id tps6507x_pmic_id[] = {
6259e108d33SLiam Girdwood 	{.name = "tps6507x",
626*4ce5ba5bSTodd Fischer 	.driver_data = (unsigned long) tps6507x_pmic_regs,},
6279e108d33SLiam Girdwood 	{ },
6283fa5b8e0SAnuj Aggarwal };
629*4ce5ba5bSTodd Fischer MODULE_DEVICE_TABLE(i2c, tps6507x_pmic_id);
6303fa5b8e0SAnuj Aggarwal 
631*4ce5ba5bSTodd Fischer static struct i2c_driver tps6507x_i2c_driver = {
6323fa5b8e0SAnuj Aggarwal 	.driver = {
6333fa5b8e0SAnuj Aggarwal 		.name = "tps6507x",
6343fa5b8e0SAnuj Aggarwal 		.owner = THIS_MODULE,
6353fa5b8e0SAnuj Aggarwal 	},
636*4ce5ba5bSTodd Fischer 	.probe = tps6507x_pmic_probe,
637*4ce5ba5bSTodd Fischer 	.remove = __devexit_p(tps6507x_pmic_remove),
638*4ce5ba5bSTodd Fischer 	.id_table = tps6507x_pmic_id,
6393fa5b8e0SAnuj Aggarwal };
6403fa5b8e0SAnuj Aggarwal 
6413fa5b8e0SAnuj Aggarwal /**
642*4ce5ba5bSTodd Fischer  * tps6507x_pmic_init
6433fa5b8e0SAnuj Aggarwal  *
6443fa5b8e0SAnuj Aggarwal  * Module init function
6453fa5b8e0SAnuj Aggarwal  */
646*4ce5ba5bSTodd Fischer static int __init tps6507x_pmic_init(void)
6473fa5b8e0SAnuj Aggarwal {
648*4ce5ba5bSTodd Fischer 	return i2c_add_driver(&tps6507x_i2c_driver);
6493fa5b8e0SAnuj Aggarwal }
650*4ce5ba5bSTodd Fischer subsys_initcall(tps6507x_pmic_init);
6513fa5b8e0SAnuj Aggarwal 
6523fa5b8e0SAnuj Aggarwal /**
653*4ce5ba5bSTodd Fischer  * tps6507x_pmic_cleanup
6543fa5b8e0SAnuj Aggarwal  *
6553fa5b8e0SAnuj Aggarwal  * Module exit function
6563fa5b8e0SAnuj Aggarwal  */
657*4ce5ba5bSTodd Fischer static void __exit tps6507x_pmic_cleanup(void)
6583fa5b8e0SAnuj Aggarwal {
659*4ce5ba5bSTodd Fischer 	i2c_del_driver(&tps6507x_i2c_driver);
6603fa5b8e0SAnuj Aggarwal }
661*4ce5ba5bSTodd Fischer module_exit(tps6507x_pmic_cleanup);
6623fa5b8e0SAnuj Aggarwal 
6633fa5b8e0SAnuj Aggarwal MODULE_AUTHOR("Texas Instruments");
6643fa5b8e0SAnuj Aggarwal MODULE_DESCRIPTION("TPS6507x voltage regulator driver");
6653fa5b8e0SAnuj Aggarwal MODULE_LICENSE("GPL v2");
666