1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Regulators driver for Marvell 88PM8607 4 * 5 * Copyright (C) 2009 Marvell International Ltd. 6 * Haojian Zhuang <haojian.zhuang@marvell.com> 7 */ 8 #include <linux/kernel.h> 9 #include <linux/init.h> 10 #include <linux/err.h> 11 #include <linux/of.h> 12 #include <linux/regulator/of_regulator.h> 13 #include <linux/platform_device.h> 14 #include <linux/regulator/driver.h> 15 #include <linux/regulator/machine.h> 16 #include <linux/mfd/88pm860x.h> 17 #include <linux/module.h> 18 19 struct pm8607_regulator_info { 20 struct regulator_desc desc; 21 22 unsigned int *vol_suspend; 23 24 int slope_double; 25 }; 26 27 static const unsigned int BUCK1_table[] = { 28 725000, 750000, 775000, 800000, 825000, 850000, 875000, 900000, 29 925000, 950000, 975000, 1000000, 1025000, 1050000, 1075000, 1100000, 30 1125000, 1150000, 1175000, 1200000, 1225000, 1250000, 1275000, 1300000, 31 1325000, 1350000, 1375000, 1400000, 1425000, 1450000, 1475000, 1500000, 32 0, 25000, 50000, 75000, 100000, 125000, 150000, 175000, 33 200000, 225000, 250000, 275000, 300000, 325000, 350000, 375000, 34 400000, 425000, 450000, 475000, 500000, 525000, 550000, 575000, 35 600000, 625000, 650000, 675000, 700000, 725000, 750000, 775000, 36 }; 37 38 static const unsigned int BUCK1_suspend_table[] = { 39 0, 25000, 50000, 75000, 100000, 125000, 150000, 175000, 40 200000, 225000, 250000, 275000, 300000, 325000, 350000, 375000, 41 400000, 425000, 450000, 475000, 500000, 525000, 550000, 575000, 42 600000, 625000, 650000, 675000, 700000, 725000, 750000, 775000, 43 800000, 825000, 850000, 875000, 900000, 925000, 950000, 975000, 44 1000000, 1025000, 1050000, 1075000, 1100000, 1125000, 1150000, 1175000, 45 1200000, 1225000, 1250000, 1275000, 1300000, 1325000, 1350000, 1375000, 46 1400000, 1425000, 1450000, 1475000, 1500000, 1500000, 1500000, 1500000, 47 }; 48 49 static const unsigned int BUCK2_table[] = { 50 0, 50000, 100000, 150000, 200000, 250000, 300000, 350000, 51 400000, 450000, 500000, 550000, 600000, 650000, 700000, 750000, 52 800000, 850000, 900000, 950000, 1000000, 1050000, 1100000, 1150000, 53 1200000, 1250000, 1300000, 1350000, 1400000, 1450000, 1500000, 1550000, 54 1600000, 1650000, 1700000, 1750000, 1800000, 1850000, 1900000, 1950000, 55 2000000, 2050000, 2100000, 2150000, 2200000, 2250000, 2300000, 2350000, 56 2400000, 2450000, 2500000, 2550000, 2600000, 2650000, 2700000, 2750000, 57 2800000, 2850000, 2900000, 2950000, 3000000, 3000000, 3000000, 3000000, 58 }; 59 60 static const unsigned int BUCK2_suspend_table[] = { 61 0, 50000, 100000, 150000, 200000, 250000, 300000, 350000, 62 400000, 450000, 500000, 550000, 600000, 650000, 700000, 750000, 63 800000, 850000, 900000, 950000, 1000000, 1050000, 1100000, 1150000, 64 1200000, 1250000, 1300000, 1350000, 1400000, 1450000, 1500000, 1550000, 65 1600000, 1650000, 1700000, 1750000, 1800000, 1850000, 1900000, 1950000, 66 2000000, 2050000, 2100000, 2150000, 2200000, 2250000, 2300000, 2350000, 67 2400000, 2450000, 2500000, 2550000, 2600000, 2650000, 2700000, 2750000, 68 2800000, 2850000, 2900000, 2950000, 3000000, 3000000, 3000000, 3000000, 69 }; 70 71 static const unsigned int BUCK3_table[] = { 72 0, 25000, 50000, 75000, 100000, 125000, 150000, 175000, 73 200000, 225000, 250000, 275000, 300000, 325000, 350000, 375000, 74 400000, 425000, 450000, 475000, 500000, 525000, 550000, 575000, 75 600000, 625000, 650000, 675000, 700000, 725000, 750000, 775000, 76 800000, 825000, 850000, 875000, 900000, 925000, 950000, 975000, 77 1000000, 1025000, 1050000, 1075000, 1100000, 1125000, 1150000, 1175000, 78 1200000, 1225000, 1250000, 1275000, 1300000, 1325000, 1350000, 1375000, 79 1400000, 1425000, 1450000, 1475000, 1500000, 1500000, 1500000, 1500000, 80 }; 81 82 static const unsigned int BUCK3_suspend_table[] = { 83 0, 25000, 50000, 75000, 100000, 125000, 150000, 175000, 84 200000, 225000, 250000, 275000, 300000, 325000, 350000, 375000, 85 400000, 425000, 450000, 475000, 500000, 525000, 550000, 575000, 86 600000, 625000, 650000, 675000, 700000, 725000, 750000, 775000, 87 800000, 825000, 850000, 875000, 900000, 925000, 950000, 975000, 88 1000000, 1025000, 1050000, 1075000, 1100000, 1125000, 1150000, 1175000, 89 1200000, 1225000, 1250000, 1275000, 1300000, 1325000, 1350000, 1375000, 90 1400000, 1425000, 1450000, 1475000, 1500000, 1500000, 1500000, 1500000, 91 }; 92 93 static const unsigned int LDO1_table[] = { 94 1800000, 1200000, 2800000, 0, 95 }; 96 97 static const unsigned int LDO1_suspend_table[] = { 98 1800000, 1200000, 0, 0, 99 }; 100 101 static const unsigned int LDO2_table[] = { 102 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 3300000, 103 }; 104 105 static const unsigned int LDO2_suspend_table[] = { 106 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 2900000, 107 }; 108 109 static const unsigned int LDO3_table[] = { 110 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 3300000, 111 }; 112 113 static const unsigned int LDO3_suspend_table[] = { 114 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 2900000, 115 }; 116 117 static const unsigned int LDO4_table[] = { 118 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2900000, 3300000, 119 }; 120 121 static const unsigned int LDO4_suspend_table[] = { 122 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2900000, 2900000, 123 }; 124 125 static const unsigned int LDO5_table[] = { 126 2900000, 3000000, 3100000, 3300000, 127 }; 128 129 static const unsigned int LDO5_suspend_table[] = { 130 2900000, 0, 0, 0, 131 }; 132 133 static const unsigned int LDO6_table[] = { 134 1800000, 1850000, 2600000, 2650000, 2700000, 2750000, 2800000, 3300000, 135 }; 136 137 static const unsigned int LDO6_suspend_table[] = { 138 1800000, 1850000, 2600000, 2650000, 2700000, 2750000, 2800000, 2900000, 139 }; 140 141 static const unsigned int LDO7_table[] = { 142 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 2900000, 143 }; 144 145 static const unsigned int LDO7_suspend_table[] = { 146 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 2900000, 147 }; 148 149 static const unsigned int LDO8_table[] = { 150 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 2900000, 151 }; 152 153 static const unsigned int LDO8_suspend_table[] = { 154 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 2900000, 155 }; 156 157 static const unsigned int LDO9_table[] = { 158 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 3300000, 159 }; 160 161 static const unsigned int LDO9_suspend_table[] = { 162 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 2900000, 163 }; 164 165 static const unsigned int LDO10_table[] = { 166 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 3300000, 167 1200000, 1200000, 1200000, 1200000, 1200000, 1200000, 1200000, 1200000, 168 }; 169 170 static const unsigned int LDO10_suspend_table[] = { 171 1800000, 1850000, 1900000, 2700000, 2750000, 2800000, 2850000, 2900000, 172 1200000, 1200000, 1200000, 1200000, 1200000, 1200000, 1200000, 1200000, 173 }; 174 175 static const unsigned int LDO12_table[] = { 176 1800000, 1900000, 2700000, 2800000, 2900000, 3000000, 3100000, 3300000, 177 1200000, 1200000, 1200000, 1200000, 1200000, 1200000, 1200000, 1200000, 178 }; 179 180 static const unsigned int LDO12_suspend_table[] = { 181 1800000, 1900000, 2700000, 2800000, 2900000, 2900000, 2900000, 2900000, 182 1200000, 1200000, 1200000, 1200000, 1200000, 1200000, 1200000, 1200000, 183 }; 184 185 static const unsigned int LDO13_table[] = { 186 1200000, 1300000, 1800000, 2000000, 2500000, 2800000, 3000000, 0, 187 }; 188 189 static const unsigned int LDO13_suspend_table[] = { 190 0, 191 }; 192 193 static const unsigned int LDO14_table[] = { 194 1800000, 1850000, 2700000, 2750000, 2800000, 2850000, 2900000, 3300000, 195 }; 196 197 static const unsigned int LDO14_suspend_table[] = { 198 1800000, 1850000, 2700000, 2750000, 2800000, 2850000, 2900000, 2900000, 199 }; 200 201 static int pm8607_list_voltage(struct regulator_dev *rdev, unsigned index) 202 { 203 struct pm8607_regulator_info *info = rdev_get_drvdata(rdev); 204 int ret; 205 206 ret = regulator_list_voltage_table(rdev, index); 207 if (ret < 0) 208 return ret; 209 210 if (info->slope_double) 211 ret <<= 1; 212 213 return ret; 214 } 215 216 static const struct regulator_ops pm8607_regulator_ops = { 217 .list_voltage = pm8607_list_voltage, 218 .set_voltage_sel = regulator_set_voltage_sel_regmap, 219 .get_voltage_sel = regulator_get_voltage_sel_regmap, 220 .enable = regulator_enable_regmap, 221 .disable = regulator_disable_regmap, 222 .is_enabled = regulator_is_enabled_regmap, 223 }; 224 225 static const struct regulator_ops pm8606_preg_ops = { 226 .enable = regulator_enable_regmap, 227 .disable = regulator_disable_regmap, 228 .is_enabled = regulator_is_enabled_regmap, 229 }; 230 231 #define PM8606_PREG(ereg, ebit) \ 232 { \ 233 .desc = { \ 234 .name = "PREG", \ 235 .of_match = of_match_ptr("PREG"), \ 236 .regulators_node = of_match_ptr("regulators"), \ 237 .ops = &pm8606_preg_ops, \ 238 .type = REGULATOR_CURRENT, \ 239 .id = PM8606_ID_PREG, \ 240 .owner = THIS_MODULE, \ 241 .enable_reg = PM8606_##ereg, \ 242 .enable_mask = (ebit), \ 243 .enable_is_inverted = true, \ 244 }, \ 245 } 246 247 #define PM8607_DVC(vreg, ureg, ubit, ereg, ebit) \ 248 { \ 249 .desc = { \ 250 .name = #vreg, \ 251 .of_match = of_match_ptr(#vreg), \ 252 .regulators_node = of_match_ptr("regulators"), \ 253 .ops = &pm8607_regulator_ops, \ 254 .type = REGULATOR_VOLTAGE, \ 255 .id = PM8607_ID_##vreg, \ 256 .owner = THIS_MODULE, \ 257 .volt_table = vreg##_table, \ 258 .n_voltages = ARRAY_SIZE(vreg##_table), \ 259 .vsel_reg = PM8607_##vreg, \ 260 .vsel_mask = ARRAY_SIZE(vreg##_table) - 1, \ 261 .apply_reg = PM8607_##ureg, \ 262 .apply_bit = (ubit), \ 263 .enable_reg = PM8607_##ereg, \ 264 .enable_mask = 1 << (ebit), \ 265 }, \ 266 .slope_double = (0), \ 267 .vol_suspend = (unsigned int *)&vreg##_suspend_table, \ 268 } 269 270 #define PM8607_LDO(_id, vreg, shift, ereg, ebit) \ 271 { \ 272 .desc = { \ 273 .name = "LDO" #_id, \ 274 .of_match = of_match_ptr("LDO" #_id), \ 275 .regulators_node = of_match_ptr("regulators"), \ 276 .ops = &pm8607_regulator_ops, \ 277 .type = REGULATOR_VOLTAGE, \ 278 .id = PM8607_ID_LDO##_id, \ 279 .owner = THIS_MODULE, \ 280 .volt_table = LDO##_id##_table, \ 281 .n_voltages = ARRAY_SIZE(LDO##_id##_table), \ 282 .vsel_reg = PM8607_##vreg, \ 283 .vsel_mask = (ARRAY_SIZE(LDO##_id##_table) - 1) << (shift), \ 284 .enable_reg = PM8607_##ereg, \ 285 .enable_mask = 1 << (ebit), \ 286 }, \ 287 .slope_double = (0), \ 288 .vol_suspend = (unsigned int *)&LDO##_id##_suspend_table, \ 289 } 290 291 static struct pm8607_regulator_info pm8607_regulator_info[] = { 292 PM8607_DVC(BUCK1, GO, BIT(0), SUPPLIES_EN11, 0), 293 PM8607_DVC(BUCK2, GO, BIT(1), SUPPLIES_EN11, 1), 294 PM8607_DVC(BUCK3, GO, BIT(2), SUPPLIES_EN11, 2), 295 296 PM8607_LDO(1, LDO1, 0, SUPPLIES_EN11, 3), 297 PM8607_LDO(2, LDO2, 0, SUPPLIES_EN11, 4), 298 PM8607_LDO(3, LDO3, 0, SUPPLIES_EN11, 5), 299 PM8607_LDO(4, LDO4, 0, SUPPLIES_EN11, 6), 300 PM8607_LDO(5, LDO5, 0, SUPPLIES_EN11, 7), 301 PM8607_LDO(6, LDO6, 0, SUPPLIES_EN12, 0), 302 PM8607_LDO(7, LDO7, 0, SUPPLIES_EN12, 1), 303 PM8607_LDO(8, LDO8, 0, SUPPLIES_EN12, 2), 304 PM8607_LDO(9, LDO9, 0, SUPPLIES_EN12, 3), 305 PM8607_LDO(10, LDO10, 0, SUPPLIES_EN12, 4), 306 PM8607_LDO(12, LDO12, 0, SUPPLIES_EN12, 5), 307 PM8607_LDO(13, VIBRATOR_SET, 1, VIBRATOR_SET, 0), 308 PM8607_LDO(14, LDO14, 0, SUPPLIES_EN12, 6), 309 }; 310 311 static struct pm8607_regulator_info pm8606_regulator_info[] = { 312 PM8606_PREG(PREREGULATORB, 5), 313 }; 314 315 static int pm8607_regulator_probe(struct platform_device *pdev) 316 { 317 struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent); 318 struct pm8607_regulator_info *info = NULL; 319 struct regulator_init_data *pdata = dev_get_platdata(&pdev->dev); 320 struct regulator_config config = { }; 321 struct regulator_dev *rdev; 322 struct resource *res; 323 int i; 324 325 res = platform_get_resource(pdev, IORESOURCE_REG, 0); 326 if (res) { 327 /* There're resources in 88PM8607 regulator driver */ 328 for (i = 0; i < ARRAY_SIZE(pm8607_regulator_info); i++) { 329 info = &pm8607_regulator_info[i]; 330 if (info->desc.vsel_reg == res->start) 331 break; 332 } 333 if (i == ARRAY_SIZE(pm8607_regulator_info)) { 334 dev_err(&pdev->dev, "Failed to find regulator %llu\n", 335 (unsigned long long)res->start); 336 return -EINVAL; 337 } 338 } else { 339 /* There's no resource in 88PM8606 PREG regulator driver */ 340 info = &pm8606_regulator_info[0]; 341 /* i is used to check regulator ID */ 342 i = -1; 343 } 344 345 /* check DVC ramp slope double */ 346 if ((i == PM8607_ID_BUCK3) && chip->buck3_double) 347 info->slope_double = 1; 348 349 config.dev = chip->dev; 350 config.driver_data = info; 351 352 if (pdata) 353 config.init_data = pdata; 354 355 if (chip->id == CHIP_PM8607) 356 config.regmap = chip->regmap; 357 else 358 config.regmap = chip->regmap_companion; 359 360 rdev = devm_regulator_register(&pdev->dev, &info->desc, &config); 361 if (IS_ERR(rdev)) { 362 dev_err(&pdev->dev, "failed to register regulator %s\n", 363 info->desc.name); 364 return PTR_ERR(rdev); 365 } 366 367 platform_set_drvdata(pdev, info); 368 return 0; 369 } 370 371 static const struct platform_device_id pm8607_regulator_driver_ids[] = { 372 { 373 .name = "88pm860x-regulator", 374 .driver_data = 0, 375 }, { 376 .name = "88pm860x-preg", 377 .driver_data = 0, 378 }, 379 { }, 380 }; 381 MODULE_DEVICE_TABLE(platform, pm8607_regulator_driver_ids); 382 383 static struct platform_driver pm8607_regulator_driver = { 384 .driver = { 385 .name = "88pm860x-regulator", 386 .probe_type = PROBE_PREFER_ASYNCHRONOUS, 387 }, 388 .probe = pm8607_regulator_probe, 389 .id_table = pm8607_regulator_driver_ids, 390 }; 391 392 static int __init pm8607_regulator_init(void) 393 { 394 return platform_driver_register(&pm8607_regulator_driver); 395 } 396 subsys_initcall(pm8607_regulator_init); 397 398 static void __exit pm8607_regulator_exit(void) 399 { 400 platform_driver_unregister(&pm8607_regulator_driver); 401 } 402 module_exit(pm8607_regulator_exit); 403 404 MODULE_LICENSE("GPL"); 405 MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>"); 406 MODULE_DESCRIPTION("Regulator Driver for Marvell 88PM8607 PMIC"); 407 MODULE_ALIAS("platform:88pm8607-regulator"); 408