1 // SPDX-License-Identifier: GPL-2.0 2 // 3 // Copyright (c) 2022 MediaTek Inc. 4 // Copyright (c) 2022 BayLibre, SAS. 5 // Author: Chen Zhong <chen.zhong@mediatek.com> 6 // Author: Fabien Parent <fparent@baylibre.com> 7 // Author: Alexandre Mergnat <amergnat@baylibre.com> 8 // 9 // Based on mt6397-regulator.c 10 // 11 12 #include <linux/module.h> 13 #include <linux/of.h> 14 #include <linux/platform_device.h> 15 #include <linux/regmap.h> 16 #include <linux/mfd/mt6397/core.h> 17 #include <linux/mfd/mt6357/registers.h> 18 #include <linux/regulator/driver.h> 19 #include <linux/regulator/machine.h> 20 #include <linux/regulator/mt6357-regulator.h> 21 #include <linux/regulator/of_regulator.h> 22 23 /* 24 * MT6357 regulators' information 25 * 26 * @desc: standard fields of regulator description. 27 * @da_vsel_reg: Monitor register for query buck's voltage. 28 * @da_vsel_mask: Mask for query buck's voltage. 29 */ 30 struct mt6357_regulator_info { 31 struct regulator_desc desc; 32 u32 da_vsel_reg; 33 u32 da_vsel_mask; 34 }; 35 36 #define MT6357_BUCK(match, vreg, min, max, step, \ 37 volt_ranges, vosel_reg, vosel_mask, _da_vsel_mask) \ 38 [MT6357_ID_##vreg] = { \ 39 .desc = { \ 40 .name = #vreg, \ 41 .of_match = of_match_ptr(match), \ 42 .regulators_node = "regulators", \ 43 .ops = &mt6357_volt_range_ops, \ 44 .type = REGULATOR_VOLTAGE, \ 45 .id = MT6357_ID_##vreg, \ 46 .owner = THIS_MODULE, \ 47 .n_voltages = ((max) - (min)) / (step) + 1, \ 48 .linear_ranges = volt_ranges, \ 49 .n_linear_ranges = ARRAY_SIZE(volt_ranges), \ 50 .vsel_reg = vosel_reg, \ 51 .vsel_mask = vosel_mask, \ 52 .enable_reg = MT6357_BUCK_##vreg##_CON0, \ 53 .enable_mask = BIT(0), \ 54 }, \ 55 .da_vsel_reg = MT6357_BUCK_##vreg##_DBG0, \ 56 .da_vsel_mask = vosel_mask, \ 57 } 58 59 #define MT6357_LDO(match, vreg, ldo_volt_table, \ 60 enreg, vosel, vosel_mask) \ 61 [MT6357_ID_##vreg] = { \ 62 .desc = { \ 63 .name = #vreg, \ 64 .of_match = of_match_ptr(match), \ 65 .regulators_node = "regulators", \ 66 .ops = &mt6357_volt_table_ops, \ 67 .type = REGULATOR_VOLTAGE, \ 68 .id = MT6357_ID_##vreg, \ 69 .owner = THIS_MODULE, \ 70 .n_voltages = ARRAY_SIZE(ldo_volt_table), \ 71 .volt_table = ldo_volt_table, \ 72 .vsel_reg = vosel, \ 73 .vsel_mask = vosel_mask, \ 74 .enable_reg = enreg, \ 75 .enable_mask = BIT(0), \ 76 }, \ 77 } 78 79 #define MT6357_LDO1(match, vreg, min, max, step, volt_ranges, \ 80 enreg, vosel, vosel_mask) \ 81 [MT6357_ID_##vreg] = { \ 82 .desc = { \ 83 .name = #vreg, \ 84 .of_match = of_match_ptr(match), \ 85 .regulators_node = "regulators", \ 86 .ops = &mt6357_volt_range_ops, \ 87 .type = REGULATOR_VOLTAGE, \ 88 .id = MT6357_ID_##vreg, \ 89 .owner = THIS_MODULE, \ 90 .n_voltages = ((max) - (min)) / (step) + 1, \ 91 .linear_ranges = volt_ranges, \ 92 .n_linear_ranges = ARRAY_SIZE(volt_ranges), \ 93 .vsel_reg = vosel, \ 94 .vsel_mask = vosel_mask, \ 95 .enable_reg = enreg, \ 96 .enable_mask = BIT(0), \ 97 }, \ 98 .da_vsel_reg = MT6357_LDO_##vreg##_DBG0, \ 99 .da_vsel_mask = 0x7f00, \ 100 } 101 102 #define MT6357_REG_FIXED(match, vreg, volt) \ 103 [MT6357_ID_##vreg] = { \ 104 .desc = { \ 105 .name = #vreg, \ 106 .of_match = of_match_ptr(match), \ 107 .regulators_node = "regulators", \ 108 .ops = &mt6357_volt_fixed_ops, \ 109 .type = REGULATOR_VOLTAGE, \ 110 .id = MT6357_ID_##vreg, \ 111 .owner = THIS_MODULE, \ 112 .n_voltages = 1, \ 113 .enable_reg = MT6357_LDO_##vreg##_CON0, \ 114 .enable_mask = BIT(0), \ 115 .min_uV = volt, \ 116 }, \ 117 } 118 119 /** 120 * mt6357_get_buck_voltage_sel - get_voltage_sel for regmap users 121 * 122 * @rdev: regulator to operate on 123 * 124 * Regulators that use regmap for their register I/O can set the 125 * da_vsel_reg and da_vsel_mask fields in the info structure and 126 * then use this as their get_voltage_vsel operation. 127 */ 128 static int mt6357_get_buck_voltage_sel(struct regulator_dev *rdev) 129 { 130 int ret, regval; 131 struct mt6357_regulator_info *info = rdev_get_drvdata(rdev); 132 133 ret = regmap_read(rdev->regmap, info->da_vsel_reg, ®val); 134 if (ret != 0) { 135 dev_err(&rdev->dev, 136 "Failed to get mt6357 Buck %s vsel reg: %d\n", 137 info->desc.name, ret); 138 return ret; 139 } 140 141 regval &= info->da_vsel_mask; 142 regval >>= ffs(info->da_vsel_mask) - 1; 143 144 return regval; 145 } 146 147 static const struct regulator_ops mt6357_volt_range_ops = { 148 .list_voltage = regulator_list_voltage_linear_range, 149 .map_voltage = regulator_map_voltage_linear_range, 150 .set_voltage_sel = regulator_set_voltage_sel_regmap, 151 .get_voltage_sel = mt6357_get_buck_voltage_sel, 152 .set_voltage_time_sel = regulator_set_voltage_time_sel, 153 .enable = regulator_enable_regmap, 154 .disable = regulator_disable_regmap, 155 .is_enabled = regulator_is_enabled_regmap, 156 }; 157 158 static const struct regulator_ops mt6357_volt_table_ops = { 159 .list_voltage = regulator_list_voltage_table, 160 .map_voltage = regulator_map_voltage_iterate, 161 .set_voltage_sel = regulator_set_voltage_sel_regmap, 162 .get_voltage_sel = regulator_get_voltage_sel_regmap, 163 .set_voltage_time_sel = regulator_set_voltage_time_sel, 164 .enable = regulator_enable_regmap, 165 .disable = regulator_disable_regmap, 166 .is_enabled = regulator_is_enabled_regmap, 167 }; 168 169 static const struct regulator_ops mt6357_volt_fixed_ops = { 170 .list_voltage = regulator_list_voltage_linear, 171 .enable = regulator_enable_regmap, 172 .disable = regulator_disable_regmap, 173 .is_enabled = regulator_is_enabled_regmap, 174 }; 175 176 static const int vxo22_voltages[] = { 177 2200000, 178 0, 179 2400000, 180 }; 181 182 static const int vefuse_voltages[] = { 183 1200000, 184 1300000, 185 1500000, 186 0, 187 1800000, 188 0, 189 0, 190 0, 191 0, 192 2800000, 193 2900000, 194 3000000, 195 0, 196 3300000, 197 }; 198 199 static const int vcn33_voltages[] = { 200 0, 201 3300000, 202 3400000, 203 3500000, 204 }; 205 206 static const int vcama_voltages[] = { 207 0, 208 0, 209 0, 210 0, 211 0, 212 0, 213 0, 214 2500000, 215 0, 216 0, 217 2800000, 218 }; 219 220 static const int vcamd_voltages[] = { 221 0, 222 0, 223 0, 224 0, 225 1000000, 226 1100000, 227 1200000, 228 1300000, 229 0, 230 1500000, 231 0, 232 0, 233 1800000, 234 }; 235 236 static const int vldo28_voltages[] = { 237 0, 238 2800000, 239 0, 240 3000000, 241 }; 242 243 static const int vdram_voltages[] = { 244 0, 245 1100000, 246 1200000, 247 }; 248 249 static const int vsim_voltages[] = { 250 0, 251 0, 252 0, 253 1700000, 254 1800000, 255 0, 256 0, 257 0, 258 2700000, 259 0, 260 0, 261 3000000, 262 3100000, 263 }; 264 265 static const int vibr_voltages[] = { 266 1200000, 267 1300000, 268 1500000, 269 0, 270 1800000, 271 2000000, 272 0, 273 0, 274 0, 275 2800000, 276 0, 277 3000000, 278 0, 279 3300000, 280 }; 281 282 static const int vmc_voltages[] = { 283 0, 284 0, 285 0, 286 0, 287 1800000, 288 0, 289 0, 290 0, 291 0, 292 0, 293 2900000, 294 3000000, 295 0, 296 3300000, 297 }; 298 299 static const int vmch_voltages[] = { 300 0, 301 0, 302 2900000, 303 3000000, 304 0, 305 3300000, 306 }; 307 308 static const int vemc_voltages[] = { 309 0, 310 0, 311 2900000, 312 3000000, 313 0, 314 3300000, 315 }; 316 317 static const int vusb_voltages[] = { 318 0, 319 0, 320 0, 321 3000000, 322 3100000, 323 }; 324 325 static const struct linear_range buck_volt_range1[] = { 326 REGULATOR_LINEAR_RANGE(518750, 0, 0x7f, 6250), 327 }; 328 329 static const struct linear_range buck_volt_range2[] = { 330 REGULATOR_LINEAR_RANGE(500000, 0, 0x7f, 6250), 331 }; 332 333 static const struct linear_range buck_volt_range3[] = { 334 REGULATOR_LINEAR_RANGE(500000, 0, 0x3f, 50000), 335 }; 336 337 static const struct linear_range buck_volt_range4[] = { 338 REGULATOR_LINEAR_RANGE(1200000, 0, 0x7f, 12500), 339 }; 340 341 /* The array is indexed by id(MT6357_ID_XXX) */ 342 static struct mt6357_regulator_info mt6357_regulators[] = { 343 /* Bucks */ 344 MT6357_BUCK("buck-vcore", VCORE, 518750, 1312500, 6250, 345 buck_volt_range1, MT6357_BUCK_VCORE_ELR0, 0x7f, 0x7f), 346 MT6357_BUCK("buck-vproc", VPROC, 518750, 1312500, 6250, 347 buck_volt_range1, MT6357_BUCK_VPROC_ELR0, 0x7f, 0x7f), 348 MT6357_BUCK("buck-vmodem", VMODEM, 500000, 1293750, 6250, 349 buck_volt_range2, MT6357_BUCK_VMODEM_ELR0, 0x7f, 0x7f), 350 MT6357_BUCK("buck-vpa", VPA, 500000, 3650000, 50000, 351 buck_volt_range3, MT6357_BUCK_VPA_CON1, 0x3f, 0x3f), 352 MT6357_BUCK("buck-vs1", VS1, 1200000, 2787500, 12500, 353 buck_volt_range4, MT6357_BUCK_VS1_ELR0, 0x7f, 0x7f), 354 355 /* LDOs */ 356 MT6357_LDO("ldo-vcama", VCAMA, vcama_voltages, 357 MT6357_LDO_VCAMA_CON0, MT6357_VCAMA_ANA_CON0, 0xf00), 358 MT6357_LDO("ldo-vcamd", VCAMD, vcamd_voltages, 359 MT6357_LDO_VCAMD_CON0, MT6357_VCAMD_ANA_CON0, 0xf00), 360 MT6357_LDO("ldo-vcn33-bt", VCN33_BT, vcn33_voltages, 361 MT6357_LDO_VCN33_CON0_0, MT6357_VCN33_ANA_CON0, 0x300), 362 MT6357_LDO("ldo-vcn33-wifi", VCN33_WIFI, vcn33_voltages, 363 MT6357_LDO_VCN33_CON0_1, MT6357_VCN33_ANA_CON0, 0x300), 364 MT6357_LDO("ldo-vdram", VDRAM, vdram_voltages, 365 MT6357_LDO_VDRAM_CON0, MT6357_VDRAM_ELR_2, 0x300), 366 MT6357_LDO("ldo-vefuse", VEFUSE, vefuse_voltages, 367 MT6357_LDO_VEFUSE_CON0, MT6357_VEFUSE_ANA_CON0, 0xf00), 368 MT6357_LDO("ldo-vemc", VEMC, vemc_voltages, 369 MT6357_LDO_VEMC_CON0, MT6357_VEMC_ANA_CON0, 0x700), 370 MT6357_LDO("ldo-vibr", VIBR, vibr_voltages, 371 MT6357_LDO_VIBR_CON0, MT6357_VIBR_ANA_CON0, 0xf00), 372 MT6357_LDO("ldo-vldo28", VLDO28, vldo28_voltages, 373 MT6357_LDO_VLDO28_CON0_0, MT6357_VLDO28_ANA_CON0, 0x300), 374 MT6357_LDO("ldo-vmc", VMC, vmc_voltages, 375 MT6357_LDO_VMC_CON0, MT6357_VMC_ANA_CON0, 0xf00), 376 MT6357_LDO("ldo-vmch", VMCH, vmch_voltages, 377 MT6357_LDO_VMCH_CON0, MT6357_VMCH_ANA_CON0, 0x700), 378 MT6357_LDO("ldo-vsim1", VSIM1, vsim_voltages, 379 MT6357_LDO_VSIM1_CON0, MT6357_VSIM1_ANA_CON0, 0xf00), 380 MT6357_LDO("ldo-vsim2", VSIM2, vsim_voltages, 381 MT6357_LDO_VSIM2_CON0, MT6357_VSIM2_ANA_CON0, 0xf00), 382 MT6357_LDO("ldo-vusb33", VUSB33, vusb_voltages, 383 MT6357_LDO_VUSB33_CON0_0, MT6357_VUSB33_ANA_CON0, 0x700), 384 MT6357_LDO("ldo-vxo22", VXO22, vxo22_voltages, 385 MT6357_LDO_VXO22_CON0, MT6357_VXO22_ANA_CON0, 0x300), 386 387 MT6357_LDO1("ldo-vsram-proc", VSRAM_PROC, 518750, 1312500, 6250, 388 buck_volt_range1, MT6357_LDO_VSRAM_PROC_CON0, 389 MT6357_LDO_VSRAM_CON0, 0x7f00), 390 MT6357_LDO1("ldo-vsram-others", VSRAM_OTHERS, 518750, 1312500, 6250, 391 buck_volt_range1, MT6357_LDO_VSRAM_OTHERS_CON0, 392 MT6357_LDO_VSRAM_CON1, 0x7f00), 393 394 MT6357_REG_FIXED("ldo-vaud28", VAUD28, 2800000), 395 MT6357_REG_FIXED("ldo-vaux18", VAUX18, 1800000), 396 MT6357_REG_FIXED("ldo-vcamio18", VCAMIO, 1800000), 397 MT6357_REG_FIXED("ldo-vcn18", VCN18, 1800000), 398 MT6357_REG_FIXED("ldo-vcn28", VCN28, 2800000), 399 MT6357_REG_FIXED("ldo-vfe28", VFE28, 2800000), 400 MT6357_REG_FIXED("ldo-vio18", VIO18, 1800000), 401 MT6357_REG_FIXED("ldo-vio28", VIO28, 2800000), 402 MT6357_REG_FIXED("ldo-vrf12", VRF12, 1200000), 403 MT6357_REG_FIXED("ldo-vrf18", VRF18, 1800000), 404 }; 405 406 static int mt6357_regulator_probe(struct platform_device *pdev) 407 { 408 struct mt6397_chip *mt6357 = dev_get_drvdata(pdev->dev.parent); 409 struct regulator_config config = {}; 410 struct regulator_dev *rdev; 411 int i; 412 413 pdev->dev.of_node = pdev->dev.parent->of_node; 414 415 for (i = 0; i < MT6357_MAX_REGULATOR; i++) { 416 config.dev = &pdev->dev; 417 config.driver_data = &mt6357_regulators[i]; 418 config.regmap = mt6357->regmap; 419 420 rdev = devm_regulator_register(&pdev->dev, 421 &mt6357_regulators[i].desc, 422 &config); 423 if (IS_ERR(rdev)) { 424 dev_err(&pdev->dev, "failed to register %s\n", 425 mt6357_regulators[i].desc.name); 426 return PTR_ERR(rdev); 427 } 428 } 429 430 return 0; 431 } 432 433 static const struct platform_device_id mt6357_platform_ids[] = { 434 { "mt6357-regulator" }, 435 { /* sentinel */ }, 436 }; 437 MODULE_DEVICE_TABLE(platform, mt6357_platform_ids); 438 439 static struct platform_driver mt6357_regulator_driver = { 440 .driver = { 441 .name = "mt6357-regulator", 442 }, 443 .probe = mt6357_regulator_probe, 444 .id_table = mt6357_platform_ids, 445 }; 446 447 module_platform_driver(mt6357_regulator_driver); 448 449 MODULE_AUTHOR("Chen Zhong <chen.zhong@mediatek.com>"); 450 MODULE_AUTHOR("Fabien Parent <fabien.parent@linaro.org>"); 451 MODULE_AUTHOR("Alexandre Mergnat <amergnat@baylibre.com>"); 452 MODULE_DESCRIPTION("Regulator Driver for MediaTek MT6357 PMIC"); 453 MODULE_LICENSE("GPL"); 454