File Index
Files and directories
Sign in
FILE

rt5739.c

File preview with syntax highlighting.

linux-6.19.14/drivers/regulator/rt5739.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Device driver for RT5739 regulator
  4 *
  5 * Copyright (C) 2023 Richtek Technology Corp.
  6 *
  7 * Author: ChiYuan Huang <cy_huang@richtek.com>
  8 */
  9
 10#include <linux/bits.h>
 11#include <linux/gpio/consumer.h>
 12#include <linux/i2c.h>
 13#include <linux/kernel.h>
 14#include <linux/mod_devicetable.h>
 15#include <linux/property.h>
 16#include <linux/regmap.h>
 17#include <linux/regulator/driver.h>
 18#include <linux/regulator/of_regulator.h>
 19
 20#define RT5739_AUTO_MODE	0
 21#define RT5739_FPWM_MODE	1
 22
 23#define RT5739_REG_NSEL0	0x00
 24#define RT5739_REG_NSEL1	0x01
 25#define RT5739_REG_CNTL1	0x02
 26#define RT5739_REG_ID1		0x03
 27#define RT5739_REG_ID2		0x04
 28#define RT5739_REG_MON		0x05
 29#define RT5739_REG_CNTL2	0x06
 30#define RT5739_REG_CNTL4	0x08
 31
 32#define RT5739_VSEL_MASK	GENMASK(7, 0)
 33#define RT5739_MODEVSEL1_MASK	BIT(1)
 34#define RT5739_MODEVSEL0_MASK	BIT(0)
 35#define RT5739_VID_MASK		GENMASK(7, 5)
 36#define RT5739_DID_MASK		GENMASK(3, 0)
 37#define RT5739_ACTD_MASK	BIT(7)
 38#define RT5739_ENVSEL1_MASK	BIT(1)
 39#define RT5739_ENVSEL0_MASK	BIT(0)
 40
 41#define RT5733_CHIPDIE_ID	0x1
 42#define RT5733_VOLT_MINUV	270000
 43#define RT5733_VOLT_MAXUV	1401250
 44#define RT5733_VOLT_STPUV	6250
 45#define RT5733_N_VOLTS		182
 46
 47#define RT5739_VOLT_MINUV	300000
 48#define RT5739_VOLT_MAXUV	1300000
 49#define RT5739_VOLT_STPUV	5000
 50#define RT5739_N_VOLTS		201
 51#define RT5739_I2CRDY_TIMEUS	1000
 52
 53static int rt5739_set_mode(struct regulator_dev *rdev, unsigned int mode)
 54{
 55	const struct regulator_desc *desc = rdev->desc;
 56	struct regmap *regmap = rdev_get_regmap(rdev);
 57	unsigned int mask, val;
 58
 59	if (desc->vsel_reg == RT5739_REG_NSEL0)
 60		mask = RT5739_MODEVSEL0_MASK;
 61	else
 62		mask = RT5739_MODEVSEL1_MASK;
 63
 64	switch (mode) {
 65	case REGULATOR_MODE_FAST:
 66		val = mask;
 67		break;
 68	case REGULATOR_MODE_NORMAL:
 69		val = 0;
 70		break;
 71	default:
 72		return -EINVAL;
 73	}
 74
 75	return regmap_update_bits(regmap, RT5739_REG_CNTL1, mask, val);
 76}
 77
 78static unsigned int rt5739_get_mode(struct regulator_dev *rdev)
 79{
 80	const struct regulator_desc *desc = rdev->desc;
 81	struct regmap *regmap = rdev_get_regmap(rdev);
 82	unsigned int mask, val;
 83	int ret;
 84
 85	if (desc->vsel_reg == RT5739_REG_NSEL0)
 86		mask = RT5739_MODEVSEL0_MASK;
 87	else
 88		mask = RT5739_MODEVSEL1_MASK;
 89
 90	ret = regmap_read(regmap, RT5739_REG_CNTL1, &val);
 91	if (ret)
 92		return REGULATOR_MODE_INVALID;
 93
 94	if (val & mask)
 95		return REGULATOR_MODE_FAST;
 96
 97	return REGULATOR_MODE_NORMAL;
 98}
 99
100static int rt5739_set_suspend_voltage(struct regulator_dev *rdev, int uV)
101{
102	const struct regulator_desc *desc = rdev->desc;
103	struct regmap *regmap = rdev_get_regmap(rdev);
104	unsigned int reg, vsel;
105	int max_uV;
106
107	max_uV = desc->min_uV + desc->uV_step * (desc->n_voltages - 1);
108
109	if (uV < desc->min_uV || uV > max_uV)
110		return -EINVAL;
111
112	if (desc->vsel_reg == RT5739_REG_NSEL0)
113		reg = RT5739_REG_NSEL1;
114	else
115		reg = RT5739_REG_NSEL0;
116
117	vsel = (uV - desc->min_uV) / desc->uV_step;
118	return regmap_write(regmap, reg, vsel);
119}
120
121static int rt5739_set_suspend_enable(struct regulator_dev *rdev)
122{
123	const struct regulator_desc *desc = rdev->desc;
124	struct regmap *regmap = rdev_get_regmap(rdev);
125	unsigned int mask;
126
127	if (desc->vsel_reg == RT5739_REG_NSEL0)
128		mask = RT5739_ENVSEL1_MASK;
129	else
130		mask = RT5739_ENVSEL0_MASK;
131
132	return regmap_update_bits(regmap, desc->enable_reg, mask, mask);
133}
134
135static int rt5739_set_suspend_disable(struct regulator_dev *rdev)
136{
137	const struct regulator_desc *desc = rdev->desc;
138	struct regmap *regmap = rdev_get_regmap(rdev);
139	unsigned int mask;
140
141	if (desc->vsel_reg == RT5739_REG_NSEL0)
142		mask = RT5739_ENVSEL1_MASK;
143	else
144		mask = RT5739_ENVSEL0_MASK;
145
146	return regmap_update_bits(regmap, desc->enable_reg, mask, 0);
147}
148
149static int rt5739_set_suspend_mode(struct regulator_dev *rdev,
150				   unsigned int mode)
151{
152	const struct regulator_desc *desc = rdev->desc;
153	struct regmap *regmap = rdev_get_regmap(rdev);
154	unsigned int mask, val;
155
156	if (desc->vsel_reg == RT5739_REG_NSEL0)
157		mask = RT5739_MODEVSEL1_MASK;
158	else
159		mask = RT5739_MODEVSEL0_MASK;
160
161	switch (mode) {
162	case REGULATOR_MODE_FAST:
163		val = mask;
164		break;
165	case REGULATOR_MODE_NORMAL:
166		val = 0;
167		break;
168	default:
169		return -EINVAL;
170	}
171
172	return regmap_update_bits(regmap, RT5739_REG_CNTL1, mask, val);
173}
174
175static const struct regulator_ops rt5739_regulator_ops = {
176	.list_voltage = regulator_list_voltage_linear,
177	.get_voltage_sel = regulator_get_voltage_sel_regmap,
178	.set_voltage_sel = regulator_set_voltage_sel_regmap,
179	.enable	= regulator_enable_regmap,
180	.disable = regulator_disable_regmap,
181	.is_enabled = regulator_is_enabled_regmap,
182	.set_active_discharge = regulator_set_active_discharge_regmap,
183	.set_mode = rt5739_set_mode,
184	.get_mode = rt5739_get_mode,
185	.set_suspend_voltage = rt5739_set_suspend_voltage,
186	.set_suspend_enable = rt5739_set_suspend_enable,
187	.set_suspend_disable = rt5739_set_suspend_disable,
188	.set_suspend_mode = rt5739_set_suspend_mode,
189};
190
191static unsigned int rt5739_of_map_mode(unsigned int mode)
192{
193	switch (mode) {
194	case RT5739_AUTO_MODE:
195		return REGULATOR_MODE_NORMAL;
196	case RT5739_FPWM_MODE:
197		return REGULATOR_MODE_FAST;
198	default:
199		return REGULATOR_MODE_INVALID;
200	}
201}
202
203static void rt5739_init_regulator_desc(struct regulator_desc *desc,
204				       bool vsel_active_high, u8 did)
205{
206	/* Fixed */
207	desc->name = "rt5739-regulator";
208	desc->owner = THIS_MODULE;
209	desc->ops = &rt5739_regulator_ops;
210	desc->vsel_mask = RT5739_VSEL_MASK;
211	desc->enable_reg = RT5739_REG_CNTL2;
212	desc->active_discharge_reg = RT5739_REG_CNTL1;
213	desc->active_discharge_mask = RT5739_ACTD_MASK;
214	desc->active_discharge_on = RT5739_ACTD_MASK;
215	desc->of_map_mode = rt5739_of_map_mode;
216
217	/* Assigned by vsel level */
218	if (vsel_active_high) {
219		desc->vsel_reg = RT5739_REG_NSEL1;
220		desc->enable_mask = RT5739_ENVSEL1_MASK;
221	} else {
222		desc->vsel_reg = RT5739_REG_NSEL0;
223		desc->enable_mask = RT5739_ENVSEL0_MASK;
224	}
225
226	/* Assigned by CHIPDIE ID */
227	switch (did) {
228	case RT5733_CHIPDIE_ID:
229		desc->n_voltages = RT5733_N_VOLTS;
230		desc->min_uV = RT5733_VOLT_MINUV;
231		desc->uV_step = RT5733_VOLT_STPUV;
232		break;
233	default:
234		desc->n_voltages = RT5739_N_VOLTS;
235		desc->min_uV = RT5739_VOLT_MINUV;
236		desc->uV_step = RT5739_VOLT_STPUV;
237		break;
238	}
239}
240
241static bool rt5739_volatile_reg(struct device *dev, unsigned int reg)
242{
243	return reg == RT5739_REG_MON;
244}
245
246static const struct regmap_config rt5739_regmap_config = {
247	.name = "rt5739",
248	.reg_bits = 8,
249	.val_bits = 8,
250	.max_register = RT5739_REG_CNTL4,
251	.cache_type = REGCACHE_MAPLE,
252	.volatile_reg = rt5739_volatile_reg,
253};
254
255static int rt5739_probe(struct i2c_client *i2c)
256{
257	struct device *dev = &i2c->dev;
258	struct regulator_desc *desc;
259	struct regmap *regmap;
260	struct gpio_desc *enable_gpio;
261	struct regulator_config cfg = {};
262	struct regulator_dev *rdev;
263	bool vsel_acth;
264	unsigned int vid;
265	int ret;
266
267	desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
268	if (!desc)
269		return -ENOMEM;
270
271	enable_gpio = devm_gpiod_get_optional(dev, "enable", GPIOD_OUT_HIGH);
272	if (IS_ERR(enable_gpio))
273		return dev_err_probe(dev, PTR_ERR(enable_gpio), "Failed to get 'enable' gpio\n");
274	else if (enable_gpio)
275		usleep_range(RT5739_I2CRDY_TIMEUS, RT5739_I2CRDY_TIMEUS + 1000);
276
277	regmap = devm_regmap_init_i2c(i2c, &rt5739_regmap_config);
278	if (IS_ERR(regmap))
279		return dev_err_probe(dev, PTR_ERR(regmap), "Failed to init regmap\n");
280
281	ret = regmap_read(regmap, RT5739_REG_ID1, &vid);
282	if (ret)
283		return dev_err_probe(dev, ret, "Failed to read VID\n");
284
285	/* RT5739: (VID & MASK) must be 0 */
286	if (vid & RT5739_VID_MASK)
287		return dev_err_probe(dev, -ENODEV, "Incorrect VID (0x%02x)\n", vid);
288
289	vsel_acth = device_property_read_bool(dev, "richtek,vsel-active-high");
290
291	rt5739_init_regulator_desc(desc, vsel_acth, vid & RT5739_DID_MASK);
292
293	cfg.dev = dev;
294	cfg.of_node = dev_of_node(dev);
295	cfg.init_data = of_get_regulator_init_data(dev, dev_of_node(dev), desc);
296	rdev = devm_regulator_register(dev, desc, &cfg);
297	if (IS_ERR(rdev))
298		return dev_err_probe(dev, PTR_ERR(rdev), "Failed to register regulator\n");
299
300	return 0;
301}
302
303static const struct of_device_id rt5739_device_table[] = {
304	{ .compatible = "richtek,rt5733" },
305	{ .compatible = "richtek,rt5739" },
306	{ /* sentinel */ }
307};
308MODULE_DEVICE_TABLE(of, rt5739_device_table);
309
310static struct i2c_driver rt5739_driver = {
311	.driver = {
312		.name = "rt5739",
313		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
314		.of_match_table = rt5739_device_table,
315	},
316	.probe = rt5739_probe,
317};
318module_i2c_driver(rt5739_driver);
319
320MODULE_AUTHOR("ChiYuan Huang <cy_huang@richtek.com>");
321MODULE_DESCRIPTION("Richtek RT5739 regulator driver");
322MODULE_LICENSE("GPL");
~/ Read-only file preview.