Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

regulator: Add support for TPS6286x

TI's TPS62864/TPS6286/TPS62868/TPS62869 are high-frequency synchronous
step-down converters controlled via I2C. There are differences in the
electrical characteristics and packaging between the variants, but the
register interfaces are identical.

Signed-off-by: Vincent Whitchurch <vincent.whitchurch@axis.com>
Link: https://lore.kernel.org/r/20220204155241.576342-3-vincent.whitchurch@axis.com
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Vincent Whitchurch and committed by
Mark Brown
e2a01b4e 2f04aa69

+169
+9
drivers/regulator/Kconfig
··· 1264 1264 high-frequency synchronous step down dc-dc converter optimized 1265 1265 for battery-powered portable applications. 1266 1266 1267 + config REGULATOR_TPS6286X 1268 + tristate "TI TPS6286x Power Regulator" 1269 + depends on I2C && OF 1270 + select REGMAP_I2C 1271 + help 1272 + This driver supports TPS6236x voltage regulator chips. These are 1273 + high-frequency synchronous step-down converters with an I2C 1274 + interface. 1275 + 1267 1276 config REGULATOR_TPS65023 1268 1277 tristate "TI TPS65023 Power regulators" 1269 1278 depends on I2C
+1
drivers/regulator/Makefile
··· 149 149 obj-$(CONFIG_REGULATOR_TI_ABB) += ti-abb-regulator.o 150 150 obj-$(CONFIG_REGULATOR_TPS6105X) += tps6105x-regulator.o 151 151 obj-$(CONFIG_REGULATOR_TPS62360) += tps62360-regulator.o 152 + obj-$(CONFIG_REGULATOR_TPS6286X) += tps6286x-regulator.o 152 153 obj-$(CONFIG_REGULATOR_TPS65023) += tps65023-regulator.o 153 154 obj-$(CONFIG_REGULATOR_TPS6507X) += tps6507x-regulator.o 154 155 obj-$(CONFIG_REGULATOR_TPS65086) += tps65086-regulator.o
+159
drivers/regulator/tps6286x-regulator.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + // Copyright Axis Communications AB 3 + 4 + #include <linux/err.h> 5 + #include <linux/i2c.h> 6 + #include <linux/module.h> 7 + #include <linux/of_device.h> 8 + #include <linux/regmap.h> 9 + #include <linux/regulator/of_regulator.h> 10 + #include <linux/regulator/machine.h> 11 + #include <linux/regulator/driver.h> 12 + 13 + #include <dt-bindings/regulator/ti,tps62864.h> 14 + 15 + #define TPS6286X_VOUT1 0x01 16 + #define TPS6286X_VOUT1_VO1_SET GENMASK(7, 0) 17 + 18 + #define TPS6286X_CONTROL 0x03 19 + #define TPS6286X_CONTROL_FPWM BIT(4) 20 + #define TPS6286X_CONTROL_SWEN BIT(5) 21 + 22 + #define TPS6286X_MIN_MV 400 23 + #define TPS6286X_MAX_MV 1675 24 + #define TPS6286X_STEP_MV 5 25 + 26 + static const struct regmap_config tps6286x_regmap_config = { 27 + .reg_bits = 8, 28 + .val_bits = 8, 29 + }; 30 + 31 + static int tps6286x_set_mode(struct regulator_dev *rdev, unsigned int mode) 32 + { 33 + unsigned int val; 34 + 35 + switch (mode) { 36 + case REGULATOR_MODE_NORMAL: 37 + val = 0; 38 + break; 39 + case REGULATOR_MODE_FAST: 40 + val = TPS6286X_CONTROL_FPWM; 41 + break; 42 + default: 43 + return -EINVAL; 44 + } 45 + 46 + return regmap_update_bits(rdev->regmap, TPS6286X_CONTROL, 47 + TPS6286X_CONTROL_FPWM, val); 48 + } 49 + 50 + static unsigned int tps6286x_get_mode(struct regulator_dev *rdev) 51 + { 52 + unsigned int val; 53 + int ret; 54 + 55 + ret = regmap_read(rdev->regmap, TPS6286X_CONTROL, &val); 56 + if (ret < 0) 57 + return 0; 58 + 59 + return (val & TPS6286X_CONTROL_FPWM) ? REGULATOR_MODE_FAST : REGULATOR_MODE_NORMAL; 60 + } 61 + 62 + static const struct regulator_ops tps6286x_regulator_ops = { 63 + .enable = regulator_enable_regmap, 64 + .disable = regulator_disable_regmap, 65 + .set_mode = tps6286x_set_mode, 66 + .get_mode = tps6286x_get_mode, 67 + .is_enabled = regulator_is_enabled_regmap, 68 + .set_voltage_sel = regulator_set_voltage_sel_regmap, 69 + .get_voltage_sel = regulator_get_voltage_sel_regmap, 70 + .list_voltage = regulator_list_voltage_linear, 71 + }; 72 + 73 + static unsigned int tps6286x_of_map_mode(unsigned int mode) 74 + { 75 + switch (mode) { 76 + case TPS62864_MODE_NORMAL: 77 + return REGULATOR_MODE_NORMAL; 78 + case TPS62864_MODE_FPWM: 79 + return REGULATOR_MODE_FAST; 80 + default: 81 + return REGULATOR_MODE_INVALID; 82 + } 83 + } 84 + 85 + static const struct regulator_desc tps6286x_reg = { 86 + .name = "tps6286x", 87 + .of_match = of_match_ptr("SW"), 88 + .owner = THIS_MODULE, 89 + .ops = &tps6286x_regulator_ops, 90 + .of_map_mode = tps6286x_of_map_mode, 91 + .regulators_node = of_match_ptr("regulators"), 92 + .type = REGULATOR_VOLTAGE, 93 + .n_voltages = ((TPS6286X_MAX_MV - TPS6286X_MIN_MV) / TPS6286X_STEP_MV) + 1, 94 + .min_uV = TPS6286X_MIN_MV * 1000, 95 + .uV_step = TPS6286X_STEP_MV * 1000, 96 + .vsel_reg = TPS6286X_VOUT1, 97 + .vsel_mask = TPS6286X_VOUT1_VO1_SET, 98 + .enable_reg = TPS6286X_CONTROL, 99 + .enable_mask = TPS6286X_CONTROL_SWEN, 100 + .ramp_delay = 1000, 101 + /* tDelay + tRamp, rounded up */ 102 + .enable_time = 3000, 103 + }; 104 + 105 + static const struct of_device_id tps6286x_dt_ids[] = { 106 + { .compatible = "ti,tps62864", }, 107 + { .compatible = "ti,tps62866", }, 108 + { .compatible = "ti,tps62868", }, 109 + { .compatible = "ti,tps62869", }, 110 + { } 111 + }; 112 + MODULE_DEVICE_TABLE(of, tps6286x_dt_ids); 113 + 114 + static int tps6286x_i2c_probe(struct i2c_client *i2c, 115 + const struct i2c_device_id *id) 116 + { 117 + struct device *dev = &i2c->dev; 118 + struct regulator_config config = {}; 119 + struct regulator_dev *rdev; 120 + struct regmap *regmap; 121 + 122 + regmap = devm_regmap_init_i2c(i2c, &tps6286x_regmap_config); 123 + if (IS_ERR(regmap)) 124 + return PTR_ERR(regmap); 125 + 126 + config.dev = &i2c->dev; 127 + config.of_node = dev->of_node; 128 + config.regmap = regmap; 129 + 130 + rdev = devm_regulator_register(&i2c->dev, &tps6286x_reg, &config); 131 + if (IS_ERR(rdev)) { 132 + dev_err(&i2c->dev, "Failed to register tps6286x regulator\n"); 133 + return PTR_ERR(rdev); 134 + } 135 + 136 + return 0; 137 + } 138 + 139 + static const struct i2c_device_id tps6286x_i2c_id[] = { 140 + { "tps62864", 0 }, 141 + { "tps62866", 0 }, 142 + { "tps62868", 0 }, 143 + { "tps62869", 0 }, 144 + {}, 145 + }; 146 + MODULE_DEVICE_TABLE(i2c, tps6286x_i2c_id); 147 + 148 + static struct i2c_driver tps6286x_regulator_driver = { 149 + .driver = { 150 + .name = "tps6286x", 151 + .of_match_table = of_match_ptr(tps6286x_dt_ids), 152 + }, 153 + .probe = tps6286x_i2c_probe, 154 + .id_table = tps6286x_i2c_id, 155 + }; 156 + 157 + module_i2c_driver(tps6286x_regulator_driver); 158 + 159 + MODULE_LICENSE("GPL v2");