Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * max8907-regulator.c -- support regulators in max8907
0004  *
0005  * Copyright (C) 2010 Gyungoh Yoo <jack.yoo@maxim-ic.com>
0006  * Copyright (C) 2010-2012, NVIDIA CORPORATION. All rights reserved.
0007  *
0008  * Portions based on drivers/regulator/tps65910-regulator.c,
0009  *     Copyright 2010 Texas Instruments Inc.
0010  *     Author: Graeme Gregory <gg@slimlogic.co.uk>
0011  *     Author: Jorge Eduardo Candelaria <jedu@slimlogic.co.uk>
0012  */
0013 
0014 #include <linux/err.h>
0015 #include <linux/init.h>
0016 #include <linux/mfd/core.h>
0017 #include <linux/mfd/max8907.h>
0018 #include <linux/module.h>
0019 #include <linux/of.h>
0020 #include <linux/platform_device.h>
0021 #include <linux/regulator/driver.h>
0022 #include <linux/regulator/machine.h>
0023 #include <linux/regulator/of_regulator.h>
0024 #include <linux/regmap.h>
0025 #include <linux/slab.h>
0026 
0027 #define MAX8907_II2RR_VERSION_MASK  0xF0
0028 #define MAX8907_II2RR_VERSION_REV_A 0x00
0029 #define MAX8907_II2RR_VERSION_REV_B 0x10
0030 #define MAX8907_II2RR_VERSION_REV_C 0x30
0031 
0032 struct max8907_regulator {
0033     struct regulator_desc desc[MAX8907_NUM_REGULATORS];
0034 };
0035 
0036 #define REG_MBATT() \
0037     [MAX8907_MBATT] = { \
0038         .name = "MBATT", \
0039         .supply_name = "mbatt", \
0040         .id = MAX8907_MBATT, \
0041         .ops = &max8907_mbatt_ops, \
0042         .type = REGULATOR_VOLTAGE, \
0043         .owner = THIS_MODULE, \
0044     }
0045 
0046 #define REG_LDO(ids, supply, base, min, max, step) \
0047     [MAX8907_##ids] = { \
0048         .name = #ids, \
0049         .supply_name = supply, \
0050         .id = MAX8907_##ids, \
0051         .n_voltages = ((max) - (min)) / (step) + 1, \
0052         .ops = &max8907_ldo_ops, \
0053         .type = REGULATOR_VOLTAGE, \
0054         .owner = THIS_MODULE, \
0055         .min_uV = (min), \
0056         .uV_step = (step), \
0057         .vsel_reg = (base) + MAX8907_VOUT, \
0058         .vsel_mask = 0x3f, \
0059         .enable_reg = (base) + MAX8907_CTL, \
0060         .enable_mask = MAX8907_MASK_LDO_EN, \
0061     }
0062 
0063 #define REG_FIXED(ids, supply, voltage) \
0064     [MAX8907_##ids] = { \
0065         .name = #ids, \
0066         .supply_name = supply, \
0067         .id = MAX8907_##ids, \
0068         .n_voltages = 1, \
0069         .ops = &max8907_fixed_ops, \
0070         .type = REGULATOR_VOLTAGE, \
0071         .owner = THIS_MODULE, \
0072         .min_uV = (voltage), \
0073     }
0074 
0075 #define REG_OUT5V(ids, supply, base, voltage) \
0076     [MAX8907_##ids] = { \
0077         .name = #ids, \
0078         .supply_name = supply, \
0079         .id = MAX8907_##ids, \
0080         .n_voltages = 1, \
0081         .ops = &max8907_out5v_ops, \
0082         .type = REGULATOR_VOLTAGE, \
0083         .owner = THIS_MODULE, \
0084         .min_uV = (voltage), \
0085         .enable_reg = (base), \
0086         .enable_mask = MAX8907_MASK_OUT5V_EN, \
0087     }
0088 
0089 #define REG_BBAT(ids, supply, base, min, max, step) \
0090     [MAX8907_##ids] = { \
0091         .name = #ids, \
0092         .supply_name = supply, \
0093         .id = MAX8907_##ids, \
0094         .n_voltages = ((max) - (min)) / (step) + 1, \
0095         .ops = &max8907_bbat_ops, \
0096         .type = REGULATOR_VOLTAGE, \
0097         .owner = THIS_MODULE, \
0098         .min_uV = (min), \
0099         .uV_step = (step), \
0100         .vsel_reg = (base), \
0101         .vsel_mask = MAX8907_MASK_VBBATTCV, \
0102     }
0103 
0104 #define LDO_750_50(id, supply, base) REG_LDO(id, supply, (base), \
0105             750000, 3900000, 50000)
0106 #define LDO_650_25(id, supply, base) REG_LDO(id, supply, (base), \
0107             650000, 2225000, 25000)
0108 
0109 static const struct regulator_ops max8907_mbatt_ops = {
0110 };
0111 
0112 static const struct regulator_ops max8907_ldo_ops = {
0113     .list_voltage = regulator_list_voltage_linear,
0114     .set_voltage_sel = regulator_set_voltage_sel_regmap,
0115     .get_voltage_sel = regulator_get_voltage_sel_regmap,
0116     .enable = regulator_enable_regmap,
0117     .disable = regulator_disable_regmap,
0118     .is_enabled = regulator_is_enabled_regmap,
0119 };
0120 
0121 static const struct regulator_ops max8907_ldo_hwctl_ops = {
0122     .list_voltage = regulator_list_voltage_linear,
0123     .set_voltage_sel = regulator_set_voltage_sel_regmap,
0124     .get_voltage_sel = regulator_get_voltage_sel_regmap,
0125 };
0126 
0127 static const struct regulator_ops max8907_fixed_ops = {
0128     .list_voltage = regulator_list_voltage_linear,
0129 };
0130 
0131 static const struct regulator_ops max8907_out5v_ops = {
0132     .list_voltage = regulator_list_voltage_linear,
0133     .enable = regulator_enable_regmap,
0134     .disable = regulator_disable_regmap,
0135     .is_enabled = regulator_is_enabled_regmap,
0136 };
0137 
0138 static const struct regulator_ops max8907_out5v_hwctl_ops = {
0139     .list_voltage = regulator_list_voltage_linear,
0140 };
0141 
0142 static const struct regulator_ops max8907_bbat_ops = {
0143     .list_voltage = regulator_list_voltage_linear,
0144     .set_voltage_sel = regulator_set_voltage_sel_regmap,
0145     .get_voltage_sel = regulator_get_voltage_sel_regmap,
0146 };
0147 
0148 static const struct regulator_desc max8907_regulators[] = {
0149     REG_MBATT(),
0150     REG_LDO(SD1, "in-v1", MAX8907_REG_SDCTL1, 650000, 2225000, 25000),
0151     REG_LDO(SD2, "in-v2", MAX8907_REG_SDCTL2, 637500, 1425000, 12500),
0152     REG_LDO(SD3, "in-v3", MAX8907_REG_SDCTL3, 750000, 3900000, 50000),
0153     LDO_750_50(LDO1, "in1", MAX8907_REG_LDOCTL1),
0154     LDO_650_25(LDO2, "in2", MAX8907_REG_LDOCTL2),
0155     LDO_650_25(LDO3, "in3", MAX8907_REG_LDOCTL3),
0156     LDO_750_50(LDO4, "in4", MAX8907_REG_LDOCTL4),
0157     LDO_750_50(LDO5, "in5", MAX8907_REG_LDOCTL5),
0158     LDO_750_50(LDO6, "in6", MAX8907_REG_LDOCTL6),
0159     LDO_750_50(LDO7, "in7", MAX8907_REG_LDOCTL7),
0160     LDO_750_50(LDO8, "in8", MAX8907_REG_LDOCTL8),
0161     LDO_750_50(LDO9, "in9", MAX8907_REG_LDOCTL9),
0162     LDO_750_50(LDO10, "in10", MAX8907_REG_LDOCTL10),
0163     LDO_750_50(LDO11, "in11", MAX8907_REG_LDOCTL11),
0164     LDO_750_50(LDO12, "in12", MAX8907_REG_LDOCTL12),
0165     LDO_750_50(LDO13, "in13", MAX8907_REG_LDOCTL13),
0166     LDO_750_50(LDO14, "in14", MAX8907_REG_LDOCTL14),
0167     LDO_750_50(LDO15, "in15", MAX8907_REG_LDOCTL15),
0168     LDO_750_50(LDO16, "in16", MAX8907_REG_LDOCTL16),
0169     LDO_650_25(LDO17, "in17", MAX8907_REG_LDOCTL17),
0170     LDO_650_25(LDO18, "in18", MAX8907_REG_LDOCTL18),
0171     LDO_750_50(LDO19, "in19", MAX8907_REG_LDOCTL19),
0172     LDO_750_50(LDO20, "in20", MAX8907_REG_LDOCTL20),
0173     REG_OUT5V(OUT5V, "mbatt", MAX8907_REG_OUT5VEN, 5000000),
0174     REG_OUT5V(OUT33V, "mbatt",  MAX8907_REG_OUT33VEN, 3300000),
0175     REG_BBAT(BBAT, "MBATT", MAX8907_REG_BBAT_CNFG,
0176                         2400000, 3000000, 200000),
0177     REG_FIXED(SDBY, "MBATT", 1200000),
0178     REG_FIXED(VRTC, "MBATT", 3300000),
0179 };
0180 
0181 #ifdef CONFIG_OF
0182 
0183 #define MATCH(_name, _id) \
0184     [MAX8907_##_id] = { \
0185         .name = #_name, \
0186         .driver_data = (void *)&max8907_regulators[MAX8907_##_id], \
0187     }
0188 
0189 static struct of_regulator_match max8907_matches[] = {
0190     MATCH(mbatt, MBATT),
0191     MATCH(sd1, SD1),
0192     MATCH(sd2, SD2),
0193     MATCH(sd3, SD3),
0194     MATCH(ldo1, LDO1),
0195     MATCH(ldo2, LDO2),
0196     MATCH(ldo3, LDO3),
0197     MATCH(ldo4, LDO4),
0198     MATCH(ldo5, LDO5),
0199     MATCH(ldo6, LDO6),
0200     MATCH(ldo7, LDO7),
0201     MATCH(ldo8, LDO8),
0202     MATCH(ldo9, LDO9),
0203     MATCH(ldo10, LDO10),
0204     MATCH(ldo11, LDO11),
0205     MATCH(ldo12, LDO12),
0206     MATCH(ldo13, LDO13),
0207     MATCH(ldo14, LDO14),
0208     MATCH(ldo15, LDO15),
0209     MATCH(ldo16, LDO16),
0210     MATCH(ldo17, LDO17),
0211     MATCH(ldo18, LDO18),
0212     MATCH(ldo19, LDO19),
0213     MATCH(ldo20, LDO20),
0214     MATCH(out5v, OUT5V),
0215     MATCH(out33v, OUT33V),
0216     MATCH(bbat, BBAT),
0217     MATCH(sdby, SDBY),
0218     MATCH(vrtc, VRTC),
0219 };
0220 
0221 static int max8907_regulator_parse_dt(struct platform_device *pdev)
0222 {
0223     struct device_node *np, *regulators;
0224     int ret;
0225 
0226     np = pdev->dev.parent->of_node;
0227     if (!np)
0228         return 0;
0229 
0230     regulators = of_get_child_by_name(np, "regulators");
0231     if (!regulators) {
0232         dev_err(&pdev->dev, "regulators node not found\n");
0233         return -EINVAL;
0234     }
0235 
0236     ret = of_regulator_match(&pdev->dev, regulators, max8907_matches,
0237                  ARRAY_SIZE(max8907_matches));
0238     of_node_put(regulators);
0239     if (ret < 0) {
0240         dev_err(&pdev->dev, "Error parsing regulator init data: %d\n",
0241             ret);
0242         return ret;
0243     }
0244 
0245     return 0;
0246 }
0247 
0248 static inline struct regulator_init_data *match_init_data(int index)
0249 {
0250     return max8907_matches[index].init_data;
0251 }
0252 
0253 static inline struct device_node *match_of_node(int index)
0254 {
0255     return max8907_matches[index].of_node;
0256 }
0257 #else
0258 static int max8907_regulator_parse_dt(struct platform_device *pdev)
0259 {
0260     return 0;
0261 }
0262 
0263 static inline struct regulator_init_data *match_init_data(int index)
0264 {
0265     return NULL;
0266 }
0267 
0268 static inline struct device_node *match_of_node(int index)
0269 {
0270     return NULL;
0271 }
0272 #endif
0273 
0274 static int max8907_regulator_probe(struct platform_device *pdev)
0275 {
0276     struct max8907 *max8907 = dev_get_drvdata(pdev->dev.parent);
0277     struct max8907_platform_data *pdata = dev_get_platdata(max8907->dev);
0278     int ret;
0279     struct max8907_regulator *pmic;
0280     unsigned int val;
0281     int i;
0282     struct regulator_config config = {};
0283     struct regulator_init_data *idata;
0284     const char *mbatt_rail_name = NULL;
0285 
0286     ret = max8907_regulator_parse_dt(pdev);
0287     if (ret)
0288         return ret;
0289 
0290     pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL);
0291     if (!pmic)
0292         return -ENOMEM;
0293 
0294     platform_set_drvdata(pdev, pmic);
0295 
0296     memcpy(pmic->desc, max8907_regulators, sizeof(pmic->desc));
0297 
0298     /* Backwards compatibility with MAX8907B; SD1 uses different voltages */
0299     ret = regmap_read(max8907->regmap_gen, MAX8907_REG_II2RR, &val);
0300     if (ret)
0301         return ret;
0302 
0303     if ((val & MAX8907_II2RR_VERSION_MASK) ==
0304         MAX8907_II2RR_VERSION_REV_B) {
0305         pmic->desc[MAX8907_SD1].min_uV = 637500;
0306         pmic->desc[MAX8907_SD1].uV_step = 12500;
0307         pmic->desc[MAX8907_SD1].n_voltages =
0308                         (1425000 - 637500) / 12500 + 1;
0309     }
0310 
0311     for (i = 0; i < MAX8907_NUM_REGULATORS; i++) {
0312         struct regulator_dev *rdev;
0313 
0314         config.dev = pdev->dev.parent;
0315         if (pdata)
0316             idata = pdata->init_data[i];
0317         else
0318             idata = match_init_data(i);
0319         config.init_data = idata;
0320         config.driver_data = pmic;
0321         config.regmap = max8907->regmap_gen;
0322         config.of_node = match_of_node(i);
0323 
0324         switch (pmic->desc[i].id) {
0325         case MAX8907_MBATT:
0326             if (idata && idata->constraints.name)
0327                 mbatt_rail_name = idata->constraints.name;
0328             else
0329                 mbatt_rail_name = pmic->desc[i].name;
0330             break;
0331         case MAX8907_BBAT:
0332         case MAX8907_SDBY:
0333         case MAX8907_VRTC:
0334             idata->supply_regulator = mbatt_rail_name;
0335             break;
0336         }
0337 
0338         if (pmic->desc[i].ops == &max8907_ldo_ops) {
0339             ret = regmap_read(config.regmap, pmic->desc[i].enable_reg,
0340                     &val);
0341             if (ret)
0342                 return ret;
0343 
0344             if ((val & MAX8907_MASK_LDO_SEQ) !=
0345                 MAX8907_MASK_LDO_SEQ)
0346                 pmic->desc[i].ops = &max8907_ldo_hwctl_ops;
0347         } else if (pmic->desc[i].ops == &max8907_out5v_ops) {
0348             ret = regmap_read(config.regmap, pmic->desc[i].enable_reg,
0349                     &val);
0350             if (ret)
0351                 return ret;
0352 
0353             if ((val & (MAX8907_MASK_OUT5V_VINEN |
0354                         MAX8907_MASK_OUT5V_ENSRC)) !=
0355                 MAX8907_MASK_OUT5V_ENSRC)
0356                 pmic->desc[i].ops = &max8907_out5v_hwctl_ops;
0357         }
0358 
0359         rdev = devm_regulator_register(&pdev->dev,
0360                         &pmic->desc[i], &config);
0361         if (IS_ERR(rdev)) {
0362             dev_err(&pdev->dev,
0363                 "failed to register %s regulator\n",
0364                 pmic->desc[i].name);
0365             return PTR_ERR(rdev);
0366         }
0367     }
0368 
0369     return 0;
0370 }
0371 
0372 static struct platform_driver max8907_regulator_driver = {
0373     .driver = {
0374            .name = "max8907-regulator",
0375            },
0376     .probe = max8907_regulator_probe,
0377 };
0378 
0379 static int __init max8907_regulator_init(void)
0380 {
0381     return platform_driver_register(&max8907_regulator_driver);
0382 }
0383 
0384 subsys_initcall(max8907_regulator_init);
0385 
0386 static void __exit max8907_reg_exit(void)
0387 {
0388     platform_driver_unregister(&max8907_regulator_driver);
0389 }
0390 
0391 module_exit(max8907_reg_exit);
0392 
0393 MODULE_DESCRIPTION("MAX8907 regulator driver");
0394 MODULE_AUTHOR("Gyungoh Yoo <jack.yoo@maxim-ic.com>");
0395 MODULE_LICENSE("GPL v2");
0396 MODULE_ALIAS("platform:max8907-regulator");