Commit | Line | Data |
---|---|---|
0555d414 CH |
1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | ||
3 | #include <linux/bitops.h> | |
4 | #include <linux/i2c.h> | |
5 | #include <linux/kernel.h> | |
6 | #include <linux/module.h> | |
7 | #include <linux/of.h> | |
8 | #include <linux/regmap.h> | |
9 | #include <linux/regulator/driver.h> | |
10 | ||
11 | enum { | |
12 | RTQ2134_IDX_BUCK1 = 0, | |
13 | RTQ2134_IDX_BUCK2, | |
14 | RTQ2134_IDX_BUCK3, | |
15 | RTQ2134_IDX_MAX | |
16 | }; | |
17 | ||
18 | #define RTQ2134_AUTO_MODE 0 | |
19 | #define RTQ2134_FCCM_MODE 1 | |
20 | ||
21 | #define RTQ2134_BUCK_DVS0_CTRL 0 | |
22 | #define RTQ2134_BUCK_VSEL_CTRL 2 | |
23 | ||
24 | #define RTQ2134_REG_IO_CHIPNAME 0x01 | |
25 | #define RTQ2134_REG_FLT_RECORDTEMP 0x13 | |
26 | #define RTQ2134_REG_FLT_RECORDBUCK(_id) (0x14 + (_id)) | |
27 | #define RTQ2134_REG_FLT_BUCKCTRL(_id) (0x37 + (_id)) | |
28 | #define RTQ2134_REG_BUCK1_CFG0 0x42 | |
29 | #define RTQ2134_REG_BUCK1_DVS0CFG1 0x48 | |
30 | #define RTQ2134_REG_BUCK1_DVS0CFG0 0x49 | |
31 | #define RTQ2134_REG_BUCK1_DVS1CFG1 0x4A | |
32 | #define RTQ2134_REG_BUCK1_DVS1CFG0 0x4B | |
33 | #define RTQ2134_REG_BUCK1_DVSCFG 0x52 | |
34 | #define RTQ2134_REG_BUCK1_RSPCFG 0x54 | |
35 | #define RTQ2134_REG_BUCK2_CFG0 0x5F | |
36 | #define RTQ2134_REG_BUCK2_DVS0CFG1 0x62 | |
37 | #define RTQ2134_REG_BUCK2_DVS0CFG0 0x63 | |
38 | #define RTQ2134_REG_BUCK2_DVS1CFG1 0x64 | |
39 | #define RTQ2134_REG_BUCK2_DVS1CFG0 0x65 | |
40 | #define RTQ2134_REG_BUCK2_DVSCFG 0x6C | |
41 | #define RTQ2134_REG_BUCK2_RSPCFG 0x6E | |
42 | #define RTQ2134_REG_BUCK3_CFG0 0x79 | |
43 | #define RTQ2134_REG_BUCK3_DVS0CFG1 0x7C | |
44 | #define RTQ2134_REG_BUCK3_DVS0CFG0 0x7D | |
45 | #define RTQ2134_REG_BUCK3_DVS1CFG1 0x7E | |
46 | #define RTQ2134_REG_BUCK3_DVS1CFG0 0x7F | |
47 | #define RTQ2134_REG_BUCK3_DVSCFG 0x86 | |
48 | #define RTQ2134_REG_BUCK3_RSPCFG 0x88 | |
49 | #define RTQ2134_REG_BUCK3_SLEWCTRL 0x89 | |
50 | ||
51 | #define RTQ2134_VOUT_MAXNUM 256 | |
52 | #define RTQ2134_VOUT_MASK 0xFF | |
53 | #define RTQ2134_VOUTEN_MASK BIT(0) | |
54 | #define RTQ2134_ACTDISCHG_MASK BIT(0) | |
55 | #define RTQ2134_RSPUP_MASK GENMASK(6, 4) | |
56 | #define RTQ2134_FCCM_MASK BIT(5) | |
57 | #define RTQ2134_UVHICCUP_MASK BIT(3) | |
58 | #define RTQ2134_BUCKDVS_CTRL_MASK GENMASK(1, 0) | |
59 | #define RTQ2134_CHIPOT_MASK BIT(2) | |
60 | #define RTQ2134_BUCKOV_MASK BIT(5) | |
61 | #define RTQ2134_BUCKUV_MASK BIT(4) | |
62 | ||
63 | struct rtq2134_regulator_desc { | |
64 | struct regulator_desc desc; | |
65 | /* Extension for proprietary register and mask */ | |
66 | unsigned int mode_reg; | |
67 | unsigned int mode_mask; | |
68 | unsigned int suspend_enable_reg; | |
69 | unsigned int suspend_enable_mask; | |
70 | unsigned int suspend_vsel_reg; | |
71 | unsigned int suspend_vsel_mask; | |
72 | unsigned int suspend_mode_reg; | |
73 | unsigned int suspend_mode_mask; | |
74 | unsigned int dvs_ctrl_reg; | |
75 | }; | |
76 | ||
77 | static int rtq2134_buck_set_mode(struct regulator_dev *rdev, unsigned int mode) | |
78 | { | |
79 | struct rtq2134_regulator_desc *desc = | |
80 | (struct rtq2134_regulator_desc *)rdev->desc; | |
81 | unsigned int val; | |
82 | ||
83 | if (mode == REGULATOR_MODE_NORMAL) | |
84 | val = RTQ2134_AUTO_MODE; | |
85 | else if (mode == REGULATOR_MODE_FAST) | |
86 | val = RTQ2134_FCCM_MODE; | |
87 | else | |
88 | return -EINVAL; | |
89 | ||
90 | val <<= ffs(desc->mode_mask) - 1; | |
91 | return regmap_update_bits(rdev->regmap, desc->mode_reg, desc->mode_mask, | |
92 | val); | |
93 | } | |
94 | ||
95 | static unsigned int rtq2134_buck_get_mode(struct regulator_dev *rdev) | |
96 | { | |
97 | struct rtq2134_regulator_desc *desc = | |
98 | (struct rtq2134_regulator_desc *)rdev->desc; | |
99 | unsigned int mode; | |
100 | int ret; | |
101 | ||
102 | ret = regmap_read(rdev->regmap, desc->mode_reg, &mode); | |
103 | if (ret) | |
104 | return ret; | |
105 | ||
106 | if (mode & desc->mode_mask) | |
107 | return REGULATOR_MODE_FAST; | |
108 | return REGULATOR_MODE_NORMAL; | |
109 | } | |
110 | ||
111 | static int rtq2134_buck_set_suspend_voltage(struct regulator_dev *rdev, int uV) | |
112 | { | |
113 | struct rtq2134_regulator_desc *desc = | |
114 | (struct rtq2134_regulator_desc *)rdev->desc; | |
115 | int sel; | |
116 | ||
117 | sel = regulator_map_voltage_linear_range(rdev, uV, uV); | |
118 | if (sel < 0) | |
119 | return sel; | |
120 | ||
121 | sel <<= ffs(desc->suspend_vsel_mask) - 1; | |
122 | ||
123 | return regmap_update_bits(rdev->regmap, desc->suspend_vsel_reg, | |
124 | desc->suspend_vsel_mask, sel); | |
125 | } | |
126 | ||
127 | static int rtq2134_buck_set_suspend_enable(struct regulator_dev *rdev) | |
128 | { | |
129 | struct rtq2134_regulator_desc *desc = | |
130 | (struct rtq2134_regulator_desc *)rdev->desc; | |
131 | unsigned int val = desc->suspend_enable_mask; | |
132 | ||
133 | return regmap_update_bits(rdev->regmap, desc->suspend_enable_reg, | |
134 | desc->suspend_enable_mask, val); | |
135 | } | |
136 | ||
137 | static int rtq2134_buck_set_suspend_disable(struct regulator_dev *rdev) | |
138 | { | |
139 | struct rtq2134_regulator_desc *desc = | |
140 | (struct rtq2134_regulator_desc *)rdev->desc; | |
141 | ||
142 | return regmap_update_bits(rdev->regmap, desc->suspend_enable_reg, | |
143 | desc->suspend_enable_mask, 0); | |
144 | } | |
145 | ||
146 | static int rtq2134_buck_set_suspend_mode(struct regulator_dev *rdev, | |
147 | unsigned int mode) | |
148 | { | |
149 | struct rtq2134_regulator_desc *desc = | |
150 | (struct rtq2134_regulator_desc *)rdev->desc; | |
151 | unsigned int val; | |
152 | ||
153 | if (mode == REGULATOR_MODE_NORMAL) | |
154 | val = RTQ2134_AUTO_MODE; | |
155 | else if (mode == REGULATOR_MODE_FAST) | |
156 | val = RTQ2134_FCCM_MODE; | |
157 | else | |
158 | return -EINVAL; | |
159 | ||
160 | val <<= ffs(desc->suspend_mode_mask) - 1; | |
161 | return regmap_update_bits(rdev->regmap, desc->suspend_mode_reg, | |
162 | desc->suspend_mode_mask, val); | |
163 | } | |
164 | ||
165 | static int rtq2134_buck_get_error_flags(struct regulator_dev *rdev, | |
166 | unsigned int *flags) | |
167 | { | |
168 | int rid = rdev_get_id(rdev); | |
169 | unsigned int chip_error, buck_error, events = 0; | |
170 | int ret; | |
171 | ||
172 | ret = regmap_read(rdev->regmap, RTQ2134_REG_FLT_RECORDTEMP, | |
173 | &chip_error); | |
174 | if (ret) { | |
175 | dev_err(&rdev->dev, "Failed to get chip error flag\n"); | |
176 | return ret; | |
177 | } | |
178 | ||
179 | ret = regmap_read(rdev->regmap, RTQ2134_REG_FLT_RECORDBUCK(rid), | |
180 | &buck_error); | |
181 | if (ret) { | |
182 | dev_err(&rdev->dev, "Failed to get buck error flag\n"); | |
183 | return ret; | |
184 | } | |
185 | ||
186 | if (chip_error & RTQ2134_CHIPOT_MASK) | |
187 | events |= REGULATOR_ERROR_OVER_TEMP; | |
188 | ||
189 | if (buck_error & RTQ2134_BUCKUV_MASK) | |
190 | events |= REGULATOR_ERROR_UNDER_VOLTAGE; | |
191 | ||
192 | if (buck_error & RTQ2134_BUCKOV_MASK) | |
193 | events |= REGULATOR_ERROR_REGULATION_OUT; | |
194 | ||
195 | *flags = events; | |
196 | return 0; | |
197 | } | |
198 | ||
199 | static const struct regulator_ops rtq2134_buck_ops = { | |
200 | .list_voltage = regulator_list_voltage_linear_range, | |
201 | .set_voltage_sel = regulator_set_voltage_sel_regmap, | |
202 | .get_voltage_sel = regulator_get_voltage_sel_regmap, | |
203 | .enable = regulator_enable_regmap, | |
204 | .disable = regulator_disable_regmap, | |
205 | .is_enabled = regulator_is_enabled_regmap, | |
206 | .set_active_discharge = regulator_set_active_discharge_regmap, | |
207 | .set_ramp_delay = regulator_set_ramp_delay_regmap, | |
208 | .set_mode = rtq2134_buck_set_mode, | |
209 | .get_mode = rtq2134_buck_get_mode, | |
210 | .set_suspend_voltage = rtq2134_buck_set_suspend_voltage, | |
211 | .set_suspend_enable = rtq2134_buck_set_suspend_enable, | |
212 | .set_suspend_disable = rtq2134_buck_set_suspend_disable, | |
213 | .set_suspend_mode = rtq2134_buck_set_suspend_mode, | |
214 | .get_error_flags = rtq2134_buck_get_error_flags, | |
215 | }; | |
216 | ||
217 | static const struct linear_range rtq2134_buck_vout_ranges[] = { | |
218 | REGULATOR_LINEAR_RANGE(300000, 0, 200, 5000), | |
219 | REGULATOR_LINEAR_RANGE(1310000, 201, 255, 10000) | |
220 | }; | |
221 | ||
222 | static unsigned int rtq2134_buck_of_map_mode(unsigned int mode) | |
223 | { | |
224 | switch (mode) { | |
225 | case RTQ2134_AUTO_MODE: | |
226 | return REGULATOR_MODE_NORMAL; | |
227 | case RTQ2134_FCCM_MODE: | |
228 | return REGULATOR_MODE_FAST; | |
229 | } | |
230 | ||
231 | return REGULATOR_MODE_INVALID; | |
232 | } | |
233 | ||
234 | static int rtq2134_buck_of_parse_cb(struct device_node *np, | |
235 | const struct regulator_desc *desc, | |
236 | struct regulator_config *cfg) | |
237 | { | |
238 | struct rtq2134_regulator_desc *rdesc = | |
239 | (struct rtq2134_regulator_desc *)desc; | |
240 | int rid = desc->id; | |
241 | bool uv_shutdown, vsel_dvs; | |
242 | unsigned int val; | |
243 | int ret; | |
244 | ||
245 | vsel_dvs = of_property_read_bool(np, "richtek,use-vsel-dvs"); | |
246 | if (vsel_dvs) | |
247 | val = RTQ2134_BUCK_VSEL_CTRL; | |
248 | else | |
249 | val = RTQ2134_BUCK_DVS0_CTRL; | |
250 | ||
251 | ret = regmap_update_bits(cfg->regmap, rdesc->dvs_ctrl_reg, | |
252 | RTQ2134_BUCKDVS_CTRL_MASK, val); | |
253 | if (ret) | |
254 | return ret; | |
255 | ||
256 | uv_shutdown = of_property_read_bool(np, "richtek,uv-shutdown"); | |
257 | if (uv_shutdown) | |
258 | val = 0; | |
259 | else | |
260 | val = RTQ2134_UVHICCUP_MASK; | |
261 | ||
262 | return regmap_update_bits(cfg->regmap, RTQ2134_REG_FLT_BUCKCTRL(rid), | |
263 | RTQ2134_UVHICCUP_MASK, val); | |
264 | } | |
265 | ||
266 | static const unsigned int rtq2134_buck_ramp_delay_table[] = { | |
267 | 0, 16000, 0, 8000, 4000, 2000, 1000, 500 | |
268 | }; | |
269 | ||
270 | #define RTQ2134_BUCK_DESC(_id) { \ | |
271 | .desc = { \ | |
272 | .name = "rtq2134_buck" #_id, \ | |
273 | .of_match = of_match_ptr("buck" #_id), \ | |
274 | .regulators_node = of_match_ptr("regulators"), \ | |
275 | .id = RTQ2134_IDX_BUCK##_id, \ | |
276 | .type = REGULATOR_VOLTAGE, \ | |
277 | .owner = THIS_MODULE, \ | |
278 | .ops = &rtq2134_buck_ops, \ | |
279 | .n_voltages = RTQ2134_VOUT_MAXNUM, \ | |
280 | .linear_ranges = rtq2134_buck_vout_ranges, \ | |
281 | .n_linear_ranges = ARRAY_SIZE(rtq2134_buck_vout_ranges), \ | |
282 | .vsel_reg = RTQ2134_REG_BUCK##_id##_DVS0CFG1, \ | |
283 | .vsel_mask = RTQ2134_VOUT_MASK, \ | |
284 | .enable_reg = RTQ2134_REG_BUCK##_id##_DVS0CFG0, \ | |
285 | .enable_mask = RTQ2134_VOUTEN_MASK, \ | |
286 | .active_discharge_reg = RTQ2134_REG_BUCK##_id##_CFG0, \ | |
287 | .active_discharge_mask = RTQ2134_ACTDISCHG_MASK, \ | |
17049bf9 | 288 | .active_discharge_on = RTQ2134_ACTDISCHG_MASK, \ |
0555d414 CH |
289 | .ramp_reg = RTQ2134_REG_BUCK##_id##_RSPCFG, \ |
290 | .ramp_mask = RTQ2134_RSPUP_MASK, \ | |
291 | .ramp_delay_table = rtq2134_buck_ramp_delay_table, \ | |
292 | .n_ramp_values = ARRAY_SIZE(rtq2134_buck_ramp_delay_table), \ | |
293 | .of_map_mode = rtq2134_buck_of_map_mode, \ | |
294 | .of_parse_cb = rtq2134_buck_of_parse_cb, \ | |
295 | }, \ | |
296 | .mode_reg = RTQ2134_REG_BUCK##_id##_DVS0CFG0, \ | |
297 | .mode_mask = RTQ2134_FCCM_MASK, \ | |
298 | .suspend_mode_reg = RTQ2134_REG_BUCK##_id##_DVS1CFG0, \ | |
299 | .suspend_mode_mask = RTQ2134_FCCM_MASK, \ | |
300 | .suspend_enable_reg = RTQ2134_REG_BUCK##_id##_DVS1CFG0, \ | |
301 | .suspend_enable_mask = RTQ2134_VOUTEN_MASK, \ | |
302 | .suspend_vsel_reg = RTQ2134_REG_BUCK##_id##_DVS1CFG1, \ | |
303 | .suspend_vsel_mask = RTQ2134_VOUT_MASK, \ | |
304 | .dvs_ctrl_reg = RTQ2134_REG_BUCK##_id##_DVSCFG, \ | |
305 | } | |
306 | ||
307 | static const struct rtq2134_regulator_desc rtq2134_regulator_descs[] = { | |
308 | RTQ2134_BUCK_DESC(1), | |
309 | RTQ2134_BUCK_DESC(2), | |
310 | RTQ2134_BUCK_DESC(3) | |
311 | }; | |
312 | ||
313 | static bool rtq2134_is_accissible_reg(struct device *dev, unsigned int reg) | |
314 | { | |
15b4d2b9 | 315 | if (reg >= RTQ2134_REG_IO_CHIPNAME && reg <= RTQ2134_REG_BUCK3_SLEWCTRL) |
0555d414 CH |
316 | return true; |
317 | return false; | |
318 | } | |
319 | ||
320 | static const struct regmap_config rtq2134_regmap_config = { | |
321 | .reg_bits = 8, | |
322 | .val_bits = 8, | |
323 | .max_register = RTQ2134_REG_BUCK3_SLEWCTRL, | |
324 | ||
325 | .readable_reg = rtq2134_is_accissible_reg, | |
326 | .writeable_reg = rtq2134_is_accissible_reg, | |
327 | }; | |
328 | ||
329 | static int rtq2134_probe(struct i2c_client *i2c) | |
330 | { | |
331 | struct regmap *regmap; | |
332 | struct regulator_dev *rdev; | |
15b4d2b9 | 333 | struct regulator_config regulator_cfg = {}; |
0555d414 CH |
334 | int i; |
335 | ||
336 | regmap = devm_regmap_init_i2c(i2c, &rtq2134_regmap_config); | |
337 | if (IS_ERR(regmap)) { | |
338 | dev_err(&i2c->dev, "Failed to allocate regmap\n"); | |
339 | return PTR_ERR(regmap); | |
340 | } | |
341 | ||
342 | regulator_cfg.dev = &i2c->dev; | |
343 | regulator_cfg.regmap = regmap; | |
344 | for (i = 0; i < ARRAY_SIZE(rtq2134_regulator_descs); i++) { | |
345 | rdev = devm_regulator_register(&i2c->dev, | |
346 | &rtq2134_regulator_descs[i].desc, | |
347 | ®ulator_cfg); | |
348 | if (IS_ERR(rdev)) { | |
349 | dev_err(&i2c->dev, "Failed to init %d regulator\n", i); | |
350 | return PTR_ERR(rdev); | |
351 | } | |
352 | } | |
353 | ||
354 | return 0; | |
355 | } | |
356 | ||
357 | static const struct of_device_id __maybe_unused rtq2134_device_tables[] = { | |
358 | { .compatible = "richtek,rtq2134", }, | |
359 | {} | |
360 | }; | |
361 | MODULE_DEVICE_TABLE(of, rtq2134_device_tables); | |
362 | ||
363 | static struct i2c_driver rtq2134_driver = { | |
364 | .driver = { | |
365 | .name = "rtq2134", | |
46600ab1 | 366 | .probe_type = PROBE_PREFER_ASYNCHRONOUS, |
0555d414 CH |
367 | .of_match_table = rtq2134_device_tables, |
368 | }, | |
964e1865 | 369 | .probe = rtq2134_probe, |
0555d414 CH |
370 | }; |
371 | module_i2c_driver(rtq2134_driver); | |
372 | ||
373 | MODULE_AUTHOR("ChiYuan Huang <cy_huang@richtek.com>"); | |
374 | MODULE_DESCRIPTION("Richtek RTQ2134 Regulator Driver"); | |
375 | MODULE_LICENSE("GPL v2"); |