1 // SPDX-License-Identifier: GPL-2.0
3 // Copyright (c) 2022 Collabora Ltd.
4 // Author: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
6 // Based on mt6323-regulator.c,
7 // Copyright (c) 2016 MediaTek Inc.
10 #include <linux/module.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>
21 #define MT6332_LDO_MODE_NORMAL 0
22 #define MT6332_LDO_MODE_LP 1
25 * MT6332 regulators information
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
35 struct mt6332_regulator_info
{
36 struct regulator_desc desc
;
47 #define MT6332_BUCK(match, vreg, min, max, step, volt_ranges, enreg, \
48 vosel, vosel_mask, voselon, vosel_ctrl) \
49 [MT6332_ID_##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), \
61 .vsel_mask = vosel_mask, \
62 .enable_reg = enreg, \
63 .enable_mask = BIT(0), \
66 .vselon_reg = voselon, \
67 .vselctrl_reg = vosel_ctrl, \
68 .vselctrl_mask = BIT(1), \
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] = { \
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), \
87 .vsel_mask = vosel_mask, \
88 .enable_reg = enreg, \
89 .enable_mask = BIT(0), \
92 .vselon_reg = voselon, \
93 .vselctrl_reg = vosel_ctrl, \
94 .vselctrl_mask = BIT(1), \
95 .modeset_reg = _modeset_reg, \
96 .modeset_mask = _modeset_mask, \
100 #define MT6332_LDO_AO(match, vreg, ldo_volt_table, vosel, vosel_mask) \
101 [MT6332_ID_##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, \
112 .vsel_mask = vosel_mask, \
116 #define MT6332_LDO(match, vreg, ldo_volt_table, enreg, enbit, vosel, \
117 vosel_mask, _modeset_reg, _modeset_mask) \
118 [MT6332_ID_##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, \
129 .vsel_mask = vosel_mask, \
130 .enable_reg = enreg, \
131 .enable_mask = BIT(enbit), \
134 .modeset_reg = _modeset_reg, \
135 .modeset_mask = _modeset_mask, \
139 #define MT6332_REG_FIXED(match, vreg, enreg, enbit, qibit, volt, stbit) \
140 [MT6332_ID_##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, \
149 .enable_reg = enreg, \
150 .enable_mask = BIT(enbit), \
154 .status_reg = MT6332_EN_STATUS0, \
155 .status_mask = BIT(stbit), \
158 static const struct linear_range boost_volt_range
[] = {
159 REGULATOR_LINEAR_RANGE(3500000, 0, 0x7f, 31250),
162 static const struct linear_range buck_volt_range
[] = {
163 REGULATOR_LINEAR_RANGE(700000, 0, 0x7f, 6250),
166 static const struct linear_range buck_pa_volt_range
[] = {
167 REGULATOR_LINEAR_RANGE(500000, 0, 0x3f, 50000),
170 static const struct linear_range buck_rf_volt_range
[] = {
171 REGULATOR_LINEAR_RANGE(1050000, 0, 0x7f, 9375),
174 static const unsigned int ldo_volt_table1
[] = {
175 2800000, 3000000, 0, 3200000
178 static const unsigned int ldo_volt_table2
[] = {
179 1200000, 1300000, 1400000, 1500000, 1600000, 1700000, 1800000, 1800000,
182 static int mt6332_get_status(struct regulator_dev
*rdev
)
184 struct mt6332_regulator_info
*info
= rdev_get_drvdata(rdev
);
185 u32 reg
, en_mask
, regval
;
189 reg
= info
->desc
.enable_reg
;
192 reg
= info
->status_reg
;
193 en_mask
= info
->status_mask
;
196 ret
= regmap_read(rdev
->regmap
, reg
, ®val
);
198 dev_err(&rdev
->dev
, "Failed to get enable reg: %d\n", ret
);
202 return (regval
& en_mask
) ? REGULATOR_STATUS_ON
: REGULATOR_STATUS_OFF
;
205 static int mt6332_ldo_set_mode(struct regulator_dev
*rdev
, unsigned int mode
)
207 struct mt6332_regulator_info
*info
= rdev_get_drvdata(rdev
);
211 case REGULATOR_MODE_STANDBY
:
212 val
= MT6332_LDO_MODE_LP
;
214 case REGULATOR_MODE_NORMAL
:
215 val
= MT6332_LDO_MODE_NORMAL
;
221 val
<<= ffs(info
->modeset_mask
) - 1;
223 return regmap_update_bits(rdev
->regmap
, info
->modeset_reg
,
224 info
->modeset_mask
, val
);
227 static unsigned int mt6332_ldo_get_mode(struct regulator_dev
*rdev
)
229 struct mt6332_regulator_info
*info
= rdev_get_drvdata(rdev
);
233 ret
= regmap_read(rdev
->regmap
, info
->modeset_reg
, &val
);
237 val
&= info
->modeset_mask
;
238 val
>>= ffs(info
->modeset_mask
) - 1;
240 return (val
& BIT(0)) ? REGULATOR_MODE_STANDBY
: REGULATOR_MODE_NORMAL
;
243 static 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
,
255 static 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
,
269 static 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
,
283 static 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
,
291 static 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
,
299 /* The array is indexed by id(MT6332_ID_XXX) */
300 static 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)),
330 static int mt6332_set_buck_vosel_reg(struct platform_device
*pdev
)
332 struct mt6397_chip
*mt6332
= dev_get_drvdata(pdev
->dev
.parent
);
336 for (i
= 0; i
< MT6332_ID_VREG_MAX
; i
++) {
337 if (mt6332_regulators
[i
].vselctrl_reg
) {
338 if (regmap_read(mt6332
->regmap
,
339 mt6332_regulators
[i
].vselctrl_reg
,
342 "Failed to read buck ctrl\n");
346 if (regval
& mt6332_regulators
[i
].vselctrl_mask
) {
347 mt6332_regulators
[i
].desc
.vsel_reg
=
348 mt6332_regulators
[i
].vselon_reg
;
356 static int mt6332_regulator_probe(struct platform_device
*pdev
)
358 struct mt6397_chip
*mt6332
= dev_get_drvdata(pdev
->dev
.parent
);
359 struct regulator_config config
= {};
360 struct regulator_dev
*rdev
;
364 /* Query buck controller to select activated voltage register part */
365 if (mt6332_set_buck_vosel_reg(pdev
))
368 /* Read PMIC chip revision to update constraints and voltage table */
369 if (regmap_read(mt6332
->regmap
, MT6332_HWCID
, ®_value
) < 0) {
370 dev_err(&pdev
->dev
, "Failed to read Chip ID\n");
373 reg_value
&= GENMASK(7, 0);
375 dev_info(&pdev
->dev
, "Chip ID = 0x%x\n", reg_value
);
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
384 if (reg_value
== 0x10) {
385 dev_err(&pdev
->dev
, "Chip version not supported. Bailing out.\n");
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(&pdev
->dev
,
394 &mt6332_regulators
[i
].desc
, &config
);
396 dev_err(&pdev
->dev
, "failed to register %s\n",
397 mt6332_regulators
[i
].desc
.name
);
398 return PTR_ERR(rdev
);
404 static const struct platform_device_id mt6332_platform_ids
[] = {
405 {"mt6332-regulator", 0},
408 MODULE_DEVICE_TABLE(platform
, mt6332_platform_ids
);
410 static struct platform_driver mt6332_regulator_driver
= {
412 .name
= "mt6332-regulator",
413 .probe_type
= PROBE_PREFER_ASYNCHRONOUS
,
415 .probe
= mt6332_regulator_probe
,
416 .id_table
= mt6332_platform_ids
,
419 module_platform_driver(mt6332_regulator_driver
);
421 MODULE_AUTHOR("AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>");
422 MODULE_DESCRIPTION("Regulator Driver for MediaTek MT6332 PMIC");
423 MODULE_LICENSE("GPL");