linux/drivers/regulator/ab8500-ext.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Copyright (C) ST-Ericsson SA 2010
   4 *
   5 * Authors: Bengt Jonsson <bengt.g.jonsson@stericsson.com>
   6 *
   7 * This file is based on drivers/regulator/ab8500.c
   8 *
   9 * AB8500 external regulators
  10 *
  11 * ab8500-ext supports the following regulators:
  12 * - VextSupply3
  13 */
  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 regulators
  46 */
  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 information
  84 * @dev: device pointer
  85 * @desc: regulator description
  86 * @cfg: regulator configuration (extension of regulator FW configuration)
  87 * @update_bank: bank to control on/off
  88 * @update_reg: register to control on/off
  89 * @update_mask: mask to enable/disable and set mode of regulator
  90 * @update_val: bits holding the regulator current mode
  91 * @update_val_hp: bits to set EN pin active (LPn pin deactive)
  92 *                 normally this means high power mode
  93 * @update_val_lp: bits to set EN pin active and LPn pin active
  94 *                 normally this means low power mode
  95 * @update_val_hw: bits to set regulator pins in HW control
  96 *                 SysClkReq pins and logic will choose mode
  97 */
  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 regulator
 124         * must be on in high power.
 125         */
 126        if (info->cfg && info->cfg->hwreq)
 127                regval = info->update_val_hp;
 128        else
 129                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 configured
 161         */
 162        if (info->cfg && info->cfg->hwreq)
 163                regval = info->update_val_hw;
 164        else
 165                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, &regval);
 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        else
 212                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 regulator
 240           must be on in high power, so we don't need to write the register with
 241           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        else
 281                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_info
 336                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        },
 450};
 451
 452static int __init ab8500_ext_regulator_init(void)
 453{
 454        int ret;
 455
 456        ret = platform_driver_register(&ab8500_ext_regulator_driver);
 457        if (ret)
 458                pr_err("Failed to register ab8500 ext regulator: %d\n", ret);
 459
 460        return ret;
 461}
 462subsys_initcall(ab8500_ext_regulator_init);
 463
 464static void __exit ab8500_ext_regulator_exit(void)
 465{
 466        platform_driver_unregister(&ab8500_ext_regulator_driver);
 467}
 468module_exit(ab8500_ext_regulator_exit);
 469
 470MODULE_LICENSE("GPL v2");
 471MODULE_AUTHOR("Bengt Jonsson <bengt.g.jonsson@stericsson.com>");
 472MODULE_DESCRIPTION("AB8500 external regulator driver");
 473MODULE_ALIAS("platform:ab8500-ext-regulator");
 474