420 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (C) 2015 Texas Instruments Incorporated - https://www.ti.com/4 *5 * Author: Andrew F. Davis <afd@ti.com>6 *7 * Based on the TPS65912 driver8 */9 10#include <linux/module.h>11#include <linux/of.h>12#include <linux/platform_device.h>13#include <linux/regulator/driver.h>14 15#include <linux/mfd/tps65086.h>16 17enum tps65086_regulators { BUCK1, BUCK2, BUCK3, BUCK4, BUCK5, BUCK6, LDOA1,18 LDOA2, LDOA3, VTT, SWA1, SWB1, SWB2 };19 20/* Selector for regulator configuration regarding PMIC chip ID. */21enum tps65086_ids {22 TPS6508640 = 0,23 TPS65086401,24 TPS6508641,25 TPS65086470,26};27 28#define TPS65086_REGULATOR(_name, _of, _id, _nv, _vr, _vm, _er, _em, _lr, _dr, _dm) \29 [_id] = { \30 .desc = { \31 .name = _name, \32 .of_match = of_match_ptr(_of), \33 .regulators_node = "regulators", \34 .of_parse_cb = tps65086_of_parse_cb, \35 .id = _id, \36 .ops = ®_ops, \37 .n_voltages = _nv, \38 .type = REGULATOR_VOLTAGE, \39 .owner = THIS_MODULE, \40 .vsel_reg = _vr, \41 .vsel_mask = _vm, \42 .enable_reg = _er, \43 .enable_mask = _em, \44 .volt_table = NULL, \45 .linear_ranges = _lr, \46 .n_linear_ranges = ARRAY_SIZE(_lr), \47 }, \48 .decay_reg = _dr, \49 .decay_mask = _dm, \50 }51 52#define TPS65086_SWITCH(_name, _of, _id, _er, _em) \53 [_id] = { \54 .desc = { \55 .name = _name, \56 .of_match = of_match_ptr(_of), \57 .regulators_node = "regulators", \58 .of_parse_cb = tps65086_of_parse_cb, \59 .id = _id, \60 .ops = &switch_ops, \61 .type = REGULATOR_VOLTAGE, \62 .owner = THIS_MODULE, \63 .enable_reg = _er, \64 .enable_mask = _em, \65 }, \66 }67 68 69#define TPS65086_REGULATOR_CONFIG(_chip_id, _config) \70 [_chip_id] = { \71 .config = _config, \72 .num_elems = ARRAY_SIZE(_config), \73 }74 75struct tps65086_regulator {76 struct regulator_desc desc;77 unsigned int decay_reg;78 unsigned int decay_mask;79};80 81struct tps65086_regulator_config {82 struct tps65086_regulator * const config;83 const unsigned int num_elems;84};85 86static const struct linear_range tps65086_10mv_ranges[] = {87 REGULATOR_LINEAR_RANGE(0, 0x0, 0x0, 0),88 REGULATOR_LINEAR_RANGE(410000, 0x1, 0x7F, 10000),89};90 91static const struct linear_range tps65086_buck126_25mv_ranges[] = {92 REGULATOR_LINEAR_RANGE(0, 0x0, 0x0, 0),93 REGULATOR_LINEAR_RANGE(1000000, 0x1, 0x18, 0),94 REGULATOR_LINEAR_RANGE(1025000, 0x19, 0x7F, 25000),95};96 97static const struct linear_range tps65086_buck345_25mv_ranges[] = {98 REGULATOR_LINEAR_RANGE(0, 0x0, 0x0, 0),99 REGULATOR_LINEAR_RANGE(425000, 0x1, 0x7F, 25000),100};101 102static const struct linear_range tps65086_ldoa1_ranges[] = {103 REGULATOR_LINEAR_RANGE(1350000, 0x0, 0x0, 0),104 REGULATOR_LINEAR_RANGE(1500000, 0x1, 0x7, 100000),105 REGULATOR_LINEAR_RANGE(2300000, 0x8, 0xB, 100000),106 REGULATOR_LINEAR_RANGE(2850000, 0xC, 0xD, 150000),107 REGULATOR_LINEAR_RANGE(3300000, 0xE, 0xE, 0),108};109 110static const struct linear_range tps65086_ldoa23_ranges[] = {111 REGULATOR_LINEAR_RANGE(700000, 0x0, 0xD, 50000),112 REGULATOR_LINEAR_RANGE(1400000, 0xE, 0xF, 100000),113};114 115/* Operations permitted on regulators */116static const struct regulator_ops reg_ops = {117 .enable = regulator_enable_regmap,118 .disable = regulator_disable_regmap,119 .is_enabled = regulator_is_enabled_regmap,120 .set_voltage_sel = regulator_set_voltage_sel_regmap,121 .map_voltage = regulator_map_voltage_linear_range,122 .get_voltage_sel = regulator_get_voltage_sel_regmap,123 .list_voltage = regulator_list_voltage_linear_range,124};125 126/* Operations permitted on load switches */127static const struct regulator_ops switch_ops = {128 .enable = regulator_enable_regmap,129 .disable = regulator_disable_regmap,130 .is_enabled = regulator_is_enabled_regmap,131};132 133static int tps65086_of_parse_cb(struct device_node *dev,134 const struct regulator_desc *desc,135 struct regulator_config *config);136 137static struct tps65086_regulator tps6508640_regulator_config[] = {138 TPS65086_REGULATOR("BUCK1", "buck1", BUCK1, 0x80, TPS65086_BUCK1CTRL,139 BUCK_VID_MASK, TPS65086_BUCK123CTRL, BIT(0),140 tps65086_10mv_ranges, TPS65086_BUCK1CTRL,141 BIT(0)),142 TPS65086_REGULATOR("BUCK2", "buck2", BUCK2, 0x80, TPS65086_BUCK2CTRL,143 BUCK_VID_MASK, TPS65086_BUCK123CTRL, BIT(1),144 tps65086_10mv_ranges, TPS65086_BUCK2CTRL,145 BIT(0)),146 TPS65086_REGULATOR("BUCK3", "buck3", BUCK3, 0x80, TPS65086_BUCK3VID,147 BUCK_VID_MASK, TPS65086_BUCK123CTRL, BIT(2),148 tps65086_10mv_ranges, TPS65086_BUCK3DECAY,149 BIT(0)),150 TPS65086_REGULATOR("BUCK4", "buck4", BUCK4, 0x80, TPS65086_BUCK4VID,151 BUCK_VID_MASK, TPS65086_BUCK4CTRL, BIT(0),152 tps65086_10mv_ranges, TPS65086_BUCK4VID,153 BIT(0)),154 TPS65086_REGULATOR("BUCK5", "buck5", BUCK5, 0x80, TPS65086_BUCK5VID,155 BUCK_VID_MASK, TPS65086_BUCK5CTRL, BIT(0),156 tps65086_10mv_ranges, TPS65086_BUCK5CTRL,157 BIT(0)),158 TPS65086_REGULATOR("BUCK6", "buck6", BUCK6, 0x80, TPS65086_BUCK6VID,159 BUCK_VID_MASK, TPS65086_BUCK6CTRL, BIT(0),160 tps65086_10mv_ranges, TPS65086_BUCK6CTRL,161 BIT(0)),162 TPS65086_REGULATOR("LDOA1", "ldoa1", LDOA1, 0xF, TPS65086_LDOA1CTRL,163 VDOA1_VID_MASK, TPS65086_SWVTT_EN, BIT(7),164 tps65086_ldoa1_ranges, 0, 0),165 TPS65086_REGULATOR("LDOA2", "ldoa2", LDOA2, 0x10, TPS65086_LDOA2VID,166 VDOA23_VID_MASK, TPS65086_LDOA2CTRL, BIT(0),167 tps65086_ldoa23_ranges, 0, 0),168 TPS65086_REGULATOR("LDOA3", "ldoa3", LDOA3, 0x10, TPS65086_LDOA3VID,169 VDOA23_VID_MASK, TPS65086_LDOA3CTRL, BIT(0),170 tps65086_ldoa23_ranges, 0, 0),171 TPS65086_SWITCH("VTT", "vtt", VTT, TPS65086_SWVTT_EN, BIT(4)),172 TPS65086_SWITCH("SWA1", "swa1", SWA1, TPS65086_SWVTT_EN, BIT(5)),173 TPS65086_SWITCH("SWB1", "swb1", SWB1, TPS65086_SWVTT_EN, BIT(6)),174 TPS65086_SWITCH("SWB2", "swb2", SWB2, TPS65086_LDOA1CTRL, BIT(0)),175};176 177static struct tps65086_regulator tps65086401_regulator_config[] = {178 TPS65086_REGULATOR("BUCK1", "buck1", BUCK1, 0x80, TPS65086_BUCK1CTRL,179 BUCK_VID_MASK, TPS65086_BUCK123CTRL, BIT(0),180 tps65086_10mv_ranges, TPS65086_BUCK1CTRL,181 BIT(0)),182 TPS65086_REGULATOR("BUCK2", "buck2", BUCK2, 0x80, TPS65086_BUCK2CTRL,183 BUCK_VID_MASK, TPS65086_BUCK123CTRL, BIT(1),184 tps65086_10mv_ranges, TPS65086_BUCK2CTRL,185 BIT(0)),186 TPS65086_REGULATOR("BUCK3", "buck3", BUCK3, 0x80, TPS65086_BUCK3VID,187 BUCK_VID_MASK, TPS65086_BUCK123CTRL, BIT(2),188 tps65086_10mv_ranges, TPS65086_BUCK3DECAY,189 BIT(0)),190 TPS65086_REGULATOR("BUCK4", "buck4", BUCK4, 0x80, TPS65086_BUCK4VID,191 BUCK_VID_MASK, TPS65086_BUCK4CTRL, BIT(0),192 tps65086_10mv_ranges, TPS65086_BUCK4VID,193 BIT(0)),194 TPS65086_REGULATOR("BUCK5", "buck5", BUCK5, 0x80, TPS65086_BUCK5VID,195 BUCK_VID_MASK, TPS65086_BUCK5CTRL, BIT(0),196 tps65086_10mv_ranges, TPS65086_BUCK5CTRL,197 BIT(0)),198 TPS65086_REGULATOR("BUCK6", "buck6", BUCK6, 0x80, TPS65086_BUCK6VID,199 BUCK_VID_MASK, TPS65086_BUCK6CTRL, BIT(0),200 tps65086_10mv_ranges, TPS65086_BUCK6CTRL,201 BIT(0)),202 TPS65086_REGULATOR("LDOA1", "ldoa1", LDOA1, 0xF, TPS65086_LDOA1CTRL,203 VDOA1_VID_MASK, TPS65086_SWVTT_EN, BIT(7),204 tps65086_ldoa1_ranges, 0, 0),205 TPS65086_REGULATOR("LDOA2", "ldoa2", LDOA2, 0x10, TPS65086_LDOA2VID,206 VDOA23_VID_MASK, TPS65086_LDOA2CTRL, BIT(0),207 tps65086_ldoa23_ranges, 0, 0),208 TPS65086_REGULATOR("LDOA3", "ldoa3", LDOA3, 0x10, TPS65086_LDOA3VID,209 VDOA23_VID_MASK, TPS65086_LDOA3CTRL, BIT(0),210 tps65086_ldoa23_ranges, 0, 0),211 TPS65086_SWITCH("VTT", "vtt", VTT, TPS65086_SWVTT_EN, BIT(4)),212 TPS65086_SWITCH("SWA1", "swa1", SWA1, TPS65086_SWVTT_EN, BIT(5)),213 TPS65086_SWITCH("SWB1", "swb1", SWB1, TPS65086_SWVTT_EN, BIT(6)),214};215 216static struct tps65086_regulator tps6508641_regulator_config[] = {217 TPS65086_REGULATOR("BUCK1", "buck1", BUCK1, 0x80, TPS65086_BUCK1CTRL,218 BUCK_VID_MASK, TPS65086_BUCK123CTRL, BIT(0),219 tps65086_10mv_ranges, TPS65086_BUCK1CTRL,220 BIT(0)),221 TPS65086_REGULATOR("BUCK2", "buck2", BUCK2, 0x80, TPS65086_BUCK2CTRL,222 BUCK_VID_MASK, TPS65086_BUCK123CTRL, BIT(1),223 tps65086_10mv_ranges, TPS65086_BUCK2CTRL,224 BIT(0)),225 TPS65086_REGULATOR("BUCK3", "buck3", BUCK3, 0x80, TPS65086_BUCK3VID,226 BUCK_VID_MASK, TPS65086_BUCK123CTRL, BIT(2),227 tps65086_10mv_ranges, TPS65086_BUCK3DECAY,228 BIT(0)),229 TPS65086_REGULATOR("BUCK4", "buck4", BUCK4, 0x80, TPS65086_BUCK4VID,230 BUCK_VID_MASK, TPS65086_BUCK4CTRL, BIT(0),231 tps65086_10mv_ranges, TPS65086_BUCK4VID,232 BIT(0)),233 TPS65086_REGULATOR("BUCK5", "buck5", BUCK5, 0x80, TPS65086_BUCK5VID,234 BUCK_VID_MASK, TPS65086_BUCK5CTRL, BIT(0),235 tps65086_10mv_ranges, TPS65086_BUCK5CTRL,236 BIT(0)),237 TPS65086_REGULATOR("BUCK6", "buck6", BUCK6, 0x80, TPS65086_BUCK6VID,238 BUCK_VID_MASK, TPS65086_BUCK6CTRL, BIT(0),239 tps65086_10mv_ranges, TPS65086_BUCK6CTRL,240 BIT(0)),241 TPS65086_REGULATOR("LDOA1", "ldoa1", LDOA1, 0xF, TPS65086_LDOA1CTRL,242 VDOA1_VID_MASK, TPS65086_SWVTT_EN, BIT(7),243 tps65086_ldoa1_ranges, 0, 0),244 TPS65086_REGULATOR("LDOA2", "ldoa2", LDOA2, 0x10, TPS65086_LDOA2VID,245 VDOA23_VID_MASK, TPS65086_LDOA2CTRL, BIT(0),246 tps65086_ldoa23_ranges, 0, 0),247 TPS65086_REGULATOR("LDOA3", "ldoa3", LDOA3, 0x10, TPS65086_LDOA3VID,248 VDOA23_VID_MASK, TPS65086_LDOA3CTRL, BIT(0),249 tps65086_ldoa23_ranges, 0, 0),250 TPS65086_SWITCH("VTT", "vtt", VTT, TPS65086_SWVTT_EN, BIT(4)),251 TPS65086_SWITCH("SWA1", "swa1", SWA1, TPS65086_SWVTT_EN, BIT(5)),252 TPS65086_SWITCH("SWB1", "swb1", SWB1, TPS65086_SWVTT_EN, BIT(6)),253};254 255static struct tps65086_regulator tps65086470_regulator_config[] = {256 TPS65086_REGULATOR("BUCK1", "buck1", BUCK1, 0x80, TPS65086_BUCK1CTRL,257 BUCK_VID_MASK, TPS65086_BUCK123CTRL, BIT(0),258 tps65086_10mv_ranges, TPS65086_BUCK1CTRL,259 BIT(0)),260 TPS65086_REGULATOR("BUCK2", "buck2", BUCK2, 0x80, TPS65086_BUCK2CTRL,261 BUCK_VID_MASK, TPS65086_BUCK123CTRL, BIT(1),262 tps65086_10mv_ranges, TPS65086_BUCK2CTRL,263 BIT(0)),264 TPS65086_REGULATOR("BUCK3", "buck3", BUCK3, 0x80, TPS65086_BUCK3VID,265 BUCK_VID_MASK, TPS65086_BUCK123CTRL, BIT(2),266 tps65086_10mv_ranges, TPS65086_BUCK3DECAY,267 BIT(0)),268 TPS65086_REGULATOR("BUCK4", "buck4", BUCK4, 0x80, TPS65086_BUCK4VID,269 BUCK_VID_MASK, TPS65086_BUCK4CTRL, BIT(0),270 tps65086_10mv_ranges, TPS65086_BUCK4VID,271 BIT(0)),272 TPS65086_REGULATOR("BUCK5", "buck5", BUCK5, 0x80, TPS65086_BUCK5VID,273 BUCK_VID_MASK, TPS65086_BUCK5CTRL, BIT(0),274 tps65086_10mv_ranges, TPS65086_BUCK5CTRL,275 BIT(0)),276 TPS65086_REGULATOR("BUCK6", "buck6", BUCK6, 0x80, TPS65086_BUCK6VID,277 BUCK_VID_MASK, TPS65086_BUCK6CTRL, BIT(0),278 tps65086_10mv_ranges, TPS65086_BUCK6CTRL,279 BIT(0)),280 TPS65086_REGULATOR("LDOA1", "ldoa1", LDOA1, 0xF, TPS65086_LDOA1CTRL,281 VDOA1_VID_MASK, TPS65086_LDOA1CTRL, BIT(0),282 tps65086_ldoa1_ranges, 0, 0),283 TPS65086_REGULATOR("LDOA2", "ldoa2", LDOA2, 0x10, TPS65086_LDOA2VID,284 VDOA23_VID_MASK, TPS65086_LDOA2CTRL, BIT(0),285 tps65086_ldoa23_ranges, 0, 0),286 TPS65086_REGULATOR("LDOA3", "ldoa3", LDOA3, 0x10, TPS65086_LDOA3VID,287 VDOA23_VID_MASK, TPS65086_LDOA3CTRL, BIT(0),288 tps65086_ldoa23_ranges, 0, 0),289 TPS65086_SWITCH("VTT", "vtt", VTT, TPS65086_SWVTT_EN, BIT(4)),290 TPS65086_SWITCH("SWA1", "swa1", SWA1, TPS65086_SWVTT_EN, BIT(5)),291 TPS65086_SWITCH("SWB1", "swb1", SWB1, TPS65086_SWVTT_EN, BIT(6)),292 TPS65086_SWITCH("SWB2", "swb2", SWB2, TPS65086_SWVTT_EN, BIT(7)),293};294 295static const struct tps65086_regulator_config regulator_configs[] = {296 TPS65086_REGULATOR_CONFIG(TPS6508640, tps6508640_regulator_config),297 TPS65086_REGULATOR_CONFIG(TPS65086401, tps65086401_regulator_config),298 TPS65086_REGULATOR_CONFIG(TPS6508641, tps6508641_regulator_config),299 TPS65086_REGULATOR_CONFIG(TPS65086470, tps65086470_regulator_config)300};301 302static int tps65086_of_parse_cb(struct device_node *node,303 const struct regulator_desc *desc,304 struct regulator_config *config)305{306 struct tps65086 * const tps = dev_get_drvdata(config->dev);307 struct tps65086_regulator *regulators = tps->reg_config->config;308 int ret;309 310 /* Check for 25mV step mode */311 if (of_property_read_bool(node, "ti,regulator-step-size-25mv")) {312 switch (desc->id) {313 case BUCK1:314 case BUCK2:315 case BUCK6:316 regulators[desc->id].desc.linear_ranges =317 tps65086_buck126_25mv_ranges;318 regulators[desc->id].desc.n_linear_ranges =319 ARRAY_SIZE(tps65086_buck126_25mv_ranges);320 break;321 case BUCK3:322 case BUCK4:323 case BUCK5:324 regulators[desc->id].desc.linear_ranges =325 tps65086_buck345_25mv_ranges;326 regulators[desc->id].desc.n_linear_ranges =327 ARRAY_SIZE(tps65086_buck345_25mv_ranges);328 break;329 default:330 dev_warn(config->dev, "25mV step mode only valid for BUCK regulators\n");331 }332 }333 334 /* Check for decay mode */335 if (desc->id <= BUCK6 && of_property_read_bool(node, "ti,regulator-decay")) {336 ret = regmap_write_bits(config->regmap,337 regulators[desc->id].decay_reg,338 regulators[desc->id].decay_mask,339 regulators[desc->id].decay_mask);340 if (ret) {341 dev_err(config->dev, "Error setting decay\n");342 return ret;343 }344 }345 346 return 0;347}348 349static int tps65086_regulator_probe(struct platform_device *pdev)350{351 struct tps65086 *tps = dev_get_drvdata(pdev->dev.parent);352 struct regulator_config config = { };353 unsigned int selector_reg_config;354 struct regulator_dev *rdev;355 int i;356 357 /* Select regulator configuration for used PMIC device */358 switch (tps->chip_id) {359 case TPS6508640_ID:360 selector_reg_config = TPS6508640;361 break;362 case TPS65086401_ID:363 selector_reg_config = TPS65086401;364 break;365 case TPS6508641_ID:366 selector_reg_config = TPS6508641;367 break;368 case TPS65086470_ID:369 selector_reg_config = TPS65086470;370 break;371 default:372 dev_err(tps->dev, "Unknown device ID. Cannot determine regulator config.\n");373 return -ENODEV;374 }375 tps->reg_config = ®ulator_configs[selector_reg_config];376 377 platform_set_drvdata(pdev, tps);378 379 config.dev = &pdev->dev;380 config.dev->of_node = tps->dev->of_node;381 config.driver_data = tps;382 config.regmap = tps->regmap;383 384 for (i = 0; i < tps->reg_config->num_elems; ++i) {385 struct regulator_desc * const desc_ptr = &tps->reg_config->config[i].desc;386 387 dev_dbg(tps->dev, "Index: %u; Regulator name: \"%s\"; Regulator ID: %d\n",388 i, desc_ptr->name, desc_ptr->id);389 390 rdev = devm_regulator_register(&pdev->dev, desc_ptr, &config);391 if (IS_ERR(rdev)) {392 dev_err(tps->dev, "failed to register %d \"%s\" regulator\n",393 i, desc_ptr->name);394 return PTR_ERR(rdev);395 }396 }397 398 return 0;399}400 401static const struct platform_device_id tps65086_regulator_id_table[] = {402 { "tps65086-regulator", },403 { /* sentinel */ }404};405MODULE_DEVICE_TABLE(platform, tps65086_regulator_id_table);406 407static struct platform_driver tps65086_regulator_driver = {408 .driver = {409 .name = "tps65086-regulator",410 .probe_type = PROBE_PREFER_ASYNCHRONOUS,411 },412 .probe = tps65086_regulator_probe,413 .id_table = tps65086_regulator_id_table,414};415module_platform_driver(tps65086_regulator_driver);416 417MODULE_AUTHOR("Andrew F. Davis <afd@ti.com>");418MODULE_DESCRIPTION("TPS65086 Regulator driver");419MODULE_LICENSE("GPL v2");420