linux/drivers/regulator/lp8788-buck.c
<<
>>
Prefs
   1/*
   2 * TI LP8788 MFD - buck regulator driver
   3 *
   4 * Copyright 2012 Texas Instruments
   5 *
   6 * Author: Milo(Woogyom) Kim <milo.kim@ti.com>
   7 *
   8 * This program is free software; you can redistribute it and/or modify
   9 * it under the terms of the GNU General Public License version 2 as
  10 * published by the Free Software Foundation.
  11 *
  12 */
  13
  14#include <linux/module.h>
  15#include <linux/slab.h>
  16#include <linux/err.h>
  17#include <linux/platform_device.h>
  18#include <linux/regulator/driver.h>
  19#include <linux/mfd/lp8788.h>
  20#include <linux/gpio.h>
  21
  22/* register address */
  23#define LP8788_EN_BUCK                  0x0C
  24#define LP8788_BUCK_DVS_SEL             0x1D
  25#define LP8788_BUCK1_VOUT0              0x1E
  26#define LP8788_BUCK1_VOUT1              0x1F
  27#define LP8788_BUCK1_VOUT2              0x20
  28#define LP8788_BUCK1_VOUT3              0x21
  29#define LP8788_BUCK2_VOUT0              0x22
  30#define LP8788_BUCK2_VOUT1              0x23
  31#define LP8788_BUCK2_VOUT2              0x24
  32#define LP8788_BUCK2_VOUT3              0x25
  33#define LP8788_BUCK3_VOUT               0x26
  34#define LP8788_BUCK4_VOUT               0x27
  35#define LP8788_BUCK1_TIMESTEP           0x28
  36#define LP8788_BUCK_PWM                 0x2D
  37
  38/* mask/shift bits */
  39#define LP8788_EN_BUCK1_M               BIT(0)  /* Addr 0Ch */
  40#define LP8788_EN_BUCK2_M               BIT(1)
  41#define LP8788_EN_BUCK3_M               BIT(2)
  42#define LP8788_EN_BUCK4_M               BIT(3)
  43#define LP8788_BUCK1_DVS_SEL_M          0x04    /* Addr 1Dh */
  44#define LP8788_BUCK1_DVS_M              0x03
  45#define LP8788_BUCK1_DVS_S              0
  46#define LP8788_BUCK2_DVS_SEL_M          0x40
  47#define LP8788_BUCK2_DVS_M              0x30
  48#define LP8788_BUCK2_DVS_S              4
  49#define LP8788_BUCK1_DVS_I2C            BIT(2)
  50#define LP8788_BUCK2_DVS_I2C            BIT(6)
  51#define LP8788_BUCK1_DVS_PIN            (0 << 2)
  52#define LP8788_BUCK2_DVS_PIN            (0 << 6)
  53#define LP8788_VOUT_M                   0x1F    /* Addr 1Eh ~ 27h */
  54#define LP8788_STARTUP_TIME_M           0xF8    /* Addr 28h ~ 2Bh */
  55#define LP8788_STARTUP_TIME_S           3
  56#define LP8788_FPWM_BUCK1_M             BIT(0)  /* Addr 2Dh */
  57#define LP8788_FPWM_BUCK1_S             0
  58#define LP8788_FPWM_BUCK2_M             BIT(1)
  59#define LP8788_FPWM_BUCK2_S             1
  60#define LP8788_FPWM_BUCK3_M             BIT(2)
  61#define LP8788_FPWM_BUCK3_S             2
  62#define LP8788_FPWM_BUCK4_M             BIT(3)
  63#define LP8788_FPWM_BUCK4_S             3
  64
  65#define INVALID_ADDR                    0xFF
  66#define LP8788_FORCE_PWM                1
  67#define LP8788_AUTO_PWM                 0
  68#define PIN_LOW                         0
  69#define PIN_HIGH                        1
  70#define ENABLE_TIME_USEC                32
  71
  72#define BUCK_FPWM_MASK(x)               (1 << (x))
  73#define BUCK_FPWM_SHIFT(x)              (x)
  74
  75enum lp8788_dvs_state {
  76        DVS_LOW  = GPIOF_OUT_INIT_LOW,
  77        DVS_HIGH = GPIOF_OUT_INIT_HIGH,
  78};
  79
  80enum lp8788_dvs_mode {
  81        REGISTER,
  82        EXTPIN,
  83};
  84
  85enum lp8788_buck_id {
  86        BUCK1,
  87        BUCK2,
  88        BUCK3,
  89        BUCK4,
  90};
  91
  92struct lp8788_buck {
  93        struct lp8788 *lp;
  94        struct regulator_dev *regulator;
  95        void *dvs;
  96};
  97
  98/* BUCK 1 ~ 4 voltage table */
  99static const int lp8788_buck_vtbl[] = {
 100         500000,  800000,  850000,  900000,  950000, 1000000, 1050000, 1100000,
 101        1150000, 1200000, 1250000, 1300000, 1350000, 1400000, 1450000, 1500000,
 102        1550000, 1600000, 1650000, 1700000, 1750000, 1800000, 1850000, 1900000,
 103        1950000, 2000000,
 104};
 105
 106static const u8 buck1_vout_addr[] = {
 107        LP8788_BUCK1_VOUT0, LP8788_BUCK1_VOUT1,
 108        LP8788_BUCK1_VOUT2, LP8788_BUCK1_VOUT3,
 109};
 110
 111static const u8 buck2_vout_addr[] = {
 112        LP8788_BUCK2_VOUT0, LP8788_BUCK2_VOUT1,
 113        LP8788_BUCK2_VOUT2, LP8788_BUCK2_VOUT3,
 114};
 115
 116static void lp8788_buck1_set_dvs(struct lp8788_buck *buck)
 117{
 118        struct lp8788_buck1_dvs *dvs = (struct lp8788_buck1_dvs *)buck->dvs;
 119        enum lp8788_dvs_state pinstate;
 120
 121        if (!dvs)
 122                return;
 123
 124        pinstate = dvs->vsel == DVS_SEL_V0 ? DVS_LOW : DVS_HIGH;
 125        if (gpio_is_valid(dvs->gpio))
 126                gpio_set_value(dvs->gpio, pinstate);
 127}
 128
 129static void lp8788_buck2_set_dvs(struct lp8788_buck *buck)
 130{
 131        struct lp8788_buck2_dvs *dvs = (struct lp8788_buck2_dvs *)buck->dvs;
 132        enum lp8788_dvs_state pin1, pin2;
 133
 134        if (!dvs)
 135                return;
 136
 137        switch (dvs->vsel) {
 138        case DVS_SEL_V0:
 139                pin1 = DVS_LOW;
 140                pin2 = DVS_LOW;
 141                break;
 142        case DVS_SEL_V1:
 143                pin1 = DVS_HIGH;
 144                pin2 = DVS_LOW;
 145                break;
 146        case DVS_SEL_V2:
 147                pin1 = DVS_LOW;
 148                pin2 = DVS_HIGH;
 149                break;
 150        case DVS_SEL_V3:
 151                pin1 = DVS_HIGH;
 152                pin2 = DVS_HIGH;
 153                break;
 154        default:
 155                return;
 156        }
 157
 158        if (gpio_is_valid(dvs->gpio[0]))
 159                gpio_set_value(dvs->gpio[0], pin1);
 160
 161        if (gpio_is_valid(dvs->gpio[1]))
 162                gpio_set_value(dvs->gpio[1], pin2);
 163}
 164
 165static void lp8788_set_dvs(struct lp8788_buck *buck, enum lp8788_buck_id id)
 166{
 167        switch (id) {
 168        case BUCK1:
 169                lp8788_buck1_set_dvs(buck);
 170                break;
 171        case BUCK2:
 172                lp8788_buck2_set_dvs(buck);
 173                break;
 174        default:
 175                break;
 176        }
 177}
 178
 179static enum lp8788_dvs_mode
 180lp8788_get_buck_dvs_ctrl_mode(struct lp8788_buck *buck, enum lp8788_buck_id id)
 181{
 182        u8 val, mask;
 183
 184        switch (id) {
 185        case BUCK1:
 186                mask = LP8788_BUCK1_DVS_SEL_M;
 187                break;
 188        case BUCK2:
 189                mask = LP8788_BUCK2_DVS_SEL_M;
 190                break;
 191        default:
 192                return REGISTER;
 193        }
 194
 195        lp8788_read_byte(buck->lp, LP8788_BUCK_DVS_SEL, &val);
 196
 197        return val & mask ? REGISTER : EXTPIN;
 198}
 199
 200static bool lp8788_is_valid_buck_addr(u8 addr)
 201{
 202        switch (addr) {
 203        case LP8788_BUCK1_VOUT0:
 204        case LP8788_BUCK1_VOUT1:
 205        case LP8788_BUCK1_VOUT2:
 206        case LP8788_BUCK1_VOUT3:
 207        case LP8788_BUCK2_VOUT0:
 208        case LP8788_BUCK2_VOUT1:
 209        case LP8788_BUCK2_VOUT2:
 210        case LP8788_BUCK2_VOUT3:
 211                return true;
 212        default:
 213                return false;
 214        }
 215}
 216
 217static u8 lp8788_select_buck_vout_addr(struct lp8788_buck *buck,
 218                                        enum lp8788_buck_id id)
 219{
 220        enum lp8788_dvs_mode mode = lp8788_get_buck_dvs_ctrl_mode(buck, id);
 221        struct lp8788_buck1_dvs *b1_dvs;
 222        struct lp8788_buck2_dvs *b2_dvs;
 223        u8 val, idx, addr;
 224        int pin1, pin2;
 225
 226        switch (id) {
 227        case BUCK1:
 228                if (mode == EXTPIN) {
 229                        b1_dvs = (struct lp8788_buck1_dvs *)buck->dvs;
 230                        if (!b1_dvs)
 231                                goto err;
 232
 233                        idx = gpio_get_value(b1_dvs->gpio) ? 1 : 0;
 234                } else {
 235                        lp8788_read_byte(buck->lp, LP8788_BUCK_DVS_SEL, &val);
 236                        idx = (val & LP8788_BUCK1_DVS_M) >> LP8788_BUCK1_DVS_S;
 237                }
 238                addr = buck1_vout_addr[idx];
 239                break;
 240        case BUCK2:
 241                if (mode == EXTPIN) {
 242                        b2_dvs = (struct lp8788_buck2_dvs *)buck->dvs;
 243                        if (!b2_dvs)
 244                                goto err;
 245
 246                        pin1 = gpio_get_value(b2_dvs->gpio[0]);
 247                        pin2 = gpio_get_value(b2_dvs->gpio[1]);
 248
 249                        if (pin1 == PIN_LOW && pin2 == PIN_LOW)
 250                                idx = 0;
 251                        else if (pin1 == PIN_LOW && pin2 == PIN_HIGH)
 252                                idx = 2;
 253                        else if (pin1 == PIN_HIGH && pin2 == PIN_LOW)
 254                                idx = 1;
 255                        else
 256                                idx = 3;
 257                } else {
 258                        lp8788_read_byte(buck->lp, LP8788_BUCK_DVS_SEL, &val);
 259                        idx = (val & LP8788_BUCK2_DVS_M) >> LP8788_BUCK2_DVS_S;
 260                }
 261                addr = buck2_vout_addr[idx];
 262                break;
 263        default:
 264                goto err;
 265        }
 266
 267        return addr;
 268err:
 269        return INVALID_ADDR;
 270}
 271
 272static int lp8788_buck12_set_voltage_sel(struct regulator_dev *rdev,
 273                                        unsigned selector)
 274{
 275        struct lp8788_buck *buck = rdev_get_drvdata(rdev);
 276        enum lp8788_buck_id id = rdev_get_id(rdev);
 277        u8 addr;
 278
 279        if (buck->dvs)
 280                lp8788_set_dvs(buck, id);
 281
 282        addr = lp8788_select_buck_vout_addr(buck, id);
 283        if (!lp8788_is_valid_buck_addr(addr))
 284                return -EINVAL;
 285
 286        return lp8788_update_bits(buck->lp, addr, LP8788_VOUT_M, selector);
 287}
 288
 289static int lp8788_buck12_get_voltage_sel(struct regulator_dev *rdev)
 290{
 291        struct lp8788_buck *buck = rdev_get_drvdata(rdev);
 292        enum lp8788_buck_id id = rdev_get_id(rdev);
 293        int ret;
 294        u8 val, addr;
 295
 296        addr = lp8788_select_buck_vout_addr(buck, id);
 297        if (!lp8788_is_valid_buck_addr(addr))
 298                return -EINVAL;
 299
 300        ret = lp8788_read_byte(buck->lp, addr, &val);
 301        if (ret)
 302                return ret;
 303
 304        return val & LP8788_VOUT_M;
 305}
 306
 307static int lp8788_buck_enable_time(struct regulator_dev *rdev)
 308{
 309        struct lp8788_buck *buck = rdev_get_drvdata(rdev);
 310        enum lp8788_buck_id id = rdev_get_id(rdev);
 311        u8 val, addr = LP8788_BUCK1_TIMESTEP + id;
 312
 313        if (lp8788_read_byte(buck->lp, addr, &val))
 314                return -EINVAL;
 315
 316        val = (val & LP8788_STARTUP_TIME_M) >> LP8788_STARTUP_TIME_S;
 317
 318        return ENABLE_TIME_USEC * val;
 319}
 320
 321static int lp8788_buck_set_mode(struct regulator_dev *rdev, unsigned int mode)
 322{
 323        struct lp8788_buck *buck = rdev_get_drvdata(rdev);
 324        enum lp8788_buck_id id = rdev_get_id(rdev);
 325        u8 mask, val;
 326
 327        mask = BUCK_FPWM_MASK(id);
 328        switch (mode) {
 329        case REGULATOR_MODE_FAST:
 330                val = LP8788_FORCE_PWM << BUCK_FPWM_SHIFT(id);
 331                break;
 332        case REGULATOR_MODE_NORMAL:
 333                val = LP8788_AUTO_PWM << BUCK_FPWM_SHIFT(id);
 334                break;
 335        default:
 336                return -EINVAL;
 337        }
 338
 339        return lp8788_update_bits(buck->lp, LP8788_BUCK_PWM, mask, val);
 340}
 341
 342static unsigned int lp8788_buck_get_mode(struct regulator_dev *rdev)
 343{
 344        struct lp8788_buck *buck = rdev_get_drvdata(rdev);
 345        enum lp8788_buck_id id = rdev_get_id(rdev);
 346        u8 val;
 347        int ret;
 348
 349        ret = lp8788_read_byte(buck->lp, LP8788_BUCK_PWM, &val);
 350        if (ret)
 351                return ret;
 352
 353        return val & BUCK_FPWM_MASK(id) ?
 354                                REGULATOR_MODE_FAST : REGULATOR_MODE_NORMAL;
 355}
 356
 357static struct regulator_ops lp8788_buck12_ops = {
 358        .list_voltage = regulator_list_voltage_table,
 359        .set_voltage_sel = lp8788_buck12_set_voltage_sel,
 360        .get_voltage_sel = lp8788_buck12_get_voltage_sel,
 361        .enable = regulator_enable_regmap,
 362        .disable = regulator_disable_regmap,
 363        .is_enabled = regulator_is_enabled_regmap,
 364        .enable_time = lp8788_buck_enable_time,
 365        .set_mode = lp8788_buck_set_mode,
 366        .get_mode = lp8788_buck_get_mode,
 367};
 368
 369static struct regulator_ops lp8788_buck34_ops = {
 370        .list_voltage = regulator_list_voltage_table,
 371        .set_voltage_sel = regulator_set_voltage_sel_regmap,
 372        .get_voltage_sel = regulator_get_voltage_sel_regmap,
 373        .enable = regulator_enable_regmap,
 374        .disable = regulator_disable_regmap,
 375        .is_enabled = regulator_is_enabled_regmap,
 376        .enable_time = lp8788_buck_enable_time,
 377        .set_mode = lp8788_buck_set_mode,
 378        .get_mode = lp8788_buck_get_mode,
 379};
 380
 381static struct regulator_desc lp8788_buck_desc[] = {
 382        {
 383                .name = "buck1",
 384                .id = BUCK1,
 385                .ops = &lp8788_buck12_ops,
 386                .n_voltages = ARRAY_SIZE(lp8788_buck_vtbl),
 387                .volt_table = lp8788_buck_vtbl,
 388                .type = REGULATOR_VOLTAGE,
 389                .owner = THIS_MODULE,
 390                .enable_reg = LP8788_EN_BUCK,
 391                .enable_mask = LP8788_EN_BUCK1_M,
 392        },
 393        {
 394                .name = "buck2",
 395                .id = BUCK2,
 396                .ops = &lp8788_buck12_ops,
 397                .n_voltages = ARRAY_SIZE(lp8788_buck_vtbl),
 398                .volt_table = lp8788_buck_vtbl,
 399                .type = REGULATOR_VOLTAGE,
 400                .owner = THIS_MODULE,
 401                .enable_reg = LP8788_EN_BUCK,
 402                .enable_mask = LP8788_EN_BUCK2_M,
 403        },
 404        {
 405                .name = "buck3",
 406                .id = BUCK3,
 407                .ops = &lp8788_buck34_ops,
 408                .n_voltages = ARRAY_SIZE(lp8788_buck_vtbl),
 409                .volt_table = lp8788_buck_vtbl,
 410                .type = REGULATOR_VOLTAGE,
 411                .owner = THIS_MODULE,
 412                .vsel_reg = LP8788_BUCK3_VOUT,
 413                .vsel_mask = LP8788_VOUT_M,
 414                .enable_reg = LP8788_EN_BUCK,
 415                .enable_mask = LP8788_EN_BUCK3_M,
 416        },
 417        {
 418                .name = "buck4",
 419                .id = BUCK4,
 420                .ops = &lp8788_buck34_ops,
 421                .n_voltages = ARRAY_SIZE(lp8788_buck_vtbl),
 422                .volt_table = lp8788_buck_vtbl,
 423                .type = REGULATOR_VOLTAGE,
 424                .owner = THIS_MODULE,
 425                .vsel_reg = LP8788_BUCK4_VOUT,
 426                .vsel_mask = LP8788_VOUT_M,
 427                .enable_reg = LP8788_EN_BUCK,
 428                .enable_mask = LP8788_EN_BUCK4_M,
 429        },
 430};
 431
 432static int _gpio_request(struct lp8788_buck *buck, int gpio, char *name)
 433{
 434        struct device *dev = buck->lp->dev;
 435
 436        if (!gpio_is_valid(gpio)) {
 437                dev_err(dev, "invalid gpio: %d\n", gpio);
 438                return -EINVAL;
 439        }
 440
 441        return devm_gpio_request_one(dev, gpio, DVS_LOW, name);
 442}
 443
 444static int lp8788_dvs_gpio_request(struct lp8788_buck *buck,
 445                                enum lp8788_buck_id id)
 446{
 447        struct lp8788_platform_data *pdata = buck->lp->pdata;
 448        char *b1_name = "LP8788_B1_DVS";
 449        char *b2_name[] = { "LP8788_B2_DVS1", "LP8788_B2_DVS2" };
 450        int i, gpio, ret;
 451
 452        switch (id) {
 453        case BUCK1:
 454                gpio = pdata->buck1_dvs->gpio;
 455                ret = _gpio_request(buck, gpio, b1_name);
 456                if (ret)
 457                        return ret;
 458
 459                buck->dvs = pdata->buck1_dvs;
 460                break;
 461        case BUCK2:
 462                for (i = 0 ; i < LP8788_NUM_BUCK2_DVS ; i++) {
 463                        gpio = pdata->buck2_dvs->gpio[i];
 464                        ret = _gpio_request(buck, gpio, b2_name[i]);
 465                        if (ret)
 466                                return ret;
 467                }
 468                buck->dvs = pdata->buck2_dvs;
 469                break;
 470        default:
 471                break;
 472        }
 473
 474        return 0;
 475}
 476
 477static int lp8788_init_dvs(struct lp8788_buck *buck, enum lp8788_buck_id id)
 478{
 479        struct lp8788_platform_data *pdata = buck->lp->pdata;
 480        u8 mask[] = { LP8788_BUCK1_DVS_SEL_M, LP8788_BUCK2_DVS_SEL_M };
 481        u8 val[]  = { LP8788_BUCK1_DVS_PIN, LP8788_BUCK2_DVS_PIN };
 482        u8 default_dvs_mode[] = { LP8788_BUCK1_DVS_I2C, LP8788_BUCK2_DVS_I2C };
 483
 484        /* no dvs for buck3, 4 */
 485        if (id == BUCK3 || id == BUCK4)
 486                return 0;
 487
 488        /* no dvs platform data, then dvs will be selected by I2C registers */
 489        if (!pdata)
 490                goto set_default_dvs_mode;
 491
 492        if ((id == BUCK1 && !pdata->buck1_dvs) ||
 493                (id == BUCK2 && !pdata->buck2_dvs))
 494                goto set_default_dvs_mode;
 495
 496        if (lp8788_dvs_gpio_request(buck, id))
 497                goto set_default_dvs_mode;
 498
 499        return lp8788_update_bits(buck->lp, LP8788_BUCK_DVS_SEL, mask[id],
 500                                val[id]);
 501
 502set_default_dvs_mode:
 503        return lp8788_update_bits(buck->lp, LP8788_BUCK_DVS_SEL, mask[id],
 504                                  default_dvs_mode[id]);
 505}
 506
 507static __devinit int lp8788_buck_probe(struct platform_device *pdev)
 508{
 509        struct lp8788 *lp = dev_get_drvdata(pdev->dev.parent);
 510        int id = pdev->id;
 511        struct lp8788_buck *buck;
 512        struct regulator_config cfg = { };
 513        struct regulator_dev *rdev;
 514        int ret;
 515
 516        buck = devm_kzalloc(lp->dev, sizeof(struct lp8788_buck), GFP_KERNEL);
 517        if (!buck)
 518                return -ENOMEM;
 519
 520        buck->lp = lp;
 521
 522        ret = lp8788_init_dvs(buck, id);
 523        if (ret)
 524                return ret;
 525
 526        cfg.dev = lp->dev;
 527        cfg.init_data = lp->pdata ? lp->pdata->buck_data[id] : NULL;
 528        cfg.driver_data = buck;
 529        cfg.regmap = lp->regmap;
 530
 531        rdev = regulator_register(&lp8788_buck_desc[id], &cfg);
 532        if (IS_ERR(rdev)) {
 533                ret = PTR_ERR(rdev);
 534                dev_err(lp->dev, "BUCK%d regulator register err = %d\n",
 535                                id + 1, ret);
 536                return ret;
 537        }
 538
 539        buck->regulator = rdev;
 540        platform_set_drvdata(pdev, buck);
 541
 542        return 0;
 543}
 544
 545static int __devexit lp8788_buck_remove(struct platform_device *pdev)
 546{
 547        struct lp8788_buck *buck = platform_get_drvdata(pdev);
 548
 549        platform_set_drvdata(pdev, NULL);
 550        regulator_unregister(buck->regulator);
 551
 552        return 0;
 553}
 554
 555static struct platform_driver lp8788_buck_driver = {
 556        .probe = lp8788_buck_probe,
 557        .remove = __devexit_p(lp8788_buck_remove),
 558        .driver = {
 559                .name = LP8788_DEV_BUCK,
 560                .owner = THIS_MODULE,
 561        },
 562};
 563
 564static int __init lp8788_buck_init(void)
 565{
 566        return platform_driver_register(&lp8788_buck_driver);
 567}
 568subsys_initcall(lp8788_buck_init);
 569
 570static void __exit lp8788_buck_exit(void)
 571{
 572        platform_driver_unregister(&lp8788_buck_driver);
 573}
 574module_exit(lp8788_buck_exit);
 575
 576MODULE_DESCRIPTION("TI LP8788 BUCK Driver");
 577MODULE_AUTHOR("Milo Kim");
 578MODULE_LICENSE("GPL");
 579MODULE_ALIAS("platform:lp8788-buck");
 580
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.