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 enable_bit[2];
  61        int enable_reg[2];
  62
  63        /* for DVM regulators */
  64        int go_reg;
  65        int go_bit;
  66};
  67
  68static inline struct device *to_tps6586x_dev(struct regulator_dev *rdev)
  69{
  70        return rdev_get_dev(rdev)->parent;
  71}
  72
  73static int tps6586x_set_voltage_sel(struct regulator_dev *rdev,
  74                                    unsigned selector)
  75{
  76        struct tps6586x_regulator *ri = rdev_get_drvdata(rdev);
  77        struct device *parent = to_tps6586x_dev(rdev);
  78        int ret, val, rid = rdev_get_id(rdev);
  79        uint8_t mask;
  80
  81        val = selector << (ffs(rdev->desc->vsel_mask) - 1);
  82        mask = rdev->desc->vsel_mask;
  83
  84        ret = tps6586x_update(parent, rdev->desc->vsel_reg, val, mask);
  85        if (ret)
  86                return ret;
  87
  88        /* Update go bit for DVM regulators */
  89        switch (rid) {
  90        case TPS6586X_ID_LDO_2:
  91        case TPS6586X_ID_LDO_4:
  92        case TPS6586X_ID_SM_0:
  93        case TPS6586X_ID_SM_1:
  94                ret = tps6586x_set_bits(parent, ri->go_reg, 1 << ri->go_bit);
  95                break;
  96        }
  97        return ret;
  98}
  99
 100static struct regulator_ops tps6586x_regulator_ops = {
 101        .list_voltage = regulator_list_voltage_table,
 102        .get_voltage_sel = regulator_get_voltage_sel_regmap,
 103        .set_voltage_sel = tps6586x_set_voltage_sel,
 104
 105        .is_enabled = regulator_is_enabled_regmap,
 106        .enable = regulator_enable_regmap,
 107        .disable = regulator_disable_regmap,
 108};
 109
 110static struct regulator_ops tps6586x_sys_regulator_ops = {
 111};
 112
 113static const unsigned int tps6586x_ldo0_voltages[] = {
 114        1200000, 1500000, 1800000, 2500000, 2700000, 2850000, 3100000, 3300000,
 115};
 116
 117static const unsigned int tps6586x_ldo4_voltages[] = {
 118        1700000, 1725000, 1750000, 1775000, 1800000, 1825000, 1850000, 1875000,
 119        1900000, 1925000, 1950000, 1975000, 2000000, 2025000, 2050000, 2075000,
 120        2100000, 2125000, 2150000, 2175000, 2200000, 2225000, 2250000, 2275000,
 121        2300000, 2325000, 2350000, 2375000, 2400000, 2425000, 2450000, 2475000,
 122};
 123
 124static const unsigned int tps6586x_ldo_voltages[] = {
 125        1250000, 1500000, 1800000, 2500000, 2700000, 2850000, 3100000, 3300000,
 126};
 127
 128static const unsigned int tps6586x_sm2_voltages[] = {
 129        3000000, 3050000, 3100000, 3150000, 3200000, 3250000, 3300000, 3350000,
 130        3400000, 3450000, 3500000, 3550000, 3600000, 3650000, 3700000, 3750000,
 131        3800000, 3850000, 3900000, 3950000, 4000000, 4050000, 4100000, 4150000,
 132        4200000, 4250000, 4300000, 4350000, 4400000, 4450000, 4500000, 4550000,
 133};
 134
 135static const unsigned int tps6586x_dvm_voltages[] = {
 136         725000,  750000,  775000,  800000,  825000,  850000,  875000,  900000,
 137         925000,  950000,  975000, 1000000, 1025000, 1050000, 1075000, 1100000,
 138        1125000, 1150000, 1175000, 1200000, 1225000, 1250000, 1275000, 1300000,
 139        1325000, 1350000, 1375000, 1400000, 1425000, 1450000, 1475000, 1500000,
 140};
 141
 142#define TPS6586X_REGULATOR(_id, _pin_name, vdata, vreg, shift, nbits,   \
 143                           ereg0, ebit0, ereg1, ebit1)                  \
 144        .desc   = {                                                     \
 145                .supply_name = _pin_name,                               \
 146                .name   = "REG-" #_id,                                  \
 147                .ops    = &tps6586x_regulator_ops,                      \
 148                .type   = REGULATOR_VOLTAGE,                            \
 149                .id     = TPS6586X_ID_##_id,                            \
 150                .n_voltages = ARRAY_SIZE(tps6586x_##vdata##_voltages),  \
 151                .volt_table = tps6586x_##vdata##_voltages,              \
 152                .owner  = THIS_MODULE,                                  \
 153                .enable_reg = TPS6586X_SUPPLY##ereg0,                   \
 154                .enable_mask = 1 << (ebit0),                            \
 155                .vsel_reg = TPS6586X_##vreg,                            \
 156                .vsel_mask = ((1 << (nbits)) - 1) << (shift),           \
 157        },                                                              \
 158        .enable_reg[0]  = TPS6586X_SUPPLY##ereg0,                       \
 159        .enable_bit[0]  = (ebit0),                                      \
 160        .enable_reg[1]  = TPS6586X_SUPPLY##ereg1,                       \
 161        .enable_bit[1]  = (ebit1),
 162
 163#define TPS6586X_REGULATOR_DVM_GOREG(goreg, gobit)                      \
 164        .go_reg = TPS6586X_##goreg,                                     \
 165        .go_bit = (gobit),
 166
 167#define TPS6586X_LDO(_id, _pname, vdata, vreg, shift, nbits,            \
 168                     ereg0, ebit0, ereg1, ebit1)                        \
 169{                                                                       \
 170        TPS6586X_REGULATOR(_id, _pname, vdata, vreg, shift, nbits,      \
 171                           ereg0, ebit0, ereg1, ebit1)                  \
 172}
 173
 174#define TPS6586X_DVM(_id, _pname, vdata, vreg, shift, nbits,            \
 175                     ereg0, ebit0, ereg1, ebit1, goreg, gobit)          \
 176{                                                                       \
 177        TPS6586X_REGULATOR(_id, _pname, vdata, vreg, shift, nbits,      \
 178                           ereg0, ebit0, ereg1, ebit1)                  \
 179        TPS6586X_REGULATOR_DVM_GOREG(goreg, gobit)                      \
 180}
 181
 182#define TPS6586X_SYS_REGULATOR()                                        \
 183{                                                                       \
 184        .desc   = {                                                     \
 185                .supply_name = "sys",                                   \
 186                .name   = "REG-SYS",                                    \
 187                .ops    = &tps6586x_sys_regulator_ops,                  \
 188                .type   = REGULATOR_VOLTAGE,                            \
 189                .id     = TPS6586X_ID_SYS,                              \
 190                .owner  = THIS_MODULE,                                  \
 191        },                                                              \
 192}
 193
 194static struct tps6586x_regulator tps6586x_regulator[] = {
 195        TPS6586X_SYS_REGULATOR(),
 196        TPS6586X_LDO(LDO_0, "vinldo01", ldo0, SUPPLYV1, 5, 3, ENC, 0, END, 0),
 197        TPS6586X_LDO(LDO_3, "vinldo23", ldo, SUPPLYV4, 0, 3, ENC, 2, END, 2),
 198        TPS6586X_LDO(LDO_5, "REG-SYS", ldo, SUPPLYV6, 0, 3, ENE, 6, ENE, 6),
 199        TPS6586X_LDO(LDO_6, "vinldo678", ldo, SUPPLYV3, 0, 3, ENC, 4, END, 4),
 200        TPS6586X_LDO(LDO_7, "vinldo678", ldo, SUPPLYV3, 3, 3, ENC, 5, END, 5),
 201        TPS6586X_LDO(LDO_8, "vinldo678", ldo, SUPPLYV2, 5, 3, ENC, 6, END, 6),
 202        TPS6586X_LDO(LDO_9, "vinldo9", ldo, SUPPLYV6, 3, 3, ENE, 7, ENE, 7),
 203        TPS6586X_LDO(LDO_RTC, "REG-SYS", ldo, SUPPLYV4, 3, 3, V4, 7, V4, 7),
 204        TPS6586X_LDO(LDO_1, "vinldo01", dvm, SUPPLYV1, 0, 5, ENC, 1, END, 1),
 205        TPS6586X_LDO(SM_2, "vin-sm2", sm2, SUPPLYV2, 0, 5, ENC, 7, END, 7),
 206
 207        TPS6586X_DVM(LDO_2, "vinldo23", dvm, LDO2BV1, 0, 5, ENA, 3,
 208                                        ENB, 3, VCC2, 6),
 209        TPS6586X_DVM(LDO_4, "vinldo4", ldo4, LDO4V1, 0, 5, ENC, 3,
 210                                        END, 3, VCC1, 6),
 211        TPS6586X_DVM(SM_0, "vin-sm0", dvm, SM0V1, 0, 5, ENA, 1,
 212                                        ENB, 1, VCC1, 2),
 213        TPS6586X_DVM(SM_1, "vin-sm1", dvm, SM1V1, 0, 5, ENA, 0,
 214                                        ENB, 0, VCC1, 0),
 215};
 216
 217/*
 218 * TPS6586X has 2 enable bits that are OR'ed to determine the actual
 219 * regulator state. Clearing one of this bits allows switching
 220 * regulator on and of with single register write.
 221 */
 222static inline int tps6586x_regulator_preinit(struct device *parent,
 223                                             struct tps6586x_regulator *ri)
 224{
 225        uint8_t val1, val2;
 226        int ret;
 227
 228        if (ri->enable_reg[0] == ri->enable_reg[1] &&
 229            ri->enable_bit[0] == ri->enable_bit[1])
 230                        return 0;
 231
 232        ret = tps6586x_read(parent, ri->enable_reg[0], &val1);
 233        if (ret)
 234                return ret;
 235
 236        ret = tps6586x_read(parent, ri->enable_reg[1], &val2);
 237        if (ret)
 238                return ret;
 239
 240        if (!(val2 & (1 << ri->enable_bit[1])))
 241                return 0;
 242
 243        /*
 244         * The regulator is on, but it's enabled with the bit we don't
 245         * want to use, so we switch the enable bits
 246         */
 247        if (!(val1 & (1 << ri->enable_bit[0]))) {
 248                ret = tps6586x_set_bits(parent, ri->enable_reg[0],
 249                                        1 << ri->enable_bit[0]);
 250                if (ret)
 251                        return ret;
 252        }
 253
 254        return tps6586x_clr_bits(parent, ri->enable_reg[1],
 255                                 1 << ri->enable_bit[1]);
 256}
 257
 258static int tps6586x_regulator_set_slew_rate(struct platform_device *pdev)
 259{
 260        struct device *parent = pdev->dev.parent;
 261        struct regulator_init_data *p = pdev->dev.platform_data;
 262        struct tps6586x_settings *setting = p->driver_data;
 263        uint8_t reg;
 264
 265        if (setting == NULL)
 266                return 0;
 267
 268        if (!(setting->slew_rate & TPS6586X_SLEW_RATE_SET))
 269                return 0;
 270
 271        /* only SM0 and SM1 can have the slew rate settings */
 272        switch (pdev->id) {
 273        case TPS6586X_ID_SM_0:
 274                reg = TPS6586X_SM0SL;
 275                break;
 276        case TPS6586X_ID_SM_1:
 277                reg = TPS6586X_SM1SL;
 278                break;
 279        default:
 280                dev_warn(&pdev->dev, "Only SM0/SM1 can set slew rate\n");
 281                return -EINVAL;
 282        }
 283
 284        return tps6586x_write(parent, reg,
 285                        setting->slew_rate & TPS6586X_SLEW_RATE_MASK);
 286}
 287
 288static inline struct tps6586x_regulator *find_regulator_info(int id)
 289{
 290        struct tps6586x_regulator *ri;
 291        int i;
 292
 293        for (i = 0; i < ARRAY_SIZE(tps6586x_regulator); i++) {
 294                ri = &tps6586x_regulator[i];
 295                if (ri->desc.id == id)
 296                        return ri;
 297        }
 298        return NULL;
 299}
 300
 301static int __devinit tps6586x_regulator_probe(struct platform_device *pdev)
 302{
 303        struct tps6586x_regulator *ri = NULL;
 304        struct regulator_config config = { };
 305        struct regulator_dev *rdev;
 306        int id = pdev->id;
 307        int err;
 308
 309        dev_dbg(&pdev->dev, "Probing regulator %d\n", id);
 310
 311        ri = find_regulator_info(id);
 312        if (ri == NULL) {
 313                dev_err(&pdev->dev, "invalid regulator ID specified\n");
 314                return -EINVAL;
 315        }
 316
 317        err = tps6586x_regulator_preinit(pdev->dev.parent, ri);
 318        if (err)
 319                return err;
 320
 321        config.dev = pdev->dev.parent;
 322        config.of_node = pdev->dev.of_node;
 323        config.init_data = pdev->dev.platform_data;
 324        config.driver_data = ri;
 325
 326        rdev = regulator_register(&ri->desc, &config);
 327        if (IS_ERR(rdev)) {
 328                dev_err(&pdev->dev, "failed to register regulator %s\n",
 329                                ri->desc.name);
 330                return PTR_ERR(rdev);
 331        }
 332
 333        platform_set_drvdata(pdev, rdev);
 334
 335        return tps6586x_regulator_set_slew_rate(pdev);
 336}
 337
 338static int __devexit tps6586x_regulator_remove(struct platform_device *pdev)
 339{
 340        struct regulator_dev *rdev = platform_get_drvdata(pdev);
 341
 342        regulator_unregister(rdev);
 343        return 0;
 344}
 345
 346static struct platform_driver tps6586x_regulator_driver = {
 347        .driver = {
 348                .name   = "tps6586x-regulator",
 349                .owner  = THIS_MODULE,
 350        },
 351        .probe          = tps6586x_regulator_probe,
 352        .remove         = __devexit_p(tps6586x_regulator_remove),
 353};
 354
 355static int __init tps6586x_regulator_init(void)
 356{
 357        return platform_driver_register(&tps6586x_regulator_driver);
 358}
 359subsys_initcall(tps6586x_regulator_init);
 360
 361static void __exit tps6586x_regulator_exit(void)
 362{
 363        platform_driver_unregister(&tps6586x_regulator_driver);
 364}
 365module_exit(tps6586x_regulator_exit);
 366
 367MODULE_LICENSE("GPL");
 368MODULE_AUTHOR("Mike Rapoport <mike@compulab.co.il>");
 369MODULE_DESCRIPTION("Regulator Driver for TI TPS6586X PMIC");
 370MODULE_ALIAS("platform:tps6586x-regulator");
 371
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.