475 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (C) ST-Ericsson SA 20104 *5 * Authors: Bengt Jonsson <bengt.g.jonsson@stericsson.com>6 *7 * This file is based on drivers/regulator/ab8500.c8 *9 * AB8500 external regulators10 *11 * ab8500-ext supports the following regulators:12 * - VextSupply313 */14#include <linux/init.h>15#include <linux/kernel.h>16#include <linux/err.h>17#include <linux/module.h>18#include <linux/of.h>19#include <linux/platform_device.h>20#include <linux/regulator/driver.h>21#include <linux/regulator/machine.h>22#include <linux/regulator/of_regulator.h>23#include <linux/mfd/abx500.h>24#include <linux/mfd/abx500/ab8500.h>25 26/* AB8500 external regulators */27enum ab8500_ext_regulator_id {28 AB8500_EXT_SUPPLY1,29 AB8500_EXT_SUPPLY2,30 AB8500_EXT_SUPPLY3,31 AB8500_NUM_EXT_REGULATORS,32};33 34struct ab8500_ext_regulator_cfg {35 bool hwreq; /* requires hw mode or high power mode */36};37 38/* supply for VextSupply3 */39static struct regulator_consumer_supply ab8500_ext_supply3_consumers[] = {40 /* SIM supply for 3 V SIM cards */41 REGULATOR_SUPPLY("vinvsim", "sim-detect.0"),42};43 44/*45 * AB8500 external regulators46 */47static struct regulator_init_data ab8500_ext_regulators[] = {48 /* fixed Vbat supplies VSMPS1_EXT_1V8 */49 [AB8500_EXT_SUPPLY1] = {50 .constraints = {51 .name = "ab8500-ext-supply1",52 .min_uV = 1800000,53 .max_uV = 1800000,54 .initial_mode = REGULATOR_MODE_IDLE,55 .boot_on = 1,56 .always_on = 1,57 },58 },59 /* fixed Vbat supplies VSMPS2_EXT_1V36 and VSMPS5_EXT_1V15 */60 [AB8500_EXT_SUPPLY2] = {61 .constraints = {62 .name = "ab8500-ext-supply2",63 .min_uV = 1360000,64 .max_uV = 1360000,65 },66 },67 /* fixed Vbat supplies VSMPS3_EXT_3V4 and VSMPS4_EXT_3V4 */68 [AB8500_EXT_SUPPLY3] = {69 .constraints = {70 .name = "ab8500-ext-supply3",71 .min_uV = 3400000,72 .max_uV = 3400000,73 .valid_ops_mask = REGULATOR_CHANGE_STATUS,74 .boot_on = 1,75 },76 .num_consumer_supplies =77 ARRAY_SIZE(ab8500_ext_supply3_consumers),78 .consumer_supplies = ab8500_ext_supply3_consumers,79 },80};81 82/**83 * struct ab8500_ext_regulator_info - ab8500 regulator information84 * @dev: device pointer85 * @desc: regulator description86 * @cfg: regulator configuration (extension of regulator FW configuration)87 * @update_bank: bank to control on/off88 * @update_reg: register to control on/off89 * @update_mask: mask to enable/disable and set mode of regulator90 * @update_val: bits holding the regulator current mode91 * @update_val_hp: bits to set EN pin active (LPn pin deactive)92 * normally this means high power mode93 * @update_val_lp: bits to set EN pin active and LPn pin active94 * normally this means low power mode95 * @update_val_hw: bits to set regulator pins in HW control96 * SysClkReq pins and logic will choose mode97 */98struct ab8500_ext_regulator_info {99 struct device *dev;100 struct regulator_desc desc;101 struct ab8500_ext_regulator_cfg *cfg;102 u8 update_bank;103 u8 update_reg;104 u8 update_mask;105 u8 update_val;106 u8 update_val_hp;107 u8 update_val_lp;108 u8 update_val_hw;109};110 111static int ab8500_ext_regulator_enable(struct regulator_dev *rdev)112{113 int ret;114 struct ab8500_ext_regulator_info *info = rdev_get_drvdata(rdev);115 u8 regval;116 117 if (info == NULL) {118 dev_err(rdev_get_dev(rdev), "regulator info null pointer\n");119 return -EINVAL;120 }121 122 /*123 * To satisfy both HW high power request and SW request, the regulator124 * must be on in high power.125 */126 if (info->cfg && info->cfg->hwreq)127 regval = info->update_val_hp;128 else129 regval = info->update_val;130 131 ret = abx500_mask_and_set_register_interruptible(info->dev,132 info->update_bank, info->update_reg,133 info->update_mask, regval);134 if (ret < 0) {135 dev_err(rdev_get_dev(rdev),136 "couldn't set enable bits for regulator\n");137 return ret;138 }139 140 dev_dbg(rdev_get_dev(rdev),141 "%s-enable (bank, reg, mask, value): 0x%02x, 0x%02x, 0x%02x, 0x%02x\n",142 info->desc.name, info->update_bank, info->update_reg,143 info->update_mask, regval);144 145 return 0;146}147 148static int ab8500_ext_regulator_disable(struct regulator_dev *rdev)149{150 int ret;151 struct ab8500_ext_regulator_info *info = rdev_get_drvdata(rdev);152 u8 regval;153 154 if (info == NULL) {155 dev_err(rdev_get_dev(rdev), "regulator info null pointer\n");156 return -EINVAL;157 }158 159 /*160 * Set the regulator in HW request mode if configured161 */162 if (info->cfg && info->cfg->hwreq)163 regval = info->update_val_hw;164 else165 regval = 0;166 167 ret = abx500_mask_and_set_register_interruptible(info->dev,168 info->update_bank, info->update_reg,169 info->update_mask, regval);170 if (ret < 0) {171 dev_err(rdev_get_dev(rdev),172 "couldn't set disable bits for regulator\n");173 return ret;174 }175 176 dev_dbg(rdev_get_dev(rdev), "%s-disable (bank, reg, mask, value):"177 " 0x%02x, 0x%02x, 0x%02x, 0x%02x\n",178 info->desc.name, info->update_bank, info->update_reg,179 info->update_mask, regval);180 181 return 0;182}183 184static int ab8500_ext_regulator_is_enabled(struct regulator_dev *rdev)185{186 int ret;187 struct ab8500_ext_regulator_info *info = rdev_get_drvdata(rdev);188 u8 regval;189 190 if (info == NULL) {191 dev_err(rdev_get_dev(rdev), "regulator info null pointer\n");192 return -EINVAL;193 }194 195 ret = abx500_get_register_interruptible(info->dev,196 info->update_bank, info->update_reg, ®val);197 if (ret < 0) {198 dev_err(rdev_get_dev(rdev),199 "couldn't read 0x%x register\n", info->update_reg);200 return ret;201 }202 203 dev_dbg(rdev_get_dev(rdev), "%s-is_enabled (bank, reg, mask, value):"204 " 0x%02x, 0x%02x, 0x%02x, 0x%02x\n",205 info->desc.name, info->update_bank, info->update_reg,206 info->update_mask, regval);207 208 if (((regval & info->update_mask) == info->update_val_lp) ||209 ((regval & info->update_mask) == info->update_val_hp))210 return 1;211 else212 return 0;213}214 215static int ab8500_ext_regulator_set_mode(struct regulator_dev *rdev,216 unsigned int mode)217{218 int ret = 0;219 struct ab8500_ext_regulator_info *info = rdev_get_drvdata(rdev);220 u8 regval;221 222 if (info == NULL) {223 dev_err(rdev_get_dev(rdev), "regulator info null pointer\n");224 return -EINVAL;225 }226 227 switch (mode) {228 case REGULATOR_MODE_NORMAL:229 regval = info->update_val_hp;230 break;231 case REGULATOR_MODE_IDLE:232 regval = info->update_val_lp;233 break;234 235 default:236 return -EINVAL;237 }238 239 /* If regulator is enabled and info->cfg->hwreq is set, the regulator240 must be on in high power, so we don't need to write the register with241 the same value.242 */243 if (ab8500_ext_regulator_is_enabled(rdev) &&244 !(info->cfg && info->cfg->hwreq)) {245 ret = abx500_mask_and_set_register_interruptible(info->dev,246 info->update_bank, info->update_reg,247 info->update_mask, regval);248 if (ret < 0) {249 dev_err(rdev_get_dev(rdev),250 "Could not set regulator mode.\n");251 return ret;252 }253 254 dev_dbg(rdev_get_dev(rdev),255 "%s-set_mode (bank, reg, mask, value): "256 "0x%x, 0x%x, 0x%x, 0x%x\n",257 info->desc.name, info->update_bank, info->update_reg,258 info->update_mask, regval);259 }260 261 info->update_val = regval;262 263 return 0;264}265 266static unsigned int ab8500_ext_regulator_get_mode(struct regulator_dev *rdev)267{268 struct ab8500_ext_regulator_info *info = rdev_get_drvdata(rdev);269 int ret;270 271 if (info == NULL) {272 dev_err(rdev_get_dev(rdev), "regulator info null pointer\n");273 return -EINVAL;274 }275 276 if (info->update_val == info->update_val_hp)277 ret = REGULATOR_MODE_NORMAL;278 else if (info->update_val == info->update_val_lp)279 ret = REGULATOR_MODE_IDLE;280 else281 ret = -EINVAL;282 283 return ret;284}285 286static int ab8500_ext_set_voltage(struct regulator_dev *rdev, int min_uV,287 int max_uV, unsigned *selector)288{289 struct regulation_constraints *regu_constraints = rdev->constraints;290 291 if (!regu_constraints) {292 dev_err(rdev_get_dev(rdev), "No regulator constraints\n");293 return -EINVAL;294 }295 296 if (regu_constraints->min_uV == min_uV &&297 regu_constraints->max_uV == max_uV)298 return 0;299 300 dev_err(rdev_get_dev(rdev),301 "Requested min %duV max %duV != constrained min %duV max %duV\n",302 min_uV, max_uV,303 regu_constraints->min_uV, regu_constraints->max_uV);304 305 return -EINVAL;306}307 308static int ab8500_ext_list_voltage(struct regulator_dev *rdev,309 unsigned selector)310{311 struct regulation_constraints *regu_constraints = rdev->constraints;312 313 if (regu_constraints == NULL) {314 dev_err(rdev_get_dev(rdev), "regulator constraints null pointer\n");315 return -EINVAL;316 }317 /* return the uV for the fixed regulators */318 if (regu_constraints->min_uV && regu_constraints->max_uV) {319 if (regu_constraints->min_uV == regu_constraints->max_uV)320 return regu_constraints->min_uV;321 }322 return -EINVAL;323}324 325static const struct regulator_ops ab8500_ext_regulator_ops = {326 .enable = ab8500_ext_regulator_enable,327 .disable = ab8500_ext_regulator_disable,328 .is_enabled = ab8500_ext_regulator_is_enabled,329 .set_mode = ab8500_ext_regulator_set_mode,330 .get_mode = ab8500_ext_regulator_get_mode,331 .set_voltage = ab8500_ext_set_voltage,332 .list_voltage = ab8500_ext_list_voltage,333};334 335static struct ab8500_ext_regulator_info336 ab8500_ext_regulator_info[AB8500_NUM_EXT_REGULATORS] = {337 [AB8500_EXT_SUPPLY1] = {338 .desc = {339 .name = "VEXTSUPPLY1",340 .of_match = of_match_ptr("ab8500_ext1"),341 .ops = &ab8500_ext_regulator_ops,342 .type = REGULATOR_VOLTAGE,343 .id = AB8500_EXT_SUPPLY1,344 .owner = THIS_MODULE,345 .n_voltages = 1,346 },347 .update_bank = 0x04,348 .update_reg = 0x08,349 .update_mask = 0x03,350 .update_val = 0x01,351 .update_val_hp = 0x01,352 .update_val_lp = 0x03,353 .update_val_hw = 0x02,354 },355 [AB8500_EXT_SUPPLY2] = {356 .desc = {357 .name = "VEXTSUPPLY2",358 .of_match = of_match_ptr("ab8500_ext2"),359 .ops = &ab8500_ext_regulator_ops,360 .type = REGULATOR_VOLTAGE,361 .id = AB8500_EXT_SUPPLY2,362 .owner = THIS_MODULE,363 .n_voltages = 1,364 },365 .update_bank = 0x04,366 .update_reg = 0x08,367 .update_mask = 0x0c,368 .update_val = 0x04,369 .update_val_hp = 0x04,370 .update_val_lp = 0x0c,371 .update_val_hw = 0x08,372 },373 [AB8500_EXT_SUPPLY3] = {374 .desc = {375 .name = "VEXTSUPPLY3",376 .of_match = of_match_ptr("ab8500_ext3"),377 .ops = &ab8500_ext_regulator_ops,378 .type = REGULATOR_VOLTAGE,379 .id = AB8500_EXT_SUPPLY3,380 .owner = THIS_MODULE,381 .n_voltages = 1,382 },383 .update_bank = 0x04,384 .update_reg = 0x08,385 .update_mask = 0x30,386 .update_val = 0x10,387 .update_val_hp = 0x10,388 .update_val_lp = 0x30,389 .update_val_hw = 0x20,390 },391};392 393static int ab8500_ext_regulator_probe(struct platform_device *pdev)394{395 struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent);396 struct regulator_config config = { };397 struct regulator_dev *rdev;398 int i;399 400 if (!ab8500) {401 dev_err(&pdev->dev, "null mfd parent\n");402 return -EINVAL;403 }404 405 /* check for AB8500 2.x */406 if (is_ab8500_2p0_or_earlier(ab8500)) {407 struct ab8500_ext_regulator_info *info;408 409 /* VextSupply3LPn is inverted on AB8500 2.x */410 info = &ab8500_ext_regulator_info[AB8500_EXT_SUPPLY3];411 info->update_val = 0x30;412 info->update_val_hp = 0x30;413 info->update_val_lp = 0x10;414 }415 416 /* register all regulators */417 for (i = 0; i < ARRAY_SIZE(ab8500_ext_regulator_info); i++) {418 struct ab8500_ext_regulator_info *info = NULL;419 420 /* assign per-regulator data */421 info = &ab8500_ext_regulator_info[i];422 info->dev = &pdev->dev;423 info->cfg = (struct ab8500_ext_regulator_cfg *)424 ab8500_ext_regulators[i].driver_data;425 426 config.dev = &pdev->dev;427 config.driver_data = info;428 config.init_data = &ab8500_ext_regulators[i];429 430 /* register regulator with framework */431 rdev = devm_regulator_register(&pdev->dev, &info->desc,432 &config);433 if (IS_ERR(rdev)) {434 dev_err(&pdev->dev, "failed to register regulator %s\n",435 info->desc.name);436 return PTR_ERR(rdev);437 }438 439 dev_dbg(&pdev->dev, "%s-probed\n", info->desc.name);440 }441 442 return 0;443}444 445static struct platform_driver ab8500_ext_regulator_driver = {446 .probe = ab8500_ext_regulator_probe,447 .driver = {448 .name = "ab8500-ext-regulator",449 .probe_type = PROBE_PREFER_ASYNCHRONOUS,450 },451};452 453static int __init ab8500_ext_regulator_init(void)454{455 int ret;456 457 ret = platform_driver_register(&ab8500_ext_regulator_driver);458 if (ret)459 pr_err("Failed to register ab8500 ext regulator: %d\n", ret);460 461 return ret;462}463subsys_initcall(ab8500_ext_regulator_init);464 465static void __exit ab8500_ext_regulator_exit(void)466{467 platform_driver_unregister(&ab8500_ext_regulator_driver);468}469module_exit(ab8500_ext_regulator_exit);470 471MODULE_LICENSE("GPL v2");472MODULE_AUTHOR("Bengt Jonsson <bengt.g.jonsson@stericsson.com>");473MODULE_DESCRIPTION("AB8500 external regulator driver");474MODULE_ALIAS("platform:ab8500-ext-regulator");475