Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * TI LM363X Regulator Driver
0004  *
0005  * Copyright 2015 Texas Instruments
0006  *
0007  * Author: Milo Kim <milo.kim@ti.com>
0008  */
0009 
0010 #include <linux/err.h>
0011 #include <linux/kernel.h>
0012 #include <linux/mfd/ti-lmu.h>
0013 #include <linux/mfd/ti-lmu-register.h>
0014 #include <linux/module.h>
0015 #include <linux/of.h>
0016 #include <linux/gpio/consumer.h>
0017 #include <linux/platform_device.h>
0018 #include <linux/regulator/driver.h>
0019 #include <linux/regulator/of_regulator.h>
0020 #include <linux/slab.h>
0021 
0022 /* LM3631 */
0023 #define LM3631_BOOST_VSEL_MAX       0x25
0024 #define LM3631_LDO_VSEL_MAX     0x28
0025 #define LM3631_CONT_VSEL_MAX        0x03
0026 #define LM3631_VBOOST_MIN       4500000
0027 #define LM3631_VCONT_MIN        1800000
0028 #define LM3631_VLDO_MIN         4000000
0029 #define ENABLE_TIME_USEC        1000
0030 
0031 /* LM3632 */
0032 #define LM3632_BOOST_VSEL_MAX       0x26
0033 #define LM3632_LDO_VSEL_MAX     0x28
0034 #define LM3632_VBOOST_MIN       4500000
0035 #define LM3632_VLDO_MIN         4000000
0036 
0037 /* LM36274 */
0038 #define LM36274_BOOST_VSEL_MAX      0x3f
0039 #define LM36274_LDO_VSEL_MAX        0x32
0040 #define LM36274_VOLTAGE_MIN     4000000
0041 
0042 /* Common */
0043 #define LM363X_STEP_50mV        50000
0044 #define LM363X_STEP_500mV       500000
0045 
0046 static const int ldo_cont_enable_time[] = {
0047     0, 2000, 5000, 10000, 20000, 50000, 100000, 200000,
0048 };
0049 
0050 static int lm363x_regulator_enable_time(struct regulator_dev *rdev)
0051 {
0052     enum lm363x_regulator_id id = rdev_get_id(rdev);
0053     unsigned int val, addr, mask;
0054 
0055     switch (id) {
0056     case LM3631_LDO_CONT:
0057         addr = LM3631_REG_ENTIME_VCONT;
0058         mask = LM3631_ENTIME_CONT_MASK;
0059         break;
0060     case LM3631_LDO_OREF:
0061         addr = LM3631_REG_ENTIME_VOREF;
0062         mask = LM3631_ENTIME_MASK;
0063         break;
0064     case LM3631_LDO_POS:
0065         addr = LM3631_REG_ENTIME_VPOS;
0066         mask = LM3631_ENTIME_MASK;
0067         break;
0068     case LM3631_LDO_NEG:
0069         addr = LM3631_REG_ENTIME_VNEG;
0070         mask = LM3631_ENTIME_MASK;
0071         break;
0072     default:
0073         return 0;
0074     }
0075 
0076     if (regmap_read(rdev->regmap, addr, &val))
0077         return -EINVAL;
0078 
0079     val = (val & mask) >> LM3631_ENTIME_SHIFT;
0080 
0081     if (id == LM3631_LDO_CONT)
0082         return ldo_cont_enable_time[val];
0083     else
0084         return ENABLE_TIME_USEC * val;
0085 }
0086 
0087 static const struct regulator_ops lm363x_boost_voltage_table_ops = {
0088     .list_voltage     = regulator_list_voltage_linear,
0089     .set_voltage_sel  = regulator_set_voltage_sel_regmap,
0090     .get_voltage_sel  = regulator_get_voltage_sel_regmap,
0091 };
0092 
0093 static const struct regulator_ops lm363x_regulator_voltage_table_ops = {
0094     .list_voltage     = regulator_list_voltage_linear,
0095     .set_voltage_sel  = regulator_set_voltage_sel_regmap,
0096     .get_voltage_sel  = regulator_get_voltage_sel_regmap,
0097     .enable           = regulator_enable_regmap,
0098     .disable          = regulator_disable_regmap,
0099     .is_enabled       = regulator_is_enabled_regmap,
0100     .enable_time      = lm363x_regulator_enable_time,
0101 };
0102 
0103 static const struct regulator_desc lm363x_regulator_desc[] = {
0104     /* LM3631 */
0105     {
0106         .name           = "vboost",
0107         .of_match   = "vboost",
0108         .id             = LM3631_BOOST,
0109         .ops            = &lm363x_boost_voltage_table_ops,
0110         .n_voltages     = LM3631_BOOST_VSEL_MAX + 1,
0111         .min_uV         = LM3631_VBOOST_MIN,
0112         .uV_step        = LM363X_STEP_50mV,
0113         .type           = REGULATOR_VOLTAGE,
0114         .owner          = THIS_MODULE,
0115         .vsel_reg       = LM3631_REG_VOUT_BOOST,
0116         .vsel_mask      = LM3631_VOUT_MASK,
0117     },
0118     {
0119         .name           = "ldo_cont",
0120         .of_match   = "vcont",
0121         .id             = LM3631_LDO_CONT,
0122         .ops            = &lm363x_regulator_voltage_table_ops,
0123         .n_voltages     = LM3631_CONT_VSEL_MAX + 1,
0124         .min_uV         = LM3631_VCONT_MIN,
0125         .uV_step        = LM363X_STEP_500mV,
0126         .type           = REGULATOR_VOLTAGE,
0127         .owner          = THIS_MODULE,
0128         .vsel_reg       = LM3631_REG_VOUT_CONT,
0129         .vsel_mask      = LM3631_VOUT_CONT_MASK,
0130         .enable_reg     = LM3631_REG_LDO_CTRL2,
0131         .enable_mask    = LM3631_EN_CONT_MASK,
0132     },
0133     {
0134         .name           = "ldo_oref",
0135         .of_match   = "voref",
0136         .id             = LM3631_LDO_OREF,
0137         .ops            = &lm363x_regulator_voltage_table_ops,
0138         .n_voltages     = LM3631_LDO_VSEL_MAX + 1,
0139         .min_uV         = LM3631_VLDO_MIN,
0140         .uV_step        = LM363X_STEP_50mV,
0141         .type           = REGULATOR_VOLTAGE,
0142         .owner          = THIS_MODULE,
0143         .vsel_reg       = LM3631_REG_VOUT_OREF,
0144         .vsel_mask      = LM3631_VOUT_MASK,
0145         .enable_reg     = LM3631_REG_LDO_CTRL1,
0146         .enable_mask    = LM3631_EN_OREF_MASK,
0147     },
0148     {
0149         .name           = "ldo_vpos",
0150         .of_match   = "vpos",
0151         .id             = LM3631_LDO_POS,
0152         .ops            = &lm363x_regulator_voltage_table_ops,
0153         .n_voltages     = LM3631_LDO_VSEL_MAX + 1,
0154         .min_uV         = LM3631_VLDO_MIN,
0155         .uV_step        = LM363X_STEP_50mV,
0156         .type           = REGULATOR_VOLTAGE,
0157         .owner          = THIS_MODULE,
0158         .vsel_reg       = LM3631_REG_VOUT_POS,
0159         .vsel_mask      = LM3631_VOUT_MASK,
0160         .enable_reg     = LM3631_REG_LDO_CTRL1,
0161         .enable_mask    = LM3631_EN_VPOS_MASK,
0162     },
0163     {
0164         .name           = "ldo_vneg",
0165         .of_match   = "vneg",
0166         .id             = LM3631_LDO_NEG,
0167         .ops            = &lm363x_regulator_voltage_table_ops,
0168         .n_voltages     = LM3631_LDO_VSEL_MAX + 1,
0169         .min_uV         = LM3631_VLDO_MIN,
0170         .uV_step        = LM363X_STEP_50mV,
0171         .type           = REGULATOR_VOLTAGE,
0172         .owner          = THIS_MODULE,
0173         .vsel_reg       = LM3631_REG_VOUT_NEG,
0174         .vsel_mask      = LM3631_VOUT_MASK,
0175         .enable_reg     = LM3631_REG_LDO_CTRL1,
0176         .enable_mask    = LM3631_EN_VNEG_MASK,
0177     },
0178     /* LM3632 */
0179     {
0180         .name           = "vboost",
0181         .of_match   = "vboost",
0182         .id             = LM3632_BOOST,
0183         .ops            = &lm363x_boost_voltage_table_ops,
0184         .n_voltages     = LM3632_BOOST_VSEL_MAX + 1,
0185         .min_uV         = LM3632_VBOOST_MIN,
0186         .uV_step        = LM363X_STEP_50mV,
0187         .type           = REGULATOR_VOLTAGE,
0188         .owner          = THIS_MODULE,
0189         .vsel_reg       = LM3632_REG_VOUT_BOOST,
0190         .vsel_mask      = LM3632_VOUT_MASK,
0191     },
0192     {
0193         .name           = "ldo_vpos",
0194         .of_match   = "vpos",
0195         .id             = LM3632_LDO_POS,
0196         .ops            = &lm363x_regulator_voltage_table_ops,
0197         .n_voltages     = LM3632_LDO_VSEL_MAX + 1,
0198         .min_uV         = LM3632_VLDO_MIN,
0199         .uV_step        = LM363X_STEP_50mV,
0200         .type           = REGULATOR_VOLTAGE,
0201         .owner          = THIS_MODULE,
0202         .vsel_reg       = LM3632_REG_VOUT_POS,
0203         .vsel_mask      = LM3632_VOUT_MASK,
0204         .enable_reg     = LM3632_REG_BIAS_CONFIG,
0205         .enable_mask    = LM3632_EN_VPOS_MASK,
0206     },
0207     {
0208         .name           = "ldo_vneg",
0209         .of_match   = "vneg",
0210         .id             = LM3632_LDO_NEG,
0211         .ops            = &lm363x_regulator_voltage_table_ops,
0212         .n_voltages     = LM3632_LDO_VSEL_MAX + 1,
0213         .min_uV         = LM3632_VLDO_MIN,
0214         .uV_step        = LM363X_STEP_50mV,
0215         .type           = REGULATOR_VOLTAGE,
0216         .owner          = THIS_MODULE,
0217         .vsel_reg       = LM3632_REG_VOUT_NEG,
0218         .vsel_mask      = LM3632_VOUT_MASK,
0219         .enable_reg     = LM3632_REG_BIAS_CONFIG,
0220         .enable_mask    = LM3632_EN_VNEG_MASK,
0221     },
0222 
0223     /* LM36274 */
0224     {
0225         .name           = "vboost",
0226         .of_match   = "vboost",
0227         .id             = LM36274_BOOST,
0228         .ops            = &lm363x_boost_voltage_table_ops,
0229         .n_voltages     = LM36274_BOOST_VSEL_MAX + 1,
0230         .min_uV         = LM36274_VOLTAGE_MIN,
0231         .uV_step        = LM363X_STEP_50mV,
0232         .type           = REGULATOR_VOLTAGE,
0233         .owner          = THIS_MODULE,
0234         .vsel_reg       = LM36274_REG_VOUT_BOOST,
0235         .vsel_mask      = LM36274_VOUT_MASK,
0236     },
0237     {
0238         .name           = "ldo_vpos",
0239         .of_match   = "vpos",
0240         .id             = LM36274_LDO_POS,
0241         .ops            = &lm363x_regulator_voltage_table_ops,
0242         .n_voltages     = LM36274_LDO_VSEL_MAX + 1,
0243         .min_uV         = LM36274_VOLTAGE_MIN,
0244         .uV_step        = LM363X_STEP_50mV,
0245         .type           = REGULATOR_VOLTAGE,
0246         .owner          = THIS_MODULE,
0247         .vsel_reg       = LM36274_REG_VOUT_POS,
0248         .vsel_mask      = LM36274_VOUT_MASK,
0249         .enable_reg     = LM36274_REG_BIAS_CONFIG_1,
0250         .enable_mask    = LM36274_EN_VPOS_MASK,
0251     },
0252     {
0253         .name           = "ldo_vneg",
0254         .of_match   = "vneg",
0255         .id             = LM36274_LDO_NEG,
0256         .ops            = &lm363x_regulator_voltage_table_ops,
0257         .n_voltages     = LM36274_LDO_VSEL_MAX + 1,
0258         .min_uV         = LM36274_VOLTAGE_MIN,
0259         .uV_step        = LM363X_STEP_50mV,
0260         .type           = REGULATOR_VOLTAGE,
0261         .owner          = THIS_MODULE,
0262         .vsel_reg       = LM36274_REG_VOUT_NEG,
0263         .vsel_mask      = LM36274_VOUT_MASK,
0264         .enable_reg     = LM36274_REG_BIAS_CONFIG_1,
0265         .enable_mask    = LM36274_EN_VNEG_MASK,
0266     },
0267 };
0268 
0269 static struct gpio_desc *lm363x_regulator_of_get_enable_gpio(struct device *dev, int id)
0270 {
0271     /*
0272      * Check LCM_EN1/2_GPIO is configured.
0273      * Those pins are used for enabling VPOS/VNEG LDOs.
0274      * Do not use devm* here: the regulator core takes over the
0275      * lifecycle management of the GPIO descriptor.
0276      */
0277     switch (id) {
0278     case LM3632_LDO_POS:
0279     case LM36274_LDO_POS:
0280         return gpiod_get_index_optional(dev, "enable", 0,
0281                 GPIOD_OUT_LOW | GPIOD_FLAGS_BIT_NONEXCLUSIVE);
0282     case LM3632_LDO_NEG:
0283     case LM36274_LDO_NEG:
0284         return gpiod_get_index_optional(dev, "enable", 1,
0285                 GPIOD_OUT_LOW | GPIOD_FLAGS_BIT_NONEXCLUSIVE);
0286     default:
0287         return NULL;
0288     }
0289 }
0290 
0291 static int lm363x_regulator_set_ext_en(struct regmap *regmap, int id)
0292 {
0293     int ext_en_mask = 0;
0294 
0295     switch (id) {
0296     case LM3632_LDO_POS:
0297     case LM3632_LDO_NEG:
0298         ext_en_mask = LM3632_EXT_EN_MASK;
0299         break;
0300     case LM36274_LDO_POS:
0301     case LM36274_LDO_NEG:
0302         ext_en_mask = LM36274_EXT_EN_MASK;
0303         break;
0304     default:
0305         return -ENODEV;
0306     }
0307 
0308     return regmap_update_bits(regmap, lm363x_regulator_desc[id].enable_reg,
0309                  ext_en_mask, ext_en_mask);
0310 }
0311 
0312 static int lm363x_regulator_probe(struct platform_device *pdev)
0313 {
0314     struct ti_lmu *lmu = dev_get_drvdata(pdev->dev.parent);
0315     struct regmap *regmap = lmu->regmap;
0316     struct regulator_config cfg = { };
0317     struct regulator_dev *rdev;
0318     struct device *dev = &pdev->dev;
0319     int id = pdev->id;
0320     struct gpio_desc *gpiod;
0321     int ret;
0322 
0323     cfg.dev = dev;
0324     cfg.regmap = regmap;
0325 
0326     /*
0327      * LM3632 LDOs can be controlled by external pin.
0328      * Register update is required if the pin is used.
0329      */
0330     gpiod = lm363x_regulator_of_get_enable_gpio(dev, id);
0331     if (IS_ERR(gpiod))
0332         return PTR_ERR(gpiod);
0333 
0334     if (gpiod) {
0335         cfg.ena_gpiod = gpiod;
0336         ret = lm363x_regulator_set_ext_en(regmap, id);
0337         if (ret) {
0338             gpiod_put(gpiod);
0339             dev_err(dev, "External pin err: %d\n", ret);
0340             return ret;
0341         }
0342     }
0343 
0344     rdev = devm_regulator_register(dev, &lm363x_regulator_desc[id], &cfg);
0345     if (IS_ERR(rdev)) {
0346         ret = PTR_ERR(rdev);
0347         dev_err(dev, "[%d] regulator register err: %d\n", id, ret);
0348         return ret;
0349     }
0350 
0351     return 0;
0352 }
0353 
0354 static struct platform_driver lm363x_regulator_driver = {
0355     .probe = lm363x_regulator_probe,
0356     .driver = {
0357         .name = "lm363x-regulator",
0358     },
0359 };
0360 
0361 module_platform_driver(lm363x_regulator_driver);
0362 
0363 MODULE_DESCRIPTION("TI LM363X Regulator Driver");
0364 MODULE_AUTHOR("Milo Kim");
0365 MODULE_LICENSE("GPL v2");
0366 MODULE_ALIAS("platform:lm363x-regulator");