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