462 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * tps6507x-regulator.c4 *5 * Regulator driver for TPS65073 PMIC6 *7 * Copyright (C) 2009 Texas Instrument Incorporated - https://www.ti.com/8 */9 10#include <linux/kernel.h>11#include <linux/module.h>12#include <linux/init.h>13#include <linux/err.h>14#include <linux/platform_device.h>15#include <linux/regulator/driver.h>16#include <linux/regulator/machine.h>17#include <linux/regulator/tps6507x.h>18#include <linux/of.h>19#include <linux/slab.h>20#include <linux/mfd/tps6507x.h>21#include <linux/regulator/of_regulator.h>22 23/* DCDC's */24#define TPS6507X_DCDC_1 025#define TPS6507X_DCDC_2 126#define TPS6507X_DCDC_3 227/* LDOs */28#define TPS6507X_LDO_1 329#define TPS6507X_LDO_2 430 31#define TPS6507X_MAX_REG_ID TPS6507X_LDO_232 33/* Number of step-down converters available */34#define TPS6507X_NUM_DCDC 335/* Number of LDO voltage regulators available */36#define TPS6507X_NUM_LDO 237/* Number of total regulators available */38#define TPS6507X_NUM_REGULATOR (TPS6507X_NUM_DCDC + TPS6507X_NUM_LDO)39 40/* Supported voltage values for regulators (in microVolts) */41static const unsigned int VDCDCx_VSEL_table[] = {42 725000, 750000, 775000, 800000,43 825000, 850000, 875000, 900000,44 925000, 950000, 975000, 1000000,45 1025000, 1050000, 1075000, 1100000,46 1125000, 1150000, 1175000, 1200000,47 1225000, 1250000, 1275000, 1300000,48 1325000, 1350000, 1375000, 1400000,49 1425000, 1450000, 1475000, 1500000,50 1550000, 1600000, 1650000, 1700000,51 1750000, 1800000, 1850000, 1900000,52 1950000, 2000000, 2050000, 2100000,53 2150000, 2200000, 2250000, 2300000,54 2350000, 2400000, 2450000, 2500000,55 2550000, 2600000, 2650000, 2700000,56 2750000, 2800000, 2850000, 2900000,57 3000000, 3100000, 3200000, 3300000,58};59 60static const unsigned int LDO1_VSEL_table[] = {61 1000000, 1100000, 1200000, 1250000,62 1300000, 1350000, 1400000, 1500000,63 1600000, 1800000, 2500000, 2750000,64 2800000, 3000000, 3100000, 3300000,65};66 67/* The voltage mapping table for LDO2 is the same as VDCDCx */68#define LDO2_VSEL_table VDCDCx_VSEL_table69 70struct tps_info {71 const char *name;72 u8 table_len;73 const unsigned int *table;74 75 /* Does DCDC high or the low register defines output voltage? */76 bool defdcdc_default;77};78 79static struct tps_info tps6507x_pmic_regs[] = {80 {81 .name = "VDCDC1",82 .table_len = ARRAY_SIZE(VDCDCx_VSEL_table),83 .table = VDCDCx_VSEL_table,84 },85 {86 .name = "VDCDC2",87 .table_len = ARRAY_SIZE(VDCDCx_VSEL_table),88 .table = VDCDCx_VSEL_table,89 },90 {91 .name = "VDCDC3",92 .table_len = ARRAY_SIZE(VDCDCx_VSEL_table),93 .table = VDCDCx_VSEL_table,94 },95 {96 .name = "LDO1",97 .table_len = ARRAY_SIZE(LDO1_VSEL_table),98 .table = LDO1_VSEL_table,99 },100 {101 .name = "LDO2",102 .table_len = ARRAY_SIZE(LDO2_VSEL_table),103 .table = LDO2_VSEL_table,104 },105};106 107struct tps6507x_pmic {108 struct regulator_desc desc[TPS6507X_NUM_REGULATOR];109 struct tps6507x_dev *mfd;110 struct tps_info *info[TPS6507X_NUM_REGULATOR];111 struct mutex io_lock;112};113static inline int tps6507x_pmic_read(struct tps6507x_pmic *tps, u8 reg)114{115 u8 val;116 int err;117 118 err = tps->mfd->read_dev(tps->mfd, reg, 1, &val);119 120 if (err)121 return err;122 123 return val;124}125 126static inline int tps6507x_pmic_write(struct tps6507x_pmic *tps, u8 reg, u8 val)127{128 return tps->mfd->write_dev(tps->mfd, reg, 1, &val);129}130 131static int tps6507x_pmic_set_bits(struct tps6507x_pmic *tps, u8 reg, u8 mask)132{133 int err, data;134 135 mutex_lock(&tps->io_lock);136 137 data = tps6507x_pmic_read(tps, reg);138 if (data < 0) {139 dev_err(tps->mfd->dev, "Read from reg 0x%x failed\n", reg);140 err = data;141 goto out;142 }143 144 data |= mask;145 err = tps6507x_pmic_write(tps, reg, data);146 if (err)147 dev_err(tps->mfd->dev, "Write for reg 0x%x failed\n", reg);148 149out:150 mutex_unlock(&tps->io_lock);151 return err;152}153 154static int tps6507x_pmic_clear_bits(struct tps6507x_pmic *tps, u8 reg, u8 mask)155{156 int err, data;157 158 mutex_lock(&tps->io_lock);159 160 data = tps6507x_pmic_read(tps, reg);161 if (data < 0) {162 dev_err(tps->mfd->dev, "Read from reg 0x%x failed\n", reg);163 err = data;164 goto out;165 }166 167 data &= ~mask;168 err = tps6507x_pmic_write(tps, reg, data);169 if (err)170 dev_err(tps->mfd->dev, "Write for reg 0x%x failed\n", reg);171 172out:173 mutex_unlock(&tps->io_lock);174 return err;175}176 177static int tps6507x_pmic_reg_read(struct tps6507x_pmic *tps, u8 reg)178{179 int data;180 181 mutex_lock(&tps->io_lock);182 183 data = tps6507x_pmic_read(tps, reg);184 if (data < 0)185 dev_err(tps->mfd->dev, "Read from reg 0x%x failed\n", reg);186 187 mutex_unlock(&tps->io_lock);188 return data;189}190 191static int tps6507x_pmic_reg_write(struct tps6507x_pmic *tps, u8 reg, u8 val)192{193 int err;194 195 mutex_lock(&tps->io_lock);196 197 err = tps6507x_pmic_write(tps, reg, val);198 if (err < 0)199 dev_err(tps->mfd->dev, "Write for reg 0x%x failed\n", reg);200 201 mutex_unlock(&tps->io_lock);202 return err;203}204 205static int tps6507x_pmic_is_enabled(struct regulator_dev *dev)206{207 struct tps6507x_pmic *tps = rdev_get_drvdata(dev);208 int data, rid = rdev_get_id(dev);209 u8 shift;210 211 if (rid < TPS6507X_DCDC_1 || rid > TPS6507X_LDO_2)212 return -EINVAL;213 214 shift = TPS6507X_MAX_REG_ID - rid;215 data = tps6507x_pmic_reg_read(tps, TPS6507X_REG_CON_CTRL1);216 217 if (data < 0)218 return data;219 else220 return (data & 1<<shift) ? 1 : 0;221}222 223static int tps6507x_pmic_enable(struct regulator_dev *dev)224{225 struct tps6507x_pmic *tps = rdev_get_drvdata(dev);226 int rid = rdev_get_id(dev);227 u8 shift;228 229 if (rid < TPS6507X_DCDC_1 || rid > TPS6507X_LDO_2)230 return -EINVAL;231 232 shift = TPS6507X_MAX_REG_ID - rid;233 return tps6507x_pmic_set_bits(tps, TPS6507X_REG_CON_CTRL1, 1 << shift);234}235 236static int tps6507x_pmic_disable(struct regulator_dev *dev)237{238 struct tps6507x_pmic *tps = rdev_get_drvdata(dev);239 int rid = rdev_get_id(dev);240 u8 shift;241 242 if (rid < TPS6507X_DCDC_1 || rid > TPS6507X_LDO_2)243 return -EINVAL;244 245 shift = TPS6507X_MAX_REG_ID - rid;246 return tps6507x_pmic_clear_bits(tps, TPS6507X_REG_CON_CTRL1,247 1 << shift);248}249 250static int tps6507x_pmic_get_voltage_sel(struct regulator_dev *dev)251{252 struct tps6507x_pmic *tps = rdev_get_drvdata(dev);253 int data, rid = rdev_get_id(dev);254 u8 reg, mask;255 256 switch (rid) {257 case TPS6507X_DCDC_1:258 reg = TPS6507X_REG_DEFDCDC1;259 mask = TPS6507X_DEFDCDCX_DCDC_MASK;260 break;261 case TPS6507X_DCDC_2:262 if (tps->info[rid]->defdcdc_default)263 reg = TPS6507X_REG_DEFDCDC2_HIGH;264 else265 reg = TPS6507X_REG_DEFDCDC2_LOW;266 mask = TPS6507X_DEFDCDCX_DCDC_MASK;267 break;268 case TPS6507X_DCDC_3:269 if (tps->info[rid]->defdcdc_default)270 reg = TPS6507X_REG_DEFDCDC3_HIGH;271 else272 reg = TPS6507X_REG_DEFDCDC3_LOW;273 mask = TPS6507X_DEFDCDCX_DCDC_MASK;274 break;275 case TPS6507X_LDO_1:276 reg = TPS6507X_REG_LDO_CTRL1;277 mask = TPS6507X_REG_LDO_CTRL1_LDO1_MASK;278 break;279 case TPS6507X_LDO_2:280 reg = TPS6507X_REG_DEFLDO2;281 mask = TPS6507X_REG_DEFLDO2_LDO2_MASK;282 break;283 default:284 return -EINVAL;285 }286 287 data = tps6507x_pmic_reg_read(tps, reg);288 if (data < 0)289 return data;290 291 data &= mask;292 return data;293}294 295static int tps6507x_pmic_set_voltage_sel(struct regulator_dev *dev,296 unsigned selector)297{298 struct tps6507x_pmic *tps = rdev_get_drvdata(dev);299 int data, rid = rdev_get_id(dev);300 u8 reg, mask;301 302 switch (rid) {303 case TPS6507X_DCDC_1:304 reg = TPS6507X_REG_DEFDCDC1;305 mask = TPS6507X_DEFDCDCX_DCDC_MASK;306 break;307 case TPS6507X_DCDC_2:308 if (tps->info[rid]->defdcdc_default)309 reg = TPS6507X_REG_DEFDCDC2_HIGH;310 else311 reg = TPS6507X_REG_DEFDCDC2_LOW;312 mask = TPS6507X_DEFDCDCX_DCDC_MASK;313 break;314 case TPS6507X_DCDC_3:315 if (tps->info[rid]->defdcdc_default)316 reg = TPS6507X_REG_DEFDCDC3_HIGH;317 else318 reg = TPS6507X_REG_DEFDCDC3_LOW;319 mask = TPS6507X_DEFDCDCX_DCDC_MASK;320 break;321 case TPS6507X_LDO_1:322 reg = TPS6507X_REG_LDO_CTRL1;323 mask = TPS6507X_REG_LDO_CTRL1_LDO1_MASK;324 break;325 case TPS6507X_LDO_2:326 reg = TPS6507X_REG_DEFLDO2;327 mask = TPS6507X_REG_DEFLDO2_LDO2_MASK;328 break;329 default:330 return -EINVAL;331 }332 333 data = tps6507x_pmic_reg_read(tps, reg);334 if (data < 0)335 return data;336 337 data &= ~mask;338 data |= selector;339 340 return tps6507x_pmic_reg_write(tps, reg, data);341}342 343static const struct regulator_ops tps6507x_pmic_ops = {344 .is_enabled = tps6507x_pmic_is_enabled,345 .enable = tps6507x_pmic_enable,346 .disable = tps6507x_pmic_disable,347 .get_voltage_sel = tps6507x_pmic_get_voltage_sel,348 .set_voltage_sel = tps6507x_pmic_set_voltage_sel,349 .list_voltage = regulator_list_voltage_table,350 .map_voltage = regulator_map_voltage_ascend,351};352 353static int tps6507x_pmic_of_parse_cb(struct device_node *np,354 const struct regulator_desc *desc,355 struct regulator_config *config)356{357 struct tps6507x_pmic *tps = config->driver_data;358 struct tps_info *info = tps->info[desc->id];359 u32 prop;360 int ret;361 362 ret = of_property_read_u32(np, "ti,defdcdc_default", &prop);363 if (!ret)364 info->defdcdc_default = prop;365 366 return 0;367}368 369static int tps6507x_pmic_probe(struct platform_device *pdev)370{371 struct tps6507x_dev *tps6507x_dev = dev_get_drvdata(pdev->dev.parent);372 struct tps_info *info = &tps6507x_pmic_regs[0];373 struct regulator_config config = { };374 struct regulator_init_data *init_data = NULL;375 struct regulator_dev *rdev;376 struct tps6507x_pmic *tps;377 struct tps6507x_board *tps_board;378 int i;379 380 /**381 * tps_board points to pmic related constants382 * coming from the board-evm file.383 */384 385 tps_board = dev_get_platdata(tps6507x_dev->dev);386 if (tps_board)387 init_data = tps_board->tps6507x_pmic_init_data;388 389 tps = devm_kzalloc(&pdev->dev, sizeof(*tps), GFP_KERNEL);390 if (!tps)391 return -ENOMEM;392 393 mutex_init(&tps->io_lock);394 395 /* common for all regulators */396 tps->mfd = tps6507x_dev;397 398 for (i = 0; i < TPS6507X_NUM_REGULATOR; i++, info++) {399 /* Register the regulators */400 tps->info[i] = info;401 if (init_data && init_data[i].driver_data) {402 struct tps6507x_reg_platform_data *data =403 init_data[i].driver_data;404 info->defdcdc_default = data->defdcdc_default;405 }406 407 tps->desc[i].name = info->name;408 tps->desc[i].of_match = of_match_ptr(info->name);409 tps->desc[i].regulators_node = of_match_ptr("regulators");410 tps->desc[i].of_parse_cb = tps6507x_pmic_of_parse_cb;411 tps->desc[i].id = i;412 tps->desc[i].n_voltages = info->table_len;413 tps->desc[i].volt_table = info->table;414 tps->desc[i].ops = &tps6507x_pmic_ops;415 tps->desc[i].type = REGULATOR_VOLTAGE;416 tps->desc[i].owner = THIS_MODULE;417 418 config.dev = tps6507x_dev->dev;419 config.init_data = init_data;420 config.driver_data = tps;421 422 rdev = devm_regulator_register(&pdev->dev, &tps->desc[i],423 &config);424 if (IS_ERR(rdev)) {425 dev_err(tps6507x_dev->dev,426 "failed to register %s regulator\n",427 pdev->name);428 return PTR_ERR(rdev);429 }430 }431 432 tps6507x_dev->pmic = tps;433 platform_set_drvdata(pdev, tps6507x_dev);434 435 return 0;436}437 438static struct platform_driver tps6507x_pmic_driver = {439 .driver = {440 .name = "tps6507x-pmic",441 .probe_type = PROBE_PREFER_ASYNCHRONOUS,442 },443 .probe = tps6507x_pmic_probe,444};445 446static int __init tps6507x_pmic_init(void)447{448 return platform_driver_register(&tps6507x_pmic_driver);449}450subsys_initcall(tps6507x_pmic_init);451 452static void __exit tps6507x_pmic_cleanup(void)453{454 platform_driver_unregister(&tps6507x_pmic_driver);455}456module_exit(tps6507x_pmic_cleanup);457 458MODULE_AUTHOR("Texas Instruments");459MODULE_DESCRIPTION("TPS6507x voltage regulator driver");460MODULE_LICENSE("GPL v2");461MODULE_ALIAS("platform:tps6507x-pmic");462