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