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(®ulators[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