uboot/drivers/power/regulator/s2mps11_regulator.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 *  Copyright (C) 2018 Samsung Electronics
   4 *  Jaehoon Chung <jh80.chung@samsung.com>
   5 */
   6
   7#include <common.h>
   8#include <fdtdec.h>
   9#include <errno.h>
  10#include <dm.h>
  11#include <i2c.h>
  12#include <power/pmic.h>
  13#include <power/regulator.h>
  14#include <power/s2mps11.h>
  15
  16#define MODE(_id, _val, _name) { \
  17        .id = _id, \
  18        .register_value = _val, \
  19        .name = _name, \
  20}
  21
  22/* BUCK : 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 */
  23static struct dm_regulator_mode s2mps11_buck_modes[] = {
  24        MODE(OP_OFF, S2MPS11_BUCK_MODE_OFF, "OFF"),
  25        MODE(OP_STANDBY, S2MPS11_BUCK_MODE_STANDBY, "ON/OFF"),
  26        MODE(OP_ON, S2MPS11_BUCK_MODE_STANDBY, "ON"),
  27};
  28
  29static struct dm_regulator_mode s2mps11_ldo_modes[] = {
  30        MODE(OP_OFF, S2MPS11_LDO_MODE_OFF, "OFF"),
  31        MODE(OP_STANDBY, S2MPS11_LDO_MODE_STANDBY, "ON/OFF"),
  32        MODE(OP_STANDBY_LPM, S2MPS11_LDO_MODE_STANDBY_LPM, "ON/LPM"),
  33        MODE(OP_ON, S2MPS11_LDO_MODE_ON, "ON"),
  34};
  35
  36static const char s2mps11_buck_ctrl[] = {
  37        0xff, 0x25, 0x27, 0x29, 0x2b, 0x2d, 0x33, 0x35, 0x37, 0x39, 0x3b
  38};
  39
  40static const char s2mps11_buck_out[] = {
  41        0xff, 0x26, 0x28, 0x2a, 0x2c, 0x2f, 0x34, 0x36, 0x38, 0x3a, 0x3c
  42};
  43
  44static int s2mps11_buck_hex2volt(int buck, int hex)
  45{
  46        unsigned int uV = 0;
  47
  48        if (hex < 0)
  49                goto bad;
  50
  51        switch (buck) {
  52        case 7:
  53        case 8:
  54        case 10:
  55                if (hex > S2MPS11_BUCK7_8_10_VOLT_MAX_HEX)
  56                        goto bad;
  57
  58                uV = hex * S2MPS11_BUCK_HSTEP + S2MPS11_BUCK_UV_HMIN;
  59                break;
  60        case 9:
  61                if (hex > S2MPS11_BUCK9_VOLT_MAX_HEX)
  62                        goto bad;
  63                uV = hex * S2MPS11_BUCK9_STEP * 2 + S2MPS11_BUCK9_UV_MIN;
  64                break;
  65        default:
  66                if (buck == 5 && hex > S2MPS11_BUCK5_VOLT_MAX_HEX)
  67                        goto bad;
  68                else if (buck != 5 && hex > S2MPS11_BUCK_VOLT_MAX_HEX)
  69                        goto bad;
  70
  71                uV = hex * S2MPS11_BUCK_LSTEP + S2MPS11_BUCK_UV_MIN;
  72                break;
  73        }
  74
  75        return uV;
  76bad:
  77        pr_err("Value: %#x is wrong for BUCK%d", hex, buck);
  78        return -EINVAL;
  79}
  80
  81static int s2mps11_buck_volt2hex(int buck, int uV)
  82{
  83        int hex;
  84
  85        switch (buck) {
  86        case 7:
  87        case 8:
  88        case 10:
  89                hex = (uV - S2MPS11_BUCK_UV_HMIN) / S2MPS11_BUCK_HSTEP;
  90                if (hex > S2MPS11_BUCK7_8_10_VOLT_MAX_HEX)
  91                        goto bad;
  92
  93                break;
  94        case 9:
  95                hex = (uV - S2MPS11_BUCK9_UV_MIN) / S2MPS11_BUCK9_STEP;
  96                if (hex > S2MPS11_BUCK9_VOLT_MAX_HEX)
  97                        goto bad;
  98                break;
  99        default:
 100                hex = (uV - S2MPS11_BUCK_UV_MIN) / S2MPS11_BUCK_LSTEP;
 101                if (buck == 5 && hex > S2MPS11_BUCK5_VOLT_MAX_HEX)
 102                        goto bad;
 103                else if (buck != 5 && hex > S2MPS11_BUCK_VOLT_MAX_HEX)
 104                        goto bad;
 105                break;
 106        };
 107
 108        if (hex >= 0)
 109                return hex;
 110
 111bad:
 112        pr_err("Value: %d uV is wrong for BUCK%d", uV, buck);
 113        return -EINVAL;
 114}
 115
 116static int s2mps11_buck_val(struct udevice *dev, int op, int *uV)
 117{
 118        int hex, buck, ret;
 119        u32 mask, addr;
 120        u8 val;
 121
 122        buck = dev->driver_data;
 123        if (buck < 1 || buck > S2MPS11_BUCK_NUM) {
 124                pr_err("Wrong buck number: %d\n", buck);
 125                return -EINVAL;
 126        }
 127
 128        if (op == PMIC_OP_GET)
 129                *uV = 0;
 130
 131        addr = s2mps11_buck_out[buck];
 132
 133        switch (buck) {
 134        case 9:
 135                mask = S2MPS11_BUCK9_VOLT_MASK;
 136                break;
 137        default:
 138                mask = S2MPS11_BUCK_VOLT_MASK;
 139                break;
 140        }
 141
 142        ret = pmic_read(dev->parent, addr, &val, 1);
 143        if (ret)
 144                return ret;
 145
 146        if (op == PMIC_OP_GET) {
 147                val &= mask;
 148                ret = s2mps11_buck_hex2volt(buck, val);
 149                if (ret < 0)
 150                        return ret;
 151                *uV = ret;
 152                return 0;
 153        }
 154
 155        hex = s2mps11_buck_volt2hex(buck, *uV);
 156        if (hex < 0)
 157                return hex;
 158
 159        val &= ~mask;
 160        val |= hex;
 161        ret = pmic_write(dev->parent, addr, &val, 1);
 162
 163        return ret;
 164}
 165
 166static int s2mps11_buck_mode(struct udevice *dev, int op, int *opmode)
 167{
 168        unsigned int addr, mode;
 169        unsigned char val;
 170        int buck, ret;
 171
 172        buck = dev->driver_data;
 173        if (buck < 1 || buck > S2MPS11_BUCK_NUM) {
 174                pr_err("Wrong buck number: %d\n", buck);
 175                return -EINVAL;
 176        }
 177
 178        addr = s2mps11_buck_ctrl[buck];
 179
 180        ret = pmic_read(dev->parent, addr, &val, 1);
 181        if (ret)
 182                return ret;
 183
 184        if (op == PMIC_OP_GET) {
 185                val &= (S2MPS11_BUCK_MODE_MASK << S2MPS11_BUCK_MODE_SHIFT);
 186                switch (val) {
 187                case S2MPS11_BUCK_MODE_OFF:
 188                        *opmode = OP_OFF;
 189                        break;
 190                case S2MPS11_BUCK_MODE_STANDBY:
 191                        *opmode = OP_STANDBY;
 192                        break;
 193                case S2MPS11_BUCK_MODE_ON:
 194                        *opmode = OP_ON;
 195                        break;
 196                default:
 197                        return -EINVAL;
 198                }
 199                return 0;
 200        }
 201
 202        switch (*opmode) {
 203        case OP_OFF:
 204                mode = S2MPS11_BUCK_MODE_OFF;
 205                break;
 206        case OP_STANDBY:
 207                mode = S2MPS11_BUCK_MODE_STANDBY;
 208                break;
 209        case OP_ON:
 210                mode = S2MPS11_BUCK_MODE_ON;
 211                break;
 212        default:
 213                pr_err("Wrong mode: %d for buck: %d\n", *opmode, buck);
 214                return -EINVAL;
 215        }
 216
 217        val &= ~(S2MPS11_BUCK_MODE_MASK << S2MPS11_BUCK_MODE_SHIFT);
 218        val |= mode;
 219        ret = pmic_write(dev->parent, addr, &val, 1);
 220
 221        return ret;
 222}
 223
 224static int s2mps11_buck_enable(struct udevice *dev, int op, bool *enable)
 225{
 226        int ret, on_off;
 227
 228        if (op == PMIC_OP_GET) {
 229                ret = s2mps11_buck_mode(dev, op, &on_off);
 230                if (ret)
 231                        return ret;
 232                switch (on_off) {
 233                case OP_OFF:
 234                        *enable = false;
 235                        break;
 236                case OP_ON:
 237                        *enable = true;
 238                        break;
 239                default:
 240                        return -EINVAL;
 241                }
 242        } else if (op == PMIC_OP_SET) {
 243                if (*enable)
 244                        on_off = OP_ON;
 245                else
 246                        on_off = OP_OFF;
 247
 248                ret = s2mps11_buck_mode(dev, op, &on_off);
 249                if (ret)
 250                        return ret;
 251        }
 252
 253        return 0;
 254}
 255
 256static int buck_get_value(struct udevice *dev)
 257{
 258        int uV;
 259        int ret;
 260
 261        ret = s2mps11_buck_val(dev, PMIC_OP_GET, &uV);
 262        if (ret)
 263                return ret;
 264        return uV;
 265}
 266
 267static int buck_set_value(struct udevice *dev, int uV)
 268{
 269        return s2mps11_buck_val(dev, PMIC_OP_SET, &uV);
 270}
 271
 272static int buck_get_enable(struct udevice *dev)
 273{
 274        bool enable = false;
 275        int ret;
 276
 277        ret = s2mps11_buck_enable(dev, PMIC_OP_GET, &enable);
 278        if (ret)
 279                return ret;
 280        return enable;
 281}
 282
 283static int buck_set_enable(struct udevice *dev, bool enable)
 284{
 285        return s2mps11_buck_enable(dev, PMIC_OP_SET, &enable);
 286}
 287
 288static int buck_get_mode(struct udevice *dev)
 289{
 290        int mode;
 291        int ret;
 292
 293        ret = s2mps11_buck_mode(dev, PMIC_OP_GET, &mode);
 294        if (ret)
 295                return ret;
 296
 297        return mode;
 298}
 299
 300static int buck_set_mode(struct udevice *dev, int mode)
 301{
 302        return s2mps11_buck_mode(dev, PMIC_OP_SET, &mode);
 303}
 304
 305static int s2mps11_buck_probe(struct udevice *dev)
 306{
 307        struct dm_regulator_uclass_platdata *uc_pdata;
 308
 309        uc_pdata = dev_get_uclass_platdata(dev);
 310
 311        uc_pdata->type = REGULATOR_TYPE_BUCK;
 312        uc_pdata->mode = s2mps11_buck_modes;
 313        uc_pdata->mode_count = ARRAY_SIZE(s2mps11_buck_modes);
 314
 315        return 0;
 316}
 317
 318static const struct dm_regulator_ops s2mps11_buck_ops = {
 319        .get_value      = buck_get_value,
 320        .set_value      = buck_set_value,
 321        .get_enable     = buck_get_enable,
 322        .set_enable     = buck_set_enable,
 323        .get_mode       = buck_get_mode,
 324        .set_mode       = buck_set_mode,
 325};
 326
 327U_BOOT_DRIVER(s2mps11_buck) = {
 328        .name = S2MPS11_BUCK_DRIVER,
 329        .id = UCLASS_REGULATOR,
 330        .ops = &s2mps11_buck_ops,
 331        .probe = s2mps11_buck_probe,
 332};
 333
 334static int s2mps11_ldo_hex2volt(int ldo, int hex)
 335{
 336        unsigned int uV = 0;
 337
 338        if (hex > S2MPS11_LDO_VOLT_MAX_HEX) {
 339                pr_err("Value: %#x is wrong for LDO%d", hex, ldo);
 340                return -EINVAL;
 341        }
 342
 343        switch (ldo) {
 344        case 1:
 345        case 6:
 346        case 11:
 347        case 22:
 348        case 23:
 349                uV = hex * S2MPS11_LDO_STEP + S2MPS11_LDO_UV_MIN;
 350                break;
 351        default:
 352                uV = hex * S2MPS11_LDO_STEP * 2 + S2MPS11_LDO_UV_MIN;
 353                break;
 354        }
 355
 356        return uV;
 357}
 358
 359static int s2mps11_ldo_volt2hex(int ldo, int uV)
 360{
 361        int hex = 0;
 362
 363        switch (ldo) {
 364        case 1:
 365        case 6:
 366        case 11:
 367        case 22:
 368        case 23:
 369                hex = (uV - S2MPS11_LDO_UV_MIN) / S2MPS11_LDO_STEP;
 370                break;
 371        default:
 372                hex = (uV - S2MPS11_LDO_UV_MIN) / (S2MPS11_LDO_STEP * 2);
 373                break;
 374        }
 375
 376        if (hex >= 0 && hex <= S2MPS11_LDO_VOLT_MAX_HEX)
 377                return hex;
 378
 379        pr_err("Value: %d uV is wrong for LDO%d", uV, ldo);
 380        return -EINVAL;
 381
 382        return 0;
 383}
 384
 385static int s2mps11_ldo_val(struct udevice *dev, int op, int *uV)
 386{
 387        unsigned int addr;
 388        unsigned char val;
 389        int hex, ldo, ret;
 390
 391        ldo = dev->driver_data;
 392        if (ldo < 1 || ldo > S2MPS11_LDO_NUM) {
 393                pr_err("Wrong ldo number: %d\n", ldo);
 394                return -EINVAL;
 395        }
 396
 397        addr = S2MPS11_REG_L1CTRL + ldo - 1;
 398
 399        ret = pmic_read(dev->parent, addr, &val, 1);
 400        if (ret)
 401                return ret;
 402
 403        if (op == PMIC_OP_GET) {
 404                *uV = 0;
 405                val &= S2MPS11_LDO_VOLT_MASK;
 406                ret = s2mps11_ldo_hex2volt(ldo, val);
 407                if (ret < 0)
 408                        return ret;
 409
 410                *uV = ret;
 411                return 0;
 412        }
 413
 414        hex = s2mps11_ldo_volt2hex(ldo, *uV);
 415        if (hex < 0)
 416                return hex;
 417
 418        val &= ~S2MPS11_LDO_VOLT_MASK;
 419        val |= hex;
 420        ret = pmic_write(dev->parent, addr, &val, 1);
 421
 422        return ret;
 423}
 424
 425static int s2mps11_ldo_mode(struct udevice *dev, int op, int *opmode)
 426{
 427        unsigned int addr, mode;
 428        unsigned char val;
 429        int ldo, ret;
 430
 431        ldo = dev->driver_data;
 432        if (ldo < 1 || ldo > S2MPS11_LDO_NUM) {
 433                pr_err("Wrong ldo number: %d\n", ldo);
 434                return -EINVAL;
 435        }
 436        addr = S2MPS11_REG_L1CTRL + ldo - 1;
 437
 438        ret = pmic_read(dev->parent, addr, &val, 1);
 439        if (ret)
 440                return ret;
 441
 442        if (op == PMIC_OP_GET) {
 443                val &= (S2MPS11_LDO_MODE_MASK << S2MPS11_LDO_MODE_SHIFT);
 444                switch (val) {
 445                case S2MPS11_LDO_MODE_OFF:
 446                        *opmode = OP_OFF;
 447                        break;
 448                case S2MPS11_LDO_MODE_STANDBY:
 449                        *opmode = OP_STANDBY;
 450                        break;
 451                case S2MPS11_LDO_MODE_STANDBY_LPM:
 452                        *opmode = OP_STANDBY_LPM;
 453                        break;
 454                case S2MPS11_LDO_MODE_ON:
 455                        *opmode = OP_ON;
 456                        break;
 457                default:
 458                        return -EINVAL;
 459                }
 460                return 0;
 461        }
 462
 463        switch (*opmode) {
 464        case OP_OFF:
 465                mode = S2MPS11_LDO_MODE_OFF;
 466                break;
 467        case OP_STANDBY:
 468                mode = S2MPS11_LDO_MODE_STANDBY;
 469                break;
 470        case OP_STANDBY_LPM:
 471                mode = S2MPS11_LDO_MODE_STANDBY_LPM;
 472                break;
 473        case OP_ON:
 474                mode = S2MPS11_LDO_MODE_ON;
 475                break;
 476        default:
 477                pr_err("Wrong mode: %d for ldo: %d\n", *opmode, ldo);
 478                return -EINVAL;
 479        }
 480
 481        val &= ~(S2MPS11_LDO_MODE_MASK << S2MPS11_LDO_MODE_SHIFT);
 482        val |= mode;
 483        ret = pmic_write(dev->parent, addr, &val, 1);
 484
 485        return ret;
 486}
 487
 488static int s2mps11_ldo_enable(struct udevice *dev, int op, bool *enable)
 489{
 490        int ret, on_off;
 491
 492        if (op == PMIC_OP_GET) {
 493                ret = s2mps11_ldo_mode(dev, op, &on_off);
 494                if (ret)
 495                        return ret;
 496                switch (on_off) {
 497                case OP_OFF:
 498                        *enable = false;
 499                        break;
 500                case OP_ON:
 501                        *enable = true;
 502                        break;
 503                default:
 504                        return -EINVAL;
 505                }
 506        } else if (op == PMIC_OP_SET) {
 507                if (*enable)
 508                        on_off = OP_ON;
 509                else
 510                        on_off = OP_OFF;
 511
 512                ret = s2mps11_ldo_mode(dev, op, &on_off);
 513                if (ret)
 514                        return ret;
 515        }
 516
 517        return 0;
 518}
 519
 520static int ldo_get_value(struct udevice *dev)
 521{
 522        int uV;
 523        int ret;
 524
 525        ret = s2mps11_ldo_val(dev, PMIC_OP_GET, &uV);
 526        if (ret)
 527                return ret;
 528
 529        return uV;
 530}
 531
 532static int ldo_set_value(struct udevice *dev, int uV)
 533{
 534        return s2mps11_ldo_val(dev, PMIC_OP_SET, &uV);
 535}
 536
 537static int ldo_get_enable(struct udevice *dev)
 538{
 539        bool enable = false;
 540        int ret;
 541
 542        ret = s2mps11_ldo_enable(dev, PMIC_OP_GET, &enable);
 543        if (ret)
 544                return ret;
 545        return enable;
 546}
 547
 548static int ldo_set_enable(struct udevice *dev, bool enable)
 549{
 550        return s2mps11_ldo_enable(dev, PMIC_OP_SET, &enable);
 551}
 552
 553static int ldo_get_mode(struct udevice *dev)
 554{
 555        int mode, ret;
 556
 557        ret = s2mps11_ldo_mode(dev, PMIC_OP_GET, &mode);
 558        if (ret)
 559                return ret;
 560        return mode;
 561}
 562
 563static int ldo_set_mode(struct udevice *dev, int mode)
 564{
 565        return s2mps11_ldo_mode(dev, PMIC_OP_SET, &mode);
 566}
 567
 568static int s2mps11_ldo_probe(struct udevice *dev)
 569{
 570        struct dm_regulator_uclass_platdata *uc_pdata;
 571
 572        uc_pdata = dev_get_uclass_platdata(dev);
 573        uc_pdata->type = REGULATOR_TYPE_LDO;
 574        uc_pdata->mode = s2mps11_ldo_modes;
 575        uc_pdata->mode_count = ARRAY_SIZE(s2mps11_ldo_modes);
 576
 577        return 0;
 578}
 579
 580static const struct dm_regulator_ops s2mps11_ldo_ops = {
 581        .get_value      = ldo_get_value,
 582        .set_value      = ldo_set_value,
 583        .get_enable     = ldo_get_enable,
 584        .set_enable     = ldo_set_enable,
 585        .get_mode       = ldo_get_mode,
 586        .set_mode       = ldo_set_mode,
 587};
 588
 589U_BOOT_DRIVER(s2mps11_ldo) = {
 590        .name = S2MPS11_LDO_DRIVER,
 591        .id = UCLASS_REGULATOR,
 592        .ops = &s2mps11_ldo_ops,
 593        .probe = s2mps11_ldo_probe,
 594};
 595