424 lines · c
1// SPDX-License-Identifier: GPL-2.02//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 022#define MT6332_LDO_MODE_LP 123 24/*25 * MT6332 regulators information26 *27 * @desc: standard fields of regulator description.28 * @qi: Mask for query enable signal status of regulators29 * @vselon_reg: Register sections for hardware control mode of bucks30 * @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 unavailable33 * @status_mask: Mask for querying regulator enable status34 */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, 3200000176};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(rdev->regmap, reg, ®val);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(rdev->regmap, info->modeset_reg,224 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(rdev->regmap, info->modeset_reg, &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(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(mt6332->regmap,339 mt6332_regulators[i].vselctrl_reg,340 ®val) < 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(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(mt6332->regmap, MT6332_HWCID, ®_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 and379 * it's currently not supported in this driver. Upon detection of380 * this ID, refuse to register the regulators, as we will wrongly381 * interpret the VSEL for this revision, potentially overvolting382 * 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(&pdev->dev,394 &mt6332_regulators[i].desc, &config);395 if (IS_ERR(rdev)) {396 dev_err(&pdev->dev, "failed to register %s\n",397 mt6332_regulators[i].desc.name);398 return PTR_ERR(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