502 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (C) ST-Ericsson SA 20104 *5 * Authors: Sundar Iyer <sundar.iyer@stericsson.com> for ST-Ericsson6 * Bengt Jonsson <bengt.g.jonsson@stericsson.com> for ST-Ericsson7 *8 * Power domain regulators on DB85009 */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 const 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 control86 */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 switch140 */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 = false;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 const 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 information211 */212static struct dbx500_regulator_info213dbx500_regulator_info[DB8500_NUM_REGULATORS] = {214 [DB8500_REGULATOR_VAPE] = {215 .desc = {216 .name = "db8500-vape",217 .of_match = of_match_ptr("db8500_vape"),218 .id = DB8500_REGULATOR_VAPE,219 .ops = &db8500_regulator_ops,220 .type = REGULATOR_VOLTAGE,221 .owner = THIS_MODULE,222 },223 },224 [DB8500_REGULATOR_VARM] = {225 .desc = {226 .name = "db8500-varm",227 .of_match = of_match_ptr("db8500_varm"),228 .id = DB8500_REGULATOR_VARM,229 .ops = &db8500_regulator_ops,230 .type = REGULATOR_VOLTAGE,231 .owner = THIS_MODULE,232 },233 },234 [DB8500_REGULATOR_VMODEM] = {235 .desc = {236 .name = "db8500-vmodem",237 .of_match = of_match_ptr("db8500_vmodem"),238 .id = DB8500_REGULATOR_VMODEM,239 .ops = &db8500_regulator_ops,240 .type = REGULATOR_VOLTAGE,241 .owner = THIS_MODULE,242 },243 },244 [DB8500_REGULATOR_VPLL] = {245 .desc = {246 .name = "db8500-vpll",247 .of_match = of_match_ptr("db8500_vpll"),248 .id = DB8500_REGULATOR_VPLL,249 .ops = &db8500_regulator_ops,250 .type = REGULATOR_VOLTAGE,251 .owner = THIS_MODULE,252 },253 },254 [DB8500_REGULATOR_VSMPS1] = {255 .desc = {256 .name = "db8500-vsmps1",257 .of_match = of_match_ptr("db8500_vsmps1"),258 .id = DB8500_REGULATOR_VSMPS1,259 .ops = &db8500_regulator_ops,260 .type = REGULATOR_VOLTAGE,261 .owner = THIS_MODULE,262 },263 },264 [DB8500_REGULATOR_VSMPS2] = {265 .desc = {266 .name = "db8500-vsmps2",267 .of_match = of_match_ptr("db8500_vsmps2"),268 .id = DB8500_REGULATOR_VSMPS2,269 .ops = &db8500_regulator_ops,270 .type = REGULATOR_VOLTAGE,271 .owner = THIS_MODULE,272 .fixed_uV = 1800000,273 .n_voltages = 1,274 },275 .exclude_from_power_state = true,276 },277 [DB8500_REGULATOR_VSMPS3] = {278 .desc = {279 .name = "db8500-vsmps3",280 .of_match = of_match_ptr("db8500_vsmps3"),281 .id = DB8500_REGULATOR_VSMPS3,282 .ops = &db8500_regulator_ops,283 .type = REGULATOR_VOLTAGE,284 .owner = THIS_MODULE,285 },286 },287 [DB8500_REGULATOR_VRF1] = {288 .desc = {289 .name = "db8500-vrf1",290 .of_match = of_match_ptr("db8500_vrf1"),291 .id = DB8500_REGULATOR_VRF1,292 .ops = &db8500_regulator_ops,293 .type = REGULATOR_VOLTAGE,294 .owner = THIS_MODULE,295 },296 },297 [DB8500_REGULATOR_SWITCH_SVAMMDSP] = {298 .desc = {299 .name = "db8500-sva-mmdsp",300 .of_match = of_match_ptr("db8500_sva_mmdsp"),301 .id = DB8500_REGULATOR_SWITCH_SVAMMDSP,302 .ops = &db8500_regulator_switch_ops,303 .type = REGULATOR_VOLTAGE,304 .owner = THIS_MODULE,305 },306 .epod_id = EPOD_ID_SVAMMDSP,307 },308 [DB8500_REGULATOR_SWITCH_SVAMMDSPRET] = {309 .desc = {310 .name = "db8500-sva-mmdsp-ret",311 .of_match = of_match_ptr("db8500_sva_mmdsp_ret"),312 .id = DB8500_REGULATOR_SWITCH_SVAMMDSPRET,313 .ops = &db8500_regulator_switch_ops,314 .type = REGULATOR_VOLTAGE,315 .owner = THIS_MODULE,316 },317 .epod_id = EPOD_ID_SVAMMDSP,318 .is_ramret = true,319 },320 [DB8500_REGULATOR_SWITCH_SVAPIPE] = {321 .desc = {322 .name = "db8500-sva-pipe",323 .of_match = of_match_ptr("db8500_sva_pipe"),324 .id = DB8500_REGULATOR_SWITCH_SVAPIPE,325 .ops = &db8500_regulator_switch_ops,326 .type = REGULATOR_VOLTAGE,327 .owner = THIS_MODULE,328 },329 .epod_id = EPOD_ID_SVAPIPE,330 },331 [DB8500_REGULATOR_SWITCH_SIAMMDSP] = {332 .desc = {333 .name = "db8500-sia-mmdsp",334 .of_match = of_match_ptr("db8500_sia_mmdsp"),335 .id = DB8500_REGULATOR_SWITCH_SIAMMDSP,336 .ops = &db8500_regulator_switch_ops,337 .type = REGULATOR_VOLTAGE,338 .owner = THIS_MODULE,339 },340 .epod_id = EPOD_ID_SIAMMDSP,341 },342 [DB8500_REGULATOR_SWITCH_SIAMMDSPRET] = {343 .desc = {344 .name = "db8500-sia-mmdsp-ret",345 .of_match = of_match_ptr("db8500_sia_mmdsp_ret"),346 .id = DB8500_REGULATOR_SWITCH_SIAMMDSPRET,347 .ops = &db8500_regulator_switch_ops,348 .type = REGULATOR_VOLTAGE,349 .owner = THIS_MODULE,350 },351 .epod_id = EPOD_ID_SIAMMDSP,352 .is_ramret = true,353 },354 [DB8500_REGULATOR_SWITCH_SIAPIPE] = {355 .desc = {356 .name = "db8500-sia-pipe",357 .of_match = of_match_ptr("db8500_sia_pipe"),358 .id = DB8500_REGULATOR_SWITCH_SIAPIPE,359 .ops = &db8500_regulator_switch_ops,360 .type = REGULATOR_VOLTAGE,361 .owner = THIS_MODULE,362 },363 .epod_id = EPOD_ID_SIAPIPE,364 },365 [DB8500_REGULATOR_SWITCH_SGA] = {366 .desc = {367 .name = "db8500-sga",368 .of_match = of_match_ptr("db8500_sga"),369 .id = DB8500_REGULATOR_SWITCH_SGA,370 .ops = &db8500_regulator_switch_ops,371 .type = REGULATOR_VOLTAGE,372 .owner = THIS_MODULE,373 },374 .epod_id = EPOD_ID_SGA,375 },376 [DB8500_REGULATOR_SWITCH_B2R2_MCDE] = {377 .desc = {378 .name = "db8500-b2r2-mcde",379 .of_match = of_match_ptr("db8500_b2r2_mcde"),380 .id = DB8500_REGULATOR_SWITCH_B2R2_MCDE,381 .ops = &db8500_regulator_switch_ops,382 .type = REGULATOR_VOLTAGE,383 .owner = THIS_MODULE,384 },385 .epod_id = EPOD_ID_B2R2_MCDE,386 },387 [DB8500_REGULATOR_SWITCH_ESRAM12] = {388 .desc = {389 .name = "db8500-esram12",390 .of_match = of_match_ptr("db8500_esram12"),391 .id = DB8500_REGULATOR_SWITCH_ESRAM12,392 .ops = &db8500_regulator_switch_ops,393 .type = REGULATOR_VOLTAGE,394 .owner = THIS_MODULE,395 },396 .epod_id = EPOD_ID_ESRAM12,397 .is_enabled = true,398 },399 [DB8500_REGULATOR_SWITCH_ESRAM12RET] = {400 .desc = {401 .name = "db8500-esram12-ret",402 .of_match = of_match_ptr("db8500_esram12_ret"),403 .id = DB8500_REGULATOR_SWITCH_ESRAM12RET,404 .ops = &db8500_regulator_switch_ops,405 .type = REGULATOR_VOLTAGE,406 .owner = THIS_MODULE,407 },408 .epod_id = EPOD_ID_ESRAM12,409 .is_ramret = true,410 },411 [DB8500_REGULATOR_SWITCH_ESRAM34] = {412 .desc = {413 .name = "db8500-esram34",414 .of_match = of_match_ptr("db8500_esram34"),415 .id = DB8500_REGULATOR_SWITCH_ESRAM34,416 .ops = &db8500_regulator_switch_ops,417 .type = REGULATOR_VOLTAGE,418 .owner = THIS_MODULE,419 },420 .epod_id = EPOD_ID_ESRAM34,421 .is_enabled = true,422 },423 [DB8500_REGULATOR_SWITCH_ESRAM34RET] = {424 .desc = {425 .name = "db8500-esram34-ret",426 .of_match = of_match_ptr("db8500_esram34_ret"),427 .id = DB8500_REGULATOR_SWITCH_ESRAM34RET,428 .ops = &db8500_regulator_switch_ops,429 .type = REGULATOR_VOLTAGE,430 .owner = THIS_MODULE,431 },432 .epod_id = EPOD_ID_ESRAM34,433 .is_ramret = true,434 },435};436 437static int db8500_regulator_probe(struct platform_device *pdev)438{439 struct regulator_init_data *db8500_init_data;440 struct dbx500_regulator_info *info;441 struct regulator_config config = { };442 struct regulator_dev *rdev;443 int err, i;444 445 db8500_init_data = dev_get_platdata(&pdev->dev);446 447 for (i = 0; i < ARRAY_SIZE(dbx500_regulator_info); i++) {448 /* assign per-regulator data */449 info = &dbx500_regulator_info[i];450 451 config.driver_data = info;452 config.dev = &pdev->dev;453 if (db8500_init_data)454 config.init_data = &db8500_init_data[i];455 456 rdev = devm_regulator_register(&pdev->dev, &info->desc,457 &config);458 if (IS_ERR(rdev)) {459 err = PTR_ERR(rdev);460 dev_err(&pdev->dev, "failed to register %s: err %i\n",461 info->desc.name, err);462 return err;463 }464 dev_dbg(&pdev->dev, "regulator-%s-probed\n", info->desc.name);465 }466 467 ux500_regulator_debug_init(pdev, dbx500_regulator_info,468 ARRAY_SIZE(dbx500_regulator_info));469 return 0;470}471 472static void db8500_regulator_remove(struct platform_device *pdev)473{474 ux500_regulator_debug_exit();475}476 477static struct platform_driver db8500_regulator_driver = {478 .driver = {479 .name = "db8500-prcmu-regulators",480 .probe_type = PROBE_PREFER_ASYNCHRONOUS,481 },482 .probe = db8500_regulator_probe,483 .remove_new = db8500_regulator_remove,484};485 486static int __init db8500_regulator_init(void)487{488 return platform_driver_register(&db8500_regulator_driver);489}490 491static void __exit db8500_regulator_exit(void)492{493 platform_driver_unregister(&db8500_regulator_driver);494}495 496arch_initcall(db8500_regulator_init);497module_exit(db8500_regulator_exit);498 499MODULE_AUTHOR("STMicroelectronics/ST-Ericsson");500MODULE_DESCRIPTION("DB8500 regulator driver");501MODULE_LICENSE("GPL v2");502