191 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (C) 2023 Axis Communications AB4 *5 * Driver for Texas Instruments TPS6287x PMIC.6 * Datasheet: https://www.ti.com/lit/ds/symlink/tps62873.pdf7 */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 0x0021#define TPS6287X_CTRL1 0x0122#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 0x0226#define TPS6287X_CTRL2_VRANGE GENMASK(3, 2)27#define TPS6287X_CTRL3 0x0328#define TPS6287X_STATUS 0x0429 30static const struct regmap_config tps6287x_regmap_config = {31 .reg_bits = 8,32 .val_bits = 8,33 .max_register = TPS6287X_STATUS,34};35 36static 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 43static const unsigned int tps6287x_voltage_range_sel[] = {44 0x0, 0x1, 0x2, 0x345};46 47static const unsigned int tps6287x_ramp_table[] = {48 10000, 5000, 1250, 50049};50 51static 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 70static 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 83static 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 94static 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 106static const 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 .range_applied_by_vsel = true,119 .ramp_reg = TPS6287X_CTRL1,120 .ramp_mask = TPS6287X_CTRL1_VRAMP,121 .ramp_delay_table = tps6287x_ramp_table,122 .n_ramp_values = ARRAY_SIZE(tps6287x_ramp_table),123 .n_voltages = 256 * ARRAY_SIZE(tps6287x_voltage_ranges),124 .linear_ranges = tps6287x_voltage_ranges,125 .n_linear_ranges = ARRAY_SIZE(tps6287x_voltage_ranges),126 .linear_range_selectors_bitfield = tps6287x_voltage_range_sel,127};128 129static int tps6287x_i2c_probe(struct i2c_client *i2c)130{131 struct device *dev = &i2c->dev;132 struct regulator_config config = {};133 struct regulator_dev *rdev;134 135 config.regmap = devm_regmap_init_i2c(i2c, &tps6287x_regmap_config);136 if (IS_ERR(config.regmap)) {137 dev_err(dev, "Failed to init i2c\n");138 return PTR_ERR(config.regmap);139 }140 141 config.dev = dev;142 config.of_node = dev->of_node;143 config.init_data = of_get_regulator_init_data(dev, dev->of_node,144 &tps6287x_reg);145 146 rdev = devm_regulator_register(dev, &tps6287x_reg, &config);147 if (IS_ERR(rdev)) {148 dev_err(dev, "Failed to register regulator\n");149 return PTR_ERR(rdev);150 }151 152 dev_dbg(dev, "Probed regulator\n");153 154 return 0;155}156 157static const struct of_device_id tps6287x_dt_ids[] = {158 { .compatible = "ti,tps62870", },159 { .compatible = "ti,tps62871", },160 { .compatible = "ti,tps62872", },161 { .compatible = "ti,tps62873", },162 { }163};164 165MODULE_DEVICE_TABLE(of, tps6287x_dt_ids);166 167static const struct i2c_device_id tps6287x_i2c_id[] = {168 { "tps62870" },169 { "tps62871" },170 { "tps62872" },171 { "tps62873" },172 {}173};174 175MODULE_DEVICE_TABLE(i2c, tps6287x_i2c_id);176 177static struct i2c_driver tps6287x_regulator_driver = {178 .driver = {179 .name = "tps6287x",180 .of_match_table = tps6287x_dt_ids,181 },182 .probe = tps6287x_i2c_probe,183 .id_table = tps6287x_i2c_id,184};185 186module_i2c_driver(tps6287x_regulator_driver);187 188MODULE_AUTHOR("Mårten Lindahl <marten.lindahl@axis.com>");189MODULE_DESCRIPTION("Regulator driver for TI TPS6287X PMIC");190MODULE_LICENSE("GPL");191