1b59320ccSDaniel Jeong /* 2b59320ccSDaniel Jeong * LP8755 High Performance Power Management Unit : System Interface Driver 3b59320ccSDaniel Jeong * (based on rev. 0.26) 4b59320ccSDaniel Jeong * Copyright 2012 Texas Instruments 5b59320ccSDaniel Jeong * 6b59320ccSDaniel Jeong * Author: Daniel(Geon Si) Jeong <daniel.jeong@ti.com> 7b59320ccSDaniel Jeong * 8b59320ccSDaniel Jeong * This program is free software; you can redistribute it and/or modify 9b59320ccSDaniel Jeong * it under the terms of the GNU General Public License version 2 as 10b59320ccSDaniel Jeong * published by the Free Software Foundation. 11b59320ccSDaniel Jeong * 12b59320ccSDaniel Jeong */ 13b59320ccSDaniel Jeong 14b59320ccSDaniel Jeong #include <linux/module.h> 15b59320ccSDaniel Jeong #include <linux/slab.h> 16b59320ccSDaniel Jeong #include <linux/i2c.h> 17b59320ccSDaniel Jeong #include <linux/err.h> 18b59320ccSDaniel Jeong #include <linux/irq.h> 19b59320ccSDaniel Jeong #include <linux/interrupt.h> 20b59320ccSDaniel Jeong #include <linux/gpio.h> 21b59320ccSDaniel Jeong #include <linux/regmap.h> 22b59320ccSDaniel Jeong #include <linux/uaccess.h> 23b59320ccSDaniel Jeong #include <linux/regulator/driver.h> 24b59320ccSDaniel Jeong #include <linux/regulator/machine.h> 25b59320ccSDaniel Jeong #include <linux/platform_data/lp8755.h> 26b59320ccSDaniel Jeong 27b59320ccSDaniel Jeong #define LP8755_REG_BUCK0 0x00 28b59320ccSDaniel Jeong #define LP8755_REG_BUCK1 0x03 29b59320ccSDaniel Jeong #define LP8755_REG_BUCK2 0x04 30b59320ccSDaniel Jeong #define LP8755_REG_BUCK3 0x01 31b59320ccSDaniel Jeong #define LP8755_REG_BUCK4 0x05 32b59320ccSDaniel Jeong #define LP8755_REG_BUCK5 0x02 33b59320ccSDaniel Jeong #define LP8755_REG_MAX 0xFF 34b59320ccSDaniel Jeong 35b59320ccSDaniel Jeong #define LP8755_BUCK_EN_M BIT(7) 36b59320ccSDaniel Jeong #define LP8755_BUCK_LINEAR_OUT_MAX 0x76 37b59320ccSDaniel Jeong #define LP8755_BUCK_VOUT_M 0x7F 38b59320ccSDaniel Jeong 39b59320ccSDaniel Jeong struct lp8755_mphase { 40b59320ccSDaniel Jeong int nreg; 41b59320ccSDaniel Jeong int buck_num[LP8755_BUCK_MAX]; 42b59320ccSDaniel Jeong }; 43b59320ccSDaniel Jeong 44b59320ccSDaniel Jeong struct lp8755_chip { 45b59320ccSDaniel Jeong struct device *dev; 46b59320ccSDaniel Jeong struct regmap *regmap; 47b59320ccSDaniel Jeong struct lp8755_platform_data *pdata; 48b59320ccSDaniel Jeong 49b59320ccSDaniel Jeong int irq; 50b59320ccSDaniel Jeong unsigned int irqmask; 51b59320ccSDaniel Jeong 52b59320ccSDaniel Jeong int mphase; 53b59320ccSDaniel Jeong struct regulator_dev *rdev[LP8755_BUCK_MAX]; 54b59320ccSDaniel Jeong }; 55b59320ccSDaniel Jeong 56b59320ccSDaniel Jeong /** 57b59320ccSDaniel Jeong *lp8755_read : read a single register value from lp8755. 58b59320ccSDaniel Jeong *@pchip : device to read from 59b59320ccSDaniel Jeong *@reg : register to read from 60b59320ccSDaniel Jeong *@val : pointer to store read value 61b59320ccSDaniel Jeong */ 62b59320ccSDaniel Jeong static int lp8755_read(struct lp8755_chip *pchip, unsigned int reg, 63b59320ccSDaniel Jeong unsigned int *val) 64b59320ccSDaniel Jeong { 65b59320ccSDaniel Jeong return regmap_read(pchip->regmap, reg, val); 66b59320ccSDaniel Jeong } 67b59320ccSDaniel Jeong 68b59320ccSDaniel Jeong /** 69b59320ccSDaniel Jeong *lp8755_write : write a single register value to lp8755. 70b59320ccSDaniel Jeong *@pchip : device to write to 71b59320ccSDaniel Jeong *@reg : register to write to 72b59320ccSDaniel Jeong *@val : value to be written 73b59320ccSDaniel Jeong */ 74b59320ccSDaniel Jeong static int lp8755_write(struct lp8755_chip *pchip, unsigned int reg, 75b59320ccSDaniel Jeong unsigned int val) 76b59320ccSDaniel Jeong { 77b59320ccSDaniel Jeong return regmap_write(pchip->regmap, reg, val); 78b59320ccSDaniel Jeong } 79b59320ccSDaniel Jeong 80b59320ccSDaniel Jeong /** 81b59320ccSDaniel Jeong *lp8755_update_bits : set the values of bit fields in lp8755 register. 82b59320ccSDaniel Jeong *@pchip : device to read from 83b59320ccSDaniel Jeong *@reg : register to update 84b59320ccSDaniel Jeong *@mask : bitmask to be changed 85b59320ccSDaniel Jeong *@val : value for bitmask 86b59320ccSDaniel Jeong */ 87b59320ccSDaniel Jeong static int lp8755_update_bits(struct lp8755_chip *pchip, unsigned int reg, 88b59320ccSDaniel Jeong unsigned int mask, unsigned int val) 89b59320ccSDaniel Jeong { 90b59320ccSDaniel Jeong return regmap_update_bits(pchip->regmap, reg, mask, val); 91b59320ccSDaniel Jeong } 92b59320ccSDaniel Jeong 93b59320ccSDaniel Jeong static int lp8755_buck_enable_time(struct regulator_dev *rdev) 94b59320ccSDaniel Jeong { 95b59320ccSDaniel Jeong int ret; 96b59320ccSDaniel Jeong unsigned int regval; 97b59320ccSDaniel Jeong enum lp8755_bucks id = rdev_get_id(rdev); 98b59320ccSDaniel Jeong struct lp8755_chip *pchip = rdev_get_drvdata(rdev); 99b59320ccSDaniel Jeong 100b59320ccSDaniel Jeong ret = lp8755_read(pchip, 0x12 + id, ®val); 101b59320ccSDaniel Jeong if (ret < 0) { 10280aec6f5SColin Ian King dev_err(pchip->dev, "i2c access error %s\n", __func__); 103b59320ccSDaniel Jeong return ret; 104b59320ccSDaniel Jeong } 105b59320ccSDaniel Jeong return (regval & 0xff) * 100; 106b59320ccSDaniel Jeong } 107b59320ccSDaniel Jeong 108b59320ccSDaniel Jeong static int lp8755_buck_set_mode(struct regulator_dev *rdev, unsigned int mode) 109b59320ccSDaniel Jeong { 110b59320ccSDaniel Jeong int ret; 111b59320ccSDaniel Jeong unsigned int regbval = 0x0; 112b59320ccSDaniel Jeong enum lp8755_bucks id = rdev_get_id(rdev); 113b59320ccSDaniel Jeong struct lp8755_chip *pchip = rdev_get_drvdata(rdev); 114b59320ccSDaniel Jeong 115b59320ccSDaniel Jeong switch (mode) { 116b59320ccSDaniel Jeong case REGULATOR_MODE_FAST: 117b59320ccSDaniel Jeong /* forced pwm mode */ 118b59320ccSDaniel Jeong regbval = (0x01 << id); 119b59320ccSDaniel Jeong break; 120b59320ccSDaniel Jeong case REGULATOR_MODE_NORMAL: 121b59320ccSDaniel Jeong /* enable automatic pwm/pfm mode */ 122b59320ccSDaniel Jeong ret = lp8755_update_bits(pchip, 0x08 + id, 0x20, 0x00); 123b59320ccSDaniel Jeong if (ret < 0) 124b59320ccSDaniel Jeong goto err_i2c; 125b59320ccSDaniel Jeong break; 126b59320ccSDaniel Jeong case REGULATOR_MODE_IDLE: 127b59320ccSDaniel Jeong /* enable automatic pwm/pfm/lppfm mode */ 128b59320ccSDaniel Jeong ret = lp8755_update_bits(pchip, 0x08 + id, 0x20, 0x20); 129b59320ccSDaniel Jeong if (ret < 0) 130b59320ccSDaniel Jeong goto err_i2c; 131b59320ccSDaniel Jeong 132b59320ccSDaniel Jeong ret = lp8755_update_bits(pchip, 0x10, 0x01, 0x01); 133b59320ccSDaniel Jeong if (ret < 0) 134b59320ccSDaniel Jeong goto err_i2c; 135b59320ccSDaniel Jeong break; 136b59320ccSDaniel Jeong default: 137b59320ccSDaniel Jeong dev_err(pchip->dev, "Not supported buck mode %s\n", __func__); 138b59320ccSDaniel Jeong /* forced pwm mode */ 139b59320ccSDaniel Jeong regbval = (0x01 << id); 140b59320ccSDaniel Jeong } 141b59320ccSDaniel Jeong 142b59320ccSDaniel Jeong ret = lp8755_update_bits(pchip, 0x06, 0x01 << id, regbval); 143b59320ccSDaniel Jeong if (ret < 0) 144b59320ccSDaniel Jeong goto err_i2c; 145b59320ccSDaniel Jeong return ret; 146b59320ccSDaniel Jeong err_i2c: 14780aec6f5SColin Ian King dev_err(pchip->dev, "i2c access error %s\n", __func__); 148b59320ccSDaniel Jeong return ret; 149b59320ccSDaniel Jeong } 150b59320ccSDaniel Jeong 151b59320ccSDaniel Jeong static unsigned int lp8755_buck_get_mode(struct regulator_dev *rdev) 152b59320ccSDaniel Jeong { 153b59320ccSDaniel Jeong int ret; 154b59320ccSDaniel Jeong unsigned int regval; 155b59320ccSDaniel Jeong enum lp8755_bucks id = rdev_get_id(rdev); 156b59320ccSDaniel Jeong struct lp8755_chip *pchip = rdev_get_drvdata(rdev); 157b59320ccSDaniel Jeong 158b59320ccSDaniel Jeong ret = lp8755_read(pchip, 0x06, ®val); 159b59320ccSDaniel Jeong if (ret < 0) 160b59320ccSDaniel Jeong goto err_i2c; 161b59320ccSDaniel Jeong 162b59320ccSDaniel Jeong /* mode fast means forced pwm mode */ 163b59320ccSDaniel Jeong if (regval & (0x01 << id)) 164b59320ccSDaniel Jeong return REGULATOR_MODE_FAST; 165b59320ccSDaniel Jeong 166b59320ccSDaniel Jeong ret = lp8755_read(pchip, 0x08 + id, ®val); 167b59320ccSDaniel Jeong if (ret < 0) 168b59320ccSDaniel Jeong goto err_i2c; 169b59320ccSDaniel Jeong 170b59320ccSDaniel Jeong /* mode idle means automatic pwm/pfm/lppfm mode */ 171b59320ccSDaniel Jeong if (regval & 0x20) 172b59320ccSDaniel Jeong return REGULATOR_MODE_IDLE; 173b59320ccSDaniel Jeong 174b59320ccSDaniel Jeong /* mode normal means automatic pwm/pfm mode */ 175b59320ccSDaniel Jeong return REGULATOR_MODE_NORMAL; 176b59320ccSDaniel Jeong 177b59320ccSDaniel Jeong err_i2c: 17880aec6f5SColin Ian King dev_err(pchip->dev, "i2c access error %s\n", __func__); 179b59320ccSDaniel Jeong return 0; 180b59320ccSDaniel Jeong } 181b59320ccSDaniel Jeong 182b59320ccSDaniel Jeong static int lp8755_buck_set_ramp(struct regulator_dev *rdev, int ramp) 183b59320ccSDaniel Jeong { 184b59320ccSDaniel Jeong int ret; 185b59320ccSDaniel Jeong unsigned int regval = 0x00; 186b59320ccSDaniel Jeong enum lp8755_bucks id = rdev_get_id(rdev); 187b59320ccSDaniel Jeong struct lp8755_chip *pchip = rdev_get_drvdata(rdev); 188b59320ccSDaniel Jeong 189b59320ccSDaniel Jeong /* uV/us */ 190b59320ccSDaniel Jeong switch (ramp) { 191b59320ccSDaniel Jeong case 0 ... 230: 192b59320ccSDaniel Jeong regval = 0x07; 193b59320ccSDaniel Jeong break; 194b59320ccSDaniel Jeong case 231 ... 470: 195b59320ccSDaniel Jeong regval = 0x06; 196b59320ccSDaniel Jeong break; 197b59320ccSDaniel Jeong case 471 ... 940: 198b59320ccSDaniel Jeong regval = 0x05; 199b59320ccSDaniel Jeong break; 200b59320ccSDaniel Jeong case 941 ... 1900: 201b59320ccSDaniel Jeong regval = 0x04; 202b59320ccSDaniel Jeong break; 203b59320ccSDaniel Jeong case 1901 ... 3800: 204b59320ccSDaniel Jeong regval = 0x03; 205b59320ccSDaniel Jeong break; 206b59320ccSDaniel Jeong case 3801 ... 7500: 207b59320ccSDaniel Jeong regval = 0x02; 208b59320ccSDaniel Jeong break; 209b59320ccSDaniel Jeong case 7501 ... 15000: 210b59320ccSDaniel Jeong regval = 0x01; 211b59320ccSDaniel Jeong break; 212b59320ccSDaniel Jeong case 15001 ... 30000: 213b59320ccSDaniel Jeong regval = 0x00; 214b59320ccSDaniel Jeong break; 215b59320ccSDaniel Jeong default: 216b59320ccSDaniel Jeong dev_err(pchip->dev, 217b59320ccSDaniel Jeong "Not supported ramp value %d %s\n", ramp, __func__); 218b59320ccSDaniel Jeong return -EINVAL; 219b59320ccSDaniel Jeong } 220b59320ccSDaniel Jeong 221b59320ccSDaniel Jeong ret = lp8755_update_bits(pchip, 0x07 + id, 0x07, regval); 222b59320ccSDaniel Jeong if (ret < 0) 223b59320ccSDaniel Jeong goto err_i2c; 224b59320ccSDaniel Jeong return ret; 225b59320ccSDaniel Jeong err_i2c: 22680aec6f5SColin Ian King dev_err(pchip->dev, "i2c access error %s\n", __func__); 227b59320ccSDaniel Jeong return ret; 228b59320ccSDaniel Jeong } 229b59320ccSDaniel Jeong 230d42797a4SBhumika Goyal static const struct regulator_ops lp8755_buck_ops = { 23156a942e9SMark Brown .map_voltage = regulator_map_voltage_linear, 232b59320ccSDaniel Jeong .list_voltage = regulator_list_voltage_linear, 233b59320ccSDaniel Jeong .set_voltage_sel = regulator_set_voltage_sel_regmap, 234b59320ccSDaniel Jeong .get_voltage_sel = regulator_get_voltage_sel_regmap, 235b59320ccSDaniel Jeong .enable = regulator_enable_regmap, 236b59320ccSDaniel Jeong .disable = regulator_disable_regmap, 237b59320ccSDaniel Jeong .is_enabled = regulator_is_enabled_regmap, 238b59320ccSDaniel Jeong .enable_time = lp8755_buck_enable_time, 239b59320ccSDaniel Jeong .set_mode = lp8755_buck_set_mode, 240b59320ccSDaniel Jeong .get_mode = lp8755_buck_get_mode, 241b59320ccSDaniel Jeong .set_ramp_delay = lp8755_buck_set_ramp, 242b59320ccSDaniel Jeong }; 243b59320ccSDaniel Jeong 244b59320ccSDaniel Jeong #define lp8755_rail(_id) "lp8755_buck"#_id 245b59320ccSDaniel Jeong #define lp8755_buck_init(_id)\ 246b59320ccSDaniel Jeong {\ 247b59320ccSDaniel Jeong .constraints = {\ 248b59320ccSDaniel Jeong .name = lp8755_rail(_id),\ 249b59320ccSDaniel Jeong .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,\ 250b59320ccSDaniel Jeong .min_uV = 500000,\ 251b59320ccSDaniel Jeong .max_uV = 1675000,\ 252b59320ccSDaniel Jeong },\ 253b59320ccSDaniel Jeong } 254b59320ccSDaniel Jeong 255b59320ccSDaniel Jeong static struct regulator_init_data lp8755_reg_default[LP8755_BUCK_MAX] = { 256510799eaSAxel Lin [LP8755_BUCK0] = lp8755_buck_init(0), 257510799eaSAxel Lin [LP8755_BUCK1] = lp8755_buck_init(1), 258510799eaSAxel Lin [LP8755_BUCK2] = lp8755_buck_init(2), 259510799eaSAxel Lin [LP8755_BUCK3] = lp8755_buck_init(3), 260510799eaSAxel Lin [LP8755_BUCK4] = lp8755_buck_init(4), 261510799eaSAxel Lin [LP8755_BUCK5] = lp8755_buck_init(5), 262b59320ccSDaniel Jeong }; 263b59320ccSDaniel Jeong 264b59320ccSDaniel Jeong static const struct lp8755_mphase mphase_buck[MPHASE_CONF_MAX] = { 265510799eaSAxel Lin { 3, { LP8755_BUCK0, LP8755_BUCK3, LP8755_BUCK5 } }, 266510799eaSAxel Lin { 6, { LP8755_BUCK0, LP8755_BUCK1, LP8755_BUCK2, LP8755_BUCK3, 267510799eaSAxel Lin LP8755_BUCK4, LP8755_BUCK5 } }, 268510799eaSAxel Lin { 5, { LP8755_BUCK0, LP8755_BUCK2, LP8755_BUCK3, LP8755_BUCK4, 269510799eaSAxel Lin LP8755_BUCK5} }, 270510799eaSAxel Lin { 4, { LP8755_BUCK0, LP8755_BUCK3, LP8755_BUCK4, LP8755_BUCK5} }, 271510799eaSAxel Lin { 3, { LP8755_BUCK0, LP8755_BUCK4, LP8755_BUCK5} }, 272510799eaSAxel Lin { 2, { LP8755_BUCK0, LP8755_BUCK5} }, 273510799eaSAxel Lin { 1, { LP8755_BUCK0} }, 274510799eaSAxel Lin { 2, { LP8755_BUCK0, LP8755_BUCK3} }, 275510799eaSAxel Lin { 4, { LP8755_BUCK0, LP8755_BUCK2, LP8755_BUCK3, LP8755_BUCK5} }, 276b59320ccSDaniel Jeong }; 277b59320ccSDaniel Jeong 278b59320ccSDaniel Jeong static int lp8755_init_data(struct lp8755_chip *pchip) 279b59320ccSDaniel Jeong { 280b59320ccSDaniel Jeong unsigned int regval; 281b59320ccSDaniel Jeong int ret, icnt, buck_num; 282b59320ccSDaniel Jeong struct lp8755_platform_data *pdata = pchip->pdata; 283b59320ccSDaniel Jeong 284b59320ccSDaniel Jeong /* read back muti-phase configuration */ 285b59320ccSDaniel Jeong ret = lp8755_read(pchip, 0x3D, ®val); 286b59320ccSDaniel Jeong if (ret < 0) 287b59320ccSDaniel Jeong goto out_i2c_error; 288cad877efSAxel Lin pchip->mphase = regval & 0x0F; 289b59320ccSDaniel Jeong 290b59320ccSDaniel Jeong /* set default data based on multi-phase config */ 291b59320ccSDaniel Jeong for (icnt = 0; icnt < mphase_buck[pchip->mphase].nreg; icnt++) { 292b59320ccSDaniel Jeong buck_num = mphase_buck[pchip->mphase].buck_num[icnt]; 293b59320ccSDaniel Jeong pdata->buck_data[buck_num] = &lp8755_reg_default[buck_num]; 294b59320ccSDaniel Jeong } 295b59320ccSDaniel Jeong return ret; 296b59320ccSDaniel Jeong 297b59320ccSDaniel Jeong out_i2c_error: 29880aec6f5SColin Ian King dev_err(pchip->dev, "i2c access error %s\n", __func__); 299b59320ccSDaniel Jeong return ret; 300b59320ccSDaniel Jeong } 301b59320ccSDaniel Jeong 302b59320ccSDaniel Jeong #define lp8755_buck_desc(_id)\ 303b59320ccSDaniel Jeong {\ 304b59320ccSDaniel Jeong .name = lp8755_rail(_id),\ 305b59320ccSDaniel Jeong .id = LP8755_BUCK##_id,\ 306b59320ccSDaniel Jeong .ops = &lp8755_buck_ops,\ 307b59320ccSDaniel Jeong .n_voltages = LP8755_BUCK_LINEAR_OUT_MAX+1,\ 308b59320ccSDaniel Jeong .uV_step = 10000,\ 309b59320ccSDaniel Jeong .min_uV = 500000,\ 310b59320ccSDaniel Jeong .type = REGULATOR_VOLTAGE,\ 311b59320ccSDaniel Jeong .owner = THIS_MODULE,\ 312b59320ccSDaniel Jeong .enable_reg = LP8755_REG_BUCK##_id,\ 313b59320ccSDaniel Jeong .enable_mask = LP8755_BUCK_EN_M,\ 314b59320ccSDaniel Jeong .vsel_reg = LP8755_REG_BUCK##_id,\ 315b59320ccSDaniel Jeong .vsel_mask = LP8755_BUCK_VOUT_M,\ 316b59320ccSDaniel Jeong } 317b59320ccSDaniel Jeong 318b59320ccSDaniel Jeong static struct regulator_desc lp8755_regulators[] = { 319b59320ccSDaniel Jeong lp8755_buck_desc(0), 320b59320ccSDaniel Jeong lp8755_buck_desc(1), 321b59320ccSDaniel Jeong lp8755_buck_desc(2), 322b59320ccSDaniel Jeong lp8755_buck_desc(3), 323b59320ccSDaniel Jeong lp8755_buck_desc(4), 324b59320ccSDaniel Jeong lp8755_buck_desc(5), 325b59320ccSDaniel Jeong }; 326b59320ccSDaniel Jeong 327b59320ccSDaniel Jeong static int lp8755_regulator_init(struct lp8755_chip *pchip) 328b59320ccSDaniel Jeong { 329b59320ccSDaniel Jeong int ret, icnt, buck_num; 330b59320ccSDaniel Jeong struct lp8755_platform_data *pdata = pchip->pdata; 331b59320ccSDaniel Jeong struct regulator_config rconfig = { }; 332b59320ccSDaniel Jeong 333b59320ccSDaniel Jeong rconfig.regmap = pchip->regmap; 334b59320ccSDaniel Jeong rconfig.dev = pchip->dev; 335b59320ccSDaniel Jeong rconfig.driver_data = pchip; 336b59320ccSDaniel Jeong 337b59320ccSDaniel Jeong for (icnt = 0; icnt < mphase_buck[pchip->mphase].nreg; icnt++) { 338b59320ccSDaniel Jeong buck_num = mphase_buck[pchip->mphase].buck_num[icnt]; 339b59320ccSDaniel Jeong rconfig.init_data = pdata->buck_data[buck_num]; 340b59320ccSDaniel Jeong rconfig.of_node = pchip->dev->of_node; 341b59320ccSDaniel Jeong pchip->rdev[buck_num] = 34257135250SHimangi Saraogi devm_regulator_register(pchip->dev, 34357135250SHimangi Saraogi &lp8755_regulators[buck_num], &rconfig); 344b59320ccSDaniel Jeong if (IS_ERR(pchip->rdev[buck_num])) { 345b59320ccSDaniel Jeong ret = PTR_ERR(pchip->rdev[buck_num]); 346a1a41ab4SAxel Lin pchip->rdev[buck_num] = NULL; 347a1a41ab4SAxel Lin dev_err(pchip->dev, "regulator init failed: buck %d\n", 348a1a41ab4SAxel Lin buck_num); 34957135250SHimangi Saraogi return ret; 350b59320ccSDaniel Jeong } 351b59320ccSDaniel Jeong } 352b59320ccSDaniel Jeong 353b59320ccSDaniel Jeong return 0; 354b59320ccSDaniel Jeong } 355b59320ccSDaniel Jeong 356b59320ccSDaniel Jeong static irqreturn_t lp8755_irq_handler(int irq, void *data) 357b59320ccSDaniel Jeong { 358b59320ccSDaniel Jeong int ret, icnt; 359b59320ccSDaniel Jeong unsigned int flag0, flag1; 360b59320ccSDaniel Jeong struct lp8755_chip *pchip = data; 361b59320ccSDaniel Jeong 362b59320ccSDaniel Jeong /* read flag0 register */ 363b59320ccSDaniel Jeong ret = lp8755_read(pchip, 0x0D, &flag0); 364b59320ccSDaniel Jeong if (ret < 0) 365b59320ccSDaniel Jeong goto err_i2c; 366b59320ccSDaniel Jeong /* clear flag register to pull up int. pin */ 367b59320ccSDaniel Jeong ret = lp8755_write(pchip, 0x0D, 0x00); 368b59320ccSDaniel Jeong if (ret < 0) 369b59320ccSDaniel Jeong goto err_i2c; 370b59320ccSDaniel Jeong 371b59320ccSDaniel Jeong /* sent power fault detection event to specific regulator */ 3721200c60bSAxel Lin for (icnt = 0; icnt < LP8755_BUCK_MAX; icnt++) 373b59320ccSDaniel Jeong if ((flag0 & (0x4 << icnt)) 374b59320ccSDaniel Jeong && (pchip->irqmask & (0x04 << icnt)) 375b59320ccSDaniel Jeong && (pchip->rdev[icnt] != NULL)) 376b59320ccSDaniel Jeong regulator_notifier_call_chain(pchip->rdev[icnt], 377b59320ccSDaniel Jeong LP8755_EVENT_PWR_FAULT, 378b59320ccSDaniel Jeong NULL); 379b59320ccSDaniel Jeong 380b59320ccSDaniel Jeong /* read flag1 register */ 381b59320ccSDaniel Jeong ret = lp8755_read(pchip, 0x0E, &flag1); 382b59320ccSDaniel Jeong if (ret < 0) 383b59320ccSDaniel Jeong goto err_i2c; 384b59320ccSDaniel Jeong /* clear flag register to pull up int. pin */ 385b59320ccSDaniel Jeong ret = lp8755_write(pchip, 0x0E, 0x00); 386b59320ccSDaniel Jeong if (ret < 0) 387b59320ccSDaniel Jeong goto err_i2c; 388b59320ccSDaniel Jeong 389b59320ccSDaniel Jeong /* send OCP event to all regualtor devices */ 390b59320ccSDaniel Jeong if ((flag1 & 0x01) && (pchip->irqmask & 0x01)) 391b59320ccSDaniel Jeong for (icnt = 0; icnt < LP8755_BUCK_MAX; icnt++) 392b59320ccSDaniel Jeong if (pchip->rdev[icnt] != NULL) 393b59320ccSDaniel Jeong regulator_notifier_call_chain(pchip->rdev[icnt], 394b59320ccSDaniel Jeong LP8755_EVENT_OCP, 395b59320ccSDaniel Jeong NULL); 396b59320ccSDaniel Jeong 397b59320ccSDaniel Jeong /* send OVP event to all regualtor devices */ 398b59320ccSDaniel Jeong if ((flag1 & 0x02) && (pchip->irqmask & 0x02)) 399b59320ccSDaniel Jeong for (icnt = 0; icnt < LP8755_BUCK_MAX; icnt++) 400b59320ccSDaniel Jeong if (pchip->rdev[icnt] != NULL) 401b59320ccSDaniel Jeong regulator_notifier_call_chain(pchip->rdev[icnt], 402b59320ccSDaniel Jeong LP8755_EVENT_OVP, 403b59320ccSDaniel Jeong NULL); 404b59320ccSDaniel Jeong return IRQ_HANDLED; 405b59320ccSDaniel Jeong 406b59320ccSDaniel Jeong err_i2c: 40780aec6f5SColin Ian King dev_err(pchip->dev, "i2c access error %s\n", __func__); 408b59320ccSDaniel Jeong return IRQ_NONE; 409b59320ccSDaniel Jeong } 410b59320ccSDaniel Jeong 411b59320ccSDaniel Jeong static int lp8755_int_config(struct lp8755_chip *pchip) 412b59320ccSDaniel Jeong { 413b59320ccSDaniel Jeong int ret; 414b59320ccSDaniel Jeong unsigned int regval; 415b59320ccSDaniel Jeong 416b59320ccSDaniel Jeong if (pchip->irq == 0) { 417b59320ccSDaniel Jeong dev_warn(pchip->dev, "not use interrupt : %s\n", __func__); 418b59320ccSDaniel Jeong return 0; 419b59320ccSDaniel Jeong } 420b59320ccSDaniel Jeong 421b59320ccSDaniel Jeong ret = lp8755_read(pchip, 0x0F, ®val); 422840499aaSAxel Lin if (ret < 0) { 42380aec6f5SColin Ian King dev_err(pchip->dev, "i2c access error %s\n", __func__); 424b59320ccSDaniel Jeong return ret; 425b59320ccSDaniel Jeong } 426b59320ccSDaniel Jeong 427840499aaSAxel Lin pchip->irqmask = regval; 428840499aaSAxel Lin return devm_request_threaded_irq(pchip->dev, pchip->irq, NULL, 429840499aaSAxel Lin lp8755_irq_handler, 430840499aaSAxel Lin IRQF_TRIGGER_FALLING | IRQF_ONESHOT, 431840499aaSAxel Lin "lp8755-irq", pchip); 432840499aaSAxel Lin } 433840499aaSAxel Lin 434b59320ccSDaniel Jeong static const struct regmap_config lp8755_regmap = { 435b59320ccSDaniel Jeong .reg_bits = 8, 436b59320ccSDaniel Jeong .val_bits = 8, 437b59320ccSDaniel Jeong .max_register = LP8755_REG_MAX, 438b59320ccSDaniel Jeong }; 439b59320ccSDaniel Jeong 440b59320ccSDaniel Jeong static int lp8755_probe(struct i2c_client *client, 441b59320ccSDaniel Jeong const struct i2c_device_id *id) 442b59320ccSDaniel Jeong { 443b59320ccSDaniel Jeong int ret, icnt; 444b59320ccSDaniel Jeong struct lp8755_chip *pchip; 445dff91d0bSJingoo Han struct lp8755_platform_data *pdata = dev_get_platdata(&client->dev); 446b59320ccSDaniel Jeong 447b59320ccSDaniel Jeong if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { 448b59320ccSDaniel Jeong dev_err(&client->dev, "i2c functionality check fail.\n"); 449b59320ccSDaniel Jeong return -EOPNOTSUPP; 450b59320ccSDaniel Jeong } 451b59320ccSDaniel Jeong 452b59320ccSDaniel Jeong pchip = devm_kzalloc(&client->dev, 453b59320ccSDaniel Jeong sizeof(struct lp8755_chip), GFP_KERNEL); 454b59320ccSDaniel Jeong if (!pchip) 455b59320ccSDaniel Jeong return -ENOMEM; 456b59320ccSDaniel Jeong 457b59320ccSDaniel Jeong pchip->dev = &client->dev; 458b59320ccSDaniel Jeong pchip->regmap = devm_regmap_init_i2c(client, &lp8755_regmap); 459b59320ccSDaniel Jeong if (IS_ERR(pchip->regmap)) { 460b59320ccSDaniel Jeong ret = PTR_ERR(pchip->regmap); 461b59320ccSDaniel Jeong dev_err(&client->dev, "fail to allocate regmap %d\n", ret); 462b59320ccSDaniel Jeong return ret; 463b59320ccSDaniel Jeong } 464b59320ccSDaniel Jeong i2c_set_clientdata(client, pchip); 465b59320ccSDaniel Jeong 466b59320ccSDaniel Jeong if (pdata != NULL) { 467b59320ccSDaniel Jeong pchip->pdata = pdata; 468b59320ccSDaniel Jeong pchip->mphase = pdata->mphase; 469b59320ccSDaniel Jeong } else { 470b59320ccSDaniel Jeong pchip->pdata = devm_kzalloc(pchip->dev, 471b59320ccSDaniel Jeong sizeof(struct lp8755_platform_data), 472b59320ccSDaniel Jeong GFP_KERNEL); 473b59320ccSDaniel Jeong if (!pchip->pdata) 474b59320ccSDaniel Jeong return -ENOMEM; 475b59320ccSDaniel Jeong ret = lp8755_init_data(pchip); 476240a5291SAxel Lin if (ret < 0) { 477240a5291SAxel Lin dev_err(&client->dev, "fail to initialize chip\n"); 478240a5291SAxel Lin return ret; 479240a5291SAxel Lin } 480b59320ccSDaniel Jeong } 481b59320ccSDaniel Jeong 482b59320ccSDaniel Jeong ret = lp8755_regulator_init(pchip); 483240a5291SAxel Lin if (ret < 0) { 484240a5291SAxel Lin dev_err(&client->dev, "fail to initialize regulators\n"); 48557135250SHimangi Saraogi goto err; 486240a5291SAxel Lin } 487b59320ccSDaniel Jeong 488b59320ccSDaniel Jeong pchip->irq = client->irq; 489b59320ccSDaniel Jeong ret = lp8755_int_config(pchip); 490240a5291SAxel Lin if (ret < 0) { 491240a5291SAxel Lin dev_err(&client->dev, "fail to irq config\n"); 49257135250SHimangi Saraogi goto err; 493240a5291SAxel Lin } 494b59320ccSDaniel Jeong 495b59320ccSDaniel Jeong return ret; 496b59320ccSDaniel Jeong 49757135250SHimangi Saraogi err: 498b59320ccSDaniel Jeong /* output disable */ 4991200c60bSAxel Lin for (icnt = 0; icnt < LP8755_BUCK_MAX; icnt++) 500b59320ccSDaniel Jeong lp8755_write(pchip, icnt, 0x00); 501b59320ccSDaniel Jeong 502b59320ccSDaniel Jeong return ret; 503b59320ccSDaniel Jeong } 504b59320ccSDaniel Jeong 505b59320ccSDaniel Jeong static int lp8755_remove(struct i2c_client *client) 506b59320ccSDaniel Jeong { 507b59320ccSDaniel Jeong int icnt; 508b59320ccSDaniel Jeong struct lp8755_chip *pchip = i2c_get_clientdata(client); 509b59320ccSDaniel Jeong 5101200c60bSAxel Lin for (icnt = 0; icnt < LP8755_BUCK_MAX; icnt++) 511b59320ccSDaniel Jeong lp8755_write(pchip, icnt, 0x00); 512b59320ccSDaniel Jeong 513b59320ccSDaniel Jeong return 0; 514b59320ccSDaniel Jeong } 515b59320ccSDaniel Jeong 516b59320ccSDaniel Jeong static const struct i2c_device_id lp8755_id[] = { 517b59320ccSDaniel Jeong {LP8755_NAME, 0}, 518b59320ccSDaniel Jeong {} 519b59320ccSDaniel Jeong }; 520b59320ccSDaniel Jeong 521b59320ccSDaniel Jeong MODULE_DEVICE_TABLE(i2c, lp8755_id); 522b59320ccSDaniel Jeong 523b59320ccSDaniel Jeong static struct i2c_driver lp8755_i2c_driver = { 524b59320ccSDaniel Jeong .driver = { 525b59320ccSDaniel Jeong .name = LP8755_NAME, 526b59320ccSDaniel Jeong }, 527b59320ccSDaniel Jeong .probe = lp8755_probe, 528a1a41ab4SAxel Lin .remove = lp8755_remove, 529b59320ccSDaniel Jeong .id_table = lp8755_id, 530b59320ccSDaniel Jeong }; 531b59320ccSDaniel Jeong 532b59320ccSDaniel Jeong static int __init lp8755_init(void) 533b59320ccSDaniel Jeong { 534b59320ccSDaniel Jeong return i2c_add_driver(&lp8755_i2c_driver); 535b59320ccSDaniel Jeong } 536b59320ccSDaniel Jeong 537b59320ccSDaniel Jeong subsys_initcall(lp8755_init); 538b59320ccSDaniel Jeong 539b59320ccSDaniel Jeong static void __exit lp8755_exit(void) 540b59320ccSDaniel Jeong { 541b59320ccSDaniel Jeong i2c_del_driver(&lp8755_i2c_driver); 542b59320ccSDaniel Jeong } 543b59320ccSDaniel Jeong 544b59320ccSDaniel Jeong module_exit(lp8755_exit); 545b59320ccSDaniel Jeong 546b59320ccSDaniel Jeong MODULE_DESCRIPTION("Texas Instruments lp8755 driver"); 547b59320ccSDaniel Jeong MODULE_AUTHOR("Daniel Jeong <daniel.jeong@ti.com>"); 548b59320ccSDaniel Jeong MODULE_LICENSE("GPL v2"); 549