xref: /openbmc/linux/drivers/regulator/rt4803.c (revision 55b37d9c)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (C) 2023 Richtek Technology Corp.
4  *
5  * Author: ChiYuan Huang <cy_huang@richtek.com>
6  */
7 
8 #include <linux/i2c.h>
9 #include <linux/kernel.h>
10 #include <linux/mod_devicetable.h>
11 #include <linux/module.h>
12 #include <linux/property.h>
13 #include <linux/regmap.h>
14 #include <linux/regulator/driver.h>
15 #include <linux/regulator/of_regulator.h>
16 
17 #define RT4803_AUTO_MODE	1
18 #define RT4803_FPWM_MODE	2
19 
20 #define RT4803_REG_CONFIG	0x01
21 #define RT4803_REG_VSELL	0x02
22 #define RT4803_REG_VSELH	0x03
23 #define RT4803_REG_ILIM		0x04
24 #define RT4803_REG_STAT		0x05
25 
26 #define RT4803_MODE_MASK	GENMASK(1, 0)
27 #define RT4803_VSEL_MASK	GENMASK(4, 0)
28 #define RT4803_ILIM_MASK	GENMASK(3, 0)
29 #define RT4803_TSD_MASK		BIT(7)
30 #define RT4803_HOTDIE_MASK	BIT(6)
31 #define RT4803_FAULT_MASK	BIT(1)
32 #define RT4803_PGOOD_MASK	BIT(0)
33 
34 #define RT4803_VOUT_MINUV	2850000
35 #define RT4803_VOUT_STEPUV	50000
36 #define RT4803_VOUT_NUM		32
37 
38 static int rt4803_set_mode(struct regulator_dev *rdev, unsigned int mode)
39 {
40 	struct regmap *regmap = rdev_get_regmap(rdev);
41 	unsigned int modeval;
42 
43 	switch (mode) {
44 	case REGULATOR_MODE_NORMAL:
45 		modeval = RT4803_AUTO_MODE;
46 		break;
47 	case REGULATOR_MODE_FAST:
48 		modeval = RT4803_FPWM_MODE;
49 		break;
50 	default:
51 		return -EINVAL;
52 	}
53 
54 	modeval <<= ffs(RT4803_MODE_MASK) - 1;
55 
56 	return regmap_update_bits(regmap, RT4803_REG_CONFIG, RT4803_MODE_MASK, modeval);
57 }
58 
59 static unsigned int rt4803_get_mode(struct regulator_dev *rdev)
60 {
61 	struct regmap *regmap = rdev_get_regmap(rdev);
62 	unsigned int modeval;
63 	int ret;
64 
65 	ret = regmap_read(regmap, RT4803_REG_CONFIG, &modeval);
66 	if (ret)
67 		return REGULATOR_MODE_INVALID;
68 
69 	modeval >>= ffs(RT4803_MODE_MASK) - 1;
70 
71 	switch (modeval) {
72 	case RT4803_AUTO_MODE:
73 		return REGULATOR_MODE_NORMAL;
74 	case RT4803_FPWM_MODE:
75 		return REGULATOR_MODE_FAST;
76 	default:
77 		return REGULATOR_MODE_INVALID;
78 	}
79 }
80 
81 static int rt4803_get_error_flags(struct regulator_dev *rdev, unsigned int *flags)
82 {
83 	struct regmap *regmap = rdev_get_regmap(rdev);
84 	unsigned int state, events = 0;
85 	int ret;
86 
87 	ret = regmap_read(regmap, RT4803_REG_STAT, &state);
88 	if (ret)
89 		return ret;
90 
91 	if (state & RT4803_PGOOD_MASK)
92 		goto out_error_flag;
93 
94 	if (state & RT4803_FAULT_MASK)
95 		events |= REGULATOR_ERROR_FAIL;
96 
97 	if (state & RT4803_HOTDIE_MASK)
98 		events |= REGULATOR_ERROR_OVER_TEMP_WARN;
99 
100 	if (state & RT4803_TSD_MASK)
101 		events |= REGULATOR_ERROR_OVER_TEMP;
102 
103 out_error_flag:
104 	*flags = events;
105 	return 0;
106 }
107 
108 static int rt4803_set_suspend_voltage(struct regulator_dev *rdev, int uV)
109 {
110 	struct regmap *regmap = rdev_get_regmap(rdev);
111 	unsigned int reg, vsel;
112 
113 	if (rdev->desc->vsel_reg == RT4803_REG_VSELL)
114 		reg = RT4803_REG_VSELH;
115 	else
116 		reg = RT4803_REG_VSELL;
117 
118 	vsel = (uV - rdev->desc->min_uV) / rdev->desc->uV_step;
119 	vsel <<= ffs(RT4803_VSEL_MASK) - 1;
120 
121 	return regmap_update_bits(regmap, reg, RT4803_VSEL_MASK, vsel);
122 }
123 
124 static const struct regulator_ops rt4803_regulator_ops = {
125 	.list_voltage = regulator_list_voltage_linear,
126 	.set_voltage_sel = regulator_set_voltage_sel_regmap,
127 	.get_voltage_sel = regulator_get_voltage_sel_regmap,
128 	.set_mode = rt4803_set_mode,
129 	.get_mode = rt4803_get_mode,
130 	.get_error_flags = rt4803_get_error_flags,
131 	.set_suspend_voltage = rt4803_set_suspend_voltage,
132 };
133 
134 static unsigned int rt4803_of_map_mode(unsigned int mode)
135 {
136 	switch (mode) {
137 	case RT4803_AUTO_MODE:
138 		return REGULATOR_MODE_NORMAL;
139 	case RT4803_FPWM_MODE:
140 		return REGULATOR_MODE_FAST;
141 	default:
142 		return REGULATOR_MODE_INVALID;
143 	}
144 }
145 
146 static const struct regmap_config rt4803_regmap_config = {
147 	.reg_bits = 8,
148 	.val_bits = 8,
149 	.max_register = RT4803_REG_STAT,
150 };
151 
152 static int rt4803_probe(struct i2c_client *i2c)
153 {
154 	struct device *dev = &i2c->dev;
155 	struct regmap *regmap;
156 	struct regulator_desc *desc;
157 	struct regulator_config cfg = {};
158 	struct regulator_dev *rdev;
159 	bool vsel_act_high;
160 	int ret;
161 
162 	desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
163 	if (!desc)
164 		return -ENOMEM;
165 
166 	regmap = devm_regmap_init_i2c(i2c, &rt4803_regmap_config);
167 	if (IS_ERR(regmap))
168 		return dev_err_probe(dev, PTR_ERR(regmap), "Failed to init regmap\n");
169 
170 	/* Always configure the input current limit to max 5A at initial */
171 	ret = regmap_update_bits(regmap, RT4803_REG_ILIM, RT4803_ILIM_MASK, 0xff);
172 	if (ret)
173 		return dev_err_probe(dev, ret, "Failed to config ILIM to max\n");
174 
175 	vsel_act_high = device_property_read_bool(dev, "richtek,vsel-active-high");
176 
177 	desc->name = "rt4803-regulator";
178 	desc->type = REGULATOR_VOLTAGE;
179 	desc->owner = THIS_MODULE;
180 	desc->ops = &rt4803_regulator_ops;
181 	desc->min_uV = RT4803_VOUT_MINUV;
182 	desc->uV_step = RT4803_VOUT_STEPUV;
183 	desc->n_voltages = RT4803_VOUT_NUM;
184 	desc->vsel_mask = RT4803_VSEL_MASK;
185 	desc->of_map_mode = rt4803_of_map_mode;
186 	if (vsel_act_high)
187 		desc->vsel_reg = RT4803_REG_VSELH;
188 	else
189 		desc->vsel_reg = RT4803_REG_VSELL;
190 
191 	cfg.dev = dev;
192 	cfg.of_node = dev_of_node(dev);
193 	cfg.init_data = of_get_regulator_init_data(dev, dev_of_node(dev), desc);
194 
195 	rdev = devm_regulator_register(dev, desc, &cfg);
196 	return PTR_ERR_OR_ZERO(rdev);
197 }
198 
199 static const struct of_device_id rt4803_device_match_table[] = {
200 	{ .compatible = "richtek,rt4803" },
201 	{}
202 };
203 MODULE_DEVICE_TABLE(of, rt4803_device_match_table);
204 
205 static struct i2c_driver rt4803_driver = {
206 	.driver = {
207 		.name = "rt4803",
208 		.of_match_table = rt4803_device_match_table,
209 	},
210 	.probe = rt4803_probe,
211 };
212 module_i2c_driver(rt4803_driver);
213 
214 MODULE_DESCRIPTION("Richtek RT4803 voltage regulator driver");
215 MODULE_AUTHOR("ChiYuan Huang <cy_huang@richtek.com>");
216 MODULE_LICENSE("GPL");
217