LP8758 - consolidated version
[mlp-open-source/kernel.git] / drivers / regulator / lp8758.c
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 */
@@ -88,22 +80,42 @@ static const unsigned int lp8758_current_limit_uA[] = {
        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,
@@ -112,24 +124,17 @@ 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;
@@ -139,22 +144,13 @@ static int lp8758_buck_get_current_limit(struct regulator_dev *rdev)
 {
        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;
 }
@@ -194,28 +187,69 @@ static unsigned int lp8758_buck_get_mode(struct regulator_dev *rdev)
        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,
@@ -227,38 +261,138 @@ static struct regulator_ops lp8758_buck_ops = {
        .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;
@@ -273,7 +407,7 @@ static int lp8758_regulator_init(struct lp8758_chip *pchip)
                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;
@@ -281,7 +415,6 @@ static int lp8758_regulator_init(struct lp8758_chip *pchip)
                                                "regulator init failed: buck %d\n",     icnt);
                        return ret;
                }
-               dev_info(pchip->dev, "lp8758 regulator %d\n is registered",icnt);
        }
        return 0;
 }
@@ -289,20 +422,53 @@ static int lp8758_regulator_init(struct lp8758_chip *pchip)
 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;
 }
 
@@ -310,17 +476,18 @@ static int lp8758_intr_config(struct lp8758_chip *pchip)
 {
        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;
@@ -329,22 +496,21 @@ static int lp8758_intr_config(struct lp8758_chip *pchip)
        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);
@@ -353,17 +519,31 @@ static int lp8758_parse_dt(struct i2c_client *client,
                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;
 }
 
@@ -384,7 +564,6 @@ static int lp8758_probe(struct i2c_client *client,
        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;
@@ -405,7 +584,6 @@ static int lp8758_probe(struct i2c_client *client,
        ret = lp8758_parse_dt(client, pchip);
        if(ret < 0)
                return ret;
-
        pchip->dev = &client->dev;
        i2c_set_clientdata(client, pchip);
 
@@ -415,6 +593,12 @@ static int lp8758_probe(struct i2c_client *client,
                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");