uboot/drivers/power/regulator/tps65910_regulator.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (C) EETS GmbH, 2017, Felix Brack <f.brack@eets.ch>
   4 */
   5
   6#include <common.h>
   7#include <dm.h>
   8#include <log.h>
   9#include <power/pmic.h>
  10#include <power/regulator.h>
  11#include <power/tps65910_pmic.h>
  12
  13#define VOUT_CHOICE_COUNT 4
  14
  15/*
  16 * struct regulator_props - Properties of a LDO and VIO SMPS regulator
  17 *
  18 * All of these regulators allow setting one out of four output voltages.
  19 * These output voltages are only achievable when supplying the regulator
  20 * with a minimum input voltage.
  21 *
  22 * @vin_min[]: minimum supply input voltage in uV required to achieve the
  23 *             corresponding vout[] voltage
  24 * @vout[]:    regulator output voltage in uV
  25 * @reg:       I2C register used to set regulator voltage
  26 */
  27struct regulator_props {
  28        int vin_min[VOUT_CHOICE_COUNT];
  29        int vout[VOUT_CHOICE_COUNT];
  30        int reg;
  31};
  32
  33static const struct regulator_props ldo_props_vdig1 = {
  34        .vin_min = { 1700000, 2100000, 2700000, 3200000 },
  35        .vout = { 1200000, 1500000, 1800000, 2700000 },
  36        .reg = TPS65910_REG_VDIG1
  37};
  38
  39static const struct regulator_props ldo_props_vdig2 = {
  40        .vin_min = { 1700000, 1700000, 1700000, 2700000 },
  41        .vout = { 1000000, 1100000, 1200000, 1800000 },
  42        .reg = TPS65910_REG_VDIG2
  43};
  44
  45static const struct regulator_props ldo_props_vpll = {
  46        .vin_min = { 2700000, 2700000, 2700000, 3000000 },
  47        .vout = { 1000000, 1100000, 1800000, 2500000 },
  48        .reg = TPS65910_REG_VPLL
  49};
  50
  51static const struct regulator_props ldo_props_vdac = {
  52        .vin_min = { 2700000, 3000000, 3200000, 3200000 },
  53        .vout = { 1800000, 2600000, 2800000, 2850000 },
  54        .reg = TPS65910_REG_VDAC
  55};
  56
  57static const struct regulator_props ldo_props_vaux1 = {
  58        .vin_min = { 2700000, 3200000, 3200000, 3200000 },
  59        .vout = { 1800000, 2500000, 2800000, 2850000 },
  60        .reg = TPS65910_REG_VAUX1
  61};
  62
  63static const struct regulator_props ldo_props_vaux2 = {
  64        .vin_min = { 2700000, 3200000, 3200000, 3600000 },
  65        .vout = { 1800000, 2800000, 2900000, 3300000 },
  66        .reg = TPS65910_REG_VAUX2
  67};
  68
  69static const struct regulator_props ldo_props_vaux33 = {
  70        .vin_min = { 2700000, 2700000, 3200000, 3600000 },
  71        .vout = { 1800000, 2000000, 2800000, 3300000 },
  72        .reg = TPS65910_REG_VAUX33
  73};
  74
  75static const struct regulator_props ldo_props_vmmc = {
  76        .vin_min = { 2700000, 3200000, 3200000, 3600000 },
  77        .vout = { 1800000, 2800000, 3000000, 3300000 },
  78        .reg = TPS65910_REG_VMMC
  79};
  80
  81static const struct regulator_props smps_props_vio = {
  82        .vin_min = { 3200000, 3200000, 4000000, 4400000 },
  83        .vout = { 1500000, 1800000, 2500000, 3300000 },
  84        .reg = TPS65910_REG_VIO
  85};
  86
  87/* lookup table of control registers indexed by regulator unit number */
  88static const int ctrl_regs[] = {
  89        TPS65910_REG_VRTC,
  90        TPS65910_REG_VIO,
  91        TPS65910_REG_VDD1,
  92        TPS65910_REG_VDD2,
  93        TPS65910_REG_VDD3,
  94        TPS65910_REG_VDIG1,
  95        TPS65910_REG_VDIG2,
  96        TPS65910_REG_VPLL,
  97        TPS65910_REG_VDAC,
  98        TPS65910_REG_VAUX1,
  99        TPS65910_REG_VAUX2,
 100        TPS65910_REG_VAUX33,
 101        TPS65910_REG_VMMC
 102};
 103
 104/* supply names as used in DT */
 105static const char * const supply_names[] = {
 106        "vccio-supply",
 107        "vcc1-supply",
 108        "vcc2-supply",
 109        "vcc3-supply",
 110        "vcc4-supply",
 111        "vcc5-supply",
 112        "vcc6-supply",
 113        "vcc7-supply"
 114};
 115
 116/* lookup table of regulator supplies indexed by regulator unit number */
 117static const int regulator_supplies[] = {
 118        TPS65910_SUPPLY_VCC7,
 119        TPS65910_SUPPLY_VCCIO,
 120        TPS65910_SUPPLY_VCC1,
 121        TPS65910_SUPPLY_VCC2,
 122        TPS65910_SUPPLY_VCC7,
 123        TPS65910_SUPPLY_VCC6,
 124        TPS65910_SUPPLY_VCC6,
 125        TPS65910_SUPPLY_VCC5,
 126        TPS65910_SUPPLY_VCC5,
 127        TPS65910_SUPPLY_VCC4,
 128        TPS65910_SUPPLY_VCC4,
 129        TPS65910_SUPPLY_VCC3,
 130        TPS65910_SUPPLY_VCC3
 131};
 132
 133static int get_ctrl_reg_from_unit_addr(const uint unit_addr)
 134{
 135        if (unit_addr < ARRAY_SIZE(ctrl_regs))
 136                return ctrl_regs[unit_addr];
 137        return -ENXIO;
 138}
 139
 140static int tps65910_regulator_get_value(struct udevice *dev,
 141                                        const struct regulator_props *rgp)
 142{
 143        int sel, val, vout;
 144        struct tps65910_regulator_pdata *pdata = dev_get_plat(dev);
 145        int vin = pdata->supply;
 146
 147        val = pmic_reg_read(dev->parent, rgp->reg);
 148        if (val < 0)
 149                return val;
 150        sel = (val & TPS65910_SEL_MASK) >> 2;
 151        vout = (vin >= *(rgp->vin_min + sel)) ? *(rgp->vout + sel) : 0;
 152        vout = ((val & TPS65910_SUPPLY_STATE_MASK) == 1) ? vout : 0;
 153
 154        return vout;
 155}
 156
 157static int tps65910_ldo_get_value(struct udevice *dev)
 158{
 159        struct tps65910_regulator_pdata *pdata = dev_get_plat(dev);
 160        int vin;
 161
 162        if (!pdata)
 163                return 0;
 164        vin = pdata->supply;
 165
 166        switch (pdata->unit) {
 167        case TPS65910_UNIT_VRTC:
 168                /* VRTC is fixed and can't be turned off */
 169                return (vin >= 2500000) ? 1830000 : 0;
 170        case TPS65910_UNIT_VDIG1:
 171                return tps65910_regulator_get_value(dev, &ldo_props_vdig1);
 172        case TPS65910_UNIT_VDIG2:
 173                return tps65910_regulator_get_value(dev, &ldo_props_vdig2);
 174        case TPS65910_UNIT_VPLL:
 175                return tps65910_regulator_get_value(dev, &ldo_props_vpll);
 176        case TPS65910_UNIT_VDAC:
 177                return tps65910_regulator_get_value(dev, &ldo_props_vdac);
 178        case TPS65910_UNIT_VAUX1:
 179                return tps65910_regulator_get_value(dev, &ldo_props_vaux1);
 180        case TPS65910_UNIT_VAUX2:
 181                return tps65910_regulator_get_value(dev, &ldo_props_vaux2);
 182        case TPS65910_UNIT_VAUX33:
 183                return tps65910_regulator_get_value(dev, &ldo_props_vaux33);
 184        case TPS65910_UNIT_VMMC:
 185                return tps65910_regulator_get_value(dev, &ldo_props_vmmc);
 186        default:
 187                return 0;
 188        }
 189}
 190
 191static int tps65910_regulator_set_value(struct udevice *dev,
 192                                        const struct regulator_props *ldo,
 193                                        int uV)
 194{
 195        int val;
 196        int sel = 0;
 197        struct tps65910_regulator_pdata *pdata = dev_get_plat(dev);
 198
 199        do {
 200                /* we only allow exact voltage matches */
 201                if (uV == *(ldo->vout + sel))
 202                        break;
 203        } while (++sel < VOUT_CHOICE_COUNT);
 204        if (sel == VOUT_CHOICE_COUNT)
 205                return -EINVAL;
 206        if (pdata->supply < *(ldo->vin_min + sel))
 207                return -EINVAL;
 208
 209        val = pmic_reg_read(dev->parent, ldo->reg);
 210        if (val < 0)
 211                return val;
 212        val &= ~TPS65910_SEL_MASK;
 213        val |= sel << 2;
 214        return pmic_reg_write(dev->parent, ldo->reg, val);
 215}
 216
 217static int tps65910_ldo_set_value(struct udevice *dev, int uV)
 218{
 219        struct tps65910_regulator_pdata *pdata = dev_get_plat(dev);
 220        int vin = pdata->supply;
 221
 222        switch (pdata->unit) {
 223        case TPS65910_UNIT_VRTC:
 224                /* VRTC is fixed to 1.83V and can't be turned off */
 225                if (vin < 2500000)
 226                        return -EINVAL;
 227                return 0;
 228        case TPS65910_UNIT_VDIG1:
 229                return tps65910_regulator_set_value(dev, &ldo_props_vdig1, uV);
 230        case TPS65910_UNIT_VDIG2:
 231                return tps65910_regulator_set_value(dev, &ldo_props_vdig2, uV);
 232        case TPS65910_UNIT_VPLL:
 233                return tps65910_regulator_set_value(dev, &ldo_props_vpll, uV);
 234        case TPS65910_UNIT_VDAC:
 235                return tps65910_regulator_set_value(dev, &ldo_props_vdac, uV);
 236        case TPS65910_UNIT_VAUX1:
 237                return tps65910_regulator_set_value(dev, &ldo_props_vaux1, uV);
 238        case TPS65910_UNIT_VAUX2:
 239                return tps65910_regulator_set_value(dev, &ldo_props_vaux2, uV);
 240        case TPS65910_UNIT_VAUX33:
 241                return tps65910_regulator_set_value(dev, &ldo_props_vaux33, uV);
 242        case TPS65910_UNIT_VMMC:
 243                return tps65910_regulator_set_value(dev, &ldo_props_vmmc, uV);
 244        default:
 245                return 0;
 246        }
 247}
 248
 249static int tps65910_get_enable(struct udevice *dev)
 250{
 251        int reg, val;
 252        struct tps65910_regulator_pdata *pdata = dev_get_plat(dev);
 253
 254        reg = get_ctrl_reg_from_unit_addr(pdata->unit);
 255        if (reg < 0)
 256                return reg;
 257
 258        val = pmic_reg_read(dev->parent, reg);
 259        if (val < 0)
 260                return val;
 261
 262        /* bits 1:0 of regulator control register define state */
 263        return ((val & TPS65910_SUPPLY_STATE_MASK) == 1);
 264}
 265
 266static int tps65910_set_enable(struct udevice *dev, bool enable)
 267{
 268        int reg;
 269        uint clr, set;
 270        struct tps65910_regulator_pdata *pdata = dev_get_plat(dev);
 271
 272        reg = get_ctrl_reg_from_unit_addr(pdata->unit);
 273        if (reg < 0)
 274                return reg;
 275
 276        if (enable) {
 277                clr = TPS65910_SUPPLY_STATE_MASK & ~TPS65910_SUPPLY_STATE_ON;
 278                set = TPS65910_SUPPLY_STATE_MASK & TPS65910_SUPPLY_STATE_ON;
 279        } else {
 280                clr = TPS65910_SUPPLY_STATE_MASK & ~TPS65910_SUPPLY_STATE_OFF;
 281                set = TPS65910_SUPPLY_STATE_MASK & TPS65910_SUPPLY_STATE_OFF;
 282        }
 283        return pmic_clrsetbits(dev->parent, reg, clr, set);
 284}
 285
 286static int buck_get_vdd1_vdd2_value(struct udevice *dev, int reg_vdd)
 287{
 288        int gain;
 289        int val = pmic_reg_read(dev, reg_vdd);
 290
 291        if (val < 0)
 292                return val;
 293        gain = (val & TPS65910_GAIN_SEL_MASK) >> 6;
 294        gain = (gain == 0) ? 1 : gain;
 295        val = pmic_reg_read(dev, reg_vdd + 1);
 296        if (val < 0)
 297                return val;
 298        if (val & TPS65910_VDD_SR_MASK)
 299                /* use smart reflex value instead */
 300                val = pmic_reg_read(dev, reg_vdd + 2);
 301        if (val < 0)
 302                return val;
 303        return (562500 + (val & TPS65910_VDD_SEL_MASK) * 12500) * gain;
 304}
 305
 306static int tps65910_buck_get_value(struct udevice *dev)
 307{
 308        struct tps65910_regulator_pdata *pdata = dev_get_plat(dev);
 309
 310        switch (pdata->unit) {
 311        case TPS65910_UNIT_VIO:
 312                return tps65910_regulator_get_value(dev, &smps_props_vio);
 313        case TPS65910_UNIT_VDD1:
 314                return buck_get_vdd1_vdd2_value(dev->parent, TPS65910_REG_VDD1);
 315        case TPS65910_UNIT_VDD2:
 316                return buck_get_vdd1_vdd2_value(dev->parent, TPS65910_REG_VDD2);
 317        default:
 318                return 0;
 319        }
 320}
 321
 322static int buck_set_vdd1_vdd2_value(struct udevice *dev, int uV)
 323{
 324        int ret, reg_vdd, gain;
 325        int val;
 326        struct dm_regulator_uclass_plat *uc_pdata;
 327        struct tps65910_regulator_pdata *pdata = dev_get_plat(dev);
 328
 329        switch (pdata->unit) {
 330        case TPS65910_UNIT_VDD1:
 331                reg_vdd = TPS65910_REG_VDD1;
 332                break;
 333        case TPS65910_UNIT_VDD2:
 334                reg_vdd = TPS65910_REG_VDD2;
 335                break;
 336        default:
 337                return -EINVAL;
 338        }
 339        uc_pdata = dev_get_uclass_plat(dev);
 340
 341        /* check setpoint is within limits */
 342        if (uV < uc_pdata->min_uV) {
 343                pr_err("voltage %duV for %s too low\n", uV, dev->name);
 344                return -EINVAL;
 345        }
 346        if (uV > uc_pdata->max_uV) {
 347                pr_err("voltage %duV for %s too high\n", uV, dev->name);
 348                return -EINVAL;
 349        }
 350
 351        val = pmic_reg_read(dev->parent, reg_vdd);
 352        if (val < 0)
 353                return val;
 354        gain = (val & TPS65910_GAIN_SEL_MASK) >> 6;
 355        gain = (gain == 0) ? 1 : gain;
 356        val = ((uV / gain) - 562500) / 12500;
 357        if (val < TPS65910_VDD_SEL_MIN || val > TPS65910_VDD_SEL_MAX)
 358                /*
 359                 * Neither do we change the gain, nor do we allow shutdown or
 360                 * any approximate value (for now)
 361                 */
 362                return -EPERM;
 363        val &= TPS65910_VDD_SEL_MASK;
 364        ret = pmic_reg_write(dev->parent, reg_vdd + 1, val);
 365        if (ret)
 366                return ret;
 367        return 0;
 368}
 369
 370static int tps65910_buck_set_value(struct udevice *dev, int uV)
 371{
 372        struct tps65910_regulator_pdata *pdata = dev_get_plat(dev);
 373
 374        if (pdata->unit == TPS65910_UNIT_VIO)
 375                return tps65910_regulator_set_value(dev, &smps_props_vio, uV);
 376
 377        return buck_set_vdd1_vdd2_value(dev, uV);
 378}
 379
 380static int tps65910_boost_get_value(struct udevice *dev)
 381{
 382        int vout;
 383        struct tps65910_regulator_pdata *pdata = dev_get_plat(dev);
 384
 385        vout = (pdata->supply >= 3000000) ? 5000000 : 0;
 386        return vout;
 387}
 388
 389static int tps65910_regulator_of_to_plat(struct udevice *dev)
 390{
 391        struct udevice *supply;
 392        int ret;
 393        const char *supply_name;
 394        struct tps65910_regulator_pdata *pdata = dev_get_plat(dev);
 395
 396        pdata->unit = dev_get_driver_data(dev);
 397        if (pdata->unit > TPS65910_UNIT_VMMC)
 398                return -EINVAL;
 399        supply_name = supply_names[regulator_supplies[pdata->unit]];
 400
 401        debug("Looking up supply power %s\n", supply_name);
 402        ret = device_get_supply_regulator(dev->parent, supply_name, &supply);
 403        if (ret) {
 404                debug("  missing supply power %s\n", supply_name);
 405                return ret;
 406        }
 407        pdata->supply = regulator_get_value(supply);
 408        if (pdata->supply < 0) {
 409                debug("  invalid supply voltage for regulator %s\n",
 410                      supply->name);
 411                return -EINVAL;
 412        }
 413
 414        return 0;
 415}
 416
 417static const struct dm_regulator_ops tps65910_boost_ops = {
 418        .get_value  = tps65910_boost_get_value,
 419        .get_enable = tps65910_get_enable,
 420        .set_enable = tps65910_set_enable,
 421};
 422
 423U_BOOT_DRIVER(tps65910_boost) = {
 424        .name = TPS65910_BOOST_DRIVER,
 425        .id = UCLASS_REGULATOR,
 426        .ops = &tps65910_boost_ops,
 427        .plat_auto      = sizeof(struct tps65910_regulator_pdata),
 428        .of_to_plat = tps65910_regulator_of_to_plat,
 429};
 430
 431static const struct dm_regulator_ops tps65910_buck_ops = {
 432        .get_value  = tps65910_buck_get_value,
 433        .set_value  = tps65910_buck_set_value,
 434        .get_enable = tps65910_get_enable,
 435        .set_enable = tps65910_set_enable,
 436};
 437
 438U_BOOT_DRIVER(tps65910_buck) = {
 439        .name = TPS65910_BUCK_DRIVER,
 440        .id = UCLASS_REGULATOR,
 441        .ops = &tps65910_buck_ops,
 442        .plat_auto      = sizeof(struct tps65910_regulator_pdata),
 443        .of_to_plat = tps65910_regulator_of_to_plat,
 444};
 445
 446static const struct dm_regulator_ops tps65910_ldo_ops = {
 447        .get_value  = tps65910_ldo_get_value,
 448        .set_value  = tps65910_ldo_set_value,
 449        .get_enable = tps65910_get_enable,
 450        .set_enable = tps65910_set_enable,
 451};
 452
 453U_BOOT_DRIVER(tps65910_ldo) = {
 454        .name = TPS65910_LDO_DRIVER,
 455        .id = UCLASS_REGULATOR,
 456        .ops = &tps65910_ldo_ops,
 457        .plat_auto      = sizeof(struct tps65910_regulator_pdata),
 458        .of_to_plat = tps65910_regulator_of_to_plat,
 459};
 460