xref: /openbmc/linux/drivers/regulator/tps6287x-regulator.c (revision b181f7029bd71238ac2754ce7052dffd69432085)
17b0518fbSMårten Lindahl // SPDX-License-Identifier: GPL-2.0-only
27b0518fbSMårten Lindahl /*
37b0518fbSMårten Lindahl  * Copyright (C) 2023 Axis Communications AB
47b0518fbSMårten Lindahl  *
57b0518fbSMårten Lindahl  * Driver for Texas Instruments TPS6287x PMIC.
67b0518fbSMårten Lindahl  * Datasheet: https://www.ti.com/lit/ds/symlink/tps62873.pdf
77b0518fbSMårten Lindahl  */
87b0518fbSMårten Lindahl 
97b0518fbSMårten Lindahl #include <linux/err.h>
107b0518fbSMårten Lindahl #include <linux/i2c.h>
11045a44d4SRob Herring #include <linux/mod_devicetable.h>
127b0518fbSMårten Lindahl #include <linux/module.h>
137b0518fbSMårten Lindahl #include <linux/regmap.h>
147b0518fbSMårten Lindahl #include <linux/regulator/of_regulator.h>
157b0518fbSMårten Lindahl #include <linux/regulator/machine.h>
167b0518fbSMårten Lindahl #include <linux/regulator/driver.h>
177b0518fbSMårten Lindahl #include <linux/bitfield.h>
187b0518fbSMårten Lindahl #include <linux/linear_range.h>
197b0518fbSMårten Lindahl 
207b0518fbSMårten Lindahl #define TPS6287X_VSET		0x00
217b0518fbSMårten Lindahl #define TPS6287X_CTRL1		0x01
227b0518fbSMårten Lindahl #define TPS6287X_CTRL1_VRAMP	GENMASK(1, 0)
237b0518fbSMårten Lindahl #define TPS6287X_CTRL1_FPWMEN	BIT(4)
247b0518fbSMårten Lindahl #define TPS6287X_CTRL1_SWEN	BIT(5)
257b0518fbSMårten Lindahl #define TPS6287X_CTRL2		0x02
267b0518fbSMårten Lindahl #define TPS6287X_CTRL2_VRANGE	GENMASK(3, 2)
277b0518fbSMårten Lindahl #define TPS6287X_CTRL3		0x03
287b0518fbSMårten Lindahl #define TPS6287X_STATUS		0x04
297b0518fbSMårten Lindahl 
307b0518fbSMårten Lindahl static const struct regmap_config tps6287x_regmap_config = {
317b0518fbSMårten Lindahl 	.reg_bits = 8,
327b0518fbSMårten Lindahl 	.val_bits = 8,
337b0518fbSMårten Lindahl 	.max_register = TPS6287X_STATUS,
347b0518fbSMårten Lindahl };
357b0518fbSMårten Lindahl 
367b0518fbSMårten Lindahl static const struct linear_range tps6287x_voltage_ranges[] = {
377b0518fbSMårten Lindahl 	LINEAR_RANGE(400000, 0, 0xFF, 1250),
387b0518fbSMårten Lindahl 	LINEAR_RANGE(400000, 0, 0xFF, 2500),
397b0518fbSMårten Lindahl 	LINEAR_RANGE(400000, 0, 0xFF, 5000),
407b0518fbSMårten Lindahl 	LINEAR_RANGE(800000, 0, 0xFF, 10000),
417b0518fbSMårten Lindahl };
427b0518fbSMårten Lindahl 
437b0518fbSMårten Lindahl static const unsigned int tps6287x_voltage_range_sel[] = {
44269cb04bSChen-Yu Tsai 	0x0, 0x1, 0x2, 0x3
457b0518fbSMårten Lindahl };
467b0518fbSMårten Lindahl 
477b0518fbSMårten Lindahl static const unsigned int tps6287x_ramp_table[] = {
487b0518fbSMårten Lindahl 	10000, 5000, 1250, 500
497b0518fbSMårten Lindahl };
507b0518fbSMårten Lindahl 
tps6287x_set_mode(struct regulator_dev * rdev,unsigned int mode)517b0518fbSMårten Lindahl static int tps6287x_set_mode(struct regulator_dev *rdev, unsigned int mode)
527b0518fbSMårten Lindahl {
537b0518fbSMårten Lindahl 	unsigned int val;
547b0518fbSMårten Lindahl 
557b0518fbSMårten Lindahl 	switch (mode) {
567b0518fbSMårten Lindahl 	case REGULATOR_MODE_NORMAL:
577b0518fbSMårten Lindahl 		val = 0;
587b0518fbSMårten Lindahl 		break;
597b0518fbSMårten Lindahl 	case REGULATOR_MODE_FAST:
607b0518fbSMårten Lindahl 		val = TPS6287X_CTRL1_FPWMEN;
617b0518fbSMårten Lindahl 		break;
627b0518fbSMårten Lindahl 	default:
637b0518fbSMårten Lindahl 		return -EINVAL;
647b0518fbSMårten Lindahl 	}
657b0518fbSMårten Lindahl 
667b0518fbSMårten Lindahl 	return regmap_update_bits(rdev->regmap, TPS6287X_CTRL1,
677b0518fbSMårten Lindahl 				  TPS6287X_CTRL1_FPWMEN, val);
687b0518fbSMårten Lindahl }
697b0518fbSMårten Lindahl 
tps6287x_get_mode(struct regulator_dev * rdev)707b0518fbSMårten Lindahl static unsigned int tps6287x_get_mode(struct regulator_dev *rdev)
717b0518fbSMårten Lindahl {
727b0518fbSMårten Lindahl 	unsigned int val;
737b0518fbSMårten Lindahl 	int ret;
747b0518fbSMårten Lindahl 
757b0518fbSMårten Lindahl 	ret = regmap_read(rdev->regmap, TPS6287X_CTRL1, &val);
767b0518fbSMårten Lindahl 	if (ret < 0)
777b0518fbSMårten Lindahl 		return 0;
787b0518fbSMårten Lindahl 
797b0518fbSMårten Lindahl 	return (val & TPS6287X_CTRL1_FPWMEN) ? REGULATOR_MODE_FAST :
807b0518fbSMårten Lindahl 	    REGULATOR_MODE_NORMAL;
817b0518fbSMårten Lindahl }
827b0518fbSMårten Lindahl 
tps6287x_of_map_mode(unsigned int mode)837b0518fbSMårten Lindahl static unsigned int tps6287x_of_map_mode(unsigned int mode)
847b0518fbSMårten Lindahl {
857b0518fbSMårten Lindahl 	switch (mode) {
867b0518fbSMårten Lindahl 	case REGULATOR_MODE_NORMAL:
877b0518fbSMårten Lindahl 	case REGULATOR_MODE_FAST:
887b0518fbSMårten Lindahl 		return mode;
897b0518fbSMårten Lindahl 	default:
907b0518fbSMårten Lindahl 		return REGULATOR_MODE_INVALID;
917b0518fbSMårten Lindahl 	}
927b0518fbSMårten Lindahl }
937b0518fbSMårten Lindahl 
947b0518fbSMårten Lindahl static const struct regulator_ops tps6287x_regulator_ops = {
957b0518fbSMårten Lindahl 	.enable = regulator_enable_regmap,
967b0518fbSMårten Lindahl 	.disable = regulator_disable_regmap,
977b0518fbSMårten Lindahl 	.set_mode = tps6287x_set_mode,
987b0518fbSMårten Lindahl 	.get_mode = tps6287x_get_mode,
997b0518fbSMårten Lindahl 	.is_enabled = regulator_is_enabled_regmap,
1007b0518fbSMårten Lindahl 	.get_voltage_sel = regulator_get_voltage_sel_pickable_regmap,
1017b0518fbSMårten Lindahl 	.set_voltage_sel = regulator_set_voltage_sel_pickable_regmap,
1027b0518fbSMårten Lindahl 	.list_voltage = regulator_list_voltage_pickable_linear_range,
1037b0518fbSMårten Lindahl 	.set_ramp_delay = regulator_set_ramp_delay_regmap,
1047b0518fbSMårten Lindahl };
1057b0518fbSMårten Lindahl 
1067b0518fbSMårten Lindahl static struct regulator_desc tps6287x_reg = {
1077b0518fbSMårten Lindahl 	.name = "tps6287x",
1087b0518fbSMårten Lindahl 	.owner = THIS_MODULE,
1097b0518fbSMårten Lindahl 	.ops = &tps6287x_regulator_ops,
1107b0518fbSMårten Lindahl 	.of_map_mode = tps6287x_of_map_mode,
1117b0518fbSMårten Lindahl 	.type = REGULATOR_VOLTAGE,
1127b0518fbSMårten Lindahl 	.enable_reg = TPS6287X_CTRL1,
1137b0518fbSMårten Lindahl 	.enable_mask = TPS6287X_CTRL1_SWEN,
1147b0518fbSMårten Lindahl 	.vsel_reg = TPS6287X_VSET,
1157b0518fbSMårten Lindahl 	.vsel_mask = 0xFF,
1167b0518fbSMårten Lindahl 	.vsel_range_reg = TPS6287X_CTRL2,
1177b0518fbSMårten Lindahl 	.vsel_range_mask = TPS6287X_CTRL2_VRANGE,
118*35db7c9dSMatti Vaittinen 	.range_applied_by_vsel = true,
1197b0518fbSMårten Lindahl 	.ramp_reg = TPS6287X_CTRL1,
1207b0518fbSMårten Lindahl 	.ramp_mask = TPS6287X_CTRL1_VRAMP,
1217b0518fbSMårten Lindahl 	.ramp_delay_table = tps6287x_ramp_table,
1227b0518fbSMårten Lindahl 	.n_ramp_values = ARRAY_SIZE(tps6287x_ramp_table),
123c6929055SVincent Whitchurch 	.n_voltages = 256 * ARRAY_SIZE(tps6287x_voltage_ranges),
1247b0518fbSMårten Lindahl 	.linear_ranges = tps6287x_voltage_ranges,
1257b0518fbSMårten Lindahl 	.n_linear_ranges = ARRAY_SIZE(tps6287x_voltage_ranges),
126269cb04bSChen-Yu Tsai 	.linear_range_selectors_bitfield = tps6287x_voltage_range_sel,
1277b0518fbSMårten Lindahl };
1287b0518fbSMårten Lindahl 
tps6287x_i2c_probe(struct i2c_client * i2c)1297b0518fbSMårten Lindahl static int tps6287x_i2c_probe(struct i2c_client *i2c)
1307b0518fbSMårten Lindahl {
1317b0518fbSMårten Lindahl 	struct device *dev = &i2c->dev;
1327b0518fbSMårten Lindahl 	struct regulator_config config = {};
1337b0518fbSMårten Lindahl 	struct regulator_dev *rdev;
1347b0518fbSMårten Lindahl 
1357b0518fbSMårten Lindahl 	config.regmap = devm_regmap_init_i2c(i2c, &tps6287x_regmap_config);
1367b0518fbSMårten Lindahl 	if (IS_ERR(config.regmap)) {
1377b0518fbSMårten Lindahl 		dev_err(dev, "Failed to init i2c\n");
1387b0518fbSMårten Lindahl 		return PTR_ERR(config.regmap);
1397b0518fbSMårten Lindahl 	}
1407b0518fbSMårten Lindahl 
1417b0518fbSMårten Lindahl 	config.dev = dev;
1427b0518fbSMårten Lindahl 	config.of_node = dev->of_node;
1437b0518fbSMårten Lindahl 	config.init_data = of_get_regulator_init_data(dev, dev->of_node,
1447b0518fbSMårten Lindahl 						      &tps6287x_reg);
1457b0518fbSMårten Lindahl 
1467b0518fbSMårten Lindahl 	rdev = devm_regulator_register(dev, &tps6287x_reg, &config);
1477b0518fbSMårten Lindahl 	if (IS_ERR(rdev)) {
1487b0518fbSMårten Lindahl 		dev_err(dev, "Failed to register regulator\n");
1497b0518fbSMårten Lindahl 		return PTR_ERR(rdev);
1507b0518fbSMårten Lindahl 	}
1517b0518fbSMårten Lindahl 
1527b0518fbSMårten Lindahl 	dev_dbg(dev, "Probed regulator\n");
1537b0518fbSMårten Lindahl 
1547b0518fbSMårten Lindahl 	return 0;
1557b0518fbSMårten Lindahl }
1567b0518fbSMårten Lindahl 
1577b0518fbSMårten Lindahl static const struct of_device_id tps6287x_dt_ids[] = {
1587b0518fbSMårten Lindahl 	{ .compatible = "ti,tps62870", },
1597b0518fbSMårten Lindahl 	{ .compatible = "ti,tps62871", },
1607b0518fbSMårten Lindahl 	{ .compatible = "ti,tps62872", },
1617b0518fbSMårten Lindahl 	{ .compatible = "ti,tps62873", },
1627b0518fbSMårten Lindahl 	{ }
1637b0518fbSMårten Lindahl };
1647b0518fbSMårten Lindahl 
1657b0518fbSMårten Lindahl MODULE_DEVICE_TABLE(of, tps6287x_dt_ids);
1667b0518fbSMårten Lindahl 
1677b0518fbSMårten Lindahl static const struct i2c_device_id tps6287x_i2c_id[] = {
1687b0518fbSMårten Lindahl 	{ "tps62870", 0 },
1697b0518fbSMårten Lindahl 	{ "tps62871", 0 },
1707b0518fbSMårten Lindahl 	{ "tps62872", 0 },
1717b0518fbSMårten Lindahl 	{ "tps62873", 0 },
1727b0518fbSMårten Lindahl 	{},
1737b0518fbSMårten Lindahl };
1747b0518fbSMårten Lindahl 
1757b0518fbSMårten Lindahl MODULE_DEVICE_TABLE(i2c, tps6287x_i2c_id);
1767b0518fbSMårten Lindahl 
1777b0518fbSMårten Lindahl static struct i2c_driver tps6287x_regulator_driver = {
1787b0518fbSMårten Lindahl 	.driver = {
1797b0518fbSMårten Lindahl 		.name = "tps6287x",
1807b0518fbSMårten Lindahl 		.of_match_table = tps6287x_dt_ids,
1817b0518fbSMårten Lindahl 	},
182d692cc61SUwe Kleine-König 	.probe = tps6287x_i2c_probe,
1837b0518fbSMårten Lindahl 	.id_table = tps6287x_i2c_id,
1847b0518fbSMårten Lindahl };
1857b0518fbSMårten Lindahl 
1867b0518fbSMårten Lindahl module_i2c_driver(tps6287x_regulator_driver);
1877b0518fbSMårten Lindahl 
1887b0518fbSMårten Lindahl MODULE_AUTHOR("Mårten Lindahl <marten.lindahl@axis.com>");
1897b0518fbSMårten Lindahl MODULE_DESCRIPTION("Regulator driver for TI TPS6287X PMIC");
1907b0518fbSMårten Lindahl MODULE_LICENSE("GPL");
191