uboot/drivers/power/regulator/lp873x_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/lp873x.h>
  17
  18static const char lp873x_buck_ctrl[LP873X_BUCK_NUM] = {0x2, 0x4};
  19static const char lp873x_buck_volt[LP873X_BUCK_NUM] = {0x6, 0x7};
  20static const char lp873x_ldo_ctrl[LP873X_LDO_NUM] = {0x8, 0x9};
  21static const char lp873x_ldo_volt[LP873X_LDO_NUM] = {0xA, 0xB};
  22
  23static int lp873x_buck_enable(struct udevice *dev, int op, bool *enable)
  24{
  25        int ret;
  26        unsigned int adr;
  27        struct dm_regulator_uclass_platdata *uc_pdata;
  28
  29        uc_pdata = dev_get_uclass_platdata(dev);
  30        adr = uc_pdata->ctrl_reg;
  31
  32        ret = pmic_reg_read(dev->parent, adr);
  33        if (ret < 0)
  34                return ret;
  35
  36        if (op == PMIC_OP_GET) {
  37                ret &= LP873X_BUCK_MODE_MASK;
  38
  39                if (ret)
  40                        *enable = true;
  41                else
  42                        *enable = false;
  43
  44                return 0;
  45        } else if (op == PMIC_OP_SET) {
  46                if (*enable)
  47                        ret |= LP873X_BUCK_MODE_MASK;
  48                else
  49                        ret &= ~(LP873X_BUCK_MODE_MASK);
  50                ret = pmic_reg_write(dev->parent, adr, ret);
  51                if (ret)
  52                        return ret;
  53        }
  54
  55        return 0;
  56}
  57
  58static int lp873x_buck_volt2hex(int uV)
  59{
  60        if (uV > LP873X_BUCK_VOLT_MAX)
  61                return -EINVAL;
  62        else if (uV > 1400000)
  63                return (uV - 1420000) / 20000 + 0x9E;
  64        else if (uV > 730000)
  65                return (uV - 735000) / 5000 + 0x18;
  66        else if (uV >= 700000)
  67                return (uV - 700000) / 10000 + 0x1;
  68        else
  69                return -EINVAL;
  70}
  71
  72static int lp873x_buck_hex2volt(int hex)
  73{
  74        if (hex > LP873X_BUCK_VOLT_MAX_HEX)
  75                return -EINVAL;
  76        else if (hex > 0x9D)
  77                return 1400000 + (hex - 0x9D) * 20000;
  78        else if (hex > 0x17)
  79                return 730000 + (hex - 0x17) * 5000;
  80        else if (hex >= 0x14)
  81                return 700000 + (hex - 0x14) * 10000;
  82        else
  83                return -EINVAL;
  84}
  85
  86static int lp873x_buck_val(struct udevice *dev, int op, int *uV)
  87{
  88        unsigned int hex, adr;
  89        int ret;
  90        struct dm_regulator_uclass_platdata *uc_pdata;
  91
  92        uc_pdata = dev_get_uclass_platdata(dev);
  93
  94        if (op == PMIC_OP_GET)
  95                *uV = 0;
  96
  97        adr = uc_pdata->volt_reg;
  98
  99        ret = pmic_reg_read(dev->parent, adr);
 100        if (ret < 0)
 101                return ret;
 102
 103        if (op == PMIC_OP_GET) {
 104                ret &= LP873X_BUCK_VOLT_MASK;
 105                ret = lp873x_buck_hex2volt(ret);
 106                if (ret < 0)
 107                        return ret;
 108                *uV = ret;
 109
 110                return 0;
 111        }
 112
 113        hex = lp873x_buck_volt2hex(*uV);
 114        if (hex < 0)
 115                return hex;
 116
 117        ret &= 0x0;
 118        ret |= hex;
 119
 120        ret = pmic_reg_write(dev->parent, adr, ret);
 121
 122        return ret;
 123}
 124
 125static int lp873x_ldo_enable(struct udevice *dev, int op, bool *enable)
 126{
 127        int ret;
 128        unsigned int adr;
 129        struct dm_regulator_uclass_platdata *uc_pdata;
 130
 131        uc_pdata = dev_get_uclass_platdata(dev);
 132        adr = uc_pdata->ctrl_reg;
 133
 134        ret = pmic_reg_read(dev->parent, adr);
 135        if (ret < 0)
 136                return ret;
 137
 138        if (op == PMIC_OP_GET) {
 139                ret &= LP873X_LDO_MODE_MASK;
 140
 141                if (ret)
 142                        *enable = true;
 143                else
 144                        *enable = false;
 145
 146                return 0;
 147        } else if (op == PMIC_OP_SET) {
 148                if (*enable)
 149                        ret |= LP873X_LDO_MODE_MASK;
 150                else
 151                        ret &= ~(LP873X_LDO_MODE_MASK);
 152
 153                ret = pmic_reg_write(dev->parent, adr, ret);
 154                if (ret)
 155                        return ret;
 156        }
 157
 158        return 0;
 159}
 160
 161static int lp873x_ldo_volt2hex(int uV)
 162{
 163        if (uV > LP873X_LDO_VOLT_MAX)
 164                return -EINVAL;
 165
 166        return (uV - 800000) / 100000;
 167}
 168
 169static int lp873x_ldo_hex2volt(int hex)
 170{
 171        if (hex > LP873X_LDO_VOLT_MAX_HEX)
 172                return -EINVAL;
 173
 174        if (!hex)
 175                return 0;
 176
 177        return (hex * 100000) + 800000;
 178}
 179
 180static int lp873x_ldo_val(struct udevice *dev, int op, int *uV)
 181{
 182        unsigned int hex, adr;
 183        int ret;
 184
 185        struct dm_regulator_uclass_platdata *uc_pdata;
 186
 187        if (op == PMIC_OP_GET)
 188                *uV = 0;
 189
 190        uc_pdata = dev_get_uclass_platdata(dev);
 191
 192        adr = uc_pdata->volt_reg;
 193
 194        ret = pmic_reg_read(dev->parent, adr);
 195        if (ret < 0)
 196                return ret;
 197
 198        if (op == PMIC_OP_GET) {
 199                ret &= LP873X_LDO_VOLT_MASK;
 200                ret = lp873x_ldo_hex2volt(ret);
 201                if (ret < 0)
 202                        return ret;
 203                *uV = ret;
 204                return 0;
 205        }
 206
 207        hex = lp873x_ldo_volt2hex(*uV);
 208        if (hex < 0)
 209                return hex;
 210
 211        ret &= ~LP873X_LDO_VOLT_MASK;
 212        ret |= hex;
 213        if (*uV > 1650000)
 214                ret |= 0x80;
 215        ret = pmic_reg_write(dev->parent, adr, ret);
 216
 217        return ret;
 218}
 219
 220static int lp873x_ldo_probe(struct udevice *dev)
 221{
 222        struct dm_regulator_uclass_platdata *uc_pdata;
 223
 224        uc_pdata = dev_get_uclass_platdata(dev);
 225        uc_pdata->type = REGULATOR_TYPE_LDO;
 226
 227        int idx = dev->driver_data;
 228        if (idx >= LP873X_LDO_NUM) {
 229                printf("Wrong ID for regulator\n");
 230                return -1;
 231        }
 232
 233        uc_pdata->ctrl_reg = lp873x_ldo_ctrl[idx];
 234        uc_pdata->volt_reg = lp873x_ldo_volt[idx];
 235
 236        return 0;
 237}
 238
 239static int ldo_get_value(struct udevice *dev)
 240{
 241        int uV;
 242        int ret;
 243
 244        ret = lp873x_ldo_val(dev, PMIC_OP_GET, &uV);
 245        if (ret)
 246                return ret;
 247
 248        return uV;
 249}
 250
 251static int ldo_set_value(struct udevice *dev, int uV)
 252{
 253        return lp873x_ldo_val(dev, PMIC_OP_SET, &uV);
 254}
 255
 256static int ldo_get_enable(struct udevice *dev)
 257{
 258        bool enable = false;
 259        int ret;
 260
 261        ret = lp873x_ldo_enable(dev, PMIC_OP_GET, &enable);
 262        if (ret)
 263                return ret;
 264
 265        return enable;
 266}
 267
 268static int ldo_set_enable(struct udevice *dev, bool enable)
 269{
 270        return lp873x_ldo_enable(dev, PMIC_OP_SET, &enable);
 271}
 272
 273static int lp873x_buck_probe(struct udevice *dev)
 274{
 275        struct dm_regulator_uclass_platdata *uc_pdata;
 276        int idx;
 277
 278        uc_pdata = dev_get_uclass_platdata(dev);
 279        uc_pdata->type = REGULATOR_TYPE_BUCK;
 280
 281        idx = dev->driver_data;
 282        if (idx >= LP873X_BUCK_NUM) {
 283                printf("Wrong ID for regulator\n");
 284                return -1;
 285        }
 286
 287        uc_pdata->ctrl_reg = lp873x_buck_ctrl[idx];
 288        uc_pdata->volt_reg = lp873x_buck_volt[idx];
 289
 290        return 0;
 291}
 292
 293static int buck_get_value(struct udevice *dev)
 294{
 295        int uV;
 296        int ret;
 297
 298        ret = lp873x_buck_val(dev, PMIC_OP_GET, &uV);
 299        if (ret)
 300                return ret;
 301
 302        return uV;
 303}
 304
 305static int buck_set_value(struct udevice *dev, int uV)
 306{
 307        return lp873x_buck_val(dev, PMIC_OP_SET, &uV);
 308}
 309
 310static int buck_get_enable(struct udevice *dev)
 311{
 312        bool enable = false;
 313        int ret;
 314
 315
 316        ret = lp873x_buck_enable(dev, PMIC_OP_GET, &enable);
 317        if (ret)
 318                return ret;
 319
 320        return enable;
 321}
 322
 323static int buck_set_enable(struct udevice *dev, bool enable)
 324{
 325        return lp873x_buck_enable(dev, PMIC_OP_SET, &enable);
 326}
 327
 328static const struct dm_regulator_ops lp873x_ldo_ops = {
 329        .get_value  = ldo_get_value,
 330        .set_value  = ldo_set_value,
 331        .get_enable = ldo_get_enable,
 332        .set_enable = ldo_set_enable,
 333};
 334
 335U_BOOT_DRIVER(lp873x_ldo) = {
 336        .name = LP873X_LDO_DRIVER,
 337        .id = UCLASS_REGULATOR,
 338        .ops = &lp873x_ldo_ops,
 339        .probe = lp873x_ldo_probe,
 340};
 341
 342static const struct dm_regulator_ops lp873x_buck_ops = {
 343        .get_value  = buck_get_value,
 344        .set_value  = buck_set_value,
 345        .get_enable = buck_get_enable,
 346        .set_enable = buck_set_enable,
 347};
 348
 349U_BOOT_DRIVER(lp873x_buck) = {
 350        .name = LP873X_BUCK_DRIVER,
 351        .id = UCLASS_REGULATOR,
 352        .ops = &lp873x_buck_ops,
 353        .probe = lp873x_buck_probe,
 354};
 355