On Wed, 27 Sep 2017, Kever Yang wrote:

From: Elaine Zhang <zhangq...@rock-chips.com>

Add Rockchip pmic rk816 support.

RK816 have 4 DCDC, 6 LDO, RTC, CHARGER, FUEL GAUGE, GPIO, PWRKEY.
The DCDC and LDO voltage output range and current loading are different
from RK808 and RK818.
RK816 add mask bit for enable/disable for read/write safety.

The RK816 most used with rk312x/rk322x/rk332x SoCs.

Signed-off-by: Elaine Zhang <zhangq...@rock-chips.com>
Signed-off-by: Kever Yang <kever.y...@rock-chips.com>

The changes I requested (https://patchwork.ozlabs.org/patch/813297/) to to split this up (so we avoid having different logic in a switch/case for every function have not been addressed).

The RK816 apparently is different enough from the RK808 and RK816 to warrant a separate DM driver.

Our basic rule-of-thumb for deciding when to split a driver should be whether the new device can be added using driverdata containing parameters or whether we end up adding new conditional and exclusive code-paths (i.e. if there's a conditional statement in the middle that just adds/removes one step of processing, when this certainly won't justify splitting a driver) to the overwhelming number of the ops.

Please split this to introduce a new driver for the RK816 and keep the existing driver as simple as it is today.

---

Changes in v2:
- add introduce info for RK816 in commit message

drivers/power/pmic/rk8xx.c      |   1 +
drivers/power/regulator/rk8xx.c | 212 ++++++++++++++++++++++++++++++++--------
include/power/rk8xx_pmic.h      |   9 +-
3 files changed, 182 insertions(+), 40 deletions(-)

diff --git a/drivers/power/pmic/rk8xx.c b/drivers/power/pmic/rk8xx.c
index eb3ec0f..0fdea95 100644
--- a/drivers/power/pmic/rk8xx.c
+++ b/drivers/power/pmic/rk8xx.c
@@ -100,6 +100,7 @@ static struct dm_pmic_ops rk8xx_ops = {

static const struct udevice_id rk8xx_ids[] = {
        { .compatible = "rockchip,rk808" },
+       { .compatible = "rockchip,rk816" },
        { .compatible = "rockchip,rk818" },
        { }
};
diff --git a/drivers/power/regulator/rk8xx.c b/drivers/power/regulator/rk8xx.c
index 76fc2ef..cf3566e 100644
--- a/drivers/power/regulator/rk8xx.c
+++ b/drivers/power/regulator/rk8xx.c
@@ -48,6 +48,21 @@ static const struct rk8xx_reg_info rk808_buck[] = {
        { 1800000, 100000, REG_BUCK4_ON_VSEL, RK808_BUCK4_VSEL_MASK, },
};

+static const struct rk8xx_reg_info rk816_buck[] = {
+       /* buck 1 */
+       { 712500, 12500, REG_BUCK1_ON_VSEL, RK818_BUCK_VSEL_MASK, },
+       { 1800000, 200000, REG_BUCK1_ON_VSEL, RK818_BUCK_VSEL_MASK, },
+       { 2300000, 0, REG_BUCK1_ON_VSEL, RK818_BUCK_VSEL_MASK, },
+       /* buck 2 */
+       { 712500, 12500, REG_BUCK2_ON_VSEL, RK818_BUCK_VSEL_MASK, },
+       { 1800000, 200000, REG_BUCK2_ON_VSEL, RK818_BUCK_VSEL_MASK, },
+       { 2300000, 0, REG_BUCK2_ON_VSEL, RK818_BUCK_VSEL_MASK, },
+       /* buck 3 */
+       { 712500, 12500, -1, RK818_BUCK_VSEL_MASK, },
+       /* buck 4 */
+       { 800000, 100000, REG_BUCK4_ON_VSEL, RK818_BUCK4_VSEL_MASK, },
+};
+
static const struct rk8xx_reg_info rk818_buck[] = {
        { 712500, 12500, REG_BUCK1_ON_VSEL, RK818_BUCK_VSEL_MASK, },
        { 712500, 12500, REG_BUCK2_ON_VSEL, RK818_BUCK_VSEL_MASK, },
@@ -67,6 +82,15 @@ static const struct rk8xx_reg_info rk808_ldo[] = {
        { 1800000, 100000, REG_LDO8_ON_VSEL, RK808_LDO_VSEL_MASK, },
};

+static const struct rk8xx_reg_info rk816_ldo[] = {
+       { 800000, 100000, REG_LDO1_ON_VSEL, RK818_LDO_VSEL_MASK, },
+       { 800000, 100000, REG_LDO2_ON_VSEL, RK818_LDO_VSEL_MASK, },
+       { 800000, 100000, REG_LDO3_ON_VSEL, RK818_LDO_VSEL_MASK, },
+       { 800000, 100000, REG_LDO4_ON_VSEL, RK818_LDO_VSEL_MASK, },
+       { 800000, 100000, REG_LDO5_ON_VSEL, RK818_LDO_VSEL_MASK, },
+       { 800000, 100000, REG_LDO6_ON_VSEL, RK818_LDO_VSEL_MASK, },
+};
+
static const struct rk8xx_reg_info rk818_ldo[] = {
        { 1800000, 100000, REG_LDO1_ON_VSEL, RK818_LDO_VSEL_MASK, },
        { 1800000, 100000, REG_LDO2_ON_VSEL, RK818_LDO_VSEL_MASK, },
@@ -88,10 +112,24 @@ static const uint rk818_chrg_shutdown_vsel_array[] = {
};

static const struct rk8xx_reg_info *get_buck_reg(struct udevice *pmic,
-                                            int num)
+                                                int num, int uvolt)
{
        struct rk8xx_priv *priv = dev_get_priv(pmic);
+
        switch (priv->variant) {
+       case RK816_ID:
+               switch (num) {
+               case 0:
+               case 1:
+                       if (uvolt <= 1450000)
+                               return &rk816_buck[num * 3 + 0];
+                       else if (uvolt <= 2200000)
+                               return &rk816_buck[num * 3 + 1];
+                       else
+                               return &rk816_buck[num * 3 + 2];
+               default:
+                       return &rk816_buck[num + 4];
+               }
        case RK818_ID:
                return &rk818_buck[num];
        default:
@@ -101,7 +139,7 @@ static const struct rk8xx_reg_info *get_buck_reg(struct 
udevice *pmic,

static int _buck_set_value(struct udevice *pmic, int buck, int uvolt)
{
-       const struct rk8xx_reg_info *info = get_buck_reg(pmic, buck - 1);
+       const struct rk8xx_reg_info *info = get_buck_reg(pmic, buck, uvolt);
        int mask = info->vsel_mask;
        int val;

@@ -114,23 +152,76 @@ static int _buck_set_value(struct udevice *pmic, int 
buck, int uvolt)
        return pmic_clrsetbits(pmic, info->vsel_reg, mask, val);
}

+static int _buck_get_enable(struct udevice *pmic, int buck)
+{
+       struct rk8xx_priv *priv = dev_get_priv(pmic);
+       uint mask = 0;
+       int ret = 0;
+
+       switch (priv->variant) {
+       case RK816_ID:
+               if (buck >= 4) {
+                       mask = 1 << (buck - 4);
+                       ret = pmic_reg_read(pmic, RK816_REG_DCDC_EN2);
+               } else {
+                       mask = 1 << buck;
+                       ret = pmic_reg_read(pmic, RK816_REG_DCDC_EN1);
+               }
+               break;
+       case RK808_ID:
+       case RK818_ID:
+               mask = 1 << buck;
+               ret = pmic_reg_read(pmic, REG_DCDC_EN);
+               if (ret < 0)
+                       return ret;
+               break;
+       }
+       return ret & mask ? true : false;
+}
+
+
static int _buck_set_enable(struct udevice *pmic, int buck, bool enable)
{
-       uint mask;
+       uint mask, value, en_reg;
        int ret;
+       struct rk8xx_priv *priv = dev_get_priv(pmic);

-       buck--;
-       mask = 1 << buck;
-       if (enable) {
-               ret = pmic_clrsetbits(pmic, REG_DCDC_ILMAX, 0, 3 << (buck * 2));
-               if (ret)
-                       return ret;
-               ret = pmic_clrsetbits(pmic, REG_DCDC_UV_ACT, 1 << buck, 0);
-               if (ret)
-                       return ret;
+       switch (priv->variant) {
+       case RK816_ID:
+               if (buck >= 4) {
+                       buck -= 4;
+                       en_reg = RK816_REG_DCDC_EN2;
+               } else {
+                       en_reg = RK816_REG_DCDC_EN1;
+               }
+               if (enable)
+                       value = ((1 << buck) | (1 << (buck + 4)));
+               else
+                       value = ((0 << buck) | (1 << (buck + 4)));
+               ret = pmic_reg_write(pmic, en_reg, value);
+               break;
+
+       case RK808_ID:
+       case RK818_ID:
+               mask = 1 << buck;
+               if (enable) {
+                       ret = pmic_clrsetbits(pmic, REG_DCDC_ILMAX,
+                                             0, 3 << (buck * 2));
+                       if (ret)
+                               return ret;
+                       ret = pmic_clrsetbits(pmic, REG_DCDC_UV_ACT,
+                                             1 << buck, 0);
+                       if (ret)
+                               return ret;
+               }
+               ret = pmic_clrsetbits(pmic, REG_DCDC_EN, mask,
+                                     enable ? mask : 0);
+               break;
+       default:
+               ret = -EINVAL;
        }

-       return pmic_clrsetbits(pmic, REG_DCDC_EN, mask, enable ? mask : 0);
+       return ret;
}

#ifdef ENABLE_DRIVER
@@ -138,7 +229,10 @@ static const struct rk8xx_reg_info *get_ldo_reg(struct 
udevice *pmic,
                                             int num)
{
        struct rk8xx_priv *priv = dev_get_priv(pmic);
+
        switch (priv->variant) {
+       case RK816_ID:
+               return &rk816_ldo[num];
        case RK818_ID:
                return &rk818_ldo[num];
        default:
@@ -146,10 +240,70 @@ static const struct rk8xx_reg_info *get_ldo_reg(struct 
udevice *pmic,
        }
}

+static int _ldo_get_enable(struct udevice *pmic, int ldo)
+{
+       struct rk8xx_priv *priv = dev_get_priv(pmic);
+       uint mask = 0;
+       int ret = 0;
+
+       switch (priv->variant) {
+       case RK816_ID:
+               if (ldo >= 4) {
+                       mask = 1 << (ldo - 4);
+                       ret = pmic_reg_read(pmic, RK816_REG_LDO_EN2);
+               } else {
+                       mask = 1 << ldo;
+                       ret = pmic_reg_read(pmic, RK816_REG_LDO_EN1);
+               }
+               break;
+       case RK808_ID:
+       case RK818_ID:
+               mask = 1 << ldo;
+               ret = pmic_reg_read(pmic, REG_LDO_EN);
+               if (ret < 0)
+                       return ret;
+               break;
+       }
+       return ret & mask ? true : false;
+}
+
+
+static int _ldo_set_enable(struct udevice *pmic, int ldo, bool enable)
+{
+       struct rk8xx_priv *priv = dev_get_priv(pmic);
+       uint mask, value, en_reg;
+       int ret = 0;
+
+       switch (priv->variant) {
+       case RK816_ID:
+               if (ldo >= 4) {
+                       ldo -= 4;
+                       en_reg = RK816_REG_LDO_EN2;
+               } else {
+                       en_reg = RK816_REG_LDO_EN1;
+               }
+               if (enable)
+                       value = ((1 << ldo) | (1 << (ldo + 4)));
+               else
+                       value = ((0 << ldo) | (1 << (ldo + 4)));
+
+               ret = pmic_reg_write(pmic, en_reg, value);
+               break;
+       case RK808_ID:
+       case RK818_ID:
+               mask = 1 << ldo;
+               ret = pmic_clrsetbits(pmic, REG_LDO_EN, mask,
+                                      enable ? mask : 0);
+               break;
+       }
+
+       return ret;
+}
+
static int buck_get_value(struct udevice *dev)
{
        int buck = dev->driver_data - 1;
-       const struct rk8xx_reg_info *info = get_buck_reg(dev->parent, buck);
+       const struct rk8xx_reg_info *info = get_buck_reg(dev->parent, buck, 0);
        int mask = info->vsel_mask;
        int ret, val;

@@ -165,14 +319,14 @@ static int buck_get_value(struct udevice *dev)

static int buck_set_value(struct udevice *dev, int uvolt)
{
-       int buck = dev->driver_data;
+       int buck = dev->driver_data - 1;

        return _buck_set_value(dev->parent, buck, uvolt);
}

static int buck_set_enable(struct udevice *dev, bool enable)
{
-       int buck = dev->driver_data;
+       int buck = dev->driver_data - 1;

        return _buck_set_enable(dev->parent, buck, enable);
}
@@ -180,16 +334,8 @@ static int buck_set_enable(struct udevice *dev, bool 
enable)
static int buck_get_enable(struct udevice *dev)
{
        int buck = dev->driver_data - 1;
-       int ret;
-       uint mask;
-
-       mask = 1 << buck;

-       ret = pmic_reg_read(dev->parent, REG_DCDC_EN);
-       if (ret < 0)
-               return ret;
-
-       return ret & mask ? true : false;
+       return _buck_get_enable(dev->parent, buck);
}

static int ldo_get_value(struct udevice *dev)
@@ -228,27 +374,15 @@ static int ldo_set_value(struct udevice *dev, int uvolt)
static int ldo_set_enable(struct udevice *dev, bool enable)
{
        int ldo = dev->driver_data - 1;
-       uint mask;
-
-       mask = 1 << ldo;

-       return pmic_clrsetbits(dev->parent, REG_LDO_EN, mask,
-                              enable ? mask : 0);
+       return _ldo_set_enable(dev->parent, ldo, enable);
}

static int ldo_get_enable(struct udevice *dev)
{
        int ldo = dev->driver_data - 1;
-       int ret;
-       uint mask;
-
-       mask = 1 << ldo;

-       ret = pmic_reg_read(dev->parent, REG_LDO_EN);
-       if (ret < 0)
-               return ret;
-
-       return ret & mask ? true : false;
+       return _ldo_get_enable(dev->parent, ldo);
}

static int switch_set_enable(struct udevice *dev, bool enable)
diff --git a/include/power/rk8xx_pmic.h b/include/power/rk8xx_pmic.h
index 47a6b36..8e821c3 100644
--- a/include/power/rk8xx_pmic.h
+++ b/include/power/rk8xx_pmic.h
@@ -171,8 +171,15 @@ enum {
};

enum {
-       RK805_ID = 0x8050,
+       RK816_REG_DCDC_EN1 = 0x23,
+       RK816_REG_DCDC_EN2,
+       RK816_REG_LDO_EN1 = 0x27,
+       RK816_REG_LDO_EN2,
+};
+
+enum {
        RK808_ID = 0x0000,
+       RK816_ID = 0x8160,
        RK818_ID = 0x8180,
};


_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot

Reply via email to