1/* 2 * Copyright (C) ST-Ericsson SA 2010 3 * 4 * License Terms: GNU General Public License v2 5 * Authors: Sundar Iyer <sundar.iyer@stericsson.com> for ST-Ericsson 6 * Bengt Jonsson <bengt.g.jonsson@stericsson.com> for ST-Ericsson 7 * 8 * Power domain regulators on DB8500 9 */ 10 11#include <linux/kernel.h> 12#include <linux/init.h> 13#include <linux/err.h> 14#include <linux/spinlock.h> 15#include <linux/platform_device.h> 16#include <linux/mfd/dbx500-prcmu.h> 17#include <linux/regulator/driver.h> 18#include <linux/regulator/machine.h> 19#include <linux/regulator/db8500-prcmu.h> 20#include <linux/regulator/of_regulator.h> 21#include <linux/of.h> 22#include <linux/module.h> 23#include "dbx500-prcmu.h" 24 25static int db8500_regulator_enable(struct regulator_dev *rdev) 26{ 27 struct dbx500_regulator_info *info = rdev_get_drvdata(rdev); 28 29 if (info == NULL) 30 return -EINVAL; 31 32 dev_vdbg(rdev_get_dev(rdev), "regulator-%s-enable\n", 33 info->desc.name); 34 35 if (!info->is_enabled) { 36 info->is_enabled = true; 37 if (!info->exclude_from_power_state) 38 power_state_active_enable(); 39 } 40 41 return 0; 42} 43 44static int db8500_regulator_disable(struct regulator_dev *rdev) 45{ 46 struct dbx500_regulator_info *info = rdev_get_drvdata(rdev); 47 int ret = 0; 48 49 if (info == NULL) 50 return -EINVAL; 51 52 dev_vdbg(rdev_get_dev(rdev), "regulator-%s-disable\n", 53 info->desc.name); 54 55 if (info->is_enabled) { 56 info->is_enabled = false; 57 if (!info->exclude_from_power_state) 58 ret = power_state_active_disable(); 59 } 60 61 return ret; 62} 63 64static int db8500_regulator_is_enabled(struct regulator_dev *rdev) 65{ 66 struct dbx500_regulator_info *info = rdev_get_drvdata(rdev); 67 68 if (info == NULL) 69 return -EINVAL; 70 71 dev_vdbg(rdev_get_dev(rdev), "regulator-%s-is_enabled (is_enabled):" 72 " %i\n", info->desc.name, info->is_enabled); 73 74 return info->is_enabled; 75} 76 77/* db8500 regulator operations */ 78static struct regulator_ops db8500_regulator_ops = { 79 .enable = db8500_regulator_enable, 80 .disable = db8500_regulator_disable, 81 .is_enabled = db8500_regulator_is_enabled, 82}; 83 84/* 85 * EPOD control 86 */ 87static bool epod_on[NUM_EPOD_ID]; 88static bool epod_ramret[NUM_EPOD_ID]; 89 90static int enable_epod(u16 epod_id, bool ramret) 91{ 92 int ret; 93 94 if (ramret) { 95 if (!epod_on[epod_id]) { 96 ret = prcmu_set_epod(epod_id, EPOD_STATE_RAMRET); 97 if (ret < 0) 98 return ret; 99 } 100 epod_ramret[epod_id] = true; 101 } else { 102 ret = prcmu_set_epod(epod_id, EPOD_STATE_ON); 103 if (ret < 0) 104 return ret; 105 epod_on[epod_id] = true; 106 } 107 108 return 0; 109} 110 111static int disable_epod(u16 epod_id, bool ramret) 112{ 113 int ret; 114 115 if (ramret) { 116 if (!epod_on[epod_id]) { 117 ret = prcmu_set_epod(epod_id, EPOD_STATE_OFF); 118 if (ret < 0) 119 return ret; 120 } 121 epod_ramret[epod_id] = false; 122 } else { 123 if (epod_ramret[epod_id]) { 124 ret = prcmu_set_epod(epod_id, EPOD_STATE_RAMRET); 125 if (ret < 0) 126 return ret; 127 } else { 128 ret = prcmu_set_epod(epod_id, EPOD_STATE_OFF); 129 if (ret < 0) 130 return ret; 131 } 132 epod_on[epod_id] = false; 133 } 134 135 return 0; 136} 137 138/* 139 * Regulator switch 140 */ 141static int db8500_regulator_switch_enable(struct regulator_dev *rdev) 142{ 143 struct dbx500_regulator_info *info = rdev_get_drvdata(rdev); 144 int ret; 145 146 if (info == NULL) 147 return -EINVAL; 148 149 dev_vdbg(rdev_get_dev(rdev), "regulator-switch-%s-enable\n", 150 info->desc.name); 151 152 ret = enable_epod(info->epod_id, info->is_ramret); 153 if (ret < 0) { 154 dev_err(rdev_get_dev(rdev), 155 "regulator-switch-%s-enable: prcmu call failed\n", 156 info->desc.name); 157 goto out; 158 } 159 160 info->is_enabled = true; 161out: 162 return ret; 163} 164 165static int db8500_regulator_switch_disable(struct regulator_dev *rdev) 166{ 167 struct dbx500_regulator_info *info = rdev_get_drvdata(rdev); 168 int ret; 169 170 if (info == NULL) 171 return -EINVAL; 172 173 dev_vdbg(rdev_get_dev(rdev), "regulator-switch-%s-disable\n", 174 info->desc.name); 175 176 ret = disable_epod(info->epod_id, info->is_ramret); 177 if (ret < 0) { 178 dev_err(rdev_get_dev(rdev), 179 "regulator_switch-%s-disable: prcmu call failed\n", 180 info->desc.name); 181 goto out; 182 } 183 184 info->is_enabled = 0; 185out: 186 return ret; 187} 188 189static int db8500_regulator_switch_is_enabled(struct regulator_dev *rdev) 190{ 191 struct dbx500_regulator_info *info = rdev_get_drvdata(rdev); 192 193 if (info == NULL) 194 return -EINVAL; 195 196 dev_vdbg(rdev_get_dev(rdev), 197 "regulator-switch-%s-is_enabled (is_enabled): %i\n", 198 info->desc.name, info->is_enabled); 199 200 return info->is_enabled; 201} 202 203static struct regulator_ops db8500_regulator_switch_ops = { 204 .enable = db8500_regulator_switch_enable, 205 .disable = db8500_regulator_switch_disable, 206 .is_enabled = db8500_regulator_switch_is_enabled, 207}; 208 209/* 210 * Regulator information 211 */ 212static struct dbx500_regulator_info 213dbx500_regulator_info[DB8500_NUM_REGULATORS] = { 214 [DB8500_REGULATOR_VAPE] = { 215 .desc = { 216 .name = "db8500-vape", 217 .id = DB8500_REGULATOR_VAPE, 218 .ops = &db8500_regulator_ops, 219 .type = REGULATOR_VOLTAGE, 220 .owner = THIS_MODULE, 221 }, 222 }, 223 [DB8500_REGULATOR_VARM] = { 224 .desc = { 225 .name = "db8500-varm", 226 .id = DB8500_REGULATOR_VARM, 227 .ops = &db8500_regulator_ops, 228 .type = REGULATOR_VOLTAGE, 229 .owner = THIS_MODULE, 230 }, 231 }, 232 [DB8500_REGULATOR_VMODEM] = { 233 .desc = { 234 .name = "db8500-vmodem", 235 .id = DB8500_REGULATOR_VMODEM, 236 .ops = &db8500_regulator_ops, 237 .type = REGULATOR_VOLTAGE, 238 .owner = THIS_MODULE, 239 }, 240 }, 241 [DB8500_REGULATOR_VPLL] = { 242 .desc = { 243 .name = "db8500-vpll", 244 .id = DB8500_REGULATOR_VPLL, 245 .ops = &db8500_regulator_ops, 246 .type = REGULATOR_VOLTAGE, 247 .owner = THIS_MODULE, 248 }, 249 }, 250 [DB8500_REGULATOR_VSMPS1] = { 251 .desc = { 252 .name = "db8500-vsmps1", 253 .id = DB8500_REGULATOR_VSMPS1, 254 .ops = &db8500_regulator_ops, 255 .type = REGULATOR_VOLTAGE, 256 .owner = THIS_MODULE, 257 }, 258 }, 259 [DB8500_REGULATOR_VSMPS2] = { 260 .desc = { 261 .name = "db8500-vsmps2", 262 .id = DB8500_REGULATOR_VSMPS2, 263 .ops = &db8500_regulator_ops, 264 .type = REGULATOR_VOLTAGE, 265 .owner = THIS_MODULE, 266 .fixed_uV = 1800000, 267 .n_voltages = 1, 268 }, 269 .exclude_from_power_state = true, 270 }, 271 [DB8500_REGULATOR_VSMPS3] = { 272 .desc = { 273 .name = "db8500-vsmps3", 274 .id = DB8500_REGULATOR_VSMPS3, 275 .ops = &db8500_regulator_ops, 276 .type = REGULATOR_VOLTAGE, 277 .owner = THIS_MODULE, 278 }, 279 }, 280 [DB8500_REGULATOR_VRF1] = { 281 .desc = { 282 .name = "db8500-vrf1", 283 .id = DB8500_REGULATOR_VRF1, 284 .ops = &db8500_regulator_ops, 285 .type = REGULATOR_VOLTAGE, 286 .owner = THIS_MODULE, 287 }, 288 }, 289 [DB8500_REGULATOR_SWITCH_SVAMMDSP] = { 290 .desc = { 291 .name = "db8500-sva-mmdsp", 292 .id = DB8500_REGULATOR_SWITCH_SVAMMDSP, 293 .ops = &db8500_regulator_switch_ops, 294 .type = REGULATOR_VOLTAGE, 295 .owner = THIS_MODULE, 296 }, 297 .epod_id = EPOD_ID_SVAMMDSP, 298 }, 299 [DB8500_REGULATOR_SWITCH_SVAMMDSPRET] = { 300 .desc = { 301 .name = "db8500-sva-mmdsp-ret", 302 .id = DB8500_REGULATOR_SWITCH_SVAMMDSPRET, 303 .ops = &db8500_regulator_switch_ops, 304 .type = REGULATOR_VOLTAGE, 305 .owner = THIS_MODULE, 306 }, 307 .epod_id = EPOD_ID_SVAMMDSP, 308 .is_ramret = true, 309 }, 310 [DB8500_REGULATOR_SWITCH_SVAPIPE] = { 311 .desc = { 312 .name = "db8500-sva-pipe", 313 .id = DB8500_REGULATOR_SWITCH_SVAPIPE, 314 .ops = &db8500_regulator_switch_ops, 315 .type = REGULATOR_VOLTAGE, 316 .owner = THIS_MODULE, 317 }, 318 .epod_id = EPOD_ID_SVAPIPE, 319 }, 320 [DB8500_REGULATOR_SWITCH_SIAMMDSP] = { 321 .desc = { 322 .name = "db8500-sia-mmdsp", 323 .id = DB8500_REGULATOR_SWITCH_SIAMMDSP, 324 .ops = &db8500_regulator_switch_ops, 325 .type = REGULATOR_VOLTAGE, 326 .owner = THIS_MODULE, 327 }, 328 .epod_id = EPOD_ID_SIAMMDSP, 329 }, 330 [DB8500_REGULATOR_SWITCH_SIAMMDSPRET] = { 331 .desc = { 332 .name = "db8500-sia-mmdsp-ret", 333 .id = DB8500_REGULATOR_SWITCH_SIAMMDSPRET, 334 .ops = &db8500_regulator_switch_ops, 335 .type = REGULATOR_VOLTAGE, 336 .owner = THIS_MODULE, 337 }, 338 .epod_id = EPOD_ID_SIAMMDSP, 339 .is_ramret = true, 340 }, 341 [DB8500_REGULATOR_SWITCH_SIAPIPE] = { 342 .desc = { 343 .name = "db8500-sia-pipe", 344 .id = DB8500_REGULATOR_SWITCH_SIAPIPE, 345 .ops = &db8500_regulator_switch_ops, 346 .type = REGULATOR_VOLTAGE, 347 .owner = THIS_MODULE, 348 }, 349 .epod_id = EPOD_ID_SIAPIPE, 350 }, 351 [DB8500_REGULATOR_SWITCH_SGA] = { 352 .desc = { 353 .name = "db8500-sga", 354 .id = DB8500_REGULATOR_SWITCH_SGA, 355 .ops = &db8500_regulator_switch_ops, 356 .type = REGULATOR_VOLTAGE, 357 .owner = THIS_MODULE, 358 }, 359 .epod_id = EPOD_ID_SGA, 360 }, 361 [DB8500_REGULATOR_SWITCH_B2R2_MCDE] = { 362 .desc = { 363 .name = "db8500-b2r2-mcde", 364 .id = DB8500_REGULATOR_SWITCH_B2R2_MCDE, 365 .ops = &db8500_regulator_switch_ops, 366 .type = REGULATOR_VOLTAGE, 367 .owner = THIS_MODULE, 368 }, 369 .epod_id = EPOD_ID_B2R2_MCDE, 370 }, 371 [DB8500_REGULATOR_SWITCH_ESRAM12] = { 372 .desc = { 373 .name = "db8500-esram12", 374 .id = DB8500_REGULATOR_SWITCH_ESRAM12, 375 .ops = &db8500_regulator_switch_ops, 376 .type = REGULATOR_VOLTAGE, 377 .owner = THIS_MODULE, 378 }, 379 .epod_id = EPOD_ID_ESRAM12, 380 .is_enabled = true, 381 }, 382 [DB8500_REGULATOR_SWITCH_ESRAM12RET] = { 383 .desc = { 384 .name = "db8500-esram12-ret", 385 .id = DB8500_REGULATOR_SWITCH_ESRAM12RET, 386 .ops = &db8500_regulator_switch_ops, 387 .type = REGULATOR_VOLTAGE, 388 .owner = THIS_MODULE, 389 }, 390 .epod_id = EPOD_ID_ESRAM12, 391 .is_ramret = true, 392 }, 393 [DB8500_REGULATOR_SWITCH_ESRAM34] = { 394 .desc = { 395 .name = "db8500-esram34", 396 .id = DB8500_REGULATOR_SWITCH_ESRAM34, 397 .ops = &db8500_regulator_switch_ops, 398 .type = REGULATOR_VOLTAGE, 399 .owner = THIS_MODULE, 400 }, 401 .epod_id = EPOD_ID_ESRAM34, 402 .is_enabled = true, 403 }, 404 [DB8500_REGULATOR_SWITCH_ESRAM34RET] = { 405 .desc = { 406 .name = "db8500-esram34-ret", 407 .id = DB8500_REGULATOR_SWITCH_ESRAM34RET, 408 .ops = &db8500_regulator_switch_ops, 409 .type = REGULATOR_VOLTAGE, 410 .owner = THIS_MODULE, 411 }, 412 .epod_id = EPOD_ID_ESRAM34, 413 .is_ramret = true, 414 }, 415}; 416 417static int db8500_regulator_register(struct platform_device *pdev, 418 struct regulator_init_data *init_data, 419 int id, 420 struct device_node *np) 421{ 422 struct dbx500_regulator_info *info; 423 struct regulator_config config = { }; 424 int err; 425 426 /* assign per-regulator data */ 427 info = &dbx500_regulator_info[id]; 428 info->dev = &pdev->dev; 429 430 config.dev = &pdev->dev; 431 config.init_data = init_data; 432 config.driver_data = info; 433 config.of_node = np; 434 435 /* register with the regulator framework */ 436 info->rdev = devm_regulator_register(&pdev->dev, &info->desc, &config); 437 if (IS_ERR(info->rdev)) { 438 err = PTR_ERR(info->rdev); 439 dev_err(&pdev->dev, "failed to register %s: err %i\n", 440 info->desc.name, err); 441 return err; 442 } 443 444 dev_dbg(rdev_get_dev(info->rdev), 445 "regulator-%s-probed\n", info->desc.name); 446 447 return 0; 448} 449 450static struct of_regulator_match db8500_regulator_matches[] = { 451 { .name = "db8500_vape", .driver_data = (void *) DB8500_REGULATOR_VAPE, }, 452 { .name = "db8500_varm", .driver_data = (void *) DB8500_REGULATOR_VARM, }, 453 { .name = "db8500_vmodem", .driver_data = (void *) DB8500_REGULATOR_VMODEM, }, 454 { .name = "db8500_vpll", .driver_data = (void *) DB8500_REGULATOR_VPLL, }, 455 { .name = "db8500_vsmps1", .driver_data = (void *) DB8500_REGULATOR_VSMPS1, }, 456 { .name = "db8500_vsmps2", .driver_data = (void *) DB8500_REGULATOR_VSMPS2, }, 457 { .name = "db8500_vsmps3", .driver_data = (void *) DB8500_REGULATOR_VSMPS3, }, 458 { .name = "db8500_vrf1", .driver_data = (void *) DB8500_REGULATOR_VRF1, }, 459 { .name = "db8500_sva_mmdsp", .driver_data = (void *) DB8500_REGULATOR_SWITCH_SVAMMDSP, }, 460 { .name = "db8500_sva_mmdsp_ret", .driver_data = (void *) DB8500_REGULATOR_SWITCH_SVAMMDSPRET, }, 461 { .name = "db8500_sva_pipe", .driver_data = (void *) DB8500_REGULATOR_SWITCH_SVAPIPE, }, 462 { .name = "db8500_sia_mmdsp", .driver_data = (void *) DB8500_REGULATOR_SWITCH_SIAMMDSP, }, 463 { .name = "db8500_sia_mmdsp_ret", .driver_data = (void *) DB8500_REGULATOR_SWITCH_SIAMMDSPRET, }, 464 { .name = "db8500_sia_pipe", .driver_data = (void *) DB8500_REGULATOR_SWITCH_SIAPIPE, }, 465 { .name = "db8500_sga", .driver_data = (void *) DB8500_REGULATOR_SWITCH_SGA, }, 466 { .name = "db8500_b2r2_mcde", .driver_data = (void *) DB8500_REGULATOR_SWITCH_B2R2_MCDE, }, 467 { .name = "db8500_esram12", .driver_data = (void *) DB8500_REGULATOR_SWITCH_ESRAM12, }, 468 { .name = "db8500_esram12_ret", .driver_data = (void *) DB8500_REGULATOR_SWITCH_ESRAM12RET, }, 469 { .name = "db8500_esram34", .driver_data = (void *) DB8500_REGULATOR_SWITCH_ESRAM34, }, 470 { .name = "db8500_esram34_ret", .driver_data = (void *) DB8500_REGULATOR_SWITCH_ESRAM34RET, }, 471}; 472 473static int 474db8500_regulator_of_probe(struct platform_device *pdev, 475 struct device_node *np) 476{ 477 int i, err; 478 479 for (i = 0; i < ARRAY_SIZE(dbx500_regulator_info); i++) { 480 err = db8500_regulator_register( 481 pdev, db8500_regulator_matches[i].init_data, 482 i, db8500_regulator_matches[i].of_node); 483 if (err) 484 return err; 485 } 486 487 return 0; 488} 489 490static int db8500_regulator_probe(struct platform_device *pdev) 491{ 492 struct regulator_init_data *db8500_init_data = 493 dev_get_platdata(&pdev->dev); 494 struct device_node *np = pdev->dev.of_node; 495 int i, err; 496 497 /* register all regulators */ 498 if (np) { 499 err = of_regulator_match(&pdev->dev, np, 500 db8500_regulator_matches, 501 ARRAY_SIZE(db8500_regulator_matches)); 502 if (err < 0) { 503 dev_err(&pdev->dev, 504 "Error parsing regulator init data: %d\n", err); 505 return err; 506 } 507 508 err = db8500_regulator_of_probe(pdev, np); 509 if (err) 510 return err; 511 } else { 512 for (i = 0; i < ARRAY_SIZE(dbx500_regulator_info); i++) { 513 err = db8500_regulator_register(pdev, 514 &db8500_init_data[i], 515 i, NULL); 516 if (err) 517 return err; 518 } 519 } 520 521 err = ux500_regulator_debug_init(pdev, 522 dbx500_regulator_info, 523 ARRAY_SIZE(dbx500_regulator_info)); 524 return 0; 525} 526 527static int db8500_regulator_remove(struct platform_device *pdev) 528{ 529 ux500_regulator_debug_exit(); 530 531 return 0; 532} 533 534static struct platform_driver db8500_regulator_driver = { 535 .driver = { 536 .name = "db8500-prcmu-regulators", 537 }, 538 .probe = db8500_regulator_probe, 539 .remove = db8500_regulator_remove, 540}; 541 542static int __init db8500_regulator_init(void) 543{ 544 return platform_driver_register(&db8500_regulator_driver); 545} 546 547static void __exit db8500_regulator_exit(void) 548{ 549 platform_driver_unregister(&db8500_regulator_driver); 550} 551 552arch_initcall(db8500_regulator_init); 553module_exit(db8500_regulator_exit); 554 555MODULE_AUTHOR("STMicroelectronics/ST-Ericsson"); 556MODULE_DESCRIPTION("DB8500 regulator driver"); 557MODULE_LICENSE("GPL v2"); 558