Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 //
0003 // da9052-regulator.c: Regulator driver for DA9052
0004 //
0005 // Copyright(c) 2011 Dialog Semiconductor Ltd.
0006 //
0007 // Author: David Dajun Chen <dchen@diasemi.com>
0008 
0009 #include <linux/module.h>
0010 #include <linux/moduleparam.h>
0011 #include <linux/init.h>
0012 #include <linux/err.h>
0013 #include <linux/platform_device.h>
0014 #include <linux/regulator/driver.h>
0015 #include <linux/regulator/machine.h>
0016 #include <linux/of.h>
0017 #include <linux/regulator/of_regulator.h>
0018 
0019 #include <linux/mfd/da9052/da9052.h>
0020 #include <linux/mfd/da9052/reg.h>
0021 #include <linux/mfd/da9052/pdata.h>
0022 
0023 /* Buck step size */
0024 #define DA9052_BUCK_PERI_3uV_STEP       100000
0025 #define DA9052_BUCK_PERI_REG_MAP_UPTO_3uV   24
0026 #define DA9052_CONST_3uV            3000000
0027 
0028 #define DA9052_MIN_UA       0
0029 #define DA9052_MAX_UA       3
0030 #define DA9052_CURRENT_RANGE    4
0031 
0032 /* Bit masks */
0033 #define DA9052_BUCK_ILIM_MASK_EVEN  0x0c
0034 #define DA9052_BUCK_ILIM_MASK_ODD   0xc0
0035 
0036 /* DA9052 REGULATOR IDs */
0037 #define DA9052_ID_BUCK1     0
0038 #define DA9052_ID_BUCK2     1
0039 #define DA9052_ID_BUCK3     2
0040 #define DA9052_ID_BUCK4     3
0041 #define DA9052_ID_LDO1      4
0042 #define DA9052_ID_LDO2      5
0043 #define DA9052_ID_LDO3      6
0044 #define DA9052_ID_LDO4      7
0045 #define DA9052_ID_LDO5      8
0046 #define DA9052_ID_LDO6      9
0047 #define DA9052_ID_LDO7      10
0048 #define DA9052_ID_LDO8      11
0049 #define DA9052_ID_LDO9      12
0050 #define DA9052_ID_LDO10     13
0051 
0052 static const u32 da9052_current_limits[3][4] = {
0053     {700000, 800000, 1000000, 1200000}, /* DA9052-BC BUCKs */
0054     {1600000, 2000000, 2400000, 3000000},   /* DA9053-AA/Bx BUCK-CORE */
0055     {800000, 1000000, 1200000, 1500000},    /* DA9053-AA/Bx BUCK-PRO,
0056                          * BUCK-MEM and BUCK-PERI
0057                         */
0058 };
0059 
0060 struct da9052_regulator_info {
0061     struct regulator_desc reg_desc;
0062     int step_uV;
0063     int min_uV;
0064     int max_uV;
0065     unsigned char activate_bit;
0066 };
0067 
0068 struct da9052_regulator {
0069     struct da9052 *da9052;
0070     struct da9052_regulator_info *info;
0071     struct regulator_dev *rdev;
0072 };
0073 
0074 static int verify_range(struct da9052_regulator_info *info,
0075              int min_uV, int max_uV)
0076 {
0077     if (min_uV > info->max_uV || max_uV < info->min_uV)
0078         return -EINVAL;
0079 
0080     return 0;
0081 }
0082 
0083 static int da9052_dcdc_get_current_limit(struct regulator_dev *rdev)
0084 {
0085     struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
0086     int offset = rdev_get_id(rdev);
0087     int ret, row = 2;
0088 
0089     ret = da9052_reg_read(regulator->da9052, DA9052_BUCKA_REG + offset/2);
0090     if (ret < 0)
0091         return ret;
0092 
0093     /* Determine the even or odd position of the buck current limit
0094      * register field
0095     */
0096     if (offset % 2 == 0)
0097         ret = (ret & DA9052_BUCK_ILIM_MASK_EVEN) >> 2;
0098     else
0099         ret = (ret & DA9052_BUCK_ILIM_MASK_ODD) >> 6;
0100 
0101     /* Select the appropriate current limit range */
0102     if (regulator->da9052->chip_id == DA9052)
0103         row = 0;
0104     else if (offset == 0)
0105         row = 1;
0106 
0107     return da9052_current_limits[row][ret];
0108 }
0109 
0110 static int da9052_dcdc_set_current_limit(struct regulator_dev *rdev, int min_uA,
0111                       int max_uA)
0112 {
0113     struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
0114     int offset = rdev_get_id(rdev);
0115     int reg_val = 0;
0116     int i, row = 2;
0117 
0118     /* Select the appropriate current limit range */
0119     if (regulator->da9052->chip_id == DA9052)
0120         row = 0;
0121     else if (offset == 0)
0122         row = 1;
0123 
0124     for (i = DA9052_CURRENT_RANGE - 1; i >= 0; i--) {
0125         if ((min_uA <= da9052_current_limits[row][i]) &&
0126             (da9052_current_limits[row][i] <= max_uA)) {
0127             reg_val = i;
0128             break;
0129         }
0130     }
0131 
0132     if (i < 0)
0133         return -EINVAL;
0134 
0135     /* Determine the even or odd position of the buck current limit
0136      * register field
0137     */
0138     if (offset % 2 == 0)
0139         return da9052_reg_update(regulator->da9052,
0140                      DA9052_BUCKA_REG + offset/2,
0141                      DA9052_BUCK_ILIM_MASK_EVEN,
0142                      reg_val << 2);
0143     else
0144         return da9052_reg_update(regulator->da9052,
0145                      DA9052_BUCKA_REG + offset/2,
0146                      DA9052_BUCK_ILIM_MASK_ODD,
0147                      reg_val << 6);
0148 }
0149 
0150 static int da9052_list_voltage(struct regulator_dev *rdev,
0151                 unsigned int selector)
0152 {
0153     struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
0154     struct da9052_regulator_info *info = regulator->info;
0155     int id = rdev_get_id(rdev);
0156     int volt_uV;
0157 
0158     if ((id == DA9052_ID_BUCK4) && (regulator->da9052->chip_id == DA9052)
0159         && (selector >= DA9052_BUCK_PERI_REG_MAP_UPTO_3uV)) {
0160         volt_uV = ((DA9052_BUCK_PERI_REG_MAP_UPTO_3uV * info->step_uV)
0161               + info->min_uV);
0162         volt_uV += (selector - DA9052_BUCK_PERI_REG_MAP_UPTO_3uV)
0163                     * (DA9052_BUCK_PERI_3uV_STEP);
0164     } else {
0165         volt_uV = (selector * info->step_uV) + info->min_uV;
0166     }
0167 
0168     if (volt_uV > info->max_uV)
0169         return -EINVAL;
0170 
0171     return volt_uV;
0172 }
0173 
0174 static int da9052_map_voltage(struct regulator_dev *rdev,
0175                   int min_uV, int max_uV)
0176 {
0177     struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
0178     struct da9052_regulator_info *info = regulator->info;
0179     int id = rdev_get_id(rdev);
0180     int ret, sel;
0181 
0182     ret = verify_range(info, min_uV, max_uV);
0183     if (ret < 0)
0184         return ret;
0185 
0186     if (min_uV < info->min_uV)
0187         min_uV = info->min_uV;
0188 
0189     if ((id == DA9052_ID_BUCK4) && (regulator->da9052->chip_id == DA9052)
0190         && (min_uV >= DA9052_CONST_3uV)) {
0191             sel = DA9052_BUCK_PERI_REG_MAP_UPTO_3uV +
0192                   DIV_ROUND_UP(min_uV - DA9052_CONST_3uV,
0193                        DA9052_BUCK_PERI_3uV_STEP);
0194     } else {
0195         sel = DIV_ROUND_UP(min_uV - info->min_uV, info->step_uV);
0196     }
0197 
0198     ret = da9052_list_voltage(rdev, sel);
0199     if (ret < 0)
0200         return ret;
0201 
0202     return sel;
0203 }
0204 
0205 static int da9052_regulator_set_voltage_sel(struct regulator_dev *rdev,
0206                         unsigned int selector)
0207 {
0208     struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
0209     struct da9052_regulator_info *info = regulator->info;
0210     int id = rdev_get_id(rdev);
0211     int ret;
0212 
0213     ret = da9052_reg_update(regulator->da9052, rdev->desc->vsel_reg,
0214                 rdev->desc->vsel_mask, selector);
0215     if (ret < 0)
0216         return ret;
0217 
0218     /* Some LDOs and DCDCs are DVC controlled which requires enabling of
0219      * the activate bit to implment the changes on the output.
0220      */
0221     switch (id) {
0222     case DA9052_ID_BUCK1:
0223     case DA9052_ID_BUCK2:
0224     case DA9052_ID_BUCK3:
0225     case DA9052_ID_LDO2:
0226     case DA9052_ID_LDO3:
0227         ret = da9052_reg_update(regulator->da9052, DA9052_SUPPLY_REG,
0228                     info->activate_bit, info->activate_bit);
0229         break;
0230     }
0231 
0232     return ret;
0233 }
0234 
0235 static int da9052_regulator_set_voltage_time_sel(struct regulator_dev *rdev,
0236                          unsigned int old_sel,
0237                          unsigned int new_sel)
0238 {
0239     struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
0240     struct da9052_regulator_info *info = regulator->info;
0241     int id = rdev_get_id(rdev);
0242     int ret = 0;
0243 
0244     /* The DVC controlled LDOs and DCDCs ramp with 6.25mV/µs after enabling
0245      * the activate bit.
0246      */
0247     switch (id) {
0248     case DA9052_ID_BUCK1:
0249     case DA9052_ID_BUCK2:
0250     case DA9052_ID_BUCK3:
0251     case DA9052_ID_LDO2:
0252     case DA9052_ID_LDO3:
0253         ret = DIV_ROUND_UP(abs(new_sel - old_sel) * info->step_uV,
0254                    6250);
0255         break;
0256     }
0257 
0258     return ret;
0259 }
0260 
0261 static const struct regulator_ops da9052_dcdc_ops = {
0262     .get_current_limit = da9052_dcdc_get_current_limit,
0263     .set_current_limit = da9052_dcdc_set_current_limit,
0264 
0265     .list_voltage = da9052_list_voltage,
0266     .map_voltage = da9052_map_voltage,
0267     .get_voltage_sel = regulator_get_voltage_sel_regmap,
0268     .set_voltage_sel = da9052_regulator_set_voltage_sel,
0269     .set_voltage_time_sel = da9052_regulator_set_voltage_time_sel,
0270     .is_enabled = regulator_is_enabled_regmap,
0271     .enable = regulator_enable_regmap,
0272     .disable = regulator_disable_regmap,
0273 };
0274 
0275 static const struct regulator_ops da9052_ldo_ops = {
0276     .list_voltage = da9052_list_voltage,
0277     .map_voltage = da9052_map_voltage,
0278     .get_voltage_sel = regulator_get_voltage_sel_regmap,
0279     .set_voltage_sel = da9052_regulator_set_voltage_sel,
0280     .set_voltage_time_sel = da9052_regulator_set_voltage_time_sel,
0281     .is_enabled = regulator_is_enabled_regmap,
0282     .enable = regulator_enable_regmap,
0283     .disable = regulator_disable_regmap,
0284 };
0285 
0286 #define DA9052_LDO(_id, _name, step, min, max, sbits, ebits, abits) \
0287 {\
0288     .reg_desc = {\
0289         .name = #_name,\
0290         .of_match = of_match_ptr(#_name),\
0291         .regulators_node = of_match_ptr("regulators"),\
0292         .ops = &da9052_ldo_ops,\
0293         .type = REGULATOR_VOLTAGE,\
0294         .id = DA9052_ID_##_id,\
0295         .n_voltages = (max - min) / step + 1, \
0296         .owner = THIS_MODULE,\
0297         .vsel_reg = DA9052_BUCKCORE_REG + DA9052_ID_##_id, \
0298         .vsel_mask = (1 << (sbits)) - 1,\
0299         .enable_reg = DA9052_BUCKCORE_REG + DA9052_ID_##_id, \
0300         .enable_mask = 1 << (ebits),\
0301     },\
0302     .min_uV = (min) * 1000,\
0303     .max_uV = (max) * 1000,\
0304     .step_uV = (step) * 1000,\
0305     .activate_bit = (abits),\
0306 }
0307 
0308 #define DA9052_DCDC(_id, _name, step, min, max, sbits, ebits, abits) \
0309 {\
0310     .reg_desc = {\
0311         .name = #_name,\
0312         .of_match = of_match_ptr(#_name),\
0313         .regulators_node = of_match_ptr("regulators"),\
0314         .ops = &da9052_dcdc_ops,\
0315         .type = REGULATOR_VOLTAGE,\
0316         .id = DA9052_ID_##_id,\
0317         .n_voltages = (max - min) / step + 1, \
0318         .owner = THIS_MODULE,\
0319         .vsel_reg = DA9052_BUCKCORE_REG + DA9052_ID_##_id, \
0320         .vsel_mask = (1 << (sbits)) - 1,\
0321         .enable_reg = DA9052_BUCKCORE_REG + DA9052_ID_##_id, \
0322         .enable_mask = 1 << (ebits),\
0323     },\
0324     .min_uV = (min) * 1000,\
0325     .max_uV = (max) * 1000,\
0326     .step_uV = (step) * 1000,\
0327     .activate_bit = (abits),\
0328 }
0329 
0330 static struct da9052_regulator_info da9052_regulator_info[] = {
0331     DA9052_DCDC(BUCK1, buck1, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBCOREGO),
0332     DA9052_DCDC(BUCK2, buck2, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBPROGO),
0333     DA9052_DCDC(BUCK3, buck3, 25, 950, 2525, 6, 6, DA9052_SUPPLY_VBMEMGO),
0334     DA9052_DCDC(BUCK4, buck4, 50, 1800, 3600, 5, 6, 0),
0335     DA9052_LDO(LDO1, ldo1, 50, 600, 1800, 5, 6, 0),
0336     DA9052_LDO(LDO2, ldo2, 25, 600, 1800, 6, 6, DA9052_SUPPLY_VLDO2GO),
0337     DA9052_LDO(LDO3, ldo3, 25, 1725, 3300, 6, 6, DA9052_SUPPLY_VLDO3GO),
0338     DA9052_LDO(LDO4, ldo4, 25, 1725, 3300, 6, 6, 0),
0339     DA9052_LDO(LDO5, ldo5, 50, 1200, 3600, 6, 6, 0),
0340     DA9052_LDO(LDO6, ldo6, 50, 1200, 3600, 6, 6, 0),
0341     DA9052_LDO(LDO7, ldo7, 50, 1200, 3600, 6, 6, 0),
0342     DA9052_LDO(LDO8, ldo8, 50, 1200, 3600, 6, 6, 0),
0343     DA9052_LDO(LDO9, ldo9, 50, 1250, 3650, 6, 6, 0),
0344     DA9052_LDO(LDO10, ldo10, 50, 1200, 3600, 6, 6, 0),
0345 };
0346 
0347 static struct da9052_regulator_info da9053_regulator_info[] = {
0348     DA9052_DCDC(BUCK1, buck1, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBCOREGO),
0349     DA9052_DCDC(BUCK2, buck2, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBPROGO),
0350     DA9052_DCDC(BUCK3, buck3, 25, 950, 2525, 6, 6, DA9052_SUPPLY_VBMEMGO),
0351     DA9052_DCDC(BUCK4, buck4, 25, 950, 2525, 6, 6, 0),
0352     DA9052_LDO(LDO1, ldo1, 50, 600, 1800, 5, 6, 0),
0353     DA9052_LDO(LDO2, ldo2, 25, 600, 1800, 6, 6, DA9052_SUPPLY_VLDO2GO),
0354     DA9052_LDO(LDO3, ldo3, 25, 1725, 3300, 6, 6, DA9052_SUPPLY_VLDO3GO),
0355     DA9052_LDO(LDO4, ldo4, 25, 1725, 3300, 6, 6, 0),
0356     DA9052_LDO(LDO5, ldo5, 50, 1200, 3600, 6, 6, 0),
0357     DA9052_LDO(LDO6, ldo6, 50, 1200, 3600, 6, 6, 0),
0358     DA9052_LDO(LDO7, ldo7, 50, 1200, 3600, 6, 6, 0),
0359     DA9052_LDO(LDO8, ldo8, 50, 1200, 3600, 6, 6, 0),
0360     DA9052_LDO(LDO9, ldo9, 50, 1250, 3650, 6, 6, 0),
0361     DA9052_LDO(LDO10, ldo10, 50, 1200, 3600, 6, 6, 0),
0362 };
0363 
0364 static inline struct da9052_regulator_info *find_regulator_info(u8 chip_id,
0365                                  int id)
0366 {
0367     struct da9052_regulator_info *info;
0368     int i;
0369 
0370     switch (chip_id) {
0371     case DA9052:
0372         for (i = 0; i < ARRAY_SIZE(da9052_regulator_info); i++) {
0373             info = &da9052_regulator_info[i];
0374             if (info->reg_desc.id == id)
0375                 return info;
0376         }
0377         break;
0378     case DA9053_AA:
0379     case DA9053_BA:
0380     case DA9053_BB:
0381     case DA9053_BC:
0382         for (i = 0; i < ARRAY_SIZE(da9053_regulator_info); i++) {
0383             info = &da9053_regulator_info[i];
0384             if (info->reg_desc.id == id)
0385                 return info;
0386         }
0387         break;
0388     }
0389 
0390     return NULL;
0391 }
0392 
0393 static int da9052_regulator_probe(struct platform_device *pdev)
0394 {
0395     const struct mfd_cell *cell = mfd_get_cell(pdev);
0396     struct regulator_config config = { };
0397     struct da9052_regulator *regulator;
0398     struct da9052 *da9052;
0399     struct da9052_pdata *pdata;
0400 
0401     regulator = devm_kzalloc(&pdev->dev, sizeof(struct da9052_regulator),
0402                  GFP_KERNEL);
0403     if (!regulator)
0404         return -ENOMEM;
0405 
0406     da9052 = dev_get_drvdata(pdev->dev.parent);
0407     pdata = dev_get_platdata(da9052->dev);
0408     regulator->da9052 = da9052;
0409 
0410     regulator->info = find_regulator_info(regulator->da9052->chip_id,
0411                           cell->id);
0412     if (regulator->info == NULL) {
0413         dev_err(&pdev->dev, "invalid regulator ID specified\n");
0414         return -EINVAL;
0415     }
0416 
0417     config.dev = da9052->dev;
0418     config.driver_data = regulator;
0419     config.regmap = da9052->regmap;
0420     if (pdata)
0421         config.init_data = pdata->regulators[cell->id];
0422 
0423     regulator->rdev = devm_regulator_register(&pdev->dev,
0424                           &regulator->info->reg_desc,
0425                           &config);
0426     if (IS_ERR(regulator->rdev)) {
0427         dev_err(&pdev->dev, "failed to register regulator %s\n",
0428             regulator->info->reg_desc.name);
0429         return PTR_ERR(regulator->rdev);
0430     }
0431 
0432     platform_set_drvdata(pdev, regulator);
0433 
0434     return 0;
0435 }
0436 
0437 static struct platform_driver da9052_regulator_driver = {
0438     .probe = da9052_regulator_probe,
0439     .driver = {
0440         .name = "da9052-regulator",
0441     },
0442 };
0443 
0444 static int __init da9052_regulator_init(void)
0445 {
0446     return platform_driver_register(&da9052_regulator_driver);
0447 }
0448 subsys_initcall(da9052_regulator_init);
0449 
0450 static void __exit da9052_regulator_exit(void)
0451 {
0452     platform_driver_unregister(&da9052_regulator_driver);
0453 }
0454 module_exit(da9052_regulator_exit);
0455 
0456 MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");
0457 MODULE_DESCRIPTION("Power Regulator driver for Dialog DA9052 PMIC");
0458 MODULE_LICENSE("GPL");
0459 MODULE_ALIAS("platform:da9052-regulator");