Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 //
0003 // mpq7920.c  - regulator driver for mps mpq7920
0004 //
0005 // Copyright 2019 Monolithic Power Systems, Inc
0006 //
0007 // Author: Saravanan Sekar <sravanhome@gmail.com>
0008 
0009 #include <linux/kernel.h>
0010 #include <linux/module.h>
0011 #include <linux/init.h>
0012 #include <linux/err.h>
0013 #include <linux/of.h>
0014 #include <linux/of_device.h>
0015 #include <linux/platform_device.h>
0016 #include <linux/regulator/driver.h>
0017 #include <linux/regulator/of_regulator.h>
0018 #include <linux/i2c.h>
0019 #include <linux/regmap.h>
0020 #include "mpq7920.h"
0021 
0022 #define MPQ7920_BUCK_VOLT_RANGE \
0023     ((MPQ7920_VOLT_MAX - MPQ7920_BUCK_VOLT_MIN)/MPQ7920_VOLT_STEP + 1)
0024 #define MPQ7920_LDO_VOLT_RANGE \
0025     ((MPQ7920_VOLT_MAX - MPQ7920_LDO_VOLT_MIN)/MPQ7920_VOLT_STEP + 1)
0026 
0027 #define MPQ7920BUCK(_name, _id, _ilim)                  \
0028     [MPQ7920_BUCK ## _id] = {                   \
0029         .id = MPQ7920_BUCK ## _id,              \
0030         .name = _name,                      \
0031         .of_match = _name,                  \
0032         .regulators_node = "regulators",            \
0033         .of_parse_cb = mpq7920_parse_cb,            \
0034         .ops = &mpq7920_buck_ops,               \
0035         .min_uV = MPQ7920_BUCK_VOLT_MIN,            \
0036         .uV_step = MPQ7920_VOLT_STEP,               \
0037         .n_voltages = MPQ7920_BUCK_VOLT_RANGE,          \
0038         .curr_table = _ilim,                    \
0039         .n_current_limits = ARRAY_SIZE(_ilim),          \
0040         .csel_reg = MPQ7920_BUCK ##_id## _REG_C,        \
0041         .csel_mask = MPQ7920_MASK_BUCK_ILIM,            \
0042         .enable_reg = MPQ7920_REG_REGULATOR_EN,         \
0043         .enable_mask = BIT(MPQ7920_REGULATOR_EN_OFFSET -    \
0044                      MPQ7920_BUCK ## _id),      \
0045         .vsel_reg = MPQ7920_BUCK ##_id## _REG_A,        \
0046         .vsel_mask = MPQ7920_MASK_VREF,             \
0047         .active_discharge_on    = MPQ7920_DISCHARGE_ON,     \
0048         .active_discharge_reg   = MPQ7920_BUCK ##_id## _REG_B,  \
0049         .active_discharge_mask  = MPQ7920_MASK_DISCHARGE,   \
0050         .soft_start_reg     = MPQ7920_BUCK ##_id## _REG_C,  \
0051         .soft_start_mask    = MPQ7920_MASK_SOFTSTART,   \
0052         .owner          = THIS_MODULE,          \
0053     }
0054 
0055 #define MPQ7920LDO(_name, _id, _ops, _ilim, _ilim_sz, _creg, _cmask)    \
0056     [MPQ7920_LDO ## _id] = {                    \
0057         .id = MPQ7920_LDO ## _id,               \
0058         .name = _name,                      \
0059         .of_match = _name,                  \
0060         .regulators_node = "regulators",            \
0061         .ops = _ops,                        \
0062         .min_uV = MPQ7920_LDO_VOLT_MIN,             \
0063         .uV_step = MPQ7920_VOLT_STEP,               \
0064         .n_voltages = MPQ7920_LDO_VOLT_RANGE,           \
0065         .vsel_reg = MPQ7920_LDO ##_id## _REG_A,         \
0066         .vsel_mask = MPQ7920_MASK_VREF,             \
0067         .curr_table = _ilim,                    \
0068         .n_current_limits = _ilim_sz,               \
0069         .csel_reg = _creg,                  \
0070         .csel_mask = _cmask,                    \
0071         .enable_reg = (_id == 1) ? 0 : MPQ7920_REG_REGULATOR_EN,\
0072         .enable_mask = BIT(MPQ7920_REGULATOR_EN_OFFSET -    \
0073                     MPQ7920_LDO ##_id + 1),     \
0074         .active_discharge_on    = MPQ7920_DISCHARGE_ON,     \
0075         .active_discharge_mask  = MPQ7920_MASK_DISCHARGE,   \
0076         .active_discharge_reg   = MPQ7920_LDO ##_id## _REG_B,   \
0077         .type           = REGULATOR_VOLTAGE,        \
0078         .owner          = THIS_MODULE,          \
0079     }
0080 
0081 enum mpq7920_regulators {
0082     MPQ7920_BUCK1,
0083     MPQ7920_BUCK2,
0084     MPQ7920_BUCK3,
0085     MPQ7920_BUCK4,
0086     MPQ7920_LDO1, /* LDORTC */
0087     MPQ7920_LDO2,
0088     MPQ7920_LDO3,
0089     MPQ7920_LDO4,
0090     MPQ7920_LDO5,
0091     MPQ7920_MAX_REGULATORS,
0092 };
0093 
0094 struct mpq7920_regulator_info {
0095     struct regmap *regmap;
0096     struct regulator_desc *rdesc;
0097 };
0098 
0099 static const struct regmap_config mpq7920_regmap_config = {
0100     .reg_bits = 8,
0101     .val_bits = 8,
0102     .max_register = 0x25,
0103 };
0104 
0105 /* Current limits array (in uA)
0106  * ILIM1 & ILIM3
0107  */
0108 static const unsigned int mpq7920_I_limits1[] = {
0109     4600000, 6600000, 7600000, 9300000
0110 };
0111 
0112 /* ILIM2 & ILIM4 */
0113 static const unsigned int mpq7920_I_limits2[] = {
0114     2700000, 3900000, 5100000, 6100000
0115 };
0116 
0117 /* LDO4 & LDO5 */
0118 static const unsigned int mpq7920_I_limits3[] = {
0119     300000, 700000
0120 };
0121 
0122 static int mpq7920_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay);
0123 static int mpq7920_parse_cb(struct device_node *np,
0124                 const struct regulator_desc *rdesc,
0125                 struct regulator_config *config);
0126 
0127 /* RTCLDO not controllable, always ON */
0128 static const struct regulator_ops mpq7920_ldortc_ops = {
0129     .list_voltage       = regulator_list_voltage_linear,
0130     .map_voltage        = regulator_map_voltage_linear,
0131     .get_voltage_sel    = regulator_get_voltage_sel_regmap,
0132     .set_voltage_sel    = regulator_set_voltage_sel_regmap,
0133 };
0134 
0135 static const struct regulator_ops mpq7920_ldo_wo_current_ops = {
0136     .enable         = regulator_enable_regmap,
0137     .disable        = regulator_disable_regmap,
0138     .is_enabled     = regulator_is_enabled_regmap,
0139     .list_voltage       = regulator_list_voltage_linear,
0140     .map_voltage        = regulator_map_voltage_linear,
0141     .get_voltage_sel    = regulator_get_voltage_sel_regmap,
0142     .set_voltage_sel    = regulator_set_voltage_sel_regmap,
0143     .set_active_discharge   = regulator_set_active_discharge_regmap,
0144 };
0145 
0146 static const struct regulator_ops mpq7920_ldo_ops = {
0147     .enable         = regulator_enable_regmap,
0148     .disable        = regulator_disable_regmap,
0149     .is_enabled     = regulator_is_enabled_regmap,
0150     .list_voltage       = regulator_list_voltage_linear,
0151     .map_voltage        = regulator_map_voltage_linear,
0152     .get_voltage_sel    = regulator_get_voltage_sel_regmap,
0153     .set_voltage_sel    = regulator_set_voltage_sel_regmap,
0154     .set_active_discharge   = regulator_set_active_discharge_regmap,
0155     .get_current_limit  = regulator_get_current_limit_regmap,
0156     .set_current_limit  = regulator_set_current_limit_regmap,
0157 };
0158 
0159 static const struct regulator_ops mpq7920_buck_ops = {
0160     .enable         = regulator_enable_regmap,
0161     .disable        = regulator_disable_regmap,
0162     .is_enabled     = regulator_is_enabled_regmap,
0163     .list_voltage       = regulator_list_voltage_linear,
0164     .map_voltage        = regulator_map_voltage_linear,
0165     .get_voltage_sel    = regulator_get_voltage_sel_regmap,
0166     .set_voltage_sel    = regulator_set_voltage_sel_regmap,
0167     .set_active_discharge   = regulator_set_active_discharge_regmap,
0168     .set_soft_start     = regulator_set_soft_start_regmap,
0169     .set_ramp_delay     = mpq7920_set_ramp_delay,
0170 };
0171 
0172 static struct regulator_desc mpq7920_regulators_desc[MPQ7920_MAX_REGULATORS] = {
0173     MPQ7920BUCK("buck1", 1, mpq7920_I_limits1),
0174     MPQ7920BUCK("buck2", 2, mpq7920_I_limits2),
0175     MPQ7920BUCK("buck3", 3, mpq7920_I_limits1),
0176     MPQ7920BUCK("buck4", 4, mpq7920_I_limits2),
0177     MPQ7920LDO("ldortc", 1, &mpq7920_ldortc_ops, NULL, 0, 0, 0),
0178     MPQ7920LDO("ldo2", 2, &mpq7920_ldo_wo_current_ops, NULL, 0, 0, 0),
0179     MPQ7920LDO("ldo3", 3, &mpq7920_ldo_wo_current_ops, NULL, 0, 0, 0),
0180     MPQ7920LDO("ldo4", 4, &mpq7920_ldo_ops, mpq7920_I_limits3,
0181             ARRAY_SIZE(mpq7920_I_limits3), MPQ7920_LDO4_REG_B,
0182             MPQ7920_MASK_LDO_ILIM),
0183     MPQ7920LDO("ldo5", 5, &mpq7920_ldo_ops, mpq7920_I_limits3,
0184             ARRAY_SIZE(mpq7920_I_limits3), MPQ7920_LDO5_REG_B,
0185             MPQ7920_MASK_LDO_ILIM),
0186 };
0187 
0188 /*
0189  * DVS ramp rate BUCK1 to BUCK4
0190  * 00-01: Reserved
0191  * 10: 8mV/us
0192  * 11: 4mV/us
0193  */
0194 static int mpq7920_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay)
0195 {
0196     unsigned int ramp_val;
0197 
0198     if (ramp_delay > 8000 || ramp_delay < 0)
0199         return -EINVAL;
0200 
0201     if (ramp_delay <= 4000)
0202         ramp_val = 3;
0203     else
0204         ramp_val = 2;
0205 
0206     return regmap_update_bits(rdev->regmap, MPQ7920_REG_CTL0,
0207                   MPQ7920_MASK_DVS_SLEWRATE, ramp_val << 6);
0208 }
0209 
0210 static int mpq7920_parse_cb(struct device_node *np,
0211                 const struct regulator_desc *desc,
0212                 struct regulator_config *config)
0213 {
0214     uint8_t val;
0215     int ret;
0216     struct mpq7920_regulator_info *info = config->driver_data;
0217     struct regulator_desc *rdesc = &info->rdesc[desc->id];
0218 
0219     if (of_property_read_bool(np, "mps,buck-ovp-disable")) {
0220         regmap_update_bits(config->regmap,
0221                 MPQ7920_BUCK1_REG_B + (rdesc->id * 4),
0222                 MPQ7920_MASK_OVP, MPQ7920_OVP_DISABLE);
0223     }
0224 
0225     ret = of_property_read_u8(np, "mps,buck-phase-delay", &val);
0226     if (!ret) {
0227         regmap_update_bits(config->regmap,
0228                 MPQ7920_BUCK1_REG_C + (rdesc->id * 4),
0229                 MPQ7920_MASK_BUCK_PHASE_DEALY,
0230                 (val & 3) << 4);
0231     }
0232 
0233     ret = of_property_read_u8(np, "mps,buck-softstart", &val);
0234     if (!ret)
0235         rdesc->soft_start_val_on = (val & 3) << 2;
0236 
0237     return 0;
0238 }
0239 
0240 static void mpq7920_parse_dt(struct device *dev,
0241          struct mpq7920_regulator_info *info)
0242 {
0243     int ret;
0244     struct device_node *np = dev->of_node;
0245     uint8_t freq;
0246 
0247     np = of_get_child_by_name(np, "regulators");
0248     if (!np) {
0249         dev_err(dev, "missing 'regulators' subnode in DT\n");
0250         return;
0251     }
0252 
0253     ret = of_property_read_u8(np, "mps,switch-freq", &freq);
0254     if (!ret) {
0255         regmap_update_bits(info->regmap, MPQ7920_REG_CTL0,
0256                     MPQ7920_MASK_SWITCH_FREQ,
0257                     (freq & 3) << 4);
0258     }
0259 
0260     of_node_put(np);
0261 }
0262 
0263 static int mpq7920_i2c_probe(struct i2c_client *client)
0264 {
0265     struct device *dev = &client->dev;
0266     struct mpq7920_regulator_info *info;
0267     struct regulator_config config = { NULL, };
0268     struct regulator_dev *rdev;
0269     struct regmap *regmap;
0270     int i;
0271 
0272     info = devm_kzalloc(dev, sizeof(struct mpq7920_regulator_info),
0273                 GFP_KERNEL);
0274     if (!info)
0275         return -ENOMEM;
0276 
0277     info->rdesc = mpq7920_regulators_desc;
0278     regmap = devm_regmap_init_i2c(client, &mpq7920_regmap_config);
0279     if (IS_ERR(regmap)) {
0280         dev_err(dev, "Failed to allocate regmap!\n");
0281         return PTR_ERR(regmap);
0282     }
0283 
0284     i2c_set_clientdata(client, info);
0285     info->regmap = regmap;
0286     if (client->dev.of_node)
0287         mpq7920_parse_dt(&client->dev, info);
0288 
0289     config.dev = dev;
0290     config.regmap = regmap;
0291     config.driver_data = info;
0292 
0293     for (i = 0; i < MPQ7920_MAX_REGULATORS; i++) {
0294         rdev = devm_regulator_register(dev,
0295                            &mpq7920_regulators_desc[i],
0296                            &config);
0297         if (IS_ERR(rdev)) {
0298             dev_err(dev, "Failed to register regulator!\n");
0299             return PTR_ERR(rdev);
0300         }
0301     }
0302 
0303     return 0;
0304 }
0305 
0306 static const struct of_device_id mpq7920_of_match[] = {
0307     { .compatible = "mps,mpq7920"},
0308     {},
0309 };
0310 MODULE_DEVICE_TABLE(of, mpq7920_of_match);
0311 
0312 static const struct i2c_device_id mpq7920_id[] = {
0313     { "mpq7920", },
0314     { },
0315 };
0316 MODULE_DEVICE_TABLE(i2c, mpq7920_id);
0317 
0318 static struct i2c_driver mpq7920_regulator_driver = {
0319     .driver = {
0320         .name = "mpq7920",
0321         .of_match_table = of_match_ptr(mpq7920_of_match),
0322     },
0323     .probe_new = mpq7920_i2c_probe,
0324     .id_table = mpq7920_id,
0325 };
0326 module_i2c_driver(mpq7920_regulator_driver);
0327 
0328 MODULE_AUTHOR("Saravanan Sekar <sravanhome@gmail.com>");
0329 MODULE_DESCRIPTION("MPQ7920 PMIC regulator driver");
0330 MODULE_LICENSE("GPL");