1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2023 Axis Communications AB 4 * 5 * Driver for Texas Instruments TPS6287x PMIC. 6 * Datasheet: https://www.ti.com/lit/ds/symlink/tps62873.pdf 7 */ 8 9 #include <linux/err.h> 10 #include <linux/i2c.h> 11 #include <linux/mod_devicetable.h> 12 #include <linux/module.h> 13 #include <linux/regmap.h> 14 #include <linux/regulator/of_regulator.h> 15 #include <linux/regulator/machine.h> 16 #include <linux/regulator/driver.h> 17 #include <linux/bitfield.h> 18 #include <linux/linear_range.h> 19 20 #define TPS6287X_VSET 0x00 21 #define TPS6287X_CTRL1 0x01 22 #define TPS6287X_CTRL1_VRAMP GENMASK(1, 0) 23 #define TPS6287X_CTRL1_FPWMEN BIT(4) 24 #define TPS6287X_CTRL1_SWEN BIT(5) 25 #define TPS6287X_CTRL2 0x02 26 #define TPS6287X_CTRL2_VRANGE GENMASK(3, 2) 27 #define TPS6287X_CTRL3 0x03 28 #define TPS6287X_STATUS 0x04 29 30 static const struct regmap_config tps6287x_regmap_config = { 31 .reg_bits = 8, 32 .val_bits = 8, 33 .max_register = TPS6287X_STATUS, 34 }; 35 36 static const struct linear_range tps6287x_voltage_ranges[] = { 37 LINEAR_RANGE(400000, 0, 0xFF, 1250), 38 LINEAR_RANGE(400000, 0, 0xFF, 2500), 39 LINEAR_RANGE(400000, 0, 0xFF, 5000), 40 LINEAR_RANGE(800000, 0, 0xFF, 10000), 41 }; 42 43 static const unsigned int tps6287x_voltage_range_sel[] = { 44 0x0, 0x1, 0x2, 0x3 45 }; 46 47 static const unsigned int tps6287x_ramp_table[] = { 48 10000, 5000, 1250, 500 49 }; 50 51 static int tps6287x_set_mode(struct regulator_dev *rdev, unsigned int mode) 52 { 53 unsigned int val; 54 55 switch (mode) { 56 case REGULATOR_MODE_NORMAL: 57 val = 0; 58 break; 59 case REGULATOR_MODE_FAST: 60 val = TPS6287X_CTRL1_FPWMEN; 61 break; 62 default: 63 return -EINVAL; 64 } 65 66 return regmap_update_bits(rdev->regmap, TPS6287X_CTRL1, 67 TPS6287X_CTRL1_FPWMEN, val); 68 } 69 70 static unsigned int tps6287x_get_mode(struct regulator_dev *rdev) 71 { 72 unsigned int val; 73 int ret; 74 75 ret = regmap_read(rdev->regmap, TPS6287X_CTRL1, &val); 76 if (ret < 0) 77 return 0; 78 79 return (val & TPS6287X_CTRL1_FPWMEN) ? REGULATOR_MODE_FAST : 80 REGULATOR_MODE_NORMAL; 81 } 82 83 static unsigned int tps6287x_of_map_mode(unsigned int mode) 84 { 85 switch (mode) { 86 case REGULATOR_MODE_NORMAL: 87 case REGULATOR_MODE_FAST: 88 return mode; 89 default: 90 return REGULATOR_MODE_INVALID; 91 } 92 } 93 94 static const struct regulator_ops tps6287x_regulator_ops = { 95 .enable = regulator_enable_regmap, 96 .disable = regulator_disable_regmap, 97 .set_mode = tps6287x_set_mode, 98 .get_mode = tps6287x_get_mode, 99 .is_enabled = regulator_is_enabled_regmap, 100 .get_voltage_sel = regulator_get_voltage_sel_pickable_regmap, 101 .set_voltage_sel = regulator_set_voltage_sel_pickable_regmap, 102 .list_voltage = regulator_list_voltage_pickable_linear_range, 103 .set_ramp_delay = regulator_set_ramp_delay_regmap, 104 }; 105 106 static struct regulator_desc tps6287x_reg = { 107 .name = "tps6287x", 108 .owner = THIS_MODULE, 109 .ops = &tps6287x_regulator_ops, 110 .of_map_mode = tps6287x_of_map_mode, 111 .type = REGULATOR_VOLTAGE, 112 .enable_reg = TPS6287X_CTRL1, 113 .enable_mask = TPS6287X_CTRL1_SWEN, 114 .vsel_reg = TPS6287X_VSET, 115 .vsel_mask = 0xFF, 116 .vsel_range_reg = TPS6287X_CTRL2, 117 .vsel_range_mask = TPS6287X_CTRL2_VRANGE, 118 .ramp_reg = TPS6287X_CTRL1, 119 .ramp_mask = TPS6287X_CTRL1_VRAMP, 120 .ramp_delay_table = tps6287x_ramp_table, 121 .n_ramp_values = ARRAY_SIZE(tps6287x_ramp_table), 122 .n_voltages = 256, 123 .linear_ranges = tps6287x_voltage_ranges, 124 .n_linear_ranges = ARRAY_SIZE(tps6287x_voltage_ranges), 125 .linear_range_selectors_bitfield = tps6287x_voltage_range_sel, 126 }; 127 128 static int tps6287x_i2c_probe(struct i2c_client *i2c) 129 { 130 struct device *dev = &i2c->dev; 131 struct regulator_config config = {}; 132 struct regulator_dev *rdev; 133 134 config.regmap = devm_regmap_init_i2c(i2c, &tps6287x_regmap_config); 135 if (IS_ERR(config.regmap)) { 136 dev_err(dev, "Failed to init i2c\n"); 137 return PTR_ERR(config.regmap); 138 } 139 140 config.dev = dev; 141 config.of_node = dev->of_node; 142 config.init_data = of_get_regulator_init_data(dev, dev->of_node, 143 &tps6287x_reg); 144 145 rdev = devm_regulator_register(dev, &tps6287x_reg, &config); 146 if (IS_ERR(rdev)) { 147 dev_err(dev, "Failed to register regulator\n"); 148 return PTR_ERR(rdev); 149 } 150 151 dev_dbg(dev, "Probed regulator\n"); 152 153 return 0; 154 } 155 156 static const struct of_device_id tps6287x_dt_ids[] = { 157 { .compatible = "ti,tps62870", }, 158 { .compatible = "ti,tps62871", }, 159 { .compatible = "ti,tps62872", }, 160 { .compatible = "ti,tps62873", }, 161 { } 162 }; 163 164 MODULE_DEVICE_TABLE(of, tps6287x_dt_ids); 165 166 static const struct i2c_device_id tps6287x_i2c_id[] = { 167 { "tps62870", 0 }, 168 { "tps62871", 0 }, 169 { "tps62872", 0 }, 170 { "tps62873", 0 }, 171 {}, 172 }; 173 174 MODULE_DEVICE_TABLE(i2c, tps6287x_i2c_id); 175 176 static struct i2c_driver tps6287x_regulator_driver = { 177 .driver = { 178 .name = "tps6287x", 179 .of_match_table = tps6287x_dt_ids, 180 }, 181 .probe = tps6287x_i2c_probe, 182 .id_table = tps6287x_i2c_id, 183 }; 184 185 module_i2c_driver(tps6287x_regulator_driver); 186 187 MODULE_AUTHOR("Mårten Lindahl <marten.lindahl@axis.com>"); 188 MODULE_DESCRIPTION("Regulator driver for TI TPS6287X PMIC"); 189 MODULE_LICENSE("GPL"); 190