linux/drivers/regulator/lm363x-regulator.c
<<
>>
Prefs
   1/*
   2 * TI LM363X Regulator Driver
   3 *
   4 * Copyright 2015 Texas Instruments
   5 *
   6 * Author: Milo Kim <milo.kim@ti.com>
   7 *
   8 * This program is free software; you can redistribute it and/or modify
   9 * it under the terms of the GNU General Public License version 2 as
  10 * published by the Free Software Foundation.
  11 */
  12
  13#include <linux/err.h>
  14#include <linux/kernel.h>
  15#include <linux/mfd/ti-lmu.h>
  16#include <linux/mfd/ti-lmu-register.h>
  17#include <linux/module.h>
  18#include <linux/of.h>
  19#include <linux/of_gpio.h>
  20#include <linux/platform_device.h>
  21#include <linux/regulator/driver.h>
  22#include <linux/regulator/of_regulator.h>
  23#include <linux/slab.h>
  24
  25/* LM3631 */
  26#define LM3631_BOOST_VSEL_MAX           0x25
  27#define LM3631_LDO_VSEL_MAX             0x28
  28#define LM3631_CONT_VSEL_MAX            0x03
  29#define LM3631_VBOOST_MIN               4500000
  30#define LM3631_VCONT_MIN                1800000
  31#define LM3631_VLDO_MIN                 4000000
  32#define ENABLE_TIME_USEC                1000
  33
  34/* LM3632 */
  35#define LM3632_BOOST_VSEL_MAX           0x26
  36#define LM3632_LDO_VSEL_MAX             0x29
  37#define LM3632_VBOOST_MIN               4500000
  38#define LM3632_VLDO_MIN                 4000000
  39
  40/* Common */
  41#define LM363X_STEP_50mV                50000
  42#define LM363X_STEP_500mV               500000
  43
  44static const int ldo_cont_enable_time[] = {
  45        0, 2000, 5000, 10000, 20000, 50000, 100000, 200000,
  46};
  47
  48static int lm363x_regulator_enable_time(struct regulator_dev *rdev)
  49{
  50        enum lm363x_regulator_id id = rdev_get_id(rdev);
  51        u8 val, addr, mask;
  52
  53        switch (id) {
  54        case LM3631_LDO_CONT:
  55                addr = LM3631_REG_ENTIME_VCONT;
  56                mask = LM3631_ENTIME_CONT_MASK;
  57                break;
  58        case LM3631_LDO_OREF:
  59                addr = LM3631_REG_ENTIME_VOREF;
  60                mask = LM3631_ENTIME_MASK;
  61                break;
  62        case LM3631_LDO_POS:
  63                addr = LM3631_REG_ENTIME_VPOS;
  64                mask = LM3631_ENTIME_MASK;
  65                break;
  66        case LM3631_LDO_NEG:
  67                addr = LM3631_REG_ENTIME_VNEG;
  68                mask = LM3631_ENTIME_MASK;
  69                break;
  70        default:
  71                return 0;
  72        }
  73
  74        if (regmap_read(rdev->regmap, addr, (unsigned int *)&val))
  75                return -EINVAL;
  76
  77        val = (val & mask) >> LM3631_ENTIME_SHIFT;
  78
  79        if (id == LM3631_LDO_CONT)
  80                return ldo_cont_enable_time[val];
  81        else
  82                return ENABLE_TIME_USEC * val;
  83}
  84
  85static struct regulator_ops lm363x_boost_voltage_table_ops = {
  86        .list_voltage     = regulator_list_voltage_linear,
  87        .set_voltage_sel  = regulator_set_voltage_sel_regmap,
  88        .get_voltage_sel  = regulator_get_voltage_sel_regmap,
  89};
  90
  91static struct regulator_ops lm363x_regulator_voltage_table_ops = {
  92        .list_voltage     = regulator_list_voltage_linear,
  93        .set_voltage_sel  = regulator_set_voltage_sel_regmap,
  94        .get_voltage_sel  = regulator_get_voltage_sel_regmap,
  95        .enable           = regulator_enable_regmap,
  96        .disable          = regulator_disable_regmap,
  97        .is_enabled       = regulator_is_enabled_regmap,
  98        .enable_time      = lm363x_regulator_enable_time,
  99};
 100
 101static const struct regulator_desc lm363x_regulator_desc[] = {
 102        /* LM3631 */
 103        {
 104                .name           = "vboost",
 105                .of_match       = "vboost",
 106                .id             = LM3631_BOOST,
 107                .ops            = &lm363x_boost_voltage_table_ops,
 108                .n_voltages     = LM3631_BOOST_VSEL_MAX + 1,
 109                .min_uV         = LM3631_VBOOST_MIN,
 110                .uV_step        = LM363X_STEP_50mV,
 111                .type           = REGULATOR_VOLTAGE,
 112                .owner          = THIS_MODULE,
 113                .vsel_reg       = LM3631_REG_VOUT_BOOST,
 114                .vsel_mask      = LM3631_VOUT_MASK,
 115        },
 116        {
 117                .name           = "ldo_cont",
 118                .of_match       = "vcont",
 119                .id             = LM3631_LDO_CONT,
 120                .ops            = &lm363x_regulator_voltage_table_ops,
 121                .n_voltages     = LM3631_CONT_VSEL_MAX + 1,
 122                .min_uV         = LM3631_VCONT_MIN,
 123                .uV_step        = LM363X_STEP_500mV,
 124                .type           = REGULATOR_VOLTAGE,
 125                .owner          = THIS_MODULE,
 126                .vsel_reg       = LM3631_REG_VOUT_CONT,
 127                .vsel_mask      = LM3631_VOUT_CONT_MASK,
 128                .enable_reg     = LM3631_REG_LDO_CTRL2,
 129                .enable_mask    = LM3631_EN_CONT_MASK,
 130        },
 131        {
 132                .name           = "ldo_oref",
 133                .of_match       = "voref",
 134                .id             = LM3631_LDO_OREF,
 135                .ops            = &lm363x_regulator_voltage_table_ops,
 136                .n_voltages     = LM3631_LDO_VSEL_MAX + 1,
 137                .min_uV         = LM3631_VLDO_MIN,
 138                .uV_step        = LM363X_STEP_50mV,
 139                .type           = REGULATOR_VOLTAGE,
 140                .owner          = THIS_MODULE,
 141                .vsel_reg       = LM3631_REG_VOUT_OREF,
 142                .vsel_mask      = LM3631_VOUT_MASK,
 143                .enable_reg     = LM3631_REG_LDO_CTRL1,
 144                .enable_mask    = LM3631_EN_OREF_MASK,
 145        },
 146        {
 147                .name           = "ldo_vpos",
 148                .of_match       = "vpos",
 149                .id             = LM3631_LDO_POS,
 150                .ops            = &lm363x_regulator_voltage_table_ops,
 151                .n_voltages     = LM3631_LDO_VSEL_MAX + 1,
 152                .min_uV         = LM3631_VLDO_MIN,
 153                .uV_step        = LM363X_STEP_50mV,
 154                .type           = REGULATOR_VOLTAGE,
 155                .owner          = THIS_MODULE,
 156                .vsel_reg       = LM3631_REG_VOUT_POS,
 157                .vsel_mask      = LM3631_VOUT_MASK,
 158                .enable_reg     = LM3631_REG_LDO_CTRL1,
 159                .enable_mask    = LM3631_EN_VPOS_MASK,
 160        },
 161        {
 162                .name           = "ldo_vneg",
 163                .of_match       = "vneg",
 164                .id             = LM3631_LDO_NEG,
 165                .ops            = &lm363x_regulator_voltage_table_ops,
 166                .n_voltages     = LM3631_LDO_VSEL_MAX + 1,
 167                .min_uV         = LM3631_VLDO_MIN,
 168                .uV_step        = LM363X_STEP_50mV,
 169                .type           = REGULATOR_VOLTAGE,
 170                .owner          = THIS_MODULE,
 171                .vsel_reg       = LM3631_REG_VOUT_NEG,
 172                .vsel_mask      = LM3631_VOUT_MASK,
 173                .enable_reg     = LM3631_REG_LDO_CTRL1,
 174                .enable_mask    = LM3631_EN_VNEG_MASK,
 175        },
 176        /* LM3632 */
 177        {
 178                .name           = "vboost",
 179                .of_match       = "vboost",
 180                .id             = LM3632_BOOST,
 181                .ops            = &lm363x_boost_voltage_table_ops,
 182                .n_voltages     = LM3632_BOOST_VSEL_MAX + 1,
 183                .min_uV         = LM3632_VBOOST_MIN,
 184                .uV_step        = LM363X_STEP_50mV,
 185                .type           = REGULATOR_VOLTAGE,
 186                .owner          = THIS_MODULE,
 187                .vsel_reg       = LM3632_REG_VOUT_BOOST,
 188                .vsel_mask      = LM3632_VOUT_MASK,
 189        },
 190        {
 191                .name           = "ldo_vpos",
 192                .of_match       = "vpos",
 193                .id             = LM3632_LDO_POS,
 194                .ops            = &lm363x_regulator_voltage_table_ops,
 195                .n_voltages     = LM3632_LDO_VSEL_MAX + 1,
 196                .min_uV         = LM3632_VLDO_MIN,
 197                .uV_step        = LM363X_STEP_50mV,
 198                .type           = REGULATOR_VOLTAGE,
 199                .owner          = THIS_MODULE,
 200                .vsel_reg       = LM3632_REG_VOUT_POS,
 201                .vsel_mask      = LM3632_VOUT_MASK,
 202                .enable_reg     = LM3632_REG_BIAS_CONFIG,
 203                .enable_mask    = LM3632_EN_VPOS_MASK,
 204        },
 205        {
 206                .name           = "ldo_vneg",
 207                .of_match       = "vneg",
 208                .id             = LM3632_LDO_NEG,
 209                .ops            = &lm363x_regulator_voltage_table_ops,
 210                .n_voltages     = LM3632_LDO_VSEL_MAX + 1,
 211                .min_uV         = LM3632_VLDO_MIN,
 212                .uV_step        = LM363X_STEP_50mV,
 213                .type           = REGULATOR_VOLTAGE,
 214                .owner          = THIS_MODULE,
 215                .vsel_reg       = LM3632_REG_VOUT_NEG,
 216                .vsel_mask      = LM3632_VOUT_MASK,
 217                .enable_reg     = LM3632_REG_BIAS_CONFIG,
 218                .enable_mask    = LM3632_EN_VNEG_MASK,
 219        },
 220};
 221
 222static int lm363x_regulator_of_get_enable_gpio(struct device_node *np, int id)
 223{
 224        /*
 225         * Check LCM_EN1/2_GPIO is configured.
 226         * Those pins are used for enabling VPOS/VNEG LDOs.
 227         */
 228        switch (id) {
 229        case LM3632_LDO_POS:
 230                return of_get_named_gpio(np, "enable-gpios", 0);
 231        case LM3632_LDO_NEG:
 232                return of_get_named_gpio(np, "enable-gpios", 1);
 233        default:
 234                return -EINVAL;
 235        }
 236}
 237
 238static int lm363x_regulator_probe(struct platform_device *pdev)
 239{
 240        struct ti_lmu *lmu = dev_get_drvdata(pdev->dev.parent);
 241        struct regmap *regmap = lmu->regmap;
 242        struct regulator_config cfg = { };
 243        struct regulator_dev *rdev;
 244        struct device *dev = &pdev->dev;
 245        int id = pdev->id;
 246        int ret, ena_gpio;
 247
 248        cfg.dev = dev;
 249        cfg.regmap = regmap;
 250
 251        /*
 252         * LM3632 LDOs can be controlled by external pin.
 253         * Register update is required if the pin is used.
 254         */
 255        ena_gpio = lm363x_regulator_of_get_enable_gpio(dev->of_node, id);
 256        if (gpio_is_valid(ena_gpio)) {
 257                cfg.ena_gpio = ena_gpio;
 258                cfg.ena_gpio_flags = GPIOF_OUT_INIT_LOW;
 259
 260                ret = regmap_update_bits(regmap, LM3632_REG_BIAS_CONFIG,
 261                                         LM3632_EXT_EN_MASK,
 262                                         LM3632_EXT_EN_MASK);
 263                if (ret) {
 264                        dev_err(dev, "External pin err: %d\n", ret);
 265                        return ret;
 266                }
 267        }
 268
 269        rdev = devm_regulator_register(dev, &lm363x_regulator_desc[id], &cfg);
 270        if (IS_ERR(rdev)) {
 271                ret = PTR_ERR(rdev);
 272                dev_err(dev, "[%d] regulator register err: %d\n", id, ret);
 273                return ret;
 274        }
 275
 276        return 0;
 277}
 278
 279static struct platform_driver lm363x_regulator_driver = {
 280        .probe = lm363x_regulator_probe,
 281        .driver = {
 282                .name = "lm363x-regulator",
 283        },
 284};
 285
 286module_platform_driver(lm363x_regulator_driver);
 287
 288MODULE_DESCRIPTION("TI LM363X Regulator Driver");
 289MODULE_AUTHOR("Milo Kim");
 290MODULE_LICENSE("GPL v2");
 291MODULE_ALIAS("platform:lm363x-regulator");
 292