]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/commitdiff
Merge tag 'v3.5-rc4' into regulator-drivers
authorMark Brown <broonie@opensource.wolfsonmicro.com>
Mon, 25 Jun 2012 09:11:40 +0000 (10:11 +0100)
committerMark Brown <broonie@opensource.wolfsonmicro.com>
Mon, 25 Jun 2012 09:11:40 +0000 (10:11 +0100)
Linux 3.5-rc4 contains patches which conflict with some of the
development work.

1  2 
drivers/regulator/anatop-regulator.c
drivers/regulator/core.c
drivers/regulator/palmas-regulator.c
drivers/regulator/s5m8767.c

index 4324cea0114105bdc2078eda03695b646741b8fe,e82e7eaac0f18fd2a50ba3d5506c5620e3e50183..e9c2085f9dfbe0993c6931c573efb52a660f06a0
@@@ -43,15 -43,33 +43,15 @@@ struct anatop_regulator 
        struct regulator_init_data *initdata;
  };
  
 -static int anatop_set_voltage(struct regulator_dev *reg, int min_uV,
 -                                int max_uV, unsigned *selector)
 +static int anatop_set_voltage_sel(struct regulator_dev *reg, unsigned selector)
  {
        struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg);
 -      u32 val, sel, mask;
 -      int uv;
 -
 -      uv = min_uV;
 -      dev_dbg(&reg->dev, "%s: uv %d, min %d, max %d\n", __func__,
 -              uv, anatop_reg->min_voltage,
 -              anatop_reg->max_voltage);
 -
 -      if (uv < anatop_reg->min_voltage) {
 -              if (max_uV > anatop_reg->min_voltage)
 -                      uv = anatop_reg->min_voltage;
 -              else
 -                      return -EINVAL;
 -      }
 +      u32 val, mask;
  
        if (!anatop_reg->control_reg)
                return -ENOTSUPP;
  
 -      sel = DIV_ROUND_UP(uv - anatop_reg->min_voltage, 25000);
 -      if (sel * 25000 + anatop_reg->min_voltage > anatop_reg->max_voltage)
 -              return -EINVAL;
 -      val = anatop_reg->min_bit_val + sel;
 -      *selector = sel;
 +      val = anatop_reg->min_bit_val + selector;
        dev_dbg(&reg->dev, "%s: calculated val %d\n", __func__, val);
        mask = ((1 << anatop_reg->vol_bit_width) - 1) <<
                anatop_reg->vol_bit_shift;
@@@ -76,11 -94,21 +76,11 @@@ static int anatop_get_voltage_sel(struc
        return val - anatop_reg->min_bit_val;
  }
  
 -static int anatop_list_voltage(struct regulator_dev *reg, unsigned selector)
 -{
 -      struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg);
 -      int uv;
 -
 -      uv = anatop_reg->min_voltage + selector * 25000;
 -      dev_dbg(&reg->dev, "vddio = %d, selector = %u\n", uv, selector);
 -
 -      return uv;
 -}
 -
  static struct regulator_ops anatop_rops = {
 -      .set_voltage     = anatop_set_voltage,
 +      .set_voltage_sel = anatop_set_voltage_sel,
        .get_voltage_sel = anatop_get_voltage_sel,
 -      .list_voltage    = anatop_list_voltage,
 +      .list_voltage = regulator_list_voltage_linear,
 +      .map_voltage = regulator_map_voltage_linear,
  };
  
  static int __devinit anatop_regulator_probe(struct platform_device *pdev)
  
        rdesc->n_voltages = (sreg->max_voltage - sreg->min_voltage)
                / 25000 + 1;
 +      rdesc->min_uV = sreg->min_voltage;
 +      rdesc->uV_step = 25000;
  
        config.dev = &pdev->dev;
        config.init_data = initdata;
@@@ -198,7 -224,7 +198,7 @@@ static struct platform_driver anatop_re
                .of_match_table = of_anatop_regulator_match_tbl,
        },
        .probe  = anatop_regulator_probe,
-       .remove = anatop_regulator_remove,
+       .remove = __devexit_p(anatop_regulator_remove),
  };
  
  static int __init anatop_regulator_init(void)
diff --combined drivers/regulator/core.c
index e3597ab09be34f8440058dfbc16d42d6071b322d,09a737c868b573227d22226926a081f35a29e6b2..aa82c0465f4f35ccd1811cf42dbf9c1913850168
@@@ -967,14 -967,6 +967,14 @@@ static int set_machine_constraints(stru
                }
        }
  
 +      if (rdev->constraints->ramp_delay && ops->set_ramp_delay) {
 +              ret = ops->set_ramp_delay(rdev, rdev->constraints->ramp_delay);
 +              if (ret < 0) {
 +                      rdev_err(rdev, "failed to set ramp_delay\n");
 +                      goto out;
 +              }
 +      }
 +
        print_constraints(rdev);
        return 0;
  out:
@@@ -1467,7 -1459,7 +1467,7 @@@ void devm_regulator_put(struct regulato
  {
        int rc;
  
 -      rc = devres_destroy(regulator->dev, devm_regulator_release,
 +      rc = devres_release(regulator->dev, devm_regulator_release,
                            devm_regulator_match, regulator);
        if (rc == 0)
                regulator_put(regulator);
@@@ -1890,31 -1882,6 +1890,31 @@@ int regulator_list_voltage_linear(struc
  }
  EXPORT_SYMBOL_GPL(regulator_list_voltage_linear);
  
 +/**
 + * regulator_list_voltage_table - List voltages with table based mapping
 + *
 + * @rdev: Regulator device
 + * @selector: Selector to convert into a voltage
 + *
 + * Regulators with table based mapping between voltages and
 + * selectors can set volt_table in the regulator descriptor
 + * and then use this function as their list_voltage() operation.
 + */
 +int regulator_list_voltage_table(struct regulator_dev *rdev,
 +                               unsigned int selector)
 +{
 +      if (!rdev->desc->volt_table) {
 +              BUG_ON(!rdev->desc->volt_table);
 +              return -EINVAL;
 +      }
 +
 +      if (selector >= rdev->desc->n_voltages)
 +              return -EINVAL;
 +
 +      return rdev->desc->volt_table[selector];
 +}
 +EXPORT_SYMBOL_GPL(regulator_list_voltage_table);
 +
  /**
   * regulator_list_voltage - enumerate supported voltages
   * @regulator: regulator source
@@@ -2078,19 -2045,14 +2078,22 @@@ int regulator_map_voltage_linear(struc
  {
        int ret, voltage;
  
 +      /* Allow uV_step to be 0 for fixed voltage */
 +      if (rdev->desc->n_voltages == 1 && rdev->desc->uV_step == 0) {
 +              if (min_uV <= rdev->desc->min_uV && rdev->desc->min_uV <= max_uV)
 +                      return 0;
 +              else
 +                      return -EINVAL;
 +      }
 +
        if (!rdev->desc->uV_step) {
                BUG_ON(!rdev->desc->uV_step);
                return -EINVAL;
        }
  
+       if (min_uV < rdev->desc->min_uV)
+               min_uV = rdev->desc->min_uV;
        ret = DIV_ROUND_UP(min_uV - rdev->desc->min_uV, rdev->desc->uV_step);
        if (ret < 0)
                return ret;
@@@ -2122,8 -2084,7 +2125,8 @@@ static int _regulator_do_set_voltage(st
         * If we can't obtain the old selector there is not enough
         * info to call set_voltage_time_sel().
         */
 -      if (rdev->desc->ops->set_voltage_time_sel &&
 +      if (_regulator_is_enabled(rdev) &&
 +          rdev->desc->ops->set_voltage_time_sel &&
            rdev->desc->ops->get_voltage_sel) {
                old_selector = rdev->desc->ops->get_voltage_sel(rdev);
                if (old_selector < 0)
                best_val = -1;
  
        /* Call set_voltage_time_sel if successfully obtained old_selector */
 -      if (ret == 0 && old_selector >= 0 &&
 +      if (_regulator_is_enabled(rdev) && ret == 0 && old_selector >= 0 &&
            rdev->desc->ops->set_voltage_time_sel) {
  
                delay = rdev->desc->ops->set_voltage_time_sel(rdev,
@@@ -2287,46 -2248,6 +2290,46 @@@ int regulator_set_voltage_time(struct r
  }
  EXPORT_SYMBOL_GPL(regulator_set_voltage_time);
  
 +/**
 + *regulator_set_voltage_time_sel - get raise/fall time
 + * @regulator: regulator source
 + * @old_selector: selector for starting voltage
 + * @new_selector: selector for target voltage
 + *
 + * Provided with the starting and target voltage selectors, this function
 + * returns time in microseconds required to rise or fall to this new voltage
 + *
 + * Drivers providing ramp_delay in regulation_constraints can use this as their
 + * set_voltage_time_sel() operation.
 + */
 +int regulator_set_voltage_time_sel(struct regulator_dev *rdev,
 +                                 unsigned int old_selector,
 +                                 unsigned int new_selector)
 +{
 +      unsigned int ramp_delay = 0;
 +      int old_volt, new_volt;
 +
 +      if (rdev->constraints->ramp_delay)
 +              ramp_delay = rdev->constraints->ramp_delay;
 +      else if (rdev->desc->ramp_delay)
 +              ramp_delay = rdev->desc->ramp_delay;
 +
 +      if (ramp_delay == 0) {
 +              rdev_warn(rdev, "ramp_delay not set\n");
 +              return 0;
 +      }
 +
 +      /* sanity check */
 +      if (!rdev->desc->ops->list_voltage)
 +              return -EINVAL;
 +
 +      old_volt = rdev->desc->ops->list_voltage(rdev, old_selector);
 +      new_volt = rdev->desc->ops->list_voltage(rdev, new_selector);
 +
 +      return DIV_ROUND_UP(abs(new_volt - old_volt), ramp_delay);
 +}
 +EXPORT_SYMBOL_GPL(regulator_set_voltage_time_sel);
 +
  /**
   * regulator_sync_voltage - re-apply last regulator output voltage
   * @regulator: regulator source
@@@ -3184,10 -3105,7 +3187,10 @@@ regulator_register(const struct regulat
        rdev->reg_data = config->driver_data;
        rdev->owner = regulator_desc->owner;
        rdev->desc = regulator_desc;
 -      rdev->regmap = config->regmap;
 +      if (config->regmap)
 +              rdev->regmap = config->regmap;
 +      else
 +              rdev->regmap = dev_get_regmap(dev, NULL);
        INIT_LIST_HEAD(&rdev->consumer_list);
        INIT_LIST_HEAD(&rdev->list);
        BLOCKING_INIT_NOTIFIER_HEAD(&rdev->notifier);
index 55267bbfcd9ce5e55837308c816e1b3d9b722d17,9b7ca90057d53806c581387bba8c6ab72ae46826..6c485116dd2a5ecb44e1feb5db5eca660dd55947
@@@ -257,7 -257,8 +257,7 @@@ static int palmas_set_mode_smps(struct 
        unsigned int reg;
  
        palmas_smps_read(pmic->palmas, palmas_regs_info[id].ctrl_addr, &reg);
 -      reg &= ~PALMAS_SMPS12_CTRL_STATUS_MASK;
 -      reg >>= PALMAS_SMPS12_CTRL_STATUS_SHIFT;
 +      reg &= ~PALMAS_SMPS12_CTRL_MODE_ACTIVE_MASK;
  
        switch (mode) {
        case REGULATOR_MODE_NORMAL:
@@@ -399,14 -400,19 +399,14 @@@ static struct regulator_ops palmas_ops_
        .map_voltage            = palmas_map_voltage_smps,
  };
  
 -static int palmas_list_voltage_smps10(struct regulator_dev *dev,
 -                                      unsigned selector)
 -{
 -      return 3750000 + (selector * 1250000);
 -}
 -
  static struct regulator_ops palmas_ops_smps10 = {
        .is_enabled             = regulator_is_enabled_regmap,
        .enable                 = regulator_enable_regmap,
        .disable                = regulator_disable_regmap,
        .get_voltage_sel        = regulator_get_voltage_sel_regmap,
        .set_voltage_sel        = regulator_set_voltage_sel_regmap,
 -      .list_voltage           = palmas_list_voltage_smps10,
 +      .list_voltage           = regulator_list_voltage_linear,
 +      .map_voltage            = regulator_map_voltage_linear,
  };
  
  static int palmas_is_enabled_ldo(struct regulator_dev *dev)
@@@ -516,15 -522,7 +516,15 @@@ static int palmas_smps_init(struct palm
        if (ret)
                return ret;
  
 -      if (id != PALMAS_REG_SMPS10) {
 +      switch (id) {
 +      case PALMAS_REG_SMPS10:
 +              if (reg_init->mode_sleep) {
 +                      reg &= ~PALMAS_SMPS10_CTRL_MODE_SLEEP_MASK;
 +                      reg |= reg_init->mode_sleep <<
 +                                      PALMAS_SMPS10_CTRL_MODE_SLEEP_SHIFT;
 +              }
 +              break;
 +      default:
                if (reg_init->warm_reset)
                        reg |= PALMAS_SMPS12_CTRL_WR_S;
  
                        reg |= reg_init->mode_sleep <<
                                        PALMAS_SMPS12_CTRL_MODE_SLEEP_SHIFT;
                }
 -      } else {
 -              if (reg_init->mode_sleep) {
 -                      reg &= ~PALMAS_SMPS10_CTRL_MODE_SLEEP_MASK;
 -                      reg |= reg_init->mode_sleep <<
 -                                      PALMAS_SMPS10_CTRL_MODE_SLEEP_SHIFT;
 -              }
 -
        }
 +
        ret = palmas_smps_write(palmas, addr, reg);
        if (ret)
                return ret;
@@@ -661,20 -665,16 +661,20 @@@ static __devinit int palmas_probe(struc
                pmic->desc[id].name = palmas_regs_info[id].name;
                pmic->desc[id].id = id;
  
 -              if (id != PALMAS_REG_SMPS10) {
 -                      pmic->desc[id].ops = &palmas_ops_smps;
 -                      pmic->desc[id].n_voltages = PALMAS_SMPS_NUM_VOLTAGES;
 -              } else {
 +              switch (id) {
 +              case PALMAS_REG_SMPS10:
                        pmic->desc[id].n_voltages = PALMAS_SMPS10_NUM_VOLTAGES;
                        pmic->desc[id].ops = &palmas_ops_smps10;
                        pmic->desc[id].vsel_reg = PALMAS_SMPS10_CTRL;
                        pmic->desc[id].vsel_mask = SMPS10_VSEL;
                        pmic->desc[id].enable_reg = PALMAS_SMPS10_STATUS;
                        pmic->desc[id].enable_mask = SMPS10_BOOST_EN;
 +                      pmic->desc[id].min_uV = 3750000;
 +                      pmic->desc[id].uV_step = 1250000;
 +                      break;
 +              default:
 +                      pmic->desc[id].ops = &palmas_ops_smps;
 +                      pmic->desc[id].n_voltages = PALMAS_SMPS_NUM_VOLTAGES;
                }
  
                pmic->desc[id].type = REGULATOR_VOLTAGE;
  err_unregister_regulator:
        while (--id >= 0)
                regulator_unregister(pmic->rdev[id]);
-       kfree(pmic->rdev);
-       kfree(pmic->desc);
-       kfree(pmic);
        return ret;
  }
  
@@@ -788,10 -785,6 +785,6 @@@ static int __devexit palmas_remove(stru
  
        for (id = 0; id < PALMAS_NUM_REGS; id++)
                regulator_unregister(pmic->rdev[id]);
-       kfree(pmic->rdev);
-       kfree(pmic->desc);
-       kfree(pmic);
        return 0;
  }
  
index fd89574c405ccdd00f37191382677025139c2847,9caadb4821786308aa624e9ef03cd7408dc2083f..22642c3ccf76cebf3e200006278e591599472614
@@@ -41,7 -41,6 +41,7 @@@ struct s5m8767_info 
        u8 buck3_vol[8];
        u8 buck4_vol[8];
        int buck_gpios[3];
 +      int buck_ds[3];
        int buck_gpioindex;
  };
  
@@@ -284,17 -283,17 +284,17 @@@ static int s5m8767_get_voltage_register
                reg = S5M8767_REG_BUCK1CTRL2;
                break;
        case S5M8767_BUCK2:
 -              reg = S5M8767_REG_BUCK2DVS1;
 +              reg = S5M8767_REG_BUCK2DVS2;
                if (s5m8767->buck2_gpiodvs)
                        reg += s5m8767->buck_gpioindex;
                break;
        case S5M8767_BUCK3:
 -              reg = S5M8767_REG_BUCK3DVS1;
 +              reg = S5M8767_REG_BUCK3DVS2;
                if (s5m8767->buck3_gpiodvs)
                        reg += s5m8767->buck_gpioindex;
                break;
        case S5M8767_BUCK4:
 -              reg = S5M8767_REG_BUCK4DVS1;
 +              reg = S5M8767_REG_BUCK4DVS2;
                if (s5m8767->buck4_gpiodvs)
                        reg += s5m8767->buck_gpioindex;
                break;
@@@ -358,34 -357,32 +358,34 @@@ static int s5m8767_convert_voltage_to_s
        return selector;
  }
  
 -static inline void s5m8767_set_high(struct s5m8767_info *s5m8767)
 +static inline int s5m8767_set_high(struct s5m8767_info *s5m8767)
  {
        int temp_index = s5m8767->buck_gpioindex;
  
        gpio_set_value(s5m8767->buck_gpios[0], (temp_index >> 2) & 0x1);
        gpio_set_value(s5m8767->buck_gpios[1], (temp_index >> 1) & 0x1);
        gpio_set_value(s5m8767->buck_gpios[2], temp_index & 0x1);
 +
 +      return 0;
  }
  
 -static inline void s5m8767_set_low(struct s5m8767_info *s5m8767)
 +static inline int s5m8767_set_low(struct s5m8767_info *s5m8767)
  {
        int temp_index = s5m8767->buck_gpioindex;
  
        gpio_set_value(s5m8767->buck_gpios[2], temp_index & 0x1);
        gpio_set_value(s5m8767->buck_gpios[1], (temp_index >> 1) & 0x1);
        gpio_set_value(s5m8767->buck_gpios[0], (temp_index >> 2) & 0x1);
 +
 +      return 0;
  }
  
 -static int s5m8767_set_voltage(struct regulator_dev *rdev,
 -                              int min_uV, int max_uV, unsigned *selector)
 +static int s5m8767_set_voltage_sel(struct regulator_dev *rdev,
 +                                 unsigned selector)
  {
        struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev);
 -      const struct s5m_voltage_desc *desc;
        int reg_id = rdev_get_id(rdev);
 -      int sel, reg, mask, ret = 0, old_index, index = 0;
 -      u8 val;
 +      int reg, mask, ret = 0, old_index, index = 0;
        u8 *buck234_vol = NULL;
  
        switch (reg_id) {
                return -EINVAL;
        }
  
 -      desc = reg_voltage_map[reg_id];
 -
 -      sel = s5m8767_convert_voltage_to_sel(desc, min_uV, max_uV);
 -      if (sel < 0)
 -              return sel;
 -
        /* buck234_vol != NULL means to control buck234 voltage via DVS GPIO */
        if (buck234_vol) {
 -              while (*buck234_vol != sel) {
 +              while (*buck234_vol != selector) {
                        buck234_vol++;
                        index++;
                }
                s5m8767->buck_gpioindex = index;
  
                if (index > old_index)
 -                      s5m8767_set_high(s5m8767);
 +                      return s5m8767_set_high(s5m8767);
                else
 -                      s5m8767_set_low(s5m8767);
 +                      return s5m8767_set_low(s5m8767);
        } else {
                ret = s5m8767_get_voltage_register(rdev, &reg);
                if (ret)
                        return ret;
  
 -              s5m_reg_read(s5m8767->iodev, reg, &val);
 -              val = (val & ~mask) | sel;
 -
 -              ret = s5m_reg_write(s5m8767->iodev, reg, val);
 +              return s5m_reg_update(s5m8767->iodev, reg, selector, mask);
        }
 -
 -      *selector = sel;
 -      return ret;
  }
  
  static int s5m8767_set_voltage_time_sel(struct regulator_dev *rdev,
  
        desc = reg_voltage_map[reg_id];
  
-       if (old_sel < new_sel)
+       if ((old_sel < new_sel) && s5m8767->ramp_delay)
                return DIV_ROUND_UP(desc->step * (new_sel - old_sel),
                                        s5m8767->ramp_delay * 1000);
        return 0;
@@@ -454,7 -463,7 +454,7 @@@ static struct regulator_ops s5m8767_op
        .enable                 = s5m8767_reg_enable,
        .disable                = s5m8767_reg_disable,
        .get_voltage_sel        = s5m8767_get_voltage_sel,
 -      .set_voltage            = s5m8767_set_voltage,
 +      .set_voltage_sel        = s5m8767_set_voltage_sel,
        .set_voltage_time_sel   = s5m8767_set_voltage_time_sel,
  };
  
@@@ -513,7 -522,7 +513,7 @@@ static __devinit int s5m8767_pmic_probe
        struct regulator_config config = { };
        struct regulator_dev **rdev;
        struct s5m8767_info *s5m8767;
 -      int i, ret, size;
 +      int i, ret, size, buck_init;
  
        if (!pdata) {
                dev_err(pdev->dev.parent, "Platform data not supplied\n");
        s5m8767->buck_gpios[0] = pdata->buck_gpios[0];
        s5m8767->buck_gpios[1] = pdata->buck_gpios[1];
        s5m8767->buck_gpios[2] = pdata->buck_gpios[2];
 +      s5m8767->buck_ds[0] = pdata->buck_ds[0];
 +      s5m8767->buck_ds[1] = pdata->buck_ds[1];
 +      s5m8767->buck_ds[2] = pdata->buck_ds[2];
 +
        s5m8767->ramp_delay = pdata->buck_ramp_delay;
        s5m8767->buck2_ramp = pdata->buck2_ramp_enable;
        s5m8767->buck3_ramp = pdata->buck3_ramp_enable;
        s5m8767->buck4_ramp = pdata->buck4_ramp_enable;
        s5m8767->opmode = pdata->opmode;
  
 +      buck_init = s5m8767_convert_voltage_to_sel(&buck_voltage_val2,
 +                                              pdata->buck2_init,
 +                                              pdata->buck2_init +
 +                                              buck_voltage_val2.step);
 +
 +      s5m_reg_write(s5m8767->iodev, S5M8767_REG_BUCK2DVS2, buck_init);
 +
 +      buck_init = s5m8767_convert_voltage_to_sel(&buck_voltage_val2,
 +                                              pdata->buck3_init,
 +                                              pdata->buck3_init +
 +                                              buck_voltage_val2.step);
 +
 +      s5m_reg_write(s5m8767->iodev, S5M8767_REG_BUCK3DVS2, buck_init);
 +
 +      buck_init = s5m8767_convert_voltage_to_sel(&buck_voltage_val2,
 +                                              pdata->buck4_init,
 +                                              pdata->buck4_init +
 +                                              buck_voltage_val2.step);
 +
 +      s5m_reg_write(s5m8767->iodev, S5M8767_REG_BUCK4DVS2, buck_init);
 +
        for (i = 0; i < 8; i++) {
                if (s5m8767->buck2_gpiodvs) {
                        s5m8767->buck2_vol[i] =
                }
        }
  
 -      if (pdata->buck2_gpiodvs || pdata->buck3_gpiodvs ||
 -              pdata->buck4_gpiodvs) {
 -              if (gpio_is_valid(pdata->buck_gpios[0]) &&
 -                      gpio_is_valid(pdata->buck_gpios[1]) &&
 -                      gpio_is_valid(pdata->buck_gpios[2])) {
 -                      ret = gpio_request(pdata->buck_gpios[0],
 -                                              "S5M8767 SET1");
 -                      if (ret == -EBUSY)
 -                              dev_warn(&pdev->dev, "Duplicated gpio request for SET1\n");
 -
 -                      ret = gpio_request(pdata->buck_gpios[1],
 -                                         "S5M8767 SET2");
 -                      if (ret == -EBUSY)
 -                              dev_warn(&pdev->dev, "Duplicated gpio request for SET2\n");
 -
 -                      ret = gpio_request(pdata->buck_gpios[2],
 -                                         "S5M8767 SET3");
 -                      if (ret == -EBUSY)
 -                              dev_warn(&pdev->dev, "Duplicated gpio request for SET3\n");
 -                      /* SET1 GPIO */
 -                      gpio_direction_output(pdata->buck_gpios[0],
 -                                      (s5m8767->buck_gpioindex >> 2) & 0x1);
 -                      /* SET2 GPIO */
 -                      gpio_direction_output(pdata->buck_gpios[1],
 -                                      (s5m8767->buck_gpioindex >> 1) & 0x1);
 -                      /* SET3 GPIO */
 -                      gpio_direction_output(pdata->buck_gpios[2],
 -                                      (s5m8767->buck_gpioindex >> 0) & 0x1);
 -                      ret = 0;
 -              } else {
 -                      dev_err(&pdev->dev, "GPIO NOT VALID\n");
 -                      ret = -EINVAL;
 -                      return ret;
 -              }
 +      if (gpio_is_valid(pdata->buck_gpios[0]) &&
 +              gpio_is_valid(pdata->buck_gpios[1]) &&
 +              gpio_is_valid(pdata->buck_gpios[2])) {
 +              ret = gpio_request(pdata->buck_gpios[0], "S5M8767 SET1");
 +              if (ret == -EBUSY)
 +                      dev_warn(&pdev->dev, "Duplicated gpio request"
 +                              " for SET1\n");
 +
 +              ret = gpio_request(pdata->buck_gpios[1], "S5M8767 SET2");
 +              if (ret == -EBUSY)
 +                      dev_warn(&pdev->dev, "Duplicated gpio request"
 +                              " for SET2\n");
 +
 +              ret = gpio_request(pdata->buck_gpios[2], "S5M8767 SET3");
 +              if (ret == -EBUSY)
 +                      dev_warn(&pdev->dev, "Duplicated gpio request"
 +                                      " for SET3\n");
 +              /* SET1 GPIO */
 +              gpio_direction_output(pdata->buck_gpios[0],
 +                              (s5m8767->buck_gpioindex >> 2) & 0x1);
 +              /* SET2 GPIO */
 +              gpio_direction_output(pdata->buck_gpios[1],
 +                              (s5m8767->buck_gpioindex >> 1) & 0x1);
 +              /* SET3 GPIO */
 +              gpio_direction_output(pdata->buck_gpios[2],
 +                              (s5m8767->buck_gpioindex >> 0) & 0x1);
 +              ret = 0;
 +
 +      } else {
 +              dev_err(&pdev->dev, "GPIO NOT VALID\n");
 +              ret = -EINVAL;
 +              return ret;
        }
  
 -      s5m_reg_update(s5m8767->iodev, S5M8767_REG_BUCK2CTRL,
 -                      (pdata->buck2_gpiodvs) ? (1 << 1) : (0 << 1), 1 << 1);
 -      s5m_reg_update(s5m8767->iodev, S5M8767_REG_BUCK3CTRL,
 -                      (pdata->buck3_gpiodvs) ? (1 << 1) : (0 << 1), 1 << 1);
 -      s5m_reg_update(s5m8767->iodev, S5M8767_REG_BUCK4CTRL,
 -                      (pdata->buck4_gpiodvs) ? (1 << 1) : (0 << 1), 1 << 1);
 +      ret = gpio_request(pdata->buck_ds[0], "S5M8767 DS2");
 +      if (ret == -EBUSY)
 +              dev_warn(&pdev->dev, "Duplicated gpio request for DS2\n");
 +
 +      ret = gpio_request(pdata->buck_ds[1], "S5M8767 DS3");
 +      if (ret == -EBUSY)
 +              dev_warn(&pdev->dev, "Duplicated gpio request for DS3\n");
 +
 +      ret = gpio_request(pdata->buck_ds[2], "S5M8767 DS4");
 +      if (ret == -EBUSY)
 +              dev_warn(&pdev->dev, "Duplicated gpio request for DS4\n");
 +
 +      /* DS2 GPIO */
 +      gpio_direction_output(pdata->buck_ds[0], 0x0);
 +      /* DS3 GPIO */
 +      gpio_direction_output(pdata->buck_ds[1], 0x0);
 +      /* DS4 GPIO */
 +      gpio_direction_output(pdata->buck_ds[2], 0x0);
 +
 +      if (pdata->buck2_gpiodvs || pdata->buck3_gpiodvs ||
 +         pdata->buck4_gpiodvs) {
 +              s5m_reg_update(s5m8767->iodev, S5M8767_REG_BUCK2CTRL,
 +                              (pdata->buck2_gpiodvs) ? (1 << 1) : (0 << 1),
 +                              1 << 1);
 +              s5m_reg_update(s5m8767->iodev, S5M8767_REG_BUCK3CTRL,
 +                              (pdata->buck3_gpiodvs) ? (1 << 1) : (0 << 1),
 +                              1 << 1);
 +              s5m_reg_update(s5m8767->iodev, S5M8767_REG_BUCK4CTRL,
 +                              (pdata->buck4_gpiodvs) ? (1 << 1) : (0 << 1),
 +                              1 << 1);
 +      }
  
        /* Initialize GPIO DVS registers */
        for (i = 0; i < 8; i++) {
                                           s5m8767->buck4_vol[i]);
                }
        }
 -      s5m_reg_update(s5m8767->iodev, S5M8767_REG_BUCK2CTRL, 0x78, 0xff);
 -      s5m_reg_update(s5m8767->iodev, S5M8767_REG_BUCK3CTRL, 0x58, 0xff);
 -      s5m_reg_update(s5m8767->iodev, S5M8767_REG_BUCK4CTRL, 0x78, 0xff);
  
        if (s5m8767->buck2_ramp)
                s5m_reg_update(s5m8767->iodev, S5M8767_REG_DVSRAMP, 0x08, 0x08);