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 void lp8788_buck1_set_dvs(struct lp8788_buck *buck)
 107{
 108        struct lp8788_buck1_dvs *dvs = (struct lp8788_buck1_dvs *)buck->dvs;
 109        enum lp8788_dvs_state pinstate;
 110
 111        if (!dvs)
 112                return;
 113
 114        pinstate = dvs->vsel == DVS_SEL_V0 ? DVS_LOW : DVS_HIGH;
 115        if (gpio_is_valid(dvs->gpio))
 116                gpio_set_value(dvs->gpio, pinstate);
 117}
 118
 119static void lp8788_buck2_set_dvs(struct lp8788_buck *buck)
 120{
 121        struct lp8788_buck2_dvs *dvs = (struct lp8788_buck2_dvs *)buck->dvs;
 122        enum lp8788_dvs_state pin1, pin2;
 123
 124        if (!dvs)
 125                return;
 126
 127        switch (dvs->vsel) {
 128        case DVS_SEL_V0:
 129                pin1 = DVS_LOW;
 130                pin2 = DVS_LOW;
 131                break;
 132        case DVS_SEL_V1:
 133                pin1 = DVS_HIGH;
 134                pin2 = DVS_LOW;
 135                break;
 136        case DVS_SEL_V2:
 137                pin1 = DVS_LOW;
 138                pin2 = DVS_HIGH;
 139                break;
 140        case DVS_SEL_V3:
 141                pin1 = DVS_HIGH;
 142                pin2 = DVS_HIGH;
 143                break;
 144        default:
 145                return;
 146        }
 147
 148        if (gpio_is_valid(dvs->gpio[0]))
 149                gpio_set_value(dvs->gpio[0], pin1);
 150
 151        if (gpio_is_valid(dvs->gpio[1]))
 152                gpio_set_value(dvs->gpio[1], pin2);
 153}
 154
 155static void lp8788_set_dvs(struct lp8788_buck *buck, enum lp8788_buck_id id)
 156{
 157        switch (id) {
 158        case BUCK1:
 159                lp8788_buck1_set_dvs(buck);
 160                break;
 161        case BUCK2:
 162                lp8788_buck2_set_dvs(buck);
 163                break;
 164        default:
 165                break;
 166        }
 167}
 168
 169static enum lp8788_dvs_mode
 170lp8788_get_buck_dvs_ctrl_mode(struct lp8788_buck *buck, enum lp8788_buck_id id)
 171{
 172        u8 val, mask;
 173
 174        switch (id) {
 175        case BUCK1:
 176                mask = LP8788_BUCK1_DVS_SEL_M;
 177                break;
 178        case BUCK2:
 179                mask = LP8788_BUCK2_DVS_SEL_M;
 180                break;
 181        default:
 182                return REGISTER;
 183        }
 184
 185        lp8788_read_byte(buck->lp, LP8788_BUCK_DVS_SEL, &val);
 186
 187        return val & mask ? REGISTER : EXTPIN;
 188}
 189
 190static bool lp8788_is_valid_buck_addr(u8 addr)
 191{
 192        switch (addr) {
 193        case LP8788_BUCK1_VOUT0:
 194        case LP8788_BUCK1_VOUT1:
 195        case LP8788_BUCK1_VOUT2:
 196        case LP8788_BUCK1_VOUT3:
 197        case LP8788_BUCK2_VOUT0:
 198        case LP8788_BUCK2_VOUT1:
 199        case LP8788_BUCK2_VOUT2:
 200        case LP8788_BUCK2_VOUT3:
 201                return true;
 202        default:
 203                return false;
 204        }
 205}
 206
 207static u8 lp8788_select_buck_vout_addr(struct lp8788_buck *buck,
 208                                        enum lp8788_buck_id id)
 209{
 210        enum lp8788_dvs_mode mode = lp8788_get_buck_dvs_ctrl_mode(buck, id);
 211        struct lp8788_buck1_dvs *b1_dvs;
 212        struct lp8788_buck2_dvs *b2_dvs;
 213        u8 val, idx, addr;
 214        int pin1, pin2;
 215
 216        switch (id) {
 217        case BUCK1:
 218                if (mode == EXTPIN) {
 219                        b1_dvs = (struct lp8788_buck1_dvs *)buck->dvs;
 220                        if (!b1_dvs)
 221                                goto err;
 222
 223                        idx = gpio_get_value(b1_dvs->gpio) ? 1 : 0;
 224                } else {
 225                        lp8788_read_byte(buck->lp, LP8788_BUCK_DVS_SEL, &val);
 226                        idx = (val & LP8788_BUCK1_DVS_M) >> LP8788_BUCK1_DVS_S;
 227                }
 228                addr = LP8788_BUCK1_VOUT0 + idx;
 229                break;
 230        case BUCK2:
 231                if (mode == EXTPIN) {
 232                        b2_dvs = (struct lp8788_buck2_dvs *)buck->dvs;
 233                        if (!b2_dvs)
 234                                goto err;
 235
 236                        pin1 = gpio_get_value(b2_dvs->gpio[0]);
 237                        pin2 = gpio_get_value(b2_dvs->gpio[1]);
 238
 239                        if (pin1 == PIN_LOW && pin2 == PIN_LOW)
 240                                idx = 0;
 241                        else if (pin1 == PIN_LOW && pin2 == PIN_HIGH)
 242                                idx = 2;
 243                        else if (pin1 == PIN_HIGH && pin2 == PIN_LOW)
 244                                idx = 1;
 245                        else
 246                                idx = 3;
 247                } else {
 248                        lp8788_read_byte(buck->lp, LP8788_BUCK_DVS_SEL, &val);
 249                        idx = (val & LP8788_BUCK2_DVS_M) >> LP8788_BUCK2_DVS_S;
 250                }
 251                addr = LP8788_BUCK2_VOUT0 + idx;
 252                break;
 253        default:
 254                goto err;
 255        }
 256
 257        return addr;
 258err:
 259        return INVALID_ADDR;
 260}
 261
 262static int lp8788_buck12_set_voltage_sel(struct regulator_dev *rdev,
 263                                        unsigned selector)
 264{
 265        struct lp8788_buck *buck = rdev_get_drvdata(rdev);
 266        enum lp8788_buck_id id = rdev_get_id(rdev);
 267        u8 addr;
 268
 269        if (buck->dvs)
 270                lp8788_set_dvs(buck, id);
 271
 272        addr = lp8788_select_buck_vout_addr(buck, id);
 273        if (!lp8788_is_valid_buck_addr(addr))
 274                return -EINVAL;
 275
 276        return lp8788_update_bits(buck->lp, addr, LP8788_VOUT_M, selector);
 277}
 278
 279static int lp8788_buck12_get_voltage_sel(struct regulator_dev *rdev)
 280{
 281        struct lp8788_buck *buck = rdev_get_drvdata(rdev);
 282        enum lp8788_buck_id id = rdev_get_id(rdev);
 283        int ret;
 284        u8 val, addr;
 285
 286        addr = lp8788_select_buck_vout_addr(buck, id);
 287        if (!lp8788_is_valid_buck_addr(addr))
 288                return -EINVAL;
 289
 290        ret = lp8788_read_byte(buck->lp, addr, &val);
 291        if (ret)
 292                return ret;
 293
 294        return val & LP8788_VOUT_M;
 295}
 296
 297static int lp8788_buck_enable_time(struct regulator_dev *rdev)
 298{
 299        struct lp8788_buck *buck = rdev_get_drvdata(rdev);
 300        enum lp8788_buck_id id = rdev_get_id(rdev);
 301        u8 val, addr = LP8788_BUCK1_TIMESTEP + id;
 302
 303        if (lp8788_read_byte(buck->lp, addr, &val))
 304                return -EINVAL;
 305
 306        val = (val & LP8788_STARTUP_TIME_M) >> LP8788_STARTUP_TIME_S;
 307
 308        return ENABLE_TIME_USEC * val;
 309}
 310
 311static int lp8788_buck_set_mode(struct regulator_dev *rdev, unsigned int mode)
 312{
 313        struct lp8788_buck *buck = rdev_get_drvdata(rdev);
 314        enum lp8788_buck_id id = rdev_get_id(rdev);
 315        u8 mask, val;
 316
 317        mask = BUCK_FPWM_MASK(id);
 318        switch (mode) {
 319        case REGULATOR_MODE_FAST:
 320                val = LP8788_FORCE_PWM << BUCK_FPWM_SHIFT(id);
 321                break;
 322        case REGULATOR_MODE_NORMAL:
 323                val = LP8788_AUTO_PWM << BUCK_FPWM_SHIFT(id);
 324                break;
 325        default:
 326                return -EINVAL;
 327        }
 328
 329        return lp8788_update_bits(buck->lp, LP8788_BUCK_PWM, mask, val);
 330}
 331
 332static unsigned int lp8788_buck_get_mode(struct regulator_dev *rdev)
 333{
 334        struct lp8788_buck *buck = rdev_get_drvdata(rdev);
 335        enum lp8788_buck_id id = rdev_get_id(rdev);
 336        u8 val;
 337        int ret;
 338
 339        ret = lp8788_read_byte(buck->lp, LP8788_BUCK_PWM, &val);
 340        if (ret)
 341                return ret;
 342
 343        return val & BUCK_FPWM_MASK(id) ?
 344                                REGULATOR_MODE_FAST : REGULATOR_MODE_NORMAL;
 345}
 346
 347static struct regulator_ops lp8788_buck12_ops = {
 348        .list_voltage = regulator_list_voltage_table,
 349        .set_voltage_sel = lp8788_buck12_set_voltage_sel,
 350        .get_voltage_sel = lp8788_buck12_get_voltage_sel,
 351        .enable = regulator_enable_regmap,
 352        .disable = regulator_disable_regmap,
 353        .is_enabled = regulator_is_enabled_regmap,
 354        .enable_time = lp8788_buck_enable_time,
 355        .set_mode = lp8788_buck_set_mode,
 356        .get_mode = lp8788_buck_get_mode,
 357};
 358
 359static struct regulator_ops lp8788_buck34_ops = {
 360        .list_voltage = regulator_list_voltage_table,
 361        .set_voltage_sel = regulator_set_voltage_sel_regmap,
 362        .get_voltage_sel = regulator_get_voltage_sel_regmap,
 363        .enable = regulator_enable_regmap,
 364        .disable = regulator_disable_regmap,
 365        .is_enabled = regulator_is_enabled_regmap,
 366        .enable_time = lp8788_buck_enable_time,
 367        .set_mode = lp8788_buck_set_mode,
 368        .get_mode = lp8788_buck_get_mode,
 369};
 370
 371static struct regulator_desc lp8788_buck_desc[] = {
 372        {
 373                .name = "buck1",
 374                .id = BUCK1,
 375                .ops = &lp8788_buck12_ops,
 376                .n_voltages = ARRAY_SIZE(lp8788_buck_vtbl),
 377                .volt_table = lp8788_buck_vtbl,
 378                .type = REGULATOR_VOLTAGE,
 379                .owner = THIS_MODULE,
 380                .enable_reg = LP8788_EN_BUCK,
 381                .enable_mask = LP8788_EN_BUCK1_M,
 382        },
 383        {
 384                .name = "buck2",
 385                .id = BUCK2,
 386                .ops = &lp8788_buck12_ops,
 387                .n_voltages = ARRAY_SIZE(lp8788_buck_vtbl),
 388                .volt_table = lp8788_buck_vtbl,
 389                .type = REGULATOR_VOLTAGE,
 390                .owner = THIS_MODULE,
 391                .enable_reg = LP8788_EN_BUCK,
 392                .enable_mask = LP8788_EN_BUCK2_M,
 393        },
 394        {
 395                .name = "buck3",
 396                .id = BUCK3,
 397                .ops = &lp8788_buck34_ops,
 398                .n_voltages = ARRAY_SIZE(lp8788_buck_vtbl),
 399                .volt_table = lp8788_buck_vtbl,
 400                .type = REGULATOR_VOLTAGE,
 401                .owner = THIS_MODULE,
 402                .vsel_reg = LP8788_BUCK3_VOUT,
 403                .vsel_mask = LP8788_VOUT_M,
 404                .enable_reg = LP8788_EN_BUCK,
 405                .enable_mask = LP8788_EN_BUCK3_M,
 406        },
 407        {
 408                .name = "buck4",
 409                .id = BUCK4,
 410                .ops = &lp8788_buck34_ops,
 411                .n_voltages = ARRAY_SIZE(lp8788_buck_vtbl),
 412                .volt_table = lp8788_buck_vtbl,
 413                .type = REGULATOR_VOLTAGE,
 414                .owner = THIS_MODULE,
 415                .vsel_reg = LP8788_BUCK4_VOUT,
 416                .vsel_mask = LP8788_VOUT_M,
 417                .enable_reg = LP8788_EN_BUCK,
 418                .enable_mask = LP8788_EN_BUCK4_M,
 419        },
 420};
 421
 422static int lp8788_dvs_gpio_request(struct platform_device *pdev,
 423                                struct lp8788_buck *buck,
 424                                enum lp8788_buck_id id)
 425{
 426        struct lp8788_platform_data *pdata = buck->lp->pdata;
 427        char *b1_name = "LP8788_B1_DVS";
 428        char *b2_name[] = { "LP8788_B2_DVS1", "LP8788_B2_DVS2" };
 429        int i, gpio, ret;
 430
 431        switch (id) {
 432        case BUCK1:
 433                gpio = pdata->buck1_dvs->gpio;
 434                ret = devm_gpio_request_one(&pdev->dev, gpio, DVS_LOW,
 435                                            b1_name);
 436                if (ret)
 437                        return ret;
 438
 439                buck->dvs = pdata->buck1_dvs;
 440                break;
 441        case BUCK2:
 442                for (i = 0; i < LP8788_NUM_BUCK2_DVS; i++) {
 443                        gpio = pdata->buck2_dvs->gpio[i];
 444                        ret = devm_gpio_request_one(&pdev->dev, gpio,
 445                                                    DVS_LOW, b2_name[i]);
 446                        if (ret)
 447                                return ret;
 448                }
 449                buck->dvs = pdata->buck2_dvs;
 450                break;
 451        default:
 452                break;
 453        }
 454
 455        return 0;
 456}
 457
 458static int lp8788_init_dvs(struct platform_device *pdev,
 459                        struct lp8788_buck *buck, enum lp8788_buck_id id)
 460{
 461        struct lp8788_platform_data *pdata = buck->lp->pdata;
 462        u8 mask[] = { LP8788_BUCK1_DVS_SEL_M, LP8788_BUCK2_DVS_SEL_M };
 463        u8 val[]  = { LP8788_BUCK1_DVS_PIN, LP8788_BUCK2_DVS_PIN };
 464        u8 default_dvs_mode[] = { LP8788_BUCK1_DVS_I2C, LP8788_BUCK2_DVS_I2C };
 465
 466        /* no dvs for buck3, 4 */
 467        if (id > BUCK2)
 468                return 0;
 469
 470        /* no dvs platform data, then dvs will be selected by I2C registers */
 471        if (!pdata)
 472                goto set_default_dvs_mode;
 473
 474        if ((id == BUCK1 && !pdata->buck1_dvs) ||
 475                (id == BUCK2 && !pdata->buck2_dvs))
 476                goto set_default_dvs_mode;
 477
 478        if (lp8788_dvs_gpio_request(pdev, buck, id))
 479                goto set_default_dvs_mode;
 480
 481        return lp8788_update_bits(buck->lp, LP8788_BUCK_DVS_SEL, mask[id],
 482                                val[id]);
 483
 484set_default_dvs_mode:
 485        return lp8788_update_bits(buck->lp, LP8788_BUCK_DVS_SEL, mask[id],
 486                                  default_dvs_mode[id]);
 487}
 488
 489static int lp8788_buck_probe(struct platform_device *pdev)
 490{
 491        struct lp8788 *lp = dev_get_drvdata(pdev->dev.parent);
 492        int id = pdev->id;
 493        struct lp8788_buck *buck;
 494        struct regulator_config cfg = { };
 495        struct regulator_dev *rdev;
 496        int ret;
 497
 498        if (id >= LP8788_NUM_BUCKS)
 499                return -EINVAL;
 500
 501        buck = devm_kzalloc(&pdev->dev, sizeof(struct lp8788_buck), GFP_KERNEL);
 502        if (!buck)
 503                return -ENOMEM;
 504
 505        buck->lp = lp;
 506
 507        ret = lp8788_init_dvs(pdev, buck, id);
 508        if (ret)
 509                return ret;
 510
 511        cfg.dev = pdev->dev.parent;
 512        cfg.init_data = lp->pdata ? lp->pdata->buck_data[id] : NULL;
 513        cfg.driver_data = buck;
 514        cfg.regmap = lp->regmap;
 515
 516        rdev = regulator_register(&lp8788_buck_desc[id], &cfg);
 517        if (IS_ERR(rdev)) {
 518                ret = PTR_ERR(rdev);
 519                dev_err(&pdev->dev, "BUCK%d regulator register err = %d\n",
 520                                id + 1, ret);
 521                return ret;
 522        }
 523
 524        buck->regulator = rdev;
 525        platform_set_drvdata(pdev, buck);
 526
 527        return 0;
 528}
 529
 530static int lp8788_buck_remove(struct platform_device *pdev)
 531{
 532        struct lp8788_buck *buck = platform_get_drvdata(pdev);
 533
 534        platform_set_drvdata(pdev, NULL);
 535        regulator_unregister(buck->regulator);
 536
 537        return 0;
 538}
 539
 540static struct platform_driver lp8788_buck_driver = {
 541        .probe = lp8788_buck_probe,
 542        .remove = lp8788_buck_remove,
 543        .driver = {
 544                .name = LP8788_DEV_BUCK,
 545                .owner = THIS_MODULE,
 546        },
 547};
 548
 549static int __init lp8788_buck_init(void)
 550{
 551        return platform_driver_register(&lp8788_buck_driver);
 552}
 553subsys_initcall(lp8788_buck_init);
 554
 555static void __exit lp8788_buck_exit(void)
 556{
 557        platform_driver_unregister(&lp8788_buck_driver);
 558}
 559module_exit(lp8788_buck_exit);
 560
 561MODULE_DESCRIPTION("TI LP8788 BUCK Driver");
 562MODULE_AUTHOR("Milo Kim");
 563MODULE_LICENSE("GPL");
 564MODULE_ALIAS("platform:lp8788-buck");
 565
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.