Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1// SPDX-License-Identifier: GPL-2.0+
2//
3// Copyright (c) 2025 Richtek Technology Corp.
4//
5// Author: ChiYuan Huang <cy_huang@richtek.com>
6
7#include <linux/bitfield.h>
8#include <linux/bits.h>
9#include <linux/gpio/consumer.h>
10#include <linux/i2c.h>
11#include <linux/mod_devicetable.h>
12#include <linux/module.h>
13#include <linux/property.h>
14#include <linux/regmap.h>
15#include <linux/regulator/consumer.h>
16#include <linux/regulator/driver.h>
17#include <linux/regulator/of_regulator.h>
18
19#define RT8092_REG_MNTRPT 0x00
20#define RT8092_REG_VOUTH 0x10
21#define RT8092_REG_VOUTL 0x11
22#define RT8092_REG_PWMMODE 0x14
23#define RT8092_REG_EVENT 0x18
24#define RT8092_REG_VBANKH 0x1C
25#define RT8092_REG_VBANKL 0x1D
26#define RT8092_REG_VBOUND 0x1E
27
28#define RT8092_TSDEVT_MASK BIT(7)
29#define RT8092_PGEVT_MASK BIT(0)
30#define RT8092_VSEL_MASK GENMASK(6, 0)
31#define RT8092_VOUTEN_MASK BIT(7)
32#define RT8092_FPWML_MASK BIT(7)
33#define RT8092_FPWMH_MASK BIT(6)
34#define RT8092_OCPEVT_MASK BIT(7)
35#define RT8092_SCPEVT_MASK BIT(4)
36#define RT8092_VINUVEVT_MASK BIT(1)
37#define RT8092_VBANK_MASK GENMASK(1, 0)
38
39#define RT8092_MODE_AUTO 0
40#define RT8092_MODE_FPWM 1
41#define RT8092_VOUT_BASEUV 303125
42#define RT8092_VOUT_STEPUV 3125
43#define RT8092_VOUT_MINSEL 15
44#define RT8092_NUM_VOLTS 128
45#define RT8092_INITSS_US 400
46
47static int rt8092_get_vbank_index(struct regmap *regmap, bool vsel_high, unsigned int *vbank_idx)
48{
49 unsigned int vbank_reg = vsel_high ? RT8092_REG_VBANKH : RT8092_REG_VBANKL;
50 unsigned int index;
51 int ret;
52
53 ret = regmap_read(regmap, vbank_reg, &index);
54 if (ret)
55 return ret;
56
57 *vbank_idx = FIELD_GET(RT8092_VBANK_MASK, index);
58 return 0;
59}
60
61static int rt8092_set_operating_mode(struct regulator_dev *rdev, unsigned int mode)
62{
63 const struct regulator_desc *desc = rdev->desc;
64 struct regmap *regmap = rdev_get_regmap(rdev);
65 unsigned int mode_mask, mode_val;
66
67 mode_mask = desc->vsel_reg == RT8092_REG_VOUTH ? RT8092_FPWMH_MASK : RT8092_FPWML_MASK;
68
69 switch (mode) {
70 case REGULATOR_MODE_FAST:
71 mode_val = mode_mask;
72 break;
73 case REGULATOR_MODE_NORMAL:
74 mode_val = 0;
75 break;
76 default:
77 return -EINVAL;
78 }
79
80 return regmap_update_bits(regmap, RT8092_REG_PWMMODE, mode_mask, mode_val);
81}
82
83static unsigned int rt8092_get_operating_mode(struct regulator_dev *rdev)
84{
85 const struct regulator_desc *desc = rdev->desc;
86 struct regmap *regmap = rdev_get_regmap(rdev);
87 unsigned int mode_mask, mode_val;
88 int ret;
89
90 mode_mask = desc->vsel_reg == RT8092_REG_VOUTH ? RT8092_FPWMH_MASK : RT8092_FPWML_MASK;
91
92 ret = regmap_read(regmap, RT8092_REG_PWMMODE, &mode_val);
93 if (ret)
94 return REGULATOR_MODE_INVALID;
95
96 return mode_val & mode_mask ? REGULATOR_MODE_FAST : REGULATOR_MODE_NORMAL;
97}
98
99static int rt8092_get_error_flags(struct regulator_dev *rdev, unsigned int *flags)
100{
101 struct regmap *regmap = rdev_get_regmap(rdev);
102 unsigned int mntrpt, evtrpt, events = 0;
103 int ret;
104
105 ret = regmap_read(regmap, RT8092_REG_MNTRPT, &mntrpt);
106 if (ret)
107 return ret;
108
109 ret = regmap_read(regmap, RT8092_REG_EVENT, &evtrpt);
110 if (ret)
111 return ret;
112
113 if (!(mntrpt & RT8092_PGEVT_MASK) || evtrpt & RT8092_VINUVEVT_MASK)
114 events |= REGULATOR_ERROR_UNDER_VOLTAGE;
115
116 if (mntrpt & RT8092_TSDEVT_MASK)
117 events |= REGULATOR_ERROR_OVER_TEMP;
118
119 if (evtrpt & RT8092_OCPEVT_MASK)
120 events |= REGULATOR_ERROR_OVER_CURRENT;
121
122 if (evtrpt & RT8092_SCPEVT_MASK)
123 events |= REGULATOR_ERROR_FAIL;
124
125 *flags = events;
126 return 0;
127}
128
129
130static int rt8092_set_suspend_voltage(struct regulator_dev *rdev, int uV)
131{
132 const struct regulator_desc *desc = rdev->desc;
133 struct regmap *regmap = rdev_get_regmap(rdev);
134 unsigned int vsel_reg, vsel_val, vbank_idx;
135 bool vsel_high;
136 int ret;
137
138 vsel_reg = desc->vsel_reg == RT8092_REG_VOUTH ? RT8092_REG_VOUTL : RT8092_REG_VOUTH;
139 vsel_high = desc->vsel_reg == RT8092_REG_VOUTH;
140
141 ret = rt8092_get_vbank_index(regmap, vsel_high, &vbank_idx);
142 if (ret)
143 return ret;
144
145 /* VOUT = (BASEUV + STEPUV * VSEL) * 2^vbank_idx */
146 uV >>= vbank_idx;
147 if (uV < RT8092_VOUT_BASEUV)
148 return -EINVAL;
149
150 vsel_val = (uV - RT8092_VOUT_BASEUV) / RT8092_VOUT_STEPUV;
151 if (vsel_val < RT8092_VOUT_MINSEL || vsel_val >= RT8092_NUM_VOLTS)
152 return -EINVAL;
153
154 return regmap_update_bits(regmap, vsel_reg, RT8092_VSEL_MASK, vsel_val);
155}
156
157static int rt8092_set_suspend_enable(struct regulator_dev *rdev)
158{
159 const struct regulator_desc *desc = rdev->desc;
160 struct regmap *regmap = rdev_get_regmap(rdev);
161 unsigned int enable_reg;
162
163 enable_reg = desc->vsel_reg == RT8092_REG_VOUTH ? RT8092_REG_VOUTL : RT8092_REG_VOUTH;
164 return regmap_set_bits(regmap, enable_reg, RT8092_VOUTEN_MASK);
165}
166
167static int rt8092_set_suspend_disable(struct regulator_dev *rdev)
168{
169 const struct regulator_desc *desc = rdev->desc;
170 struct regmap *regmap = rdev_get_regmap(rdev);
171 unsigned int enable_reg;
172
173 enable_reg = desc->vsel_reg == RT8092_REG_VOUTH ? RT8092_REG_VOUTL : RT8092_REG_VOUTH;
174 return regmap_clear_bits(regmap, enable_reg, RT8092_VOUTEN_MASK);
175}
176
177static int rt8092_set_suspend_mode(struct regulator_dev *rdev, unsigned int mode)
178{
179 const struct regulator_desc *desc = rdev->desc;
180 struct regmap *regmap = rdev_get_regmap(rdev);
181 unsigned int mode_mask, mode_val;
182
183 mode_mask = desc->vsel_reg == RT8092_REG_VOUTH ? RT8092_FPWML_MASK : RT8092_FPWMH_MASK;
184
185 switch (mode) {
186 case REGULATOR_MODE_FAST:
187 mode_val = mode_mask;
188 break;
189 case REGULATOR_MODE_NORMAL:
190 mode_val = 0;
191 break;
192 default:
193 return -EINVAL;
194 }
195
196 return regmap_update_bits(regmap, RT8092_REG_PWMMODE, mode_mask, mode_val);
197}
198
199static const struct regulator_ops rt8092_regulator_ops = {
200 .list_voltage = regulator_list_voltage_linear,
201 .get_voltage_sel = regulator_get_voltage_sel_regmap,
202 .set_voltage_sel = regulator_set_voltage_sel_regmap,
203 .enable = regulator_enable_regmap,
204 .disable = regulator_disable_regmap,
205 .is_enabled = regulator_is_enabled_regmap,
206 .set_mode = rt8092_set_operating_mode,
207 .get_mode = rt8092_get_operating_mode,
208 .get_error_flags = rt8092_get_error_flags,
209 .set_suspend_voltage = rt8092_set_suspend_voltage,
210 .set_suspend_enable = rt8092_set_suspend_enable,
211 .set_suspend_disable = rt8092_set_suspend_disable,
212 .set_suspend_mode = rt8092_set_suspend_mode,
213};
214
215static unsigned int rt8092_of_map_mode(unsigned int mode)
216{
217 switch (mode) {
218 case RT8092_MODE_AUTO:
219 return REGULATOR_MODE_NORMAL;
220 case RT8092_MODE_FPWM:
221 return REGULATOR_MODE_FAST;
222 default:
223 return REGULATOR_MODE_INVALID;
224 }
225}
226
227static const struct regmap_config rt8092_regmap_cfg = {
228 .name = "rt8092",
229 .reg_bits = 8,
230 .val_bits = 8,
231 .max_register = RT8092_REG_VBOUND,
232};
233
234static int rt8092_probe(struct i2c_client *i2c)
235{
236 unsigned int vbank_idx, min_uV, step_uV;
237 struct regulator_config cfg = {};
238 struct device *dev = &i2c->dev;
239 struct regulator_desc *desc;
240 struct regulator_dev *rdev;
241 struct gpio_desc *enable;
242 struct regmap *regmap;
243 bool vsel_high;
244 int ret;
245
246 desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
247 if (!desc)
248 return -ENOMEM;
249
250 enable = devm_gpiod_get_optional(dev, "enable", GPIOD_OUT_HIGH);
251 if (IS_ERR(enable))
252 return dev_err_probe(dev, PTR_ERR(enable), "Failed get 'enable' gpio\n");
253
254 regmap = devm_regmap_init_i2c(i2c, &rt8092_regmap_cfg);
255 if (IS_ERR(regmap))
256 return dev_err_probe(dev, PTR_ERR(regmap), "Failed to init regmap\n");
257
258 vsel_high = device_property_read_bool(dev, "richtek,vsel-active-high");
259
260 ret = rt8092_get_vbank_index(regmap, vsel_high, &vbank_idx);
261 if (ret)
262 return dev_err_probe(dev, ret, "Failed to get VOUT bank index\n");
263
264 /*
265 * step VOUT = STEP_UV * 2^vbank_idx
266 * min VOUT = (BASEUV + STEPUV * VMIN_SEL) * 2^vbank_idx
267 */
268 step_uV = RT8092_VOUT_STEPUV << vbank_idx;
269 min_uV = (RT8092_VOUT_BASEUV + RT8092_VOUT_STEPUV * RT8092_VOUT_MINSEL) << vbank_idx;
270
271 desc->name = "rt8092";
272 desc->owner = THIS_MODULE;
273 desc->type = REGULATOR_VOLTAGE;
274 desc->ops = &rt8092_regulator_ops;
275 desc->n_voltages = RT8092_NUM_VOLTS;
276 desc->min_uV = min_uV;
277 desc->uV_step = step_uV;
278 desc->linear_min_sel = RT8092_VOUT_MINSEL;
279 desc->enable_reg = desc->vsel_reg = vsel_high ? RT8092_REG_VOUTH : RT8092_REG_VOUTL;
280 desc->vsel_mask = RT8092_VSEL_MASK;
281 desc->enable_mask = RT8092_VOUTEN_MASK;
282 desc->enable_time = RT8092_INITSS_US;
283 desc->of_map_mode = rt8092_of_map_mode;
284
285 cfg.dev = dev;
286 cfg.of_node = dev_of_node(dev);
287 cfg.init_data = of_get_regulator_init_data(dev, dev_of_node(dev), desc);
288
289 rdev = devm_regulator_register(dev, desc, &cfg);
290 if (IS_ERR(rdev))
291 return dev_err_probe(dev, PTR_ERR(rdev), "Failed to register regulator\n");
292
293 return 0;
294}
295
296static const struct of_device_id rt8092_device_tables[] = {
297 { .compatible = "richtek,rt8092" },
298 {}
299};
300MODULE_DEVICE_TABLE(of, rt8092_device_tables);
301
302static struct i2c_driver rt8092_driver = {
303 .driver = {
304 .name = "rt8092",
305 .of_match_table = rt8092_device_tables,
306 },
307 .probe = rt8092_probe,
308};
309module_i2c_driver(rt8092_driver);
310
311MODULE_AUTHOR("ChiYuan Huang <cy_huang@richtek.com>");
312MODULE_DESCRIPTION("Richtek RT8092 Regulator Driver");
313MODULE_LICENSE("GPL");