linux/drivers/regulator/tps6586x-regulator.c
<<
>>
Prefs
   1/*
   2 * Regulator driver for TI TPS6586x
   3 *
   4 * Copyright (C) 2010 Compulab Ltd.
   5 * Author: Mike Rapoport <mike@compulab.co.il>
   6 *
   7 * Based on da903x
   8 * Copyright (C) 2006-2008 Marvell International Ltd.
   9 * Copyright (C) 2008 Compulab Ltd.
  10 *
  11 * This program is free software; you can redistribute it and/or modify
  12 * it under the terms of the GNU General Public License version 2 as
  13 * published by the Free Software Foundation.
  14 */
  15
  16#include <linux/kernel.h>
  17#include <linux/module.h>
  18#include <linux/init.h>
  19#include <linux/err.h>
  20#include <linux/slab.h>
  21#include <linux/platform_device.h>
  22#include <linux/regulator/driver.h>
  23#include <linux/regulator/machine.h>
  24#include <linux/mfd/tps6586x.h>
  25
  26/* supply control and voltage setting  */
  27#define TPS6586X_SUPPLYENA      0x10
  28#define TPS6586X_SUPPLYENB      0x11
  29#define TPS6586X_SUPPLYENC      0x12
  30#define TPS6586X_SUPPLYEND      0x13
  31#define TPS6586X_SUPPLYENE      0x14
  32#define TPS6586X_VCC1           0x20
  33#define TPS6586X_VCC2           0x21
  34#define TPS6586X_SM1V1          0x23
  35#define TPS6586X_SM1V2          0x24
  36#define TPS6586X_SM1SL          0x25
  37#define TPS6586X_SM0V1          0x26
  38#define TPS6586X_SM0V2          0x27
  39#define TPS6586X_SM0SL          0x28
  40#define TPS6586X_LDO2AV1        0x29
  41#define TPS6586X_LDO2AV2        0x2A
  42#define TPS6586X_LDO2BV1        0x2F
  43#define TPS6586X_LDO2BV2        0x30
  44#define TPS6586X_LDO4V1         0x32
  45#define TPS6586X_LDO4V2         0x33
  46
  47/* converter settings  */
  48#define TPS6586X_SUPPLYV1       0x41
  49#define TPS6586X_SUPPLYV2       0x42
  50#define TPS6586X_SUPPLYV3       0x43
  51#define TPS6586X_SUPPLYV4       0x44
  52#define TPS6586X_SUPPLYV5       0x45
  53#define TPS6586X_SUPPLYV6       0x46
  54#define TPS6586X_SMODE1         0x47
  55#define TPS6586X_SMODE2         0x48
  56
  57struct tps6586x_regulator {
  58        struct regulator_desc desc;
  59
  60        int volt_reg;
  61        int volt_shift;
  62        int volt_nbits;
  63        int enable_bit[2];
  64        int enable_reg[2];
  65
  66        /* for DVM regulators */
  67        int go_reg;
  68        int go_bit;
  69};
  70
  71static inline struct device *to_tps6586x_dev(struct regulator_dev *rdev)
  72{
  73        return rdev_get_dev(rdev)->parent;
  74}
  75
  76static int tps6586x_set_voltage_sel(struct regulator_dev *rdev,
  77                                    unsigned selector)
  78{
  79        struct tps6586x_regulator *ri = rdev_get_drvdata(rdev);
  80        struct device *parent = to_tps6586x_dev(rdev);
  81        int ret, val, rid = rdev_get_id(rdev);
  82        uint8_t mask;
  83
  84        val = selector << ri->volt_shift;
  85        mask = ((1 << ri->volt_nbits) - 1) << ri->volt_shift;
  86
  87        ret = tps6586x_update(parent, ri->volt_reg, val, mask);
  88        if (ret)
  89                return ret;
  90
  91        /* Update go bit for DVM regulators */
  92        switch (rid) {
  93        case TPS6586X_ID_LDO_2:
  94        case TPS6586X_ID_LDO_4:
  95        case TPS6586X_ID_SM_0:
  96        case TPS6586X_ID_SM_1:
  97                ret = tps6586x_set_bits(parent, ri->go_reg, 1 << ri->go_bit);
  98                break;
  99        }
 100        return ret;
 101}
 102
 103static int tps6586x_get_voltage_sel(struct regulator_dev *rdev)
 104{
 105        struct tps6586x_regulator *ri = rdev_get_drvdata(rdev);
 106        struct device *parent = to_tps6586x_dev(rdev);
 107        uint8_t val, mask;
 108        int ret;
 109
 110        ret = tps6586x_read(parent, ri->volt_reg, &val);
 111        if (ret)
 112                return ret;
 113
 114        mask = ((1 << ri->volt_nbits) - 1) << ri->volt_shift;
 115        val = (val & mask) >> ri->volt_shift;
 116
 117        if (val >= ri->desc.n_voltages)
 118                BUG();
 119
 120        return val;
 121}
 122
 123static int tps6586x_regulator_enable(struct regulator_dev *rdev)
 124{
 125        struct tps6586x_regulator *ri = rdev_get_drvdata(rdev);
 126        struct device *parent = to_tps6586x_dev(rdev);
 127
 128        return tps6586x_set_bits(parent, ri->enable_reg[0],
 129                                 1 << ri->enable_bit[0]);
 130}
 131
 132static int tps6586x_regulator_disable(struct regulator_dev *rdev)
 133{
 134        struct tps6586x_regulator *ri = rdev_get_drvdata(rdev);
 135        struct device *parent = to_tps6586x_dev(rdev);
 136
 137        return tps6586x_clr_bits(parent, ri->enable_reg[0],
 138                                 1 << ri->enable_bit[0]);
 139}
 140
 141static int tps6586x_regulator_is_enabled(struct regulator_dev *rdev)
 142{
 143        struct tps6586x_regulator *ri = rdev_get_drvdata(rdev);
 144        struct device *parent = to_tps6586x_dev(rdev);
 145        uint8_t reg_val;
 146        int ret;
 147
 148        ret = tps6586x_read(parent, ri->enable_reg[0], &reg_val);
 149        if (ret)
 150                return ret;
 151
 152        return !!(reg_val & (1 << ri->enable_bit[0]));
 153}
 154
 155static struct regulator_ops tps6586x_regulator_ops = {
 156        .list_voltage = regulator_list_voltage_table,
 157        .get_voltage_sel = tps6586x_get_voltage_sel,
 158        .set_voltage_sel = tps6586x_set_voltage_sel,
 159
 160        .is_enabled = tps6586x_regulator_is_enabled,
 161        .enable = tps6586x_regulator_enable,
 162        .disable = tps6586x_regulator_disable,
 163};
 164
 165static const unsigned int tps6586x_ldo0_voltages[] = {
 166        1200000, 1500000, 1800000, 2500000, 2700000, 2850000, 3100000, 3300000,
 167};
 168
 169static const unsigned int tps6586x_ldo4_voltages[] = {
 170        1700000, 1725000, 1750000, 1775000, 1800000, 1825000, 1850000, 1875000,
 171        1900000, 1925000, 1950000, 1975000, 2000000, 2025000, 2050000, 2075000,
 172        2100000, 2125000, 2150000, 2175000, 2200000, 2225000, 2250000, 2275000,
 173        2300000, 2325000, 2350000, 2375000, 2400000, 2425000, 2450000, 2475000,
 174};
 175
 176static const unsigned int tps6586x_ldo_voltages[] = {
 177        1250000, 1500000, 1800000, 2500000, 2700000, 2850000, 3100000, 3300000,
 178};
 179
 180static const unsigned int tps6586x_sm2_voltages[] = {
 181        3000000, 3050000, 3100000, 3150000, 3200000, 3250000, 3300000, 3350000,
 182        3400000, 3450000, 3500000, 3550000, 3600000, 3650000, 3700000, 3750000,
 183        3800000, 3850000, 3900000, 3950000, 4000000, 4050000, 4100000, 4150000,
 184        4200000, 4250000, 4300000, 4350000, 4400000, 4450000, 4500000, 4550000,
 185};
 186
 187static const unsigned int tps6586x_dvm_voltages[] = {
 188         725000,  750000,  775000,  800000,  825000,  850000,  875000,  900000,
 189         925000,  950000,  975000, 1000000, 1025000, 1050000, 1075000, 1100000,
 190        1125000, 1150000, 1175000, 1200000, 1225000, 1250000, 1275000, 1300000,
 191        1325000, 1350000, 1375000, 1400000, 1425000, 1450000, 1475000, 1500000,
 192};
 193
 194#define TPS6586X_REGULATOR(_id, _pin_name, vdata, vreg, shift, nbits,   \
 195                           ereg0, ebit0, ereg1, ebit1)                  \
 196        .desc   = {                                                     \
 197                .supply_name = _pin_name,                               \
 198                .name   = "REG-" #_id,                                  \
 199                .ops    = &tps6586x_regulator_ops,                      \
 200                .type   = REGULATOR_VOLTAGE,                            \
 201                .id     = TPS6586X_ID_##_id,                            \
 202                .n_voltages = ARRAY_SIZE(tps6586x_##vdata##_voltages),  \
 203                .volt_table = tps6586x_##vdata##_voltages,              \
 204                .owner  = THIS_MODULE,                                  \
 205        },                                                              \
 206        .volt_reg       = TPS6586X_##vreg,                              \
 207        .volt_shift     = (shift),                                      \
 208        .volt_nbits     = (nbits),                                      \
 209        .enable_reg[0]  = TPS6586X_SUPPLY##ereg0,                       \
 210        .enable_bit[0]  = (ebit0),                                      \
 211        .enable_reg[1]  = TPS6586X_SUPPLY##ereg1,                       \
 212        .enable_bit[1]  = (ebit1),
 213
 214#define TPS6586X_REGULATOR_DVM_GOREG(goreg, gobit)                      \
 215        .go_reg = TPS6586X_##goreg,                                     \
 216        .go_bit = (gobit),
 217
 218#define TPS6586X_LDO(_id, _pname, vdata, vreg, shift, nbits,            \
 219                     ereg0, ebit0, ereg1, ebit1)                        \
 220{                                                                       \
 221        TPS6586X_REGULATOR(_id, _pname, vdata, vreg, shift, nbits,      \
 222                           ereg0, ebit0, ereg1, ebit1)                  \
 223}
 224
 225#define TPS6586X_DVM(_id, _pname, vdata, vreg, shift, nbits,            \
 226                     ereg0, ebit0, ereg1, ebit1, goreg, gobit)          \
 227{                                                                       \
 228        TPS6586X_REGULATOR(_id, _pname, vdata, vreg, shift, nbits,      \
 229                           ereg0, ebit0, ereg1, ebit1)                  \
 230        TPS6586X_REGULATOR_DVM_GOREG(goreg, gobit)                      \
 231}
 232
 233static struct tps6586x_regulator tps6586x_regulator[] = {
 234        TPS6586X_LDO(LDO_0, "vinldo01", ldo0, SUPPLYV1, 5, 3, ENC, 0, END, 0),
 235        TPS6586X_LDO(LDO_3, "vinldo23", ldo, SUPPLYV4, 0, 3, ENC, 2, END, 2),
 236        TPS6586X_LDO(LDO_5, NULL, ldo, SUPPLYV6, 0, 3, ENE, 6, ENE, 6),
 237        TPS6586X_LDO(LDO_6, "vinldo678", ldo, SUPPLYV3, 0, 3, ENC, 4, END, 4),
 238        TPS6586X_LDO(LDO_7, "vinldo678", ldo, SUPPLYV3, 3, 3, ENC, 5, END, 5),
 239        TPS6586X_LDO(LDO_8, "vinldo678", ldo, SUPPLYV2, 5, 3, ENC, 6, END, 6),
 240        TPS6586X_LDO(LDO_9, "vinldo9", ldo, SUPPLYV6, 3, 3, ENE, 7, ENE, 7),
 241        TPS6586X_LDO(LDO_RTC, NULL, ldo, SUPPLYV4, 3, 3, V4, 7, V4, 7),
 242        TPS6586X_LDO(LDO_1, "vinldo01", dvm, SUPPLYV1, 0, 5, ENC, 1, END, 1),
 243        TPS6586X_LDO(SM_2, "vin-sm2", sm2, SUPPLYV2, 0, 5, ENC, 7, END, 7),
 244
 245        TPS6586X_DVM(LDO_2, "vinldo23", dvm, LDO2BV1, 0, 5, ENA, 3,
 246                                        ENB, 3, VCC2, 6),
 247        TPS6586X_DVM(LDO_4, "vinldo4", ldo4, LDO4V1, 0, 5, ENC, 3,
 248                                        END, 3, VCC1, 6),
 249        TPS6586X_DVM(SM_0, "vin-sm0", dvm, SM0V1, 0, 5, ENA, 1,
 250                                        ENB, 1, VCC1, 2),
 251        TPS6586X_DVM(SM_1, "vin-sm1", dvm, SM1V1, 0, 5, ENA, 0,
 252                                        ENB, 0, VCC1, 0),
 253};
 254
 255/*
 256 * TPS6586X has 2 enable bits that are OR'ed to determine the actual
 257 * regulator state. Clearing one of this bits allows switching
 258 * regulator on and of with single register write.
 259 */
 260static inline int tps6586x_regulator_preinit(struct device *parent,
 261                                             struct tps6586x_regulator *ri)
 262{
 263        uint8_t val1, val2;
 264        int ret;
 265
 266        if (ri->enable_reg[0] == ri->enable_reg[1] &&
 267            ri->enable_bit[0] == ri->enable_bit[1])
 268                        return 0;
 269
 270        ret = tps6586x_read(parent, ri->enable_reg[0], &val1);
 271        if (ret)
 272                return ret;
 273
 274        ret = tps6586x_read(parent, ri->enable_reg[1], &val2);
 275        if (ret)
 276                return ret;
 277
 278        if (!(val2 & (1 << ri->enable_bit[1])))
 279                return 0;
 280
 281        /*
 282         * The regulator is on, but it's enabled with the bit we don't
 283         * want to use, so we switch the enable bits
 284         */
 285        if (!(val1 & (1 << ri->enable_bit[0]))) {
 286                ret = tps6586x_set_bits(parent, ri->enable_reg[0],
 287                                        1 << ri->enable_bit[0]);
 288                if (ret)
 289                        return ret;
 290        }
 291
 292        return tps6586x_clr_bits(parent, ri->enable_reg[1],
 293                                 1 << ri->enable_bit[1]);
 294}
 295
 296static int tps6586x_regulator_set_slew_rate(struct platform_device *pdev)
 297{
 298        struct device *parent = pdev->dev.parent;
 299        struct regulator_init_data *p = pdev->dev.platform_data;
 300        struct tps6586x_settings *setting = p->driver_data;
 301        uint8_t reg;
 302
 303        if (setting == NULL)
 304                return 0;
 305
 306        if (!(setting->slew_rate & TPS6586X_SLEW_RATE_SET))
 307                return 0;
 308
 309        /* only SM0 and SM1 can have the slew rate settings */
 310        switch (pdev->id) {
 311        case TPS6586X_ID_SM_0:
 312                reg = TPS6586X_SM0SL;
 313                break;
 314        case TPS6586X_ID_SM_1:
 315                reg = TPS6586X_SM1SL;
 316                break;
 317        default:
 318                dev_warn(&pdev->dev, "Only SM0/SM1 can set slew rate\n");
 319                return -EINVAL;
 320        }
 321
 322        return tps6586x_write(parent, reg,
 323                        setting->slew_rate & TPS6586X_SLEW_RATE_MASK);
 324}
 325
 326static inline struct tps6586x_regulator *find_regulator_info(int id)
 327{
 328        struct tps6586x_regulator *ri;
 329        int i;
 330
 331        for (i = 0; i < ARRAY_SIZE(tps6586x_regulator); i++) {
 332                ri = &tps6586x_regulator[i];
 333                if (ri->desc.id == id)
 334                        return ri;
 335        }
 336        return NULL;
 337}
 338
 339static int __devinit tps6586x_regulator_probe(struct platform_device *pdev)
 340{
 341        struct tps6586x_regulator *ri = NULL;
 342        struct regulator_config config = { };
 343        struct regulator_dev *rdev;
 344        int id = pdev->id;
 345        int err;
 346
 347        dev_dbg(&pdev->dev, "Probing regulator %d\n", id);
 348
 349        ri = find_regulator_info(id);
 350        if (ri == NULL) {
 351                dev_err(&pdev->dev, "invalid regulator ID specified\n");
 352                return -EINVAL;
 353        }
 354
 355        err = tps6586x_regulator_preinit(pdev->dev.parent, ri);
 356        if (err)
 357                return err;
 358
 359        config.dev = pdev->dev.parent;
 360        config.of_node = pdev->dev.of_node;
 361        config.init_data = pdev->dev.platform_data;
 362        config.driver_data = ri;
 363
 364        rdev = regulator_register(&ri->desc, &config);
 365        if (IS_ERR(rdev)) {
 366                dev_err(&pdev->dev, "failed to register regulator %s\n",
 367                                ri->desc.name);
 368                return PTR_ERR(rdev);
 369        }
 370
 371        platform_set_drvdata(pdev, rdev);
 372
 373        return tps6586x_regulator_set_slew_rate(pdev);
 374}
 375
 376static int __devexit tps6586x_regulator_remove(struct platform_device *pdev)
 377{
 378        struct regulator_dev *rdev = platform_get_drvdata(pdev);
 379
 380        regulator_unregister(rdev);
 381        return 0;
 382}
 383
 384static struct platform_driver tps6586x_regulator_driver = {
 385        .driver = {
 386                .name   = "tps6586x-regulator",
 387                .owner  = THIS_MODULE,
 388        },
 389        .probe          = tps6586x_regulator_probe,
 390        .remove         = __devexit_p(tps6586x_regulator_remove),
 391};
 392
 393static int __init tps6586x_regulator_init(void)
 394{
 395        return platform_driver_register(&tps6586x_regulator_driver);
 396}
 397subsys_initcall(tps6586x_regulator_init);
 398
 399static void __exit tps6586x_regulator_exit(void)
 400{
 401        platform_driver_unregister(&tps6586x_regulator_driver);
 402}
 403module_exit(tps6586x_regulator_exit);
 404
 405MODULE_LICENSE("GPL");
 406MODULE_AUTHOR("Mike Rapoport <mike@compulab.co.il>");
 407MODULE_DESCRIPTION("Regulator Driver for TI TPS6586X PMIC");
 408MODULE_ALIAS("platform:tps6586x-regulator");
 409
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.