uboot/drivers/power/regulator/da9063.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 *  Copyright (C) 2018 Flowbird
   4 *  Martin Fuzzey  <martin.fuzzey@flowbird.group>
   5 */
   6
   7#include <common.h>
   8#include <dm.h>
   9#include <linux/bitops.h>
  10#include <power/da9063_pmic.h>
  11#include <power/pmic.h>
  12#include <power/regulator.h>
  13
  14#define DA9063_BUCK_EN          0x01
  15#define DA9063_LDO_EN           0x01
  16#define DA9063_VBUCK_MASK       0x7F
  17#define DA9063_BUCK_SL          0x80
  18#define DA9063_LDO_SL           0x80
  19
  20#define DA9063_VLDO1_MASK       0x3F
  21#define DA9063_VLDO2_MASK       0x3F
  22#define DA9063_VLDO3_MASK       0x7F
  23#define DA9063_VLDO4_MASK       0x7F
  24#define DA9063_VLDO5_MASK       0x3F
  25#define DA9063_VLDO6_MASK       0x3F
  26#define DA9063_VLDO7_MASK       0x3F
  27#define DA9063_VLDO8_MASK       0x3F
  28#define DA9063_VLDO9_MASK       0x3F
  29#define DA9063_VLDO10_MASK      0x3F
  30#define DA9063_VLDO11_MASK      0x3F
  31
  32#define DA9063_BUCK_MODE_MASK   0xC0
  33#define DA9063_BUCK_MODE_MANUAL 0x00
  34#define DA9063_BUCK_MODE_SLEEP  0x40
  35#define DA9063_BUCK_MODE_SYNC   0x80
  36#define DA9063_BUCK_MODE_AUTO   0xC0
  37
  38#define DA9063_BIO_ILIM_MASK    0x0F
  39#define DA9063_BMEM_ILIM_MASK   0xF0
  40#define DA9063_BPRO_ILIM_MASK   0x0F
  41#define DA9063_BPERI_ILIM_MASK  0xF0
  42#define DA9063_BCORE1_ILIM_MASK 0x0F
  43#define DA9063_BCORE2_ILIM_MASK 0xF0
  44
  45struct da9063_reg_info {
  46        uint min_uV;
  47        uint step_uV;
  48        uint max_uV;
  49        uint min_uA;
  50        uint step_uA;
  51        uint max_uA;
  52        uint en_reg;
  53        uint vsel_reg;
  54        uint mode_reg;
  55        uint ilim_reg;
  56        u8 en_mask;
  57        u8 vsel_mask;
  58        u8 ilim_mask;
  59        const char *dt_node_name;
  60        const int *current_limits;
  61};
  62
  63struct da9063_priv {
  64        const struct da9063_reg_info *reg_info;
  65};
  66
  67static struct dm_regulator_mode da9063_ldo_modes[] = {
  68        { .id = DA9063_LDOMODE_SLEEP,
  69                .register_value = DA9063_LDO_SL, .name = "SLEEP" },
  70        { .id = DA9063_LDOMODE_NORMAL,
  71                .register_value = 0, .name = "NORMAL" },
  72};
  73
  74#define DA9063_LDO(regl_name, min_mV, step_mV, max_mV) \
  75        .min_uV = (min_mV) * 1000, \
  76        .step_uV = (step_mV) * 1000, \
  77        .max_uV = (max_mV) * 1000, \
  78        .en_reg = DA9063_REG_##regl_name##_CONT, \
  79        .en_mask = DA9063_LDO_EN, \
  80        .vsel_reg = DA9063_REG_V##regl_name##_A, \
  81        .vsel_mask = DA9063_V##regl_name##_MASK, \
  82        .mode_reg = DA9063_REG_V##regl_name##_A \
  83
  84/* This array is directly indexed so must stay in numerical order */
  85static const struct da9063_reg_info da9063_ldo_info[] = {
  86        { DA9063_LDO(LDO1, 600, 20, 1860) },
  87        { DA9063_LDO(LDO2, 600, 20, 1860) },
  88        { DA9063_LDO(LDO3, 900, 20, 3440) },
  89        { DA9063_LDO(LDO4, 900, 20, 3440) },
  90        { DA9063_LDO(LDO5, 900, 50, 3600) },
  91        { DA9063_LDO(LDO6, 900, 50, 3600) },
  92        { DA9063_LDO(LDO7, 900, 50, 3600) },
  93        { DA9063_LDO(LDO8, 900, 50, 3600) },
  94        { DA9063_LDO(LDO9, 950, 50, 3600) },
  95        { DA9063_LDO(LDO10, 900, 50, 3600) },
  96        { DA9063_LDO(LDO11, 900, 50, 3600) },
  97};
  98
  99static struct dm_regulator_mode da9063_buck_modes[] = {
 100        { .id = DA9063_BUCKMODE_SLEEP,
 101                .register_value = DA9063_BUCK_MODE_SLEEP, .name = "SLEEP" },
 102        { .id = DA9063_BUCKMODE_SYNC,
 103                .register_value = DA9063_BUCK_MODE_SYNC, .name = "SYNC" },
 104        { .id = DA9063_BUCKMODE_AUTO,
 105                .register_value = DA9063_BUCK_MODE_AUTO, .name = "AUTO" },
 106};
 107
 108#define DA9063_BUCK(regl_name, dt_name, \
 109                    min_mV, step_mV, max_mV, \
 110                    min_mA, step_mA, max_mA, _ilim_reg) \
 111        .dt_node_name = dt_name, \
 112        .min_uV = (min_mV) * 1000, \
 113        .step_uV = (step_mV) * 1000, \
 114        .max_uV = (max_mV) * 1000, \
 115        .min_uA = (min_mA) * 1000, \
 116        .step_uA = (step_mA) * 1000, \
 117        .max_uA = (max_mA) * 1000, \
 118        .en_reg = DA9063_REG_##regl_name##_CONT, \
 119        .en_mask = DA9063_BUCK_EN, \
 120        .vsel_reg = DA9063_REG_V##regl_name##_A, \
 121        .vsel_mask = DA9063_VBUCK_MASK, \
 122        .mode_reg = DA9063_REG_##regl_name##_CFG, \
 123        .ilim_reg = DA9063_REG_BUCK_ILIM_##_ilim_reg, \
 124        .ilim_mask = DA9063_##regl_name##_ILIM_MASK
 125
 126static const struct da9063_reg_info da9063_buck_info[] = {
 127        /*                              mV              mA */
 128        { DA9063_BUCK(BCORE1, "bcore1", 300, 10, 1570,  500, 100, 2000, C) },
 129        { DA9063_BUCK(BCORE2, "bcore2", 300, 10, 1570,  500, 100, 2000, C) },
 130        { DA9063_BUCK(BPRO, "bpro",     530, 10, 1800,  500, 100, 2000, B) },
 131        { DA9063_BUCK(BMEM, "bmem",     800, 20, 3340,  1500, 100, 3000, A) },
 132        { DA9063_BUCK(BIO, "bio",       800, 20, 3340,  1500, 100, 3000, A) },
 133        { DA9063_BUCK(BPERI, "bperi",   800, 20, 3340,  1500, 100, 3000, B) },
 134};
 135
 136static int da9063_get_enable(struct udevice *dev)
 137{
 138        const struct da9063_priv *priv = dev_get_priv(dev);
 139        const struct da9063_reg_info *info = priv->reg_info;
 140        int ret;
 141
 142        ret = pmic_reg_read(dev->parent, info->en_reg);
 143        if (ret < 0)
 144                return ret;
 145
 146        return ret & info->en_mask ? true : false;
 147}
 148
 149static int da9063_set_enable(struct udevice *dev, bool enable)
 150{
 151        const struct da9063_priv *priv = dev_get_priv(dev);
 152        const struct da9063_reg_info *info = priv->reg_info;
 153
 154        return pmic_clrsetbits(dev->parent, info->en_reg,
 155                               info->en_mask, enable ? info->en_mask : 0);
 156}
 157
 158static int da9063_get_voltage(struct udevice *dev)
 159{
 160        const struct da9063_priv *priv = dev_get_priv(dev);
 161        const struct da9063_reg_info *info = priv->reg_info;
 162        int ret;
 163
 164        ret = pmic_reg_read(dev->parent, info->vsel_reg);
 165        if (ret < 0)
 166                return ret;
 167
 168        return info->min_uV + (ret & info->vsel_mask) * info->step_uV;
 169}
 170
 171static int da9063_set_voltage(struct udevice *dev, int uV)
 172{
 173        const struct da9063_priv *priv = dev_get_priv(dev);
 174        const struct da9063_reg_info *info = priv->reg_info;
 175        uint sel;
 176
 177        if (uV < info->min_uV || uV > info->max_uV)
 178                return -EINVAL;
 179
 180        sel = (uV - info->min_uV) / info->step_uV;
 181
 182        return pmic_clrsetbits(dev->parent, info->vsel_reg,
 183                               info->vsel_mask, sel);
 184}
 185
 186static const struct dm_regulator_mode
 187        *da9063_find_mode_by_id(int id,
 188                                const struct dm_regulator_mode *modes,
 189                                uint mode_count)
 190{
 191        for (; mode_count; mode_count--) {
 192                if (modes->id == id)
 193                        return modes;
 194                modes++;
 195        }
 196        return NULL;
 197}
 198
 199static int ldo_get_mode(struct udevice *dev)
 200{
 201        const struct da9063_priv *priv = dev_get_priv(dev);
 202        const struct da9063_reg_info *info = priv->reg_info;
 203        int val;
 204
 205        val = pmic_reg_read(dev->parent, info->mode_reg);
 206        if (val < 0)
 207                return val;
 208
 209        if (val & DA9063_LDO_SL)
 210                return DA9063_LDOMODE_SLEEP;
 211        else
 212                return DA9063_LDOMODE_NORMAL;
 213}
 214
 215static int ldo_set_mode(struct udevice *dev, int mode_id)
 216{
 217        const struct da9063_priv *priv = dev_get_priv(dev);
 218        const struct da9063_reg_info *info = priv->reg_info;
 219        const struct dm_regulator_mode *mode;
 220
 221        mode = da9063_find_mode_by_id(mode_id,
 222                                      da9063_ldo_modes,
 223                                      ARRAY_SIZE(da9063_ldo_modes));
 224        if (!mode)
 225                return -EINVAL;
 226
 227        return pmic_clrsetbits(dev->parent, info->mode_reg,
 228                               DA9063_LDO_SL, mode->register_value);
 229}
 230
 231static int buck_get_mode(struct udevice *dev)
 232{
 233        const struct da9063_priv *priv = dev_get_priv(dev);
 234        const struct da9063_reg_info *info = priv->reg_info;
 235        int i;
 236        int val;
 237
 238        val = pmic_reg_read(dev->parent, info->mode_reg);
 239        if (val < 0)
 240                return val;
 241
 242        val &= DA9063_BUCK_MODE_MASK;
 243        if (val == DA9063_BUCK_MODE_MANUAL) {
 244                val = pmic_reg_read(dev->parent, info->vsel_reg);
 245                if (val < 0)
 246                        return val;
 247
 248                if (val & DA9063_BUCK_SL)
 249                        return DA9063_BUCKMODE_SLEEP;
 250                else
 251                        return DA9063_BUCKMODE_SYNC;
 252        }
 253
 254        for (i = 0; i < ARRAY_SIZE(da9063_buck_modes); i++) {
 255                if (da9063_buck_modes[i].register_value == val)
 256                        return da9063_buck_modes[i].id;
 257        }
 258
 259        return -EINVAL;
 260}
 261
 262static int buck_set_mode(struct udevice *dev, int mode_id)
 263{
 264        const struct da9063_priv *priv = dev_get_priv(dev);
 265        const struct da9063_reg_info *info = priv->reg_info;
 266        const struct dm_regulator_mode *mode;
 267
 268        mode = da9063_find_mode_by_id(mode_id,
 269                                      da9063_buck_modes,
 270                                      ARRAY_SIZE(da9063_buck_modes));
 271        if (!mode)
 272                return -EINVAL;
 273
 274        return pmic_clrsetbits(dev->parent, info->mode_reg,
 275                               DA9063_BUCK_MODE_MASK, mode->register_value);
 276}
 277
 278static int buck_get_current_limit(struct udevice *dev)
 279{
 280        const struct da9063_priv *priv = dev_get_priv(dev);
 281        const struct da9063_reg_info *info = priv->reg_info;
 282        int val;
 283
 284        val = pmic_reg_read(dev->parent, info->ilim_reg);
 285        if (val < 0)
 286                return val;
 287
 288        val &= info->ilim_mask;
 289        val >>= (ffs(info->ilim_mask) - 1);
 290
 291        return info->min_uA + val * info->step_uA;
 292}
 293
 294static int buck_set_current_limit(struct udevice *dev, int uA)
 295{
 296        const struct da9063_priv *priv = dev_get_priv(dev);
 297        const struct da9063_reg_info *info = priv->reg_info;
 298        int val;
 299
 300        if (uA < info->min_uA || uA > info->max_uA)
 301                return -EINVAL;
 302
 303        val = (uA - info->min_uA) / info->step_uA;
 304        val <<= (ffs(info->ilim_mask) - 1);
 305
 306        return pmic_clrsetbits(dev->parent, info->ilim_reg,
 307                               info->ilim_mask, val);
 308}
 309
 310static int da9063_ldo_probe(struct udevice *dev)
 311{
 312        struct dm_regulator_uclass_plat *uc_pdata;
 313        struct da9063_priv *priv = dev_get_priv(dev);
 314
 315        /* LDOs are named numerically in DT so can directly index */
 316        if (dev->driver_data < 1 ||
 317            dev->driver_data > ARRAY_SIZE(da9063_ldo_info))
 318                return -EINVAL;
 319        priv->reg_info = &da9063_ldo_info[dev->driver_data - 1];
 320
 321        uc_pdata = dev_get_uclass_plat(dev);
 322        uc_pdata->type = REGULATOR_TYPE_LDO;
 323        uc_pdata->mode = da9063_ldo_modes;
 324        uc_pdata->mode_count = ARRAY_SIZE(da9063_ldo_modes);
 325
 326        return 0;
 327}
 328
 329static int da9063_buck_probe(struct udevice *dev)
 330{
 331        struct dm_regulator_uclass_plat *uc_pdata;
 332        struct da9063_priv *priv = dev_get_priv(dev);
 333        int i;
 334
 335        /* Bucks have names rather than numbers so need to match with DT */
 336        for (i = 0; i < ARRAY_SIZE(da9063_buck_info); i++) {
 337                const struct da9063_reg_info *info = &da9063_buck_info[i];
 338
 339                if (!strcmp(info->dt_node_name, dev->name)) {
 340                        priv->reg_info = info;
 341                        break;
 342                }
 343        }
 344        if (!priv->reg_info)
 345                return -ENODEV;
 346
 347        uc_pdata = dev_get_uclass_plat(dev);
 348        uc_pdata->type = REGULATOR_TYPE_BUCK;
 349        uc_pdata->mode = da9063_buck_modes;
 350        uc_pdata->mode_count = ARRAY_SIZE(da9063_buck_modes);
 351
 352        return 0;
 353}
 354
 355static const struct dm_regulator_ops da9063_ldo_ops = {
 356        .get_value  = da9063_get_voltage,
 357        .set_value  = da9063_set_voltage,
 358        .get_enable = da9063_get_enable,
 359        .set_enable = da9063_set_enable,
 360        .get_mode   = ldo_get_mode,
 361        .set_mode   = ldo_set_mode,
 362};
 363
 364U_BOOT_DRIVER(da9063_ldo) = {
 365        .name = DA9063_LDO_DRIVER,
 366        .id = UCLASS_REGULATOR,
 367        .ops = &da9063_ldo_ops,
 368        .probe = da9063_ldo_probe,
 369        .priv_auto      = sizeof(struct da9063_priv),
 370};
 371
 372static const struct dm_regulator_ops da9063_buck_ops = {
 373        .get_value  = da9063_get_voltage,
 374        .set_value  = da9063_set_voltage,
 375        .get_enable = da9063_get_enable,
 376        .set_enable = da9063_set_enable,
 377        .get_mode   = buck_get_mode,
 378        .set_mode   = buck_set_mode,
 379        .get_current = buck_get_current_limit,
 380        .set_current = buck_set_current_limit,
 381};
 382
 383U_BOOT_DRIVER(da9063_buck) = {
 384        .name = DA9063_BUCK_DRIVER,
 385        .id = UCLASS_REGULATOR,
 386        .ops = &da9063_buck_ops,
 387        .probe = da9063_buck_probe,
 388        .priv_auto      = sizeof(struct da9063_priv),
 389};
 390