brintos

brintos / linux-shallow public Read only

0
0
Text · 10.9 KiB · 6655d9c Raw
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