From b59320cc5a5e6ceaa17f0895ffbe0711ebad7adf Mon Sep 17 00:00:00 2001 From: Daniel Jeong Date: Mon, 17 Dec 2012 10:24:06 +0900 Subject: regulator: lp8755: new driver for LP8755 This patch is for new lp8755 regulator dirver and several unsed variables were deleted and then test was done. LP8755 : The LP8755 is a high performance power management unit.It contains six step-down DC-DC converters which can can be filexibly bundled together in multiphase converters as required by application. www.ti.com Signed-off-by: Daniel Jeong Signed-off-by: Mark Brown diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 551a22b..f37a1c8 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -277,6 +277,15 @@ config REGULATOR_LP872X help This driver supports LP8720/LP8725 PMIC +config REGULATOR_LP8755 + tristate "TI LP8755 High Performance PMU driver" + depends on I2C + select REGMAP_I2C + help + This driver supports LP8755 High Performance PMU driver. This + chip contains six step-down DC/DC converters which can support + 9 mode multiphase configuration. + config REGULATOR_LP8788 bool "TI LP8788 Power Regulators" depends on MFD_LP8788 diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index b802b0c..6e82503 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -30,6 +30,7 @@ obj-$(CONFIG_REGULATOR_LP3972) += lp3972.o obj-$(CONFIG_REGULATOR_LP872X) += lp872x.o obj-$(CONFIG_REGULATOR_LP8788) += lp8788-buck.o obj-$(CONFIG_REGULATOR_LP8788) += lp8788-ldo.o +obj-$(CONFIG_REGULATOR_LP8755) += lp8755.o obj-$(CONFIG_REGULATOR_MAX1586) += max1586.o obj-$(CONFIG_REGULATOR_MAX8649) += max8649.o obj-$(CONFIG_REGULATOR_MAX8660) += max8660.o diff --git a/drivers/regulator/lp8755.c b/drivers/regulator/lp8755.c new file mode 100644 index 0000000..dbc4d12 --- /dev/null +++ b/drivers/regulator/lp8755.c @@ -0,0 +1,580 @@ +/* + * LP8755 High Performance Power Management Unit : System Interface Driver + * (based on rev. 0.26) + * Copyright 2012 Texas Instruments + * + * Author: Daniel(Geon Si) Jeong + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define LP8755_REG_BUCK0 0x00 +#define LP8755_REG_BUCK1 0x03 +#define LP8755_REG_BUCK2 0x04 +#define LP8755_REG_BUCK3 0x01 +#define LP8755_REG_BUCK4 0x05 +#define LP8755_REG_BUCK5 0x02 +#define LP8755_REG_MAX 0xFF + +#define LP8755_BUCK_EN_M BIT(7) +#define LP8755_BUCK_LINEAR_OUT_MAX 0x76 +#define LP8755_BUCK_VOUT_M 0x7F + +enum bucks { + BUCK0 = 0, + BUCK1, + BUCK2, + BUCK3, + BUCK4, + BUCK5, +}; + +struct lp8755_mphase { + int nreg; + int buck_num[LP8755_BUCK_MAX]; +}; + +struct lp8755_chip { + struct device *dev; + struct regmap *regmap; + struct lp8755_platform_data *pdata; + + int irq; + unsigned int irqmask; + + int mphase; + struct regulator_dev *rdev[LP8755_BUCK_MAX]; +}; + +/** + *lp8755_read : read a single register value from lp8755. + *@pchip : device to read from + *@reg : register to read from + *@val : pointer to store read value + */ +static int lp8755_read(struct lp8755_chip *pchip, unsigned int reg, + unsigned int *val) +{ + return regmap_read(pchip->regmap, reg, val); +} + +/** + *lp8755_write : write a single register value to lp8755. + *@pchip : device to write to + *@reg : register to write to + *@val : value to be written + */ +static int lp8755_write(struct lp8755_chip *pchip, unsigned int reg, + unsigned int val) +{ + return regmap_write(pchip->regmap, reg, val); +} + +/** + *lp8755_update_bits : set the values of bit fields in lp8755 register. + *@pchip : device to read from + *@reg : register to update + *@mask : bitmask to be changed + *@val : value for bitmask + */ +static int lp8755_update_bits(struct lp8755_chip *pchip, unsigned int reg, + unsigned int mask, unsigned int val) +{ + return regmap_update_bits(pchip->regmap, reg, mask, val); +} + +static int lp8755_buck_enable_time(struct regulator_dev *rdev) +{ + int ret; + unsigned int regval; + enum lp8755_bucks id = rdev_get_id(rdev); + struct lp8755_chip *pchip = rdev_get_drvdata(rdev); + + ret = lp8755_read(pchip, 0x12 + id, ®val); + if (ret < 0) { + dev_err(pchip->dev, "i2c acceess error %s\n", __func__); + return ret; + } + return (regval & 0xff) * 100; +} + +static int lp8755_buck_set_mode(struct regulator_dev *rdev, unsigned int mode) +{ + int ret; + unsigned int regbval = 0x0; + enum lp8755_bucks id = rdev_get_id(rdev); + struct lp8755_chip *pchip = rdev_get_drvdata(rdev); + + switch (mode) { + case REGULATOR_MODE_FAST: + /* forced pwm mode */ + regbval = (0x01 << id); + break; + case REGULATOR_MODE_NORMAL: + /* enable automatic pwm/pfm mode */ + ret = lp8755_update_bits(pchip, 0x08 + id, 0x20, 0x00); + if (ret < 0) + goto err_i2c; + break; + case REGULATOR_MODE_IDLE: + /* enable automatic pwm/pfm/lppfm mode */ + ret = lp8755_update_bits(pchip, 0x08 + id, 0x20, 0x20); + if (ret < 0) + goto err_i2c; + + ret = lp8755_update_bits(pchip, 0x10, 0x01, 0x01); + if (ret < 0) + goto err_i2c; + break; + default: + dev_err(pchip->dev, "Not supported buck mode %s\n", __func__); + /* forced pwm mode */ + regbval = (0x01 << id); + } + + ret = lp8755_update_bits(pchip, 0x06, 0x01 << id, regbval); + if (ret < 0) + goto err_i2c; + return ret; +err_i2c: + dev_err(pchip->dev, "i2c acceess error %s\n", __func__); + return ret; +} + +static unsigned int lp8755_buck_get_mode(struct regulator_dev *rdev) +{ + int ret; + unsigned int regval; + enum lp8755_bucks id = rdev_get_id(rdev); + struct lp8755_chip *pchip = rdev_get_drvdata(rdev); + + ret = lp8755_read(pchip, 0x06, ®val); + if (ret < 0) + goto err_i2c; + + /* mode fast means forced pwm mode */ + if (regval & (0x01 << id)) + return REGULATOR_MODE_FAST; + + ret = lp8755_read(pchip, 0x08 + id, ®val); + if (ret < 0) + goto err_i2c; + + /* mode idle means automatic pwm/pfm/lppfm mode */ + if (regval & 0x20) + return REGULATOR_MODE_IDLE; + + /* mode normal means automatic pwm/pfm mode */ + return REGULATOR_MODE_NORMAL; + +err_i2c: + dev_err(pchip->dev, "i2c acceess error %s\n", __func__); + return 0; +} + +static int lp8755_buck_set_ramp(struct regulator_dev *rdev, int ramp) +{ + int ret; + unsigned int regval = 0x00; + enum lp8755_bucks id = rdev_get_id(rdev); + struct lp8755_chip *pchip = rdev_get_drvdata(rdev); + + /* uV/us */ + switch (ramp) { + case 0 ... 230: + regval = 0x07; + break; + case 231 ... 470: + regval = 0x06; + break; + case 471 ... 940: + regval = 0x05; + break; + case 941 ... 1900: + regval = 0x04; + break; + case 1901 ... 3800: + regval = 0x03; + break; + case 3801 ... 7500: + regval = 0x02; + break; + case 7501 ... 15000: + regval = 0x01; + break; + case 15001 ... 30000: + regval = 0x00; + break; + default: + dev_err(pchip->dev, + "Not supported ramp value %d %s\n", ramp, __func__); + return -EINVAL; + } + + ret = lp8755_update_bits(pchip, 0x07 + id, 0x07, regval); + if (ret < 0) + goto err_i2c; + return ret; +err_i2c: + dev_err(pchip->dev, "i2c acceess error %s\n", __func__); + return ret; +} + +static struct regulator_ops lp8755_buck_ops = { + .list_voltage = regulator_list_voltage_linear, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .enable_time = lp8755_buck_enable_time, + .set_mode = lp8755_buck_set_mode, + .get_mode = lp8755_buck_get_mode, + .set_ramp_delay = lp8755_buck_set_ramp, +}; + +#define lp8755_rail(_id) "lp8755_buck"#_id +#define lp8755_buck_init(_id)\ +{\ + .constraints = {\ + .name = lp8755_rail(_id),\ + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,\ + .min_uV = 500000,\ + .max_uV = 1675000,\ + },\ +} + +static struct regulator_init_data lp8755_reg_default[LP8755_BUCK_MAX] = { + [BUCK0] = lp8755_buck_init(0), + [BUCK1] = lp8755_buck_init(1), + [BUCK2] = lp8755_buck_init(2), + [BUCK3] = lp8755_buck_init(3), + [BUCK4] = lp8755_buck_init(4), + [BUCK5] = lp8755_buck_init(5), +}; + +static const struct lp8755_mphase mphase_buck[MPHASE_CONF_MAX] = { + {3, {BUCK0, BUCK3, BUCK5} + }, + {6, {BUCK0, BUCK1, BUCK2, BUCK3, BUCK4, BUCK5} + }, + {5, {BUCK0, BUCK2, BUCK3, BUCK4, BUCK5} + }, + {4, {BUCK0, BUCK3, BUCK4, BUCK5} + }, + {3, {BUCK0, BUCK4, BUCK5} + }, + {2, {BUCK0, BUCK5} + }, + {1, {BUCK0} + }, + {2, {BUCK0, BUCK3} + }, + {4, {BUCK0, BUCK2, BUCK3, BUCK5} + }, +}; + +static int lp8755_init_data(struct lp8755_chip *pchip) +{ + unsigned int regval; + int ret, icnt, buck_num; + struct lp8755_platform_data *pdata = pchip->pdata; + + /* read back muti-phase configuration */ + ret = lp8755_read(pchip, 0x3D, ®val); + if (ret < 0) + goto out_i2c_error; + pchip->mphase = regval & 0x07; + + /* set default data based on multi-phase config */ + for (icnt = 0; icnt < mphase_buck[pchip->mphase].nreg; icnt++) { + buck_num = mphase_buck[pchip->mphase].buck_num[icnt]; + pdata->buck_data[buck_num] = &lp8755_reg_default[buck_num]; + } + return ret; + +out_i2c_error: + dev_err(pchip->dev, "i2c acceess error %s\n", __func__); + return ret; +} + +#define lp8755_buck_desc(_id)\ +{\ + .name = lp8755_rail(_id),\ + .id = LP8755_BUCK##_id,\ + .ops = &lp8755_buck_ops,\ + .n_voltages = LP8755_BUCK_LINEAR_OUT_MAX+1,\ + .uV_step = 10000,\ + .min_uV = 500000,\ + .type = REGULATOR_VOLTAGE,\ + .owner = THIS_MODULE,\ + .enable_reg = LP8755_REG_BUCK##_id,\ + .enable_mask = LP8755_BUCK_EN_M,\ + .vsel_reg = LP8755_REG_BUCK##_id,\ + .vsel_mask = LP8755_BUCK_VOUT_M,\ +} + +static struct regulator_desc lp8755_regulators[] = { + lp8755_buck_desc(0), + lp8755_buck_desc(1), + lp8755_buck_desc(2), + lp8755_buck_desc(3), + lp8755_buck_desc(4), + lp8755_buck_desc(5), +}; + +static int lp8755_regulator_init(struct lp8755_chip *pchip) +{ + int ret, icnt, buck_num; + struct lp8755_platform_data *pdata = pchip->pdata; + struct regulator_config rconfig = { }; + + rconfig.regmap = pchip->regmap; + rconfig.dev = pchip->dev; + rconfig.driver_data = pchip; + + for (icnt = 0; icnt < mphase_buck[pchip->mphase].nreg; icnt++) { + buck_num = mphase_buck[pchip->mphase].buck_num[icnt]; + rconfig.init_data = pdata->buck_data[buck_num]; + rconfig.of_node = pchip->dev->of_node; + pchip->rdev[buck_num] = + regulator_register(&lp8755_regulators[buck_num], &rconfig); + if (IS_ERR(pchip->rdev[buck_num])) { + ret = PTR_ERR(pchip->rdev[buck_num]); + dev_err(pchip->dev, "regulator init failed: buck 0\n"); + goto err_buck; + } + } + + return 0; + +err_buck: + for (icnt = 0; icnt < LP8755_BUCK_MAX; icnt++) + if (pchip->rdev[icnt] != NULL) + regulator_unregister(pchip->rdev[icnt]); + return ret; +} + +static irqreturn_t lp8755_irq_handler(int irq, void *data) +{ + int ret, icnt; + unsigned int flag0, flag1; + struct lp8755_chip *pchip = data; + + /* read flag0 register */ + ret = lp8755_read(pchip, 0x0D, &flag0); + if (ret < 0) + goto err_i2c; + /* clear flag register to pull up int. pin */ + ret = lp8755_write(pchip, 0x0D, 0x00); + if (ret < 0) + goto err_i2c; + + /* sent power fault detection event to specific regulator */ + for (icnt = 0; icnt < 6; icnt++) + if ((flag0 & (0x4 << icnt)) + && (pchip->irqmask & (0x04 << icnt)) + && (pchip->rdev[icnt] != NULL)) + regulator_notifier_call_chain(pchip->rdev[icnt], + LP8755_EVENT_PWR_FAULT, + NULL); + + /* read flag1 register */ + ret = lp8755_read(pchip, 0x0E, &flag1); + if (ret < 0) + goto err_i2c; + /* clear flag register to pull up int. pin */ + ret = lp8755_write(pchip, 0x0E, 0x00); + if (ret < 0) + goto err_i2c; + + /* send OCP event to all regualtor devices */ + if ((flag1 & 0x01) && (pchip->irqmask & 0x01)) + for (icnt = 0; icnt < LP8755_BUCK_MAX; icnt++) + if (pchip->rdev[icnt] != NULL) + regulator_notifier_call_chain(pchip->rdev[icnt], + LP8755_EVENT_OCP, + NULL); + + /* send OVP event to all regualtor devices */ + if ((flag1 & 0x02) && (pchip->irqmask & 0x02)) + for (icnt = 0; icnt < LP8755_BUCK_MAX; icnt++) + if (pchip->rdev[icnt] != NULL) + regulator_notifier_call_chain(pchip->rdev[icnt], + LP8755_EVENT_OVP, + NULL); + return IRQ_HANDLED; + +err_i2c: + dev_err(pchip->dev, "i2c acceess error %s\n", __func__); + return IRQ_NONE; +} + +static int lp8755_int_config(struct lp8755_chip *pchip) +{ + int ret; + unsigned int regval; + + if (pchip->irq == 0) { + dev_warn(pchip->dev, "not use interrupt : %s\n", __func__); + return 0; + } + + ret = lp8755_read(pchip, 0x0F, ®val); + if (ret < 0) + goto err_i2c; + pchip->irqmask = regval; + ret = request_threaded_irq(pchip->irq, NULL, lp8755_irq_handler, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + "lp8755-irq", pchip); + if (ret) + return ret; + + return ret; + +err_i2c: + dev_err(pchip->dev, "i2c acceess error %s\n", __func__); + return ret; +} + +static const struct regmap_config lp8755_regmap = { + .reg_bits = 8, + .val_bits = 8, + .max_register = LP8755_REG_MAX, +}; + +static int lp8755_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + int ret, icnt; + struct lp8755_chip *pchip; + struct lp8755_platform_data *pdata = client->dev.platform_data; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + dev_err(&client->dev, "i2c functionality check fail.\n"); + return -EOPNOTSUPP; + } + + pchip = devm_kzalloc(&client->dev, + sizeof(struct lp8755_chip), GFP_KERNEL); + if (!pchip) + return -ENOMEM; + + pchip->dev = &client->dev; + pchip->regmap = devm_regmap_init_i2c(client, &lp8755_regmap); + if (IS_ERR(pchip->regmap)) { + ret = PTR_ERR(pchip->regmap); + dev_err(&client->dev, "fail to allocate regmap %d\n", ret); + return ret; + } + i2c_set_clientdata(client, pchip); + + if (pdata != NULL) { + pchip->pdata = pdata; + pchip->mphase = pdata->mphase; + } else { + pchip->pdata = devm_kzalloc(pchip->dev, + sizeof(struct lp8755_platform_data), + GFP_KERNEL); + if (!pchip->pdata) + return -ENOMEM; + ret = lp8755_init_data(pchip); + if (ret < 0) + goto err_chip_init; + } + + ret = lp8755_regulator_init(pchip); + if (ret < 0) + goto err_regulator; + + pchip->irq = client->irq; + ret = lp8755_int_config(pchip); + if (ret < 0) + goto err_irq; + + return ret; + +err_irq: + dev_err(&client->dev, "fail to irq config\n"); + + for (icnt = 0; icnt < mphase_buck[pchip->mphase].nreg; icnt++) + regulator_unregister(pchip->rdev[icnt]); + +err_regulator: + dev_err(&client->dev, "fail to initialize regulators\n"); + /* output disable */ + for (icnt = 0; icnt < 0x06; icnt++) + lp8755_write(pchip, icnt, 0x00); + +err_chip_init: + dev_err(&client->dev, "fail to initialize chip\n"); + return ret; +} + +static int lp8755_remove(struct i2c_client *client) +{ + int icnt; + struct lp8755_chip *pchip = i2c_get_clientdata(client); + + for (icnt = 0; icnt < mphase_buck[pchip->mphase].nreg; icnt++) + regulator_unregister(pchip->rdev[icnt]); + + for (icnt = 0; icnt < 0x06; icnt++) + lp8755_write(pchip, icnt, 0x00); + + if (pchip->irq != 0) + free_irq(pchip->irq, pchip); + + return 0; +} + +static const struct i2c_device_id lp8755_id[] = { + {LP8755_NAME, 0}, + {} +}; + +MODULE_DEVICE_TABLE(i2c, lp8755_id); + +static struct i2c_driver lp8755_i2c_driver = { + .driver = { + .name = LP8755_NAME, + }, + .probe = lp8755_probe, + .remove = __devexit_p(lp8755_remove), + .id_table = lp8755_id, +}; + +static int __init lp8755_init(void) +{ + return i2c_add_driver(&lp8755_i2c_driver); +} + +subsys_initcall(lp8755_init); + +static void __exit lp8755_exit(void) +{ + i2c_del_driver(&lp8755_i2c_driver); +} + +module_exit(lp8755_exit); + +MODULE_DESCRIPTION("Texas Instruments lp8755 driver"); +MODULE_AUTHOR("Daniel Jeong "); +MODULE_LICENSE("GPL v2"); diff --git a/include/linux/platform_data/lp8755.h b/include/linux/platform_data/lp8755.h new file mode 100644 index 0000000..a7fd077 --- /dev/null +++ b/include/linux/platform_data/lp8755.h @@ -0,0 +1,71 @@ +/* + * LP8755 High Performance Power Management Unit Driver:System Interface Driver + * + * Copyright (C) 2012 Texas Instruments + * + * Author: Daniel(Geon Si) Jeong + * G.Shark Jeong + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#ifndef _LP8755_H +#define _LP8755_H + +#include + +#define LP8755_NAME "lp8755-regulator" +/* + *PWR FAULT : power fault detected + *OCP : over current protect activated + *OVP : over voltage protect activated + *TEMP_WARN : thermal warning + *TEMP_SHDN : thermal shutdonw detected + *I_LOAD : current measured + */ +#define LP8755_EVENT_PWR_FAULT REGULATOR_EVENT_FAIL +#define LP8755_EVENT_OCP REGULATOR_EVENT_OVER_CURRENT +#define LP8755_EVENT_OVP 0x10000 +#define LP8755_EVENT_TEMP_WARN 0x2000 +#define LP8755_EVENT_TEMP_SHDN REGULATOR_EVENT_OVER_TEMP +#define LP8755_EVENT_I_LOAD 0x40000 + +enum lp8755_bucks { + LP8755_BUCK0 = 0, + LP8755_BUCK1, + LP8755_BUCK2, + LP8755_BUCK3, + LP8755_BUCK4, + LP8755_BUCK5, + LP8755_BUCK_MAX, +}; + +/** + * multiphase configuration options + */ +enum lp8755_mphase_config { + MPHASE_CONF0, + MPHASE_CONF1, + MPHASE_CONF2, + MPHASE_CONF3, + MPHASE_CONF4, + MPHASE_CONF5, + MPHASE_CONF6, + MPHASE_CONF7, + MPHASE_CONF8, + MPHASE_CONF_MAX +}; + +/** + * struct lp8755_platform_data + * @mphase_type : Multiphase Switcher Configurations. + * @buck_data : buck0~6 init voltage in uV + */ +struct lp8755_platform_data { + int mphase; + struct regulator_init_data *buck_data[LP8755_BUCK_MAX]; +}; +#endif -- cgit v0.10.2 From a1a41ab4e92a42d380286a6aadb1026a2b352801 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 25 Dec 2012 10:06:20 +0800 Subject: regulator: lp8755: Fix lp8755_regulator_init unwind code It's safe to pass NULL argument to regulator_unregister(), so we can remove the NULL checking before calling regulator_unregister(). However pass a ERR_PTR to regulator_unregister() is wrong, so we need to explicitly set "pchip->rdev[buck_num] = NULL" before goto err_buck. This patch also includes below cleanups: Show correct regulator id in dev_err. Remove __devexit_p. Signed-off-by: Axel Lin Signed-off-by: Mark Brown diff --git a/drivers/regulator/lp8755.c b/drivers/regulator/lp8755.c index dbc4d12..06a82e2 100644 --- a/drivers/regulator/lp8755.c +++ b/drivers/regulator/lp8755.c @@ -358,7 +358,9 @@ static int lp8755_regulator_init(struct lp8755_chip *pchip) regulator_register(&lp8755_regulators[buck_num], &rconfig); if (IS_ERR(pchip->rdev[buck_num])) { ret = PTR_ERR(pchip->rdev[buck_num]); - dev_err(pchip->dev, "regulator init failed: buck 0\n"); + pchip->rdev[buck_num] = NULL; + dev_err(pchip->dev, "regulator init failed: buck %d\n", + buck_num); goto err_buck; } } @@ -367,8 +369,7 @@ static int lp8755_regulator_init(struct lp8755_chip *pchip) err_buck: for (icnt = 0; icnt < LP8755_BUCK_MAX; icnt++) - if (pchip->rdev[icnt] != NULL) - regulator_unregister(pchip->rdev[icnt]); + regulator_unregister(pchip->rdev[icnt]); return ret; } @@ -557,7 +558,7 @@ static struct i2c_driver lp8755_i2c_driver = { .name = LP8755_NAME, }, .probe = lp8755_probe, - .remove = __devexit_p(lp8755_remove), + .remove = lp8755_remove, .id_table = lp8755_id, }; -- cgit v0.10.2 From cad877ef0af8d18aae88bb7d0f30f747f003fd0f Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 26 Dec 2012 11:56:37 +0800 Subject: regulator: lp8755: Fix mask for pchip->mphase According to the datasheet, it has 9 multi-phase mode from 0 to 8 and it takes 4 bits in the register. The mask for pchip->mphase should be 0x0F. Signed-off-by: Axel Lin Signed-off-by: Mark Brown diff --git a/drivers/regulator/lp8755.c b/drivers/regulator/lp8755.c index 06a82e2..decb3ad 100644 --- a/drivers/regulator/lp8755.c +++ b/drivers/regulator/lp8755.c @@ -301,7 +301,7 @@ static int lp8755_init_data(struct lp8755_chip *pchip) ret = lp8755_read(pchip, 0x3D, ®val); if (ret < 0) goto out_i2c_error; - pchip->mphase = regval & 0x07; + pchip->mphase = regval & 0x0F; /* set default data based on multi-phase config */ for (icnt = 0; icnt < mphase_buck[pchip->mphase].nreg; icnt++) { -- cgit v0.10.2 From 240a529108a11d235328a140fe6b03cf76cef099 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sat, 12 Jan 2013 14:58:35 +0800 Subject: regulator: lp8755: Don't show unrelated messags in lp8755_probe error paths Signed-off-by: Axel Lin Signed-off-by: Mark Brown diff --git a/drivers/regulator/lp8755.c b/drivers/regulator/lp8755.c index decb3ad..8c3f3f2 100644 --- a/drivers/regulator/lp8755.c +++ b/drivers/regulator/lp8755.c @@ -497,35 +497,36 @@ static int lp8755_probe(struct i2c_client *client, if (!pchip->pdata) return -ENOMEM; ret = lp8755_init_data(pchip); - if (ret < 0) - goto err_chip_init; + if (ret < 0) { + dev_err(&client->dev, "fail to initialize chip\n"); + return ret; + } } ret = lp8755_regulator_init(pchip); - if (ret < 0) + if (ret < 0) { + dev_err(&client->dev, "fail to initialize regulators\n"); goto err_regulator; + } pchip->irq = client->irq; ret = lp8755_int_config(pchip); - if (ret < 0) + if (ret < 0) { + dev_err(&client->dev, "fail to irq config\n"); goto err_irq; + } return ret; err_irq: - dev_err(&client->dev, "fail to irq config\n"); - for (icnt = 0; icnt < mphase_buck[pchip->mphase].nreg; icnt++) regulator_unregister(pchip->rdev[icnt]); err_regulator: - dev_err(&client->dev, "fail to initialize regulators\n"); /* output disable */ for (icnt = 0; icnt < 0x06; icnt++) lp8755_write(pchip, icnt, 0x00); -err_chip_init: - dev_err(&client->dev, "fail to initialize chip\n"); return ret; } -- cgit v0.10.2 From 510799eaba39251b9362cf00a11ad866846e9cbf Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 7 Jan 2013 10:28:31 +0800 Subject: regulator: lp8755: Remove enum bucks We already have enum lp8755_bucks in lp8755.h, so it looks pointless adding enum bucks in lp8755.c. Signed-off-by: Axel Lin Tested-by: Daniel Jeong Signed-off-by: Mark Brown diff --git a/drivers/regulator/lp8755.c b/drivers/regulator/lp8755.c index 8c3f3f2..8b1ce0f 100644 --- a/drivers/regulator/lp8755.c +++ b/drivers/regulator/lp8755.c @@ -37,15 +37,6 @@ #define LP8755_BUCK_LINEAR_OUT_MAX 0x76 #define LP8755_BUCK_VOUT_M 0x7F -enum bucks { - BUCK0 = 0, - BUCK1, - BUCK2, - BUCK3, - BUCK4, - BUCK5, -}; - struct lp8755_mphase { int nreg; int buck_num[LP8755_BUCK_MAX]; @@ -262,33 +253,26 @@ static struct regulator_ops lp8755_buck_ops = { } static struct regulator_init_data lp8755_reg_default[LP8755_BUCK_MAX] = { - [BUCK0] = lp8755_buck_init(0), - [BUCK1] = lp8755_buck_init(1), - [BUCK2] = lp8755_buck_init(2), - [BUCK3] = lp8755_buck_init(3), - [BUCK4] = lp8755_buck_init(4), - [BUCK5] = lp8755_buck_init(5), + [LP8755_BUCK0] = lp8755_buck_init(0), + [LP8755_BUCK1] = lp8755_buck_init(1), + [LP8755_BUCK2] = lp8755_buck_init(2), + [LP8755_BUCK3] = lp8755_buck_init(3), + [LP8755_BUCK4] = lp8755_buck_init(4), + [LP8755_BUCK5] = lp8755_buck_init(5), }; static const struct lp8755_mphase mphase_buck[MPHASE_CONF_MAX] = { - {3, {BUCK0, BUCK3, BUCK5} - }, - {6, {BUCK0, BUCK1, BUCK2, BUCK3, BUCK4, BUCK5} - }, - {5, {BUCK0, BUCK2, BUCK3, BUCK4, BUCK5} - }, - {4, {BUCK0, BUCK3, BUCK4, BUCK5} - }, - {3, {BUCK0, BUCK4, BUCK5} - }, - {2, {BUCK0, BUCK5} - }, - {1, {BUCK0} - }, - {2, {BUCK0, BUCK3} - }, - {4, {BUCK0, BUCK2, BUCK3, BUCK5} - }, + { 3, { LP8755_BUCK0, LP8755_BUCK3, LP8755_BUCK5 } }, + { 6, { LP8755_BUCK0, LP8755_BUCK1, LP8755_BUCK2, LP8755_BUCK3, + LP8755_BUCK4, LP8755_BUCK5 } }, + { 5, { LP8755_BUCK0, LP8755_BUCK2, LP8755_BUCK3, LP8755_BUCK4, + LP8755_BUCK5} }, + { 4, { LP8755_BUCK0, LP8755_BUCK3, LP8755_BUCK4, LP8755_BUCK5} }, + { 3, { LP8755_BUCK0, LP8755_BUCK4, LP8755_BUCK5} }, + { 2, { LP8755_BUCK0, LP8755_BUCK5} }, + { 1, { LP8755_BUCK0} }, + { 2, { LP8755_BUCK0, LP8755_BUCK3} }, + { 4, { LP8755_BUCK0, LP8755_BUCK2, LP8755_BUCK3, LP8755_BUCK5} }, }; static int lp8755_init_data(struct lp8755_chip *pchip) -- cgit v0.10.2 From 1200c60bc599b8ad678617b0bd0e83bb7b4434ba Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sat, 26 Jan 2013 13:19:47 +0800 Subject: regulator: lp8755: Use LP8755_BUCK_MAX instead of magic number Signed-off-by: Axel Lin Signed-off-by: Mark Brown diff --git a/drivers/regulator/lp8755.c b/drivers/regulator/lp8755.c index 8b1ce0f..f0f6ea0 100644 --- a/drivers/regulator/lp8755.c +++ b/drivers/regulator/lp8755.c @@ -373,7 +373,7 @@ static irqreturn_t lp8755_irq_handler(int irq, void *data) goto err_i2c; /* sent power fault detection event to specific regulator */ - for (icnt = 0; icnt < 6; icnt++) + for (icnt = 0; icnt < LP8755_BUCK_MAX; icnt++) if ((flag0 & (0x4 << icnt)) && (pchip->irqmask & (0x04 << icnt)) && (pchip->rdev[icnt] != NULL)) @@ -508,7 +508,7 @@ err_irq: err_regulator: /* output disable */ - for (icnt = 0; icnt < 0x06; icnt++) + for (icnt = 0; icnt < LP8755_BUCK_MAX; icnt++) lp8755_write(pchip, icnt, 0x00); return ret; @@ -522,7 +522,7 @@ static int lp8755_remove(struct i2c_client *client) for (icnt = 0; icnt < mphase_buck[pchip->mphase].nreg; icnt++) regulator_unregister(pchip->rdev[icnt]); - for (icnt = 0; icnt < 0x06; icnt++) + for (icnt = 0; icnt < LP8755_BUCK_MAX; icnt++) lp8755_write(pchip, icnt, 0x00); if (pchip->irq != 0) -- cgit v0.10.2