368 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * TI LM363X Regulator Driver4 *5 * Copyright 2015 Texas Instruments6 *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 0x2524#define LM3631_LDO_VSEL_MAX 0x2825#define LM3631_CONT_VSEL_MAX 0x0326#define LM3631_VBOOST_MIN 450000027#define LM3631_VCONT_MIN 180000028#define LM3631_VLDO_MIN 400000029#define ENABLE_TIME_USEC 100030 31/* LM3632 */32#define LM3632_BOOST_VSEL_MAX 0x2633#define LM3632_LDO_VSEL_MAX 0x2834#define LM3632_VBOOST_MIN 450000035#define LM3632_VLDO_MIN 400000036 37/* LM36274 */38#define LM36274_BOOST_VSEL_MAX 0x3f39#define LM36274_LDO_VSEL_MAX 0x3240#define LM36274_VOLTAGE_MIN 400000041 42/* Common */43#define LM363X_STEP_50mV 5000044#define LM363X_STEP_500mV 50000045 46static const int ldo_cont_enable_time[] = {47 0, 2000, 5000, 10000, 20000, 50000, 100000, 200000,48};49 50static 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 else84 return ENABLE_TIME_USEC * val;85}86 87static 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 93static 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 103static 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 269static 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 the275 * 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 291static 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 312static 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 354static struct platform_driver lm363x_regulator_driver = {355 .probe = lm363x_regulator_probe,356 .driver = {357 .name = "lm363x-regulator",358 .probe_type = PROBE_PREFER_ASYNCHRONOUS,359 },360};361 362module_platform_driver(lm363x_regulator_driver);363 364MODULE_DESCRIPTION("TI LM363X Regulator Driver");365MODULE_AUTHOR("Milo Kim");366MODULE_LICENSE("GPL v2");367MODULE_ALIAS("platform:lm363x-regulator");368