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

Configure Feed

Select the types of activity you want to include in your feed.

regulator: Add TPS65185 driver

Add a driver for the TPS65185 regulator. Implement handling of the various
gpio pins. Because the PWRUP (=enable) pin functionality can be achieved
by just using two bits instead, just ensure that it is set to a stable
value.
Implement the pair of symmetric LDOs as a single regulator because they
share a single voltage set register. As the VCOM regulator sits behind that
machinery, just define that one as a supply.
For simplicity, just add the temperature sensor (depending on external NTC)
directly.

There is a mechanism to measure some kick-back voltage during a defined EPD
operation, to calibrate the VCOM voltage setting and store that
non-volatile in the chip to be the power up default setup. That is not
implemented yet in the driver, but that also means that there is a
non-factory default value in these registers after power-up.

Tested-by: Josua Mayer <josua.mayer@jm0.eu>
Signed-off-by: Andreas Kemnade <andreas@kemnade.info>
Link: https://patch.msgid.link/20260102-tps65185-submit-v3-2-23bda35772f2@kemnade.info
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Andreas Kemnade and committed by
Mark Brown
b0fc1e77 da1456e4

+466
+11
drivers/regulator/Kconfig
··· 1690 1690 This driver supports TPS65132 single inductor - dual output 1691 1691 power supply specifically designed for display panels. 1692 1692 1693 + config REGULATOR_TPS65185 1694 + tristate "TI TPS65185 EPD regulator" 1695 + depends on I2C 1696 + select REGMAP_I2C 1697 + help 1698 + This driver supports the TPS65185 voltage regulator chip 1699 + which is used to provide power to Electronic Paper Displays 1700 + so it is found in E-Book readers. 1701 + If HWWON is enabled, it also provides temperature measurement. 1702 + 1703 + 1693 1704 config REGULATOR_TPS65217 1694 1705 tristate "TI TPS65217 Power regulators" 1695 1706 depends on MFD_TPS65217
+1
drivers/regulator/Makefile
··· 192 192 obj-$(CONFIG_REGULATOR_TPS6507X) += tps6507x-regulator.o 193 193 obj-$(CONFIG_REGULATOR_TPS65086) += tps65086-regulator.o 194 194 obj-$(CONFIG_REGULATOR_TPS65090) += tps65090-regulator.o 195 + obj-$(CONFIG_REGULATOR_TPS65185) += tps65185.o 195 196 obj-$(CONFIG_REGULATOR_TPS65217) += tps65217-regulator.o 196 197 obj-$(CONFIG_REGULATOR_TPS65218) += tps65218-regulator.o 197 198 obj-$(CONFIG_REGULATOR_TPS65219) += tps65219-regulator.o
+454
drivers/regulator/tps65185.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + // Copyright (C) 2025 Andreas Kemnade 3 + 4 + /* Datasheet: https://www.ti.com/lit/gpn/tps65185 */ 5 + 6 + #include <linux/cleanup.h> 7 + #include <linux/completion.h> 8 + #include <linux/gpio/consumer.h> 9 + #include <linux/i2c.h> 10 + #include <linux/module.h> 11 + #include <linux/mutex.h> 12 + #include <linux/hwmon.h> 13 + #include <linux/pm_runtime.h> 14 + #include <linux/property.h> 15 + #include <linux/regulator/consumer.h> 16 + #include <linux/regulator/driver.h> 17 + #include <linux/regulator/machine.h> 18 + #include <linux/regmap.h> 19 + 20 + #define TPS65185_REG_TMST_VALUE 0 21 + #define TPS65185_REG_ENABLE 1 22 + #define TPS65185_REG_VADJ 2 23 + #define TPS65185_REG_VCOM1 3 24 + #define TPS65185_REG_VCOM2 4 25 + #define TPS65185_REG_INT_EN1 5 26 + #define TPS65185_REG_INT_EN2 6 27 + #define TPS65185_REG_INT1 7 28 + #define TPS65185_REG_INT2 8 29 + #define TPS65185_REG_TMST1 0xd 30 + #define TPS65185_REG_TMST2 0xe 31 + #define TPS65185_REG_PG 0xf 32 + #define TPS65185_REG_REVID 0x10 33 + 34 + #define TPS65185_READ_THERM BIT(7) 35 + #define TPS65185_CONV_END BIT(5) 36 + 37 + #define TPS65185_ENABLE_ACTIVE BIT(7) 38 + #define TPS65185_ENABLE_STANDBY BIT(6) 39 + 40 + #define PGOOD_TIMEOUT_MSECS 200 41 + 42 + struct tps65185_data { 43 + struct device *dev; 44 + struct regmap *regmap; 45 + struct gpio_desc *pgood_gpio; 46 + struct gpio_desc *pwrup_gpio; 47 + struct gpio_desc *vcom_ctrl_gpio; 48 + struct gpio_desc *wakeup_gpio; 49 + struct completion pgood_completion; 50 + int pgood_irq; 51 + struct completion tmst_completion; 52 + }; 53 + 54 + static const struct hwmon_channel_info *tps65185_info[] = { 55 + HWMON_CHANNEL_INFO(chip, HWMON_C_REGISTER_TZ), 56 + HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT), 57 + NULL 58 + }; 59 + 60 + static int tps65185_hwmon_read(struct device *dev, enum hwmon_sensor_types type, 61 + u32 attr, int channel, long *temp) 62 + { 63 + struct tps65185_data *data = dev_get_drvdata(dev); 64 + unsigned int val; 65 + int ret; 66 + 67 + reinit_completion(&data->tmst_completion); 68 + /* start acquisition */ 69 + regmap_update_bits(data->regmap, TPS65185_REG_TMST1, 70 + TPS65185_READ_THERM, TPS65185_READ_THERM); 71 + wait_for_completion_timeout(&data->tmst_completion, 72 + msecs_to_jiffies(PGOOD_TIMEOUT_MSECS)); 73 + ret = regmap_read(data->regmap, TPS65185_REG_TMST1, &val); 74 + if (!(val & TPS65185_CONV_END)) 75 + return -ETIMEDOUT; 76 + 77 + ret = regmap_read(data->regmap, TPS65185_REG_TMST_VALUE, &val); 78 + if (ret) 79 + return ret; 80 + 81 + *temp = (s8)val * 1000; 82 + 83 + return 0; 84 + } 85 + 86 + static umode_t tps65185_hwmon_is_visible(const void *data, 87 + enum hwmon_sensor_types type, 88 + u32 attr, int channel) 89 + { 90 + return 0444; 91 + } 92 + 93 + static const struct hwmon_ops tps65185_hwmon_ops = { 94 + .is_visible = tps65185_hwmon_is_visible, 95 + .read = tps65185_hwmon_read, 96 + }; 97 + 98 + static const struct hwmon_chip_info tps65185_chip_info = { 99 + .ops = &tps65185_hwmon_ops, 100 + .info = tps65185_info, 101 + }; 102 + 103 + static bool tps65185_volatile_reg(struct device *dev, unsigned int reg) 104 + { 105 + switch (reg) { 106 + case TPS65185_REG_TMST_VALUE: 107 + case TPS65185_REG_ENABLE: 108 + case TPS65185_REG_VCOM2: 109 + case TPS65185_REG_INT1: 110 + case TPS65185_REG_INT2: 111 + case TPS65185_REG_TMST1: 112 + return true; 113 + default: 114 + return false; 115 + } 116 + } 117 + 118 + static const struct regmap_config regmap_config = { 119 + .reg_bits = 8, 120 + .val_bits = 8, 121 + .max_register = 0x10, 122 + .cache_type = REGCACHE_MAPLE, 123 + .volatile_reg = tps65185_volatile_reg, 124 + }; 125 + 126 + static const struct regulator_ops tps65185_v3p3ops = { 127 + .list_voltage = regulator_list_voltage_linear, 128 + .enable = regulator_enable_regmap, 129 + .disable = regulator_disable_regmap, 130 + .is_enabled = regulator_is_enabled_regmap, 131 + }; 132 + 133 + static int tps65185_check_powergood(struct regulator_dev *rdev) 134 + { 135 + struct tps65185_data *data = rdev_get_drvdata(rdev); 136 + 137 + return gpiod_get_value_cansleep(data->pgood_gpio); 138 + } 139 + 140 + static int tps65185_vposneg_get_voltage_sel(struct regulator_dev *rdev) 141 + { 142 + int ret; 143 + 144 + ret = regulator_get_voltage_sel_regmap(rdev); 145 + if (ret < 0) 146 + return ret; 147 + 148 + /* highest value is lowest voltage */ 149 + return 6 - ret; 150 + } 151 + 152 + static int tps65185_vposneg_set_voltage_sel(struct regulator_dev *rdev, unsigned int selector) 153 + { 154 + return regulator_set_voltage_sel_regmap(rdev, 6 - selector); 155 + } 156 + 157 + static irqreturn_t pgood_handler(int irq, void *dev_id) 158 + { 159 + struct tps65185_data *data = dev_id; 160 + 161 + complete(&data->pgood_completion); 162 + 163 + return IRQ_HANDLED; 164 + } 165 + 166 + static int tps65185_vposneg_enable(struct regulator_dev *rdev) 167 + { 168 + struct tps65185_data *data = rdev_get_drvdata(rdev); 169 + int ret; 170 + 171 + reinit_completion(&data->pgood_completion); 172 + if (data->pwrup_gpio) 173 + ret = gpiod_set_value_cansleep(data->pwrup_gpio, 1); 174 + else 175 + ret = regmap_update_bits(data->regmap, TPS65185_REG_ENABLE, 176 + TPS65185_ENABLE_ACTIVE, 177 + TPS65185_ENABLE_ACTIVE); 178 + 179 + if (ret) 180 + return ret; 181 + 182 + dev_dbg(data->dev, "turning on..."); 183 + wait_for_completion_timeout(&data->pgood_completion, 184 + msecs_to_jiffies(PGOOD_TIMEOUT_MSECS)); 185 + dev_dbg(data->dev, "turned on"); 186 + if (gpiod_get_value_cansleep(data->pgood_gpio) != 1) 187 + return -ETIMEDOUT; 188 + 189 + return 0; 190 + } 191 + 192 + static int tps65185_vposneg_disable(struct regulator_dev *rdev) 193 + { 194 + struct tps65185_data *data = rdev_get_drvdata(rdev); 195 + int ret; 196 + 197 + if (data->pwrup_gpio) 198 + ret = gpiod_set_value_cansleep(data->pwrup_gpio, 0); 199 + else 200 + ret = regmap_update_bits(data->regmap, TPS65185_REG_ENABLE, 201 + TPS65185_ENABLE_STANDBY, 202 + TPS65185_ENABLE_STANDBY); 203 + 204 + return ret; 205 + } 206 + 207 + static int tps65185_vcom_set_voltage_sel(struct regulator_dev *rdev, unsigned int selector) 208 + { 209 + struct tps65185_data *data = rdev_get_drvdata(rdev); 210 + int ret; 211 + 212 + ret = regmap_update_bits(data->regmap, TPS65185_REG_VCOM2, BIT(0), selector >> 8); 213 + if (ret < 0) 214 + return ret; 215 + 216 + return regmap_write(data->regmap, TPS65185_REG_VCOM1, selector & 0xFF); 217 + } 218 + 219 + static int tps65185_vcom_get_voltage_sel(struct regulator_dev *rdev) 220 + { 221 + struct tps65185_data *data = rdev_get_drvdata(rdev); 222 + int ret; 223 + unsigned int sel, sel2; 224 + 225 + ret = regmap_read(data->regmap, TPS65185_REG_VCOM1, &sel); 226 + if (ret < 0) 227 + return ret; 228 + 229 + ret = regmap_read(data->regmap, TPS65185_REG_VCOM2, &sel2); 230 + if (ret < 0) 231 + return ret; 232 + 233 + if (sel2 & BIT(0)) 234 + sel |= 0x100; 235 + 236 + return sel; 237 + } 238 + 239 + static const struct regulator_ops tps65185_vcom_ops = { 240 + .list_voltage = regulator_list_voltage_linear, 241 + .map_voltage = regulator_map_voltage_linear, 242 + .set_voltage_sel = tps65185_vcom_set_voltage_sel, 243 + .get_voltage_sel = tps65185_vcom_get_voltage_sel, 244 + }; 245 + 246 + static const struct regulator_ops tps65185_vposneg_ops = { 247 + .list_voltage = regulator_list_voltage_linear, 248 + .map_voltage = regulator_map_voltage_linear, 249 + .enable = tps65185_vposneg_enable, 250 + .disable = tps65185_vposneg_disable, 251 + .is_enabled = tps65185_check_powergood, 252 + .set_voltage_sel = tps65185_vposneg_set_voltage_sel, 253 + .get_voltage_sel = tps65185_vposneg_get_voltage_sel, 254 + }; 255 + 256 + static const struct regulator_desc regulators[] = { 257 + { 258 + .name = "v3p3", 259 + .of_match = of_match_ptr("v3p3"), 260 + .regulators_node = of_match_ptr("regulators"), 261 + .id = 0, 262 + .ops = &tps65185_v3p3ops, 263 + .type = REGULATOR_VOLTAGE, 264 + .owner = THIS_MODULE, 265 + .enable_reg = TPS65185_REG_ENABLE, 266 + .enable_mask = BIT(5), 267 + .n_voltages = 1, 268 + .min_uV = 3300000, 269 + }, 270 + { 271 + .name = "vposneg", 272 + .of_match = of_match_ptr("vposneg"), 273 + .regulators_node = of_match_ptr("regulators"), 274 + .id = 1, 275 + .ops = &tps65185_vposneg_ops, 276 + .type = REGULATOR_VOLTAGE, 277 + .owner = THIS_MODULE, 278 + .n_voltages = 4, 279 + .vsel_reg = TPS65185_REG_VADJ, 280 + .vsel_mask = 0x7, 281 + .min_uV = 14250000, 282 + .uV_step = 250000, 283 + } 284 + }; 285 + 286 + static const struct regulator_desc vcom_regulator_desc = { 287 + .name = "vcom", 288 + .of_match = of_match_ptr("vcom"), 289 + .regulators_node = of_match_ptr("regulators"), 290 + .supply_name = "vposneg", 291 + .id = 2, 292 + .ops = &tps65185_vcom_ops, 293 + .type = REGULATOR_VOLTAGE, 294 + .owner = THIS_MODULE, 295 + .n_voltages = 511, 296 + .min_uV = 0, 297 + .uV_step = 10000, 298 + }; 299 + 300 + static irqreturn_t tps65185_irq_thread(int irq, void *dev_id) 301 + { 302 + struct tps65185_data *data = dev_id; 303 + unsigned int int_status_1, int_status_2; 304 + int ret; 305 + 306 + /* read both status to have irq cleared */ 307 + ret = regmap_read(data->regmap, TPS65185_REG_INT1, &int_status_1); 308 + if (ret) 309 + return IRQ_NONE; 310 + 311 + ret = regmap_read(data->regmap, TPS65185_REG_INT2, &int_status_2); 312 + if (ret) 313 + return IRQ_NONE; 314 + 315 + if (int_status_2 & BIT(0)) 316 + complete(&data->tmst_completion); 317 + 318 + dev_dbg(data->dev, "irq status %02x %02x\n", int_status_1, int_status_2); 319 + 320 + if (int_status_1 || int_status_2) 321 + return IRQ_HANDLED; 322 + 323 + return IRQ_NONE; 324 + } 325 + 326 + static int tps65185_probe(struct i2c_client *client) 327 + { 328 + struct tps65185_data *data; 329 + struct regulator_config config = { }; 330 + struct regulator_dev *rdev; 331 + int ret = 0; 332 + int i; 333 + 334 + data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL); 335 + data->regmap = devm_regmap_init_i2c(client, &regmap_config); 336 + if (IS_ERR(data->regmap)) 337 + return dev_err_probe(&client->dev, PTR_ERR(data->regmap), 338 + "failed to allocate regmap!\n"); 339 + 340 + data->pgood_gpio = devm_gpiod_get(&client->dev, "pwr-good", GPIOD_IN); 341 + if (IS_ERR(data->pgood_gpio)) 342 + return dev_err_probe(&client->dev, 343 + PTR_ERR(data->pgood_gpio), 344 + "failed to get power good gpio\n"); 345 + 346 + data->pgood_irq = gpiod_to_irq(data->pgood_gpio); 347 + if (data->pgood_irq < 0) 348 + return data->pgood_irq; 349 + 350 + data->pwrup_gpio = devm_gpiod_get_optional(&client->dev, "enable", GPIOD_OUT_LOW); 351 + if (IS_ERR(data->pwrup_gpio)) 352 + return dev_err_probe(&client->dev, PTR_ERR(data->pwrup_gpio), 353 + "failed to get pwrup gpio\n"); 354 + 355 + data->wakeup_gpio = devm_gpiod_get_optional(&client->dev, "wakeup", GPIOD_OUT_HIGH); 356 + if (IS_ERR(data->wakeup_gpio)) 357 + return dev_err_probe(&client->dev, 358 + PTR_ERR(data->wakeup_gpio), 359 + "failed to get wakeup gpio\n"); 360 + 361 + data->vcom_ctrl_gpio = devm_gpiod_get_optional(&client->dev, "vcom-ctrl", GPIOD_OUT_LOW); 362 + if (IS_ERR(data->vcom_ctrl_gpio)) 363 + return dev_err_probe(&client->dev, 364 + PTR_ERR(data->vcom_ctrl_gpio), 365 + "failed to get vcm ctrl gpio\n"); 366 + 367 + ret = devm_regulator_get_enable(&client->dev, "vin"); 368 + if (ret) 369 + return dev_err_probe(&client->dev, ret, 370 + "failed to get vin regulator\n"); 371 + 372 + data->dev = &client->dev; 373 + i2c_set_clientdata(client, data); 374 + 375 + init_completion(&data->pgood_completion); 376 + init_completion(&data->tmst_completion); 377 + 378 + ret = devm_request_threaded_irq(&client->dev, data->pgood_irq, NULL, 379 + pgood_handler, 380 + IRQF_TRIGGER_RISING | IRQF_ONESHOT, 381 + "PGOOD", data); 382 + if (ret) 383 + return dev_err_probe(&client->dev, ret, 384 + "failed to request power good irq\n"); 385 + 386 + if (client->irq) { 387 + ret = devm_request_threaded_irq(&client->dev, client->irq, 388 + NULL, tps65185_irq_thread, 389 + IRQF_TRIGGER_LOW | IRQF_ONESHOT, 390 + "tps65185", data); 391 + if (ret) 392 + return dev_err_probe(&client->dev, ret, 393 + "failed to request irq\n"); 394 + } 395 + 396 + ret = regmap_update_bits(data->regmap, TPS65185_REG_INT_EN2, BIT(0), BIT(0)); 397 + if (ret) 398 + return dev_err_probe(&client->dev, ret, 399 + "failed to enable temp irq\n"); 400 + 401 + config.driver_data = data; 402 + config.dev = &client->dev; 403 + config.regmap = data->regmap; 404 + 405 + for (i = 0; i < ARRAY_SIZE(regulators); i++) { 406 + rdev = devm_regulator_register(&client->dev, &regulators[i], 407 + &config); 408 + if (IS_ERR(rdev)) 409 + return dev_err_probe(&client->dev, PTR_ERR(rdev), 410 + "failed to register %s regulator\n", 411 + regulators[i].name); 412 + } 413 + 414 + config.ena_gpiod = data->vcom_ctrl_gpio; 415 + rdev = devm_regulator_register(&client->dev, &vcom_regulator_desc, &config); 416 + if (IS_ERR(rdev)) 417 + return dev_err_probe(&client->dev, PTR_ERR(rdev), 418 + "failed to register vcom regulator\n"); 419 + 420 + if (IS_REACHABLE(CONFIG_HWMON)) { 421 + struct device *hwmon_dev; 422 + 423 + hwmon_dev = devm_hwmon_device_register_with_info(&client->dev, "tps65185", data, 424 + &tps65185_chip_info, NULL); 425 + if (IS_ERR(hwmon_dev)) 426 + dev_notice(&client->dev, "failed to register hwmon\n"); 427 + } 428 + 429 + return 0; 430 + } 431 + 432 + static const struct of_device_id tps65185_dt_ids[] = { 433 + { 434 + .compatible = "ti,tps65185", 435 + }, { 436 + /* sentinel */ 437 + } 438 + }; 439 + MODULE_DEVICE_TABLE(of, tps65185_dt_ids); 440 + 441 + static struct i2c_driver tps65185_i2c_driver = { 442 + .driver = { 443 + .name = "tps65185", 444 + .of_match_table = tps65185_dt_ids, 445 + }, 446 + .probe = tps65185_probe, 447 + }; 448 + 449 + module_i2c_driver(tps65185_i2c_driver); 450 + 451 + /* Module information */ 452 + MODULE_DESCRIPTION("TPS65185 regulator driver"); 453 + MODULE_LICENSE("GPL"); 454 +