root/drivers/regulator/lm363x-regulator.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. lm363x_regulator_enable_time
  2. lm363x_regulator_of_get_enable_gpio
  3. lm363x_regulator_set_ext_en
  4. lm363x_regulator_probe

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * TI LM363X Regulator Driver
   4  *
   5  * Copyright 2015 Texas Instruments
   6  *
   7  * Author: Milo Kim <milo.kim@ti.com>
   8  */
   9 
  10 #include <linux/err.h>
  11 #include <linux/kernel.h>
  12 #include <linux/mfd/ti-lmu.h>
  13 #include <linux/mfd/ti-lmu-register.h>
  14 #include <linux/module.h>
  15 #include <linux/of.h>
  16 #include <linux/gpio/consumer.h>
  17 #include <linux/platform_device.h>
  18 #include <linux/regulator/driver.h>
  19 #include <linux/regulator/of_regulator.h>
  20 #include <linux/slab.h>
  21 
  22 /* LM3631 */
  23 #define LM3631_BOOST_VSEL_MAX           0x25
  24 #define LM3631_LDO_VSEL_MAX             0x28
  25 #define LM3631_CONT_VSEL_MAX            0x03
  26 #define LM3631_VBOOST_MIN               4500000
  27 #define LM3631_VCONT_MIN                1800000
  28 #define LM3631_VLDO_MIN                 4000000
  29 #define ENABLE_TIME_USEC                1000
  30 
  31 /* LM3632 */
  32 #define LM3632_BOOST_VSEL_MAX           0x26
  33 #define LM3632_LDO_VSEL_MAX             0x28
  34 #define LM3632_VBOOST_MIN               4500000
  35 #define LM3632_VLDO_MIN                 4000000
  36 
  37 /* LM36274 */
  38 #define LM36274_BOOST_VSEL_MAX          0x3f
  39 #define LM36274_LDO_VSEL_MAX            0x32
  40 #define LM36274_VOLTAGE_MIN             4000000
  41 
  42 /* Common */
  43 #define LM363X_STEP_50mV                50000
  44 #define LM363X_STEP_500mV               500000
  45 
  46 static const int ldo_cont_enable_time[] = {
  47         0, 2000, 5000, 10000, 20000, 50000, 100000, 200000,
  48 };
  49 
  50 static int lm363x_regulator_enable_time(struct regulator_dev *rdev)
  51 {
  52         enum lm363x_regulator_id id = rdev_get_id(rdev);
  53         unsigned int val, addr, mask;
  54 
  55         switch (id) {
  56         case LM3631_LDO_CONT:
  57                 addr = LM3631_REG_ENTIME_VCONT;
  58                 mask = LM3631_ENTIME_CONT_MASK;
  59                 break;
  60         case LM3631_LDO_OREF:
  61                 addr = LM3631_REG_ENTIME_VOREF;
  62                 mask = LM3631_ENTIME_MASK;
  63                 break;
  64         case LM3631_LDO_POS:
  65                 addr = LM3631_REG_ENTIME_VPOS;
  66                 mask = LM3631_ENTIME_MASK;
  67                 break;
  68         case LM3631_LDO_NEG:
  69                 addr = LM3631_REG_ENTIME_VNEG;
  70                 mask = LM3631_ENTIME_MASK;
  71                 break;
  72         default:
  73                 return 0;
  74         }
  75 
  76         if (regmap_read(rdev->regmap, addr, &val))
  77                 return -EINVAL;
  78 
  79         val = (val & mask) >> LM3631_ENTIME_SHIFT;
  80 
  81         if (id == LM3631_LDO_CONT)
  82                 return ldo_cont_enable_time[val];
  83         else
  84                 return ENABLE_TIME_USEC * val;
  85 }
  86 
  87 static const struct regulator_ops lm363x_boost_voltage_table_ops = {
  88         .list_voltage     = regulator_list_voltage_linear,
  89         .set_voltage_sel  = regulator_set_voltage_sel_regmap,
  90         .get_voltage_sel  = regulator_get_voltage_sel_regmap,
  91 };
  92 
  93 static const struct regulator_ops lm363x_regulator_voltage_table_ops = {
  94         .list_voltage     = regulator_list_voltage_linear,
  95         .set_voltage_sel  = regulator_set_voltage_sel_regmap,
  96         .get_voltage_sel  = regulator_get_voltage_sel_regmap,
  97         .enable           = regulator_enable_regmap,
  98         .disable          = regulator_disable_regmap,
  99         .is_enabled       = regulator_is_enabled_regmap,
 100         .enable_time      = lm363x_regulator_enable_time,
 101 };
 102 
 103 static const struct regulator_desc lm363x_regulator_desc[] = {
 104         /* LM3631 */
 105         {
 106                 .name           = "vboost",
 107                 .of_match       = "vboost",
 108                 .id             = LM3631_BOOST,
 109                 .ops            = &lm363x_boost_voltage_table_ops,
 110                 .n_voltages     = LM3631_BOOST_VSEL_MAX + 1,
 111                 .min_uV         = LM3631_VBOOST_MIN,
 112                 .uV_step        = LM363X_STEP_50mV,
 113                 .type           = REGULATOR_VOLTAGE,
 114                 .owner          = THIS_MODULE,
 115                 .vsel_reg       = LM3631_REG_VOUT_BOOST,
 116                 .vsel_mask      = LM3631_VOUT_MASK,
 117         },
 118         {
 119                 .name           = "ldo_cont",
 120                 .of_match       = "vcont",
 121                 .id             = LM3631_LDO_CONT,
 122                 .ops            = &lm363x_regulator_voltage_table_ops,
 123                 .n_voltages     = LM3631_CONT_VSEL_MAX + 1,
 124                 .min_uV         = LM3631_VCONT_MIN,
 125                 .uV_step        = LM363X_STEP_500mV,
 126                 .type           = REGULATOR_VOLTAGE,
 127                 .owner          = THIS_MODULE,
 128                 .vsel_reg       = LM3631_REG_VOUT_CONT,
 129                 .vsel_mask      = LM3631_VOUT_CONT_MASK,
 130                 .enable_reg     = LM3631_REG_LDO_CTRL2,
 131                 .enable_mask    = LM3631_EN_CONT_MASK,
 132         },
 133         {
 134                 .name           = "ldo_oref",
 135                 .of_match       = "voref",
 136                 .id             = LM3631_LDO_OREF,
 137                 .ops            = &lm363x_regulator_voltage_table_ops,
 138                 .n_voltages     = LM3631_LDO_VSEL_MAX + 1,
 139                 .min_uV         = LM3631_VLDO_MIN,
 140                 .uV_step        = LM363X_STEP_50mV,
 141                 .type           = REGULATOR_VOLTAGE,
 142                 .owner          = THIS_MODULE,
 143                 .vsel_reg       = LM3631_REG_VOUT_OREF,
 144                 .vsel_mask      = LM3631_VOUT_MASK,
 145                 .enable_reg     = LM3631_REG_LDO_CTRL1,
 146                 .enable_mask    = LM3631_EN_OREF_MASK,
 147         },
 148         {
 149                 .name           = "ldo_vpos",
 150                 .of_match       = "vpos",
 151                 .id             = LM3631_LDO_POS,
 152                 .ops            = &lm363x_regulator_voltage_table_ops,
 153                 .n_voltages     = LM3631_LDO_VSEL_MAX + 1,
 154                 .min_uV         = LM3631_VLDO_MIN,
 155                 .uV_step        = LM363X_STEP_50mV,
 156                 .type           = REGULATOR_VOLTAGE,
 157                 .owner          = THIS_MODULE,
 158                 .vsel_reg       = LM3631_REG_VOUT_POS,
 159                 .vsel_mask      = LM3631_VOUT_MASK,
 160                 .enable_reg     = LM3631_REG_LDO_CTRL1,
 161                 .enable_mask    = LM3631_EN_VPOS_MASK,
 162         },
 163         {
 164                 .name           = "ldo_vneg",
 165                 .of_match       = "vneg",
 166                 .id             = LM3631_LDO_NEG,
 167                 .ops            = &lm363x_regulator_voltage_table_ops,
 168                 .n_voltages     = LM3631_LDO_VSEL_MAX + 1,
 169                 .min_uV         = LM3631_VLDO_MIN,
 170                 .uV_step        = LM363X_STEP_50mV,
 171                 .type           = REGULATOR_VOLTAGE,
 172                 .owner          = THIS_MODULE,
 173                 .vsel_reg       = LM3631_REG_VOUT_NEG,
 174                 .vsel_mask      = LM3631_VOUT_MASK,
 175                 .enable_reg     = LM3631_REG_LDO_CTRL1,
 176                 .enable_mask    = LM3631_EN_VNEG_MASK,
 177         },
 178         /* LM3632 */
 179         {
 180                 .name           = "vboost",
 181                 .of_match       = "vboost",
 182                 .id             = LM3632_BOOST,
 183                 .ops            = &lm363x_boost_voltage_table_ops,
 184                 .n_voltages     = LM3632_BOOST_VSEL_MAX + 1,
 185                 .min_uV         = LM3632_VBOOST_MIN,
 186                 .uV_step        = LM363X_STEP_50mV,
 187                 .type           = REGULATOR_VOLTAGE,
 188                 .owner          = THIS_MODULE,
 189                 .vsel_reg       = LM3632_REG_VOUT_BOOST,
 190                 .vsel_mask      = LM3632_VOUT_MASK,
 191         },
 192         {
 193                 .name           = "ldo_vpos",
 194                 .of_match       = "vpos",
 195                 .id             = LM3632_LDO_POS,
 196                 .ops            = &lm363x_regulator_voltage_table_ops,
 197                 .n_voltages     = LM3632_LDO_VSEL_MAX + 1,
 198                 .min_uV         = LM3632_VLDO_MIN,
 199                 .uV_step        = LM363X_STEP_50mV,
 200                 .type           = REGULATOR_VOLTAGE,
 201                 .owner          = THIS_MODULE,
 202                 .vsel_reg       = LM3632_REG_VOUT_POS,
 203                 .vsel_mask      = LM3632_VOUT_MASK,
 204                 .enable_reg     = LM3632_REG_BIAS_CONFIG,
 205                 .enable_mask    = LM3632_EN_VPOS_MASK,
 206         },
 207         {
 208                 .name           = "ldo_vneg",
 209                 .of_match       = "vneg",
 210                 .id             = LM3632_LDO_NEG,
 211                 .ops            = &lm363x_regulator_voltage_table_ops,
 212                 .n_voltages     = LM3632_LDO_VSEL_MAX + 1,
 213                 .min_uV         = LM3632_VLDO_MIN,
 214                 .uV_step        = LM363X_STEP_50mV,
 215                 .type           = REGULATOR_VOLTAGE,
 216                 .owner          = THIS_MODULE,
 217                 .vsel_reg       = LM3632_REG_VOUT_NEG,
 218                 .vsel_mask      = LM3632_VOUT_MASK,
 219                 .enable_reg     = LM3632_REG_BIAS_CONFIG,
 220                 .enable_mask    = LM3632_EN_VNEG_MASK,
 221         },
 222 
 223         /* LM36274 */
 224         {
 225                 .name           = "vboost",
 226                 .of_match       = "vboost",
 227                 .id             = LM36274_BOOST,
 228                 .ops            = &lm363x_boost_voltage_table_ops,
 229                 .n_voltages     = LM36274_BOOST_VSEL_MAX + 1,
 230                 .min_uV         = LM36274_VOLTAGE_MIN,
 231                 .uV_step        = LM363X_STEP_50mV,
 232                 .type           = REGULATOR_VOLTAGE,
 233                 .owner          = THIS_MODULE,
 234                 .vsel_reg       = LM36274_REG_VOUT_BOOST,
 235                 .vsel_mask      = LM36274_VOUT_MASK,
 236         },
 237         {
 238                 .name           = "ldo_vpos",
 239                 .of_match       = "vpos",
 240                 .id             = LM36274_LDO_POS,
 241                 .ops            = &lm363x_regulator_voltage_table_ops,
 242                 .n_voltages     = LM36274_LDO_VSEL_MAX + 1,
 243                 .min_uV         = LM36274_VOLTAGE_MIN,
 244                 .uV_step        = LM363X_STEP_50mV,
 245                 .type           = REGULATOR_VOLTAGE,
 246                 .owner          = THIS_MODULE,
 247                 .vsel_reg       = LM36274_REG_VOUT_POS,
 248                 .vsel_mask      = LM36274_VOUT_MASK,
 249                 .enable_reg     = LM36274_REG_BIAS_CONFIG_1,
 250                 .enable_mask    = LM36274_EN_VPOS_MASK,
 251         },
 252         {
 253                 .name           = "ldo_vneg",
 254                 .of_match       = "vneg",
 255                 .id             = LM36274_LDO_NEG,
 256                 .ops            = &lm363x_regulator_voltage_table_ops,
 257                 .n_voltages     = LM36274_LDO_VSEL_MAX + 1,
 258                 .min_uV         = LM36274_VOLTAGE_MIN,
 259                 .uV_step        = LM363X_STEP_50mV,
 260                 .type           = REGULATOR_VOLTAGE,
 261                 .owner          = THIS_MODULE,
 262                 .vsel_reg       = LM36274_REG_VOUT_NEG,
 263                 .vsel_mask      = LM36274_VOUT_MASK,
 264                 .enable_reg     = LM36274_REG_BIAS_CONFIG_1,
 265                 .enable_mask    = LM36274_EN_VNEG_MASK,
 266         },
 267 };
 268 
 269 static struct gpio_desc *lm363x_regulator_of_get_enable_gpio(struct device *dev, int id)
 270 {
 271         /*
 272          * Check LCM_EN1/2_GPIO is configured.
 273          * Those pins are used for enabling VPOS/VNEG LDOs.
 274          * Do not use devm* here: the regulator core takes over the
 275          * lifecycle management of the GPIO descriptor.
 276          */
 277         switch (id) {
 278         case LM3632_LDO_POS:
 279         case LM36274_LDO_POS:
 280                 return gpiod_get_index_optional(dev, "enable", 0,
 281                                 GPIOD_OUT_LOW | GPIOD_FLAGS_BIT_NONEXCLUSIVE);
 282         case LM3632_LDO_NEG:
 283         case LM36274_LDO_NEG:
 284                 return gpiod_get_index_optional(dev, "enable", 1,
 285                                 GPIOD_OUT_LOW | GPIOD_FLAGS_BIT_NONEXCLUSIVE);
 286         default:
 287                 return NULL;
 288         }
 289 }
 290 
 291 static int lm363x_regulator_set_ext_en(struct regmap *regmap, int id)
 292 {
 293         int ext_en_mask = 0;
 294 
 295         switch (id) {
 296         case LM3632_LDO_POS:
 297         case LM3632_LDO_NEG:
 298                 ext_en_mask = LM3632_EXT_EN_MASK;
 299                 break;
 300         case LM36274_LDO_POS:
 301         case LM36274_LDO_NEG:
 302                 ext_en_mask = LM36274_EXT_EN_MASK;
 303                 break;
 304         default:
 305                 return -ENODEV;
 306         }
 307 
 308         return regmap_update_bits(regmap, lm363x_regulator_desc[id].enable_reg,
 309                                  ext_en_mask, ext_en_mask);
 310 }
 311 
 312 static int lm363x_regulator_probe(struct platform_device *pdev)
 313 {
 314         struct ti_lmu *lmu = dev_get_drvdata(pdev->dev.parent);
 315         struct regmap *regmap = lmu->regmap;
 316         struct regulator_config cfg = { };
 317         struct regulator_dev *rdev;
 318         struct device *dev = &pdev->dev;
 319         int id = pdev->id;
 320         struct gpio_desc *gpiod;
 321         int ret;
 322 
 323         cfg.dev = dev;
 324         cfg.regmap = regmap;
 325 
 326         /*
 327          * LM3632 LDOs can be controlled by external pin.
 328          * Register update is required if the pin is used.
 329          */
 330         gpiod = lm363x_regulator_of_get_enable_gpio(dev, id);
 331         if (IS_ERR(gpiod))
 332                 return PTR_ERR(gpiod);
 333 
 334         if (gpiod) {
 335                 cfg.ena_gpiod = gpiod;
 336                 ret = lm363x_regulator_set_ext_en(regmap, id);
 337                 if (ret) {
 338                         gpiod_put(gpiod);
 339                         dev_err(dev, "External pin err: %d\n", ret);
 340                         return ret;
 341                 }
 342         }
 343 
 344         rdev = devm_regulator_register(dev, &lm363x_regulator_desc[id], &cfg);
 345         if (IS_ERR(rdev)) {
 346                 ret = PTR_ERR(rdev);
 347                 dev_err(dev, "[%d] regulator register err: %d\n", id, ret);
 348                 return ret;
 349         }
 350 
 351         return 0;
 352 }
 353 
 354 static struct platform_driver lm363x_regulator_driver = {
 355         .probe = lm363x_regulator_probe,
 356         .driver = {
 357                 .name = "lm363x-regulator",
 358         },
 359 };
 360 
 361 module_platform_driver(lm363x_regulator_driver);
 362 
 363 MODULE_DESCRIPTION("TI LM363X Regulator Driver");
 364 MODULE_AUTHOR("Milo Kim");
 365 MODULE_LICENSE("GPL v2");
 366 MODULE_ALIAS("platform:lm363x-regulator");

/* [<][>][^][v][top][bottom][index][help] */