Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 //
0003 // MP8867/MP8869 regulator driver
0004 //
0005 // Copyright (C) 2020 Synaptics Incorporated
0006 //
0007 // Author: Jisheng Zhang <jszhang@kernel.org>
0008 
0009 #include <linux/gpio/consumer.h>
0010 #include <linux/i2c.h>
0011 #include <linux/module.h>
0012 #include <linux/of_device.h>
0013 #include <linux/regmap.h>
0014 #include <linux/regulator/driver.h>
0015 #include <linux/regulator/of_regulator.h>
0016 
0017 #define MP886X_VSEL     0x00
0018 #define  MP886X_V_BOOT      (1 << 7)
0019 #define MP886X_SYSCNTLREG1  0x01
0020 #define  MP886X_MODE        (1 << 0)
0021 #define  MP886X_SLEW_SHIFT  3
0022 #define  MP886X_SLEW_MASK   (0x7 << MP886X_SLEW_SHIFT)
0023 #define  MP886X_GO      (1 << 6)
0024 #define  MP886X_EN      (1 << 7)
0025 #define MP8869_SYSCNTLREG2  0x02
0026 
0027 struct mp886x_cfg_info {
0028     const struct regulator_ops *rops;
0029     const unsigned int slew_rates[8];
0030     const int switch_freq[4];
0031     const u8 fs_reg;
0032     const u8 fs_shift;
0033 };
0034 
0035 struct mp886x_device_info {
0036     struct device *dev;
0037     struct regulator_desc desc;
0038     struct regulator_init_data *regulator;
0039     struct gpio_desc *en_gpio;
0040     const struct mp886x_cfg_info *ci;
0041     u32 r[2];
0042     unsigned int sel;
0043 };
0044 
0045 static void mp886x_set_switch_freq(struct mp886x_device_info *di,
0046                    struct regmap *regmap,
0047                    u32 freq)
0048 {
0049     const struct mp886x_cfg_info *ci = di->ci;
0050     int i;
0051 
0052     for (i = 0; i < ARRAY_SIZE(ci->switch_freq); i++) {
0053         if (freq == ci->switch_freq[i]) {
0054             regmap_update_bits(regmap, ci->fs_reg,
0055                   0x3 << ci->fs_shift, i << ci->fs_shift);
0056             return;
0057         }
0058     }
0059 
0060     dev_err(di->dev, "invalid frequency %d\n", freq);
0061 }
0062 
0063 static int mp886x_set_mode(struct regulator_dev *rdev, unsigned int mode)
0064 {
0065     switch (mode) {
0066     case REGULATOR_MODE_FAST:
0067         regmap_update_bits(rdev->regmap, MP886X_SYSCNTLREG1,
0068                    MP886X_MODE, MP886X_MODE);
0069         break;
0070     case REGULATOR_MODE_NORMAL:
0071         regmap_update_bits(rdev->regmap, MP886X_SYSCNTLREG1,
0072                    MP886X_MODE, 0);
0073         break;
0074     default:
0075         return -EINVAL;
0076     }
0077     return 0;
0078 }
0079 
0080 static unsigned int mp886x_get_mode(struct regulator_dev *rdev)
0081 {
0082     u32 val;
0083     int ret;
0084 
0085     ret = regmap_read(rdev->regmap, MP886X_SYSCNTLREG1, &val);
0086     if (ret < 0)
0087         return ret;
0088     if (val & MP886X_MODE)
0089         return REGULATOR_MODE_FAST;
0090     else
0091         return REGULATOR_MODE_NORMAL;
0092 }
0093 
0094 static int mp8869_set_voltage_sel(struct regulator_dev *rdev, unsigned int sel)
0095 {
0096     int ret;
0097 
0098     ret = regmap_update_bits(rdev->regmap, MP886X_SYSCNTLREG1,
0099                  MP886X_GO, MP886X_GO);
0100     if (ret < 0)
0101         return ret;
0102 
0103     sel <<= ffs(rdev->desc->vsel_mask) - 1;
0104     return regmap_update_bits(rdev->regmap, rdev->desc->vsel_reg,
0105                   MP886X_V_BOOT | rdev->desc->vsel_mask, sel);
0106 }
0107 
0108 static inline unsigned int mp8869_scale(unsigned int uv, u32 r1, u32 r2)
0109 {
0110     u32 tmp = uv * r1 / r2;
0111 
0112     return uv + tmp;
0113 }
0114 
0115 static int mp8869_get_voltage_sel(struct regulator_dev *rdev)
0116 {
0117     struct mp886x_device_info *di = rdev_get_drvdata(rdev);
0118     int ret, uv;
0119     unsigned int val;
0120     bool fbloop;
0121 
0122     ret = regmap_read(rdev->regmap, rdev->desc->vsel_reg, &val);
0123     if (ret)
0124         return ret;
0125 
0126     fbloop = val & MP886X_V_BOOT;
0127     if (fbloop) {
0128         uv = rdev->desc->min_uV;
0129         uv = mp8869_scale(uv, di->r[0], di->r[1]);
0130         return regulator_map_voltage_linear(rdev, uv, uv);
0131     }
0132 
0133     val &= rdev->desc->vsel_mask;
0134     val >>= ffs(rdev->desc->vsel_mask) - 1;
0135 
0136     return val;
0137 }
0138 
0139 static const struct regulator_ops mp8869_regulator_ops = {
0140     .set_voltage_sel = mp8869_set_voltage_sel,
0141     .get_voltage_sel = mp8869_get_voltage_sel,
0142     .set_voltage_time_sel = regulator_set_voltage_time_sel,
0143     .map_voltage = regulator_map_voltage_linear,
0144     .list_voltage = regulator_list_voltage_linear,
0145     .enable = regulator_enable_regmap,
0146     .disable = regulator_disable_regmap,
0147     .is_enabled = regulator_is_enabled_regmap,
0148     .set_mode = mp886x_set_mode,
0149     .get_mode = mp886x_get_mode,
0150     .set_ramp_delay = regulator_set_ramp_delay_regmap,
0151 };
0152 
0153 static const struct mp886x_cfg_info mp8869_ci = {
0154     .rops = &mp8869_regulator_ops,
0155     .slew_rates = {
0156         40000,
0157         30000,
0158         20000,
0159         10000,
0160         5000,
0161         2500,
0162         1250,
0163         625,
0164     },
0165     .switch_freq = {
0166         500000,
0167         750000,
0168         1000000,
0169         1250000,
0170     },
0171     .fs_reg = MP8869_SYSCNTLREG2,
0172     .fs_shift = 4,
0173 };
0174 
0175 static int mp8867_set_voltage_sel(struct regulator_dev *rdev, unsigned int sel)
0176 {
0177     struct mp886x_device_info *di = rdev_get_drvdata(rdev);
0178     int ret, delta;
0179 
0180     ret = mp8869_set_voltage_sel(rdev, sel);
0181     if (ret < 0)
0182         return ret;
0183 
0184     delta = di->sel - sel;
0185     if (abs(delta) <= 5)
0186         ret = regmap_update_bits(rdev->regmap, MP886X_SYSCNTLREG1,
0187                      MP886X_GO, 0);
0188     di->sel = sel;
0189 
0190     return ret;
0191 }
0192 
0193 static int mp8867_get_voltage_sel(struct regulator_dev *rdev)
0194 {
0195     struct mp886x_device_info *di = rdev_get_drvdata(rdev);
0196     int ret, uv;
0197     unsigned int val;
0198     bool fbloop;
0199 
0200     ret = regmap_read(rdev->regmap, rdev->desc->vsel_reg, &val);
0201     if (ret)
0202         return ret;
0203 
0204     fbloop = val & MP886X_V_BOOT;
0205 
0206     val &= rdev->desc->vsel_mask;
0207     val >>= ffs(rdev->desc->vsel_mask) - 1;
0208 
0209     if (fbloop) {
0210         uv = regulator_list_voltage_linear(rdev, val);
0211         uv = mp8869_scale(uv, di->r[0], di->r[1]);
0212         return regulator_map_voltage_linear(rdev, uv, uv);
0213     }
0214 
0215     return val;
0216 }
0217 
0218 static const struct regulator_ops mp8867_regulator_ops = {
0219     .set_voltage_sel = mp8867_set_voltage_sel,
0220     .get_voltage_sel = mp8867_get_voltage_sel,
0221     .set_voltage_time_sel = regulator_set_voltage_time_sel,
0222     .map_voltage = regulator_map_voltage_linear,
0223     .list_voltage = regulator_list_voltage_linear,
0224     .enable = regulator_enable_regmap,
0225     .disable = regulator_disable_regmap,
0226     .is_enabled = regulator_is_enabled_regmap,
0227     .set_mode = mp886x_set_mode,
0228     .get_mode = mp886x_get_mode,
0229     .set_ramp_delay = regulator_set_ramp_delay_regmap,
0230 };
0231 
0232 static const struct mp886x_cfg_info mp8867_ci = {
0233     .rops = &mp8867_regulator_ops,
0234     .slew_rates = {
0235         64000,
0236         32000,
0237         16000,
0238         8000,
0239         4000,
0240         2000,
0241         1000,
0242         500,
0243     },
0244     .switch_freq = {
0245         500000,
0246         750000,
0247         1000000,
0248         1500000,
0249     },
0250     .fs_reg = MP886X_SYSCNTLREG1,
0251     .fs_shift = 1,
0252 };
0253 
0254 static int mp886x_regulator_register(struct mp886x_device_info *di,
0255                      struct regulator_config *config)
0256 {
0257     struct regulator_desc *rdesc = &di->desc;
0258     struct regulator_dev *rdev;
0259 
0260     rdesc->name = "mp886x-reg";
0261     rdesc->supply_name = "vin";
0262     rdesc->ops = di->ci->rops;
0263     rdesc->type = REGULATOR_VOLTAGE;
0264     rdesc->n_voltages = 128;
0265     rdesc->enable_reg = MP886X_SYSCNTLREG1;
0266     rdesc->enable_mask = MP886X_EN;
0267     rdesc->min_uV = 600000;
0268     rdesc->uV_step = 10000;
0269     rdesc->vsel_reg = MP886X_VSEL;
0270     rdesc->vsel_mask = 0x3f;
0271     rdesc->ramp_reg = MP886X_SYSCNTLREG1;
0272     rdesc->ramp_mask = MP886X_SLEW_MASK;
0273     rdesc->ramp_delay_table = di->ci->slew_rates;
0274     rdesc->n_ramp_values = ARRAY_SIZE(di->ci->slew_rates);
0275     rdesc->owner = THIS_MODULE;
0276 
0277     rdev = devm_regulator_register(di->dev, &di->desc, config);
0278     if (IS_ERR(rdev))
0279         return PTR_ERR(rdev);
0280     di->sel = rdesc->ops->get_voltage_sel(rdev);
0281     return 0;
0282 }
0283 
0284 static const struct regmap_config mp886x_regmap_config = {
0285     .reg_bits = 8,
0286     .val_bits = 8,
0287 };
0288 
0289 static int mp886x_i2c_probe(struct i2c_client *client)
0290 {
0291     struct device *dev = &client->dev;
0292     struct device_node *np = dev->of_node;
0293     struct mp886x_device_info *di;
0294     struct regulator_config config = { };
0295     struct regmap *regmap;
0296     u32 freq;
0297     int ret;
0298 
0299     di = devm_kzalloc(dev, sizeof(struct mp886x_device_info), GFP_KERNEL);
0300     if (!di)
0301         return -ENOMEM;
0302 
0303     di->regulator = of_get_regulator_init_data(dev, np, &di->desc);
0304     if (!di->regulator) {
0305         dev_err(dev, "Platform data not found!\n");
0306         return -EINVAL;
0307     }
0308 
0309     ret = of_property_read_u32_array(np, "mps,fb-voltage-divider",
0310                      di->r, 2);
0311     if (ret)
0312         return ret;
0313 
0314     di->en_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_HIGH);
0315     if (IS_ERR(di->en_gpio))
0316         return PTR_ERR(di->en_gpio);
0317 
0318     di->ci = of_device_get_match_data(dev);
0319     di->dev = dev;
0320 
0321     regmap = devm_regmap_init_i2c(client, &mp886x_regmap_config);
0322     if (IS_ERR(regmap)) {
0323         dev_err(dev, "Failed to allocate regmap!\n");
0324         return PTR_ERR(regmap);
0325     }
0326     i2c_set_clientdata(client, di);
0327 
0328     config.dev = di->dev;
0329     config.init_data = di->regulator;
0330     config.regmap = regmap;
0331     config.driver_data = di;
0332     config.of_node = np;
0333 
0334     if (!of_property_read_u32(np, "mps,switch-frequency-hz", &freq))
0335         mp886x_set_switch_freq(di, regmap, freq);
0336 
0337     ret = mp886x_regulator_register(di, &config);
0338     if (ret < 0)
0339         dev_err(dev, "Failed to register regulator!\n");
0340     return ret;
0341 }
0342 
0343 static const struct of_device_id mp886x_dt_ids[] = {
0344     {
0345         .compatible = "mps,mp8867",
0346         .data = &mp8867_ci
0347     },
0348     {
0349         .compatible = "mps,mp8869",
0350         .data = &mp8869_ci
0351     },
0352     { }
0353 };
0354 MODULE_DEVICE_TABLE(of, mp886x_dt_ids);
0355 
0356 static const struct i2c_device_id mp886x_id[] = {
0357     { "mp886x", },
0358     { },
0359 };
0360 MODULE_DEVICE_TABLE(i2c, mp886x_id);
0361 
0362 static struct i2c_driver mp886x_regulator_driver = {
0363     .driver = {
0364         .name = "mp886x-regulator",
0365         .of_match_table = of_match_ptr(mp886x_dt_ids),
0366     },
0367     .probe_new = mp886x_i2c_probe,
0368     .id_table = mp886x_id,
0369 };
0370 module_i2c_driver(mp886x_regulator_driver);
0371 
0372 MODULE_AUTHOR("Jisheng Zhang <jszhang@kernel.org>");
0373 MODULE_DESCRIPTION("MP886x regulator driver");
0374 MODULE_LICENSE("GPL v2");