uboot/drivers/power/regulator/rk808.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2015 Google, Inc
   3 * Written by Simon Glass <sjg@chromium.org>
   4 *
   5 * Based on Rockchip's drivers/power/pmic/pmic_rk808.c:
   6 * Copyright (C) 2012 rockchips
   7 * zyw <zyw@rock-chips.com>
   8 *
   9 * SPDX-License-Identifier:     GPL-2.0+
  10 */
  11
  12#include <common.h>
  13#include <dm.h>
  14#include <errno.h>
  15#include <power/rk808_pmic.h>
  16#include <power/pmic.h>
  17#include <power/regulator.h>
  18
  19#ifndef CONFIG_SPL_BUILD
  20#define ENABLE_DRIVER
  21#endif
  22
  23struct rk808_reg_info {
  24        uint min_uv;
  25        uint step_uv;
  26        s8 vsel_reg;
  27        u8 vsel_bits;
  28};
  29
  30static const struct rk808_reg_info rk808_buck[] = {
  31        { 712500, 12500, REG_BUCK1_ON_VSEL, 6, },
  32        { 712500, 12500, REG_BUCK2_ON_VSEL, 6, },
  33        { 712500, 12500, -1, 6, },
  34        { 1800000, 100000, REG_BUCK4_ON_VSEL, 4, },
  35};
  36
  37static const struct rk808_reg_info rk808_ldo[] = {
  38        { 1800000, 100000, LDO1_ON_VSEL, 5, },
  39        { 1800000, 100000, LDO2_ON_VSEL, 5, },
  40        { 800000, 100000, LDO3_ON_VSEL, 4, },
  41        { 1800000, 100000, LDO4_ON_VSEL, 5, },
  42        { 1800000, 100000, LDO5_ON_VSEL, 5, },
  43        { 800000, 100000, LDO6_ON_VSEL, 5, },
  44        { 800000, 100000, LDO7_ON_VSEL, 5, },
  45        { 1800000, 100000, LDO8_ON_VSEL, 5, },
  46};
  47
  48
  49static int _buck_set_value(struct udevice *pmic, int buck, int uvolt)
  50{
  51        const struct rk808_reg_info *info = &rk808_buck[buck - 1];
  52        int mask = (1 << info->vsel_bits) - 1;
  53        int val;
  54
  55        if (info->vsel_reg == -1)
  56                return -ENOSYS;
  57        val = (uvolt - info->min_uv) / info->step_uv;
  58        debug("%s: reg=%x, mask=%x, val=%x\n", __func__, info->vsel_reg, mask,
  59              val);
  60
  61        return pmic_clrsetbits(pmic, info->vsel_reg, mask, val);
  62}
  63
  64static int _buck_set_enable(struct udevice *pmic, int buck, bool enable)
  65{
  66        uint mask;
  67        int ret;
  68
  69        buck--;
  70        mask = 1 << buck;
  71        if (enable) {
  72                ret = pmic_clrsetbits(pmic, DCDC_ILMAX, 0, 3 << (buck * 2));
  73                if (ret)
  74                        return ret;
  75                ret = pmic_clrsetbits(pmic, REG_DCDC_UV_ACT, 1 << buck, 0);
  76                if (ret)
  77                        return ret;
  78        }
  79
  80        return pmic_clrsetbits(pmic, REG_DCDC_EN, mask, enable ? mask : 0);
  81}
  82
  83#ifdef ENABLE_DRIVER
  84static int buck_get_value(struct udevice *dev)
  85{
  86        int buck = dev->driver_data - 1;
  87        const struct rk808_reg_info *info = &rk808_buck[buck];
  88        int mask = (1 << info->vsel_bits) - 1;
  89        int ret, val;
  90
  91        if (info->vsel_reg == -1)
  92                return -ENOSYS;
  93        ret = pmic_reg_read(dev->parent, info->vsel_reg);
  94        if (ret < 0)
  95                return ret;
  96        val = ret & mask;
  97
  98        return info->min_uv + val * info->step_uv;
  99}
 100
 101static int buck_set_value(struct udevice *dev, int uvolt)
 102{
 103        int buck = dev->driver_data;
 104
 105        return _buck_set_value(dev->parent, buck, uvolt);
 106}
 107
 108static int buck_set_enable(struct udevice *dev, bool enable)
 109{
 110        int buck = dev->driver_data;
 111
 112        return _buck_set_enable(dev->parent, buck, enable);
 113}
 114
 115static bool buck_get_enable(struct udevice *dev)
 116{
 117        int buck = dev->driver_data - 1;
 118        int ret;
 119        uint mask;
 120
 121        mask = 1 << buck;
 122
 123        ret = pmic_reg_read(dev->parent, REG_DCDC_EN);
 124        if (ret < 0)
 125                return ret;
 126
 127        return ret & mask ? true : false;
 128}
 129
 130static int ldo_get_value(struct udevice *dev)
 131{
 132        int ldo = dev->driver_data - 1;
 133        const struct rk808_reg_info *info = &rk808_ldo[ldo];
 134        int mask = (1 << info->vsel_bits) - 1;
 135        int ret, val;
 136
 137        if (info->vsel_reg == -1)
 138                return -ENOSYS;
 139        ret = pmic_reg_read(dev->parent, info->vsel_reg);
 140        if (ret < 0)
 141                return ret;
 142        val = ret & mask;
 143
 144        return info->min_uv + val * info->step_uv;
 145}
 146
 147static int ldo_set_value(struct udevice *dev, int uvolt)
 148{
 149        int ldo = dev->driver_data - 1;
 150        const struct rk808_reg_info *info = &rk808_ldo[ldo];
 151        int mask = (1 << info->vsel_bits) - 1;
 152        int val;
 153
 154        if (info->vsel_reg == -1)
 155                return -ENOSYS;
 156        val = (uvolt - info->min_uv) / info->step_uv;
 157        debug("%s: reg=%x, mask=%x, val=%x\n", __func__, info->vsel_reg, mask,
 158              val);
 159
 160        return pmic_clrsetbits(dev->parent, info->vsel_reg, mask, val);
 161}
 162
 163static int ldo_set_enable(struct udevice *dev, bool enable)
 164{
 165        int ldo = dev->driver_data - 1;
 166        uint mask;
 167
 168        mask = 1 << ldo;
 169
 170        return pmic_clrsetbits(dev->parent, REG_LDO_EN, mask,
 171                               enable ? mask : 0);
 172}
 173
 174static bool ldo_get_enable(struct udevice *dev)
 175{
 176        int ldo = dev->driver_data - 1;
 177        int ret;
 178        uint mask;
 179
 180        mask = 1 << ldo;
 181
 182        ret = pmic_reg_read(dev->parent, REG_LDO_EN);
 183        if (ret < 0)
 184                return ret;
 185
 186        return ret & mask ? true : false;
 187}
 188
 189static int switch_set_enable(struct udevice *dev, bool enable)
 190{
 191        int sw = dev->driver_data - 1;
 192        uint mask;
 193
 194        mask = 1 << (sw + 5);
 195
 196        return pmic_clrsetbits(dev->parent, REG_DCDC_EN, mask,
 197                               enable ? mask : 0);
 198}
 199
 200static bool switch_get_enable(struct udevice *dev)
 201{
 202        int sw = dev->driver_data - 1;
 203        int ret;
 204        uint mask;
 205
 206        mask = 1 << (sw + 5);
 207
 208        ret = pmic_reg_read(dev->parent, REG_DCDC_EN);
 209        if (ret < 0)
 210                return ret;
 211
 212        return ret & mask ? true : false;
 213}
 214
 215static int rk808_buck_probe(struct udevice *dev)
 216{
 217        struct dm_regulator_uclass_platdata *uc_pdata;
 218
 219        uc_pdata = dev_get_uclass_platdata(dev);
 220
 221        uc_pdata->type = REGULATOR_TYPE_BUCK;
 222        uc_pdata->mode_count = 0;
 223
 224        return 0;
 225}
 226
 227static int rk808_ldo_probe(struct udevice *dev)
 228{
 229        struct dm_regulator_uclass_platdata *uc_pdata;
 230
 231        uc_pdata = dev_get_uclass_platdata(dev);
 232
 233        uc_pdata->type = REGULATOR_TYPE_LDO;
 234        uc_pdata->mode_count = 0;
 235
 236        return 0;
 237}
 238
 239static int rk808_switch_probe(struct udevice *dev)
 240{
 241        struct dm_regulator_uclass_platdata *uc_pdata;
 242
 243        uc_pdata = dev_get_uclass_platdata(dev);
 244
 245        uc_pdata->type = REGULATOR_TYPE_FIXED;
 246        uc_pdata->mode_count = 0;
 247
 248        return 0;
 249}
 250
 251static const struct dm_regulator_ops rk808_buck_ops = {
 252        .get_value  = buck_get_value,
 253        .set_value  = buck_set_value,
 254        .get_enable = buck_get_enable,
 255        .set_enable = buck_set_enable,
 256};
 257
 258static const struct dm_regulator_ops rk808_ldo_ops = {
 259        .get_value  = ldo_get_value,
 260        .set_value  = ldo_set_value,
 261        .get_enable = ldo_get_enable,
 262        .set_enable = ldo_set_enable,
 263};
 264
 265static const struct dm_regulator_ops rk808_switch_ops = {
 266        .get_enable = switch_get_enable,
 267        .set_enable = switch_set_enable,
 268};
 269
 270U_BOOT_DRIVER(rk808_buck) = {
 271        .name = "rk808_buck",
 272        .id = UCLASS_REGULATOR,
 273        .ops = &rk808_buck_ops,
 274        .probe = rk808_buck_probe,
 275};
 276
 277U_BOOT_DRIVER(rk808_ldo) = {
 278        .name = "rk808_ldo",
 279        .id = UCLASS_REGULATOR,
 280        .ops = &rk808_ldo_ops,
 281        .probe = rk808_ldo_probe,
 282};
 283
 284U_BOOT_DRIVER(rk808_switch) = {
 285        .name = "rk808_switch",
 286        .id = UCLASS_REGULATOR,
 287        .ops = &rk808_switch_ops,
 288        .probe = rk808_switch_probe,
 289};
 290#endif
 291
 292int rk808_spl_configure_buck(struct udevice *pmic, int buck, int uvolt)
 293{
 294        int ret;
 295
 296        ret = _buck_set_value(pmic, buck, uvolt);
 297        if (ret)
 298                return ret;
 299
 300        return _buck_set_enable(pmic, buck, true);
 301}
 302