xref: /openbmc/linux/drivers/regulator/lp3971.c (revision 6faa7e0a)
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>
190cbdf7bcSMarek Szyprowski #include <linux/regulator/driver.h>
200cbdf7bcSMarek Szyprowski #include <linux/regulator/lp3971.h>
210cbdf7bcSMarek Szyprowski 
220cbdf7bcSMarek Szyprowski struct lp3971 {
230cbdf7bcSMarek Szyprowski 	struct device *dev;
240cbdf7bcSMarek Szyprowski 	struct mutex io_lock;
250cbdf7bcSMarek Szyprowski 	struct i2c_client *i2c;
260cbdf7bcSMarek Szyprowski 	int num_regulators;
270cbdf7bcSMarek Szyprowski 	struct regulator_dev **rdev;
280cbdf7bcSMarek Szyprowski };
290cbdf7bcSMarek Szyprowski 
300cbdf7bcSMarek Szyprowski static u8 lp3971_reg_read(struct lp3971 *lp3971, u8 reg);
310cbdf7bcSMarek Szyprowski static int lp3971_set_bits(struct lp3971 *lp3971, u8 reg, u16 mask, u16 val);
320cbdf7bcSMarek Szyprowski 
330cbdf7bcSMarek Szyprowski #define LP3971_SYS_CONTROL1_REG 0x07
340cbdf7bcSMarek Szyprowski 
350cbdf7bcSMarek Szyprowski /* System control register 1 initial value,
360cbdf7bcSMarek Szyprowski    bits 4 and 5 are EPROM programmable */
370cbdf7bcSMarek Szyprowski #define SYS_CONTROL1_INIT_VAL 0x40
380cbdf7bcSMarek Szyprowski #define SYS_CONTROL1_INIT_MASK 0xCF
390cbdf7bcSMarek Szyprowski 
400cbdf7bcSMarek Szyprowski #define LP3971_BUCK_VOL_ENABLE_REG 0x10
410cbdf7bcSMarek Szyprowski #define LP3971_BUCK_VOL_CHANGE_REG 0x20
420cbdf7bcSMarek Szyprowski 
430cbdf7bcSMarek Szyprowski /*	Voltage control registers shift:
440cbdf7bcSMarek Szyprowski 	LP3971_BUCK1 -> 0
450cbdf7bcSMarek Szyprowski 	LP3971_BUCK2 -> 4
460cbdf7bcSMarek Szyprowski 	LP3971_BUCK3 -> 6
470cbdf7bcSMarek Szyprowski */
480cbdf7bcSMarek Szyprowski #define BUCK_VOL_CHANGE_SHIFT(x) (((1 << x) & ~0x01) << 1)
490cbdf7bcSMarek Szyprowski #define BUCK_VOL_CHANGE_FLAG_GO 0x01
500cbdf7bcSMarek Szyprowski #define BUCK_VOL_CHANGE_FLAG_TARGET 0x02
510cbdf7bcSMarek Szyprowski #define BUCK_VOL_CHANGE_FLAG_MASK 0x03
520cbdf7bcSMarek Szyprowski 
530cbdf7bcSMarek Szyprowski #define LP3971_BUCK1_BASE 0x23
540cbdf7bcSMarek Szyprowski #define LP3971_BUCK2_BASE 0x29
550cbdf7bcSMarek Szyprowski #define LP3971_BUCK3_BASE 0x32
560cbdf7bcSMarek Szyprowski 
576faa7e0aSTobias Klauser static const int buck_base_addr[] = {
580cbdf7bcSMarek Szyprowski 	LP3971_BUCK1_BASE,
590cbdf7bcSMarek Szyprowski 	LP3971_BUCK2_BASE,
600cbdf7bcSMarek Szyprowski 	LP3971_BUCK3_BASE,
610cbdf7bcSMarek Szyprowski };
620cbdf7bcSMarek Szyprowski 
630cbdf7bcSMarek Szyprowski #define LP3971_BUCK_TARGET_VOL1_REG(x) (buck_base_addr[x])
640cbdf7bcSMarek Szyprowski #define LP3971_BUCK_TARGET_VOL2_REG(x) (buck_base_addr[x]+1)
650cbdf7bcSMarek Szyprowski 
666faa7e0aSTobias Klauser static const int buck_voltage_map[] = {
670cbdf7bcSMarek Szyprowski 	   0,  800,  850,  900,  950, 1000, 1050, 1100,
680cbdf7bcSMarek Szyprowski 	1150, 1200, 1250, 1300, 1350, 1400, 1450, 1500,
690cbdf7bcSMarek Szyprowski 	1550, 1600, 1650, 1700, 1800, 1900, 2500, 2800,
700cbdf7bcSMarek Szyprowski 	3000, 3300,
710cbdf7bcSMarek Szyprowski };
720cbdf7bcSMarek Szyprowski 
730cbdf7bcSMarek Szyprowski #define BUCK_TARGET_VOL_MASK 0x3f
740cbdf7bcSMarek Szyprowski #define BUCK_TARGET_VOL_MIN_IDX 0x01
750cbdf7bcSMarek Szyprowski #define BUCK_TARGET_VOL_MAX_IDX 0x19
760cbdf7bcSMarek Szyprowski 
770cbdf7bcSMarek Szyprowski #define LP3971_BUCK_RAMP_REG(x)	(buck_base_addr[x]+2)
780cbdf7bcSMarek Szyprowski 
790cbdf7bcSMarek Szyprowski #define LP3971_LDO_ENABLE_REG 0x12
800cbdf7bcSMarek Szyprowski #define LP3971_LDO_VOL_CONTR_BASE 0x39
810cbdf7bcSMarek Szyprowski 
820cbdf7bcSMarek Szyprowski /*	Voltage control registers:
830cbdf7bcSMarek Szyprowski 	LP3971_LDO1 -> LP3971_LDO_VOL_CONTR_BASE + 0
840cbdf7bcSMarek Szyprowski 	LP3971_LDO2 -> LP3971_LDO_VOL_CONTR_BASE + 0
850cbdf7bcSMarek Szyprowski 	LP3971_LDO3 -> LP3971_LDO_VOL_CONTR_BASE + 1
860cbdf7bcSMarek Szyprowski 	LP3971_LDO4 -> LP3971_LDO_VOL_CONTR_BASE + 1
870cbdf7bcSMarek Szyprowski 	LP3971_LDO5 -> LP3971_LDO_VOL_CONTR_BASE + 2
880cbdf7bcSMarek Szyprowski */
890cbdf7bcSMarek Szyprowski #define LP3971_LDO_VOL_CONTR_REG(x)	(LP3971_LDO_VOL_CONTR_BASE + (x >> 1))
900cbdf7bcSMarek Szyprowski 
910cbdf7bcSMarek Szyprowski /*	Voltage control registers shift:
920cbdf7bcSMarek Szyprowski 	LP3971_LDO1 -> 0, LP3971_LDO2 -> 4
930cbdf7bcSMarek Szyprowski 	LP3971_LDO3 -> 0, LP3971_LDO4 -> 4
940cbdf7bcSMarek Szyprowski 	LP3971_LDO5 -> 0
950cbdf7bcSMarek Szyprowski */
960cbdf7bcSMarek Szyprowski #define LDO_VOL_CONTR_SHIFT(x) ((x & 1) << 2)
970cbdf7bcSMarek Szyprowski #define LDO_VOL_CONTR_MASK 0x0f
980cbdf7bcSMarek Szyprowski 
996faa7e0aSTobias Klauser static const int ldo45_voltage_map[] = {
1000cbdf7bcSMarek Szyprowski 	1000, 1050, 1100, 1150, 1200, 1250, 1300, 1350,
1010cbdf7bcSMarek Szyprowski 	1400, 1500, 1800, 1900, 2500, 2800, 3000, 3300,
1020cbdf7bcSMarek Szyprowski };
1030cbdf7bcSMarek Szyprowski 
1046faa7e0aSTobias Klauser static const int ldo123_voltage_map[] = {
1050cbdf7bcSMarek Szyprowski 	1800, 1900, 2000, 2100, 2200, 2300, 2400, 2500,
1060cbdf7bcSMarek Szyprowski 	2600, 2700, 2800, 2900, 3000, 3100, 3200, 3300,
1070cbdf7bcSMarek Szyprowski };
1080cbdf7bcSMarek Szyprowski 
1096faa7e0aSTobias Klauser static const int *ldo_voltage_map[] = {
1100cbdf7bcSMarek Szyprowski 	ldo123_voltage_map, /* LDO1 */
1110cbdf7bcSMarek Szyprowski 	ldo123_voltage_map, /* LDO2 */
1120cbdf7bcSMarek Szyprowski 	ldo123_voltage_map, /* LDO3 */
1130cbdf7bcSMarek Szyprowski 	ldo45_voltage_map, /* LDO4 */
1140cbdf7bcSMarek Szyprowski 	ldo45_voltage_map, /* LDO5 */
1150cbdf7bcSMarek Szyprowski };
1160cbdf7bcSMarek Szyprowski 
1170cbdf7bcSMarek Szyprowski #define LDO_VOL_VALUE_MAP(x) (ldo_voltage_map[(x - LP3971_LDO1)])
1180cbdf7bcSMarek Szyprowski 
1190cbdf7bcSMarek Szyprowski #define LDO_VOL_MIN_IDX 0x00
1200cbdf7bcSMarek Szyprowski #define LDO_VOL_MAX_IDX 0x0f
1210cbdf7bcSMarek Szyprowski 
1220cbdf7bcSMarek Szyprowski static int lp3971_ldo_list_voltage(struct regulator_dev *dev, unsigned index)
1230cbdf7bcSMarek Szyprowski {
1240cbdf7bcSMarek Szyprowski 	int ldo = rdev_get_id(dev) - LP3971_LDO1;
1250cbdf7bcSMarek Szyprowski 	return 1000 * LDO_VOL_VALUE_MAP(ldo)[index];
1260cbdf7bcSMarek Szyprowski }
1270cbdf7bcSMarek Szyprowski 
1280cbdf7bcSMarek Szyprowski static int lp3971_ldo_is_enabled(struct regulator_dev *dev)
1290cbdf7bcSMarek Szyprowski {
1300cbdf7bcSMarek Szyprowski 	struct lp3971 *lp3971 = rdev_get_drvdata(dev);
1310cbdf7bcSMarek Szyprowski 	int ldo = rdev_get_id(dev) - LP3971_LDO1;
1320cbdf7bcSMarek Szyprowski 	u16 mask = 1 << (1 + ldo);
1330cbdf7bcSMarek Szyprowski 	u16 val;
1340cbdf7bcSMarek Szyprowski 
1350cbdf7bcSMarek Szyprowski 	val = lp3971_reg_read(lp3971, LP3971_LDO_ENABLE_REG);
1360cbdf7bcSMarek Szyprowski 	return (val & mask) != 0;
1370cbdf7bcSMarek Szyprowski }
1380cbdf7bcSMarek Szyprowski 
1390cbdf7bcSMarek Szyprowski static int lp3971_ldo_enable(struct regulator_dev *dev)
1400cbdf7bcSMarek Szyprowski {
1410cbdf7bcSMarek Szyprowski 	struct lp3971 *lp3971 = rdev_get_drvdata(dev);
1420cbdf7bcSMarek Szyprowski 	int ldo = rdev_get_id(dev) - LP3971_LDO1;
1430cbdf7bcSMarek Szyprowski 	u16 mask = 1 << (1 + ldo);
1440cbdf7bcSMarek Szyprowski 
1450cbdf7bcSMarek Szyprowski 	return lp3971_set_bits(lp3971, LP3971_LDO_ENABLE_REG, mask, mask);
1460cbdf7bcSMarek Szyprowski }
1470cbdf7bcSMarek Szyprowski 
1480cbdf7bcSMarek Szyprowski static int lp3971_ldo_disable(struct regulator_dev *dev)
1490cbdf7bcSMarek Szyprowski {
1500cbdf7bcSMarek Szyprowski 	struct lp3971 *lp3971 = rdev_get_drvdata(dev);
1510cbdf7bcSMarek Szyprowski 	int ldo = rdev_get_id(dev) - LP3971_LDO1;
1520cbdf7bcSMarek Szyprowski 	u16 mask = 1 << (1 + ldo);
1530cbdf7bcSMarek Szyprowski 
1540cbdf7bcSMarek Szyprowski 	return lp3971_set_bits(lp3971, LP3971_LDO_ENABLE_REG, mask, 0);
1550cbdf7bcSMarek Szyprowski }
1560cbdf7bcSMarek Szyprowski 
1570cbdf7bcSMarek Szyprowski static int lp3971_ldo_get_voltage(struct regulator_dev *dev)
1580cbdf7bcSMarek Szyprowski {
1590cbdf7bcSMarek Szyprowski 	struct lp3971 *lp3971 = rdev_get_drvdata(dev);
1600cbdf7bcSMarek Szyprowski 	int ldo = rdev_get_id(dev) - LP3971_LDO1;
1610cbdf7bcSMarek Szyprowski 	u16 val, reg;
1620cbdf7bcSMarek Szyprowski 
1630cbdf7bcSMarek Szyprowski 	reg = lp3971_reg_read(lp3971, LP3971_LDO_VOL_CONTR_REG(ldo));
1640cbdf7bcSMarek Szyprowski 	val = (reg >> LDO_VOL_CONTR_SHIFT(ldo)) & LDO_VOL_CONTR_MASK;
1650cbdf7bcSMarek Szyprowski 
1660cbdf7bcSMarek Szyprowski 	return 1000 * LDO_VOL_VALUE_MAP(ldo)[val];
1670cbdf7bcSMarek Szyprowski }
1680cbdf7bcSMarek Szyprowski 
1690cbdf7bcSMarek Szyprowski static int lp3971_ldo_set_voltage(struct regulator_dev *dev,
1700cbdf7bcSMarek Szyprowski 				  int min_uV, int max_uV)
1710cbdf7bcSMarek Szyprowski {
1720cbdf7bcSMarek Szyprowski 	struct lp3971 *lp3971 = rdev_get_drvdata(dev);
1730cbdf7bcSMarek Szyprowski 	int ldo = rdev_get_id(dev) - LP3971_LDO1;
1740cbdf7bcSMarek Szyprowski 	int min_vol = min_uV / 1000, max_vol = max_uV / 1000;
1750cbdf7bcSMarek Szyprowski 	const int *vol_map = LDO_VOL_VALUE_MAP(ldo);
1760cbdf7bcSMarek Szyprowski 	u16 val;
1770cbdf7bcSMarek Szyprowski 
1780cbdf7bcSMarek Szyprowski 	if (min_vol < vol_map[LDO_VOL_MIN_IDX] ||
1790cbdf7bcSMarek Szyprowski 	    min_vol > vol_map[LDO_VOL_MAX_IDX])
1800cbdf7bcSMarek Szyprowski 		return -EINVAL;
1810cbdf7bcSMarek Szyprowski 
1820cbdf7bcSMarek Szyprowski 	for (val = LDO_VOL_MIN_IDX; val <= LDO_VOL_MAX_IDX; val++)
1830cbdf7bcSMarek Szyprowski 		if (vol_map[val] >= min_vol)
1840cbdf7bcSMarek Szyprowski 			break;
1850cbdf7bcSMarek Szyprowski 
18662737d44SRoel Kluin 	if (val > LDO_VOL_MAX_IDX || vol_map[val] > max_vol)
1870cbdf7bcSMarek Szyprowski 		return -EINVAL;
1880cbdf7bcSMarek Szyprowski 
1890cbdf7bcSMarek Szyprowski 	return lp3971_set_bits(lp3971, LP3971_LDO_VOL_CONTR_REG(ldo),
1900cbdf7bcSMarek Szyprowski 		LDO_VOL_CONTR_MASK << LDO_VOL_CONTR_SHIFT(ldo), val);
1910cbdf7bcSMarek Szyprowski }
1920cbdf7bcSMarek Szyprowski 
1930cbdf7bcSMarek Szyprowski static struct regulator_ops lp3971_ldo_ops = {
1940cbdf7bcSMarek Szyprowski 	.list_voltage = lp3971_ldo_list_voltage,
1950cbdf7bcSMarek Szyprowski 	.is_enabled = lp3971_ldo_is_enabled,
1960cbdf7bcSMarek Szyprowski 	.enable = lp3971_ldo_enable,
1970cbdf7bcSMarek Szyprowski 	.disable = lp3971_ldo_disable,
1980cbdf7bcSMarek Szyprowski 	.get_voltage = lp3971_ldo_get_voltage,
1990cbdf7bcSMarek Szyprowski 	.set_voltage = lp3971_ldo_set_voltage,
2000cbdf7bcSMarek Szyprowski };
2010cbdf7bcSMarek Szyprowski 
2020cbdf7bcSMarek Szyprowski static int lp3971_dcdc_list_voltage(struct regulator_dev *dev, unsigned index)
2030cbdf7bcSMarek Szyprowski {
2040cbdf7bcSMarek Szyprowski 	return 1000 * buck_voltage_map[index];
2050cbdf7bcSMarek Szyprowski }
2060cbdf7bcSMarek Szyprowski 
2070cbdf7bcSMarek Szyprowski static int lp3971_dcdc_is_enabled(struct regulator_dev *dev)
2080cbdf7bcSMarek Szyprowski {
2090cbdf7bcSMarek Szyprowski 	struct lp3971 *lp3971 = rdev_get_drvdata(dev);
2100cbdf7bcSMarek Szyprowski 	int buck = rdev_get_id(dev) - LP3971_DCDC1;
2110cbdf7bcSMarek Szyprowski 	u16 mask = 1 << (buck * 2);
2120cbdf7bcSMarek Szyprowski 	u16 val;
2130cbdf7bcSMarek Szyprowski 
2140cbdf7bcSMarek Szyprowski 	val = lp3971_reg_read(lp3971, LP3971_BUCK_VOL_ENABLE_REG);
2150cbdf7bcSMarek Szyprowski 	return (val & mask) != 0;
2160cbdf7bcSMarek Szyprowski }
2170cbdf7bcSMarek Szyprowski 
2180cbdf7bcSMarek Szyprowski static int lp3971_dcdc_enable(struct regulator_dev *dev)
2190cbdf7bcSMarek Szyprowski {
2200cbdf7bcSMarek Szyprowski 	struct lp3971 *lp3971 = rdev_get_drvdata(dev);
2210cbdf7bcSMarek Szyprowski 	int buck = rdev_get_id(dev) - LP3971_DCDC1;
2220cbdf7bcSMarek Szyprowski 	u16 mask = 1 << (buck * 2);
2230cbdf7bcSMarek Szyprowski 
2240cbdf7bcSMarek Szyprowski 	return lp3971_set_bits(lp3971, LP3971_BUCK_VOL_ENABLE_REG, mask, mask);
2250cbdf7bcSMarek Szyprowski }
2260cbdf7bcSMarek Szyprowski 
2270cbdf7bcSMarek Szyprowski static int lp3971_dcdc_disable(struct regulator_dev *dev)
2280cbdf7bcSMarek Szyprowski {
2290cbdf7bcSMarek Szyprowski 	struct lp3971 *lp3971 = rdev_get_drvdata(dev);
2300cbdf7bcSMarek Szyprowski 	int buck = rdev_get_id(dev) - LP3971_DCDC1;
2310cbdf7bcSMarek Szyprowski 	u16 mask = 1 << (buck * 2);
2320cbdf7bcSMarek Szyprowski 
2330cbdf7bcSMarek Szyprowski 	return lp3971_set_bits(lp3971, LP3971_BUCK_VOL_ENABLE_REG, mask, 0);
2340cbdf7bcSMarek Szyprowski }
2350cbdf7bcSMarek Szyprowski 
2360cbdf7bcSMarek Szyprowski static int lp3971_dcdc_get_voltage(struct regulator_dev *dev)
2370cbdf7bcSMarek Szyprowski {
2380cbdf7bcSMarek Szyprowski 	struct lp3971 *lp3971 = rdev_get_drvdata(dev);
2390cbdf7bcSMarek Szyprowski 	int buck = rdev_get_id(dev) - LP3971_DCDC1;
2400cbdf7bcSMarek Szyprowski 	u16 reg;
2410cbdf7bcSMarek Szyprowski 	int val;
2420cbdf7bcSMarek Szyprowski 
2430cbdf7bcSMarek Szyprowski 	reg = lp3971_reg_read(lp3971, LP3971_BUCK_TARGET_VOL1_REG(buck));
2440cbdf7bcSMarek Szyprowski 	reg &= BUCK_TARGET_VOL_MASK;
2450cbdf7bcSMarek Szyprowski 
2460cbdf7bcSMarek Szyprowski 	if (reg <= BUCK_TARGET_VOL_MAX_IDX)
2470cbdf7bcSMarek Szyprowski 		val = 1000 * buck_voltage_map[reg];
2480cbdf7bcSMarek Szyprowski 	else {
2490cbdf7bcSMarek Szyprowski 		val = 0;
2500cbdf7bcSMarek Szyprowski 		dev_warn(&dev->dev, "chip reported incorrect voltage value.\n");
2510cbdf7bcSMarek Szyprowski 	}
2520cbdf7bcSMarek Szyprowski 
2530cbdf7bcSMarek Szyprowski 	return val;
2540cbdf7bcSMarek Szyprowski }
2550cbdf7bcSMarek Szyprowski 
2560cbdf7bcSMarek Szyprowski static int lp3971_dcdc_set_voltage(struct regulator_dev *dev,
2570cbdf7bcSMarek Szyprowski 				  int min_uV, int max_uV)
2580cbdf7bcSMarek Szyprowski {
2590cbdf7bcSMarek Szyprowski 	struct lp3971 *lp3971 = rdev_get_drvdata(dev);
2600cbdf7bcSMarek Szyprowski 	int buck = rdev_get_id(dev) - LP3971_DCDC1;
2610cbdf7bcSMarek Szyprowski 	int min_vol = min_uV / 1000, max_vol = max_uV / 1000;
2620cbdf7bcSMarek Szyprowski 	const int *vol_map = buck_voltage_map;
2630cbdf7bcSMarek Szyprowski 	u16 val;
2640cbdf7bcSMarek Szyprowski 	int ret;
2650cbdf7bcSMarek Szyprowski 
2660cbdf7bcSMarek Szyprowski 	if (min_vol < vol_map[BUCK_TARGET_VOL_MIN_IDX] ||
2670cbdf7bcSMarek Szyprowski 	    min_vol > vol_map[BUCK_TARGET_VOL_MAX_IDX])
2680cbdf7bcSMarek Szyprowski 		return -EINVAL;
2690cbdf7bcSMarek Szyprowski 
2700cbdf7bcSMarek Szyprowski 	for (val = BUCK_TARGET_VOL_MIN_IDX; val <= BUCK_TARGET_VOL_MAX_IDX;
2710cbdf7bcSMarek Szyprowski 	     val++)
2720cbdf7bcSMarek Szyprowski 		if (vol_map[val] >= min_vol)
2730cbdf7bcSMarek Szyprowski 			break;
2740cbdf7bcSMarek Szyprowski 
27562737d44SRoel Kluin 	if (val > BUCK_TARGET_VOL_MAX_IDX || vol_map[val] > max_vol)
2760cbdf7bcSMarek Szyprowski 		return -EINVAL;
2770cbdf7bcSMarek Szyprowski 
2780cbdf7bcSMarek Szyprowski 	ret = lp3971_set_bits(lp3971, LP3971_BUCK_TARGET_VOL1_REG(buck),
2790cbdf7bcSMarek Szyprowski 	       BUCK_TARGET_VOL_MASK, val);
2800cbdf7bcSMarek Szyprowski 	if (ret)
2810cbdf7bcSMarek Szyprowski 		return ret;
2820cbdf7bcSMarek Szyprowski 
2830cbdf7bcSMarek Szyprowski 	ret = lp3971_set_bits(lp3971, LP3971_BUCK_VOL_CHANGE_REG,
2840cbdf7bcSMarek Szyprowski 	       BUCK_VOL_CHANGE_FLAG_MASK << BUCK_VOL_CHANGE_SHIFT(buck),
2850cbdf7bcSMarek Szyprowski 	       BUCK_VOL_CHANGE_FLAG_GO << BUCK_VOL_CHANGE_SHIFT(buck));
2860cbdf7bcSMarek Szyprowski 	if (ret)
2870cbdf7bcSMarek Szyprowski 		return ret;
2880cbdf7bcSMarek Szyprowski 
2890cbdf7bcSMarek Szyprowski 	return lp3971_set_bits(lp3971, LP3971_BUCK_VOL_CHANGE_REG,
2900cbdf7bcSMarek Szyprowski 	       BUCK_VOL_CHANGE_FLAG_MASK << BUCK_VOL_CHANGE_SHIFT(buck),
2910cbdf7bcSMarek Szyprowski 	       0 << BUCK_VOL_CHANGE_SHIFT(buck));
2920cbdf7bcSMarek Szyprowski }
2930cbdf7bcSMarek Szyprowski 
2940cbdf7bcSMarek Szyprowski static struct regulator_ops lp3971_dcdc_ops = {
2950cbdf7bcSMarek Szyprowski 	.list_voltage = lp3971_dcdc_list_voltage,
2960cbdf7bcSMarek Szyprowski 	.is_enabled = lp3971_dcdc_is_enabled,
2970cbdf7bcSMarek Szyprowski 	.enable = lp3971_dcdc_enable,
2980cbdf7bcSMarek Szyprowski 	.disable = lp3971_dcdc_disable,
2990cbdf7bcSMarek Szyprowski 	.get_voltage = lp3971_dcdc_get_voltage,
3000cbdf7bcSMarek Szyprowski 	.set_voltage = lp3971_dcdc_set_voltage,
3010cbdf7bcSMarek Szyprowski };
3020cbdf7bcSMarek Szyprowski 
3030cbdf7bcSMarek Szyprowski static struct regulator_desc regulators[] = {
3040cbdf7bcSMarek Szyprowski 	{
3050cbdf7bcSMarek Szyprowski 		.name = "LDO1",
3060cbdf7bcSMarek Szyprowski 		.id = LP3971_LDO1,
3070cbdf7bcSMarek Szyprowski 		.ops = &lp3971_ldo_ops,
3080cbdf7bcSMarek Szyprowski 		.n_voltages = ARRAY_SIZE(ldo123_voltage_map),
3090cbdf7bcSMarek Szyprowski 		.type = REGULATOR_VOLTAGE,
3100cbdf7bcSMarek Szyprowski 		.owner = THIS_MODULE,
3110cbdf7bcSMarek Szyprowski 	},
3120cbdf7bcSMarek Szyprowski 	{
3130cbdf7bcSMarek Szyprowski 		.name = "LDO2",
3140cbdf7bcSMarek Szyprowski 		.id = LP3971_LDO2,
3150cbdf7bcSMarek Szyprowski 		.ops = &lp3971_ldo_ops,
3160cbdf7bcSMarek Szyprowski 		.n_voltages = ARRAY_SIZE(ldo123_voltage_map),
3170cbdf7bcSMarek Szyprowski 		.type = REGULATOR_VOLTAGE,
3180cbdf7bcSMarek Szyprowski 		.owner = THIS_MODULE,
3190cbdf7bcSMarek Szyprowski 	},
3200cbdf7bcSMarek Szyprowski 	{
3210cbdf7bcSMarek Szyprowski 		.name = "LDO3",
3220cbdf7bcSMarek Szyprowski 		.id = LP3971_LDO3,
3230cbdf7bcSMarek Szyprowski 		.ops = &lp3971_ldo_ops,
3240cbdf7bcSMarek Szyprowski 		.n_voltages = ARRAY_SIZE(ldo123_voltage_map),
3250cbdf7bcSMarek Szyprowski 		.type = REGULATOR_VOLTAGE,
3260cbdf7bcSMarek Szyprowski 		.owner = THIS_MODULE,
3270cbdf7bcSMarek Szyprowski 	},
3280cbdf7bcSMarek Szyprowski 	{
3290cbdf7bcSMarek Szyprowski 		.name = "LDO4",
3300cbdf7bcSMarek Szyprowski 		.id = LP3971_LDO4,
3310cbdf7bcSMarek Szyprowski 		.ops = &lp3971_ldo_ops,
3320cbdf7bcSMarek Szyprowski 		.n_voltages = ARRAY_SIZE(ldo45_voltage_map),
3330cbdf7bcSMarek Szyprowski 		.type = REGULATOR_VOLTAGE,
3340cbdf7bcSMarek Szyprowski 		.owner = THIS_MODULE,
3350cbdf7bcSMarek Szyprowski 	},
3360cbdf7bcSMarek Szyprowski 	{
3370cbdf7bcSMarek Szyprowski 		.name = "LDO5",
3380cbdf7bcSMarek Szyprowski 		.id = LP3971_LDO5,
3390cbdf7bcSMarek Szyprowski 		.ops = &lp3971_ldo_ops,
3400cbdf7bcSMarek Szyprowski 		.n_voltages = ARRAY_SIZE(ldo45_voltage_map),
3410cbdf7bcSMarek Szyprowski 		.type = REGULATOR_VOLTAGE,
3420cbdf7bcSMarek Szyprowski 		.owner = THIS_MODULE,
3430cbdf7bcSMarek Szyprowski 	},
3440cbdf7bcSMarek Szyprowski 	{
3450cbdf7bcSMarek Szyprowski 		.name = "DCDC1",
3460cbdf7bcSMarek Szyprowski 		.id = LP3971_DCDC1,
3470cbdf7bcSMarek Szyprowski 		.ops = &lp3971_dcdc_ops,
3480cbdf7bcSMarek Szyprowski 		.n_voltages = ARRAY_SIZE(buck_voltage_map),
3490cbdf7bcSMarek Szyprowski 		.type = REGULATOR_VOLTAGE,
3500cbdf7bcSMarek Szyprowski 		.owner = THIS_MODULE,
3510cbdf7bcSMarek Szyprowski 	},
3520cbdf7bcSMarek Szyprowski 	{
3530cbdf7bcSMarek Szyprowski 		.name = "DCDC2",
3540cbdf7bcSMarek Szyprowski 		.id = LP3971_DCDC2,
3550cbdf7bcSMarek Szyprowski 		.ops = &lp3971_dcdc_ops,
3560cbdf7bcSMarek Szyprowski 		.n_voltages = ARRAY_SIZE(buck_voltage_map),
3570cbdf7bcSMarek Szyprowski 		.type = REGULATOR_VOLTAGE,
3580cbdf7bcSMarek Szyprowski 		.owner = THIS_MODULE,
3590cbdf7bcSMarek Szyprowski 	},
3600cbdf7bcSMarek Szyprowski 	{
3610cbdf7bcSMarek Szyprowski 		.name = "DCDC3",
3620cbdf7bcSMarek Szyprowski 		.id = LP3971_DCDC3,
3630cbdf7bcSMarek Szyprowski 		.ops = &lp3971_dcdc_ops,
3640cbdf7bcSMarek Szyprowski 		.n_voltages = ARRAY_SIZE(buck_voltage_map),
3650cbdf7bcSMarek Szyprowski 		.type = REGULATOR_VOLTAGE,
3660cbdf7bcSMarek Szyprowski 		.owner = THIS_MODULE,
3670cbdf7bcSMarek Szyprowski 	},
3680cbdf7bcSMarek Szyprowski };
3690cbdf7bcSMarek Szyprowski 
3700cbdf7bcSMarek Szyprowski static int lp3971_i2c_read(struct i2c_client *i2c, char reg, int count,
3710cbdf7bcSMarek Szyprowski 	u16 *dest)
3720cbdf7bcSMarek Szyprowski {
3730cbdf7bcSMarek Szyprowski 	int ret;
3740cbdf7bcSMarek Szyprowski 
3750cbdf7bcSMarek Szyprowski 	if (count != 1)
3760cbdf7bcSMarek Szyprowski 		return -EIO;
3770cbdf7bcSMarek Szyprowski 	ret = i2c_smbus_read_byte_data(i2c, reg);
3780cbdf7bcSMarek Szyprowski 	if (ret < 0 || count != 1)
3790cbdf7bcSMarek Szyprowski 		return -EIO;
3800cbdf7bcSMarek Szyprowski 
3810cbdf7bcSMarek Szyprowski 	*dest = ret;
3820cbdf7bcSMarek Szyprowski 	return 0;
3830cbdf7bcSMarek Szyprowski }
3840cbdf7bcSMarek Szyprowski 
3850cbdf7bcSMarek Szyprowski static int lp3971_i2c_write(struct i2c_client *i2c, char reg, int count,
3860cbdf7bcSMarek Szyprowski 	const u16 *src)
3870cbdf7bcSMarek Szyprowski {
3880cbdf7bcSMarek Szyprowski 	int ret;
3890cbdf7bcSMarek Szyprowski 
3900cbdf7bcSMarek Szyprowski 	if (count != 1)
3910cbdf7bcSMarek Szyprowski 		return -EIO;
3920cbdf7bcSMarek Szyprowski 	ret = i2c_smbus_write_byte_data(i2c, reg, *src);
3930cbdf7bcSMarek Szyprowski 	if (ret >= 0)
3940cbdf7bcSMarek Szyprowski 		return 0;
3950cbdf7bcSMarek Szyprowski 
3960cbdf7bcSMarek Szyprowski 	return ret;
3970cbdf7bcSMarek Szyprowski }
3980cbdf7bcSMarek Szyprowski 
3990cbdf7bcSMarek Szyprowski static u8 lp3971_reg_read(struct lp3971 *lp3971, u8 reg)
4000cbdf7bcSMarek Szyprowski {
4010cbdf7bcSMarek Szyprowski 	u16 val = 0;
4020cbdf7bcSMarek Szyprowski 
4030cbdf7bcSMarek Szyprowski 	mutex_lock(&lp3971->io_lock);
4040cbdf7bcSMarek Szyprowski 
4050cbdf7bcSMarek Szyprowski 	lp3971_i2c_read(lp3971->i2c, reg, 1, &val);
4060cbdf7bcSMarek Szyprowski 
4070cbdf7bcSMarek Szyprowski 	dev_dbg(lp3971->dev, "reg read 0x%02x -> 0x%02x\n", (int)reg,
4080cbdf7bcSMarek Szyprowski 		(unsigned)val&0xff);
4090cbdf7bcSMarek Szyprowski 
4100cbdf7bcSMarek Szyprowski 	mutex_unlock(&lp3971->io_lock);
4110cbdf7bcSMarek Szyprowski 
4120cbdf7bcSMarek Szyprowski 	return val & 0xff;
4130cbdf7bcSMarek Szyprowski }
4140cbdf7bcSMarek Szyprowski 
4150cbdf7bcSMarek Szyprowski static int lp3971_set_bits(struct lp3971 *lp3971, u8 reg, u16 mask, u16 val)
4160cbdf7bcSMarek Szyprowski {
4170cbdf7bcSMarek Szyprowski 	u16 tmp;
4180cbdf7bcSMarek Szyprowski 	int ret;
4190cbdf7bcSMarek Szyprowski 
4200cbdf7bcSMarek Szyprowski 	mutex_lock(&lp3971->io_lock);
4210cbdf7bcSMarek Szyprowski 
4220cbdf7bcSMarek Szyprowski 	ret = lp3971_i2c_read(lp3971->i2c, reg, 1, &tmp);
4230cbdf7bcSMarek Szyprowski 	tmp = (tmp & ~mask) | val;
4240cbdf7bcSMarek Szyprowski 	if (ret == 0) {
4250cbdf7bcSMarek Szyprowski 		ret = lp3971_i2c_write(lp3971->i2c, reg, 1, &tmp);
4260cbdf7bcSMarek Szyprowski 		dev_dbg(lp3971->dev, "reg write 0x%02x -> 0x%02x\n", (int)reg,
4270cbdf7bcSMarek Szyprowski 			(unsigned)val&0xff);
4280cbdf7bcSMarek Szyprowski 	}
4290cbdf7bcSMarek Szyprowski 	mutex_unlock(&lp3971->io_lock);
4300cbdf7bcSMarek Szyprowski 
4310cbdf7bcSMarek Szyprowski 	return ret;
4320cbdf7bcSMarek Szyprowski }
4330cbdf7bcSMarek Szyprowski 
4340cbdf7bcSMarek Szyprowski static int setup_regulators(struct lp3971 *lp3971,
4350cbdf7bcSMarek Szyprowski 	struct lp3971_platform_data *pdata)
4360cbdf7bcSMarek Szyprowski {
4370cbdf7bcSMarek Szyprowski 	int i, err;
4380cbdf7bcSMarek Szyprowski 	int num_regulators = pdata->num_regulators;
4390cbdf7bcSMarek Szyprowski 	lp3971->num_regulators = num_regulators;
4400cbdf7bcSMarek Szyprowski 	lp3971->rdev = kzalloc(sizeof(struct regulator_dev *) * num_regulators,
4410cbdf7bcSMarek Szyprowski 		GFP_KERNEL);
4420cbdf7bcSMarek Szyprowski 
4430cbdf7bcSMarek Szyprowski 	/* Instantiate the regulators */
4440cbdf7bcSMarek Szyprowski 	for (i = 0; i < num_regulators; i++) {
4450cbdf7bcSMarek Szyprowski 		int id = pdata->regulators[i].id;
4460cbdf7bcSMarek Szyprowski 		lp3971->rdev[i] = regulator_register(&regulators[id],
4470cbdf7bcSMarek Szyprowski 			lp3971->dev, pdata->regulators[i].initdata, lp3971);
4480cbdf7bcSMarek Szyprowski 
449d662fc82SJulia Lawall 		if (IS_ERR(lp3971->rdev[i])) {
450d662fc82SJulia Lawall 			err = PTR_ERR(lp3971->rdev[i]);
4510cbdf7bcSMarek Szyprowski 			dev_err(lp3971->dev, "regulator init failed: %d\n",
4520cbdf7bcSMarek Szyprowski 				err);
4530cbdf7bcSMarek Szyprowski 			goto error;
4540cbdf7bcSMarek Szyprowski 		}
4550cbdf7bcSMarek Szyprowski 	}
4560cbdf7bcSMarek Szyprowski 
4570cbdf7bcSMarek Szyprowski 	return 0;
4580cbdf7bcSMarek Szyprowski error:
4590cbdf7bcSMarek Szyprowski 	for (i = 0; i < num_regulators; i++)
4600cbdf7bcSMarek Szyprowski 		if (lp3971->rdev[i])
4610cbdf7bcSMarek Szyprowski 			regulator_unregister(lp3971->rdev[i]);
4620cbdf7bcSMarek Szyprowski 	kfree(lp3971->rdev);
4630cbdf7bcSMarek Szyprowski 	lp3971->rdev = NULL;
4640cbdf7bcSMarek Szyprowski 	return err;
4650cbdf7bcSMarek Szyprowski }
4660cbdf7bcSMarek Szyprowski 
4670cbdf7bcSMarek Szyprowski static int __devinit lp3971_i2c_probe(struct i2c_client *i2c,
4680cbdf7bcSMarek Szyprowski 			    const struct i2c_device_id *id)
4690cbdf7bcSMarek Szyprowski {
4700cbdf7bcSMarek Szyprowski 	struct lp3971 *lp3971;
4710cbdf7bcSMarek Szyprowski 	struct lp3971_platform_data *pdata = i2c->dev.platform_data;
4720cbdf7bcSMarek Szyprowski 	int ret;
4730cbdf7bcSMarek Szyprowski 	u16 val;
4740cbdf7bcSMarek Szyprowski 
4750cbdf7bcSMarek Szyprowski 	lp3971 = kzalloc(sizeof(struct lp3971), GFP_KERNEL);
4760cbdf7bcSMarek Szyprowski 	if (lp3971 == NULL) {
4770cbdf7bcSMarek Szyprowski 		ret = -ENOMEM;
4780cbdf7bcSMarek Szyprowski 		goto err;
4790cbdf7bcSMarek Szyprowski 	}
4800cbdf7bcSMarek Szyprowski 
4810cbdf7bcSMarek Szyprowski 	lp3971->i2c = i2c;
4820cbdf7bcSMarek Szyprowski 	lp3971->dev = &i2c->dev;
4830cbdf7bcSMarek Szyprowski 	i2c_set_clientdata(i2c, lp3971);
4840cbdf7bcSMarek Szyprowski 
4850cbdf7bcSMarek Szyprowski 	mutex_init(&lp3971->io_lock);
4860cbdf7bcSMarek Szyprowski 
4870cbdf7bcSMarek Szyprowski 	/* Detect LP3971 */
4880cbdf7bcSMarek Szyprowski 	ret = lp3971_i2c_read(i2c, LP3971_SYS_CONTROL1_REG, 1, &val);
4890cbdf7bcSMarek Szyprowski 	if (ret == 0 && (val & SYS_CONTROL1_INIT_MASK) != SYS_CONTROL1_INIT_VAL)
4900cbdf7bcSMarek Szyprowski 		ret = -ENODEV;
4910cbdf7bcSMarek Szyprowski 	if (ret < 0) {
4920cbdf7bcSMarek Szyprowski 		dev_err(&i2c->dev, "failed to detect device\n");
4930cbdf7bcSMarek Szyprowski 		goto err_detect;
4940cbdf7bcSMarek Szyprowski 	}
4950cbdf7bcSMarek Szyprowski 
4960cbdf7bcSMarek Szyprowski 	if (pdata) {
4970cbdf7bcSMarek Szyprowski 		ret = setup_regulators(lp3971, pdata);
4980cbdf7bcSMarek Szyprowski 		if (ret < 0)
4990cbdf7bcSMarek Szyprowski 			goto err_detect;
5000cbdf7bcSMarek Szyprowski 	} else
5010cbdf7bcSMarek Szyprowski 		dev_warn(lp3971->dev, "No platform init data supplied\n");
5020cbdf7bcSMarek Szyprowski 
5030cbdf7bcSMarek Szyprowski 	return 0;
5040cbdf7bcSMarek Szyprowski 
5050cbdf7bcSMarek Szyprowski err_detect:
5060cbdf7bcSMarek Szyprowski 	i2c_set_clientdata(i2c, NULL);
5070cbdf7bcSMarek Szyprowski 	kfree(lp3971);
5080cbdf7bcSMarek Szyprowski err:
5090cbdf7bcSMarek Szyprowski 	return ret;
5100cbdf7bcSMarek Szyprowski }
5110cbdf7bcSMarek Szyprowski 
5120cbdf7bcSMarek Szyprowski static int __devexit lp3971_i2c_remove(struct i2c_client *i2c)
5130cbdf7bcSMarek Szyprowski {
5140cbdf7bcSMarek Szyprowski 	struct lp3971 *lp3971 = i2c_get_clientdata(i2c);
5150cbdf7bcSMarek Szyprowski 	int i;
5160cbdf7bcSMarek Szyprowski 	for (i = 0; i < lp3971->num_regulators; i++)
5170cbdf7bcSMarek Szyprowski 		if (lp3971->rdev[i])
5180cbdf7bcSMarek Szyprowski 			regulator_unregister(lp3971->rdev[i]);
5190cbdf7bcSMarek Szyprowski 	kfree(lp3971->rdev);
5200cbdf7bcSMarek Szyprowski 	i2c_set_clientdata(i2c, NULL);
5210cbdf7bcSMarek Szyprowski 	kfree(lp3971);
5220cbdf7bcSMarek Szyprowski 
5230cbdf7bcSMarek Szyprowski 	return 0;
5240cbdf7bcSMarek Szyprowski }
5250cbdf7bcSMarek Szyprowski 
5260cbdf7bcSMarek Szyprowski static const struct i2c_device_id lp3971_i2c_id[] = {
5270cbdf7bcSMarek Szyprowski        { "lp3971", 0 },
5280cbdf7bcSMarek Szyprowski        { }
5290cbdf7bcSMarek Szyprowski };
5300cbdf7bcSMarek Szyprowski MODULE_DEVICE_TABLE(i2c, lp3971_i2c_id);
5310cbdf7bcSMarek Szyprowski 
5320cbdf7bcSMarek Szyprowski static struct i2c_driver lp3971_i2c_driver = {
5330cbdf7bcSMarek Szyprowski 	.driver = {
5340cbdf7bcSMarek Szyprowski 		.name = "LP3971",
5350cbdf7bcSMarek Szyprowski 		.owner = THIS_MODULE,
5360cbdf7bcSMarek Szyprowski 	},
5370cbdf7bcSMarek Szyprowski 	.probe    = lp3971_i2c_probe,
5386113c3a5SLiam Girdwood 	.remove   = __devexit_p(lp3971_i2c_remove),
5390cbdf7bcSMarek Szyprowski 	.id_table = lp3971_i2c_id,
5400cbdf7bcSMarek Szyprowski };
5410cbdf7bcSMarek Szyprowski 
5420cbdf7bcSMarek Szyprowski static int __init lp3971_module_init(void)
5430cbdf7bcSMarek Szyprowski {
54412a1d933SWolfram Sang 	int ret;
5450cbdf7bcSMarek Szyprowski 
5460cbdf7bcSMarek Szyprowski 	ret = i2c_add_driver(&lp3971_i2c_driver);
5470cbdf7bcSMarek Szyprowski 	if (ret != 0)
5480cbdf7bcSMarek Szyprowski 		pr_err("Failed to register I2C driver: %d\n", ret);
5490cbdf7bcSMarek Szyprowski 
5500cbdf7bcSMarek Szyprowski 	return ret;
5510cbdf7bcSMarek Szyprowski }
5520cbdf7bcSMarek Szyprowski module_init(lp3971_module_init);
5530cbdf7bcSMarek Szyprowski 
5540cbdf7bcSMarek Szyprowski static void __exit lp3971_module_exit(void)
5550cbdf7bcSMarek Szyprowski {
5560cbdf7bcSMarek Szyprowski 	i2c_del_driver(&lp3971_i2c_driver);
5570cbdf7bcSMarek Szyprowski }
5580cbdf7bcSMarek Szyprowski module_exit(lp3971_module_exit);
5590cbdf7bcSMarek Szyprowski 
5600cbdf7bcSMarek Szyprowski MODULE_LICENSE("GPL");
5610cbdf7bcSMarek Szyprowski MODULE_AUTHOR("Marek Szyprowski <m.szyprowski@samsung.com>");
5620cbdf7bcSMarek Szyprowski MODULE_DESCRIPTION("LP3971 PMIC driver");
563