linux/drivers/regulator/lp87565-regulator.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Regulator driver for LP87565 PMIC
   4 *
   5 * Copyright (C) 2017 Texas Instruments Incorporated - https://www.ti.com/
   6 */
   7
   8#include <linux/module.h>
   9#include <linux/platform_device.h>
  10#include <linux/regmap.h>
  11
  12#include <linux/mfd/lp87565.h>
  13
  14#define LP87565_REGULATOR(_name, _id, _of, _ops, _n, _vr, _vm,          \
  15                          _er, _em, _ev, _delay, _lr, _cr)              \
  16        [_id] = {                                                       \
  17                .desc = {                                               \
  18                        .name                   = _name,                \
  19                        .supply_name            = _of "-in",            \
  20                        .id                     = _id,                  \
  21                        .of_match               = of_match_ptr(_of),    \
  22                        .regulators_node        = of_match_ptr("regulators"),\
  23                        .ops                    = &_ops,                \
  24                        .n_voltages             = _n,                   \
  25                        .type                   = REGULATOR_VOLTAGE,    \
  26                        .owner                  = THIS_MODULE,          \
  27                        .vsel_reg               = _vr,                  \
  28                        .vsel_mask              = _vm,                  \
  29                        .enable_reg             = _er,                  \
  30                        .enable_mask            = _em,                  \
  31                        .enable_val             = _ev,                  \
  32                        .ramp_delay             = _delay,               \
  33                        .linear_ranges          = _lr,                  \
  34                        .n_linear_ranges        = ARRAY_SIZE(_lr),      \
  35                        .curr_table = lp87565_buck_uA,                  \
  36                        .n_current_limits = ARRAY_SIZE(lp87565_buck_uA),\
  37                        .csel_reg = (_cr),                              \
  38                        .csel_mask = LP87565_BUCK_CTRL_2_ILIM,          \
  39                },                                                      \
  40                .ctrl2_reg = _cr,                                       \
  41        }
  42
  43struct lp87565_regulator {
  44        struct regulator_desc desc;
  45        unsigned int ctrl2_reg;
  46};
  47
  48static const struct lp87565_regulator regulators[];
  49
  50static const struct linear_range buck0_1_2_3_ranges[] = {
  51        REGULATOR_LINEAR_RANGE(600000, 0xA, 0x17, 10000),
  52        REGULATOR_LINEAR_RANGE(735000, 0x18, 0x9d, 5000),
  53        REGULATOR_LINEAR_RANGE(1420000, 0x9e, 0xff, 20000),
  54};
  55
  56static const unsigned int lp87565_buck_ramp_delay[] = {
  57        30000, 15000, 10000, 7500, 3800, 1900, 940, 470
  58};
  59
  60/* LP87565 BUCK current limit */
  61static const unsigned int lp87565_buck_uA[] = {
  62        1500000, 2000000, 2500000, 3000000, 3500000, 4000000, 4500000, 5000000,
  63};
  64
  65static int lp87565_buck_set_ramp_delay(struct regulator_dev *rdev,
  66                                       int ramp_delay)
  67{
  68        int id = rdev_get_id(rdev);
  69        unsigned int reg;
  70        int ret;
  71
  72        if (ramp_delay <= 470)
  73                reg = 7;
  74        else if (ramp_delay <= 940)
  75                reg = 6;
  76        else if (ramp_delay <= 1900)
  77                reg = 5;
  78        else if (ramp_delay <= 3800)
  79                reg = 4;
  80        else if (ramp_delay <= 7500)
  81                reg = 3;
  82        else if (ramp_delay <= 10000)
  83                reg = 2;
  84        else if (ramp_delay <= 15000)
  85                reg = 1;
  86        else
  87                reg = 0;
  88
  89        ret = regmap_update_bits(rdev->regmap, regulators[id].ctrl2_reg,
  90                                 LP87565_BUCK_CTRL_2_SLEW_RATE,
  91                                 reg << __ffs(LP87565_BUCK_CTRL_2_SLEW_RATE));
  92        if (ret) {
  93                dev_err(&rdev->dev, "SLEW RATE write failed: %d\n", ret);
  94                return ret;
  95        }
  96
  97        rdev->constraints->ramp_delay = lp87565_buck_ramp_delay[reg];
  98
  99        /* Conservatively give a 15% margin */
 100        rdev->constraints->ramp_delay =
 101                                rdev->constraints->ramp_delay * 85 / 100;
 102
 103        return 0;
 104}
 105
 106/* Operations permitted on BUCKs */
 107static const struct regulator_ops lp87565_buck_ops = {
 108        .is_enabled             = regulator_is_enabled_regmap,
 109        .enable                 = regulator_enable_regmap,
 110        .disable                = regulator_disable_regmap,
 111        .get_voltage_sel        = regulator_get_voltage_sel_regmap,
 112        .set_voltage_sel        = regulator_set_voltage_sel_regmap,
 113        .list_voltage           = regulator_list_voltage_linear_range,
 114        .map_voltage            = regulator_map_voltage_linear_range,
 115        .set_voltage_time_sel   = regulator_set_voltage_time_sel,
 116        .set_ramp_delay         = lp87565_buck_set_ramp_delay,
 117        .set_current_limit      = regulator_set_current_limit_regmap,
 118        .get_current_limit      = regulator_get_current_limit_regmap,
 119};
 120
 121static const struct lp87565_regulator regulators[] = {
 122        LP87565_REGULATOR("BUCK0", LP87565_BUCK_0, "buck0", lp87565_buck_ops,
 123                          256, LP87565_REG_BUCK0_VOUT, LP87565_BUCK_VSET,
 124                          LP87565_REG_BUCK0_CTRL_1,
 125                          LP87565_BUCK_CTRL_1_EN |
 126                          LP87565_BUCK_CTRL_1_EN_PIN_CTRL,
 127                          LP87565_BUCK_CTRL_1_EN, 3230,
 128                          buck0_1_2_3_ranges, LP87565_REG_BUCK0_CTRL_2),
 129        LP87565_REGULATOR("BUCK1", LP87565_BUCK_1, "buck1", lp87565_buck_ops,
 130                          256, LP87565_REG_BUCK1_VOUT, LP87565_BUCK_VSET,
 131                          LP87565_REG_BUCK1_CTRL_1,
 132                          LP87565_BUCK_CTRL_1_EN |
 133                          LP87565_BUCK_CTRL_1_EN_PIN_CTRL,
 134                          LP87565_BUCK_CTRL_1_EN, 3230,
 135                          buck0_1_2_3_ranges, LP87565_REG_BUCK1_CTRL_2),
 136        LP87565_REGULATOR("BUCK2", LP87565_BUCK_2, "buck2", lp87565_buck_ops,
 137                          256, LP87565_REG_BUCK2_VOUT, LP87565_BUCK_VSET,
 138                          LP87565_REG_BUCK2_CTRL_1,
 139                          LP87565_BUCK_CTRL_1_EN |
 140                          LP87565_BUCK_CTRL_1_EN_PIN_CTRL,
 141                          LP87565_BUCK_CTRL_1_EN, 3230,
 142                          buck0_1_2_3_ranges, LP87565_REG_BUCK2_CTRL_2),
 143        LP87565_REGULATOR("BUCK3", LP87565_BUCK_3, "buck3", lp87565_buck_ops,
 144                          256, LP87565_REG_BUCK3_VOUT, LP87565_BUCK_VSET,
 145                          LP87565_REG_BUCK3_CTRL_1,
 146                          LP87565_BUCK_CTRL_1_EN |
 147                          LP87565_BUCK_CTRL_1_EN_PIN_CTRL,
 148                          LP87565_BUCK_CTRL_1_EN, 3230,
 149                          buck0_1_2_3_ranges, LP87565_REG_BUCK3_CTRL_2),
 150        LP87565_REGULATOR("BUCK10", LP87565_BUCK_10, "buck10", lp87565_buck_ops,
 151                          256, LP87565_REG_BUCK0_VOUT, LP87565_BUCK_VSET,
 152                          LP87565_REG_BUCK0_CTRL_1,
 153                          LP87565_BUCK_CTRL_1_EN |
 154                          LP87565_BUCK_CTRL_1_EN_PIN_CTRL |
 155                          LP87565_BUCK_CTRL_1_FPWM_MP_0_2,
 156                          LP87565_BUCK_CTRL_1_EN |
 157                          LP87565_BUCK_CTRL_1_FPWM_MP_0_2, 3230,
 158                          buck0_1_2_3_ranges, LP87565_REG_BUCK0_CTRL_2),
 159        LP87565_REGULATOR("BUCK23", LP87565_BUCK_23, "buck23", lp87565_buck_ops,
 160                          256, LP87565_REG_BUCK2_VOUT, LP87565_BUCK_VSET,
 161                          LP87565_REG_BUCK2_CTRL_1,
 162                          LP87565_BUCK_CTRL_1_EN |
 163                          LP87565_BUCK_CTRL_1_EN_PIN_CTRL,
 164                          LP87565_BUCK_CTRL_1_EN, 3230,
 165                          buck0_1_2_3_ranges, LP87565_REG_BUCK2_CTRL_2),
 166        LP87565_REGULATOR("BUCK3210", LP87565_BUCK_3210, "buck3210",
 167                          lp87565_buck_ops, 256, LP87565_REG_BUCK0_VOUT,
 168                          LP87565_BUCK_VSET, LP87565_REG_BUCK0_CTRL_1,
 169                          LP87565_BUCK_CTRL_1_EN |
 170                          LP87565_BUCK_CTRL_1_EN_PIN_CTRL |
 171                          LP87565_BUCK_CTRL_1_FPWM_MP_0_2,
 172                          LP87565_BUCK_CTRL_1_EN |
 173                          LP87565_BUCK_CTRL_1_FPWM_MP_0_2, 3230,
 174                          buck0_1_2_3_ranges, LP87565_REG_BUCK0_CTRL_2),
 175};
 176
 177static int lp87565_regulator_probe(struct platform_device *pdev)
 178{
 179        struct lp87565 *lp87565 = dev_get_drvdata(pdev->dev.parent);
 180        struct regulator_config config = { };
 181        struct regulator_dev *rdev;
 182        int i, min_idx, max_idx;
 183
 184        platform_set_drvdata(pdev, lp87565);
 185
 186        config.dev = &pdev->dev;
 187        config.dev->of_node = lp87565->dev->of_node;
 188        config.driver_data = lp87565;
 189        config.regmap = lp87565->regmap;
 190
 191        switch (lp87565->dev_type) {
 192        case LP87565_DEVICE_TYPE_LP87565_Q1:
 193                min_idx = LP87565_BUCK_10;
 194                max_idx = LP87565_BUCK_23;
 195                break;
 196        case LP87565_DEVICE_TYPE_LP87561_Q1:
 197                min_idx = LP87565_BUCK_3210;
 198                max_idx = LP87565_BUCK_3210;
 199                break;
 200        default:
 201                min_idx = LP87565_BUCK_0;
 202                max_idx = LP87565_BUCK_3;
 203                break;
 204        }
 205
 206        for (i = min_idx; i <= max_idx; i++) {
 207                rdev = devm_regulator_register(&pdev->dev, &regulators[i].desc,
 208                                               &config);
 209                if (IS_ERR(rdev)) {
 210                        dev_err(lp87565->dev, "failed to register %s regulator\n",
 211                                pdev->name);
 212                        return PTR_ERR(rdev);
 213                }
 214        }
 215
 216        return 0;
 217}
 218
 219static const struct platform_device_id lp87565_regulator_id_table[] = {
 220        { "lp87565-regulator", },
 221        { "lp87565-q1-regulator", },
 222        { /* sentinel */ }
 223};
 224MODULE_DEVICE_TABLE(platform, lp87565_regulator_id_table);
 225
 226static struct platform_driver lp87565_regulator_driver = {
 227        .driver = {
 228                .name = "lp87565-pmic",
 229        },
 230        .probe = lp87565_regulator_probe,
 231        .id_table = lp87565_regulator_id_table,
 232};
 233module_platform_driver(lp87565_regulator_driver);
 234
 235MODULE_AUTHOR("J Keerthy <j-keerthy@ti.com>");
 236MODULE_DESCRIPTION("LP87565 voltage regulator driver");
 237MODULE_LICENSE("GPL v2");
 238