linux/drivers/regulator/max8907-regulator.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * max8907-regulator.c -- support regulators in max8907
   4 *
   5 * Copyright (C) 2010 Gyungoh Yoo <jack.yoo@maxim-ic.com>
   6 * Copyright (C) 2010-2012, NVIDIA CORPORATION. All rights reserved.
   7 *
   8 * Portions based on drivers/regulator/tps65910-regulator.c,
   9 *     Copyright 2010 Texas Instruments Inc.
  10 *     Author: Graeme Gregory <gg@slimlogic.co.uk>
  11 *     Author: Jorge Eduardo Candelaria <jedu@slimlogic.co.uk>
  12 */
  13
  14#include <linux/err.h>
  15#include <linux/init.h>
  16#include <linux/mfd/core.h>
  17#include <linux/mfd/max8907.h>
  18#include <linux/module.h>
  19#include <linux/of.h>
  20#include <linux/platform_device.h>
  21#include <linux/regulator/driver.h>
  22#include <linux/regulator/machine.h>
  23#include <linux/regulator/of_regulator.h>
  24#include <linux/regmap.h>
  25#include <linux/slab.h>
  26
  27#define MAX8907_II2RR_VERSION_MASK      0xF0
  28#define MAX8907_II2RR_VERSION_REV_A     0x00
  29#define MAX8907_II2RR_VERSION_REV_B     0x10
  30#define MAX8907_II2RR_VERSION_REV_C     0x30
  31
  32struct max8907_regulator {
  33        struct regulator_desc desc[MAX8907_NUM_REGULATORS];
  34};
  35
  36#define REG_MBATT() \
  37        [MAX8907_MBATT] = { \
  38                .name = "MBATT", \
  39                .supply_name = "mbatt", \
  40                .id = MAX8907_MBATT, \
  41                .ops = &max8907_mbatt_ops, \
  42                .type = REGULATOR_VOLTAGE, \
  43                .owner = THIS_MODULE, \
  44        }
  45
  46#define REG_LDO(ids, supply, base, min, max, step) \
  47        [MAX8907_##ids] = { \
  48                .name = #ids, \
  49                .supply_name = supply, \
  50                .id = MAX8907_##ids, \
  51                .n_voltages = ((max) - (min)) / (step) + 1, \
  52                .ops = &max8907_ldo_ops, \
  53                .type = REGULATOR_VOLTAGE, \
  54                .owner = THIS_MODULE, \
  55                .min_uV = (min), \
  56                .uV_step = (step), \
  57                .vsel_reg = (base) + MAX8907_VOUT, \
  58                .vsel_mask = 0x3f, \
  59                .enable_reg = (base) + MAX8907_CTL, \
  60                .enable_mask = MAX8907_MASK_LDO_EN, \
  61        }
  62
  63#define REG_FIXED(ids, supply, voltage) \
  64        [MAX8907_##ids] = { \
  65                .name = #ids, \
  66                .supply_name = supply, \
  67                .id = MAX8907_##ids, \
  68                .n_voltages = 1, \
  69                .ops = &max8907_fixed_ops, \
  70                .type = REGULATOR_VOLTAGE, \
  71                .owner = THIS_MODULE, \
  72                .min_uV = (voltage), \
  73        }
  74
  75#define REG_OUT5V(ids, supply, base, voltage) \
  76        [MAX8907_##ids] = { \
  77                .name = #ids, \
  78                .supply_name = supply, \
  79                .id = MAX8907_##ids, \
  80                .n_voltages = 1, \
  81                .ops = &max8907_out5v_ops, \
  82                .type = REGULATOR_VOLTAGE, \
  83                .owner = THIS_MODULE, \
  84                .min_uV = (voltage), \
  85                .enable_reg = (base), \
  86                .enable_mask = MAX8907_MASK_OUT5V_EN, \
  87        }
  88
  89#define REG_BBAT(ids, supply, base, min, max, step) \
  90        [MAX8907_##ids] = { \
  91                .name = #ids, \
  92                .supply_name = supply, \
  93                .id = MAX8907_##ids, \
  94                .n_voltages = ((max) - (min)) / (step) + 1, \
  95                .ops = &max8907_bbat_ops, \
  96                .type = REGULATOR_VOLTAGE, \
  97                .owner = THIS_MODULE, \
  98                .min_uV = (min), \
  99                .uV_step = (step), \
 100                .vsel_reg = (base), \
 101                .vsel_mask = MAX8907_MASK_VBBATTCV, \
 102        }
 103
 104#define LDO_750_50(id, supply, base) REG_LDO(id, supply, (base), \
 105                        750000, 3900000, 50000)
 106#define LDO_650_25(id, supply, base) REG_LDO(id, supply, (base), \
 107                        650000, 2225000, 25000)
 108
 109static const struct regulator_ops max8907_mbatt_ops = {
 110};
 111
 112static const struct regulator_ops max8907_ldo_ops = {
 113        .list_voltage = regulator_list_voltage_linear,
 114        .set_voltage_sel = regulator_set_voltage_sel_regmap,
 115        .get_voltage_sel = regulator_get_voltage_sel_regmap,
 116        .enable = regulator_enable_regmap,
 117        .disable = regulator_disable_regmap,
 118        .is_enabled = regulator_is_enabled_regmap,
 119};
 120
 121static const struct regulator_ops max8907_ldo_hwctl_ops = {
 122        .list_voltage = regulator_list_voltage_linear,
 123        .set_voltage_sel = regulator_set_voltage_sel_regmap,
 124        .get_voltage_sel = regulator_get_voltage_sel_regmap,
 125};
 126
 127static const struct regulator_ops max8907_fixed_ops = {
 128        .list_voltage = regulator_list_voltage_linear,
 129};
 130
 131static const struct regulator_ops max8907_out5v_ops = {
 132        .list_voltage = regulator_list_voltage_linear,
 133        .enable = regulator_enable_regmap,
 134        .disable = regulator_disable_regmap,
 135        .is_enabled = regulator_is_enabled_regmap,
 136};
 137
 138static const struct regulator_ops max8907_out5v_hwctl_ops = {
 139        .list_voltage = regulator_list_voltage_linear,
 140};
 141
 142static const struct regulator_ops max8907_bbat_ops = {
 143        .list_voltage = regulator_list_voltage_linear,
 144        .set_voltage_sel = regulator_set_voltage_sel_regmap,
 145        .get_voltage_sel = regulator_get_voltage_sel_regmap,
 146};
 147
 148static const struct regulator_desc max8907_regulators[] = {
 149        REG_MBATT(),
 150        REG_LDO(SD1, "in-v1", MAX8907_REG_SDCTL1, 650000, 2225000, 25000),
 151        REG_LDO(SD2, "in-v2", MAX8907_REG_SDCTL2, 637500, 1425000, 12500),
 152        REG_LDO(SD3, "in-v3", MAX8907_REG_SDCTL3, 750000, 3900000, 50000),
 153        LDO_750_50(LDO1, "in1", MAX8907_REG_LDOCTL1),
 154        LDO_650_25(LDO2, "in2", MAX8907_REG_LDOCTL2),
 155        LDO_650_25(LDO3, "in3", MAX8907_REG_LDOCTL3),
 156        LDO_750_50(LDO4, "in4", MAX8907_REG_LDOCTL4),
 157        LDO_750_50(LDO5, "in5", MAX8907_REG_LDOCTL5),
 158        LDO_750_50(LDO6, "in6", MAX8907_REG_LDOCTL6),
 159        LDO_750_50(LDO7, "in7", MAX8907_REG_LDOCTL7),
 160        LDO_750_50(LDO8, "in8", MAX8907_REG_LDOCTL8),
 161        LDO_750_50(LDO9, "in9", MAX8907_REG_LDOCTL9),
 162        LDO_750_50(LDO10, "in10", MAX8907_REG_LDOCTL10),
 163        LDO_750_50(LDO11, "in11", MAX8907_REG_LDOCTL11),
 164        LDO_750_50(LDO12, "in12", MAX8907_REG_LDOCTL12),
 165        LDO_750_50(LDO13, "in13", MAX8907_REG_LDOCTL13),
 166        LDO_750_50(LDO14, "in14", MAX8907_REG_LDOCTL14),
 167        LDO_750_50(LDO15, "in15", MAX8907_REG_LDOCTL15),
 168        LDO_750_50(LDO16, "in16", MAX8907_REG_LDOCTL16),
 169        LDO_650_25(LDO17, "in17", MAX8907_REG_LDOCTL17),
 170        LDO_650_25(LDO18, "in18", MAX8907_REG_LDOCTL18),
 171        LDO_750_50(LDO19, "in19", MAX8907_REG_LDOCTL19),
 172        LDO_750_50(LDO20, "in20", MAX8907_REG_LDOCTL20),
 173        REG_OUT5V(OUT5V, "mbatt", MAX8907_REG_OUT5VEN, 5000000),
 174        REG_OUT5V(OUT33V, "mbatt",  MAX8907_REG_OUT33VEN, 3300000),
 175        REG_BBAT(BBAT, "MBATT", MAX8907_REG_BBAT_CNFG,
 176                                                2400000, 3000000, 200000),
 177        REG_FIXED(SDBY, "MBATT", 1200000),
 178        REG_FIXED(VRTC, "MBATT", 3300000),
 179};
 180
 181#ifdef CONFIG_OF
 182
 183#define MATCH(_name, _id) \
 184        [MAX8907_##_id] = { \
 185                .name = #_name, \
 186                .driver_data = (void *)&max8907_regulators[MAX8907_##_id], \
 187        }
 188
 189static struct of_regulator_match max8907_matches[] = {
 190        MATCH(mbatt, MBATT),
 191        MATCH(sd1, SD1),
 192        MATCH(sd2, SD2),
 193        MATCH(sd3, SD3),
 194        MATCH(ldo1, LDO1),
 195        MATCH(ldo2, LDO2),
 196        MATCH(ldo3, LDO3),
 197        MATCH(ldo4, LDO4),
 198        MATCH(ldo5, LDO5),
 199        MATCH(ldo6, LDO6),
 200        MATCH(ldo7, LDO7),
 201        MATCH(ldo8, LDO8),
 202        MATCH(ldo9, LDO9),
 203        MATCH(ldo10, LDO10),
 204        MATCH(ldo11, LDO11),
 205        MATCH(ldo12, LDO12),
 206        MATCH(ldo13, LDO13),
 207        MATCH(ldo14, LDO14),
 208        MATCH(ldo15, LDO15),
 209        MATCH(ldo16, LDO16),
 210        MATCH(ldo17, LDO17),
 211        MATCH(ldo18, LDO18),
 212        MATCH(ldo19, LDO19),
 213        MATCH(ldo20, LDO20),
 214        MATCH(out5v, OUT5V),
 215        MATCH(out33v, OUT33V),
 216        MATCH(bbat, BBAT),
 217        MATCH(sdby, SDBY),
 218        MATCH(vrtc, VRTC),
 219};
 220
 221static int max8907_regulator_parse_dt(struct platform_device *pdev)
 222{
 223        struct device_node *np, *regulators;
 224        int ret;
 225
 226        np = pdev->dev.parent->of_node;
 227        if (!np)
 228                return 0;
 229
 230        regulators = of_get_child_by_name(np, "regulators");
 231        if (!regulators) {
 232                dev_err(&pdev->dev, "regulators node not found\n");
 233                return -EINVAL;
 234        }
 235
 236        ret = of_regulator_match(&pdev->dev, regulators, max8907_matches,
 237                                 ARRAY_SIZE(max8907_matches));
 238        of_node_put(regulators);
 239        if (ret < 0) {
 240                dev_err(&pdev->dev, "Error parsing regulator init data: %d\n",
 241                        ret);
 242                return ret;
 243        }
 244
 245        return 0;
 246}
 247
 248static inline struct regulator_init_data *match_init_data(int index)
 249{
 250        return max8907_matches[index].init_data;
 251}
 252
 253static inline struct device_node *match_of_node(int index)
 254{
 255        return max8907_matches[index].of_node;
 256}
 257#else
 258static int max8907_regulator_parse_dt(struct platform_device *pdev)
 259{
 260        return 0;
 261}
 262
 263static inline struct regulator_init_data *match_init_data(int index)
 264{
 265        return NULL;
 266}
 267
 268static inline struct device_node *match_of_node(int index)
 269{
 270        return NULL;
 271}
 272#endif
 273
 274static int max8907_regulator_probe(struct platform_device *pdev)
 275{
 276        struct max8907 *max8907 = dev_get_drvdata(pdev->dev.parent);
 277        struct max8907_platform_data *pdata = dev_get_platdata(max8907->dev);
 278        int ret;
 279        struct max8907_regulator *pmic;
 280        unsigned int val;
 281        int i;
 282        struct regulator_config config = {};
 283        struct regulator_init_data *idata;
 284        const char *mbatt_rail_name = NULL;
 285
 286        ret = max8907_regulator_parse_dt(pdev);
 287        if (ret)
 288                return ret;
 289
 290        pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL);
 291        if (!pmic)
 292                return -ENOMEM;
 293
 294        platform_set_drvdata(pdev, pmic);
 295
 296        memcpy(pmic->desc, max8907_regulators, sizeof(pmic->desc));
 297
 298        /* Backwards compatibility with MAX8907B; SD1 uses different voltages */
 299        ret = regmap_read(max8907->regmap_gen, MAX8907_REG_II2RR, &val);
 300        if (ret)
 301                return ret;
 302
 303        if ((val & MAX8907_II2RR_VERSION_MASK) ==
 304            MAX8907_II2RR_VERSION_REV_B) {
 305                pmic->desc[MAX8907_SD1].min_uV = 637500;
 306                pmic->desc[MAX8907_SD1].uV_step = 12500;
 307                pmic->desc[MAX8907_SD1].n_voltages =
 308                                                (1425000 - 637500) / 12500 + 1;
 309        }
 310
 311        for (i = 0; i < MAX8907_NUM_REGULATORS; i++) {
 312                struct regulator_dev *rdev;
 313
 314                config.dev = pdev->dev.parent;
 315                if (pdata)
 316                        idata = pdata->init_data[i];
 317                else
 318                        idata = match_init_data(i);
 319                config.init_data = idata;
 320                config.driver_data = pmic;
 321                config.regmap = max8907->regmap_gen;
 322                config.of_node = match_of_node(i);
 323
 324                switch (pmic->desc[i].id) {
 325                case MAX8907_MBATT:
 326                        if (idata && idata->constraints.name)
 327                                mbatt_rail_name = idata->constraints.name;
 328                        else
 329                                mbatt_rail_name = pmic->desc[i].name;
 330                        break;
 331                case MAX8907_BBAT:
 332                case MAX8907_SDBY:
 333                case MAX8907_VRTC:
 334                        idata->supply_regulator = mbatt_rail_name;
 335                        break;
 336                }
 337
 338                if (pmic->desc[i].ops == &max8907_ldo_ops) {
 339                        ret = regmap_read(config.regmap, pmic->desc[i].enable_reg,
 340                                    &val);
 341                        if (ret)
 342                                return ret;
 343
 344                        if ((val & MAX8907_MASK_LDO_SEQ) !=
 345                            MAX8907_MASK_LDO_SEQ)
 346                                pmic->desc[i].ops = &max8907_ldo_hwctl_ops;
 347                } else if (pmic->desc[i].ops == &max8907_out5v_ops) {
 348                        ret = regmap_read(config.regmap, pmic->desc[i].enable_reg,
 349                                    &val);
 350                        if (ret)
 351                                return ret;
 352
 353                        if ((val & (MAX8907_MASK_OUT5V_VINEN |
 354                                                MAX8907_MASK_OUT5V_ENSRC)) !=
 355                            MAX8907_MASK_OUT5V_ENSRC)
 356                                pmic->desc[i].ops = &max8907_out5v_hwctl_ops;
 357                }
 358
 359                rdev = devm_regulator_register(&pdev->dev,
 360                                                &pmic->desc[i], &config);
 361                if (IS_ERR(rdev)) {
 362                        dev_err(&pdev->dev,
 363                                "failed to register %s regulator\n",
 364                                pmic->desc[i].name);
 365                        return PTR_ERR(rdev);
 366                }
 367        }
 368
 369        return 0;
 370}
 371
 372static struct platform_driver max8907_regulator_driver = {
 373        .driver = {
 374                   .name = "max8907-regulator",
 375                   },
 376        .probe = max8907_regulator_probe,
 377};
 378
 379static int __init max8907_regulator_init(void)
 380{
 381        return platform_driver_register(&max8907_regulator_driver);
 382}
 383
 384subsys_initcall(max8907_regulator_init);
 385
 386static void __exit max8907_reg_exit(void)
 387{
 388        platform_driver_unregister(&max8907_regulator_driver);
 389}
 390
 391module_exit(max8907_reg_exit);
 392
 393MODULE_DESCRIPTION("MAX8907 regulator driver");
 394MODULE_AUTHOR("Gyungoh Yoo <jack.yoo@maxim-ic.com>");
 395MODULE_LICENSE("GPL v2");
 396MODULE_ALIAS("platform:max8907-regulator");
 397