421 lines · c
1// SPDX-License-Identifier: GPL-2.02//3// Copyright (c) 2014 MediaTek Inc.4// Author: Flora Fu <flora.fu@mediatek.com>5 6#include <linux/module.h>7#include <linux/of.h>8#include <linux/platform_device.h>9#include <linux/regmap.h>10#include <linux/mfd/mt6397/core.h>11#include <linux/mfd/mt6397/registers.h>12#include <linux/regulator/driver.h>13#include <linux/regulator/machine.h>14#include <linux/regulator/mt6397-regulator.h>15#include <linux/regulator/of_regulator.h>16#include <dt-bindings/regulator/mediatek,mt6397-regulator.h>17 18/*19 * MT6397 regulators' information20 *21 * @desc: standard fields of regulator description.22 * @qi: Mask for query enable signal status of regulators23 * @vselon_reg: Register sections for hardware control mode of bucks24 * @vselctrl_reg: Register for controlling the buck control mode.25 * @vselctrl_mask: Mask for query buck's voltage control mode.26 */27struct mt6397_regulator_info {28 struct regulator_desc desc;29 u32 qi;30 u32 vselon_reg;31 u32 vselctrl_reg;32 u32 vselctrl_mask;33 u32 modeset_reg;34 u32 modeset_mask;35};36 37#define MT6397_BUCK(match, vreg, min, max, step, volt_ranges, enreg, \38 vosel, vosel_mask, voselon, vosel_ctrl, _modeset_reg, \39 _modeset_shift) \40[MT6397_ID_##vreg] = { \41 .desc = { \42 .name = #vreg, \43 .of_match = of_match_ptr(match), \44 .ops = &mt6397_volt_range_ops, \45 .type = REGULATOR_VOLTAGE, \46 .id = MT6397_ID_##vreg, \47 .owner = THIS_MODULE, \48 .n_voltages = (max - min)/step + 1, \49 .linear_ranges = volt_ranges, \50 .n_linear_ranges = ARRAY_SIZE(volt_ranges), \51 .vsel_reg = vosel, \52 .vsel_mask = vosel_mask, \53 .enable_reg = enreg, \54 .enable_mask = BIT(0), \55 .of_map_mode = mt6397_map_mode, \56 }, \57 .qi = BIT(13), \58 .vselon_reg = voselon, \59 .vselctrl_reg = vosel_ctrl, \60 .vselctrl_mask = BIT(1), \61 .modeset_reg = _modeset_reg, \62 .modeset_mask = BIT(_modeset_shift), \63}64 65#define MT6397_LDO(match, vreg, ldo_volt_table, enreg, enbit, vosel, \66 vosel_mask) \67[MT6397_ID_##vreg] = { \68 .desc = { \69 .name = #vreg, \70 .of_match = of_match_ptr(match), \71 .ops = &mt6397_volt_table_ops, \72 .type = REGULATOR_VOLTAGE, \73 .id = MT6397_ID_##vreg, \74 .owner = THIS_MODULE, \75 .n_voltages = ARRAY_SIZE(ldo_volt_table), \76 .volt_table = ldo_volt_table, \77 .vsel_reg = vosel, \78 .vsel_mask = vosel_mask, \79 .enable_reg = enreg, \80 .enable_mask = BIT(enbit), \81 }, \82 .qi = BIT(15), \83}84 85#define MT6397_REG_FIXED(match, vreg, enreg, enbit, volt) \86[MT6397_ID_##vreg] = { \87 .desc = { \88 .name = #vreg, \89 .of_match = of_match_ptr(match), \90 .ops = &mt6397_volt_fixed_ops, \91 .type = REGULATOR_VOLTAGE, \92 .id = MT6397_ID_##vreg, \93 .owner = THIS_MODULE, \94 .n_voltages = 1, \95 .enable_reg = enreg, \96 .enable_mask = BIT(enbit), \97 .min_uV = volt, \98 }, \99 .qi = BIT(15), \100}101 102static const struct linear_range buck_volt_range1[] = {103 REGULATOR_LINEAR_RANGE(700000, 0, 0x7f, 6250),104};105 106static const struct linear_range buck_volt_range2[] = {107 REGULATOR_LINEAR_RANGE(800000, 0, 0x7f, 6250),108};109 110static const struct linear_range buck_volt_range3[] = {111 REGULATOR_LINEAR_RANGE(1500000, 0, 0x1f, 20000),112};113 114static const unsigned int ldo_volt_table1[] = {115 1500000, 1800000, 2500000, 2800000,116};117 118static const unsigned int ldo_volt_table2[] = {119 1800000, 3300000,120};121 122static const unsigned int ldo_volt_table3[] = {123 3000000, 3300000,124};125 126static const unsigned int ldo_volt_table4[] = {127 1220000, 1300000, 1500000, 1800000, 2500000, 2800000, 3000000, 3300000,128};129 130static const unsigned int ldo_volt_table5[] = {131 1200000, 1300000, 1500000, 1800000, 2500000, 2800000, 3000000, 3300000,132};133 134static const unsigned int ldo_volt_table5_v2[] = {135 1200000, 1000000, 1500000, 1800000, 2500000, 2800000, 3000000, 3300000,136};137 138static const unsigned int ldo_volt_table6[] = {139 1200000, 1300000, 1500000, 1800000, 2500000, 2800000, 3000000, 2000000,140};141 142static const unsigned int ldo_volt_table7[] = {143 1300000, 1500000, 1800000, 2000000, 2500000, 2800000, 3000000, 3300000,144};145 146static unsigned int mt6397_map_mode(unsigned int mode)147{148 switch (mode) {149 case MT6397_BUCK_MODE_AUTO:150 return REGULATOR_MODE_NORMAL;151 case MT6397_BUCK_MODE_FORCE_PWM:152 return REGULATOR_MODE_FAST;153 default:154 return REGULATOR_MODE_INVALID;155 }156}157 158static int mt6397_regulator_set_mode(struct regulator_dev *rdev,159 unsigned int mode)160{161 struct mt6397_regulator_info *info = rdev_get_drvdata(rdev);162 int ret, val;163 164 switch (mode) {165 case REGULATOR_MODE_FAST:166 val = MT6397_BUCK_MODE_FORCE_PWM;167 break;168 case REGULATOR_MODE_NORMAL:169 val = MT6397_BUCK_MODE_AUTO;170 break;171 default:172 ret = -EINVAL;173 goto err_mode;174 }175 176 dev_dbg(&rdev->dev, "mt6397 buck set_mode %#x, %#x, %#x\n",177 info->modeset_reg, info->modeset_mask, val);178 179 val <<= ffs(info->modeset_mask) - 1;180 181 ret = regmap_update_bits(rdev->regmap, info->modeset_reg,182 info->modeset_mask, val);183err_mode:184 if (ret != 0) {185 dev_err(&rdev->dev,186 "Failed to set mt6397 buck mode: %d\n", ret);187 return ret;188 }189 190 return 0;191}192 193static unsigned int mt6397_regulator_get_mode(struct regulator_dev *rdev)194{195 struct mt6397_regulator_info *info = rdev_get_drvdata(rdev);196 int ret, regval;197 198 ret = regmap_read(rdev->regmap, info->modeset_reg, ®val);199 if (ret != 0) {200 dev_err(&rdev->dev,201 "Failed to get mt6397 buck mode: %d\n", ret);202 return ret;203 }204 205 regval &= info->modeset_mask;206 regval >>= ffs(info->modeset_mask) - 1;207 208 switch (regval) {209 case MT6397_BUCK_MODE_AUTO:210 return REGULATOR_MODE_NORMAL;211 case MT6397_BUCK_MODE_FORCE_PWM:212 return REGULATOR_MODE_FAST;213 default:214 return -EINVAL;215 }216}217 218static int mt6397_get_status(struct regulator_dev *rdev)219{220 int ret;221 u32 regval;222 struct mt6397_regulator_info *info = rdev_get_drvdata(rdev);223 224 ret = regmap_read(rdev->regmap, info->desc.enable_reg, ®val);225 if (ret != 0) {226 dev_err(&rdev->dev, "Failed to get enable reg: %d\n", ret);227 return ret;228 }229 230 return (regval & info->qi) ? REGULATOR_STATUS_ON : REGULATOR_STATUS_OFF;231}232 233static const struct regulator_ops mt6397_volt_range_ops = {234 .list_voltage = regulator_list_voltage_linear_range,235 .map_voltage = regulator_map_voltage_linear_range,236 .set_voltage_sel = regulator_set_voltage_sel_regmap,237 .get_voltage_sel = regulator_get_voltage_sel_regmap,238 .set_voltage_time_sel = regulator_set_voltage_time_sel,239 .enable = regulator_enable_regmap,240 .disable = regulator_disable_regmap,241 .is_enabled = regulator_is_enabled_regmap,242 .get_status = mt6397_get_status,243 .set_mode = mt6397_regulator_set_mode,244 .get_mode = mt6397_regulator_get_mode,245};246 247static const struct regulator_ops mt6397_volt_table_ops = {248 .list_voltage = regulator_list_voltage_table,249 .map_voltage = regulator_map_voltage_iterate,250 .set_voltage_sel = regulator_set_voltage_sel_regmap,251 .get_voltage_sel = regulator_get_voltage_sel_regmap,252 .set_voltage_time_sel = regulator_set_voltage_time_sel,253 .enable = regulator_enable_regmap,254 .disable = regulator_disable_regmap,255 .is_enabled = regulator_is_enabled_regmap,256 .get_status = mt6397_get_status,257};258 259static const struct regulator_ops mt6397_volt_fixed_ops = {260 .list_voltage = regulator_list_voltage_linear,261 .enable = regulator_enable_regmap,262 .disable = regulator_disable_regmap,263 .is_enabled = regulator_is_enabled_regmap,264 .get_status = mt6397_get_status,265};266 267/* The array is indexed by id(MT6397_ID_XXX) */268static struct mt6397_regulator_info mt6397_regulators[] = {269 MT6397_BUCK("buck_vpca15", VPCA15, 700000, 1493750, 6250,270 buck_volt_range1, MT6397_VCA15_CON7, MT6397_VCA15_CON9, 0x7f,271 MT6397_VCA15_CON10, MT6397_VCA15_CON5, MT6397_VCA15_CON2, 11),272 MT6397_BUCK("buck_vpca7", VPCA7, 700000, 1493750, 6250,273 buck_volt_range1, MT6397_VPCA7_CON7, MT6397_VPCA7_CON9, 0x7f,274 MT6397_VPCA7_CON10, MT6397_VPCA7_CON5, MT6397_VPCA7_CON2, 8),275 MT6397_BUCK("buck_vsramca15", VSRAMCA15, 700000, 1493750, 6250,276 buck_volt_range1, MT6397_VSRMCA15_CON7, MT6397_VSRMCA15_CON9,277 0x7f, MT6397_VSRMCA15_CON10, MT6397_VSRMCA15_CON5,278 MT6397_VSRMCA15_CON2, 8),279 MT6397_BUCK("buck_vsramca7", VSRAMCA7, 700000, 1493750, 6250,280 buck_volt_range1, MT6397_VSRMCA7_CON7, MT6397_VSRMCA7_CON9,281 0x7f, MT6397_VSRMCA7_CON10, MT6397_VSRMCA7_CON5,282 MT6397_VSRMCA7_CON2, 8),283 MT6397_BUCK("buck_vcore", VCORE, 700000, 1493750, 6250,284 buck_volt_range1, MT6397_VCORE_CON7, MT6397_VCORE_CON9, 0x7f,285 MT6397_VCORE_CON10, MT6397_VCORE_CON5, MT6397_VCORE_CON2, 8),286 MT6397_BUCK("buck_vgpu", VGPU, 700000, 1493750, 6250, buck_volt_range1,287 MT6397_VGPU_CON7, MT6397_VGPU_CON9, 0x7f,288 MT6397_VGPU_CON10, MT6397_VGPU_CON5, MT6397_VGPU_CON2, 8),289 MT6397_BUCK("buck_vdrm", VDRM, 800000, 1593750, 6250, buck_volt_range2,290 MT6397_VDRM_CON7, MT6397_VDRM_CON9, 0x7f,291 MT6397_VDRM_CON10, MT6397_VDRM_CON5, MT6397_VDRM_CON2, 8),292 MT6397_BUCK("buck_vio18", VIO18, 1500000, 2120000, 20000,293 buck_volt_range3, MT6397_VIO18_CON7, MT6397_VIO18_CON9, 0x1f,294 MT6397_VIO18_CON10, MT6397_VIO18_CON5, MT6397_VIO18_CON2, 8),295 MT6397_REG_FIXED("ldo_vtcxo", VTCXO, MT6397_ANALDO_CON0, 10, 2800000),296 MT6397_REG_FIXED("ldo_va28", VA28, MT6397_ANALDO_CON1, 14, 2800000),297 MT6397_LDO("ldo_vcama", VCAMA, ldo_volt_table1,298 MT6397_ANALDO_CON2, 15, MT6397_ANALDO_CON6, 0xC0),299 MT6397_REG_FIXED("ldo_vio28", VIO28, MT6397_DIGLDO_CON0, 14, 2800000),300 MT6397_REG_FIXED("ldo_vusb", VUSB, MT6397_DIGLDO_CON1, 14, 3300000),301 MT6397_LDO("ldo_vmc", VMC, ldo_volt_table2,302 MT6397_DIGLDO_CON2, 12, MT6397_DIGLDO_CON29, 0x10),303 MT6397_LDO("ldo_vmch", VMCH, ldo_volt_table3,304 MT6397_DIGLDO_CON3, 14, MT6397_DIGLDO_CON17, 0x80),305 MT6397_LDO("ldo_vemc3v3", VEMC3V3, ldo_volt_table3,306 MT6397_DIGLDO_CON4, 14, MT6397_DIGLDO_CON18, 0x10),307 MT6397_LDO("ldo_vgp1", VGP1, ldo_volt_table4,308 MT6397_DIGLDO_CON5, 15, MT6397_DIGLDO_CON19, 0xE0),309 MT6397_LDO("ldo_vgp2", VGP2, ldo_volt_table5,310 MT6397_DIGLDO_CON6, 15, MT6397_DIGLDO_CON20, 0xE0),311 MT6397_LDO("ldo_vgp3", VGP3, ldo_volt_table5,312 MT6397_DIGLDO_CON7, 15, MT6397_DIGLDO_CON21, 0xE0),313 MT6397_LDO("ldo_vgp4", VGP4, ldo_volt_table5,314 MT6397_DIGLDO_CON8, 15, MT6397_DIGLDO_CON22, 0xE0),315 MT6397_LDO("ldo_vgp5", VGP5, ldo_volt_table6,316 MT6397_DIGLDO_CON9, 15, MT6397_DIGLDO_CON23, 0xE0),317 MT6397_LDO("ldo_vgp6", VGP6, ldo_volt_table5,318 MT6397_DIGLDO_CON10, 15, MT6397_DIGLDO_CON33, 0xE0),319 MT6397_LDO("ldo_vibr", VIBR, ldo_volt_table7,320 MT6397_DIGLDO_CON24, 15, MT6397_DIGLDO_CON25, 0xE00),321};322 323static int mt6397_set_buck_vosel_reg(struct platform_device *pdev)324{325 struct mt6397_chip *mt6397 = dev_get_drvdata(pdev->dev.parent);326 int i;327 u32 regval;328 329 for (i = 0; i < MT6397_MAX_REGULATOR; i++) {330 if (mt6397_regulators[i].vselctrl_reg) {331 if (regmap_read(mt6397->regmap,332 mt6397_regulators[i].vselctrl_reg,333 ®val) < 0) {334 dev_err(&pdev->dev,335 "Failed to read buck ctrl\n");336 return -EIO;337 }338 339 if (regval & mt6397_regulators[i].vselctrl_mask) {340 mt6397_regulators[i].desc.vsel_reg =341 mt6397_regulators[i].vselon_reg;342 }343 }344 }345 346 return 0;347}348 349static int mt6397_regulator_probe(struct platform_device *pdev)350{351 struct mt6397_chip *mt6397 = dev_get_drvdata(pdev->dev.parent);352 struct regulator_config config = {};353 struct regulator_dev *rdev;354 int i;355 u32 reg_value, version;356 357 /* Query buck controller to select activated voltage register part */358 if (mt6397_set_buck_vosel_reg(pdev))359 return -EIO;360 361 /* Read PMIC chip revision to update constraints and voltage table */362 if (regmap_read(mt6397->regmap, MT6397_CID, ®_value) < 0) {363 dev_err(&pdev->dev, "Failed to read Chip ID\n");364 return -EIO;365 }366 dev_info(&pdev->dev, "Chip ID = 0x%x\n", reg_value);367 368 version = (reg_value & 0xFF);369 switch (version) {370 case MT6397_REGULATOR_ID91:371 mt6397_regulators[MT6397_ID_VGP2].desc.volt_table =372 ldo_volt_table5_v2;373 break;374 default:375 break;376 }377 378 for (i = 0; i < MT6397_MAX_REGULATOR; i++) {379 config.dev = &pdev->dev;380 config.driver_data = &mt6397_regulators[i];381 config.regmap = mt6397->regmap;382 rdev = devm_regulator_register(&pdev->dev,383 &mt6397_regulators[i].desc, &config);384 if (IS_ERR(rdev)) {385 dev_err(&pdev->dev, "failed to register %s\n",386 mt6397_regulators[i].desc.name);387 return PTR_ERR(rdev);388 }389 }390 391 return 0;392}393 394static const struct platform_device_id mt6397_platform_ids[] = {395 {"mt6397-regulator", 0},396 { /* sentinel */ },397};398MODULE_DEVICE_TABLE(platform, mt6397_platform_ids);399 400static const struct of_device_id mt6397_of_match[] __maybe_unused = {401 { .compatible = "mediatek,mt6397-regulator", },402 { /* sentinel */ },403};404MODULE_DEVICE_TABLE(of, mt6397_of_match);405 406static struct platform_driver mt6397_regulator_driver = {407 .driver = {408 .name = "mt6397-regulator",409 .probe_type = PROBE_PREFER_ASYNCHRONOUS,410 .of_match_table = of_match_ptr(mt6397_of_match),411 },412 .probe = mt6397_regulator_probe,413 .id_table = mt6397_platform_ids,414};415 416module_platform_driver(mt6397_regulator_driver);417 418MODULE_AUTHOR("Flora Fu <flora.fu@mediatek.com>");419MODULE_DESCRIPTION("Regulator Driver for MediaTek MT6397 PMIC");420MODULE_LICENSE("GPL");421