summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: e32a1e6)
raw | patch | inline | side by side (parent: e32a1e6)
author | Daniel Jeong <gshark.jeong@gmail.com> | |
Thu, 15 Oct 2015 06:26:58 +0000 (15:26 +0900) | ||
committer | Daniel Jeong <gshark.jeong@gmail.com> | |
Thu, 15 Oct 2015 06:26:58 +0000 (15:26 +0900) |
Signed-off-by: Daniel Jeong <gshark.jeong@gmail.com>
Documentation/devicetree/bindings/regulator/lp8758.txt | patch | blob | history | |
drivers/regulator/lp8758.c | patch | blob | history | |
include/linux/platform_data/lp8758.h | [deleted file] | patch | blob | history |
include/linux/regulator/lp872x.h | [new file with mode: 0644] | patch | blob |
include/linux/regulator/lp8758.h | [new file with mode: 0644] | patch | blob |
diff --git a/Documentation/devicetree/bindings/regulator/lp8758.txt b/Documentation/devicetree/bindings/regulator/lp8758.txt
index 979a1b08a6faf4671a9df9b27e8903ebc754af68..70db03d490866a538b438cdc1548961731738835 100644 (file)
compatible = "ti,lp8758";
reg = <0x60>;
- /* BUCKx Pin Setting
- 0: i2c control,
- 1: EN1 Pin Enable/Disable control,
- 2: EN1 Pin Roof/Floor control,
- 3: EN2 Pin Enable/Disable control,
- 4: EN2 Pin Roof/Floor control
- */
- buck0_pinctrl = <0>;
- buck1_pinctrl = <0>;
- buck2_pinctrl = <0>;
- buck3_pinctrl = <0>;
+ /*
+ * sub version info
+ * 0 : b0
+ * 1 : d0
+ * 2 : e0
+ * 3 : f0
+ */
+ sub_version = <3>;
+
+ /*
+ * Buck Control Setting
+ * buck_ctrl[0] = buck0 control setting
+ * buck_ctrl[1] = buck1 control setting
+ * buck_ctrl[2] = buck2 control setting
+ * buck_ctrl[3] = buck3 control setting
+ * setting values
+ * 0: i2c control,
+ * 1: EN1 Pin Enable/Disable control,
+ * 2: EN1 Pin Roof/Floor control,
+ * 3: EN2 Pin Enable/Disable control,
+ * 4: EN2 Pin Roof/Floor control
+ */
+ buck_ctrl = <1 0 1 0>;
+
/*
* The gpio for interrupt depends on the processor environment.
* For example, following GPIO means GPIO60 in OMAP335x.
regulator-max-microamp = <5000000>;
regulator-boot-on;
};
+ buck1 {
+ regulator-name = "lp8758-buck1";
+ regulator-min-microamp = <1500000>;
+ regulator-max-microamp = <5000000>;
+ };
buck2 {
regulator-name = "lp8758-buck2";
regulator-min-microvolt = <500000>;
regulator-max-microamp = <5000000>;
regulator-boot-on;
};
+ buck3 {
+ regulator-name = "lp8758-buck3";
+ regulator-min-microamp = <1500000>;
+ regulator-max-microamp = <5000000>;
+ };
};
index 523162cc6b0595fa75a0e527c1732f22a1f7b00f..dbe9e59ea11cd7cdc0a359ce0ac6f6e4c3f73377 100644 (file)
*
*/
-/********************************************************************
-Notice :
- It is a preliminary version based on f0 for reference.
- A consolidated verson will be released soon.
-********************************************************************/
-
-
-
-#include <linux/module.h>
-#include <linux/slab.h>
#include <linux/err.h>
+#include <linux/gpio.h>
#include <linux/i2c.h>
-#include <linux/regmap.h>
#include <linux/interrupt.h>
-#include <linux/gpio.h>
+#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
-#include <linux/uaccess.h>
+#include <linux/regmap.h>
#include <linux/regulator/driver.h>
+#include <linux/regulator/lp8758.h>
#include <linux/regulator/machine.h>
#include <linux/regulator/of_regulator.h>
-#include <linux/platform_data/lp8758.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
struct lp8758_chip {
struct device *dev;
struct regmap *regmap;
struct lp8758_platform_data *pdata;
- int irq;
struct regulator_dev *rdev[LP8758_BUCK_MAX];
+ struct regulator_desc regulators[LP8758_BUCK_MAX];
};
/* voltage map */
1500000, 2000000, 2500000, 3000000, 3500000, 4000000, 4500000, 5000000
};
-static int lp8758_read(struct lp8758_chip *pchip, unsigned int reg,
- unsigned int *val)
-{
- return regmap_read(pchip->regmap, reg, val);
+const static int sub_version_config[LP8758_SUB_VER_MAX][LP8758_BUCK_MAX] ={
+ [LP8758_SUB_VER_B0] = { LP8758_BUCK_MASTER, LP8758_BUCK_SLAVE,
+ LP8758_BUCK_SLAVE, LP8758_BUCK_SLAVE },
+ [LP8758_SUB_VER_D0] = { LP8758_BUCK_MASTER, LP8758_BUCK_SLAVE,
+ LP8758_BUCK_MASTER, LP8758_BUCK_MASTER },
+ [LP8758_SUB_VER_E0] = { LP8758_BUCK_MASTER, LP8758_BUCK_MASTER,
+ LP8758_BUCK_MASTER, LP8758_BUCK_MASTER },
+ [LP8758_SUB_VER_F0] = { LP8758_BUCK_MASTER, LP8758_BUCK_SLAVE,
+ LP8758_BUCK_MASTER, LP8758_BUCK_SLAVE }
+};
+
+static bool lp8758_is_master(struct lp8758_chip *pchip, enum lp8758_bucks buck) {
+ int ver = pchip->pdata->sub_version;
+ if(sub_version_config[ver][buck] == LP8758_BUCK_MASTER)
+ return true;
+ return false;
}
-static int lp8758_write(struct lp8758_chip *pchip, unsigned int reg,
- unsigned int val)
-{
- return regmap_write(pchip->regmap, reg, val);
+static unsigned int lp8758_get_ctrl1_address(enum lp8758_bucks buck){
+ unsigned int ctrl_register[LP8758_BUCK_MAX] = {
+ [LP8758_BUCK0] = LP8758_REG_BUCK0_CTRL1,
+ [LP8758_BUCK1] = LP8758_REG_BUCK1_CTRL1,
+ [LP8758_BUCK2] = LP8758_REG_BUCK2_CTRL1,
+ [LP8758_BUCK3] = LP8758_REG_BUCK3_CTRL1
+ };
+ return ctrl_register[buck];
}
-static int lp8758_update_bits(struct lp8758_chip *pchip, unsigned int reg,
- unsigned int mask, unsigned int val)
-{
- return regmap_update_bits(pchip->regmap, reg, mask, val);
+static unsigned int lp8758_get_ctrl2_address(enum lp8758_bucks buck){
+ unsigned int ctrl_register[LP8758_BUCK_MAX] = {
+ [LP8758_BUCK0] = LP8758_REG_BUCK0_CTRL2,
+ [LP8758_BUCK1] = LP8758_REG_BUCK1_CTRL2,
+ [LP8758_BUCK2] = LP8758_REG_BUCK2_CTRL2,
+ [LP8758_BUCK3] = LP8758_REG_BUCK3_CTRL2
+ };
+ return ctrl_register[buck];
}
static int lp8758_buck_set_current_limit(struct regulator_dev *rdev,
struct lp8758_chip *pchip = rdev_get_drvdata(rdev);
enum lp8758_bucks buck = rdev_get_id(rdev);
int icnt;
- u8 addr;
-
- switch (buck) {
- case LP8758_BUCK0:
- addr = LP8758_REG_BUCK0_CTRL2;
- break;
- case LP8758_BUCK2:
- addr = LP8758_REG_BUCK2_CTRL2;
- break;
- default:
+
+ if(buck > LP8758_BUCK_MAX-1)
return -EINVAL;
- }
for (icnt = ARRAY_SIZE(lp8758_current_limit_uA) - 1; icnt >= 0; icnt--) {
if (lp8758_current_limit_uA[icnt] >= min_uA &&
- lp8758_current_limit_uA[icnt] <= max_uA)
- return lp8758_update_bits(pchip, addr,
- LP8758_ILIM_MASK, icnt << LP8758_ILIM_SHIFT);
+ lp8758_current_limit_uA[icnt] <= max_uA){
+ return regmap_update_bits(pchip->regmap,
+ lp8758_get_ctrl2_address(buck),
+ LP8758_ILIM_MASK, icnt << LP8758_ILIM_SHIFT);
+ }
}
return -EINVAL;
{
struct lp8758_chip *pchip = rdev_get_drvdata(rdev);
enum lp8758_bucks buck = rdev_get_id(rdev);
- u8 addr;
unsigned int val;
int ret;
-
- switch (buck) {
- case LP8758_BUCK0:
- addr = LP8758_REG_BUCK0_CTRL2;
- break;
- case LP8758_BUCK2:
- addr = LP8758_REG_BUCK2_CTRL2;
- break;
- default:
+
+ if(buck > LP8758_BUCK_MAX-1)
return -EINVAL;
- }
- ret = lp8758_read(pchip, addr, &val);
+ ret = regmap_read(pchip->regmap, lp8758_get_ctrl2_address(buck), &val);
if (ret)
return ret;
@@ -168,23 +164,20 @@ static int lp8758_buck_set_mode(struct regulator_dev *rdev, unsigned int mode)
{
struct lp8758_chip *pchip = rdev_get_drvdata(rdev);
enum lp8758_bucks buck = rdev_get_id(rdev);
- u8 addr;
-
- switch (buck) {
- case LP8758_BUCK0:
- addr = LP8758_REG_BUCK0_CTRL1;
- break;
- case LP8758_BUCK2:
- addr = LP8758_REG_BUCK2_CTRL1;
- break;
- default:
+ unsigned int addr;
+
+ if(buck > LP8758_BUCK_MAX-1)
return -EINVAL;
- }
+ addr = lp8758_get_ctrl1_address(buck);
if (mode == REGULATOR_MODE_FAST)
- return lp8758_update_bits(pchip, addr, 0x02, 0x02);
+ return regmap_update_bits(pchip->regmap, addr,
+ LP8758_BUCK_OP_MODE_MASK,
+ LP8758_BUCK_OP_FPWM);
else if (mode == REGULATOR_MODE_NORMAL)
- return lp8758_update_bits(pchip, addr, 0x02, 0x00);
+ return regmap_update_bits(pchip->regmap, addr,
+ LP8758_BUCK_OP_MODE_MASK,
+ LP8758_BUCK_OP_AUTO);
else
return -EINVAL;
}
struct lp8758_chip *pchip = rdev_get_drvdata(rdev);
enum lp8758_bucks buck = rdev_get_id(rdev);
unsigned int val;
- u8 addr;
int ret;
- switch (buck) {
- case LP8758_BUCK0:
- addr = LP8758_REG_BUCK0_CTRL1;
- break;
- case LP8758_BUCK2:
- addr = LP8758_REG_BUCK2_CTRL1;
- break;
- default:
+ if(buck > LP8758_BUCK_MAX-1)
return -EINVAL;
- }
- ret = lp8758_read(pchip, addr, &val);
+ ret = regmap_read(pchip->regmap, lp8758_get_ctrl1_address(buck), &val);
if (ret)
return ret;
- return val & 0x02 ? REGULATOR_MODE_FAST : REGULATOR_MODE_NORMAL;
+ return (val & LP8758_BUCK_OP_MODE_MASK)
+ ? REGULATOR_MODE_FAST : REGULATOR_MODE_NORMAL;
+}
+
+static int lp8758_buck_set_ramp(struct regulator_dev *rdev, int ramp)
+{
+ int ret = -EINVAL;
+ unsigned int regval = 0x00;
+ enum lp8758_bucks buck = rdev_get_id(rdev);
+ struct lp8758_chip *pchip = rdev_get_drvdata(rdev);
+
+ if(buck > LP8758_BUCK_MAX-1)
+ return -EINVAL;
+
+ if(lp8758_is_master(pchip,buck)) {
+ /* uV/us */
+ switch (ramp) {
+ case 0 ... 470:
+ regval = 0x07;
+ break;
+ case 471 ... 940:
+ regval = 0x06;
+ break;
+ case 941 ... 1900:
+ regval = 0x05;
+ break;
+ case 1901 ... 3800:
+ regval = 0x04;
+ break;
+ case 3801 ... 7500:
+ regval = 0x03;
+ break;
+ case 7501 ... 10000:
+ regval = 0x02;
+ break;
+ case 10001 ... 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 = regmap_update_bits(pchip->regmap, lp8758_get_ctrl2_address(buck),
+ LP8758_BUCK_RAMP_MASK, regval);
+ }
+ return ret;
}
-static struct regulator_ops lp8758_buck_ops = {
+/* regulator operation when it is set to master */
+static struct regulator_ops lp8758_buck_master_ops = {
.map_voltage = regulator_map_voltage_ascend,
.list_voltage = regulator_list_voltage_table,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.get_mode = lp8758_buck_get_mode,
.set_current_limit = lp8758_buck_set_current_limit,
.get_current_limit = lp8758_buck_get_current_limit,
+ .set_ramp_delay = lp8758_buck_set_ramp,
+};
+
+/* regulator operation when it is tied to another as slave */
+static struct regulator_ops lp8758_buck_slave_ops = {
+ .set_current_limit = lp8758_buck_set_current_limit,
+ .get_current_limit = lp8758_buck_get_current_limit,
};
-static struct regulator_desc lp8758_regulators[LP8758_BUCK_MAX] = {
+#define lp8758_rail(_id) "lp8755-buck"#_id
+/* regulator description when it is set to master */
+#define lp8758_buck_master_desc(_id)\
+{\
+ .name = lp8758_rail(_id),\
+ .id = LP8758_BUCK##_id,\
+ .ops = &lp8758_buck_master_ops,\
+ .n_voltages = ARRAY_SIZE(lp8758_buck_voltage_map),\
+ .volt_table = lp8758_buck_voltage_map,\
+ .type = REGULATOR_VOLTAGE,\
+ .owner = THIS_MODULE,\
+ .enable_reg = LP8758_REG_BUCK##_id##_CTRL1,\
+ .enable_mask = LP8758_BUCK_EN_MASK,\
+ .vsel_reg = LP8758_REG_BUCK##_id##_VOUT,\
+ .vsel_mask = LP8758_BUCK_VOUT_MASK,\
+}
+
+/* regulator description when it is set to master and roof/floor control */
+#define lp8758_buck_master_roof_floor_desc(_id)\
+{\
+ .name = lp8758_rail(_id),\
+ .id = LP8758_BUCK##_id,\
+ .ops = &lp8758_buck_master_ops,\
+ .n_voltages = ARRAY_SIZE(lp8758_buck_voltage_map),\
+ .volt_table = lp8758_buck_voltage_map,\
+ .type = REGULATOR_VOLTAGE,\
+ .owner = THIS_MODULE,\
+ .enable_reg = LP8758_REG_BUCK##_id##_CTRL1,\
+ .enable_mask = LP8758_BUCK_EN_MASK,\
+ .vsel_reg = LP8758_REG_BUCK##_id##_FLOORVOUT,\
+ .vsel_mask = LP8758_BUCK_VOUT_MASK,\
+}
+
+/* regulator description when it is tied to another as slave */
+#define lp8758_buck_slave_desc(_id)\
+{\
+ .name = lp8758_rail(_id),\
+ .id = LP8758_BUCK##_id,\
+ .ops = &lp8758_buck_slave_ops,\
+ .type = REGULATOR_CURRENT,\
+ .owner = THIS_MODULE,\
+}
+
+/* regulators description for all configuration */
+static struct regulator_desc lp8758_buck_master_config[LP8758_BUCK_MAX][LP8758_CTRL_MAX] = {
+ {
+ [LP8758_CTRL_MODE0] = lp8758_buck_master_desc(0),
+ [LP8758_CTRL_MODE1] = lp8758_buck_master_desc(0),
+ [LP8758_CTRL_MODE2] = lp8758_buck_master_roof_floor_desc(0),
+ [LP8758_CTRL_MODE3] = lp8758_buck_master_desc(0),
+ [LP8758_CTRL_MODE4] = lp8758_buck_master_roof_floor_desc(0)
+ },
{
- .name = "lp8758-buck0",
- .id = LP8758_BUCK0,
- .ops = &lp8758_buck_ops,
- .n_voltages = ARRAY_SIZE(lp8758_buck_voltage_map),
- .volt_table = lp8758_buck_voltage_map,
- .type = REGULATOR_VOLTAGE,
- .owner = THIS_MODULE,
- .enable_reg = LP8758_REG_BUCK0_CTRL1,
- .enable_mask = LP8758_BUCK_EN_MASK,
- .vsel_reg = LP8758_REG_BUCK0_VOUT,
- .vsel_mask = LP8758_BUCK_VOUT_MASK,
+ [LP8758_CTRL_MODE0] = lp8758_buck_master_desc(1),
+ [LP8758_CTRL_MODE1] = lp8758_buck_master_desc(1),
+ [LP8758_CTRL_MODE2] = lp8758_buck_master_roof_floor_desc(1),
+ [LP8758_CTRL_MODE3] = lp8758_buck_master_desc(1),
+ [LP8758_CTRL_MODE4] = lp8758_buck_master_roof_floor_desc(1)
},
{
- .name = "lp8758-buck2",
- .id = LP8758_BUCK2,
- .ops = &lp8758_buck_ops,
- .n_voltages = ARRAY_SIZE(lp8758_buck_voltage_map),
- .volt_table = lp8758_buck_voltage_map,
- .type = REGULATOR_VOLTAGE,
- .owner = THIS_MODULE,
- .enable_reg = LP8758_REG_BUCK2_CTRL1,
- .enable_mask = LP8758_BUCK_EN_MASK,
- .vsel_reg = LP8758_REG_BUCK2_VOUT,
- .vsel_mask = LP8758_BUCK_VOUT_MASK,
+ [LP8758_CTRL_MODE0] = lp8758_buck_master_desc(2),
+ [LP8758_CTRL_MODE1] = lp8758_buck_master_desc(2),
+ [LP8758_CTRL_MODE2] = lp8758_buck_master_roof_floor_desc(2),
+ [LP8758_CTRL_MODE3] = lp8758_buck_master_desc(2),
+ [LP8758_CTRL_MODE4] = lp8758_buck_master_roof_floor_desc(2)
+ },
+ {
+ [LP8758_CTRL_MODE0] = lp8758_buck_master_desc(3),
+ [LP8758_CTRL_MODE1] = lp8758_buck_master_desc(3),
+ [LP8758_CTRL_MODE2] = lp8758_buck_master_roof_floor_desc(3),
+ [LP8758_CTRL_MODE3] = lp8758_buck_master_desc(3),
+ [LP8758_CTRL_MODE4] = lp8758_buck_master_roof_floor_desc(3)
}
};
-static int lp8758_regulator_init(struct lp8758_chip *pchip)
+static struct regulator_desc lp8758_buck_slave_config[LP8758_BUCK_MAX] = {
+ lp8758_buck_slave_desc(0),
+ lp8758_buck_slave_desc(1),
+ lp8758_buck_slave_desc(2),
+ lp8758_buck_slave_desc(3)
+};
+
+/*
+ * select regulator description for each buck
+ * and write configuration value into control register
+ */
+static int lp8758_regulator_init(struct lp8758_chip *pchip){
+ int icnt, ret, bctrl_mode;
+ struct regulator_desc *reg;
+
+ if(pchip->pdata->sub_version > LP8758_SUB_VER_MAX-1)
+ return -EINVAL;
+
+ /* select regulator description based on sub version*/
+ for(icnt = LP8758_BUCK0 ; icnt < LP8758_BUCK_MAX; icnt++){
+ /* select regulator description based on sub version & control mode */
+ if(lp8758_is_master(pchip,icnt)) {
+ bctrl_mode = pchip->pdata->buck_ctrl[icnt];
+ if(bctrl_mode > LP8758_CTRL_MAX-1)
+ return -EINVAL;
+ reg = &lp8758_buck_master_config[icnt][bctrl_mode];
+
+ /* control registser set */
+ if(bctrl_mode != LP8758_CTRL_MODE0)
+ bctrl_mode = (bctrl_mode - 1) | LP8758_CTRL_PIN_EN_MASK;
+
+ ret = regmap_update_bits(pchip->regmap, lp8758_get_ctrl1_address(icnt),
+ LP8758_CTRL_BUCK_MASK,
+ bctrl_mode << LP8758_CTRL_BUCK_SHIFT);
+ if(ret < 0){
+ dev_err(pchip->dev, "lp8758 %s i2c error \n",__func__);
+ return ret;
+ }
+ } else {
+ reg = &lp8758_buck_slave_config[icnt],
+ dev_err(pchip->dev, "lp8758 %d regulator is SLAVE\n",icnt);
+ }
+ memcpy(&pchip->regulators[icnt], reg, sizeof(struct regulator_desc));
+ }
+ return 0;
+}
+
+static int lp8758_regulator_register(struct lp8758_chip *pchip)
{
int ret, icnt;
struct lp8758_platform_data *pdata = pchip->pdata;
rconfig.of_node = pchip->dev->of_node;
pchip->rdev[icnt] =
devm_regulator_register(pchip->dev,
- &lp8758_regulators[icnt], &rconfig);
+ &pchip->regulators[icnt], &rconfig);
if (IS_ERR(pchip->rdev[icnt])) {
ret = PTR_ERR(pchip->rdev[icnt]);
pchip->rdev[icnt] = NULL;
"regulator init failed: buck %d\n", icnt);
return ret;
}
- dev_info(pchip->dev, "lp8758 regulator %d\n is registered",icnt);
}
return 0;
}
static irqreturn_t lp8758_irq_handler(int irq, void *data)
{
int ret, icnt;
- unsigned int int_top;
+ unsigned int int_top, rdata;
struct lp8758_chip *pchip = data;
- ret = lp8758_read(pchip, LP8758_REG_INT_TOP, &int_top);
- if(int_top & LP8758_OVERTEMP_MASK)
+ ret = regmap_read(pchip->regmap, LP8758_REG_INT_TOP, &int_top);
+ if(int_top & LP8758_INT_TMEP_MASK)
for(icnt = LP8758_BUCK0; icnt < LP8758_BUCK_MAX; icnt++)
regulator_notifier_call_chain(pchip->rdev[icnt],
REGULATOR_EVENT_OVER_TEMP, NULL);
- lp8758_write(pchip, LP8758_REG_INT_BUCK_0_1, 0x77);
- lp8758_write(pchip, LP8758_REG_INT_BUCK_2_3, 0x77);
- lp8758_write(pchip, LP8758_REG_INT_TOP, 0x0f);
+ if(int_top & LP8758_INT_BUCK01_MASK) {
+ ret = regmap_read(pchip->regmap, LP8758_REG_INT_BUCK_01, &rdata);
+ if(rdata & LP8758_INT_OVC_BUCK0_MASK)
+ regulator_notifier_call_chain(pchip->rdev[LP8758_BUCK0],
+ LP8758_EVENT_OCP, NULL);
+ if(rdata & LP8758_INT_OVC_BUCK1_MASK)
+ regulator_notifier_call_chain(pchip->rdev[LP8758_BUCK1],
+ LP8758_EVENT_OCP, NULL);
+ if(rdata & LP8758_INT_PWR_FAULT_BUCK0_MASK)
+ regulator_notifier_call_chain(pchip->rdev[LP8758_BUCK0],
+ LP8758_EVENT_PWR_FAULT, NULL);
+ if(rdata & LP8758_INT_PWR_FAULT_BUCK1_MASK)
+ regulator_notifier_call_chain(pchip->rdev[LP8758_BUCK1],
+ LP8758_EVENT_PWR_FAULT, NULL);
+ }
+
+ if(int_top & LP8758_INT_BUCK23_MASK) {
+ ret = regmap_read(pchip->regmap, LP8758_REG_INT_BUCK_23, &rdata);
+ if(rdata & LP8758_INT_OVC_BUCK2_MASK)
+ regulator_notifier_call_chain(pchip->rdev[LP8758_BUCK2],
+ LP8758_EVENT_OCP, NULL);
+ if(rdata & LP8758_INT_OVC_BUCK3_MASK)
+ regulator_notifier_call_chain(pchip->rdev[LP8758_BUCK3],
+ LP8758_EVENT_OCP, NULL);
+ if(rdata & LP8758_INT_PWR_FAULT_BUCK2_MASK)
+ regulator_notifier_call_chain(pchip->rdev[LP8758_BUCK2],
+ LP8758_EVENT_PWR_FAULT, NULL);
+ if(rdata & LP8758_INT_PWR_FAULT_BUCK3_MASK)
+ regulator_notifier_call_chain(pchip->rdev[LP8758_BUCK3],
+ LP8758_EVENT_PWR_FAULT, NULL);
+ }
+
+ /* clear interrupt */
+ regmap_write(pchip->regmap, LP8758_REG_INT_BUCK_01, LP8758_INT_CLEAR_BUCK);
+ regmap_write(pchip->regmap, LP8758_REG_INT_BUCK_23, LP8758_INT_CLEAR_BUCK);
+ regmap_write(pchip->regmap, LP8758_REG_INT_TOP, LP8758_INT_CLEAR_TOP);
- dev_info(pchip->dev, "lp8758 IRQ Handeled");
+ dev_err(pchip->dev, "lp8758 IRQ Handeled");
return IRQ_HANDLED;
}
{
int ret, irq;
- if (pchip->irq == 0) {
+ if (pchip->pdata->irq == 0) {
dev_warn(pchip->dev, "not use interrupt : %s\n", __func__);
return 0;
}
- lp8758_write(pchip, LP8758_REG_INT_BUCK_0_1, 0x77);
- lp8758_write(pchip, LP8758_REG_INT_BUCK_2_3, 0x77);
- lp8758_write(pchip, LP8758_REG_INT_TOP, 0x0f);
+ /* initially clear interrupt */
+ regmap_write(pchip->regmap, LP8758_REG_INT_BUCK_01, LP8758_INT_CLEAR_BUCK);
+ regmap_write(pchip->regmap, LP8758_REG_INT_BUCK_23, LP8758_INT_CLEAR_BUCK);
+ regmap_write(pchip->regmap, LP8758_REG_INT_TOP, LP8758_INT_CLEAR_TOP);
- gpio_request_one(pchip->irq, GPIOF_DIR_IN,"lp8758-irq");
- irq = gpio_to_irq(pchip->irq);
+ gpio_request_one(pchip->pdata->irq, GPIOF_DIR_IN,"lp8758-irq");
+ irq = gpio_to_irq(pchip->pdata->irq);
if(irq < 0){
dev_warn(pchip->dev, "irq can't be configurated\n");
return -EINVAL;
ret = request_threaded_irq(irq, NULL, lp8758_irq_handler,
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
"lp8758-irq", pchip);
- dev_info(pchip->dev, "irq config is configured gpio %d irq %d\n",
- pchip->irq, irq);
-
return ret;
}
static struct of_regulator_match lp8758_matches[LP8758_BUCK_MAX] = {
{ .name = "buck0", .driver_data = (void *)LP8758_BUCK0, },
+ { .name = "buck1", .driver_data = (void *)LP8758_BUCK1, },
{ .name = "buck2", .driver_data = (void *)LP8758_BUCK2, },
+ { .name = "buck3", .driver_data = (void *)LP8758_BUCK3, },
};
static int lp8758_parse_dt(struct i2c_client *client,
struct lp8758_chip *pchip)
{
struct device_node *node = client->dev.of_node;
- int count, icnt;
+ int err, icnt;
pchip->pdata = devm_kzalloc(&client->dev,
sizeof(struct lp8758_platform_data), GFP_KERNEL);
return -ENOMEM;
}
- count = of_regulator_match(&client->dev, node,
+ err = of_regulator_match(&client->dev, node,
lp8758_matches, LP8758_BUCK_MAX);
- if (count <= 0)
+ if (err <= 0){
dev_err(&client->dev, "lp8758 --ERR - of regulator match\n");
+ return -EINVAL;
+ }
for(icnt = 0; icnt < LP8758_BUCK_MAX; icnt++){
pchip->pdata->buck_data[icnt] = lp8758_matches[icnt].init_data;
}
- pchip->irq = of_get_named_gpio(node,"irq-gpio", 0);
-
+ pchip->pdata->irq = of_get_named_gpio(node,"irq-gpio", 0);
+ err = of_property_read_u32(node, "sub_version",
+ &pchip->pdata->sub_version);
+ if(err < 0){
+ dev_err(&client->dev, "lp8758 --ERR - of chip version read\n");
+ return -EINVAL;
+ }
+
+ err = of_property_read_u32_array(node, "buck_ctrl",
+ pchip->pdata->buck_ctrl, LP8758_BUCK_MAX);
+ if(err < 0){
+ dev_err(&client->dev, "lp8758 --ERR - pin ctrl data\n");
+ return -EINVAL;
+ }
return 0;
}
struct lp8758_chip *pchip;
int ret = 0;
- dev_info(&client->dev, "lp8758 module probe\n");
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
dev_err(&client->dev, "i2c functionality check fail.\n");
return -EOPNOTSUPP;
ret = lp8758_parse_dt(client, pchip);
if(ret < 0)
return ret;
-
pchip->dev = &client->dev;
i2c_set_clientdata(client, pchip);
return ret;
}
+ ret = lp8758_regulator_register(pchip);
+ if (ret < 0) {
+ dev_err(&client->dev, "fail to register regulators\n");
+ return ret;
+ }
+
ret = lp8758_intr_config(pchip);
if (ret < 0) {
dev_err(&client->dev, "fail to irq config\n");
diff --git a/include/linux/platform_data/lp8758.h b/include/linux/platform_data/lp8758.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Simple driver for Texas Instruments lp8758 Regulator chip
- * Copyright (C) 2015 Texas Instruments
- *
- * 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 __LINUX_LP8758_H
-#define __LINUX_LP8758_H
-
-#include <linux/regulator/consumer.h>
-
-#define LP8758_NAME "lp8758"
-#define LP8758_ADDR 0x60
-
-enum lp8758_bucks {
- LP8758_BUCK0 = 0,
- LP8758_BUCK2,
- LP8758_BUCK_MAX
-};
-
-enum lp8758_registers {
- LP8758_REG_DEV_REV = 0x00,
- LP8758_REG_OTP_REV = 0x01,
- LP8758_REG_BUCK0_CTRL1 = 0x02,
- LP8758_REG_BUCK0_CTRL2 = 0x03,
- LP8758_REG_BUCK1_CTRL1 = 0x04,
- LP8758_REG_BUCK1_CTRL2 = 0x05,
- LP8758_REG_BUCK2_CTRL1 = 0x06,
- LP8758_REG_BUCK2_CTRL2 = 0x07,
- LP8758_REG_BUCK3_CTRL1 = 0x08,
- LP8758_REG_BUCK3_CTRL2 = 0x09,
- LP8758_REG_BUCK0_VOUT = 0x0a,
- LP8758_REG_BUCK0_FLOORVOUT = 0x0b,
- LP8758_REG_BUCK1_VOUT = 0x0c,
- LP8758_REG_BUCK1_FLOORVOUT = 0x0d,
- LP8758_REG_BUCK2_VOUT = 0x0e,
- LP8758_REG_BUCK2_FLOORVOUT = 0x0f,
- LP8758_REG_BUCK3_VOUT = 0x10,
- LP8758_REG_BUCK3_FLOORVOUT = 0x11,
- LP8758_REG_BUCK0_DELAY = 0x12,
- LP8758_REG_BUCK1_DELAY = 0x13,
- LP8758_REG_BUCK2_DELAY = 0x14,
- LP8758_REG_BUCK3_DELAY = 0x15,
- LP8758_REG_RESET = 0x16,
- LP8758_REG_CONFIG = 0x17,
- LP8758_REG_INT_TOP = 0x18,
- LP8758_REG_INT_BUCK_0_1 = 0x19,
- LP8758_REG_INT_BUCK_2_3 = 0x1a,
- LP8758_REG_STAT_TOP = 0x1b,
- LP8758_REG_STAT_BUCK_0_1 = 0x1c,
- LP8758_REG_STAT_BUCK_2_3 = 0x1d,
- LP8758_REG_MASK_TOP = 0x1e,
- LP8758_REG_MASK_BUCK_0_1 = 0x1f,
- LP8758_REG_MASK_BUCK_2_3 = 0x20,
- LP8758_REG_SEL_I_LOAD = 0x21,
- LP8758_REG_SEL_I_LOAD_2 = 0x22,
- LP8758_REG_SEL_I_LOAD_1 = 0x23,
- LP8758_REG_MAX = 0xff
-};
-
-#define LP8758_BUCK_EN_MASK 0x80
-#define LP8758_BUCK_VOUT_MASK 0xff
-
-/*
- * 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 LP8758_EVENT_PWR_FAULT REGULATOR_EVENT_FAIL
-#define LP8758_EVENT_OCP REGULATOR_EVENT_OVER_CURRENT
-#define LP8758_EVENT_OVP 0x10000
-#define LP8758_EVENT_TEMP_WARN 0x2000
-#define LP8758_EVENT_TEMP_SHDN REGULATOR_EVENT_OVER_TEMP
-#define LP8758_EVENT_I_LOAD 0x40000
-
-#define LP8758_BUCK0INT_MASK 0x10
-#define LP8758_BUCK1INT_MASK 0x20
-#define LP8758_BUCK2INT_MASK 0x40
-#define LP8758_BUCK3INT_MASK 0x80
-#define LP8758_OVERTEMP_MASK 0x08
-#define LP8758_OVERCURRENT_MASK 0x01
-
-#define LP8758_ILIM_MASK 0x38
-#define LP8758_ILIM_SHIFT 3
-
-/* struct lp8758 platform data
- * @buck_data : buck0~6 init voltage in uV
- */
-struct lp8758_platform_data {
-
- struct regulator_init_data *buck_data[LP8758_BUCK_MAX];
-};
-
-#endif /* __LINUX_LP8758_H */
diff --git a/include/linux/regulator/lp872x.h b/include/linux/regulator/lp872x.h
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2012 Texas Instruments
+ *
+ * Author: Milo(Woogyom) Kim <milo.kim@ti.com>
+ *
+ * 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 __LP872X_REGULATOR_H__
+#define __LP872X_REGULATOR_H__
+
+#include <linux/regulator/machine.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+
+#define LP872X_MAX_REGULATORS 9
+
+enum lp872x_regulator_id {
+ LP8720_ID_BASE,
+ LP8720_ID_LDO1 = LP8720_ID_BASE,
+ LP8720_ID_LDO2,
+ LP8720_ID_LDO3,
+ LP8720_ID_LDO4,
+ LP8720_ID_LDO5,
+ LP8720_ID_BUCK,
+
+ LP8725_ID_BASE,
+ LP8725_ID_LDO1 = LP8725_ID_BASE,
+ LP8725_ID_LDO2,
+ LP8725_ID_LDO3,
+ LP8725_ID_LDO4,
+ LP8725_ID_LDO5,
+ LP8725_ID_LILO1,
+ LP8725_ID_LILO2,
+ LP8725_ID_BUCK1,
+ LP8725_ID_BUCK2,
+
+ LP872X_ID_MAX,
+};
+
+enum lp872x_dvs_state {
+ DVS_LOW = GPIOF_OUT_INIT_LOW,
+ DVS_HIGH = GPIOF_OUT_INIT_HIGH,
+};
+
+enum lp872x_dvs_sel {
+ SEL_V1,
+ SEL_V2,
+};
+
+/**
+ * lp872x_dvs
+ * @gpio : gpio pin number for dvs control
+ * @vsel : dvs selector for buck v1 or buck v2 register
+ * @init_state : initial dvs pin state
+ */
+struct lp872x_dvs {
+ int gpio;
+ enum lp872x_dvs_sel vsel;
+ enum lp872x_dvs_state init_state;
+};
+
+/**
+ * lp872x_regdata
+ * @id : regulator id
+ * @init_data : init data for each regulator
+ */
+struct lp872x_regulator_data {
+ enum lp872x_regulator_id id;
+ struct regulator_init_data *init_data;
+};
+
+/**
+ * lp872x_platform_data
+ * @general_config : the value of LP872X_GENERAL_CFG register
+ * @update_config : if LP872X_GENERAL_CFG register is updated, set true
+ * @regulator_data : platform regulator id and init data
+ * @dvs : dvs data for buck voltage control
+ */
+struct lp872x_platform_data {
+ u8 general_config;
+ bool update_config;
+ struct lp872x_regulator_data regulator_data[LP872X_MAX_REGULATORS];
+ struct lp872x_dvs *dvs;
+};
+
+#endif
diff --git a/include/linux/regulator/lp8758.h b/include/linux/regulator/lp8758.h
--- /dev/null
@@ -0,0 +1,194 @@
+/*
+ * Simple driver for Texas Instruments lp8758 Regulator chip
+ * Copyright (C) 2015 Texas Instruments
+ *
+ * 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 __LINUX_LP8758_H
+#define __LINUX_LP8758_H
+
+#include <linux/regulator/consumer.h>
+
+#define LP8758_NAME "lp8758"
+#define LP8758_ADDR 0x60
+
+enum lp8758_otp_id {
+ LP8758_B0 = 0xb0,
+ LP8758_D0 = 0xd0,
+ LP8758_E0 = 0xe0,
+ LP8758_F0 = 0xf0
+};
+
+enum lp8758_sub_version {
+ LP8758_SUB_VER_B0 = 0,
+ LP8758_SUB_VER_D0,
+ LP8758_SUB_VER_E0,
+ LP8758_SUB_VER_F0,
+ LP8758_SUB_VER_MAX
+};
+
+enum lp8758_bucks {
+ LP8758_BUCK0 = 0,
+ LP8758_BUCK1,
+ LP8758_BUCK2,
+ LP8758_BUCK3,
+ LP8758_BUCK_MAX
+};
+
+/*
+ * MODE0 : Pin Ctrl disable
+ * MODE1 : Pin1 Ctrl + Enable/Disable
+ * MODE2 : Pin1 Ctrl + Roof/Floor
+ * MODE3 : Pin2 Ctrl + Enable/Diasble
+ * MODE4 : Pin2 Ctrl + Roof/Floor
+ */
+enum lp8758_ctrl_mode {
+ LP8758_CTRL_MODE0 = 0,
+ LP8758_CTRL_MODE1,
+ LP8758_CTRL_MODE2,
+ LP8758_CTRL_MODE3,
+ LP8758_CTRL_MODE4,
+ LP8758_CTRL_MAX
+};
+
+enum lp8758_buck_mode {
+ LP8758_BUCK_MASTER = 0,
+ LP8758_BUCK_SLAVE
+};
+
+enum lp8758_op_mode {
+ LP8758_BUCK_OP_AUTO = 0x00,
+ LP8758_BUCK_OP_FPWM = 0x02,
+};
+
+enum lp8758_registers {
+ LP8758_REG_DEV_REV = 0x00,
+ LP8758_REG_OTP_REV = 0x01,
+ LP8758_REG_BUCK0_CTRL1 = 0x02,
+ LP8758_REG_BUCK0_CTRL2 = 0x03,
+ LP8758_REG_BUCK1_CTRL1 = 0x04,
+ LP8758_REG_BUCK1_CTRL2 = 0x05,
+ LP8758_REG_BUCK2_CTRL1 = 0x06,
+ LP8758_REG_BUCK2_CTRL2 = 0x07,
+ LP8758_REG_BUCK3_CTRL1 = 0x08,
+ LP8758_REG_BUCK3_CTRL2 = 0x09,
+ LP8758_REG_BUCK0_VOUT = 0x0a,
+ LP8758_REG_BUCK0_FLOORVOUT = 0x0b,
+ LP8758_REG_BUCK1_VOUT = 0x0c,
+ LP8758_REG_BUCK1_FLOORVOUT = 0x0d,
+ LP8758_REG_BUCK2_VOUT = 0x0e,
+ LP8758_REG_BUCK2_FLOORVOUT = 0x0f,
+ LP8758_REG_BUCK3_VOUT = 0x10,
+ LP8758_REG_BUCK3_FLOORVOUT = 0x11,
+ LP8758_REG_BUCK0_DELAY = 0x12,
+ LP8758_REG_BUCK1_DELAY = 0x13,
+ LP8758_REG_BUCK2_DELAY = 0x14,
+ LP8758_REG_BUCK3_DELAY = 0x15,
+ LP8758_REG_RESET = 0x16,
+ LP8758_REG_CONFIG = 0x17,
+ LP8758_REG_INT_TOP = 0x18,
+ LP8758_REG_INT_BUCK_01 = 0x19,
+ LP8758_REG_INT_BUCK_23 = 0x1a,
+ LP8758_REG_STAT_TOP = 0x1b,
+ LP8758_REG_STAT_BUCK_01 = 0x1c,
+ LP8758_REG_STAT_BUCK_23 = 0x1d,
+ LP8758_REG_MASK_TOP = 0x1e,
+ LP8758_REG_MASK_BUCK_01 = 0x1f,
+ LP8758_REG_MASK_BUCK_23 = 0x20,
+ LP8758_REG_SEL_I_LOAD = 0x21,
+ LP8758_REG_SEL_I_LOAD_2 = 0x22,
+ LP8758_REG_SEL_I_LOAD_1 = 0x23,
+ LP8758_REG_MAX = 0xff
+};
+
+/*
+ * 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 LP8758_EVENT_PWR_FAULT REGULATOR_EVENT_FAIL
+#define LP8758_EVENT_OCP REGULATOR_EVENT_OVER_CURRENT
+#define LP8758_EVENT_OVP 0x10000
+#define LP8758_EVENT_TEMP_WARN 0x2000
+#define LP8758_EVENT_TEMP_SHDN REGULATOR_EVENT_OVER_TEMP
+#define LP8758_EVENT_I_LOAD 0x40000
+
+#define LP8758_INT_BUCK01_MASK 0x30
+#define LP8758_INT_BUCK23_MASK 0xc0
+#define LP8758_INT_TEMP_SHDN_MASK 0x08
+#define LP8758_INT_TEMP_WARN_MASK 0x04
+
+/* Over Current interrupt mask */
+#define LP8758_INT_OVC_BUCK0_MASK 0x01
+#define LP8758_INT_OVC_BUCK1_MASK 0x10
+#define LP8758_INT_OVC_BUCK2_MASK 0x01
+#define LP8758_INT_OVC_BUCK3_MASK 0x10
+/* Short Circuit interrupt mask */
+#define LP8758_INT_SC_BUCK0_MASK 0x02
+#define LP8758_INT_SC_BUCK1_MASK 0x20
+#define LP8758_INT_SC_BUCK2_MASK 0x02
+#define LP8758_INT_SC_BUCK3_MASK 0x20
+/* Power Ground Reach interrupt mask */
+#define LP8758_INT_PG_BUCK0_MASK 0x04
+#define LP8758_INT_PG_BUCK1_MASK 0x40
+#define LP8758_INT_PG_BUCK2_MASK 0x04
+#define LP8758_INT_PG_BUCK3_MASK 0x40
+
+#define LP8758_INT_TMEP_MASK\
+ (LP8758_INT_TEMP_WARN_MASK | LP8758_INT_TEMP_SHDN_MASK)
+#define LP8758_INT_PWR_FAULT_BUCK0_MASK\
+ (LP8758_INT_SC_BUCK0_MASK | LP8758_INT_SC_BUCK0_MASK)
+#define LP8758_INT_PWR_FAULT_BUCK1_MASK\
+ (LP8758_INT_SC_BUCK1_MASK | LP8758_INT_SC_BUCK1_MASK)
+#define LP8758_INT_PWR_FAULT_BUCK2_MASK\
+ (LP8758_INT_SC_BUCK2_MASK | LP8758_INT_SC_BUCK2_MASK)
+#define LP8758_INT_PWR_FAULT_BUCK3_MASK\
+ (LP8758_INT_SC_BUCK3_MASK | LP8758_INT_SC_BUCK3_MASK)
+
+#define LP8758_INT_CLEAR_TOP 0x0f
+#define LP8758_INT_CLEAR_BUCK 0x77
+
+#define LP8758_ILIM_MASK 0x38
+#define LP8758_ILIM_SHIFT 3
+
+#define LP8758_BUCK_EN_MASK 0x80
+#define LP8758_BUCK_VOUT_MASK 0xff
+
+#define LP8758_CTRL_BUCK_MASK 0x70
+#define LP8758_CTRL_BUCK_SHIFT 4
+#define LP8758_CTRL_PIN_EN_MASK 0x04
+
+#define LP8758_BUCK_RAMP_MASK 0x07
+#define LP8758_BUCK_OP_MODE_MASK 0x04
+
+/*
+ * struct lp8758 platform data
+ * @irq : irq number
+ * @sub_version : otp version 0-b0, 1-d0, 2-e0, 3-f0
+ * @buck_ctrl[] : [0] buck0 buck control config.
+ * [1] buck1 buck control config.
+ * [2] buck2 buck control config.
+ * [3] buck3 buck control config.
+ * control config
+ * : 0 - EN_BUCK bit only
+ * : 1 - EN_BUCK bit & EN_PIN1 ENABLE/DISABLE
+ * : 2 - EN_BUCK bit & EN_PIN1 ROOF/FLOOR
+ * : 3 - EN_BUCK bit & EN_PIN2 ENABLE/DISABLE
+ * : 4 - EN_BUCK bit & EN_PIN2 ROOF/FLOOR
+ * @buck_data : init buck data
+ */
+struct lp8758_platform_data {
+
+ int irq;
+ u32 sub_version;
+ u32 buck_ctrl[LP8758_BUCK_MAX];
+ struct regulator_init_data *buck_data[LP8758_BUCK_MAX];
+};
+#endif /* __LINUX_LP8758_H */