brintos

brintos / linux-shallow public Read only

0
0
Text · 4.8 KiB · 97f5ce1 Raw
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