uboot/drivers/power/regulator/palmas_regulator.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * (C) Copyright 2016
   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/palmas.h>
  17
  18#define REGULATOR_ON            0x1
  19#define REGULATOR_OFF           0x0
  20
  21#define SMPS_MODE_MASK          0x3
  22#define SMPS_MODE_SHIFT         0x0
  23#define LDO_MODE_MASK           0x1
  24#define LDO_MODE_SHIFT          0x0
  25
  26static const char palmas_smps_ctrl[][PALMAS_SMPS_NUM] = {
  27        {0x20, 0x24, 0x28, 0x2c, 0x30, 0x34, 0x38, 0x3c},
  28        {0x20, 0x24, 0x28, 0x2c, 0x30, 0x34, 0x38},
  29        {0x20, 0x24, 0x2c, 0x30, 0x38},
  30};
  31
  32static const char palmas_smps_volt[][PALMAS_SMPS_NUM] = {
  33        {0x23, 0x27, 0x2b, 0x2f, 0x33, 0x37, 0x3b, 0x3c},
  34        {0x23, 0x27, 0x2b, 0x2f, 0x33, 0x37, 0x3b},
  35        {0x23, 0x27, 0x2f, 0x33, 0x3B}
  36};
  37
  38static const char palmas_ldo_ctrl[][PALMAS_LDO_NUM] = {
  39        {0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x5e, 0x60, 0x62, 0x64},
  40        {0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x5e, 0x60, 0x62, 0x64},
  41        {0x50, 0x52, 0x54, 0x5e, 0x62}
  42};
  43
  44static const char palmas_ldo_volt[][PALMAS_LDO_NUM] = {
  45        {0x51, 0x53, 0x55, 0x57, 0x59, 0x5b, 0x5d, 0x5f, 0x61, 0x63, 0x65},
  46        {0x51, 0x53, 0x55, 0x57, 0x59, 0x5b, 0x5d, 0x5f, 0x61, 0x63, 0x65},
  47        {0x51, 0x53, 0x55, 0x5f, 0x63}
  48};
  49
  50static int palmas_smps_enable(struct udevice *dev, int op, bool *enable)
  51{
  52        int ret;
  53        unsigned int adr;
  54        struct dm_regulator_uclass_platdata *uc_pdata;
  55
  56        uc_pdata = dev_get_uclass_platdata(dev);
  57        adr = uc_pdata->ctrl_reg;
  58
  59        ret = pmic_reg_read(dev->parent, adr);
  60                if (ret < 0)
  61                        return ret;
  62
  63        if (op == PMIC_OP_GET) {
  64                ret &= PALMAS_SMPS_STATUS_MASK;
  65
  66                if (ret)
  67                        *enable = true;
  68                else
  69                        *enable = false;
  70
  71                return 0;
  72        } else if (op == PMIC_OP_SET) {
  73                if (*enable)
  74                        ret |= PALMAS_SMPS_MODE_MASK;
  75                else
  76                        ret &= ~(PALMAS_SMPS_MODE_MASK);
  77
  78                ret = pmic_reg_write(dev->parent, adr, ret);
  79                if (ret)
  80                        return ret;
  81        }
  82
  83        return 0;
  84}
  85
  86static int palmas_smps_volt2hex(int uV)
  87{
  88        if (uV > PALMAS_LDO_VOLT_MAX)
  89                return -EINVAL;
  90
  91        if (uV > 1650000)
  92                return (uV - 1000000) / 20000 + 0x6;
  93
  94        if (uV == 500000)
  95                return 0x6;
  96        else
  97                return 0x6 + ((uV - 500000) / 10000);
  98}
  99
 100static int palmas_smps_hex2volt(int hex, bool range)
 101{
 102        unsigned int uV = 0;
 103
 104        if (hex > PALMAS_SMPS_VOLT_MAX_HEX)
 105                return -EINVAL;
 106
 107        if (hex < 0x7)
 108                uV = 500000;
 109        else
 110                uV = 500000 + (hex - 0x6) * 10000;
 111
 112        if (range)
 113                uV *= 2;
 114
 115        return uV;
 116}
 117
 118static int palmas_smps_val(struct udevice *dev, int op, int *uV)
 119{
 120        unsigned int hex, adr;
 121        int ret;
 122        bool range;
 123        struct dm_regulator_uclass_platdata *uc_pdata;
 124
 125        uc_pdata = dev_get_uclass_platdata(dev);
 126
 127        if (op == PMIC_OP_GET)
 128                *uV = 0;
 129
 130        adr = uc_pdata->volt_reg;
 131
 132        ret = pmic_reg_read(dev->parent, adr);
 133        if (ret < 0)
 134                return ret;
 135
 136        if (op == PMIC_OP_GET) {
 137                if (ret & PALMAS_SMPS_RANGE_MASK)
 138                        range =  true;
 139                else
 140                        range = false;
 141
 142                ret &= PALMAS_SMPS_VOLT_MASK;
 143                ret = palmas_smps_hex2volt(ret, range);
 144                if (ret < 0)
 145                        return ret;
 146                *uV = ret;
 147
 148                return 0;
 149        }
 150
 151        hex = palmas_smps_volt2hex(*uV);
 152        if (hex < 0)
 153                return hex;
 154
 155        ret &= ~PALMAS_SMPS_VOLT_MASK;
 156        ret |= hex;
 157        if (*uV > 1650000)
 158                ret |= PALMAS_SMPS_RANGE_MASK;
 159
 160        return pmic_reg_write(dev->parent, adr, ret);
 161}
 162
 163static int palmas_ldo_bypass_enable(struct udevice *dev, bool enabled)
 164{
 165        int type = dev_get_driver_data(dev_get_parent(dev));
 166        struct dm_regulator_uclass_platdata *p;
 167        unsigned int adr;
 168        int reg;
 169
 170        if (type == TPS65917) {
 171                /* bypass available only on LDO1 and LDO2 */
 172                if (dev->driver_data > 2)
 173                        return -ENOTSUPP;
 174        } else if (type == TPS659038) {
 175                /* bypass available only on LDO9 */
 176                if (dev->driver_data != 9)
 177                        return -ENOTSUPP;
 178        }
 179
 180        p = dev_get_uclass_platdata(dev);
 181        adr = p->ctrl_reg;
 182
 183        reg = pmic_reg_read(dev->parent, adr);
 184        if (reg < 0)
 185                return reg;
 186
 187        if (enabled)
 188                reg |= PALMAS_LDO_BYPASS_EN;
 189        else
 190                reg &= ~PALMAS_LDO_BYPASS_EN;
 191
 192        return pmic_reg_write(dev->parent, adr, reg);
 193}
 194
 195static int palmas_ldo_enable(struct udevice *dev, int op, bool *enable)
 196{
 197        int ret;
 198        unsigned int adr;
 199        struct dm_regulator_uclass_platdata *uc_pdata;
 200
 201        uc_pdata = dev_get_uclass_platdata(dev);
 202        adr = uc_pdata->ctrl_reg;
 203
 204        ret = pmic_reg_read(dev->parent, adr);
 205                if (ret < 0)
 206                        return ret;
 207
 208        if (op == PMIC_OP_GET) {
 209                ret &= PALMAS_LDO_STATUS_MASK;
 210
 211                if (ret)
 212                        *enable = true;
 213                else
 214                        *enable = false;
 215
 216                return 0;
 217        } else if (op == PMIC_OP_SET) {
 218                if (*enable)
 219                        ret |= PALMAS_LDO_MODE_MASK;
 220                else
 221                        ret &= ~(PALMAS_LDO_MODE_MASK);
 222
 223                ret = pmic_reg_write(dev->parent, adr, ret);
 224                if (ret)
 225                        return ret;
 226
 227                ret = palmas_ldo_bypass_enable(dev, false);
 228                if (ret && (ret != -ENOTSUPP))
 229                        return ret;
 230        }
 231
 232        return 0;
 233}
 234
 235static int palmas_ldo_volt2hex(int uV)
 236{
 237        if (uV > PALMAS_LDO_VOLT_MAX)
 238                return -EINVAL;
 239
 240        return (uV - 850000) / 50000;
 241}
 242
 243static int palmas_ldo_hex2volt(int hex)
 244{
 245        if (hex > PALMAS_LDO_VOLT_MAX_HEX)
 246                return -EINVAL;
 247
 248        if (!hex)
 249                return 0;
 250
 251        return (hex * 50000) + 850000;
 252}
 253
 254static int palmas_ldo_val(struct udevice *dev, int op, int *uV)
 255{
 256        unsigned int hex, adr;
 257        int ret;
 258
 259        struct dm_regulator_uclass_platdata *uc_pdata;
 260
 261        if (op == PMIC_OP_GET)
 262                *uV = 0;
 263
 264        uc_pdata = dev_get_uclass_platdata(dev);
 265
 266        adr = uc_pdata->volt_reg;
 267
 268        ret = pmic_reg_read(dev->parent, adr);
 269        if (ret < 0)
 270                return ret;
 271
 272        if (op == PMIC_OP_GET) {
 273                ret &= PALMAS_LDO_VOLT_MASK;
 274                ret = palmas_ldo_hex2volt(ret);
 275                if (ret < 0)
 276                        return ret;
 277                *uV = ret;
 278                return 0;
 279        }
 280
 281        hex = palmas_ldo_volt2hex(*uV);
 282        if (hex < 0)
 283                return hex;
 284
 285        ret &= ~PALMAS_LDO_VOLT_MASK;
 286        ret |= hex;
 287        if (*uV > 1650000)
 288                ret |= 0x80;
 289
 290        return pmic_reg_write(dev->parent, adr, ret);
 291}
 292
 293static int palmas_ldo_probe(struct udevice *dev)
 294{
 295        struct dm_regulator_uclass_platdata *uc_pdata;
 296        struct udevice *parent;
 297
 298        uc_pdata = dev_get_uclass_platdata(dev);
 299
 300        parent = dev_get_parent(dev);
 301        int type = dev_get_driver_data(parent);
 302
 303        uc_pdata->type = REGULATOR_TYPE_LDO;
 304
 305        if (dev->driver_data) {
 306                u8 idx = dev->driver_data - 1;
 307                uc_pdata->ctrl_reg = palmas_ldo_ctrl[type][idx];
 308                uc_pdata->volt_reg = palmas_ldo_volt[type][idx];
 309        } else {
 310                /* check for ldoln and ldousb cases */
 311                if (!strcmp("ldoln", dev->name)) {
 312                        uc_pdata->ctrl_reg = palmas_ldo_ctrl[type][9];
 313                        uc_pdata->volt_reg = palmas_ldo_volt[type][9];
 314                } else if (!strcmp("ldousb", dev->name)) {
 315                        uc_pdata->ctrl_reg = palmas_ldo_ctrl[type][10];
 316                        uc_pdata->volt_reg = palmas_ldo_volt[type][10];
 317                }
 318        }
 319
 320        return 0;
 321}
 322
 323static int ldo_get_value(struct udevice *dev)
 324{
 325        int uV;
 326        int ret;
 327
 328        ret = palmas_ldo_val(dev, PMIC_OP_GET, &uV);
 329        if (ret)
 330                return ret;
 331
 332        return uV;
 333}
 334
 335static int ldo_set_value(struct udevice *dev, int uV)
 336{
 337        return palmas_ldo_val(dev, PMIC_OP_SET, &uV);
 338}
 339
 340static int ldo_get_enable(struct udevice *dev)
 341{
 342        bool enable = false;
 343        int ret;
 344
 345        ret = palmas_ldo_enable(dev, PMIC_OP_GET, &enable);
 346        if (ret)
 347                return ret;
 348
 349        return enable;
 350}
 351
 352static int ldo_set_enable(struct udevice *dev, bool enable)
 353{
 354        return palmas_ldo_enable(dev, PMIC_OP_SET, &enable);
 355}
 356
 357static int palmas_smps_probe(struct udevice *dev)
 358{
 359        struct dm_regulator_uclass_platdata *uc_pdata;
 360        struct udevice *parent;
 361        int idx;
 362
 363        uc_pdata = dev_get_uclass_platdata(dev);
 364
 365        parent = dev_get_parent(dev);
 366        int type = dev_get_driver_data(parent);
 367
 368        uc_pdata->type = REGULATOR_TYPE_BUCK;
 369
 370        switch (type) {
 371        case PALMAS:
 372        case TPS659038:
 373                switch (dev->driver_data) {
 374                case 123:
 375                case 12:
 376                        uc_pdata->ctrl_reg = palmas_smps_ctrl[type][0];
 377                        uc_pdata->volt_reg = palmas_smps_volt[type][0];
 378                        break;
 379                case 3:
 380                        uc_pdata->ctrl_reg = palmas_smps_ctrl[type][1];
 381                        uc_pdata->volt_reg = palmas_smps_volt[type][1];
 382                        break;
 383                case 45:
 384                        uc_pdata->ctrl_reg = palmas_smps_ctrl[type][2];
 385                        uc_pdata->volt_reg = palmas_smps_volt[type][2];
 386                        break;
 387                case 6:
 388                case 7:
 389                case 8:
 390                case 9:
 391                case 10:
 392                        idx = dev->driver_data - 3;
 393                        uc_pdata->ctrl_reg = palmas_smps_ctrl[type][idx];
 394                        uc_pdata->volt_reg = palmas_smps_volt[type][idx];
 395                        break;
 396
 397                default:
 398                        printf("Wrong ID for regulator\n");
 399                }
 400                break;
 401
 402        case TPS65917:
 403                switch (dev->driver_data) {
 404                case 1:
 405                case 2:
 406                case 3:
 407                case 4:
 408                case 5:
 409                        idx = dev->driver_data - 1;
 410                        uc_pdata->ctrl_reg = palmas_smps_ctrl[type][idx];
 411                        uc_pdata->volt_reg = palmas_smps_volt[type][idx];
 412                        break;
 413                case 12:
 414                        idx = 0;
 415                        uc_pdata->ctrl_reg = palmas_smps_ctrl[type][idx];
 416                        uc_pdata->volt_reg = palmas_smps_volt[type][idx];
 417                        break;
 418                default:
 419                        printf("Wrong ID for regulator\n");
 420                }
 421                break;
 422
 423        default:
 424                        printf("Invalid PMIC ID\n");
 425        }
 426
 427        return 0;
 428}
 429
 430static int smps_get_value(struct udevice *dev)
 431{
 432        int uV;
 433        int ret;
 434
 435        ret = palmas_smps_val(dev, PMIC_OP_GET, &uV);
 436        if (ret)
 437                return ret;
 438
 439        return uV;
 440}
 441
 442static int smps_set_value(struct udevice *dev, int uV)
 443{
 444        return palmas_smps_val(dev, PMIC_OP_SET, &uV);
 445}
 446
 447static int smps_get_enable(struct udevice *dev)
 448{
 449        bool enable = false;
 450        int ret;
 451
 452        ret = palmas_smps_enable(dev, PMIC_OP_GET, &enable);
 453        if (ret)
 454                return ret;
 455
 456        return enable;
 457}
 458
 459static int smps_set_enable(struct udevice *dev, bool enable)
 460{
 461        return palmas_smps_enable(dev, PMIC_OP_SET, &enable);
 462}
 463
 464static const struct dm_regulator_ops palmas_ldo_ops = {
 465        .get_value  = ldo_get_value,
 466        .set_value  = ldo_set_value,
 467        .get_enable = ldo_get_enable,
 468        .set_enable = ldo_set_enable,
 469};
 470
 471U_BOOT_DRIVER(palmas_ldo) = {
 472        .name = PALMAS_LDO_DRIVER,
 473        .id = UCLASS_REGULATOR,
 474        .ops = &palmas_ldo_ops,
 475        .probe = palmas_ldo_probe,
 476};
 477
 478static const struct dm_regulator_ops palmas_smps_ops = {
 479        .get_value  = smps_get_value,
 480        .set_value  = smps_set_value,
 481        .get_enable = smps_get_enable,
 482        .set_enable = smps_set_enable,
 483};
 484
 485U_BOOT_DRIVER(palmas_smps) = {
 486        .name = PALMAS_SMPS_DRIVER,
 487        .id = UCLASS_REGULATOR,
 488        .ops = &palmas_smps_ops,
 489        .probe = palmas_smps_probe,
 490};
 491