linux/drivers/regulator/hi6421v530-regulator.c
<<
>>
Prefs
   1/*
   2 * Device driver for regulators in Hi6421V530 IC
   3 *
   4 * Copyright (c) <2017> HiSilicon Technologies Co., Ltd.
   5 *              http://www.hisilicon.com
   6 * Copyright (c) <2017> Linaro Ltd.
   7 *              http://www.linaro.org
   8 *
   9 * Author: Wang Xiaoyin <hw.wangxiaoyin@hisilicon.com>
  10 *         Guodong Xu <guodong.xu@linaro.org>
  11 *
  12 * This program is free software; you can redistribute it and/or modify
  13 * it under the terms of the GNU General Public License version 2 as
  14 * published by the Free Software Foundation.
  15 */
  16
  17#include <linux/mfd/hi6421-pmic.h>
  18#include <linux/module.h>
  19#include <linux/of.h>
  20#include <linux/platform_device.h>
  21#include <linux/regmap.h>
  22#include <linux/regulator/driver.h>
  23
  24/*
  25 * struct hi6421v530_regulator_info - hi6421v530 regulator information
  26 * @desc: regulator description
  27 * @mode_mask: ECO mode bitmask of LDOs; for BUCKs, this masks sleep
  28 * @eco_microamp: eco mode load upper limit (in uA), valid for LDOs only
  29 */
  30struct hi6421v530_regulator_info {
  31        struct regulator_desc rdesc;
  32        u8 mode_mask;
  33        u32 eco_microamp;
  34};
  35
  36/* HI6421v530 regulators */
  37enum hi6421v530_regulator_id {
  38        HI6421V530_LDO3,
  39        HI6421V530_LDO9,
  40        HI6421V530_LDO11,
  41        HI6421V530_LDO15,
  42        HI6421V530_LDO16,
  43};
  44
  45static const unsigned int ldo_3_voltages[] = {
  46        1800000, 1825000, 1850000, 1875000,
  47        1900000, 1925000, 1950000, 1975000,
  48        2000000, 2025000, 2050000, 2075000,
  49        2100000, 2125000, 2150000, 2200000,
  50};
  51
  52static const unsigned int ldo_9_11_voltages[] = {
  53        1750000, 1800000, 1825000, 2800000,
  54        2850000, 2950000, 3000000, 3300000,
  55};
  56
  57static const unsigned int ldo_15_16_voltages[] = {
  58        1750000, 1800000, 2400000, 2600000,
  59        2700000, 2850000, 2950000, 3000000,
  60};
  61
  62static const struct regulator_ops hi6421v530_ldo_ops;
  63
  64#define HI6421V530_LDO_ENABLE_TIME (350)
  65
  66/*
  67 * _id - LDO id name string
  68 * v_table - voltage table
  69 * vreg - voltage select register
  70 * vmask - voltage select mask
  71 * ereg - enable register
  72 * emask - enable mask
  73 * odelay - off/on delay time in uS
  74 * ecomask - eco mode mask
  75 * ecoamp - eco mode load uppler limit in uA
  76 */
  77#define HI6421V530_LDO(_ID, v_table, vreg, vmask, ereg, emask,          \
  78                   odelay, ecomask, ecoamp) {                           \
  79        .rdesc = {                                                      \
  80                .name            = #_ID,                                \
  81                .of_match        = of_match_ptr(#_ID),                  \
  82                .regulators_node = of_match_ptr("regulators"),          \
  83                .ops             = &hi6421v530_ldo_ops,                 \
  84                .type            = REGULATOR_VOLTAGE,                   \
  85                .id              = HI6421V530_##_ID,                    \
  86                .owner           = THIS_MODULE,                         \
  87                .n_voltages      = ARRAY_SIZE(v_table),                 \
  88                .volt_table      = v_table,                             \
  89                .vsel_reg        = HI6421_REG_TO_BUS_ADDR(vreg),        \
  90                .vsel_mask       = vmask,                               \
  91                .enable_reg      = HI6421_REG_TO_BUS_ADDR(ereg),        \
  92                .enable_mask     = emask,                               \
  93                .enable_time     = HI6421V530_LDO_ENABLE_TIME,          \
  94                .off_on_delay    = odelay,                              \
  95        },                                                              \
  96        .mode_mask      = ecomask,                                      \
  97        .eco_microamp   = ecoamp,                                       \
  98}
  99
 100/* HI6421V530 regulator information */
 101
 102static struct hi6421v530_regulator_info hi6421v530_regulator_info[] = {
 103        HI6421V530_LDO(LDO3, ldo_3_voltages, 0x061, 0xf, 0x060, 0x2,
 104                   20000, 0x6, 8000),
 105        HI6421V530_LDO(LDO9, ldo_9_11_voltages, 0x06b, 0x7, 0x06a, 0x2,
 106                   40000, 0x6, 8000),
 107        HI6421V530_LDO(LDO11, ldo_9_11_voltages, 0x06f, 0x7, 0x06e, 0x2,
 108                   40000, 0x6, 8000),
 109        HI6421V530_LDO(LDO15, ldo_15_16_voltages, 0x077, 0x7, 0x076, 0x2,
 110                   40000, 0x6, 8000),
 111        HI6421V530_LDO(LDO16, ldo_15_16_voltages, 0x079, 0x7, 0x078, 0x2,
 112                   40000, 0x6, 8000),
 113};
 114
 115static unsigned int hi6421v530_regulator_ldo_get_mode(
 116                                        struct regulator_dev *rdev)
 117{
 118        struct hi6421v530_regulator_info *info;
 119        unsigned int reg_val;
 120
 121        info = rdev_get_drvdata(rdev);
 122        regmap_read(rdev->regmap, rdev->desc->enable_reg, &reg_val);
 123
 124        if (reg_val & (info->mode_mask))
 125                return REGULATOR_MODE_IDLE;
 126
 127        return REGULATOR_MODE_NORMAL;
 128}
 129
 130static int hi6421v530_regulator_ldo_set_mode(struct regulator_dev *rdev,
 131                                                unsigned int mode)
 132{
 133        struct hi6421v530_regulator_info *info;
 134        unsigned int new_mode;
 135
 136        info = rdev_get_drvdata(rdev);
 137        switch (mode) {
 138        case REGULATOR_MODE_NORMAL:
 139                new_mode = 0;
 140                break;
 141        case REGULATOR_MODE_IDLE:
 142                new_mode = info->mode_mask;
 143                break;
 144        default:
 145                return -EINVAL;
 146        }
 147
 148        regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
 149                           info->mode_mask, new_mode);
 150
 151        return 0;
 152}
 153
 154
 155static const struct regulator_ops hi6421v530_ldo_ops = {
 156        .is_enabled = regulator_is_enabled_regmap,
 157        .enable = regulator_enable_regmap,
 158        .disable = regulator_disable_regmap,
 159        .list_voltage = regulator_list_voltage_table,
 160        .map_voltage = regulator_map_voltage_ascend,
 161        .get_voltage_sel = regulator_get_voltage_sel_regmap,
 162        .set_voltage_sel = regulator_set_voltage_sel_regmap,
 163        .get_mode = hi6421v530_regulator_ldo_get_mode,
 164        .set_mode = hi6421v530_regulator_ldo_set_mode,
 165};
 166
 167static int hi6421v530_regulator_probe(struct platform_device *pdev)
 168{
 169        struct hi6421_pmic *pmic;
 170        struct regulator_dev *rdev;
 171        struct regulator_config config = { };
 172        unsigned int i;
 173
 174        pmic = dev_get_drvdata(pdev->dev.parent);
 175        if (!pmic) {
 176                dev_err(&pdev->dev, "no pmic in the regulator parent node\n");
 177                return -ENODEV;
 178        }
 179
 180        for (i = 0; i < ARRAY_SIZE(hi6421v530_regulator_info); i++) {
 181                config.dev = pdev->dev.parent;
 182                config.regmap = pmic->regmap;
 183                config.driver_data = &hi6421v530_regulator_info[i];
 184
 185                rdev = devm_regulator_register(&pdev->dev,
 186                                &hi6421v530_regulator_info[i].rdesc,
 187                                &config);
 188                if (IS_ERR(rdev)) {
 189                        dev_err(&pdev->dev, "failed to register regulator %s\n",
 190                                hi6421v530_regulator_info[i].rdesc.name);
 191                        return PTR_ERR(rdev);
 192                }
 193        }
 194        return 0;
 195}
 196
 197static const struct platform_device_id hi6421v530_regulator_table[] = {
 198        { .name = "hi6421v530-regulator" },
 199        {},
 200};
 201MODULE_DEVICE_TABLE(platform, hi6421v530_regulator_table);
 202
 203static struct platform_driver hi6421v530_regulator_driver = {
 204        .id_table = hi6421v530_regulator_table,
 205        .driver = {
 206                .name   = "hi6421v530-regulator",
 207        },
 208        .probe  = hi6421v530_regulator_probe,
 209};
 210module_platform_driver(hi6421v530_regulator_driver);
 211
 212MODULE_AUTHOR("Wang Xiaoyin <hw.wangxiaoyin@hisilicon.com>");
 213MODULE_DESCRIPTION("Hi6421v530 regulator driver");
 214MODULE_LICENSE("GPL v2");
 215