xref: /openbmc/linux/drivers/regulator/lp3971.c (revision 2c043bcb)
10cbdf7bcSMarek Szyprowski /*
20cbdf7bcSMarek Szyprowski  * Regulator driver for National Semiconductors LP3971 PMIC chip
30cbdf7bcSMarek Szyprowski  *
40cbdf7bcSMarek Szyprowski  *  Copyright (C) 2009 Samsung Electronics
50cbdf7bcSMarek Szyprowski  *  Author: Marek Szyprowski <m.szyprowski@samsung.com>
60cbdf7bcSMarek Szyprowski  *
70cbdf7bcSMarek Szyprowski  * Based on wm8350.c
80cbdf7bcSMarek Szyprowski  *
90cbdf7bcSMarek Szyprowski  * This program is free software; you can redistribute it and/or modify
100cbdf7bcSMarek Szyprowski  * it under the terms of the GNU General Public License version 2 as
110cbdf7bcSMarek Szyprowski  * published by the Free Software Foundation.
120cbdf7bcSMarek Szyprowski  *
130cbdf7bcSMarek Szyprowski  */
140cbdf7bcSMarek Szyprowski 
150cbdf7bcSMarek Szyprowski #include <linux/bug.h>
160cbdf7bcSMarek Szyprowski #include <linux/err.h>
170cbdf7bcSMarek Szyprowski #include <linux/i2c.h>
180cbdf7bcSMarek Szyprowski #include <linux/kernel.h>
1965602c32SPaul Gortmaker #include <linux/module.h>
200cbdf7bcSMarek Szyprowski #include <linux/regulator/driver.h>
210cbdf7bcSMarek Szyprowski #include <linux/regulator/lp3971.h>
225a0e3ad6STejun Heo #include <linux/slab.h>
230cbdf7bcSMarek Szyprowski 
240cbdf7bcSMarek Szyprowski struct lp3971 {
250cbdf7bcSMarek Szyprowski 	struct device *dev;
260cbdf7bcSMarek Szyprowski 	struct mutex io_lock;
270cbdf7bcSMarek Szyprowski 	struct i2c_client *i2c;
280cbdf7bcSMarek Szyprowski 	int num_regulators;
290cbdf7bcSMarek Szyprowski 	struct regulator_dev **rdev;
300cbdf7bcSMarek Szyprowski };
310cbdf7bcSMarek Szyprowski 
320cbdf7bcSMarek Szyprowski static u8 lp3971_reg_read(struct lp3971 *lp3971, u8 reg);
330cbdf7bcSMarek Szyprowski static int lp3971_set_bits(struct lp3971 *lp3971, u8 reg, u16 mask, u16 val);
340cbdf7bcSMarek Szyprowski 
350cbdf7bcSMarek Szyprowski #define LP3971_SYS_CONTROL1_REG 0x07
360cbdf7bcSMarek Szyprowski 
370cbdf7bcSMarek Szyprowski /* System control register 1 initial value,
380cbdf7bcSMarek Szyprowski    bits 4 and 5 are EPROM programmable */
390cbdf7bcSMarek Szyprowski #define SYS_CONTROL1_INIT_VAL 0x40
400cbdf7bcSMarek Szyprowski #define SYS_CONTROL1_INIT_MASK 0xCF
410cbdf7bcSMarek Szyprowski 
420cbdf7bcSMarek Szyprowski #define LP3971_BUCK_VOL_ENABLE_REG 0x10
430cbdf7bcSMarek Szyprowski #define LP3971_BUCK_VOL_CHANGE_REG 0x20
440cbdf7bcSMarek Szyprowski 
450cbdf7bcSMarek Szyprowski /*	Voltage control registers shift:
460cbdf7bcSMarek Szyprowski 	LP3971_BUCK1 -> 0
470cbdf7bcSMarek Szyprowski 	LP3971_BUCK2 -> 4
480cbdf7bcSMarek Szyprowski 	LP3971_BUCK3 -> 6
490cbdf7bcSMarek Szyprowski */
50451a73cdSAxel Lin #define BUCK_VOL_CHANGE_SHIFT(x) (((!!x) << 2) | (x & ~0x01))
510cbdf7bcSMarek Szyprowski #define BUCK_VOL_CHANGE_FLAG_GO 0x01
520cbdf7bcSMarek Szyprowski #define BUCK_VOL_CHANGE_FLAG_TARGET 0x02
530cbdf7bcSMarek Szyprowski #define BUCK_VOL_CHANGE_FLAG_MASK 0x03
540cbdf7bcSMarek Szyprowski 
550cbdf7bcSMarek Szyprowski #define LP3971_BUCK1_BASE 0x23
560cbdf7bcSMarek Szyprowski #define LP3971_BUCK2_BASE 0x29
570cbdf7bcSMarek Szyprowski #define LP3971_BUCK3_BASE 0x32
580cbdf7bcSMarek Szyprowski 
596faa7e0aSTobias Klauser static const int buck_base_addr[] = {
600cbdf7bcSMarek Szyprowski 	LP3971_BUCK1_BASE,
610cbdf7bcSMarek Szyprowski 	LP3971_BUCK2_BASE,
620cbdf7bcSMarek Szyprowski 	LP3971_BUCK3_BASE,
630cbdf7bcSMarek Szyprowski };
640cbdf7bcSMarek Szyprowski 
650cbdf7bcSMarek Szyprowski #define LP3971_BUCK_TARGET_VOL1_REG(x) (buck_base_addr[x])
660cbdf7bcSMarek Szyprowski #define LP3971_BUCK_TARGET_VOL2_REG(x) (buck_base_addr[x]+1)
670cbdf7bcSMarek Szyprowski 
686faa7e0aSTobias Klauser static const int buck_voltage_map[] = {
690cbdf7bcSMarek Szyprowski 	   0,  800,  850,  900,  950, 1000, 1050, 1100,
700cbdf7bcSMarek Szyprowski 	1150, 1200, 1250, 1300, 1350, 1400, 1450, 1500,
710cbdf7bcSMarek Szyprowski 	1550, 1600, 1650, 1700, 1800, 1900, 2500, 2800,
720cbdf7bcSMarek Szyprowski 	3000, 3300,
730cbdf7bcSMarek Szyprowski };
740cbdf7bcSMarek Szyprowski 
750cbdf7bcSMarek Szyprowski #define BUCK_TARGET_VOL_MASK 0x3f
760cbdf7bcSMarek Szyprowski #define BUCK_TARGET_VOL_MIN_IDX 0x01
770cbdf7bcSMarek Szyprowski #define BUCK_TARGET_VOL_MAX_IDX 0x19
780cbdf7bcSMarek Szyprowski 
790cbdf7bcSMarek Szyprowski #define LP3971_BUCK_RAMP_REG(x)	(buck_base_addr[x]+2)
800cbdf7bcSMarek Szyprowski 
810cbdf7bcSMarek Szyprowski #define LP3971_LDO_ENABLE_REG 0x12
820cbdf7bcSMarek Szyprowski #define LP3971_LDO_VOL_CONTR_BASE 0x39
830cbdf7bcSMarek Szyprowski 
840cbdf7bcSMarek Szyprowski /*	Voltage control registers:
850cbdf7bcSMarek Szyprowski 	LP3971_LDO1 -> LP3971_LDO_VOL_CONTR_BASE + 0
860cbdf7bcSMarek Szyprowski 	LP3971_LDO2 -> LP3971_LDO_VOL_CONTR_BASE + 0
870cbdf7bcSMarek Szyprowski 	LP3971_LDO3 -> LP3971_LDO_VOL_CONTR_BASE + 1
880cbdf7bcSMarek Szyprowski 	LP3971_LDO4 -> LP3971_LDO_VOL_CONTR_BASE + 1
890cbdf7bcSMarek Szyprowski 	LP3971_LDO5 -> LP3971_LDO_VOL_CONTR_BASE + 2
900cbdf7bcSMarek Szyprowski */
910cbdf7bcSMarek Szyprowski #define LP3971_LDO_VOL_CONTR_REG(x)	(LP3971_LDO_VOL_CONTR_BASE + (x >> 1))
920cbdf7bcSMarek Szyprowski 
930cbdf7bcSMarek Szyprowski /*	Voltage control registers shift:
940cbdf7bcSMarek Szyprowski 	LP3971_LDO1 -> 0, LP3971_LDO2 -> 4
950cbdf7bcSMarek Szyprowski 	LP3971_LDO3 -> 0, LP3971_LDO4 -> 4
960cbdf7bcSMarek Szyprowski 	LP3971_LDO5 -> 0
970cbdf7bcSMarek Szyprowski */
980cbdf7bcSMarek Szyprowski #define LDO_VOL_CONTR_SHIFT(x) ((x & 1) << 2)
990cbdf7bcSMarek Szyprowski #define LDO_VOL_CONTR_MASK 0x0f
1000cbdf7bcSMarek Szyprowski 
1016faa7e0aSTobias Klauser static const int ldo45_voltage_map[] = {
1020cbdf7bcSMarek Szyprowski 	1000, 1050, 1100, 1150, 1200, 1250, 1300, 1350,
1030cbdf7bcSMarek Szyprowski 	1400, 1500, 1800, 1900, 2500, 2800, 3000, 3300,
1040cbdf7bcSMarek Szyprowski };
1050cbdf7bcSMarek Szyprowski 
1066faa7e0aSTobias Klauser static const int ldo123_voltage_map[] = {
1070cbdf7bcSMarek Szyprowski 	1800, 1900, 2000, 2100, 2200, 2300, 2400, 2500,
1080cbdf7bcSMarek Szyprowski 	2600, 2700, 2800, 2900, 3000, 3100, 3200, 3300,
1090cbdf7bcSMarek Szyprowski };
1100cbdf7bcSMarek Szyprowski 
1116faa7e0aSTobias Klauser static const int *ldo_voltage_map[] = {
1120cbdf7bcSMarek Szyprowski 	ldo123_voltage_map, /* LDO1 */
1130cbdf7bcSMarek Szyprowski 	ldo123_voltage_map, /* LDO2 */
1140cbdf7bcSMarek Szyprowski 	ldo123_voltage_map, /* LDO3 */
1150cbdf7bcSMarek Szyprowski 	ldo45_voltage_map, /* LDO4 */
1160cbdf7bcSMarek Szyprowski 	ldo45_voltage_map, /* LDO5 */
1170cbdf7bcSMarek Szyprowski };
1180cbdf7bcSMarek Szyprowski 
1190cbdf7bcSMarek Szyprowski #define LDO_VOL_VALUE_MAP(x) (ldo_voltage_map[(x - LP3971_LDO1)])
1200cbdf7bcSMarek Szyprowski 
1210cbdf7bcSMarek Szyprowski #define LDO_VOL_MIN_IDX 0x00
1220cbdf7bcSMarek Szyprowski #define LDO_VOL_MAX_IDX 0x0f
1230cbdf7bcSMarek Szyprowski 
1240cbdf7bcSMarek Szyprowski static int lp3971_ldo_list_voltage(struct regulator_dev *dev, unsigned index)
1250cbdf7bcSMarek Szyprowski {
1260cbdf7bcSMarek Szyprowski 	int ldo = rdev_get_id(dev) - LP3971_LDO1;
1270cbdf7bcSMarek Szyprowski 	return 1000 * LDO_VOL_VALUE_MAP(ldo)[index];
1280cbdf7bcSMarek Szyprowski }
1290cbdf7bcSMarek Szyprowski 
1300cbdf7bcSMarek Szyprowski static int lp3971_ldo_is_enabled(struct regulator_dev *dev)
1310cbdf7bcSMarek Szyprowski {
1320cbdf7bcSMarek Szyprowski 	struct lp3971 *lp3971 = rdev_get_drvdata(dev);
1330cbdf7bcSMarek Szyprowski 	int ldo = rdev_get_id(dev) - LP3971_LDO1;
1340cbdf7bcSMarek Szyprowski 	u16 mask = 1 << (1 + ldo);
1350cbdf7bcSMarek Szyprowski 	u16 val;
1360cbdf7bcSMarek Szyprowski 
1370cbdf7bcSMarek Szyprowski 	val = lp3971_reg_read(lp3971, LP3971_LDO_ENABLE_REG);
1380cbdf7bcSMarek Szyprowski 	return (val & mask) != 0;
1390cbdf7bcSMarek Szyprowski }
1400cbdf7bcSMarek Szyprowski 
1410cbdf7bcSMarek Szyprowski static int lp3971_ldo_enable(struct regulator_dev *dev)
1420cbdf7bcSMarek Szyprowski {
1430cbdf7bcSMarek Szyprowski 	struct lp3971 *lp3971 = rdev_get_drvdata(dev);
1440cbdf7bcSMarek Szyprowski 	int ldo = rdev_get_id(dev) - LP3971_LDO1;
1450cbdf7bcSMarek Szyprowski 	u16 mask = 1 << (1 + ldo);
1460cbdf7bcSMarek Szyprowski 
1470cbdf7bcSMarek Szyprowski 	return lp3971_set_bits(lp3971, LP3971_LDO_ENABLE_REG, mask, mask);
1480cbdf7bcSMarek Szyprowski }
1490cbdf7bcSMarek Szyprowski 
1500cbdf7bcSMarek Szyprowski static int lp3971_ldo_disable(struct regulator_dev *dev)
1510cbdf7bcSMarek Szyprowski {
1520cbdf7bcSMarek Szyprowski 	struct lp3971 *lp3971 = rdev_get_drvdata(dev);
1530cbdf7bcSMarek Szyprowski 	int ldo = rdev_get_id(dev) - LP3971_LDO1;
1540cbdf7bcSMarek Szyprowski 	u16 mask = 1 << (1 + ldo);
1550cbdf7bcSMarek Szyprowski 
1560cbdf7bcSMarek Szyprowski 	return lp3971_set_bits(lp3971, LP3971_LDO_ENABLE_REG, mask, 0);
1570cbdf7bcSMarek Szyprowski }
1580cbdf7bcSMarek Szyprowski 
1590cbdf7bcSMarek Szyprowski static int lp3971_ldo_get_voltage(struct regulator_dev *dev)
1600cbdf7bcSMarek Szyprowski {
1610cbdf7bcSMarek Szyprowski 	struct lp3971 *lp3971 = rdev_get_drvdata(dev);
1620cbdf7bcSMarek Szyprowski 	int ldo = rdev_get_id(dev) - LP3971_LDO1;
1630cbdf7bcSMarek Szyprowski 	u16 val, reg;
1640cbdf7bcSMarek Szyprowski 
1650cbdf7bcSMarek Szyprowski 	reg = lp3971_reg_read(lp3971, LP3971_LDO_VOL_CONTR_REG(ldo));
1660cbdf7bcSMarek Szyprowski 	val = (reg >> LDO_VOL_CONTR_SHIFT(ldo)) & LDO_VOL_CONTR_MASK;
1670cbdf7bcSMarek Szyprowski 
1680cbdf7bcSMarek Szyprowski 	return 1000 * LDO_VOL_VALUE_MAP(ldo)[val];
1690cbdf7bcSMarek Szyprowski }
1700cbdf7bcSMarek Szyprowski 
1710cbdf7bcSMarek Szyprowski static int lp3971_ldo_set_voltage(struct regulator_dev *dev,
1723a93f2a9SMark Brown 				  int min_uV, int max_uV,
1733a93f2a9SMark Brown 				  unsigned int *selector)
1740cbdf7bcSMarek Szyprowski {
1750cbdf7bcSMarek Szyprowski 	struct lp3971 *lp3971 = rdev_get_drvdata(dev);
1760cbdf7bcSMarek Szyprowski 	int ldo = rdev_get_id(dev) - LP3971_LDO1;
1770cbdf7bcSMarek Szyprowski 	int min_vol = min_uV / 1000, max_vol = max_uV / 1000;
1780cbdf7bcSMarek Szyprowski 	const int *vol_map = LDO_VOL_VALUE_MAP(ldo);
1790cbdf7bcSMarek Szyprowski 	u16 val;
1800cbdf7bcSMarek Szyprowski 
1810cbdf7bcSMarek Szyprowski 	if (min_vol < vol_map[LDO_VOL_MIN_IDX] ||
1820cbdf7bcSMarek Szyprowski 	    min_vol > vol_map[LDO_VOL_MAX_IDX])
1830cbdf7bcSMarek Szyprowski 		return -EINVAL;
1840cbdf7bcSMarek Szyprowski 
1850cbdf7bcSMarek Szyprowski 	for (val = LDO_VOL_MIN_IDX; val <= LDO_VOL_MAX_IDX; val++)
1860cbdf7bcSMarek Szyprowski 		if (vol_map[val] >= min_vol)
1870cbdf7bcSMarek Szyprowski 			break;
1880cbdf7bcSMarek Szyprowski 
18962737d44SRoel Kluin 	if (val > LDO_VOL_MAX_IDX || vol_map[val] > max_vol)
1900cbdf7bcSMarek Szyprowski 		return -EINVAL;
1910cbdf7bcSMarek Szyprowski 
1923a93f2a9SMark Brown 	*selector = val;
1933a93f2a9SMark Brown 
1940cbdf7bcSMarek Szyprowski 	return lp3971_set_bits(lp3971, LP3971_LDO_VOL_CONTR_REG(ldo),
195cdb868f5SAxel Lin 			LDO_VOL_CONTR_MASK << LDO_VOL_CONTR_SHIFT(ldo),
196cdb868f5SAxel Lin 			val << LDO_VOL_CONTR_SHIFT(ldo));
1970cbdf7bcSMarek Szyprowski }
1980cbdf7bcSMarek Szyprowski 
1990cbdf7bcSMarek Szyprowski static struct regulator_ops lp3971_ldo_ops = {
2000cbdf7bcSMarek Szyprowski 	.list_voltage = lp3971_ldo_list_voltage,
2010cbdf7bcSMarek Szyprowski 	.is_enabled = lp3971_ldo_is_enabled,
2020cbdf7bcSMarek Szyprowski 	.enable = lp3971_ldo_enable,
2030cbdf7bcSMarek Szyprowski 	.disable = lp3971_ldo_disable,
2040cbdf7bcSMarek Szyprowski 	.get_voltage = lp3971_ldo_get_voltage,
2050cbdf7bcSMarek Szyprowski 	.set_voltage = lp3971_ldo_set_voltage,
2060cbdf7bcSMarek Szyprowski };
2070cbdf7bcSMarek Szyprowski 
2080cbdf7bcSMarek Szyprowski static int lp3971_dcdc_list_voltage(struct regulator_dev *dev, unsigned index)
2090cbdf7bcSMarek Szyprowski {
2100cbdf7bcSMarek Szyprowski 	return 1000 * buck_voltage_map[index];
2110cbdf7bcSMarek Szyprowski }
2120cbdf7bcSMarek Szyprowski 
2130cbdf7bcSMarek Szyprowski static int lp3971_dcdc_is_enabled(struct regulator_dev *dev)
2140cbdf7bcSMarek Szyprowski {
2150cbdf7bcSMarek Szyprowski 	struct lp3971 *lp3971 = rdev_get_drvdata(dev);
2160cbdf7bcSMarek Szyprowski 	int buck = rdev_get_id(dev) - LP3971_DCDC1;
2170cbdf7bcSMarek Szyprowski 	u16 mask = 1 << (buck * 2);
2180cbdf7bcSMarek Szyprowski 	u16 val;
2190cbdf7bcSMarek Szyprowski 
2200cbdf7bcSMarek Szyprowski 	val = lp3971_reg_read(lp3971, LP3971_BUCK_VOL_ENABLE_REG);
2210cbdf7bcSMarek Szyprowski 	return (val & mask) != 0;
2220cbdf7bcSMarek Szyprowski }
2230cbdf7bcSMarek Szyprowski 
2240cbdf7bcSMarek Szyprowski static int lp3971_dcdc_enable(struct regulator_dev *dev)
2250cbdf7bcSMarek Szyprowski {
2260cbdf7bcSMarek Szyprowski 	struct lp3971 *lp3971 = rdev_get_drvdata(dev);
2270cbdf7bcSMarek Szyprowski 	int buck = rdev_get_id(dev) - LP3971_DCDC1;
2280cbdf7bcSMarek Szyprowski 	u16 mask = 1 << (buck * 2);
2290cbdf7bcSMarek Szyprowski 
2300cbdf7bcSMarek Szyprowski 	return lp3971_set_bits(lp3971, LP3971_BUCK_VOL_ENABLE_REG, mask, mask);
2310cbdf7bcSMarek Szyprowski }
2320cbdf7bcSMarek Szyprowski 
2330cbdf7bcSMarek Szyprowski static int lp3971_dcdc_disable(struct regulator_dev *dev)
2340cbdf7bcSMarek Szyprowski {
2350cbdf7bcSMarek Szyprowski 	struct lp3971 *lp3971 = rdev_get_drvdata(dev);
2360cbdf7bcSMarek Szyprowski 	int buck = rdev_get_id(dev) - LP3971_DCDC1;
2370cbdf7bcSMarek Szyprowski 	u16 mask = 1 << (buck * 2);
2380cbdf7bcSMarek Szyprowski 
2390cbdf7bcSMarek Szyprowski 	return lp3971_set_bits(lp3971, LP3971_BUCK_VOL_ENABLE_REG, mask, 0);
2400cbdf7bcSMarek Szyprowski }
2410cbdf7bcSMarek Szyprowski 
2420cbdf7bcSMarek Szyprowski static int lp3971_dcdc_get_voltage(struct regulator_dev *dev)
2430cbdf7bcSMarek Szyprowski {
2440cbdf7bcSMarek Szyprowski 	struct lp3971 *lp3971 = rdev_get_drvdata(dev);
2450cbdf7bcSMarek Szyprowski 	int buck = rdev_get_id(dev) - LP3971_DCDC1;
2460cbdf7bcSMarek Szyprowski 	u16 reg;
2470cbdf7bcSMarek Szyprowski 	int val;
2480cbdf7bcSMarek Szyprowski 
2490cbdf7bcSMarek Szyprowski 	reg = lp3971_reg_read(lp3971, LP3971_BUCK_TARGET_VOL1_REG(buck));
2500cbdf7bcSMarek Szyprowski 	reg &= BUCK_TARGET_VOL_MASK;
2510cbdf7bcSMarek Szyprowski 
2520cbdf7bcSMarek Szyprowski 	if (reg <= BUCK_TARGET_VOL_MAX_IDX)
2530cbdf7bcSMarek Szyprowski 		val = 1000 * buck_voltage_map[reg];
2540cbdf7bcSMarek Szyprowski 	else {
2550cbdf7bcSMarek Szyprowski 		val = 0;
2560cbdf7bcSMarek Szyprowski 		dev_warn(&dev->dev, "chip reported incorrect voltage value.\n");
2570cbdf7bcSMarek Szyprowski 	}
2580cbdf7bcSMarek Szyprowski 
2590cbdf7bcSMarek Szyprowski 	return val;
2600cbdf7bcSMarek Szyprowski }
2610cbdf7bcSMarek Szyprowski 
2620cbdf7bcSMarek Szyprowski static int lp3971_dcdc_set_voltage(struct regulator_dev *dev,
2633a93f2a9SMark Brown 				   int min_uV, int max_uV,
2643a93f2a9SMark Brown 				   unsigned int *selector)
2650cbdf7bcSMarek Szyprowski {
2660cbdf7bcSMarek Szyprowski 	struct lp3971 *lp3971 = rdev_get_drvdata(dev);
2670cbdf7bcSMarek Szyprowski 	int buck = rdev_get_id(dev) - LP3971_DCDC1;
2680cbdf7bcSMarek Szyprowski 	int min_vol = min_uV / 1000, max_vol = max_uV / 1000;
2690cbdf7bcSMarek Szyprowski 	const int *vol_map = buck_voltage_map;
2700cbdf7bcSMarek Szyprowski 	u16 val;
2710cbdf7bcSMarek Szyprowski 	int ret;
2720cbdf7bcSMarek Szyprowski 
2730cbdf7bcSMarek Szyprowski 	if (min_vol < vol_map[BUCK_TARGET_VOL_MIN_IDX] ||
2740cbdf7bcSMarek Szyprowski 	    min_vol > vol_map[BUCK_TARGET_VOL_MAX_IDX])
2750cbdf7bcSMarek Szyprowski 		return -EINVAL;
2760cbdf7bcSMarek Szyprowski 
2770cbdf7bcSMarek Szyprowski 	for (val = BUCK_TARGET_VOL_MIN_IDX; val <= BUCK_TARGET_VOL_MAX_IDX;
2780cbdf7bcSMarek Szyprowski 	     val++)
2790cbdf7bcSMarek Szyprowski 		if (vol_map[val] >= min_vol)
2800cbdf7bcSMarek Szyprowski 			break;
2810cbdf7bcSMarek Szyprowski 
28262737d44SRoel Kluin 	if (val > BUCK_TARGET_VOL_MAX_IDX || vol_map[val] > max_vol)
2830cbdf7bcSMarek Szyprowski 		return -EINVAL;
2840cbdf7bcSMarek Szyprowski 
2853a93f2a9SMark Brown 	*selector = val;
2863a93f2a9SMark Brown 
2870cbdf7bcSMarek Szyprowski 	ret = lp3971_set_bits(lp3971, LP3971_BUCK_TARGET_VOL1_REG(buck),
2880cbdf7bcSMarek Szyprowski 	       BUCK_TARGET_VOL_MASK, val);
2890cbdf7bcSMarek Szyprowski 	if (ret)
2900cbdf7bcSMarek Szyprowski 		return ret;
2910cbdf7bcSMarek Szyprowski 
2920cbdf7bcSMarek Szyprowski 	ret = lp3971_set_bits(lp3971, LP3971_BUCK_VOL_CHANGE_REG,
2930cbdf7bcSMarek Szyprowski 	       BUCK_VOL_CHANGE_FLAG_MASK << BUCK_VOL_CHANGE_SHIFT(buck),
2940cbdf7bcSMarek Szyprowski 	       BUCK_VOL_CHANGE_FLAG_GO << BUCK_VOL_CHANGE_SHIFT(buck));
2950cbdf7bcSMarek Szyprowski 	if (ret)
2960cbdf7bcSMarek Szyprowski 		return ret;
2970cbdf7bcSMarek Szyprowski 
2980cbdf7bcSMarek Szyprowski 	return lp3971_set_bits(lp3971, LP3971_BUCK_VOL_CHANGE_REG,
2990cbdf7bcSMarek Szyprowski 	       BUCK_VOL_CHANGE_FLAG_MASK << BUCK_VOL_CHANGE_SHIFT(buck),
3000cbdf7bcSMarek Szyprowski 	       0 << BUCK_VOL_CHANGE_SHIFT(buck));
3010cbdf7bcSMarek Szyprowski }
3020cbdf7bcSMarek Szyprowski 
3030cbdf7bcSMarek Szyprowski static struct regulator_ops lp3971_dcdc_ops = {
3040cbdf7bcSMarek Szyprowski 	.list_voltage = lp3971_dcdc_list_voltage,
3050cbdf7bcSMarek Szyprowski 	.is_enabled = lp3971_dcdc_is_enabled,
3060cbdf7bcSMarek Szyprowski 	.enable = lp3971_dcdc_enable,
3070cbdf7bcSMarek Szyprowski 	.disable = lp3971_dcdc_disable,
3080cbdf7bcSMarek Szyprowski 	.get_voltage = lp3971_dcdc_get_voltage,
3090cbdf7bcSMarek Szyprowski 	.set_voltage = lp3971_dcdc_set_voltage,
3100cbdf7bcSMarek Szyprowski };
3110cbdf7bcSMarek Szyprowski 
3120cbdf7bcSMarek Szyprowski static struct regulator_desc regulators[] = {
3130cbdf7bcSMarek Szyprowski 	{
3140cbdf7bcSMarek Szyprowski 		.name = "LDO1",
3150cbdf7bcSMarek Szyprowski 		.id = LP3971_LDO1,
3160cbdf7bcSMarek Szyprowski 		.ops = &lp3971_ldo_ops,
3170cbdf7bcSMarek Szyprowski 		.n_voltages = ARRAY_SIZE(ldo123_voltage_map),
3180cbdf7bcSMarek Szyprowski 		.type = REGULATOR_VOLTAGE,
3190cbdf7bcSMarek Szyprowski 		.owner = THIS_MODULE,
3200cbdf7bcSMarek Szyprowski 	},
3210cbdf7bcSMarek Szyprowski 	{
3220cbdf7bcSMarek Szyprowski 		.name = "LDO2",
3230cbdf7bcSMarek Szyprowski 		.id = LP3971_LDO2,
3240cbdf7bcSMarek Szyprowski 		.ops = &lp3971_ldo_ops,
3250cbdf7bcSMarek Szyprowski 		.n_voltages = ARRAY_SIZE(ldo123_voltage_map),
3260cbdf7bcSMarek Szyprowski 		.type = REGULATOR_VOLTAGE,
3270cbdf7bcSMarek Szyprowski 		.owner = THIS_MODULE,
3280cbdf7bcSMarek Szyprowski 	},
3290cbdf7bcSMarek Szyprowski 	{
3300cbdf7bcSMarek Szyprowski 		.name = "LDO3",
3310cbdf7bcSMarek Szyprowski 		.id = LP3971_LDO3,
3320cbdf7bcSMarek Szyprowski 		.ops = &lp3971_ldo_ops,
3330cbdf7bcSMarek Szyprowski 		.n_voltages = ARRAY_SIZE(ldo123_voltage_map),
3340cbdf7bcSMarek Szyprowski 		.type = REGULATOR_VOLTAGE,
3350cbdf7bcSMarek Szyprowski 		.owner = THIS_MODULE,
3360cbdf7bcSMarek Szyprowski 	},
3370cbdf7bcSMarek Szyprowski 	{
3380cbdf7bcSMarek Szyprowski 		.name = "LDO4",
3390cbdf7bcSMarek Szyprowski 		.id = LP3971_LDO4,
3400cbdf7bcSMarek Szyprowski 		.ops = &lp3971_ldo_ops,
3410cbdf7bcSMarek Szyprowski 		.n_voltages = ARRAY_SIZE(ldo45_voltage_map),
3420cbdf7bcSMarek Szyprowski 		.type = REGULATOR_VOLTAGE,
3430cbdf7bcSMarek Szyprowski 		.owner = THIS_MODULE,
3440cbdf7bcSMarek Szyprowski 	},
3450cbdf7bcSMarek Szyprowski 	{
3460cbdf7bcSMarek Szyprowski 		.name = "LDO5",
3470cbdf7bcSMarek Szyprowski 		.id = LP3971_LDO5,
3480cbdf7bcSMarek Szyprowski 		.ops = &lp3971_ldo_ops,
3490cbdf7bcSMarek Szyprowski 		.n_voltages = ARRAY_SIZE(ldo45_voltage_map),
3500cbdf7bcSMarek Szyprowski 		.type = REGULATOR_VOLTAGE,
3510cbdf7bcSMarek Szyprowski 		.owner = THIS_MODULE,
3520cbdf7bcSMarek Szyprowski 	},
3530cbdf7bcSMarek Szyprowski 	{
3540cbdf7bcSMarek Szyprowski 		.name = "DCDC1",
3550cbdf7bcSMarek Szyprowski 		.id = LP3971_DCDC1,
3560cbdf7bcSMarek Szyprowski 		.ops = &lp3971_dcdc_ops,
3570cbdf7bcSMarek Szyprowski 		.n_voltages = ARRAY_SIZE(buck_voltage_map),
3580cbdf7bcSMarek Szyprowski 		.type = REGULATOR_VOLTAGE,
3590cbdf7bcSMarek Szyprowski 		.owner = THIS_MODULE,
3600cbdf7bcSMarek Szyprowski 	},
3610cbdf7bcSMarek Szyprowski 	{
3620cbdf7bcSMarek Szyprowski 		.name = "DCDC2",
3630cbdf7bcSMarek Szyprowski 		.id = LP3971_DCDC2,
3640cbdf7bcSMarek Szyprowski 		.ops = &lp3971_dcdc_ops,
3650cbdf7bcSMarek Szyprowski 		.n_voltages = ARRAY_SIZE(buck_voltage_map),
3660cbdf7bcSMarek Szyprowski 		.type = REGULATOR_VOLTAGE,
3670cbdf7bcSMarek Szyprowski 		.owner = THIS_MODULE,
3680cbdf7bcSMarek Szyprowski 	},
3690cbdf7bcSMarek Szyprowski 	{
3700cbdf7bcSMarek Szyprowski 		.name = "DCDC3",
3710cbdf7bcSMarek Szyprowski 		.id = LP3971_DCDC3,
3720cbdf7bcSMarek Szyprowski 		.ops = &lp3971_dcdc_ops,
3730cbdf7bcSMarek Szyprowski 		.n_voltages = ARRAY_SIZE(buck_voltage_map),
3740cbdf7bcSMarek Szyprowski 		.type = REGULATOR_VOLTAGE,
3750cbdf7bcSMarek Szyprowski 		.owner = THIS_MODULE,
3760cbdf7bcSMarek Szyprowski 	},
3770cbdf7bcSMarek Szyprowski };
3780cbdf7bcSMarek Szyprowski 
3790cbdf7bcSMarek Szyprowski static int lp3971_i2c_read(struct i2c_client *i2c, char reg, int count,
3800cbdf7bcSMarek Szyprowski 	u16 *dest)
3810cbdf7bcSMarek Szyprowski {
3820cbdf7bcSMarek Szyprowski 	int ret;
3830cbdf7bcSMarek Szyprowski 
3840cbdf7bcSMarek Szyprowski 	if (count != 1)
3850cbdf7bcSMarek Szyprowski 		return -EIO;
3860cbdf7bcSMarek Szyprowski 	ret = i2c_smbus_read_byte_data(i2c, reg);
38727ef7f00SAxel Lin 	if (ret < 0)
3880cbdf7bcSMarek Szyprowski 		return -EIO;
3890cbdf7bcSMarek Szyprowski 
3900cbdf7bcSMarek Szyprowski 	*dest = ret;
3910cbdf7bcSMarek Szyprowski 	return 0;
3920cbdf7bcSMarek Szyprowski }
3930cbdf7bcSMarek Szyprowski 
3940cbdf7bcSMarek Szyprowski static int lp3971_i2c_write(struct i2c_client *i2c, char reg, int count,
3950cbdf7bcSMarek Szyprowski 	const u16 *src)
3960cbdf7bcSMarek Szyprowski {
3970cbdf7bcSMarek Szyprowski 	if (count != 1)
3980cbdf7bcSMarek Szyprowski 		return -EIO;
3991bddc2f5SAxel Lin 	return i2c_smbus_write_byte_data(i2c, reg, *src);
4000cbdf7bcSMarek Szyprowski }
4010cbdf7bcSMarek Szyprowski 
4020cbdf7bcSMarek Szyprowski static u8 lp3971_reg_read(struct lp3971 *lp3971, u8 reg)
4030cbdf7bcSMarek Szyprowski {
4040cbdf7bcSMarek Szyprowski 	u16 val = 0;
4050cbdf7bcSMarek Szyprowski 
4060cbdf7bcSMarek Szyprowski 	mutex_lock(&lp3971->io_lock);
4070cbdf7bcSMarek Szyprowski 
4080cbdf7bcSMarek Szyprowski 	lp3971_i2c_read(lp3971->i2c, reg, 1, &val);
4090cbdf7bcSMarek Szyprowski 
4100cbdf7bcSMarek Szyprowski 	dev_dbg(lp3971->dev, "reg read 0x%02x -> 0x%02x\n", (int)reg,
4110cbdf7bcSMarek Szyprowski 		(unsigned)val&0xff);
4120cbdf7bcSMarek Szyprowski 
4130cbdf7bcSMarek Szyprowski 	mutex_unlock(&lp3971->io_lock);
4140cbdf7bcSMarek Szyprowski 
4150cbdf7bcSMarek Szyprowski 	return val & 0xff;
4160cbdf7bcSMarek Szyprowski }
4170cbdf7bcSMarek Szyprowski 
4180cbdf7bcSMarek Szyprowski static int lp3971_set_bits(struct lp3971 *lp3971, u8 reg, u16 mask, u16 val)
4190cbdf7bcSMarek Szyprowski {
4200cbdf7bcSMarek Szyprowski 	u16 tmp;
4210cbdf7bcSMarek Szyprowski 	int ret;
4220cbdf7bcSMarek Szyprowski 
4230cbdf7bcSMarek Szyprowski 	mutex_lock(&lp3971->io_lock);
4240cbdf7bcSMarek Szyprowski 
4250cbdf7bcSMarek Szyprowski 	ret = lp3971_i2c_read(lp3971->i2c, reg, 1, &tmp);
4260cbdf7bcSMarek Szyprowski 	tmp = (tmp & ~mask) | val;
4270cbdf7bcSMarek Szyprowski 	if (ret == 0) {
4280cbdf7bcSMarek Szyprowski 		ret = lp3971_i2c_write(lp3971->i2c, reg, 1, &tmp);
4290cbdf7bcSMarek Szyprowski 		dev_dbg(lp3971->dev, "reg write 0x%02x -> 0x%02x\n", (int)reg,
4300cbdf7bcSMarek Szyprowski 			(unsigned)val&0xff);
4310cbdf7bcSMarek Szyprowski 	}
4320cbdf7bcSMarek Szyprowski 	mutex_unlock(&lp3971->io_lock);
4330cbdf7bcSMarek Szyprowski 
4340cbdf7bcSMarek Szyprowski 	return ret;
4350cbdf7bcSMarek Szyprowski }
4360cbdf7bcSMarek Szyprowski 
437ebbed04fSDmitry Torokhov static int __devinit setup_regulators(struct lp3971 *lp3971,
4380cbdf7bcSMarek Szyprowski 				      struct lp3971_platform_data *pdata)
4390cbdf7bcSMarek Szyprowski {
4400cbdf7bcSMarek Szyprowski 	int i, err;
441ebbed04fSDmitry Torokhov 
442ebbed04fSDmitry Torokhov 	lp3971->num_regulators = pdata->num_regulators;
443ebbed04fSDmitry Torokhov 	lp3971->rdev = kcalloc(pdata->num_regulators,
444ebbed04fSDmitry Torokhov 				sizeof(struct regulator_dev *), GFP_KERNEL);
44567e46f34SDan Carpenter 	if (!lp3971->rdev) {
44667e46f34SDan Carpenter 		err = -ENOMEM;
44767e46f34SDan Carpenter 		goto err_nomem;
44867e46f34SDan Carpenter 	}
4490cbdf7bcSMarek Szyprowski 
4500cbdf7bcSMarek Szyprowski 	/* Instantiate the regulators */
451ebbed04fSDmitry Torokhov 	for (i = 0; i < pdata->num_regulators; i++) {
452ebbed04fSDmitry Torokhov 		struct lp3971_regulator_subdev *reg = &pdata->regulators[i];
453ebbed04fSDmitry Torokhov 		lp3971->rdev[i] = regulator_register(&regulators[reg->id],
4542c043bcbSRajendra Nayak 				lp3971->dev, reg->initdata, lp3971, NULL);
4550cbdf7bcSMarek Szyprowski 
456d662fc82SJulia Lawall 		if (IS_ERR(lp3971->rdev[i])) {
457d662fc82SJulia Lawall 			err = PTR_ERR(lp3971->rdev[i]);
4580cbdf7bcSMarek Szyprowski 			dev_err(lp3971->dev, "regulator init failed: %d\n",
4590cbdf7bcSMarek Szyprowski 				err);
4600cbdf7bcSMarek Szyprowski 			goto error;
4610cbdf7bcSMarek Szyprowski 		}
4620cbdf7bcSMarek Szyprowski 	}
4630cbdf7bcSMarek Szyprowski 
4640cbdf7bcSMarek Szyprowski 	return 0;
465ebbed04fSDmitry Torokhov 
4660cbdf7bcSMarek Szyprowski error:
467ebbed04fSDmitry Torokhov 	while (--i >= 0)
4680cbdf7bcSMarek Szyprowski 		regulator_unregister(lp3971->rdev[i]);
4690cbdf7bcSMarek Szyprowski 	kfree(lp3971->rdev);
4700cbdf7bcSMarek Szyprowski 	lp3971->rdev = NULL;
47167e46f34SDan Carpenter err_nomem:
4720cbdf7bcSMarek Szyprowski 	return err;
4730cbdf7bcSMarek Szyprowski }
4740cbdf7bcSMarek Szyprowski 
4750cbdf7bcSMarek Szyprowski static int __devinit lp3971_i2c_probe(struct i2c_client *i2c,
4760cbdf7bcSMarek Szyprowski 			    const struct i2c_device_id *id)
4770cbdf7bcSMarek Szyprowski {
4780cbdf7bcSMarek Szyprowski 	struct lp3971 *lp3971;
4790cbdf7bcSMarek Szyprowski 	struct lp3971_platform_data *pdata = i2c->dev.platform_data;
4800cbdf7bcSMarek Szyprowski 	int ret;
4810cbdf7bcSMarek Szyprowski 	u16 val;
4820cbdf7bcSMarek Szyprowski 
483ebbed04fSDmitry Torokhov 	if (!pdata) {
484ebbed04fSDmitry Torokhov 		dev_dbg(&i2c->dev, "No platform init data supplied\n");
485ebbed04fSDmitry Torokhov 		return -ENODEV;
4860cbdf7bcSMarek Szyprowski 	}
4870cbdf7bcSMarek Szyprowski 
488ebbed04fSDmitry Torokhov 	lp3971 = kzalloc(sizeof(struct lp3971), GFP_KERNEL);
489ebbed04fSDmitry Torokhov 	if (lp3971 == NULL)
490ebbed04fSDmitry Torokhov 		return -ENOMEM;
491ebbed04fSDmitry Torokhov 
4920cbdf7bcSMarek Szyprowski 	lp3971->i2c = i2c;
4930cbdf7bcSMarek Szyprowski 	lp3971->dev = &i2c->dev;
4940cbdf7bcSMarek Szyprowski 
4950cbdf7bcSMarek Szyprowski 	mutex_init(&lp3971->io_lock);
4960cbdf7bcSMarek Szyprowski 
4970cbdf7bcSMarek Szyprowski 	/* Detect LP3971 */
4980cbdf7bcSMarek Szyprowski 	ret = lp3971_i2c_read(i2c, LP3971_SYS_CONTROL1_REG, 1, &val);
4990cbdf7bcSMarek Szyprowski 	if (ret == 0 && (val & SYS_CONTROL1_INIT_MASK) != SYS_CONTROL1_INIT_VAL)
5000cbdf7bcSMarek Szyprowski 		ret = -ENODEV;
5010cbdf7bcSMarek Szyprowski 	if (ret < 0) {
5020cbdf7bcSMarek Szyprowski 		dev_err(&i2c->dev, "failed to detect device\n");
5030cbdf7bcSMarek Szyprowski 		goto err_detect;
5040cbdf7bcSMarek Szyprowski 	}
5050cbdf7bcSMarek Szyprowski 
5060cbdf7bcSMarek Szyprowski 	ret = setup_regulators(lp3971, pdata);
5070cbdf7bcSMarek Szyprowski 	if (ret < 0)
5080cbdf7bcSMarek Szyprowski 		goto err_detect;
5090cbdf7bcSMarek Szyprowski 
510ebbed04fSDmitry Torokhov 	i2c_set_clientdata(i2c, lp3971);
5110cbdf7bcSMarek Szyprowski 	return 0;
5120cbdf7bcSMarek Szyprowski 
5130cbdf7bcSMarek Szyprowski err_detect:
5140cbdf7bcSMarek Szyprowski 	kfree(lp3971);
5150cbdf7bcSMarek Szyprowski 	return ret;
5160cbdf7bcSMarek Szyprowski }
5170cbdf7bcSMarek Szyprowski 
5180cbdf7bcSMarek Szyprowski static int __devexit lp3971_i2c_remove(struct i2c_client *i2c)
5190cbdf7bcSMarek Szyprowski {
5200cbdf7bcSMarek Szyprowski 	struct lp3971 *lp3971 = i2c_get_clientdata(i2c);
5210cbdf7bcSMarek Szyprowski 	int i;
522ebbed04fSDmitry Torokhov 
523ebbed04fSDmitry Torokhov 	for (i = 0; i < lp3971->num_regulators; i++)
524ebbed04fSDmitry Torokhov 		regulator_unregister(lp3971->rdev[i]);
525ebbed04fSDmitry Torokhov 
526ebbed04fSDmitry Torokhov 	kfree(lp3971->rdev);
5270cbdf7bcSMarek Szyprowski 	kfree(lp3971);
5280cbdf7bcSMarek Szyprowski 
5290cbdf7bcSMarek Szyprowski 	return 0;
5300cbdf7bcSMarek Szyprowski }
5310cbdf7bcSMarek Szyprowski 
5320cbdf7bcSMarek Szyprowski static const struct i2c_device_id lp3971_i2c_id[] = {
5330cbdf7bcSMarek Szyprowski        { "lp3971", 0 },
5340cbdf7bcSMarek Szyprowski        { }
5350cbdf7bcSMarek Szyprowski };
5360cbdf7bcSMarek Szyprowski MODULE_DEVICE_TABLE(i2c, lp3971_i2c_id);
5370cbdf7bcSMarek Szyprowski 
5380cbdf7bcSMarek Szyprowski static struct i2c_driver lp3971_i2c_driver = {
5390cbdf7bcSMarek Szyprowski 	.driver = {
5400cbdf7bcSMarek Szyprowski 		.name = "LP3971",
5410cbdf7bcSMarek Szyprowski 		.owner = THIS_MODULE,
5420cbdf7bcSMarek Szyprowski 	},
5430cbdf7bcSMarek Szyprowski 	.probe    = lp3971_i2c_probe,
5446113c3a5SLiam Girdwood 	.remove   = __devexit_p(lp3971_i2c_remove),
5450cbdf7bcSMarek Szyprowski 	.id_table = lp3971_i2c_id,
5460cbdf7bcSMarek Szyprowski };
5470cbdf7bcSMarek Szyprowski 
5480cbdf7bcSMarek Szyprowski static int __init lp3971_module_init(void)
5490cbdf7bcSMarek Szyprowski {
55012a1d933SWolfram Sang 	int ret;
5510cbdf7bcSMarek Szyprowski 
5520cbdf7bcSMarek Szyprowski 	ret = i2c_add_driver(&lp3971_i2c_driver);
5530cbdf7bcSMarek Szyprowski 	if (ret != 0)
5540cbdf7bcSMarek Szyprowski 		pr_err("Failed to register I2C driver: %d\n", ret);
5550cbdf7bcSMarek Szyprowski 
5560cbdf7bcSMarek Szyprowski 	return ret;
5570cbdf7bcSMarek Szyprowski }
5580cbdf7bcSMarek Szyprowski module_init(lp3971_module_init);
5590cbdf7bcSMarek Szyprowski 
5600cbdf7bcSMarek Szyprowski static void __exit lp3971_module_exit(void)
5610cbdf7bcSMarek Szyprowski {
5620cbdf7bcSMarek Szyprowski 	i2c_del_driver(&lp3971_i2c_driver);
5630cbdf7bcSMarek Szyprowski }
5640cbdf7bcSMarek Szyprowski module_exit(lp3971_module_exit);
5650cbdf7bcSMarek Szyprowski 
5660cbdf7bcSMarek Szyprowski MODULE_LICENSE("GPL");
5670cbdf7bcSMarek Szyprowski MODULE_AUTHOR("Marek Szyprowski <m.szyprowski@samsung.com>");
5680cbdf7bcSMarek Szyprowski MODULE_DESCRIPTION("LP3971 PMIC driver");
569