0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/kernel.h>
0009 #include <linux/init.h>
0010 #include <linux/err.h>
0011 #include <linux/of.h>
0012 #include <linux/regulator/of_regulator.h>
0013 #include <linux/platform_device.h>
0014 #include <linux/regulator/driver.h>
0015 #include <linux/regulator/machine.h>
0016 #include <linux/mfd/88pm860x.h>
0017 #include <linux/module.h>
0018
0019 struct pm8607_regulator_info {
0020 struct regulator_desc desc;
0021
0022 unsigned int *vol_suspend;
0023
0024 int slope_double;
0025 };
0026
0027 static const unsigned int BUCK1_table[] = {
0028 725000, 750000, 775000, 800000, 825000, 850000, 875000, 900000,
0029 925000, 950000, 975000, 1000000, 1025000, 1050000, 1075000, 1100000,
0030 1125000, 1150000, 1175000, 1200000, 1225000, 1250000, 1275000, 1300000,
0031 1325000, 1350000, 1375000, 1400000, 1425000, 1450000, 1475000, 1500000,
0032 0, 25000, 50000, 75000, 100000, 125000, 150000, 175000,
0033 200000, 225000, 250000, 275000, 300000, 325000, 350000, 375000,
0034 400000, 425000, 450000, 475000, 500000, 525000, 550000, 575000,
0035 600000, 625000, 650000, 675000, 700000, 725000, 750000, 775000,
0036 };
0037
0038 static const unsigned int BUCK1_suspend_table[] = {
0039 0, 25000, 50000, 75000, 100000, 125000, 150000, 175000,
0040 200000, 225000, 250000, 275000, 300000, 325000, 350000, 375000,
0041 400000, 425000, 450000, 475000, 500000, 525000, 550000, 575000,
0042 600000, 625000, 650000, 675000, 700000, 725000, 750000, 775000,
0043 800000, 825000, 850000, 875000, 900000, 925000, 950000, 975000,
0044 1000000, 1025000, 1050000, 1075000, 1100000, 1125000, 1150000, 1175000,
0045 1200000, 1225000, 1250000, 1275000, 1300000, 1325000, 1350000, 1375000,
0046 1400000, 1425000, 1450000, 1475000, 1500000, 1500000, 1500000, 1500000,
0047 };
0048
0049 static const unsigned int BUCK2_table[] = {
0050 0, 50000, 100000, 150000, 200000, 250000, 300000, 350000,
0051 400000, 450000, 500000, 550000, 600000, 650000, 700000, 750000,
0052 800000, 850000, 900000, 950000, 1000000, 1050000, 1100000, 1150000,
0053 1200000, 1250000, 1300000, 1350000, 1400000, 1450000, 1500000, 1550000,
0054 1600000, 1650000, 1700000, 1750000, 1800000, 1850000, 1900000, 1950000,
0055 2000000, 2050000, 2100000, 2150000, 2200000, 2250000, 2300000, 2350000,
0056 2400000, 2450000, 2500000, 2550000, 2600000, 2650000, 2700000, 2750000,
0057 2800000, 2850000, 2900000, 2950000, 3000000, 3000000, 3000000, 3000000,
0058 };
0059
0060 static const unsigned int BUCK2_suspend_table[] = {
0061 0, 50000, 100000, 150000, 200000, 250000, 300000, 350000,
0062 400000, 450000, 500000, 550000, 600000, 650000, 700000, 750000,
0063 800000, 850000, 900000, 950000, 1000000, 1050000, 1100000, 1150000,
0064 1200000, 1250000, 1300000, 1350000, 1400000, 1450000, 1500000, 1550000,
0065 1600000, 1650000, 1700000, 1750000, 1800000, 1850000, 1900000, 1950000,
0066 2000000, 2050000, 2100000, 2150000, 2200000, 2250000, 2300000, 2350000,
0067 2400000, 2450000, 2500000, 2550000, 2600000, 2650000, 2700000, 2750000,
0068 2800000, 2850000, 2900000, 2950000, 3000000, 3000000, 3000000, 3000000,
0069 };
0070
0071 static const unsigned int BUCK3_table[] = {
0072 0, 25000, 50000, 75000, 100000, 125000, 150000, 175000,
0073 200000, 225000, 250000, 275000, 300000, 325000, 350000, 375000,
0074 400000, 425000, 450000, 475000, 500000, 525000, 550000, 575000,
0075 600000, 625000, 650000, 675000, 700000, 725000, 750000, 775000,
0076 800000, 825000, 850000, 875000, 900000, 925000, 950000, 975000,
0077 1000000, 1025000, 1050000, 1075000, 1100000, 1125000, 1150000, 1175000,
0078 1200000, 1225000, 1250000, 1275000, 1300000, 1325000, 1350000, 1375000,
0079 1400000, 1425000, 1450000, 1475000, 1500000, 1500000, 1500000, 1500000,
0080 };
0081
0082 static const unsigned int BUCK3_suspend_table[] = {
0083 0, 25000, 50000, 75000, 100000, 125000, 150000, 175000,
0084 200000, 225000, 250000, 275000, 300000, 325000, 350000, 375000,
0085 400000, 425000, 450000, 475000, 500000, 525000, 550000, 575000,
0086 600000, 625000, 650000, 675000, 700000, 725000, 750000, 775000,
0087 800000, 825000, 850000, 875000, 900000, 925000, 950000, 975000,
0088 1000000, 1025000, 1050000, 1075000, 1100000, 1125000, 1150000, 1175000,
0089 1200000, 1225000, 1250000, 1275000, 1300000, 1325000, 1350000, 1375000,
0090 1400000, 1425000, 1450000, 1475000, 1500000, 1500000, 1500000, 1500000,
0091 };
0092
0093 static const unsigned int LDO1_table[] = {
0094 1800000, 1200000, 2800000, 0,
0095 };
0096
0097 static const unsigned int LDO1_suspend_table[] = {
0098 1800000, 1200000, 0, 0,
0099 };
0100
0101 static const unsigned int LDO2_table[] = {
0102 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 3300000,
0103 };
0104
0105 static const unsigned int LDO2_suspend_table[] = {
0106 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 2900000,
0107 };
0108
0109 static const unsigned int LDO3_table[] = {
0110 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 3300000,
0111 };
0112
0113 static const unsigned int LDO3_suspend_table[] = {
0114 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 2900000,
0115 };
0116
0117 static const unsigned int LDO4_table[] = {
0118 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2900000, 3300000,
0119 };
0120
0121 static const unsigned int LDO4_suspend_table[] = {
0122 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2900000, 2900000,
0123 };
0124
0125 static const unsigned int LDO5_table[] = {
0126 2900000, 3000000, 3100000, 3300000,
0127 };
0128
0129 static const unsigned int LDO5_suspend_table[] = {
0130 2900000, 0, 0, 0,
0131 };
0132
0133 static const unsigned int LDO6_table[] = {
0134 1800000, 1850000, 2600000, 2650000, 2700000, 2750000, 2800000, 3300000,
0135 };
0136
0137 static const unsigned int LDO6_suspend_table[] = {
0138 1800000, 1850000, 2600000, 2650000, 2700000, 2750000, 2800000, 2900000,
0139 };
0140
0141 static const unsigned int LDO7_table[] = {
0142 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 2900000,
0143 };
0144
0145 static const unsigned int LDO7_suspend_table[] = {
0146 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 2900000,
0147 };
0148
0149 static const unsigned int LDO8_table[] = {
0150 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 2900000,
0151 };
0152
0153 static const unsigned int LDO8_suspend_table[] = {
0154 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 2900000,
0155 };
0156
0157 static const unsigned int LDO9_table[] = {
0158 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 3300000,
0159 };
0160
0161 static const unsigned int LDO9_suspend_table[] = {
0162 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 2900000,
0163 };
0164
0165 static const unsigned int LDO10_table[] = {
0166 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 3300000,
0167 1200000, 1200000, 1200000, 1200000, 1200000, 1200000, 1200000, 1200000,
0168 };
0169
0170 static const unsigned int LDO10_suspend_table[] = {
0171 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 2900000,
0172 1200000, 1200000, 1200000, 1200000, 1200000, 1200000, 1200000, 1200000,
0173 };
0174
0175 static const unsigned int LDO12_table[] = {
0176 1800000, 1900000, 2700000, 2800000, 2900000, 3000000, 3100000, 3300000,
0177 1200000, 1200000, 1200000, 1200000, 1200000, 1200000, 1200000, 1200000,
0178 };
0179
0180 static const unsigned int LDO12_suspend_table[] = {
0181 1800000, 1900000, 2700000, 2800000, 2900000, 2900000, 2900000, 2900000,
0182 1200000, 1200000, 1200000, 1200000, 1200000, 1200000, 1200000, 1200000,
0183 };
0184
0185 static const unsigned int LDO13_table[] = {
0186 1200000, 1300000, 1800000, 2000000, 2500000, 2800000, 3000000, 0,
0187 };
0188
0189 static const unsigned int LDO13_suspend_table[] = {
0190 0,
0191 };
0192
0193 static const unsigned int LDO14_table[] = {
0194 1800000, 1850000, 2700000, 2750000, 2800000, 2850000, 2900000, 3300000,
0195 };
0196
0197 static const unsigned int LDO14_suspend_table[] = {
0198 1800000, 1850000, 2700000, 2750000, 2800000, 2850000, 2900000, 2900000,
0199 };
0200
0201 static int pm8607_list_voltage(struct regulator_dev *rdev, unsigned index)
0202 {
0203 struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
0204 int ret;
0205
0206 ret = regulator_list_voltage_table(rdev, index);
0207 if (ret < 0)
0208 return ret;
0209
0210 if (info->slope_double)
0211 ret <<= 1;
0212
0213 return ret;
0214 }
0215
0216 static const struct regulator_ops pm8607_regulator_ops = {
0217 .list_voltage = pm8607_list_voltage,
0218 .set_voltage_sel = regulator_set_voltage_sel_regmap,
0219 .get_voltage_sel = regulator_get_voltage_sel_regmap,
0220 .enable = regulator_enable_regmap,
0221 .disable = regulator_disable_regmap,
0222 .is_enabled = regulator_is_enabled_regmap,
0223 };
0224
0225 static const struct regulator_ops pm8606_preg_ops = {
0226 .enable = regulator_enable_regmap,
0227 .disable = regulator_disable_regmap,
0228 .is_enabled = regulator_is_enabled_regmap,
0229 };
0230
0231 #define PM8606_PREG(ereg, ebit) \
0232 { \
0233 .desc = { \
0234 .name = "PREG", \
0235 .of_match = of_match_ptr("PREG"), \
0236 .regulators_node = of_match_ptr("regulators"), \
0237 .ops = &pm8606_preg_ops, \
0238 .type = REGULATOR_CURRENT, \
0239 .id = PM8606_ID_PREG, \
0240 .owner = THIS_MODULE, \
0241 .enable_reg = PM8606_##ereg, \
0242 .enable_mask = (ebit), \
0243 .enable_is_inverted = true, \
0244 }, \
0245 }
0246
0247 #define PM8607_DVC(vreg, ureg, ubit, ereg, ebit) \
0248 { \
0249 .desc = { \
0250 .name = #vreg, \
0251 .of_match = of_match_ptr(#vreg), \
0252 .regulators_node = of_match_ptr("regulators"), \
0253 .ops = &pm8607_regulator_ops, \
0254 .type = REGULATOR_VOLTAGE, \
0255 .id = PM8607_ID_##vreg, \
0256 .owner = THIS_MODULE, \
0257 .volt_table = vreg##_table, \
0258 .n_voltages = ARRAY_SIZE(vreg##_table), \
0259 .vsel_reg = PM8607_##vreg, \
0260 .vsel_mask = ARRAY_SIZE(vreg##_table) - 1, \
0261 .apply_reg = PM8607_##ureg, \
0262 .apply_bit = (ubit), \
0263 .enable_reg = PM8607_##ereg, \
0264 .enable_mask = 1 << (ebit), \
0265 }, \
0266 .slope_double = (0), \
0267 .vol_suspend = (unsigned int *)&vreg##_suspend_table, \
0268 }
0269
0270 #define PM8607_LDO(_id, vreg, shift, ereg, ebit) \
0271 { \
0272 .desc = { \
0273 .name = "LDO" #_id, \
0274 .of_match = of_match_ptr("LDO" #_id), \
0275 .regulators_node = of_match_ptr("regulators"), \
0276 .ops = &pm8607_regulator_ops, \
0277 .type = REGULATOR_VOLTAGE, \
0278 .id = PM8607_ID_LDO##_id, \
0279 .owner = THIS_MODULE, \
0280 .volt_table = LDO##_id##_table, \
0281 .n_voltages = ARRAY_SIZE(LDO##_id##_table), \
0282 .vsel_reg = PM8607_##vreg, \
0283 .vsel_mask = (ARRAY_SIZE(LDO##_id##_table) - 1) << (shift), \
0284 .enable_reg = PM8607_##ereg, \
0285 .enable_mask = 1 << (ebit), \
0286 }, \
0287 .slope_double = (0), \
0288 .vol_suspend = (unsigned int *)&LDO##_id##_suspend_table, \
0289 }
0290
0291 static struct pm8607_regulator_info pm8607_regulator_info[] = {
0292 PM8607_DVC(BUCK1, GO, BIT(0), SUPPLIES_EN11, 0),
0293 PM8607_DVC(BUCK2, GO, BIT(1), SUPPLIES_EN11, 1),
0294 PM8607_DVC(BUCK3, GO, BIT(2), SUPPLIES_EN11, 2),
0295
0296 PM8607_LDO(1, LDO1, 0, SUPPLIES_EN11, 3),
0297 PM8607_LDO(2, LDO2, 0, SUPPLIES_EN11, 4),
0298 PM8607_LDO(3, LDO3, 0, SUPPLIES_EN11, 5),
0299 PM8607_LDO(4, LDO4, 0, SUPPLIES_EN11, 6),
0300 PM8607_LDO(5, LDO5, 0, SUPPLIES_EN11, 7),
0301 PM8607_LDO(6, LDO6, 0, SUPPLIES_EN12, 0),
0302 PM8607_LDO(7, LDO7, 0, SUPPLIES_EN12, 1),
0303 PM8607_LDO(8, LDO8, 0, SUPPLIES_EN12, 2),
0304 PM8607_LDO(9, LDO9, 0, SUPPLIES_EN12, 3),
0305 PM8607_LDO(10, LDO10, 0, SUPPLIES_EN12, 4),
0306 PM8607_LDO(12, LDO12, 0, SUPPLIES_EN12, 5),
0307 PM8607_LDO(13, VIBRATOR_SET, 1, VIBRATOR_SET, 0),
0308 PM8607_LDO(14, LDO14, 0, SUPPLIES_EN12, 6),
0309 };
0310
0311 static struct pm8607_regulator_info pm8606_regulator_info[] = {
0312 PM8606_PREG(PREREGULATORB, 5),
0313 };
0314
0315 static int pm8607_regulator_probe(struct platform_device *pdev)
0316 {
0317 struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
0318 struct pm8607_regulator_info *info = NULL;
0319 struct regulator_init_data *pdata = dev_get_platdata(&pdev->dev);
0320 struct regulator_config config = { };
0321 struct regulator_dev *rdev;
0322 struct resource *res;
0323 int i;
0324
0325 res = platform_get_resource(pdev, IORESOURCE_REG, 0);
0326 if (res) {
0327
0328 for (i = 0; i < ARRAY_SIZE(pm8607_regulator_info); i++) {
0329 info = &pm8607_regulator_info[i];
0330 if (info->desc.vsel_reg == res->start)
0331 break;
0332 }
0333 if (i == ARRAY_SIZE(pm8607_regulator_info)) {
0334 dev_err(&pdev->dev, "Failed to find regulator %llu\n",
0335 (unsigned long long)res->start);
0336 return -EINVAL;
0337 }
0338 } else {
0339
0340 info = &pm8606_regulator_info[0];
0341
0342 i = -1;
0343 }
0344
0345
0346 if ((i == PM8607_ID_BUCK3) && chip->buck3_double)
0347 info->slope_double = 1;
0348
0349 config.dev = chip->dev;
0350 config.driver_data = info;
0351
0352 if (pdata)
0353 config.init_data = pdata;
0354
0355 if (chip->id == CHIP_PM8607)
0356 config.regmap = chip->regmap;
0357 else
0358 config.regmap = chip->regmap_companion;
0359
0360 rdev = devm_regulator_register(&pdev->dev, &info->desc, &config);
0361 if (IS_ERR(rdev)) {
0362 dev_err(&pdev->dev, "failed to register regulator %s\n",
0363 info->desc.name);
0364 return PTR_ERR(rdev);
0365 }
0366
0367 platform_set_drvdata(pdev, info);
0368 return 0;
0369 }
0370
0371 static const struct platform_device_id pm8607_regulator_driver_ids[] = {
0372 {
0373 .name = "88pm860x-regulator",
0374 .driver_data = 0,
0375 }, {
0376 .name = "88pm860x-preg",
0377 .driver_data = 0,
0378 },
0379 { },
0380 };
0381 MODULE_DEVICE_TABLE(platform, pm8607_regulator_driver_ids);
0382
0383 static struct platform_driver pm8607_regulator_driver = {
0384 .driver = {
0385 .name = "88pm860x-regulator",
0386 },
0387 .probe = pm8607_regulator_probe,
0388 .id_table = pm8607_regulator_driver_ids,
0389 };
0390
0391 static int __init pm8607_regulator_init(void)
0392 {
0393 return platform_driver_register(&pm8607_regulator_driver);
0394 }
0395 subsys_initcall(pm8607_regulator_init);
0396
0397 static void __exit pm8607_regulator_exit(void)
0398 {
0399 platform_driver_unregister(&pm8607_regulator_driver);
0400 }
0401 module_exit(pm8607_regulator_exit);
0402
0403 MODULE_LICENSE("GPL");
0404 MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
0405 MODULE_DESCRIPTION("Regulator Driver for Marvell 88PM8607 PMIC");
0406 MODULE_ALIAS("platform:88pm8607-regulator");