linux/drivers/regulator/mt6323-regulator.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2//
   3// Copyright (c) 2016 MediaTek Inc.
   4// Author: Chen Zhong <chen.zhong@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/mt6323/registers.h>
  12#include <linux/regulator/driver.h>
  13#include <linux/regulator/machine.h>
  14#include <linux/regulator/mt6323-regulator.h>
  15#include <linux/regulator/of_regulator.h>
  16
  17#define MT6323_LDO_MODE_NORMAL  0
  18#define MT6323_LDO_MODE_LP      1
  19
  20/*
  21 * MT6323 regulators' information
  22 *
  23 * @desc: standard fields of regulator description.
  24 * @qi: Mask for query enable signal status of regulators
  25 * @vselon_reg: Register sections for hardware control mode of bucks
  26 * @vselctrl_reg: Register for controlling the buck control mode.
  27 * @vselctrl_mask: Mask for query buck's voltage control mode.
  28 */
  29struct mt6323_regulator_info {
  30        struct regulator_desc desc;
  31        u32 qi;
  32        u32 vselon_reg;
  33        u32 vselctrl_reg;
  34        u32 vselctrl_mask;
  35        u32 modeset_reg;
  36        u32 modeset_mask;
  37};
  38
  39#define MT6323_BUCK(match, vreg, min, max, step, volt_ranges, enreg,    \
  40                vosel, vosel_mask, voselon, vosel_ctrl)                 \
  41[MT6323_ID_##vreg] = {                                                  \
  42        .desc = {                                                       \
  43                .name = #vreg,                                          \
  44                .of_match = of_match_ptr(match),                        \
  45                .ops = &mt6323_volt_range_ops,                          \
  46                .type = REGULATOR_VOLTAGE,                              \
  47                .id = MT6323_ID_##vreg,                                 \
  48                .owner = THIS_MODULE,                                   \
  49                .n_voltages = (max - min)/step + 1,                     \
  50                .linear_ranges = volt_ranges,                           \
  51                .n_linear_ranges = ARRAY_SIZE(volt_ranges),             \
  52                .vsel_reg = vosel,                                      \
  53                .vsel_mask = vosel_mask,                                \
  54                .enable_reg = enreg,                                    \
  55                .enable_mask = BIT(0),                                  \
  56        },                                                              \
  57        .qi = BIT(13),                                                  \
  58        .vselon_reg = voselon,                                          \
  59        .vselctrl_reg = vosel_ctrl,                                     \
  60        .vselctrl_mask = BIT(1),                                        \
  61}
  62
  63#define MT6323_LDO(match, vreg, ldo_volt_table, enreg, enbit, vosel,    \
  64                vosel_mask, _modeset_reg, _modeset_mask)                \
  65[MT6323_ID_##vreg] = {                                                  \
  66        .desc = {                                                       \
  67                .name = #vreg,                                          \
  68                .of_match = of_match_ptr(match),                        \
  69                .ops = &mt6323_volt_table_ops,                          \
  70                .type = REGULATOR_VOLTAGE,                              \
  71                .id = MT6323_ID_##vreg,                                 \
  72                .owner = THIS_MODULE,                                   \
  73                .n_voltages = ARRAY_SIZE(ldo_volt_table),               \
  74                .volt_table = ldo_volt_table,                           \
  75                .vsel_reg = vosel,                                      \
  76                .vsel_mask = vosel_mask,                                \
  77                .enable_reg = enreg,                                    \
  78                .enable_mask = BIT(enbit),                              \
  79        },                                                              \
  80        .qi = BIT(15),                                                  \
  81        .modeset_reg = _modeset_reg,                                    \
  82        .modeset_mask = _modeset_mask,                                  \
  83}
  84
  85#define MT6323_REG_FIXED(match, vreg, enreg, enbit, volt,               \
  86                _modeset_reg, _modeset_mask)                            \
  87[MT6323_ID_##vreg] = {                                                  \
  88        .desc = {                                                       \
  89                .name = #vreg,                                          \
  90                .of_match = of_match_ptr(match),                        \
  91                .ops = &mt6323_volt_fixed_ops,                          \
  92                .type = REGULATOR_VOLTAGE,                              \
  93                .id = MT6323_ID_##vreg,                                 \
  94                .owner = THIS_MODULE,                                   \
  95                .n_voltages = 1,                                        \
  96                .enable_reg = enreg,                                    \
  97                .enable_mask = BIT(enbit),                              \
  98                .min_uV = volt,                                         \
  99        },                                                              \
 100        .qi = BIT(15),                                                  \
 101        .modeset_reg = _modeset_reg,                                    \
 102        .modeset_mask = _modeset_mask,                                  \
 103}
 104
 105static const struct regulator_linear_range buck_volt_range1[] = {
 106        REGULATOR_LINEAR_RANGE(700000, 0, 0x7f, 6250),
 107};
 108
 109static const struct regulator_linear_range buck_volt_range2[] = {
 110        REGULATOR_LINEAR_RANGE(1400000, 0, 0x7f, 12500),
 111};
 112
 113static const struct regulator_linear_range buck_volt_range3[] = {
 114        REGULATOR_LINEAR_RANGE(500000, 0, 0x3f, 50000),
 115};
 116
 117static const unsigned int ldo_volt_table1[] = {
 118        3300000, 3400000, 3500000, 3600000,
 119};
 120
 121static const unsigned int ldo_volt_table2[] = {
 122        1500000, 1800000, 2500000, 2800000,
 123};
 124
 125static const unsigned int ldo_volt_table3[] = {
 126        1800000, 3300000,
 127};
 128
 129static const unsigned int ldo_volt_table4[] = {
 130        3000000, 3300000,
 131};
 132
 133static const unsigned int ldo_volt_table5[] = {
 134        1200000, 1300000, 1500000, 1800000, 2000000, 2800000, 3000000, 3300000,
 135};
 136
 137static const unsigned int ldo_volt_table6[] = {
 138        1200000, 1300000, 1500000, 1800000, 2500000, 2800000, 3000000, 2000000,
 139};
 140
 141static const unsigned int ldo_volt_table7[] = {
 142        1200000, 1300000, 1500000, 1800000,
 143};
 144
 145static const unsigned int ldo_volt_table8[] = {
 146        1800000, 3000000,
 147};
 148
 149static const unsigned int ldo_volt_table9[] = {
 150        1200000, 1350000, 1500000, 1800000,
 151};
 152
 153static const unsigned int ldo_volt_table10[] = {
 154        1200000, 1300000, 1500000, 1800000,
 155};
 156
 157static int mt6323_get_status(struct regulator_dev *rdev)
 158{
 159        int ret;
 160        u32 regval;
 161        struct mt6323_regulator_info *info = rdev_get_drvdata(rdev);
 162
 163        ret = regmap_read(rdev->regmap, info->desc.enable_reg, &regval);
 164        if (ret != 0) {
 165                dev_err(&rdev->dev, "Failed to get enable reg: %d\n", ret);
 166                return ret;
 167        }
 168
 169        return (regval & info->qi) ? REGULATOR_STATUS_ON : REGULATOR_STATUS_OFF;
 170}
 171
 172static int mt6323_ldo_set_mode(struct regulator_dev *rdev, unsigned int mode)
 173{
 174        int ret, val = 0;
 175        struct mt6323_regulator_info *info = rdev_get_drvdata(rdev);
 176
 177        if (!info->modeset_mask) {
 178                dev_err(&rdev->dev, "regulator %s doesn't support set_mode\n",
 179                        info->desc.name);
 180                return -EINVAL;
 181        }
 182
 183        switch (mode) {
 184        case REGULATOR_MODE_STANDBY:
 185                val = MT6323_LDO_MODE_LP;
 186                break;
 187        case REGULATOR_MODE_NORMAL:
 188                val = MT6323_LDO_MODE_NORMAL;
 189                break;
 190        default:
 191                return -EINVAL;
 192        }
 193
 194        val <<= ffs(info->modeset_mask) - 1;
 195
 196        ret = regmap_update_bits(rdev->regmap, info->modeset_reg,
 197                                  info->modeset_mask, val);
 198
 199        return ret;
 200}
 201
 202static unsigned int mt6323_ldo_get_mode(struct regulator_dev *rdev)
 203{
 204        unsigned int val;
 205        unsigned int mode;
 206        int ret;
 207        struct mt6323_regulator_info *info = rdev_get_drvdata(rdev);
 208
 209        if (!info->modeset_mask) {
 210                dev_err(&rdev->dev, "regulator %s doesn't support get_mode\n",
 211                        info->desc.name);
 212                return -EINVAL;
 213        }
 214
 215        ret = regmap_read(rdev->regmap, info->modeset_reg, &val);
 216        if (ret < 0)
 217                return ret;
 218
 219        val &= info->modeset_mask;
 220        val >>= ffs(info->modeset_mask) - 1;
 221
 222        if (val & 0x1)
 223                mode = REGULATOR_MODE_STANDBY;
 224        else
 225                mode = REGULATOR_MODE_NORMAL;
 226
 227        return mode;
 228}
 229
 230static const struct regulator_ops mt6323_volt_range_ops = {
 231        .list_voltage = regulator_list_voltage_linear_range,
 232        .map_voltage = regulator_map_voltage_linear_range,
 233        .set_voltage_sel = regulator_set_voltage_sel_regmap,
 234        .get_voltage_sel = regulator_get_voltage_sel_regmap,
 235        .set_voltage_time_sel = regulator_set_voltage_time_sel,
 236        .enable = regulator_enable_regmap,
 237        .disable = regulator_disable_regmap,
 238        .is_enabled = regulator_is_enabled_regmap,
 239        .get_status = mt6323_get_status,
 240};
 241
 242static const struct regulator_ops mt6323_volt_table_ops = {
 243        .list_voltage = regulator_list_voltage_table,
 244        .map_voltage = regulator_map_voltage_iterate,
 245        .set_voltage_sel = regulator_set_voltage_sel_regmap,
 246        .get_voltage_sel = regulator_get_voltage_sel_regmap,
 247        .set_voltage_time_sel = regulator_set_voltage_time_sel,
 248        .enable = regulator_enable_regmap,
 249        .disable = regulator_disable_regmap,
 250        .is_enabled = regulator_is_enabled_regmap,
 251        .get_status = mt6323_get_status,
 252        .set_mode = mt6323_ldo_set_mode,
 253        .get_mode = mt6323_ldo_get_mode,
 254};
 255
 256static const struct regulator_ops mt6323_volt_fixed_ops = {
 257        .list_voltage = regulator_list_voltage_linear,
 258        .enable = regulator_enable_regmap,
 259        .disable = regulator_disable_regmap,
 260        .is_enabled = regulator_is_enabled_regmap,
 261        .get_status = mt6323_get_status,
 262        .set_mode = mt6323_ldo_set_mode,
 263        .get_mode = mt6323_ldo_get_mode,
 264};
 265
 266/* The array is indexed by id(MT6323_ID_XXX) */
 267static struct mt6323_regulator_info mt6323_regulators[] = {
 268        MT6323_BUCK("buck_vproc", VPROC, 700000, 1493750, 6250,
 269                buck_volt_range1, MT6323_VPROC_CON7, MT6323_VPROC_CON9, 0x7f,
 270                MT6323_VPROC_CON10, MT6323_VPROC_CON5),
 271        MT6323_BUCK("buck_vsys", VSYS, 1400000, 2987500, 12500,
 272                buck_volt_range2, MT6323_VSYS_CON7, MT6323_VSYS_CON9, 0x7f,
 273                MT6323_VSYS_CON10, MT6323_VSYS_CON5),
 274        MT6323_BUCK("buck_vpa", VPA, 500000, 3650000, 50000,
 275                buck_volt_range3, MT6323_VPA_CON7, MT6323_VPA_CON9,
 276                0x3f, MT6323_VPA_CON10, MT6323_VPA_CON5),
 277        MT6323_REG_FIXED("ldo_vtcxo", VTCXO, MT6323_ANALDO_CON1, 10, 2800000,
 278                MT6323_ANALDO_CON1, 0x2),
 279        MT6323_REG_FIXED("ldo_vcn28", VCN28, MT6323_ANALDO_CON19, 12, 2800000,
 280                MT6323_ANALDO_CON20, 0x2),
 281        MT6323_LDO("ldo_vcn33_bt", VCN33_BT, ldo_volt_table1,
 282                MT6323_ANALDO_CON16, 7, MT6323_ANALDO_CON16, 0xC,
 283                MT6323_ANALDO_CON21, 0x2),
 284        MT6323_LDO("ldo_vcn33_wifi", VCN33_WIFI, ldo_volt_table1,
 285                MT6323_ANALDO_CON17, 12, MT6323_ANALDO_CON16, 0xC,
 286                MT6323_ANALDO_CON21, 0x2),
 287        MT6323_REG_FIXED("ldo_va", VA, MT6323_ANALDO_CON2, 14, 2800000,
 288                MT6323_ANALDO_CON2, 0x2),
 289        MT6323_LDO("ldo_vcama", VCAMA, ldo_volt_table2,
 290                MT6323_ANALDO_CON4, 15, MT6323_ANALDO_CON10, 0x60, -1, 0),
 291        MT6323_REG_FIXED("ldo_vio28", VIO28, MT6323_DIGLDO_CON0, 14, 2800000,
 292                MT6323_DIGLDO_CON0, 0x2),
 293        MT6323_REG_FIXED("ldo_vusb", VUSB, MT6323_DIGLDO_CON2, 14, 3300000,
 294                MT6323_DIGLDO_CON2, 0x2),
 295        MT6323_LDO("ldo_vmc", VMC, ldo_volt_table3,
 296                MT6323_DIGLDO_CON3, 12, MT6323_DIGLDO_CON24, 0x10,
 297                MT6323_DIGLDO_CON3, 0x2),
 298        MT6323_LDO("ldo_vmch", VMCH, ldo_volt_table4,
 299                MT6323_DIGLDO_CON5, 14, MT6323_DIGLDO_CON26, 0x80,
 300                MT6323_DIGLDO_CON5, 0x2),
 301        MT6323_LDO("ldo_vemc3v3", VEMC3V3, ldo_volt_table4,
 302                MT6323_DIGLDO_CON6, 14, MT6323_DIGLDO_CON27, 0x80,
 303                MT6323_DIGLDO_CON6, 0x2),
 304        MT6323_LDO("ldo_vgp1", VGP1, ldo_volt_table5,
 305                MT6323_DIGLDO_CON7, 15, MT6323_DIGLDO_CON28, 0xE0,
 306                MT6323_DIGLDO_CON7, 0x2),
 307        MT6323_LDO("ldo_vgp2", VGP2, ldo_volt_table6,
 308                MT6323_DIGLDO_CON8, 15, MT6323_DIGLDO_CON29, 0xE0,
 309                MT6323_DIGLDO_CON8, 0x2),
 310        MT6323_LDO("ldo_vgp3", VGP3, ldo_volt_table7,
 311                MT6323_DIGLDO_CON9, 15, MT6323_DIGLDO_CON30, 0x60,
 312                MT6323_DIGLDO_CON9, 0x2),
 313        MT6323_REG_FIXED("ldo_vcn18", VCN18, MT6323_DIGLDO_CON11, 14, 1800000,
 314                MT6323_DIGLDO_CON11, 0x2),
 315        MT6323_LDO("ldo_vsim1", VSIM1, ldo_volt_table8,
 316                MT6323_DIGLDO_CON13, 15, MT6323_DIGLDO_CON34, 0x20,
 317                MT6323_DIGLDO_CON13, 0x2),
 318        MT6323_LDO("ldo_vsim2", VSIM2, ldo_volt_table8,
 319                MT6323_DIGLDO_CON14, 15, MT6323_DIGLDO_CON35, 0x20,
 320                MT6323_DIGLDO_CON14, 0x2),
 321        MT6323_REG_FIXED("ldo_vrtc", VRTC, MT6323_DIGLDO_CON15, 8, 2800000,
 322                -1, 0),
 323        MT6323_LDO("ldo_vcamaf", VCAMAF, ldo_volt_table5,
 324                MT6323_DIGLDO_CON31, 15, MT6323_DIGLDO_CON32, 0xE0,
 325                MT6323_DIGLDO_CON31, 0x2),
 326        MT6323_LDO("ldo_vibr", VIBR, ldo_volt_table5,
 327                MT6323_DIGLDO_CON39, 15, MT6323_DIGLDO_CON40, 0xE0,
 328                MT6323_DIGLDO_CON39, 0x2),
 329        MT6323_REG_FIXED("ldo_vrf18", VRF18, MT6323_DIGLDO_CON45, 15, 1825000,
 330                MT6323_DIGLDO_CON45, 0x2),
 331        MT6323_LDO("ldo_vm", VM, ldo_volt_table9,
 332                MT6323_DIGLDO_CON47, 14, MT6323_DIGLDO_CON48, 0x30,
 333                MT6323_DIGLDO_CON47, 0x2),
 334        MT6323_REG_FIXED("ldo_vio18", VIO18, MT6323_DIGLDO_CON49, 14, 1800000,
 335                MT6323_DIGLDO_CON49, 0x2),
 336        MT6323_LDO("ldo_vcamd", VCAMD, ldo_volt_table10,
 337                MT6323_DIGLDO_CON51, 14, MT6323_DIGLDO_CON52, 0x60,
 338                MT6323_DIGLDO_CON51, 0x2),
 339        MT6323_REG_FIXED("ldo_vcamio", VCAMIO, MT6323_DIGLDO_CON53, 14, 1800000,
 340                MT6323_DIGLDO_CON53, 0x2),
 341};
 342
 343static int mt6323_set_buck_vosel_reg(struct platform_device *pdev)
 344{
 345        struct mt6397_chip *mt6323 = dev_get_drvdata(pdev->dev.parent);
 346        int i;
 347        u32 regval;
 348
 349        for (i = 0; i < MT6323_MAX_REGULATOR; i++) {
 350                if (mt6323_regulators[i].vselctrl_reg) {
 351                        if (regmap_read(mt6323->regmap,
 352                                mt6323_regulators[i].vselctrl_reg,
 353                                &regval) < 0) {
 354                                dev_err(&pdev->dev,
 355                                        "Failed to read buck ctrl\n");
 356                                return -EIO;
 357                        }
 358
 359                        if (regval & mt6323_regulators[i].vselctrl_mask) {
 360                                mt6323_regulators[i].desc.vsel_reg =
 361                                mt6323_regulators[i].vselon_reg;
 362                        }
 363                }
 364        }
 365
 366        return 0;
 367}
 368
 369static int mt6323_regulator_probe(struct platform_device *pdev)
 370{
 371        struct mt6397_chip *mt6323 = dev_get_drvdata(pdev->dev.parent);
 372        struct regulator_config config = {};
 373        struct regulator_dev *rdev;
 374        int i;
 375        u32 reg_value;
 376
 377        /* Query buck controller to select activated voltage register part */
 378        if (mt6323_set_buck_vosel_reg(pdev))
 379                return -EIO;
 380
 381        /* Read PMIC chip revision to update constraints and voltage table */
 382        if (regmap_read(mt6323->regmap, MT6323_CID, &reg_value) < 0) {
 383                dev_err(&pdev->dev, "Failed to read Chip ID\n");
 384                return -EIO;
 385        }
 386        dev_info(&pdev->dev, "Chip ID = 0x%x\n", reg_value);
 387
 388        for (i = 0; i < MT6323_MAX_REGULATOR; i++) {
 389                config.dev = &pdev->dev;
 390                config.driver_data = &mt6323_regulators[i];
 391                config.regmap = mt6323->regmap;
 392                rdev = devm_regulator_register(&pdev->dev,
 393                                &mt6323_regulators[i].desc, &config);
 394                if (IS_ERR(rdev)) {
 395                        dev_err(&pdev->dev, "failed to register %s\n",
 396                                mt6323_regulators[i].desc.name);
 397                        return PTR_ERR(rdev);
 398                }
 399        }
 400        return 0;
 401}
 402
 403static const struct platform_device_id mt6323_platform_ids[] = {
 404        {"mt6323-regulator", 0},
 405        { /* sentinel */ },
 406};
 407MODULE_DEVICE_TABLE(platform, mt6323_platform_ids);
 408
 409static struct platform_driver mt6323_regulator_driver = {
 410        .driver = {
 411                .name = "mt6323-regulator",
 412        },
 413        .probe = mt6323_regulator_probe,
 414        .id_table = mt6323_platform_ids,
 415};
 416
 417module_platform_driver(mt6323_regulator_driver);
 418
 419MODULE_AUTHOR("Chen Zhong <chen.zhong@mediatek.com>");
 420MODULE_DESCRIPTION("Regulator Driver for MediaTek MT6323 PMIC");
 421MODULE_LICENSE("GPL v2");
 422