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; 127dd8e2314SAxel Lin 128dd8e2314SAxel Lin if (index > LDO_VOL_MAX_IDX) 129dd8e2314SAxel Lin return -EINVAL; 130dd8e2314SAxel Lin 1310cbdf7bcSMarek Szyprowski return 1000 * LDO_VOL_VALUE_MAP(ldo)[index]; 1320cbdf7bcSMarek Szyprowski } 1330cbdf7bcSMarek Szyprowski 1340cbdf7bcSMarek Szyprowski static int lp3971_ldo_is_enabled(struct regulator_dev *dev) 1350cbdf7bcSMarek Szyprowski { 1360cbdf7bcSMarek Szyprowski struct lp3971 *lp3971 = rdev_get_drvdata(dev); 1370cbdf7bcSMarek Szyprowski int ldo = rdev_get_id(dev) - LP3971_LDO1; 1380cbdf7bcSMarek Szyprowski u16 mask = 1 << (1 + ldo); 1390cbdf7bcSMarek Szyprowski u16 val; 1400cbdf7bcSMarek Szyprowski 1410cbdf7bcSMarek Szyprowski val = lp3971_reg_read(lp3971, LP3971_LDO_ENABLE_REG); 1420cbdf7bcSMarek Szyprowski return (val & mask) != 0; 1430cbdf7bcSMarek Szyprowski } 1440cbdf7bcSMarek Szyprowski 1450cbdf7bcSMarek Szyprowski static int lp3971_ldo_enable(struct regulator_dev *dev) 1460cbdf7bcSMarek Szyprowski { 1470cbdf7bcSMarek Szyprowski struct lp3971 *lp3971 = rdev_get_drvdata(dev); 1480cbdf7bcSMarek Szyprowski int ldo = rdev_get_id(dev) - LP3971_LDO1; 1490cbdf7bcSMarek Szyprowski u16 mask = 1 << (1 + ldo); 1500cbdf7bcSMarek Szyprowski 1510cbdf7bcSMarek Szyprowski return lp3971_set_bits(lp3971, LP3971_LDO_ENABLE_REG, mask, mask); 1520cbdf7bcSMarek Szyprowski } 1530cbdf7bcSMarek Szyprowski 1540cbdf7bcSMarek Szyprowski static int lp3971_ldo_disable(struct regulator_dev *dev) 1550cbdf7bcSMarek Szyprowski { 1560cbdf7bcSMarek Szyprowski struct lp3971 *lp3971 = rdev_get_drvdata(dev); 1570cbdf7bcSMarek Szyprowski int ldo = rdev_get_id(dev) - LP3971_LDO1; 1580cbdf7bcSMarek Szyprowski u16 mask = 1 << (1 + ldo); 1590cbdf7bcSMarek Szyprowski 1600cbdf7bcSMarek Szyprowski return lp3971_set_bits(lp3971, LP3971_LDO_ENABLE_REG, mask, 0); 1610cbdf7bcSMarek Szyprowski } 1620cbdf7bcSMarek Szyprowski 1630cbdf7bcSMarek Szyprowski static int lp3971_ldo_get_voltage(struct regulator_dev *dev) 1640cbdf7bcSMarek Szyprowski { 1650cbdf7bcSMarek Szyprowski struct lp3971 *lp3971 = rdev_get_drvdata(dev); 1660cbdf7bcSMarek Szyprowski int ldo = rdev_get_id(dev) - LP3971_LDO1; 1670cbdf7bcSMarek Szyprowski u16 val, reg; 1680cbdf7bcSMarek Szyprowski 1690cbdf7bcSMarek Szyprowski reg = lp3971_reg_read(lp3971, LP3971_LDO_VOL_CONTR_REG(ldo)); 1700cbdf7bcSMarek Szyprowski val = (reg >> LDO_VOL_CONTR_SHIFT(ldo)) & LDO_VOL_CONTR_MASK; 1710cbdf7bcSMarek Szyprowski 1720cbdf7bcSMarek Szyprowski return 1000 * LDO_VOL_VALUE_MAP(ldo)[val]; 1730cbdf7bcSMarek Szyprowski } 1740cbdf7bcSMarek Szyprowski 175dd8e2314SAxel Lin static int lp3971_ldo_set_voltage_sel(struct regulator_dev *dev, 176dd8e2314SAxel Lin unsigned int selector) 1770cbdf7bcSMarek Szyprowski { 1780cbdf7bcSMarek Szyprowski struct lp3971 *lp3971 = rdev_get_drvdata(dev); 1790cbdf7bcSMarek Szyprowski int ldo = rdev_get_id(dev) - LP3971_LDO1; 1803a93f2a9SMark Brown 1810cbdf7bcSMarek Szyprowski return lp3971_set_bits(lp3971, LP3971_LDO_VOL_CONTR_REG(ldo), 182cdb868f5SAxel Lin LDO_VOL_CONTR_MASK << LDO_VOL_CONTR_SHIFT(ldo), 183dd8e2314SAxel Lin selector << LDO_VOL_CONTR_SHIFT(ldo)); 1840cbdf7bcSMarek Szyprowski } 1850cbdf7bcSMarek Szyprowski 1860cbdf7bcSMarek Szyprowski static struct regulator_ops lp3971_ldo_ops = { 1870cbdf7bcSMarek Szyprowski .list_voltage = lp3971_ldo_list_voltage, 1880cbdf7bcSMarek Szyprowski .is_enabled = lp3971_ldo_is_enabled, 1890cbdf7bcSMarek Szyprowski .enable = lp3971_ldo_enable, 1900cbdf7bcSMarek Szyprowski .disable = lp3971_ldo_disable, 1910cbdf7bcSMarek Szyprowski .get_voltage = lp3971_ldo_get_voltage, 192dd8e2314SAxel Lin .set_voltage_sel = lp3971_ldo_set_voltage_sel, 1930cbdf7bcSMarek Szyprowski }; 1940cbdf7bcSMarek Szyprowski 1950cbdf7bcSMarek Szyprowski static int lp3971_dcdc_list_voltage(struct regulator_dev *dev, unsigned index) 1960cbdf7bcSMarek Szyprowski { 197dd8e2314SAxel Lin if (index < BUCK_TARGET_VOL_MIN_IDX || index > BUCK_TARGET_VOL_MAX_IDX) 198dd8e2314SAxel Lin return -EINVAL; 199dd8e2314SAxel Lin 2000cbdf7bcSMarek Szyprowski return 1000 * buck_voltage_map[index]; 2010cbdf7bcSMarek Szyprowski } 2020cbdf7bcSMarek Szyprowski 2030cbdf7bcSMarek Szyprowski static int lp3971_dcdc_is_enabled(struct regulator_dev *dev) 2040cbdf7bcSMarek Szyprowski { 2050cbdf7bcSMarek Szyprowski struct lp3971 *lp3971 = rdev_get_drvdata(dev); 2060cbdf7bcSMarek Szyprowski int buck = rdev_get_id(dev) - LP3971_DCDC1; 2070cbdf7bcSMarek Szyprowski u16 mask = 1 << (buck * 2); 2080cbdf7bcSMarek Szyprowski u16 val; 2090cbdf7bcSMarek Szyprowski 2100cbdf7bcSMarek Szyprowski val = lp3971_reg_read(lp3971, LP3971_BUCK_VOL_ENABLE_REG); 2110cbdf7bcSMarek Szyprowski return (val & mask) != 0; 2120cbdf7bcSMarek Szyprowski } 2130cbdf7bcSMarek Szyprowski 2140cbdf7bcSMarek Szyprowski static int lp3971_dcdc_enable(struct regulator_dev *dev) 2150cbdf7bcSMarek Szyprowski { 2160cbdf7bcSMarek Szyprowski struct lp3971 *lp3971 = rdev_get_drvdata(dev); 2170cbdf7bcSMarek Szyprowski int buck = rdev_get_id(dev) - LP3971_DCDC1; 2180cbdf7bcSMarek Szyprowski u16 mask = 1 << (buck * 2); 2190cbdf7bcSMarek Szyprowski 2200cbdf7bcSMarek Szyprowski return lp3971_set_bits(lp3971, LP3971_BUCK_VOL_ENABLE_REG, mask, mask); 2210cbdf7bcSMarek Szyprowski } 2220cbdf7bcSMarek Szyprowski 2230cbdf7bcSMarek Szyprowski static int lp3971_dcdc_disable(struct regulator_dev *dev) 2240cbdf7bcSMarek Szyprowski { 2250cbdf7bcSMarek Szyprowski struct lp3971 *lp3971 = rdev_get_drvdata(dev); 2260cbdf7bcSMarek Szyprowski int buck = rdev_get_id(dev) - LP3971_DCDC1; 2270cbdf7bcSMarek Szyprowski u16 mask = 1 << (buck * 2); 2280cbdf7bcSMarek Szyprowski 2290cbdf7bcSMarek Szyprowski return lp3971_set_bits(lp3971, LP3971_BUCK_VOL_ENABLE_REG, mask, 0); 2300cbdf7bcSMarek Szyprowski } 2310cbdf7bcSMarek Szyprowski 2320cbdf7bcSMarek Szyprowski static int lp3971_dcdc_get_voltage(struct regulator_dev *dev) 2330cbdf7bcSMarek Szyprowski { 2340cbdf7bcSMarek Szyprowski struct lp3971 *lp3971 = rdev_get_drvdata(dev); 2350cbdf7bcSMarek Szyprowski int buck = rdev_get_id(dev) - LP3971_DCDC1; 2360cbdf7bcSMarek Szyprowski u16 reg; 2370cbdf7bcSMarek Szyprowski int val; 2380cbdf7bcSMarek Szyprowski 2390cbdf7bcSMarek Szyprowski reg = lp3971_reg_read(lp3971, LP3971_BUCK_TARGET_VOL1_REG(buck)); 2400cbdf7bcSMarek Szyprowski reg &= BUCK_TARGET_VOL_MASK; 2410cbdf7bcSMarek Szyprowski 2420cbdf7bcSMarek Szyprowski if (reg <= BUCK_TARGET_VOL_MAX_IDX) 2430cbdf7bcSMarek Szyprowski val = 1000 * buck_voltage_map[reg]; 2440cbdf7bcSMarek Szyprowski else { 2450cbdf7bcSMarek Szyprowski val = 0; 2460cbdf7bcSMarek Szyprowski dev_warn(&dev->dev, "chip reported incorrect voltage value.\n"); 2470cbdf7bcSMarek Szyprowski } 2480cbdf7bcSMarek Szyprowski 2490cbdf7bcSMarek Szyprowski return val; 2500cbdf7bcSMarek Szyprowski } 2510cbdf7bcSMarek Szyprowski 252dd8e2314SAxel Lin static int lp3971_dcdc_set_voltage_sel(struct regulator_dev *dev, 253dd8e2314SAxel Lin unsigned int selector) 2540cbdf7bcSMarek Szyprowski { 2550cbdf7bcSMarek Szyprowski struct lp3971 *lp3971 = rdev_get_drvdata(dev); 2560cbdf7bcSMarek Szyprowski int buck = rdev_get_id(dev) - LP3971_DCDC1; 2570cbdf7bcSMarek Szyprowski int ret; 2580cbdf7bcSMarek Szyprowski 2590cbdf7bcSMarek Szyprowski ret = lp3971_set_bits(lp3971, LP3971_BUCK_TARGET_VOL1_REG(buck), 260dd8e2314SAxel Lin BUCK_TARGET_VOL_MASK, selector); 2610cbdf7bcSMarek Szyprowski if (ret) 2620cbdf7bcSMarek Szyprowski return ret; 2630cbdf7bcSMarek Szyprowski 2640cbdf7bcSMarek Szyprowski ret = lp3971_set_bits(lp3971, LP3971_BUCK_VOL_CHANGE_REG, 2650cbdf7bcSMarek Szyprowski BUCK_VOL_CHANGE_FLAG_MASK << BUCK_VOL_CHANGE_SHIFT(buck), 2660cbdf7bcSMarek Szyprowski BUCK_VOL_CHANGE_FLAG_GO << BUCK_VOL_CHANGE_SHIFT(buck)); 2670cbdf7bcSMarek Szyprowski if (ret) 2680cbdf7bcSMarek Szyprowski return ret; 2690cbdf7bcSMarek Szyprowski 2700cbdf7bcSMarek Szyprowski return lp3971_set_bits(lp3971, LP3971_BUCK_VOL_CHANGE_REG, 2710cbdf7bcSMarek Szyprowski BUCK_VOL_CHANGE_FLAG_MASK << BUCK_VOL_CHANGE_SHIFT(buck), 2720cbdf7bcSMarek Szyprowski 0 << BUCK_VOL_CHANGE_SHIFT(buck)); 2730cbdf7bcSMarek Szyprowski } 2740cbdf7bcSMarek Szyprowski 2750cbdf7bcSMarek Szyprowski static struct regulator_ops lp3971_dcdc_ops = { 2760cbdf7bcSMarek Szyprowski .list_voltage = lp3971_dcdc_list_voltage, 2770cbdf7bcSMarek Szyprowski .is_enabled = lp3971_dcdc_is_enabled, 2780cbdf7bcSMarek Szyprowski .enable = lp3971_dcdc_enable, 2790cbdf7bcSMarek Szyprowski .disable = lp3971_dcdc_disable, 2800cbdf7bcSMarek Szyprowski .get_voltage = lp3971_dcdc_get_voltage, 281dd8e2314SAxel Lin .set_voltage_sel = lp3971_dcdc_set_voltage_sel, 2820cbdf7bcSMarek Szyprowski }; 2830cbdf7bcSMarek Szyprowski 2840cbdf7bcSMarek Szyprowski static struct regulator_desc regulators[] = { 2850cbdf7bcSMarek Szyprowski { 2860cbdf7bcSMarek Szyprowski .name = "LDO1", 2870cbdf7bcSMarek Szyprowski .id = LP3971_LDO1, 2880cbdf7bcSMarek Szyprowski .ops = &lp3971_ldo_ops, 2890cbdf7bcSMarek Szyprowski .n_voltages = ARRAY_SIZE(ldo123_voltage_map), 2900cbdf7bcSMarek Szyprowski .type = REGULATOR_VOLTAGE, 2910cbdf7bcSMarek Szyprowski .owner = THIS_MODULE, 2920cbdf7bcSMarek Szyprowski }, 2930cbdf7bcSMarek Szyprowski { 2940cbdf7bcSMarek Szyprowski .name = "LDO2", 2950cbdf7bcSMarek Szyprowski .id = LP3971_LDO2, 2960cbdf7bcSMarek Szyprowski .ops = &lp3971_ldo_ops, 2970cbdf7bcSMarek Szyprowski .n_voltages = ARRAY_SIZE(ldo123_voltage_map), 2980cbdf7bcSMarek Szyprowski .type = REGULATOR_VOLTAGE, 2990cbdf7bcSMarek Szyprowski .owner = THIS_MODULE, 3000cbdf7bcSMarek Szyprowski }, 3010cbdf7bcSMarek Szyprowski { 3020cbdf7bcSMarek Szyprowski .name = "LDO3", 3030cbdf7bcSMarek Szyprowski .id = LP3971_LDO3, 3040cbdf7bcSMarek Szyprowski .ops = &lp3971_ldo_ops, 3050cbdf7bcSMarek Szyprowski .n_voltages = ARRAY_SIZE(ldo123_voltage_map), 3060cbdf7bcSMarek Szyprowski .type = REGULATOR_VOLTAGE, 3070cbdf7bcSMarek Szyprowski .owner = THIS_MODULE, 3080cbdf7bcSMarek Szyprowski }, 3090cbdf7bcSMarek Szyprowski { 3100cbdf7bcSMarek Szyprowski .name = "LDO4", 3110cbdf7bcSMarek Szyprowski .id = LP3971_LDO4, 3120cbdf7bcSMarek Szyprowski .ops = &lp3971_ldo_ops, 3130cbdf7bcSMarek Szyprowski .n_voltages = ARRAY_SIZE(ldo45_voltage_map), 3140cbdf7bcSMarek Szyprowski .type = REGULATOR_VOLTAGE, 3150cbdf7bcSMarek Szyprowski .owner = THIS_MODULE, 3160cbdf7bcSMarek Szyprowski }, 3170cbdf7bcSMarek Szyprowski { 3180cbdf7bcSMarek Szyprowski .name = "LDO5", 3190cbdf7bcSMarek Szyprowski .id = LP3971_LDO5, 3200cbdf7bcSMarek Szyprowski .ops = &lp3971_ldo_ops, 3210cbdf7bcSMarek Szyprowski .n_voltages = ARRAY_SIZE(ldo45_voltage_map), 3220cbdf7bcSMarek Szyprowski .type = REGULATOR_VOLTAGE, 3230cbdf7bcSMarek Szyprowski .owner = THIS_MODULE, 3240cbdf7bcSMarek Szyprowski }, 3250cbdf7bcSMarek Szyprowski { 3260cbdf7bcSMarek Szyprowski .name = "DCDC1", 3270cbdf7bcSMarek Szyprowski .id = LP3971_DCDC1, 3280cbdf7bcSMarek Szyprowski .ops = &lp3971_dcdc_ops, 3290cbdf7bcSMarek Szyprowski .n_voltages = ARRAY_SIZE(buck_voltage_map), 3300cbdf7bcSMarek Szyprowski .type = REGULATOR_VOLTAGE, 3310cbdf7bcSMarek Szyprowski .owner = THIS_MODULE, 3320cbdf7bcSMarek Szyprowski }, 3330cbdf7bcSMarek Szyprowski { 3340cbdf7bcSMarek Szyprowski .name = "DCDC2", 3350cbdf7bcSMarek Szyprowski .id = LP3971_DCDC2, 3360cbdf7bcSMarek Szyprowski .ops = &lp3971_dcdc_ops, 3370cbdf7bcSMarek Szyprowski .n_voltages = ARRAY_SIZE(buck_voltage_map), 3380cbdf7bcSMarek Szyprowski .type = REGULATOR_VOLTAGE, 3390cbdf7bcSMarek Szyprowski .owner = THIS_MODULE, 3400cbdf7bcSMarek Szyprowski }, 3410cbdf7bcSMarek Szyprowski { 3420cbdf7bcSMarek Szyprowski .name = "DCDC3", 3430cbdf7bcSMarek Szyprowski .id = LP3971_DCDC3, 3440cbdf7bcSMarek Szyprowski .ops = &lp3971_dcdc_ops, 3450cbdf7bcSMarek Szyprowski .n_voltages = ARRAY_SIZE(buck_voltage_map), 3460cbdf7bcSMarek Szyprowski .type = REGULATOR_VOLTAGE, 3470cbdf7bcSMarek Szyprowski .owner = THIS_MODULE, 3480cbdf7bcSMarek Szyprowski }, 3490cbdf7bcSMarek Szyprowski }; 3500cbdf7bcSMarek Szyprowski 3510cbdf7bcSMarek Szyprowski static int lp3971_i2c_read(struct i2c_client *i2c, char reg, int count, 3520cbdf7bcSMarek Szyprowski u16 *dest) 3530cbdf7bcSMarek Szyprowski { 3540cbdf7bcSMarek Szyprowski int ret; 3550cbdf7bcSMarek Szyprowski 3560cbdf7bcSMarek Szyprowski if (count != 1) 3570cbdf7bcSMarek Szyprowski return -EIO; 3580cbdf7bcSMarek Szyprowski ret = i2c_smbus_read_byte_data(i2c, reg); 35927ef7f00SAxel Lin if (ret < 0) 3600cbdf7bcSMarek Szyprowski return -EIO; 3610cbdf7bcSMarek Szyprowski 3620cbdf7bcSMarek Szyprowski *dest = ret; 3630cbdf7bcSMarek Szyprowski return 0; 3640cbdf7bcSMarek Szyprowski } 3650cbdf7bcSMarek Szyprowski 3660cbdf7bcSMarek Szyprowski static int lp3971_i2c_write(struct i2c_client *i2c, char reg, int count, 3670cbdf7bcSMarek Szyprowski const u16 *src) 3680cbdf7bcSMarek Szyprowski { 3690cbdf7bcSMarek Szyprowski if (count != 1) 3700cbdf7bcSMarek Szyprowski return -EIO; 3711bddc2f5SAxel Lin return i2c_smbus_write_byte_data(i2c, reg, *src); 3720cbdf7bcSMarek Szyprowski } 3730cbdf7bcSMarek Szyprowski 3740cbdf7bcSMarek Szyprowski static u8 lp3971_reg_read(struct lp3971 *lp3971, u8 reg) 3750cbdf7bcSMarek Szyprowski { 3760cbdf7bcSMarek Szyprowski u16 val = 0; 3770cbdf7bcSMarek Szyprowski 3780cbdf7bcSMarek Szyprowski mutex_lock(&lp3971->io_lock); 3790cbdf7bcSMarek Szyprowski 3800cbdf7bcSMarek Szyprowski lp3971_i2c_read(lp3971->i2c, reg, 1, &val); 3810cbdf7bcSMarek Szyprowski 3820cbdf7bcSMarek Szyprowski dev_dbg(lp3971->dev, "reg read 0x%02x -> 0x%02x\n", (int)reg, 3830cbdf7bcSMarek Szyprowski (unsigned)val&0xff); 3840cbdf7bcSMarek Szyprowski 3850cbdf7bcSMarek Szyprowski mutex_unlock(&lp3971->io_lock); 3860cbdf7bcSMarek Szyprowski 3870cbdf7bcSMarek Szyprowski return val & 0xff; 3880cbdf7bcSMarek Szyprowski } 3890cbdf7bcSMarek Szyprowski 3900cbdf7bcSMarek Szyprowski static int lp3971_set_bits(struct lp3971 *lp3971, u8 reg, u16 mask, u16 val) 3910cbdf7bcSMarek Szyprowski { 3920cbdf7bcSMarek Szyprowski u16 tmp; 3930cbdf7bcSMarek Szyprowski int ret; 3940cbdf7bcSMarek Szyprowski 3950cbdf7bcSMarek Szyprowski mutex_lock(&lp3971->io_lock); 3960cbdf7bcSMarek Szyprowski 3970cbdf7bcSMarek Szyprowski ret = lp3971_i2c_read(lp3971->i2c, reg, 1, &tmp); 3980cbdf7bcSMarek Szyprowski tmp = (tmp & ~mask) | val; 3990cbdf7bcSMarek Szyprowski if (ret == 0) { 4000cbdf7bcSMarek Szyprowski ret = lp3971_i2c_write(lp3971->i2c, reg, 1, &tmp); 4010cbdf7bcSMarek Szyprowski dev_dbg(lp3971->dev, "reg write 0x%02x -> 0x%02x\n", (int)reg, 4020cbdf7bcSMarek Szyprowski (unsigned)val&0xff); 4030cbdf7bcSMarek Szyprowski } 4040cbdf7bcSMarek Szyprowski mutex_unlock(&lp3971->io_lock); 4050cbdf7bcSMarek Szyprowski 4060cbdf7bcSMarek Szyprowski return ret; 4070cbdf7bcSMarek Szyprowski } 4080cbdf7bcSMarek Szyprowski 409ebbed04fSDmitry Torokhov static int __devinit setup_regulators(struct lp3971 *lp3971, 4100cbdf7bcSMarek Szyprowski struct lp3971_platform_data *pdata) 4110cbdf7bcSMarek Szyprowski { 4120cbdf7bcSMarek Szyprowski int i, err; 413ebbed04fSDmitry Torokhov 414ebbed04fSDmitry Torokhov lp3971->num_regulators = pdata->num_regulators; 415ebbed04fSDmitry Torokhov lp3971->rdev = kcalloc(pdata->num_regulators, 416ebbed04fSDmitry Torokhov sizeof(struct regulator_dev *), GFP_KERNEL); 41767e46f34SDan Carpenter if (!lp3971->rdev) { 41867e46f34SDan Carpenter err = -ENOMEM; 41967e46f34SDan Carpenter goto err_nomem; 42067e46f34SDan Carpenter } 4210cbdf7bcSMarek Szyprowski 4220cbdf7bcSMarek Szyprowski /* Instantiate the regulators */ 423ebbed04fSDmitry Torokhov for (i = 0; i < pdata->num_regulators; i++) { 424ebbed04fSDmitry Torokhov struct lp3971_regulator_subdev *reg = &pdata->regulators[i]; 425ebbed04fSDmitry Torokhov lp3971->rdev[i] = regulator_register(®ulators[reg->id], 4262c043bcbSRajendra Nayak lp3971->dev, reg->initdata, lp3971, NULL); 4270cbdf7bcSMarek Szyprowski 428d662fc82SJulia Lawall if (IS_ERR(lp3971->rdev[i])) { 429d662fc82SJulia Lawall err = PTR_ERR(lp3971->rdev[i]); 4300cbdf7bcSMarek Szyprowski dev_err(lp3971->dev, "regulator init failed: %d\n", 4310cbdf7bcSMarek Szyprowski err); 4320cbdf7bcSMarek Szyprowski goto error; 4330cbdf7bcSMarek Szyprowski } 4340cbdf7bcSMarek Szyprowski } 4350cbdf7bcSMarek Szyprowski 4360cbdf7bcSMarek Szyprowski return 0; 437ebbed04fSDmitry Torokhov 4380cbdf7bcSMarek Szyprowski error: 439ebbed04fSDmitry Torokhov while (--i >= 0) 4400cbdf7bcSMarek Szyprowski regulator_unregister(lp3971->rdev[i]); 4410cbdf7bcSMarek Szyprowski kfree(lp3971->rdev); 4420cbdf7bcSMarek Szyprowski lp3971->rdev = NULL; 44367e46f34SDan Carpenter err_nomem: 4440cbdf7bcSMarek Szyprowski return err; 4450cbdf7bcSMarek Szyprowski } 4460cbdf7bcSMarek Szyprowski 4470cbdf7bcSMarek Szyprowski static int __devinit lp3971_i2c_probe(struct i2c_client *i2c, 4480cbdf7bcSMarek Szyprowski const struct i2c_device_id *id) 4490cbdf7bcSMarek Szyprowski { 4500cbdf7bcSMarek Szyprowski struct lp3971 *lp3971; 4510cbdf7bcSMarek Szyprowski struct lp3971_platform_data *pdata = i2c->dev.platform_data; 4520cbdf7bcSMarek Szyprowski int ret; 4530cbdf7bcSMarek Szyprowski u16 val; 4540cbdf7bcSMarek Szyprowski 455ebbed04fSDmitry Torokhov if (!pdata) { 456ebbed04fSDmitry Torokhov dev_dbg(&i2c->dev, "No platform init data supplied\n"); 457ebbed04fSDmitry Torokhov return -ENODEV; 4580cbdf7bcSMarek Szyprowski } 4590cbdf7bcSMarek Szyprowski 460ebbed04fSDmitry Torokhov lp3971 = kzalloc(sizeof(struct lp3971), GFP_KERNEL); 461ebbed04fSDmitry Torokhov if (lp3971 == NULL) 462ebbed04fSDmitry Torokhov return -ENOMEM; 463ebbed04fSDmitry Torokhov 4640cbdf7bcSMarek Szyprowski lp3971->i2c = i2c; 4650cbdf7bcSMarek Szyprowski lp3971->dev = &i2c->dev; 4660cbdf7bcSMarek Szyprowski 4670cbdf7bcSMarek Szyprowski mutex_init(&lp3971->io_lock); 4680cbdf7bcSMarek Szyprowski 4690cbdf7bcSMarek Szyprowski /* Detect LP3971 */ 4700cbdf7bcSMarek Szyprowski ret = lp3971_i2c_read(i2c, LP3971_SYS_CONTROL1_REG, 1, &val); 4710cbdf7bcSMarek Szyprowski if (ret == 0 && (val & SYS_CONTROL1_INIT_MASK) != SYS_CONTROL1_INIT_VAL) 4720cbdf7bcSMarek Szyprowski ret = -ENODEV; 4730cbdf7bcSMarek Szyprowski if (ret < 0) { 4740cbdf7bcSMarek Szyprowski dev_err(&i2c->dev, "failed to detect device\n"); 4750cbdf7bcSMarek Szyprowski goto err_detect; 4760cbdf7bcSMarek Szyprowski } 4770cbdf7bcSMarek Szyprowski 4780cbdf7bcSMarek Szyprowski ret = setup_regulators(lp3971, pdata); 4790cbdf7bcSMarek Szyprowski if (ret < 0) 4800cbdf7bcSMarek Szyprowski goto err_detect; 4810cbdf7bcSMarek Szyprowski 482ebbed04fSDmitry Torokhov i2c_set_clientdata(i2c, lp3971); 4830cbdf7bcSMarek Szyprowski return 0; 4840cbdf7bcSMarek Szyprowski 4850cbdf7bcSMarek Szyprowski err_detect: 4860cbdf7bcSMarek Szyprowski kfree(lp3971); 4870cbdf7bcSMarek Szyprowski return ret; 4880cbdf7bcSMarek Szyprowski } 4890cbdf7bcSMarek Szyprowski 4900cbdf7bcSMarek Szyprowski static int __devexit lp3971_i2c_remove(struct i2c_client *i2c) 4910cbdf7bcSMarek Szyprowski { 4920cbdf7bcSMarek Szyprowski struct lp3971 *lp3971 = i2c_get_clientdata(i2c); 4930cbdf7bcSMarek Szyprowski int i; 494ebbed04fSDmitry Torokhov 495ebbed04fSDmitry Torokhov for (i = 0; i < lp3971->num_regulators; i++) 496ebbed04fSDmitry Torokhov regulator_unregister(lp3971->rdev[i]); 497ebbed04fSDmitry Torokhov 498ebbed04fSDmitry Torokhov kfree(lp3971->rdev); 4990cbdf7bcSMarek Szyprowski kfree(lp3971); 5000cbdf7bcSMarek Szyprowski 5010cbdf7bcSMarek Szyprowski return 0; 5020cbdf7bcSMarek Szyprowski } 5030cbdf7bcSMarek Szyprowski 5040cbdf7bcSMarek Szyprowski static const struct i2c_device_id lp3971_i2c_id[] = { 5050cbdf7bcSMarek Szyprowski { "lp3971", 0 }, 5060cbdf7bcSMarek Szyprowski { } 5070cbdf7bcSMarek Szyprowski }; 5080cbdf7bcSMarek Szyprowski MODULE_DEVICE_TABLE(i2c, lp3971_i2c_id); 5090cbdf7bcSMarek Szyprowski 5100cbdf7bcSMarek Szyprowski static struct i2c_driver lp3971_i2c_driver = { 5110cbdf7bcSMarek Szyprowski .driver = { 5120cbdf7bcSMarek Szyprowski .name = "LP3971", 5130cbdf7bcSMarek Szyprowski .owner = THIS_MODULE, 5140cbdf7bcSMarek Szyprowski }, 5150cbdf7bcSMarek Szyprowski .probe = lp3971_i2c_probe, 5166113c3a5SLiam Girdwood .remove = __devexit_p(lp3971_i2c_remove), 5170cbdf7bcSMarek Szyprowski .id_table = lp3971_i2c_id, 5180cbdf7bcSMarek Szyprowski }; 5190cbdf7bcSMarek Szyprowski 5200cbdf7bcSMarek Szyprowski static int __init lp3971_module_init(void) 5210cbdf7bcSMarek Szyprowski { 52212a1d933SWolfram Sang int ret; 5230cbdf7bcSMarek Szyprowski 5240cbdf7bcSMarek Szyprowski ret = i2c_add_driver(&lp3971_i2c_driver); 5250cbdf7bcSMarek Szyprowski if (ret != 0) 5260cbdf7bcSMarek Szyprowski pr_err("Failed to register I2C driver: %d\n", ret); 5270cbdf7bcSMarek Szyprowski 5280cbdf7bcSMarek Szyprowski return ret; 5290cbdf7bcSMarek Szyprowski } 5300cbdf7bcSMarek Szyprowski module_init(lp3971_module_init); 5310cbdf7bcSMarek Szyprowski 5320cbdf7bcSMarek Szyprowski static void __exit lp3971_module_exit(void) 5330cbdf7bcSMarek Szyprowski { 5340cbdf7bcSMarek Szyprowski i2c_del_driver(&lp3971_i2c_driver); 5350cbdf7bcSMarek Szyprowski } 5360cbdf7bcSMarek Szyprowski module_exit(lp3971_module_exit); 5370cbdf7bcSMarek Szyprowski 5380cbdf7bcSMarek Szyprowski MODULE_LICENSE("GPL"); 5390cbdf7bcSMarek Szyprowski MODULE_AUTHOR("Marek Szyprowski <m.szyprowski@samsung.com>"); 5400cbdf7bcSMarek Szyprowski MODULE_DESCRIPTION("LP3971 PMIC driver"); 541