12690619bSJoseph Chen /*
22690619bSJoseph Chen * (C) Copyright 2024 Rockchip Electronics Co., Ltd.
32690619bSJoseph Chen *
42690619bSJoseph Chen * SPDX-License-Identifier: GPL-2.0+
52690619bSJoseph Chen */
62690619bSJoseph Chen
72690619bSJoseph Chen #include <common.h>
82690619bSJoseph Chen #include <dm.h>
92690619bSJoseph Chen #include <asm/gpio.h>
102690619bSJoseph Chen #include <power/pmic.h>
112690619bSJoseph Chen #include <power/rk801_pmic.h>
122690619bSJoseph Chen #include <power/regulator.h>
132690619bSJoseph Chen
142690619bSJoseph Chen #define RK801_BUCK_VSEL_MASK 0x7f
152690619bSJoseph Chen #define RK801_LDO_VSEL_MASK 0x3f
162690619bSJoseph Chen #define ENABLE_MASK(id) (BIT(4 + (id)) | BIT(id))
172690619bSJoseph Chen #define ENABLE_VAL(id) (BIT(4 + (id)) | BIT(id))
182690619bSJoseph Chen #define DISABLE_VAL(id) (BIT(4 + (id)) | 0)
192690619bSJoseph Chen
202690619bSJoseph Chen enum {
212690619bSJoseph Chen PM_SLEEP = 0,
222690619bSJoseph Chen PM_RUNTIME = 1,
232690619bSJoseph Chen };
242690619bSJoseph Chen
252690619bSJoseph Chen struct runtime_device {
262690619bSJoseph Chen int reg_src;
272690619bSJoseph Chen int reg_dst;
282690619bSJoseph Chen };
292690619bSJoseph Chen
302690619bSJoseph Chen struct regulator_desc {
312690619bSJoseph Chen int id;
322690619bSJoseph Chen unsigned int min_uV;
332690619bSJoseph Chen unsigned int uV_step;
342690619bSJoseph Chen const struct linear_range *linear_ranges;
352690619bSJoseph Chen int n_linear_ranges;
362690619bSJoseph Chen unsigned int vsel_reg;
372690619bSJoseph Chen unsigned int vsel_mask;
382690619bSJoseph Chen unsigned int enable_reg;
392690619bSJoseph Chen unsigned int enable_mask;
402690619bSJoseph Chen unsigned int enable_val;
412690619bSJoseph Chen unsigned int disable_val;
422690619bSJoseph Chen unsigned int ramp_delay;
432690619bSJoseph Chen };
442690619bSJoseph Chen
452690619bSJoseph Chen struct linear_range {
462690619bSJoseph Chen unsigned int min;
472690619bSJoseph Chen unsigned int min_sel;
482690619bSJoseph Chen unsigned int max_sel;
492690619bSJoseph Chen unsigned int step;
502690619bSJoseph Chen };
512690619bSJoseph Chen
522690619bSJoseph Chen #define REGULATOR_LINEAR_RANGE(_min_uV, _min_sel, _max_sel, _step_uV) \
532690619bSJoseph Chen { \
542690619bSJoseph Chen .min = _min_uV, \
552690619bSJoseph Chen .min_sel = _min_sel, \
562690619bSJoseph Chen .max_sel = _max_sel, \
572690619bSJoseph Chen .step = _step_uV, \
582690619bSJoseph Chen }
592690619bSJoseph Chen
602690619bSJoseph Chen static const struct linear_range rk801_buck1_voltage_ranges[] = {
612690619bSJoseph Chen REGULATOR_LINEAR_RANGE(500000, 0, 80, 12500), /* 0.5v - 1.5v */
622690619bSJoseph Chen REGULATOR_LINEAR_RANGE(1800000, 81, 82, 400000),/* 1.8v - 2.2v */
632690619bSJoseph Chen REGULATOR_LINEAR_RANGE(3300000, 83, 83, 0), /* 3.3v */
642690619bSJoseph Chen REGULATOR_LINEAR_RANGE(5000000, 84, 84, 0), /* 5.0v */
652690619bSJoseph Chen REGULATOR_LINEAR_RANGE(5250000, 85, 85, 0), /* 5.25v */
662690619bSJoseph Chen };
672690619bSJoseph Chen
682690619bSJoseph Chen static const struct linear_range rk801_buck2_voltage_ranges[] = {
692690619bSJoseph Chen REGULATOR_LINEAR_RANGE(800000, 0, 2, 50000), /* 0.8v - 0.9v */
702690619bSJoseph Chen REGULATOR_LINEAR_RANGE(1800000, 3, 4, 400000), /* 1.8v - 2.2v */
712690619bSJoseph Chen REGULATOR_LINEAR_RANGE(3300000, 5, 5, 0), /* 3.3v */
722690619bSJoseph Chen REGULATOR_LINEAR_RANGE(5000000, 6, 6, 0), /* 5.0v */
732690619bSJoseph Chen REGULATOR_LINEAR_RANGE(5250000, 7, 7, 0), /* 5.25v */
742690619bSJoseph Chen };
752690619bSJoseph Chen
762690619bSJoseph Chen static const struct linear_range rk801_buck4_voltage_ranges[] = {
772690619bSJoseph Chen REGULATOR_LINEAR_RANGE(500000, 0, 80, 12500), /* 0.5v - 1.5v */
782690619bSJoseph Chen REGULATOR_LINEAR_RANGE(1800000, 81, 82, 400000),/* 1.8v - 2.2v */
792690619bSJoseph Chen REGULATOR_LINEAR_RANGE(2500000, 83, 83, 0), /* 2.5v */
802690619bSJoseph Chen REGULATOR_LINEAR_RANGE(2800000, 84, 84, 0), /* 2.8v */
812690619bSJoseph Chen REGULATOR_LINEAR_RANGE(3000000, 85, 85, 0), /* 3.0v */
822690619bSJoseph Chen REGULATOR_LINEAR_RANGE(3300000, 86, 86, 0), /* 3.3v */
832690619bSJoseph Chen };
842690619bSJoseph Chen
852690619bSJoseph Chen static const struct linear_range rk801_ldo1_voltage_ranges[] = {
862690619bSJoseph Chen REGULATOR_LINEAR_RANGE(500000, 0, 58, 50000), /* 0.5v - 3.4v */
872690619bSJoseph Chen };
882690619bSJoseph Chen
892690619bSJoseph Chen static const struct linear_range rk801_ldo2_voltage_ranges[] = {
902690619bSJoseph Chen REGULATOR_LINEAR_RANGE(500000, 0, 58, 50000), /* 0.5v - 3.4v */
912690619bSJoseph Chen };
922690619bSJoseph Chen
932690619bSJoseph Chen static const struct regulator_desc rk801_desc[] = {
942690619bSJoseph Chen {
952690619bSJoseph Chen .id = RK801_ID_DCDC1,
962690619bSJoseph Chen .linear_ranges = rk801_buck1_voltage_ranges,
972690619bSJoseph Chen .n_linear_ranges = ARRAY_SIZE(rk801_buck1_voltage_ranges),
982690619bSJoseph Chen .vsel_reg = RK801_BUCK1_ON_VSEL_REG,
992690619bSJoseph Chen .vsel_mask = RK801_BUCK_VSEL_MASK,
1002690619bSJoseph Chen .enable_reg = RK801_POWER_EN0_REG,
1012690619bSJoseph Chen .enable_mask = ENABLE_MASK(RK801_ID_DCDC1),
1022690619bSJoseph Chen .enable_val = ENABLE_VAL(RK801_ID_DCDC1),
1032690619bSJoseph Chen .disable_val = DISABLE_VAL(RK801_ID_DCDC1),
1042690619bSJoseph Chen .ramp_delay = 1, // TODO: +32
1052690619bSJoseph Chen }, {
1062690619bSJoseph Chen .id = RK801_ID_DCDC2,
1072690619bSJoseph Chen .linear_ranges = rk801_buck2_voltage_ranges,
1082690619bSJoseph Chen .n_linear_ranges = ARRAY_SIZE(rk801_buck2_voltage_ranges),
1092690619bSJoseph Chen .vsel_reg = RK801_BUCK2_ON_VSEL_REG,
1102690619bSJoseph Chen .vsel_mask = RK801_BUCK_VSEL_MASK,
1112690619bSJoseph Chen .enable_reg = RK801_POWER_EN0_REG,
1122690619bSJoseph Chen .enable_mask = ENABLE_MASK(RK801_ID_DCDC2),
1132690619bSJoseph Chen .enable_val = ENABLE_VAL(RK801_ID_DCDC2),
1142690619bSJoseph Chen .disable_val = DISABLE_VAL(RK801_ID_DCDC2),
1152690619bSJoseph Chen .ramp_delay = 1,
1162690619bSJoseph Chen }, {
1172690619bSJoseph Chen .id = RK801_ID_DCDC3,
1182690619bSJoseph Chen .enable_reg = RK801_POWER_EN0_REG,
1192690619bSJoseph Chen .enable_mask = ENABLE_MASK(RK801_ID_DCDC3),
1202690619bSJoseph Chen .enable_val = ENABLE_VAL(RK801_ID_DCDC3),
1212690619bSJoseph Chen .disable_val = DISABLE_VAL(RK801_ID_DCDC3),
1222690619bSJoseph Chen }, {
1232690619bSJoseph Chen .id = RK801_ID_DCDC4,
1242690619bSJoseph Chen .linear_ranges = rk801_buck4_voltage_ranges,
1252690619bSJoseph Chen .n_linear_ranges = ARRAY_SIZE(rk801_buck4_voltage_ranges),
1262690619bSJoseph Chen .vsel_reg = RK801_BUCK4_ON_VSEL_REG,
1272690619bSJoseph Chen .vsel_mask = RK801_BUCK_VSEL_MASK,
1282690619bSJoseph Chen .enable_reg = RK801_POWER_EN0_REG,
1292690619bSJoseph Chen .enable_mask = ENABLE_MASK(RK801_ID_DCDC4),
1302690619bSJoseph Chen .enable_val = ENABLE_VAL(RK801_ID_DCDC4),
1312690619bSJoseph Chen .disable_val = DISABLE_VAL(RK801_ID_DCDC4),
1322690619bSJoseph Chen .ramp_delay = 1,
1332690619bSJoseph Chen }, {
1342690619bSJoseph Chen .id = RK801_ID_LDO1,
1352690619bSJoseph Chen .linear_ranges = rk801_ldo1_voltage_ranges,
1362690619bSJoseph Chen .n_linear_ranges = ARRAY_SIZE(rk801_ldo1_voltage_ranges),
1372690619bSJoseph Chen .vsel_reg = RK801_LDO1_ON_VSEL_REG,
1382690619bSJoseph Chen .vsel_mask = RK801_LDO_VSEL_MASK,
1392690619bSJoseph Chen .enable_reg = RK801_POWER_EN1_REG,
1402690619bSJoseph Chen .enable_mask = ENABLE_MASK(0),
1412690619bSJoseph Chen .enable_val = ENABLE_VAL(0),
1422690619bSJoseph Chen .disable_val = DISABLE_VAL(0),
1432690619bSJoseph Chen .ramp_delay = 1,
1442690619bSJoseph Chen }, {
1452690619bSJoseph Chen .id = RK801_ID_LDO2,
1462690619bSJoseph Chen .linear_ranges = rk801_ldo2_voltage_ranges,
1472690619bSJoseph Chen .n_linear_ranges = ARRAY_SIZE(rk801_ldo2_voltage_ranges),
1482690619bSJoseph Chen .vsel_reg = RK801_LDO2_ON_VSEL_REG,
1492690619bSJoseph Chen .vsel_mask = RK801_LDO_VSEL_MASK,
1502690619bSJoseph Chen .enable_reg = RK801_POWER_EN1_REG,
1512690619bSJoseph Chen .enable_mask = ENABLE_MASK(1),
1522690619bSJoseph Chen .enable_val = ENABLE_VAL(1),
1532690619bSJoseph Chen .disable_val = DISABLE_VAL(1),
1542690619bSJoseph Chen .ramp_delay = 1,
1552690619bSJoseph Chen }, {
1562690619bSJoseph Chen .id = RK801_ID_SWITCH,
1572690619bSJoseph Chen .n_linear_ranges = 0,
1582690619bSJoseph Chen .enable_reg = RK801_POWER_EN1_REG,
1592690619bSJoseph Chen .enable_mask = ENABLE_MASK(2),
1602690619bSJoseph Chen .enable_val = ENABLE_VAL(2),
1612690619bSJoseph Chen .disable_val = DISABLE_VAL(2),
1622690619bSJoseph Chen .ramp_delay = 1,
1632690619bSJoseph Chen },
1642690619bSJoseph Chen };
1652690619bSJoseph Chen
linear_range_get_value(const struct linear_range * r,unsigned int selector,unsigned int * val)1662690619bSJoseph Chen static int linear_range_get_value(const struct linear_range *r,
1672690619bSJoseph Chen unsigned int selector, unsigned int *val)
1682690619bSJoseph Chen {
1692690619bSJoseph Chen if (r->min_sel > selector || r->max_sel < selector)
1702690619bSJoseph Chen return -EINVAL;
1712690619bSJoseph Chen
1722690619bSJoseph Chen *val = r->min + (selector - r->min_sel) * r->step;
1732690619bSJoseph Chen
1742690619bSJoseph Chen return 0;
1752690619bSJoseph Chen }
1762690619bSJoseph Chen
linear_range_get_value_array(const struct linear_range * r,int ranges,unsigned int selector,unsigned int * uV)1772690619bSJoseph Chen static int linear_range_get_value_array(const struct linear_range *r, int ranges,
1782690619bSJoseph Chen unsigned int selector, unsigned int *uV)
1792690619bSJoseph Chen {
1802690619bSJoseph Chen int i;
1812690619bSJoseph Chen
1822690619bSJoseph Chen for (i = 0; i < ranges; i++) {
1832690619bSJoseph Chen if (r[i].min_sel <= selector && r[i].max_sel >= selector)
1842690619bSJoseph Chen return linear_range_get_value(&r[i], selector, uV);
1852690619bSJoseph Chen }
1862690619bSJoseph Chen
1872690619bSJoseph Chen return -EINVAL;
1882690619bSJoseph Chen }
1892690619bSJoseph Chen
linear_range_get_max_value(const struct linear_range * r)1902690619bSJoseph Chen static unsigned int linear_range_get_max_value(const struct linear_range *r)
1912690619bSJoseph Chen {
1922690619bSJoseph Chen return r->min + (r->max_sel - r->min_sel) * r->step;
1932690619bSJoseph Chen }
1942690619bSJoseph Chen
linear_range_get_selector_high(const struct linear_range * r,unsigned int val,unsigned int * selector,bool * found)1952690619bSJoseph Chen static int linear_range_get_selector_high(const struct linear_range *r,
1962690619bSJoseph Chen unsigned int val,
1972690619bSJoseph Chen unsigned int *selector,
1982690619bSJoseph Chen bool *found)
1992690619bSJoseph Chen {
2002690619bSJoseph Chen *found = false;
2012690619bSJoseph Chen
2022690619bSJoseph Chen if (linear_range_get_max_value(r) < val)
2032690619bSJoseph Chen return -EINVAL;
2042690619bSJoseph Chen
2052690619bSJoseph Chen if (r->min > val) {
2062690619bSJoseph Chen *selector = r->min_sel;
2072690619bSJoseph Chen return 0;
2082690619bSJoseph Chen }
2092690619bSJoseph Chen
2102690619bSJoseph Chen *found = true;
2112690619bSJoseph Chen
2122690619bSJoseph Chen if (r->step == 0)
2132690619bSJoseph Chen *selector = r->max_sel;
2142690619bSJoseph Chen else
2152690619bSJoseph Chen *selector = DIV_ROUND_UP(val - r->min, r->step) + r->min_sel;
2162690619bSJoseph Chen
2172690619bSJoseph Chen return 0;
2182690619bSJoseph Chen }
2192690619bSJoseph Chen
regulator_map_voltage_linear_range(const struct regulator_desc * desc,int min_uV,int max_uV)2202690619bSJoseph Chen int regulator_map_voltage_linear_range(const struct regulator_desc *desc,
2212690619bSJoseph Chen int min_uV, int max_uV)
2222690619bSJoseph Chen {
2232690619bSJoseph Chen const struct linear_range *range;
2242690619bSJoseph Chen int ret = -EINVAL;
2252690619bSJoseph Chen unsigned int sel;
2262690619bSJoseph Chen bool found;
2272690619bSJoseph Chen uint voltage, i;
2282690619bSJoseph Chen
2292690619bSJoseph Chen if (!desc->n_linear_ranges)
2302690619bSJoseph Chen return -EINVAL;
2312690619bSJoseph Chen
2322690619bSJoseph Chen for (i = 0; i < desc->n_linear_ranges; i++) {
2332690619bSJoseph Chen range = &desc->linear_ranges[i];
2342690619bSJoseph Chen
2352690619bSJoseph Chen ret = linear_range_get_selector_high(range, min_uV, &sel,
2362690619bSJoseph Chen &found);
2372690619bSJoseph Chen if (ret)
2382690619bSJoseph Chen continue;
2392690619bSJoseph Chen
2402690619bSJoseph Chen ret = sel;
2412690619bSJoseph Chen
2422690619bSJoseph Chen /*
2432690619bSJoseph Chen * Map back into a voltage to verify we're still in bounds.
2442690619bSJoseph Chen * If we are not, then continue checking rest of the ranges.
2452690619bSJoseph Chen */
2462690619bSJoseph Chen if (linear_range_get_value_array(desc->linear_ranges,
2472690619bSJoseph Chen desc->n_linear_ranges, sel, &voltage))
2482690619bSJoseph Chen continue;
2492690619bSJoseph Chen
2502690619bSJoseph Chen if (voltage >= min_uV && voltage <= max_uV)
2512690619bSJoseph Chen break;
2522690619bSJoseph Chen }
2532690619bSJoseph Chen
2542690619bSJoseph Chen if (i == desc->n_linear_ranges)
2552690619bSJoseph Chen return -EINVAL;
2562690619bSJoseph Chen
2572690619bSJoseph Chen return ret;
2582690619bSJoseph Chen }
2592690619bSJoseph Chen
rk801_get_desc(struct udevice * dev)2602690619bSJoseph Chen static const struct regulator_desc *rk801_get_desc(struct udevice *dev)
2612690619bSJoseph Chen {
2622690619bSJoseph Chen struct dm_regulator_uclass_platdata *uc_pdata;
2632690619bSJoseph Chen int i, id;
2642690619bSJoseph Chen
2652690619bSJoseph Chen /* Why? Because: RK801_ID_DCDC3=4, RK801_ID_DCDC4=3 */
2662690619bSJoseph Chen uc_pdata = dev_get_uclass_platdata(dev);
2672690619bSJoseph Chen if (uc_pdata->type == REGULATOR_TYPE_BUCK) {
2682690619bSJoseph Chen switch (dev->driver_data) {
2692690619bSJoseph Chen case 1:
2702690619bSJoseph Chen id = RK801_ID_DCDC1;
2712690619bSJoseph Chen break;
2722690619bSJoseph Chen case 2:
2732690619bSJoseph Chen id = RK801_ID_DCDC2;
2742690619bSJoseph Chen break;
2752690619bSJoseph Chen case 3:
2762690619bSJoseph Chen id = RK801_ID_DCDC3;
2772690619bSJoseph Chen break;
2782690619bSJoseph Chen case 4:
2792690619bSJoseph Chen id = RK801_ID_DCDC4;
2802690619bSJoseph Chen break;
2812690619bSJoseph Chen default:
2822690619bSJoseph Chen id = -EINVAL;
2832690619bSJoseph Chen }
2842690619bSJoseph Chen } else if (uc_pdata->type == REGULATOR_TYPE_LDO) {
2852690619bSJoseph Chen switch (dev->driver_data) {
2862690619bSJoseph Chen case 1:
2872690619bSJoseph Chen id = RK801_ID_LDO1;
2882690619bSJoseph Chen break;
2892690619bSJoseph Chen case 2:
2902690619bSJoseph Chen id = RK801_ID_LDO2;
2912690619bSJoseph Chen break;
2922690619bSJoseph Chen default:
2932690619bSJoseph Chen id = -EINVAL;
2942690619bSJoseph Chen }
2952690619bSJoseph Chen } else {
2962690619bSJoseph Chen id = RK801_ID_SWITCH;
2972690619bSJoseph Chen }
2982690619bSJoseph Chen
2992690619bSJoseph Chen if (id != -EINVAL) {
3002690619bSJoseph Chen for (i = 0; i < ARRAY_SIZE(rk801_desc); i++) {
3012690619bSJoseph Chen if (rk801_desc[i].id == id)
3022690619bSJoseph Chen return &rk801_desc[i];
3032690619bSJoseph Chen }
3042690619bSJoseph Chen }
3052690619bSJoseph Chen
3062690619bSJoseph Chen return NULL;
3072690619bSJoseph Chen }
3082690619bSJoseph Chen
rk801_regulator_get_value(struct udevice * dev,bool runtime)3092690619bSJoseph Chen static int rk801_regulator_get_value(struct udevice *dev, bool runtime)
3102690619bSJoseph Chen {
3112690619bSJoseph Chen const struct regulator_desc *desc = rk801_get_desc(dev);
3122690619bSJoseph Chen struct udevice *pmic = dev->parent;
3132690619bSJoseph Chen int sel, val, vsel_reg, ret;
3142690619bSJoseph Chen uint uV;
3152690619bSJoseph Chen
3162690619bSJoseph Chen if (!desc)
3172690619bSJoseph Chen return -ENODEV;
3182690619bSJoseph Chen
3192690619bSJoseph Chen if (desc->id == RK801_ID_DCDC3)
3202690619bSJoseph Chen return -ENOSYS;
3212690619bSJoseph Chen
3222690619bSJoseph Chen if (runtime)
3232690619bSJoseph Chen vsel_reg = desc->vsel_reg;
3242690619bSJoseph Chen else
3252690619bSJoseph Chen vsel_reg = desc->vsel_reg + RK801_SLP_REG_OFFSET;
3262690619bSJoseph Chen
3272690619bSJoseph Chen val = pmic_reg_read(pmic, vsel_reg);
3282690619bSJoseph Chen if (val < 0)
3292690619bSJoseph Chen return val;
3302690619bSJoseph Chen
3312690619bSJoseph Chen sel = (val & desc->vsel_mask) >> (ffs(desc->vsel_mask) - 1);
3322690619bSJoseph Chen ret = linear_range_get_value_array(desc->linear_ranges,
3332690619bSJoseph Chen desc->n_linear_ranges, sel, &uV);
3342690619bSJoseph Chen
3352690619bSJoseph Chen debug("%s, %s, desc[%d]: reg=%02x, ret=%d, sel=0x%02x(%d), uV=%d\n",
3362690619bSJoseph Chen __func__, dev->name, desc->id, vsel_reg, ret, sel, sel, uV);
3372690619bSJoseph Chen
3382690619bSJoseph Chen return ret ? ret : uV;
3392690619bSJoseph Chen }
3402690619bSJoseph Chen
rk801_regulator_set_value(struct udevice * dev,int uV,bool runtime)3412690619bSJoseph Chen static int rk801_regulator_set_value(struct udevice *dev, int uV, bool runtime)
3422690619bSJoseph Chen {
3432690619bSJoseph Chen const struct regulator_desc *desc = rk801_get_desc(dev);
3442690619bSJoseph Chen struct udevice *pmic = dev->parent;
3452690619bSJoseph Chen struct rk801_priv *priv = dev_get_priv(pmic);
3462690619bSJoseph Chen const struct gpio_desc *gpio = &priv->pwrctrl_gpio;
3472690619bSJoseph Chen uint reg, reg0, reg1, sel;
3482690619bSJoseph Chen int ret, gpio_level;
3492690619bSJoseph Chen
3502690619bSJoseph Chen if (!desc)
3512690619bSJoseph Chen return -ENODEV;
3522690619bSJoseph Chen
3532690619bSJoseph Chen if (desc->id == RK801_ID_DCDC3)
3542690619bSJoseph Chen return -ENOSYS;
3552690619bSJoseph Chen
3562690619bSJoseph Chen if (priv->req_pwrctrl_dvs) {
3572690619bSJoseph Chen reg0 = desc->vsel_reg;
3582690619bSJoseph Chen reg1 = desc->vsel_reg + RK801_SLP_REG_OFFSET;
3592690619bSJoseph Chen
3602690619bSJoseph Chen gpio_level = dm_gpio_get_value(gpio);
3612690619bSJoseph Chen reg = (gpio_level == 1) ? reg0 : reg1;
3622690619bSJoseph Chen
3632690619bSJoseph Chen sel = regulator_map_voltage_linear_range(desc, uV, uV);
3642690619bSJoseph Chen if (sel < 0)
3652690619bSJoseph Chen return sel;
3662690619bSJoseph Chen
3672690619bSJoseph Chen sel <<= ffs(desc->vsel_mask) - 1;
3682690619bSJoseph Chen
3692690619bSJoseph Chen debug("%s, %s, desc[%d]: reg=%02x, uV=%d, sel=0x%02x(%d), gpio=%d\n",
3702690619bSJoseph Chen __func__, dev->name, desc->id, reg, uV, sel, sel, gpio_level);
3712690619bSJoseph Chen
3722690619bSJoseph Chen ret = pmic_clrsetbits(pmic, reg, desc->vsel_mask, sel);
3732690619bSJoseph Chen if (ret)
3742690619bSJoseph Chen return ret;
3752690619bSJoseph Chen
3762690619bSJoseph Chen udelay(40); /* hw sync */
3772690619bSJoseph Chen
3782690619bSJoseph Chen dm_gpio_set_value(gpio, !gpio_level);
3792690619bSJoseph Chen
3802690619bSJoseph Chen if (reg == reg0)
3812690619bSJoseph Chen ret = pmic_clrsetbits(pmic, reg1, desc->vsel_mask, sel);
3822690619bSJoseph Chen else
3832690619bSJoseph Chen ret = pmic_clrsetbits(pmic, reg0, desc->vsel_mask, sel);
3842690619bSJoseph Chen
385*5e8035f6SJoseph Chen /* if sleep mode: set pwrctrl pin inactive anyway */
3862690619bSJoseph Chen if (!runtime) {
3872690619bSJoseph Chen dm_gpio_set_value(gpio, 0);
3882690619bSJoseph Chen udelay(40); /* hw sync */
3892690619bSJoseph Chen }
3902690619bSJoseph Chen
3912690619bSJoseph Chen return ret;
3922690619bSJoseph Chen } else {
3932690619bSJoseph Chen if (runtime)
3942690619bSJoseph Chen reg = desc->vsel_reg;
3952690619bSJoseph Chen else
3962690619bSJoseph Chen reg = desc->vsel_reg + RK801_SLP_REG_OFFSET;
3972690619bSJoseph Chen
3982690619bSJoseph Chen sel = regulator_map_voltage_linear_range(desc, uV, uV);
3992690619bSJoseph Chen if (sel < 0)
4002690619bSJoseph Chen return sel;
4012690619bSJoseph Chen
4022690619bSJoseph Chen debug("%s, %s, desc[%d]: reg=%02x, uV=%d, sel=0x%02x(%d)\n",
4032690619bSJoseph Chen __func__, dev->name, desc->id, reg, uV, sel, sel);
4042690619bSJoseph Chen
4052690619bSJoseph Chen sel <<= ffs(desc->vsel_mask) - 1;
4062690619bSJoseph Chen
4072690619bSJoseph Chen return pmic_clrsetbits(pmic, reg, desc->vsel_mask, sel);
4082690619bSJoseph Chen }
4092690619bSJoseph Chen }
4102690619bSJoseph Chen
rk801_regulator_get_enable(struct udevice * dev,bool runtime)4112690619bSJoseph Chen static int rk801_regulator_get_enable(struct udevice *dev, bool runtime)
4122690619bSJoseph Chen {
4132690619bSJoseph Chen const struct regulator_desc *desc = rk801_get_desc(dev);
4142690619bSJoseph Chen struct udevice *pmic = dev->parent;
4152690619bSJoseph Chen int val;
4162690619bSJoseph Chen
4172690619bSJoseph Chen if (!desc)
4182690619bSJoseph Chen return -ENODEV;
4192690619bSJoseph Chen
4202690619bSJoseph Chen if (runtime) {
4212690619bSJoseph Chen val = pmic_reg_read(pmic, desc->enable_reg);
4222690619bSJoseph Chen if (val < 0)
4232690619bSJoseph Chen return val;
4242690619bSJoseph Chen
4252690619bSJoseph Chen val &= desc->enable_mask;
4262690619bSJoseph Chen
4272690619bSJoseph Chen return val == desc->enable_val;
4282690619bSJoseph Chen } else {
4292690619bSJoseph Chen val = pmic_reg_read(pmic, RK801_POWER_SLP_EN_REG);
4302690619bSJoseph Chen if (val < 0)
4312690619bSJoseph Chen return val;
4322690619bSJoseph Chen
4332690619bSJoseph Chen return (val & BIT(desc->id));
4342690619bSJoseph Chen }
4352690619bSJoseph Chen }
4362690619bSJoseph Chen
rk801_regulator_set_enable(struct udevice * dev,bool enable)4372690619bSJoseph Chen static int rk801_regulator_set_enable(struct udevice *dev, bool enable)
4382690619bSJoseph Chen {
4392690619bSJoseph Chen const struct regulator_desc *desc = rk801_get_desc(dev);
4402690619bSJoseph Chen struct udevice *pmic = dev->parent;
4412690619bSJoseph Chen int val;
4422690619bSJoseph Chen
4432690619bSJoseph Chen if (!desc)
4442690619bSJoseph Chen return -ENODEV;
4452690619bSJoseph Chen
4462690619bSJoseph Chen val = enable ? desc->enable_val : desc->disable_val;
4472690619bSJoseph Chen
4482690619bSJoseph Chen debug("%s, %s, desc[%d]: reg=%02x, mask=%02x, enable=%d, val=0x%02x(%d)\n",
4492690619bSJoseph Chen __func__, dev->name, desc->id, desc->enable_reg,
4502690619bSJoseph Chen desc->enable_mask, enable, val, val);
4512690619bSJoseph Chen
4522690619bSJoseph Chen return pmic_clrsetbits(pmic, desc->enable_reg, desc->enable_mask, val);
4532690619bSJoseph Chen }
4542690619bSJoseph Chen
rk801_regulator_set_suspend_enable(struct udevice * dev,bool enable)4552690619bSJoseph Chen static int rk801_regulator_set_suspend_enable(struct udevice *dev, bool enable)
4562690619bSJoseph Chen {
4572690619bSJoseph Chen const struct regulator_desc *desc = rk801_get_desc(dev);
4582690619bSJoseph Chen struct udevice *pmic = dev->parent;
4592690619bSJoseph Chen
4602690619bSJoseph Chen if (!desc)
4612690619bSJoseph Chen return -ENODEV;
4622690619bSJoseph Chen
4632690619bSJoseph Chen debug("%s, %s, desc[%d]: reg=%02x, mask=%02lx, enable=0x%02x, val=0x%02lx\n",
4642690619bSJoseph Chen __func__, dev->name, desc->id, RK801_POWER_SLP_EN_REG,
4652690619bSJoseph Chen BIT(desc->id), enable, BIT(desc->id));
4662690619bSJoseph Chen
4672690619bSJoseph Chen return pmic_clrsetbits(pmic, RK801_POWER_SLP_EN_REG,
4682690619bSJoseph Chen BIT(desc->id), BIT(desc->id));
4692690619bSJoseph Chen }
4702690619bSJoseph Chen
buck_ldo_get_value(struct udevice * dev)4712690619bSJoseph Chen static int buck_ldo_get_value(struct udevice *dev)
4722690619bSJoseph Chen {
4732690619bSJoseph Chen return rk801_regulator_get_value(dev, PM_RUNTIME);
4742690619bSJoseph Chen }
4752690619bSJoseph Chen
buck_ldo_set_value(struct udevice * dev,int uV)4762690619bSJoseph Chen static int buck_ldo_set_value(struct udevice *dev, int uV)
4772690619bSJoseph Chen {
4782690619bSJoseph Chen return rk801_regulator_set_value(dev, uV, PM_RUNTIME);
4792690619bSJoseph Chen }
4802690619bSJoseph Chen
buck_ldo_get_enable(struct udevice * dev)4812690619bSJoseph Chen static int buck_ldo_get_enable(struct udevice *dev)
4822690619bSJoseph Chen {
4832690619bSJoseph Chen return rk801_regulator_get_enable(dev, PM_RUNTIME);
4842690619bSJoseph Chen }
4852690619bSJoseph Chen
buck_ldo_set_enable(struct udevice * dev,bool enable)4862690619bSJoseph Chen static int buck_ldo_set_enable(struct udevice *dev, bool enable)
4872690619bSJoseph Chen {
4882690619bSJoseph Chen struct rk801_priv *priv = dev_get_priv(dev->parent);
4892690619bSJoseph Chen int ret;
4902690619bSJoseph Chen
4912690619bSJoseph Chen ret = rk801_regulator_set_enable(dev, enable);
4922690619bSJoseph Chen if (ret)
4932690619bSJoseph Chen return ret;
4942690619bSJoseph Chen
4952690619bSJoseph Chen if (priv->req_pwrctrl_dvs)
4962690619bSJoseph Chen return rk801_regulator_set_suspend_enable(dev, enable);
4972690619bSJoseph Chen
4982690619bSJoseph Chen return 0;
4992690619bSJoseph Chen }
5002690619bSJoseph Chen
buck_ldo_get_suspend_value(struct udevice * dev)5012690619bSJoseph Chen static int buck_ldo_get_suspend_value(struct udevice *dev)
5022690619bSJoseph Chen {
5032690619bSJoseph Chen return rk801_regulator_get_value(dev, PM_SLEEP);
5042690619bSJoseph Chen }
5052690619bSJoseph Chen
buck_ldo_set_suspend_value(struct udevice * dev,int uV)5062690619bSJoseph Chen static int buck_ldo_set_suspend_value(struct udevice *dev, int uV)
5072690619bSJoseph Chen {
5082690619bSJoseph Chen return rk801_regulator_set_value(dev, uV, PM_SLEEP);
5092690619bSJoseph Chen }
5102690619bSJoseph Chen
buck_ldo_get_suspend_enable(struct udevice * dev)5112690619bSJoseph Chen static int buck_ldo_get_suspend_enable(struct udevice *dev)
5122690619bSJoseph Chen {
5132690619bSJoseph Chen return rk801_regulator_get_enable(dev, PM_SLEEP);
5142690619bSJoseph Chen }
5152690619bSJoseph Chen
buck_ldo_set_suspend_enable(struct udevice * dev,bool enable)5162690619bSJoseph Chen static int buck_ldo_set_suspend_enable(struct udevice *dev, bool enable)
5172690619bSJoseph Chen {
5182690619bSJoseph Chen struct rk801_priv *priv = dev_get_priv(dev->parent);
5192690619bSJoseph Chen int ret;
5202690619bSJoseph Chen
5212690619bSJoseph Chen ret = rk801_regulator_set_suspend_enable(dev, enable);
5222690619bSJoseph Chen if (ret)
5232690619bSJoseph Chen return ret;
5242690619bSJoseph Chen
5252690619bSJoseph Chen if (priv->req_pwrctrl_dvs)
5262690619bSJoseph Chen return rk801_regulator_set_enable(dev, enable);
5272690619bSJoseph Chen
5282690619bSJoseph Chen return 0;
5292690619bSJoseph Chen }
5302690619bSJoseph Chen
buck_ldo_get_ramp_delay(struct udevice * dev,int old_uV,int new_uV)5312690619bSJoseph Chen int buck_ldo_get_ramp_delay(struct udevice *dev, int old_uV, int new_uV)
5322690619bSJoseph Chen {
5332690619bSJoseph Chen const struct regulator_desc *desc = rk801_get_desc(dev);
5342690619bSJoseph Chen struct dm_regulator_uclass_platdata *uc_pdata;
5352690619bSJoseph Chen
5362690619bSJoseph Chen if (!desc)
5372690619bSJoseph Chen return 0;
5382690619bSJoseph Chen
5392690619bSJoseph Chen uc_pdata = dev_get_uclass_platdata(dev);
5402690619bSJoseph Chen if (uc_pdata->type != REGULATOR_TYPE_BUCK)
5412690619bSJoseph Chen return 0;
5422690619bSJoseph Chen
5432690619bSJoseph Chen return abs(new_uV - old_uV) / 1000 + 32;
5442690619bSJoseph Chen }
5452690619bSJoseph Chen
switch_set_enable(struct udevice * dev,bool enable)5462690619bSJoseph Chen static int switch_set_enable(struct udevice *dev, bool enable)
5472690619bSJoseph Chen {
5482690619bSJoseph Chen return buck_ldo_set_enable(dev, enable);
5492690619bSJoseph Chen }
5502690619bSJoseph Chen
switch_get_enable(struct udevice * dev)5512690619bSJoseph Chen static int switch_get_enable(struct udevice *dev)
5522690619bSJoseph Chen {
5532690619bSJoseph Chen return rk801_regulator_get_enable(dev, PM_RUNTIME);
5542690619bSJoseph Chen }
5552690619bSJoseph Chen
switch_set_suspend_enable(struct udevice * dev,bool enable)5562690619bSJoseph Chen static int switch_set_suspend_enable(struct udevice *dev, bool enable)
5572690619bSJoseph Chen {
5582690619bSJoseph Chen return buck_ldo_set_suspend_enable(dev, enable);
5592690619bSJoseph Chen }
5602690619bSJoseph Chen
switch_get_suspend_enable(struct udevice * dev)5612690619bSJoseph Chen static int switch_get_suspend_enable(struct udevice *dev)
5622690619bSJoseph Chen {
5632690619bSJoseph Chen return rk801_regulator_get_enable(dev, PM_SLEEP);
5642690619bSJoseph Chen }
5652690619bSJoseph Chen
switch_get_value(struct udevice * dev)5662690619bSJoseph Chen static int switch_get_value(struct udevice *dev)
5672690619bSJoseph Chen {
5682690619bSJoseph Chen return 0;
5692690619bSJoseph Chen }
5702690619bSJoseph Chen
switch_set_value(struct udevice * dev,int uV)5712690619bSJoseph Chen static int switch_set_value(struct udevice *dev, int uV)
5722690619bSJoseph Chen {
5732690619bSJoseph Chen return 0;
5742690619bSJoseph Chen }
5752690619bSJoseph Chen
switch_set_suspend_value(struct udevice * dev,int uV)5762690619bSJoseph Chen static int switch_set_suspend_value(struct udevice *dev, int uV)
5772690619bSJoseph Chen {
5782690619bSJoseph Chen return 0;
5792690619bSJoseph Chen }
5802690619bSJoseph Chen
switch_get_suspend_value(struct udevice * dev)5812690619bSJoseph Chen static int switch_get_suspend_value(struct udevice *dev)
5822690619bSJoseph Chen {
5832690619bSJoseph Chen return 0;
5842690619bSJoseph Chen }
5852690619bSJoseph Chen
rk801_buck_probe(struct udevice * dev)5862690619bSJoseph Chen static int rk801_buck_probe(struct udevice *dev)
5872690619bSJoseph Chen {
588*5e8035f6SJoseph Chen struct rk801_priv *priv = dev_get_priv(dev->parent);
5892690619bSJoseph Chen struct dm_regulator_uclass_platdata *uc_pdata;
5902690619bSJoseph Chen struct udevice *pmic = dev->parent;
5912690619bSJoseph Chen struct runtime_device rdev[] = {
5922690619bSJoseph Chen { RK801_BUCK1_ON_VSEL_REG, RK801_BUCK1_SLP_VSEL_REG },
5932690619bSJoseph Chen { RK801_BUCK2_ON_VSEL_REG, RK801_BUCK2_SLP_VSEL_REG },
5942690619bSJoseph Chen { RK801_BUCK4_ON_VSEL_REG, RK801_BUCK4_SLP_VSEL_REG },
5952690619bSJoseph Chen { RK801_LDO1_ON_VSEL_REG, RK801_LDO1_SLP_VSEL_REG },
5962690619bSJoseph Chen { RK801_LDO2_ON_VSEL_REG, RK801_LDO2_SLP_VSEL_REG },
5972690619bSJoseph Chen };
5982690619bSJoseph Chen uint val, en0, en1;
5992690619bSJoseph Chen int i, ret;
6002690619bSJoseph Chen
6012690619bSJoseph Chen uc_pdata = dev_get_uclass_platdata(dev);
6022690619bSJoseph Chen uc_pdata->type = REGULATOR_TYPE_BUCK;
6032690619bSJoseph Chen uc_pdata->mode_count = 0;
6042690619bSJoseph Chen
6052690619bSJoseph Chen /* probe only once by buck1 */
6062690619bSJoseph Chen if (dev->driver_data != 1)
6072690619bSJoseph Chen return 0;
6082690619bSJoseph Chen
609*5e8035f6SJoseph Chen /* set pwrctrl active pol and use sleep function */
610*5e8035f6SJoseph Chen val = (priv->pwrctrl_gpio.flags & GPIOD_ACTIVE_LOW) ?
611*5e8035f6SJoseph Chen RK801_SLEEP_ACT_L : RK801_SLEEP_ACT_H;
6122690619bSJoseph Chen ret = pmic_clrsetbits(pmic, RK801_SYS_CFG2_REG,
613*5e8035f6SJoseph Chen RK801_SLEEP_POL_MSK, val);
6142690619bSJoseph Chen if (ret < 0)
6152690619bSJoseph Chen return ret;
6162690619bSJoseph Chen
6172690619bSJoseph Chen ret = pmic_clrsetbits(pmic, RK801_SLEEP_CFG_REG,
6182690619bSJoseph Chen RK801_SLEEP_FUN_MSK, RK801_SLEEP_FUN);
6192690619bSJoseph Chen if (ret < 0)
6202690619bSJoseph Chen return ret;
6212690619bSJoseph Chen
6222690619bSJoseph Chen /* disable buck/pldo slp lp */
6232690619bSJoseph Chen ret = pmic_clrsetbits(pmic, RK801_SLP_LP_CONFIG_REG,
6242690619bSJoseph Chen RK801_SLP_LP_MASK, 0);
6252690619bSJoseph Chen if (ret < 0)
6262690619bSJoseph Chen return ret;
6272690619bSJoseph Chen
6282690619bSJoseph Chen /* copy on/slp enabel */
6292690619bSJoseph Chen en0 = pmic_reg_read(pmic, RK801_POWER_EN0_REG);
6302690619bSJoseph Chen if (en0 < 0)
6312690619bSJoseph Chen return en0;
6322690619bSJoseph Chen
6332690619bSJoseph Chen en1 = pmic_reg_read(pmic, RK801_POWER_EN1_REG);
6342690619bSJoseph Chen if (en1 < 0)
6352690619bSJoseph Chen return en1;
6362690619bSJoseph Chen
6372690619bSJoseph Chen val = (en0 & 0x0f) | ((en1 & 0x0f) << 4);
6382690619bSJoseph Chen ret = pmic_reg_write(pmic, RK801_POWER_SLP_EN_REG, val);
6392690619bSJoseph Chen if (ret < 0)
6402690619bSJoseph Chen return ret;
6412690619bSJoseph Chen
6422690619bSJoseph Chen /* copy on/slp vsel */
6432690619bSJoseph Chen for (i = 0; i < ARRAY_SIZE(rdev); i++) {
6442690619bSJoseph Chen val = pmic_reg_read(pmic, rdev[i].reg_src);
6452690619bSJoseph Chen if (val < 0)
6462690619bSJoseph Chen return val;
6472690619bSJoseph Chen
6482690619bSJoseph Chen ret = pmic_reg_write(pmic, rdev[i].reg_dst, val);
6492690619bSJoseph Chen if (ret < 0)
6502690619bSJoseph Chen return ret;
6512690619bSJoseph Chen }
6522690619bSJoseph Chen
6532690619bSJoseph Chen return 0;
6542690619bSJoseph Chen }
6552690619bSJoseph Chen
rk801_ldo_probe(struct udevice * dev)6562690619bSJoseph Chen static int rk801_ldo_probe(struct udevice *dev)
6572690619bSJoseph Chen {
6582690619bSJoseph Chen struct dm_regulator_uclass_platdata *uc_pdata;
6592690619bSJoseph Chen
6602690619bSJoseph Chen uc_pdata = dev_get_uclass_platdata(dev);
6612690619bSJoseph Chen uc_pdata->type = REGULATOR_TYPE_LDO;
6622690619bSJoseph Chen uc_pdata->mode_count = 0;
6632690619bSJoseph Chen
6642690619bSJoseph Chen return 0;
6652690619bSJoseph Chen }
6662690619bSJoseph Chen
rk801_switch_probe(struct udevice * dev)6672690619bSJoseph Chen static int rk801_switch_probe(struct udevice *dev)
6682690619bSJoseph Chen {
6692690619bSJoseph Chen struct dm_regulator_uclass_platdata *uc_pdata;
6702690619bSJoseph Chen
6712690619bSJoseph Chen uc_pdata = dev_get_uclass_platdata(dev);
6722690619bSJoseph Chen uc_pdata->type = REGULATOR_TYPE_FIXED;
6732690619bSJoseph Chen uc_pdata->mode_count = 0;
6742690619bSJoseph Chen
6752690619bSJoseph Chen return 0;
6762690619bSJoseph Chen }
6772690619bSJoseph Chen
6782690619bSJoseph Chen static const struct dm_regulator_ops rk801_buck_ldo_ops = {
6792690619bSJoseph Chen .get_value = buck_ldo_get_value,
6802690619bSJoseph Chen .set_value = buck_ldo_set_value,
6812690619bSJoseph Chen .set_enable = buck_ldo_set_enable,
6822690619bSJoseph Chen .get_enable = buck_ldo_get_enable,
6832690619bSJoseph Chen .set_suspend_value = buck_ldo_set_suspend_value,
6842690619bSJoseph Chen .get_suspend_value = buck_ldo_get_suspend_value,
6852690619bSJoseph Chen .set_suspend_enable = buck_ldo_set_suspend_enable,
6862690619bSJoseph Chen .get_suspend_enable = buck_ldo_get_suspend_enable,
6872690619bSJoseph Chen .get_ramp_delay = buck_ldo_get_ramp_delay,
6882690619bSJoseph Chen };
6892690619bSJoseph Chen
6902690619bSJoseph Chen static const struct dm_regulator_ops rk801_switch_ops = {
6912690619bSJoseph Chen .get_value = switch_get_value,
6922690619bSJoseph Chen .set_value = switch_set_value,
6932690619bSJoseph Chen .set_enable = switch_set_enable,
6942690619bSJoseph Chen .get_enable = switch_get_enable,
6952690619bSJoseph Chen .set_suspend_enable = switch_set_suspend_enable,
6962690619bSJoseph Chen .get_suspend_enable = switch_get_suspend_enable,
6972690619bSJoseph Chen .set_suspend_value = switch_set_suspend_value,
6982690619bSJoseph Chen .get_suspend_value = switch_get_suspend_value,
6992690619bSJoseph Chen };
7002690619bSJoseph Chen
7012690619bSJoseph Chen U_BOOT_DRIVER(rk801_buck) = {
7022690619bSJoseph Chen .name = "rk801_buck",
7032690619bSJoseph Chen .id = UCLASS_REGULATOR,
7042690619bSJoseph Chen .ops = &rk801_buck_ldo_ops,
7052690619bSJoseph Chen .probe = rk801_buck_probe,
7062690619bSJoseph Chen };
7072690619bSJoseph Chen
7082690619bSJoseph Chen U_BOOT_DRIVER(rk801_ldo) = {
7092690619bSJoseph Chen .name = "rk801_ldo",
7102690619bSJoseph Chen .id = UCLASS_REGULATOR,
7112690619bSJoseph Chen .ops = &rk801_buck_ldo_ops,
7122690619bSJoseph Chen .probe = rk801_ldo_probe,
7132690619bSJoseph Chen };
7142690619bSJoseph Chen
7152690619bSJoseph Chen U_BOOT_DRIVER(rk801_switch) = {
7162690619bSJoseph Chen .name = "rk801_switch",
7172690619bSJoseph Chen .id = UCLASS_REGULATOR,
7182690619bSJoseph Chen .ops = &rk801_switch_ops,
7192690619bSJoseph Chen .probe = rk801_switch_probe,
7202690619bSJoseph Chen };
7212690619bSJoseph Chen
722