1// SPDX-License-Identifier: GPL-2.0
2//
3// Copyright (c) 2022 Collabora Ltd.
4// Author: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
5//
6// Based on mt6323-regulator.c,
7// Copyright (c) 2016 MediaTek Inc.
8//
9
10#include <linux/module.h>
11#include <linux/of.h>
12#include <linux/platform_device.h>
13#include <linux/regmap.h>
14#include <linux/mfd/mt6397/core.h>
15#include <linux/mfd/mt6332/registers.h>
16#include <linux/regulator/driver.h>
17#include <linux/regulator/machine.h>
18#include <linux/regulator/mt6332-regulator.h>
19#include <linux/regulator/of_regulator.h>
20
21#define MT6332_LDO_MODE_NORMAL 0
22#define MT6332_LDO_MODE_LP 1
23
24/*
25 * MT6332 regulators information
26 *
27 * @desc: standard fields of regulator description.
28 * @qi: Mask for query enable signal status of regulators
29 * @vselon_reg: Register sections for hardware control mode of bucks
30 * @vselctrl_reg: Register for controlling the buck control mode.
31 * @vselctrl_mask: Mask for query buck's voltage control mode.
32 * @status_reg: Register for regulator enable status where qi unavailable
33 * @status_mask: Mask for querying regulator enable status
34 */
35struct mt6332_regulator_info {
36 struct regulator_desc desc;
37 u32 qi;
38 u32 vselon_reg;
39 u32 vselctrl_reg;
40 u32 vselctrl_mask;
41 u32 modeset_reg;
42 u32 modeset_mask;
43 u32 status_reg;
44 u32 status_mask;
45};
46
47#define MT6332_BUCK(match, vreg, min, max, step, volt_ranges, enreg, \
48 vosel, vosel_mask, voselon, vosel_ctrl) \
49[MT6332_ID_##vreg] = { \
50 .desc = { \
51 .name = #vreg, \
52 .of_match = of_match_ptr(match), \
53 .ops = &mt6332_buck_volt_range_ops, \
54 .type = REGULATOR_VOLTAGE, \
55 .id = MT6332_ID_##vreg, \
56 .owner = THIS_MODULE, \
57 .n_voltages = (max - min)/step + 1, \
58 .linear_ranges = volt_ranges, \
59 .n_linear_ranges = ARRAY_SIZE(volt_ranges), \
60 .vsel_reg = vosel, \
61 .vsel_mask = vosel_mask, \
62 .enable_reg = enreg, \
63 .enable_mask = BIT(0), \
64 }, \
65 .qi = BIT(13), \
66 .vselon_reg = voselon, \
67 .vselctrl_reg = vosel_ctrl, \
68 .vselctrl_mask = BIT(1), \
69 .status_mask = 0, \
70}
71
72#define MT6332_LDO_LINEAR(match, vreg, min, max, step, volt_ranges, \
73 enreg, vosel, vosel_mask, voselon, \
74 vosel_ctrl, _modeset_reg, _modeset_mask) \
75[MT6332_ID_##vreg] = { \
76 .desc = { \
77 .name = #vreg, \
78 .of_match = of_match_ptr(match), \
79 .ops = &mt6332_ldo_volt_range_ops, \
80 .type = REGULATOR_VOLTAGE, \
81 .id = MT6332_ID_##vreg, \
82 .owner = THIS_MODULE, \
83 .n_voltages = (max - min)/step + 1, \
84 .linear_ranges = volt_ranges, \
85 .n_linear_ranges = ARRAY_SIZE(volt_ranges), \
86 .vsel_reg = vosel, \
87 .vsel_mask = vosel_mask, \
88 .enable_reg = enreg, \
89 .enable_mask = BIT(0), \
90 }, \
91 .qi = BIT(15), \
92 .vselon_reg = voselon, \
93 .vselctrl_reg = vosel_ctrl, \
94 .vselctrl_mask = BIT(1), \
95 .modeset_reg = _modeset_reg, \
96 .modeset_mask = _modeset_mask, \
97 .status_mask = 0, \
98}
99
100#define MT6332_LDO_AO(match, vreg, ldo_volt_table, vosel, vosel_mask) \
101[MT6332_ID_##vreg] = { \
102 .desc = { \
103 .name = #vreg, \
104 .of_match = of_match_ptr(match), \
105 .ops = &mt6332_volt_table_ao_ops, \
106 .type = REGULATOR_VOLTAGE, \
107 .id = MT6332_ID_##vreg, \
108 .owner = THIS_MODULE, \
109 .n_voltages = ARRAY_SIZE(ldo_volt_table), \
110 .volt_table = ldo_volt_table, \
111 .vsel_reg = vosel, \
112 .vsel_mask = vosel_mask, \
113 }, \
114}
115
116#define MT6332_LDO(match, vreg, ldo_volt_table, enreg, enbit, vosel, \
117 vosel_mask, _modeset_reg, _modeset_mask) \
118[MT6332_ID_##vreg] = { \
119 .desc = { \
120 .name = #vreg, \
121 .of_match = of_match_ptr(match), \
122 .ops = &mt6332_volt_table_ops, \
123 .type = REGULATOR_VOLTAGE, \
124 .id = MT6332_ID_##vreg, \
125 .owner = THIS_MODULE, \
126 .n_voltages = ARRAY_SIZE(ldo_volt_table), \
127 .volt_table = ldo_volt_table, \
128 .vsel_reg = vosel, \
129 .vsel_mask = vosel_mask, \
130 .enable_reg = enreg, \
131 .enable_mask = BIT(enbit), \
132 }, \
133 .qi = BIT(15), \
134 .modeset_reg = _modeset_reg, \
135 .modeset_mask = _modeset_mask, \
136 .status_mask = 0, \
137}
138
139#define MT6332_REG_FIXED(match, vreg, enreg, enbit, qibit, volt, stbit) \
140[MT6332_ID_##vreg] = { \
141 .desc = { \
142 .name = #vreg, \
143 .of_match = of_match_ptr(match), \
144 .ops = &mt6332_volt_fixed_ops, \
145 .type = REGULATOR_VOLTAGE, \
146 .id = MT6332_ID_##vreg, \
147 .owner = THIS_MODULE, \
148 .n_voltages = 1, \
149 .enable_reg = enreg, \
150 .enable_mask = BIT(enbit), \
151 .min_uV = volt, \
152 }, \
153 .qi = BIT(qibit), \
154 .status_reg = MT6332_EN_STATUS0, \
155 .status_mask = BIT(stbit), \
156}
157
158static const struct linear_range boost_volt_range[] = {
159 REGULATOR_LINEAR_RANGE(3500000, 0, 0x7f, 31250),
160};
161
162static const struct linear_range buck_volt_range[] = {
163 REGULATOR_LINEAR_RANGE(700000, 0, 0x7f, 6250),
164};
165
166static const struct linear_range buck_pa_volt_range[] = {
167 REGULATOR_LINEAR_RANGE(500000, 0, 0x3f, 50000),
168};
169
170static const struct linear_range buck_rf_volt_range[] = {
171 REGULATOR_LINEAR_RANGE(1050000, 0, 0x7f, 9375),
172};
173
174static const unsigned int ldo_volt_table1[] = {
175 2800000, 3000000, 0, 3200000
176};
177
178static const unsigned int ldo_volt_table2[] = {
179 1200000, 1300000, 1400000, 1500000, 1600000, 1700000, 1800000, 1800000,
180};
181
182static int mt6332_get_status(struct regulator_dev *rdev)
183{
184 struct mt6332_regulator_info *info = rdev_get_drvdata(rdev);
185 u32 reg, en_mask, regval;
186 int ret;
187
188 if (info->qi > 0) {
189 reg = info->desc.enable_reg;
190 en_mask = info->qi;
191 } else {
192 reg = info->status_reg;
193 en_mask = info->status_mask;
194 }
195
196 ret = regmap_read(map: rdev->regmap, reg, val: &regval);
197 if (ret != 0) {
198 dev_err(&rdev->dev, "Failed to get enable reg: %d\n", ret);
199 return ret;
200 }
201
202 return (regval & en_mask) ? REGULATOR_STATUS_ON : REGULATOR_STATUS_OFF;
203}
204
205static int mt6332_ldo_set_mode(struct regulator_dev *rdev, unsigned int mode)
206{
207 struct mt6332_regulator_info *info = rdev_get_drvdata(rdev);
208 int val;
209
210 switch (mode) {
211 case REGULATOR_MODE_STANDBY:
212 val = MT6332_LDO_MODE_LP;
213 break;
214 case REGULATOR_MODE_NORMAL:
215 val = MT6332_LDO_MODE_NORMAL;
216 break;
217 default:
218 return -EINVAL;
219 }
220
221 val <<= ffs(info->modeset_mask) - 1;
222
223 return regmap_update_bits(map: rdev->regmap, reg: info->modeset_reg,
224 mask: info->modeset_mask, val);
225}
226
227static unsigned int mt6332_ldo_get_mode(struct regulator_dev *rdev)
228{
229 struct mt6332_regulator_info *info = rdev_get_drvdata(rdev);
230 unsigned int val;
231 int ret;
232
233 ret = regmap_read(map: rdev->regmap, reg: info->modeset_reg, val: &val);
234 if (ret < 0)
235 return ret;
236
237 val &= info->modeset_mask;
238 val >>= ffs(info->modeset_mask) - 1;
239
240 return (val & BIT(0)) ? REGULATOR_MODE_STANDBY : REGULATOR_MODE_NORMAL;
241}
242
243static const struct regulator_ops mt6332_buck_volt_range_ops = {
244 .list_voltage = regulator_list_voltage_linear_range,
245 .map_voltage = regulator_map_voltage_linear_range,
246 .set_voltage_sel = regulator_set_voltage_sel_regmap,
247 .get_voltage_sel = regulator_get_voltage_sel_regmap,
248 .set_voltage_time_sel = regulator_set_voltage_time_sel,
249 .enable = regulator_enable_regmap,
250 .disable = regulator_disable_regmap,
251 .is_enabled = regulator_is_enabled_regmap,
252 .get_status = mt6332_get_status,
253};
254
255static const struct regulator_ops mt6332_ldo_volt_range_ops = {
256 .list_voltage = regulator_list_voltage_linear_range,
257 .map_voltage = regulator_map_voltage_linear_range,
258 .set_voltage_sel = regulator_set_voltage_sel_regmap,
259 .get_voltage_sel = regulator_get_voltage_sel_regmap,
260 .set_voltage_time_sel = regulator_set_voltage_time_sel,
261 .enable = regulator_enable_regmap,
262 .disable = regulator_disable_regmap,
263 .is_enabled = regulator_is_enabled_regmap,
264 .get_status = mt6332_get_status,
265 .set_mode = mt6332_ldo_set_mode,
266 .get_mode = mt6332_ldo_get_mode,
267};
268
269static const struct regulator_ops mt6332_volt_table_ops = {
270 .list_voltage = regulator_list_voltage_table,
271 .map_voltage = regulator_map_voltage_iterate,
272 .set_voltage_sel = regulator_set_voltage_sel_regmap,
273 .get_voltage_sel = regulator_get_voltage_sel_regmap,
274 .set_voltage_time_sel = regulator_set_voltage_time_sel,
275 .enable = regulator_enable_regmap,
276 .disable = regulator_disable_regmap,
277 .is_enabled = regulator_is_enabled_regmap,
278 .get_status = mt6332_get_status,
279 .set_mode = mt6332_ldo_set_mode,
280 .get_mode = mt6332_ldo_get_mode,
281};
282
283static const struct regulator_ops mt6332_volt_table_ao_ops = {
284 .list_voltage = regulator_list_voltage_table,
285 .map_voltage = regulator_map_voltage_iterate,
286 .set_voltage_sel = regulator_set_voltage_sel_regmap,
287 .get_voltage_sel = regulator_get_voltage_sel_regmap,
288 .set_voltage_time_sel = regulator_set_voltage_time_sel,
289};
290
291static const struct regulator_ops mt6332_volt_fixed_ops = {
292 .list_voltage = regulator_list_voltage_linear,
293 .enable = regulator_enable_regmap,
294 .disable = regulator_disable_regmap,
295 .is_enabled = regulator_is_enabled_regmap,
296 .get_status = mt6332_get_status,
297};
298
299/* The array is indexed by id(MT6332_ID_XXX) */
300static struct mt6332_regulator_info mt6332_regulators[] = {
301 MT6332_BUCK("buck-vdram", VDRAM, 700000, 1493750, 6250, buck_volt_range,
302 MT6332_EN_STATUS0, MT6332_VDRAM_CON11, GENMASK(6, 0),
303 MT6332_VDRAM_CON12, MT6332_VDRAM_CON7),
304 MT6332_BUCK("buck-vdvfs2", VDVFS2, 700000, 1312500, 6250, buck_volt_range,
305 MT6332_VDVFS2_CON9, MT6332_VDVFS2_CON11, GENMASK(6, 0),
306 MT6332_VDVFS2_CON12, MT6332_VDVFS2_CON7),
307 MT6332_BUCK("buck-vpa", VPA, 500000, 3400000, 50000, buck_pa_volt_range,
308 MT6332_VPA_CON9, MT6332_VPA_CON11, GENMASK(5, 0),
309 MT6332_VPA_CON12, MT6332_VPA_CON7),
310 MT6332_BUCK("buck-vrf18a", VRF1, 1050000, 2240625, 9375, buck_rf_volt_range,
311 MT6332_VRF1_CON9, MT6332_VRF1_CON11, GENMASK(6, 0),
312 MT6332_VRF1_CON12, MT6332_VRF1_CON7),
313 MT6332_BUCK("buck-vrf18b", VRF2, 1050000, 2240625, 9375, buck_rf_volt_range,
314 MT6332_VRF2_CON9, MT6332_VRF2_CON11, GENMASK(6, 0),
315 MT6332_VRF2_CON12, MT6332_VRF2_CON7),
316 MT6332_BUCK("buck-vsbst", VSBST, 3500000, 7468750, 31250, boost_volt_range,
317 MT6332_VSBST_CON8, MT6332_VSBST_CON12, GENMASK(6, 0),
318 MT6332_VSBST_CON13, MT6332_VSBST_CON8),
319 MT6332_LDO("ldo-vauxb32", VAUXB32, ldo_volt_table1, MT6332_LDO_CON1, 10,
320 MT6332_LDO_CON9, GENMASK(6, 5), MT6332_LDO_CON1, GENMASK(1, 0)),
321 MT6332_REG_FIXED("ldo-vbif28", VBIF28, MT6332_LDO_CON2, 10, 0, 2800000, 1),
322 MT6332_REG_FIXED("ldo-vusb33", VUSB33, MT6332_LDO_CON3, 10, 0, 3300000, 2),
323 MT6332_LDO_LINEAR("ldo-vsram", VSRAM_DVFS2, 700000, 1493750, 6250, buck_volt_range,
324 MT6332_EN_STATUS0, MT6332_LDO_CON8, GENMASK(15, 9),
325 MT6332_VDVFS2_CON23, MT6332_VDVFS2_CON22,
326 MT6332_LDO_CON5, GENMASK(1, 0)),
327 MT6332_LDO_AO("ldo-vdig18", VDIG18, ldo_volt_table2, MT6332_LDO_CON12, GENMASK(11, 9)),
328};
329
330static int mt6332_set_buck_vosel_reg(struct platform_device *pdev)
331{
332 struct mt6397_chip *mt6332 = dev_get_drvdata(dev: pdev->dev.parent);
333 int i;
334 u32 regval;
335
336 for (i = 0; i < MT6332_ID_VREG_MAX; i++) {
337 if (mt6332_regulators[i].vselctrl_reg) {
338 if (regmap_read(map: mt6332->regmap,
339 reg: mt6332_regulators[i].vselctrl_reg,
340 val: &regval) < 0) {
341 dev_err(&pdev->dev,
342 "Failed to read buck ctrl\n");
343 return -EIO;
344 }
345
346 if (regval & mt6332_regulators[i].vselctrl_mask) {
347 mt6332_regulators[i].desc.vsel_reg =
348 mt6332_regulators[i].vselon_reg;
349 }
350 }
351 }
352
353 return 0;
354}
355
356static int mt6332_regulator_probe(struct platform_device *pdev)
357{
358 struct mt6397_chip *mt6332 = dev_get_drvdata(dev: pdev->dev.parent);
359 struct regulator_config config = {};
360 struct regulator_dev *rdev;
361 int i;
362 u32 reg_value;
363
364 /* Query buck controller to select activated voltage register part */
365 if (mt6332_set_buck_vosel_reg(pdev))
366 return -EIO;
367
368 /* Read PMIC chip revision to update constraints and voltage table */
369 if (regmap_read(map: mt6332->regmap, MT6332_HWCID, val: &reg_value) < 0) {
370 dev_err(&pdev->dev, "Failed to read Chip ID\n");
371 return -EIO;
372 }
373 reg_value &= GENMASK(7, 0);
374
375 dev_info(&pdev->dev, "Chip ID = 0x%x\n", reg_value);
376
377 /*
378 * ChipID 0x10 is "MT6332 E1", has a different voltage table and
379 * it's currently not supported in this driver. Upon detection of
380 * this ID, refuse to register the regulators, as we will wrongly
381 * interpret the VSEL for this revision, potentially overvolting
382 * some device.
383 */
384 if (reg_value == 0x10) {
385 dev_err(&pdev->dev, "Chip version not supported. Bailing out.\n");
386 return -EINVAL;
387 }
388
389 for (i = 0; i < MT6332_ID_VREG_MAX; i++) {
390 config.dev = &pdev->dev;
391 config.driver_data = &mt6332_regulators[i];
392 config.regmap = mt6332->regmap;
393 rdev = devm_regulator_register(dev: &pdev->dev,
394 regulator_desc: &mt6332_regulators[i].desc, config: &config);
395 if (IS_ERR(ptr: rdev)) {
396 dev_err(&pdev->dev, "failed to register %s\n",
397 mt6332_regulators[i].desc.name);
398 return PTR_ERR(ptr: rdev);
399 }
400 }
401 return 0;
402}
403
404static const struct platform_device_id mt6332_platform_ids[] = {
405 {"mt6332-regulator", 0},
406 { /* sentinel */ },
407};
408MODULE_DEVICE_TABLE(platform, mt6332_platform_ids);
409
410static struct platform_driver mt6332_regulator_driver = {
411 .driver = {
412 .name = "mt6332-regulator",
413 .probe_type = PROBE_PREFER_ASYNCHRONOUS,
414 },
415 .probe = mt6332_regulator_probe,
416 .id_table = mt6332_platform_ids,
417};
418
419module_platform_driver(mt6332_regulator_driver);
420
421MODULE_AUTHOR("AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>");
422MODULE_DESCRIPTION("Regulator Driver for MediaTek MT6332 PMIC");
423MODULE_LICENSE("GPL");
424

source code of linux/drivers/regulator/mt6332-regulator.c