uboot/drivers/power/regulator/tps65941_regulator.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * (C) Copyright 2019
   4 * Texas Instruments Incorporated, <www.ti.com>
   5 *
   6 * Keerthy <j-keerthy@ti.com>
   7 */
   8
   9#include <common.h>
  10#include <fdtdec.h>
  11#include <errno.h>
  12#include <dm.h>
  13#include <i2c.h>
  14#include <power/pmic.h>
  15#include <power/regulator.h>
  16#include <power/tps65941.h>
  17
  18static const char tps65941_buck_ctrl[TPS65941_BUCK_NUM] = {0x4, 0x6, 0x8, 0xA,
  19                                                                0xC};
  20static const char tps65941_buck_vout[TPS65941_BUCK_NUM] = {0xE, 0x10, 0x12,
  21                                                                0x14, 0x16};
  22static const char tps65941_ldo_ctrl[TPS65941_BUCK_NUM] = {0x1D, 0x1E, 0x1F,
  23                                                                0x20};
  24static const char tps65941_ldo_vout[TPS65941_BUCK_NUM] = {0x23, 0x24, 0x25,
  25                                                                0x26};
  26
  27static int tps65941_buck_enable(struct udevice *dev, int op, bool *enable)
  28{
  29        int ret;
  30        unsigned int adr;
  31        struct dm_regulator_uclass_platdata *uc_pdata;
  32
  33        uc_pdata = dev_get_uclass_platdata(dev);
  34        adr = uc_pdata->ctrl_reg;
  35
  36        ret = pmic_reg_read(dev->parent, adr);
  37        if (ret < 0)
  38                return ret;
  39
  40        if (op == PMIC_OP_GET) {
  41                ret &= TPS65941_BUCK_MODE_MASK;
  42
  43                if (ret)
  44                        *enable = true;
  45                else
  46                        *enable = false;
  47
  48                return 0;
  49        } else if (op == PMIC_OP_SET) {
  50                if (*enable)
  51                        ret |= TPS65941_BUCK_MODE_MASK;
  52                else
  53                        ret &= ~TPS65941_BUCK_MODE_MASK;
  54                ret = pmic_reg_write(dev->parent, adr, ret);
  55                if (ret)
  56                        return ret;
  57        }
  58
  59        return 0;
  60}
  61
  62static int tps65941_buck_volt2val(int uV)
  63{
  64        if (uV > TPS65941_BUCK_VOLT_MAX)
  65                return -EINVAL;
  66        else if (uV > 1650000)
  67                return (uV - 1660000) / 20000 + 0xAB;
  68        else if (uV > 1110000)
  69                return (uV - 1110000) / 10000 + 0x73;
  70        else if (uV > 600000)
  71                return (uV - 600000) / 5000 + 0x0F;
  72        else if (uV >= 300000)
  73                return (uV - 300000) / 20000 + 0x00;
  74        else
  75                return -EINVAL;
  76}
  77
  78static int tps65941_buck_val2volt(int val)
  79{
  80        if (val > TPS65941_BUCK_VOLT_MAX_HEX)
  81                return -EINVAL;
  82        else if (val > 0xAB)
  83                return 1660000 + (val - 0xAB) * 20000;
  84        else if (val > 0x73)
  85                return 1100000 + (val - 0x73) * 10000;
  86        else if (val > 0xF)
  87                return 600000 + (val - 0xF) * 5000;
  88        else if (val >= 0x0)
  89                return 300000 + val * 5000;
  90        else
  91                return -EINVAL;
  92}
  93
  94int tps65941_lookup_slew(int id)
  95{
  96        switch (id) {
  97        case 0:
  98                return 33000;
  99        case 1:
 100                return 20000;
 101        case 2:
 102                return 10000;
 103        case 3:
 104                return 5000;
 105        case 4:
 106                return 2500;
 107        case 5:
 108                return 1300;
 109        case 6:
 110                return 630;
 111        case 7:
 112                return 310;
 113        default:
 114                return -1;
 115        }
 116}
 117
 118static int tps65941_buck_val(struct udevice *dev, int op, int *uV)
 119{
 120        unsigned int hex, adr;
 121        int ret, delta, uwait, slew;
 122        struct dm_regulator_uclass_platdata *uc_pdata;
 123
 124        uc_pdata = dev_get_uclass_platdata(dev);
 125
 126        if (op == PMIC_OP_GET)
 127                *uV = 0;
 128
 129        adr = uc_pdata->volt_reg;
 130
 131        ret = pmic_reg_read(dev->parent, adr);
 132        if (ret < 0)
 133                return ret;
 134
 135        ret &= TPS65941_BUCK_VOLT_MASK;
 136        ret = tps65941_buck_val2volt(ret);
 137        if (ret < 0)
 138                return ret;
 139
 140        if (op == PMIC_OP_GET) {
 141                *uV = ret;
 142                return 0;
 143        }
 144
 145        /*
 146         * Compute the delta voltage, find the slew rate and wait
 147         * for the appropriate amount of time after voltage switch
 148         */
 149        if (*uV > ret)
 150                delta = *uV - ret;
 151        else
 152                delta = ret - *uV;
 153
 154        slew = pmic_reg_read(dev->parent, uc_pdata->ctrl_reg + 1);
 155        if (slew < 0)
 156                return ret;
 157
 158        slew &= TP65941_BUCK_CONF_SLEW_MASK;
 159        slew = tps65941_lookup_slew(slew);
 160        if (slew <= 0)
 161                return ret;
 162
 163        uwait = delta / slew;
 164
 165        hex = tps65941_buck_volt2val(*uV);
 166        if (hex < 0)
 167                return hex;
 168
 169        ret &= 0x0;
 170        ret = hex;
 171
 172        ret = pmic_reg_write(dev->parent, adr, ret);
 173
 174        udelay(uwait);
 175
 176        return ret;
 177}
 178
 179static int tps65941_ldo_enable(struct udevice *dev, int op, bool *enable)
 180{
 181        int ret;
 182        unsigned int adr;
 183        struct dm_regulator_uclass_platdata *uc_pdata;
 184
 185        uc_pdata = dev_get_uclass_platdata(dev);
 186        adr = uc_pdata->ctrl_reg;
 187
 188        ret = pmic_reg_read(dev->parent, adr);
 189        if (ret < 0)
 190                return ret;
 191
 192        if (op == PMIC_OP_GET) {
 193                ret &= TPS65941_LDO_MODE_MASK;
 194
 195                if (ret)
 196                        *enable = true;
 197                else
 198                        *enable = false;
 199
 200                return 0;
 201        } else if (op == PMIC_OP_SET) {
 202                if (*enable)
 203                        ret |= TPS65941_LDO_MODE_MASK;
 204                else
 205                        ret &= ~TPS65941_LDO_MODE_MASK;
 206                ret = pmic_reg_write(dev->parent, adr, ret);
 207                if (ret)
 208                        return ret;
 209        }
 210
 211        return 0;
 212}
 213
 214static int tps65941_ldo_val2volt(int val)
 215{
 216        if (val > TPS65941_LDO_VOLT_MAX_HEX || val < TPS65941_LDO_VOLT_MIN_HEX)
 217                return -EINVAL;
 218        else if (val >= TPS65941_LDO_VOLT_MIN_HEX)
 219                return 600000 + (val - TPS65941_LDO_VOLT_MIN_HEX) * 50000;
 220        else
 221                return -EINVAL;
 222}
 223
 224static int tps65941_ldo_val(struct udevice *dev, int op, int *uV)
 225{
 226        unsigned int hex, adr;
 227        int ret;
 228        struct dm_regulator_uclass_platdata *uc_pdata;
 229
 230        uc_pdata = dev_get_uclass_platdata(dev);
 231
 232        if (op == PMIC_OP_GET)
 233                *uV = 0;
 234
 235        adr = uc_pdata->volt_reg;
 236
 237        ret = pmic_reg_read(dev->parent, adr);
 238        if (ret < 0)
 239                return ret;
 240
 241        ret &= TPS65941_LDO_VOLT_MASK;
 242        ret = tps65941_ldo_val2volt(ret);
 243        if (ret < 0)
 244                return ret;
 245
 246        if (op == PMIC_OP_GET) {
 247                *uV = ret;
 248                return 0;
 249        }
 250
 251        hex = tps65941_buck_volt2val(*uV);
 252        if (hex < 0)
 253                return hex;
 254
 255        ret &= 0x0;
 256        ret = hex;
 257
 258        ret = pmic_reg_write(dev->parent, adr, ret);
 259
 260        return ret;
 261}
 262
 263static int tps65941_ldo_probe(struct udevice *dev)
 264{
 265        struct dm_regulator_uclass_platdata *uc_pdata;
 266        int idx;
 267
 268        uc_pdata = dev_get_uclass_platdata(dev);
 269        uc_pdata->type = REGULATOR_TYPE_LDO;
 270
 271        idx = dev->driver_data;
 272        if (idx == 1 || idx == 2 || idx == 3 || idx == 4) {
 273                debug("Single phase regulator\n");
 274        } else {
 275                printf("Wrong ID for regulator\n");
 276                return -EINVAL;
 277        }
 278
 279        uc_pdata->ctrl_reg = tps65941_ldo_ctrl[idx - 1];
 280        uc_pdata->volt_reg = tps65941_ldo_vout[idx - 1];
 281
 282        return 0;
 283}
 284
 285static int tps65941_buck_probe(struct udevice *dev)
 286{
 287        struct dm_regulator_uclass_platdata *uc_pdata;
 288        int idx;
 289
 290        uc_pdata = dev_get_uclass_platdata(dev);
 291        uc_pdata->type = REGULATOR_TYPE_BUCK;
 292
 293        idx = dev->driver_data;
 294        if (idx == 1 || idx == 2 || idx == 3 || idx == 4 || idx == 5) {
 295                debug("Single phase regulator\n");
 296        } else if (idx == 12) {
 297                idx = 1;
 298        } else if (idx == 34) {
 299                idx = 3;
 300        } else if (idx == 1234) {
 301                idx = 1;
 302        } else {
 303                printf("Wrong ID for regulator\n");
 304                return -EINVAL;
 305        }
 306
 307        uc_pdata->ctrl_reg = tps65941_buck_ctrl[idx - 1];
 308        uc_pdata->volt_reg = tps65941_buck_vout[idx - 1];
 309
 310        return 0;
 311}
 312
 313static int ldo_get_value(struct udevice *dev)
 314{
 315        int uV;
 316        int ret;
 317
 318        ret = tps65941_ldo_val(dev, PMIC_OP_GET, &uV);
 319        if (ret)
 320                return ret;
 321
 322        return uV;
 323}
 324
 325static int ldo_set_value(struct udevice *dev, int uV)
 326{
 327        return tps65941_ldo_val(dev, PMIC_OP_SET, &uV);
 328}
 329
 330static int ldo_get_enable(struct udevice *dev)
 331{
 332        bool enable = false;
 333        int ret;
 334
 335        ret = tps65941_ldo_enable(dev, PMIC_OP_GET, &enable);
 336        if (ret)
 337                return ret;
 338
 339        return enable;
 340}
 341
 342static int ldo_set_enable(struct udevice *dev, bool enable)
 343{
 344        return tps65941_ldo_enable(dev, PMIC_OP_SET, &enable);
 345}
 346
 347static int buck_get_value(struct udevice *dev)
 348{
 349        int uV;
 350        int ret;
 351
 352        ret = tps65941_buck_val(dev, PMIC_OP_GET, &uV);
 353        if (ret)
 354                return ret;
 355
 356        return uV;
 357}
 358
 359static int buck_set_value(struct udevice *dev, int uV)
 360{
 361        return tps65941_buck_val(dev, PMIC_OP_SET, &uV);
 362}
 363
 364static int buck_get_enable(struct udevice *dev)
 365{
 366        bool enable = false;
 367        int ret;
 368
 369        ret = tps65941_buck_enable(dev, PMIC_OP_GET, &enable);
 370        if (ret)
 371                return ret;
 372
 373        return enable;
 374}
 375
 376static int buck_set_enable(struct udevice *dev, bool enable)
 377{
 378        return tps65941_buck_enable(dev, PMIC_OP_SET, &enable);
 379}
 380
 381static const struct dm_regulator_ops tps65941_ldo_ops = {
 382        .get_value  = ldo_get_value,
 383        .set_value  = ldo_set_value,
 384        .get_enable = ldo_get_enable,
 385        .set_enable = ldo_set_enable,
 386};
 387
 388U_BOOT_DRIVER(tps65941_ldo) = {
 389        .name = TPS65941_LDO_DRIVER,
 390        .id = UCLASS_REGULATOR,
 391        .ops = &tps65941_ldo_ops,
 392        .probe = tps65941_ldo_probe,
 393};
 394
 395static const struct dm_regulator_ops tps65941_buck_ops = {
 396        .get_value  = buck_get_value,
 397        .set_value  = buck_set_value,
 398        .get_enable = buck_get_enable,
 399        .set_enable = buck_set_enable,
 400};
 401
 402U_BOOT_DRIVER(tps65941_buck) = {
 403        .name = TPS65941_BUCK_DRIVER,
 404        .id = UCLASS_REGULATOR,
 405        .ops = &tps65941_buck_ops,
 406        .probe = tps65941_buck_probe,
 407};
 408