linux/drivers/regulator/fan53555.c
<<
>>
Prefs
   1/*
   2 * FAN53555 Fairchild Digitally Programmable TinyBuck Regulator Driver.
   3 *
   4 * Supported Part Numbers:
   5 * FAN53555UC00X/01X/03X/04X/05X
   6 *
   7 * Copyright (c) 2012 Marvell Technology Ltd.
   8 * Yunfan Zhang <yfzhang@marvell.com>
   9 *
  10 * This package is free software; you can redistribute it and/or modify
  11 * it under the terms of the GNU General Public License version 2 as
  12 * published by the Free Software Foundation.
  13 *
  14 */
  15#include <linux/module.h>
  16#include <linux/param.h>
  17#include <linux/err.h>
  18#include <linux/platform_device.h>
  19#include <linux/regulator/driver.h>
  20#include <linux/regulator/machine.h>
  21#include <linux/regulator/of_regulator.h>
  22#include <linux/of_device.h>
  23#include <linux/i2c.h>
  24#include <linux/slab.h>
  25#include <linux/regmap.h>
  26#include <linux/regulator/fan53555.h>
  27
  28/* Voltage setting */
  29#define FAN53555_VSEL0          0x00
  30#define FAN53555_VSEL1          0x01
  31/* Control register */
  32#define FAN53555_CONTROL        0x02
  33/* IC Type */
  34#define FAN53555_ID1            0x03
  35/* IC mask version */
  36#define FAN53555_ID2            0x04
  37/* Monitor register */
  38#define FAN53555_MONITOR        0x05
  39
  40/* VSEL bit definitions */
  41#define VSEL_BUCK_EN    (1 << 7)
  42#define VSEL_MODE               (1 << 6)
  43#define VSEL_NSEL_MASK  0x3F
  44/* Chip ID and Verison */
  45#define DIE_ID          0x0F    /* ID1 */
  46#define DIE_REV         0x0F    /* ID2 */
  47/* Control bit definitions */
  48#define CTL_OUTPUT_DISCHG       (1 << 7)
  49#define CTL_SLEW_MASK           (0x7 << 4)
  50#define CTL_SLEW_SHIFT          4
  51#define CTL_RESET                       (1 << 2)
  52
  53#define FAN53555_NVOLTAGES      64      /* Numbers of voltages */
  54
  55enum fan53555_vendor {
  56        FAN53555_VENDOR_FAIRCHILD = 0,
  57        FAN53555_VENDOR_SILERGY,
  58};
  59
  60/* IC Type */
  61enum {
  62        FAN53555_CHIP_ID_00 = 0,
  63        FAN53555_CHIP_ID_01,
  64        FAN53555_CHIP_ID_02,
  65        FAN53555_CHIP_ID_03,
  66        FAN53555_CHIP_ID_04,
  67        FAN53555_CHIP_ID_05,
  68        FAN53555_CHIP_ID_08 = 8,
  69};
  70
  71/* IC mask revision */
  72enum {
  73        FAN53555_CHIP_REV_00 = 0x3,
  74        FAN53555_CHIP_REV_13 = 0xf,
  75};
  76
  77enum {
  78        SILERGY_SYR82X = 8,
  79};
  80
  81struct fan53555_device_info {
  82        enum fan53555_vendor vendor;
  83        struct regmap *regmap;
  84        struct device *dev;
  85        struct regulator_desc desc;
  86        struct regulator_dev *rdev;
  87        struct regulator_init_data *regulator;
  88        /* IC Type and Rev */
  89        int chip_id;
  90        int chip_rev;
  91        /* Voltage setting register */
  92        unsigned int vol_reg;
  93        unsigned int sleep_reg;
  94        /* Voltage range and step(linear) */
  95        unsigned int vsel_min;
  96        unsigned int vsel_step;
  97        /* Voltage slew rate limiting */
  98        unsigned int slew_rate;
  99        /* Sleep voltage cache */
 100        unsigned int sleep_vol_cache;
 101};
 102
 103static int fan53555_set_suspend_voltage(struct regulator_dev *rdev, int uV)
 104{
 105        struct fan53555_device_info *di = rdev_get_drvdata(rdev);
 106        int ret;
 107
 108        if (di->sleep_vol_cache == uV)
 109                return 0;
 110        ret = regulator_map_voltage_linear(rdev, uV, uV);
 111        if (ret < 0)
 112                return ret;
 113        ret = regmap_update_bits(di->regmap, di->sleep_reg,
 114                                        VSEL_NSEL_MASK, ret);
 115        if (ret < 0)
 116                return ret;
 117        /* Cache the sleep voltage setting.
 118         * Might not be the real voltage which is rounded */
 119        di->sleep_vol_cache = uV;
 120
 121        return 0;
 122}
 123
 124static int fan53555_set_suspend_enable(struct regulator_dev *rdev)
 125{
 126        struct fan53555_device_info *di = rdev_get_drvdata(rdev);
 127
 128        return regmap_update_bits(di->regmap, di->sleep_reg,
 129                                  VSEL_BUCK_EN, VSEL_BUCK_EN);
 130}
 131
 132static int fan53555_set_suspend_disable(struct regulator_dev *rdev)
 133{
 134        struct fan53555_device_info *di = rdev_get_drvdata(rdev);
 135
 136        return regmap_update_bits(di->regmap, di->sleep_reg,
 137                                  VSEL_BUCK_EN, 0);
 138}
 139
 140static int fan53555_set_mode(struct regulator_dev *rdev, unsigned int mode)
 141{
 142        struct fan53555_device_info *di = rdev_get_drvdata(rdev);
 143
 144        switch (mode) {
 145        case REGULATOR_MODE_FAST:
 146                regmap_update_bits(di->regmap, di->vol_reg,
 147                                VSEL_MODE, VSEL_MODE);
 148                break;
 149        case REGULATOR_MODE_NORMAL:
 150                regmap_update_bits(di->regmap, di->vol_reg, VSEL_MODE, 0);
 151                break;
 152        default:
 153                return -EINVAL;
 154        }
 155        return 0;
 156}
 157
 158static unsigned int fan53555_get_mode(struct regulator_dev *rdev)
 159{
 160        struct fan53555_device_info *di = rdev_get_drvdata(rdev);
 161        unsigned int val;
 162        int ret = 0;
 163
 164        ret = regmap_read(di->regmap, di->vol_reg, &val);
 165        if (ret < 0)
 166                return ret;
 167        if (val & VSEL_MODE)
 168                return REGULATOR_MODE_FAST;
 169        else
 170                return REGULATOR_MODE_NORMAL;
 171}
 172
 173static const int slew_rates[] = {
 174        64000,
 175        32000,
 176        16000,
 177         8000,
 178         4000,
 179         2000,
 180         1000,
 181          500,
 182};
 183
 184static int fan53555_set_ramp(struct regulator_dev *rdev, int ramp)
 185{
 186        struct fan53555_device_info *di = rdev_get_drvdata(rdev);
 187        int regval = -1, i;
 188
 189        for (i = 0; i < ARRAY_SIZE(slew_rates); i++) {
 190                if (ramp <= slew_rates[i])
 191                        regval = i;
 192                else
 193                        break;
 194        }
 195
 196        if (regval < 0) {
 197                dev_err(di->dev, "unsupported ramp value %d\n", ramp);
 198                return -EINVAL;
 199        }
 200
 201        return regmap_update_bits(di->regmap, FAN53555_CONTROL,
 202                                  CTL_SLEW_MASK, regval << CTL_SLEW_SHIFT);
 203}
 204
 205static const struct regulator_ops fan53555_regulator_ops = {
 206        .set_voltage_sel = regulator_set_voltage_sel_regmap,
 207        .get_voltage_sel = regulator_get_voltage_sel_regmap,
 208        .set_voltage_time_sel = regulator_set_voltage_time_sel,
 209        .map_voltage = regulator_map_voltage_linear,
 210        .list_voltage = regulator_list_voltage_linear,
 211        .set_suspend_voltage = fan53555_set_suspend_voltage,
 212        .enable = regulator_enable_regmap,
 213        .disable = regulator_disable_regmap,
 214        .is_enabled = regulator_is_enabled_regmap,
 215        .set_mode = fan53555_set_mode,
 216        .get_mode = fan53555_get_mode,
 217        .set_ramp_delay = fan53555_set_ramp,
 218        .set_suspend_enable = fan53555_set_suspend_enable,
 219        .set_suspend_disable = fan53555_set_suspend_disable,
 220};
 221
 222static int fan53555_voltages_setup_fairchild(struct fan53555_device_info *di)
 223{
 224        /* Init voltage range and step */
 225        switch (di->chip_id) {
 226        case FAN53555_CHIP_ID_00:
 227                switch (di->chip_rev) {
 228                case FAN53555_CHIP_REV_00:
 229                        di->vsel_min = 600000;
 230                        di->vsel_step = 10000;
 231                        break;
 232                case FAN53555_CHIP_REV_13:
 233                        di->vsel_min = 800000;
 234                        di->vsel_step = 10000;
 235                        break;
 236                default:
 237                        dev_err(di->dev,
 238                                "Chip ID %d with rev %d not supported!\n",
 239                                di->chip_id, di->chip_rev);
 240                        return -EINVAL;
 241                }
 242                break;
 243        case FAN53555_CHIP_ID_01:
 244        case FAN53555_CHIP_ID_03:
 245        case FAN53555_CHIP_ID_05:
 246        case FAN53555_CHIP_ID_08:
 247                di->vsel_min = 600000;
 248                di->vsel_step = 10000;
 249                break;
 250        case FAN53555_CHIP_ID_04:
 251                di->vsel_min = 603000;
 252                di->vsel_step = 12826;
 253                break;
 254        default:
 255                dev_err(di->dev,
 256                        "Chip ID %d not supported!\n", di->chip_id);
 257                return -EINVAL;
 258        }
 259
 260        return 0;
 261}
 262
 263static int fan53555_voltages_setup_silergy(struct fan53555_device_info *di)
 264{
 265        /* Init voltage range and step */
 266        switch (di->chip_id) {
 267        case SILERGY_SYR82X:
 268                di->vsel_min = 712500;
 269                di->vsel_step = 12500;
 270                break;
 271        default:
 272                dev_err(di->dev,
 273                        "Chip ID %d not supported!\n", di->chip_id);
 274                return -EINVAL;
 275        }
 276
 277        return 0;
 278}
 279
 280/* For 00,01,03,05 options:
 281 * VOUT = 0.60V + NSELx * 10mV, from 0.60 to 1.23V.
 282 * For 04 option:
 283 * VOUT = 0.603V + NSELx * 12.826mV, from 0.603 to 1.411V.
 284 * */
 285static int fan53555_device_setup(struct fan53555_device_info *di,
 286                                struct fan53555_platform_data *pdata)
 287{
 288        int ret = 0;
 289
 290        /* Setup voltage control register */
 291        switch (pdata->sleep_vsel_id) {
 292        case FAN53555_VSEL_ID_0:
 293                di->sleep_reg = FAN53555_VSEL0;
 294                di->vol_reg = FAN53555_VSEL1;
 295                break;
 296        case FAN53555_VSEL_ID_1:
 297                di->sleep_reg = FAN53555_VSEL1;
 298                di->vol_reg = FAN53555_VSEL0;
 299                break;
 300        default:
 301                dev_err(di->dev, "Invalid VSEL ID!\n");
 302                return -EINVAL;
 303        }
 304
 305        switch (di->vendor) {
 306        case FAN53555_VENDOR_FAIRCHILD:
 307                ret = fan53555_voltages_setup_fairchild(di);
 308                break;
 309        case FAN53555_VENDOR_SILERGY:
 310                ret = fan53555_voltages_setup_silergy(di);
 311                break;
 312        default:
 313                dev_err(di->dev, "vendor %d not supported!\n", di->vendor);
 314                return -EINVAL;
 315        }
 316
 317        return ret;
 318}
 319
 320static int fan53555_regulator_register(struct fan53555_device_info *di,
 321                        struct regulator_config *config)
 322{
 323        struct regulator_desc *rdesc = &di->desc;
 324
 325        rdesc->name = "fan53555-reg";
 326        rdesc->supply_name = "vin";
 327        rdesc->ops = &fan53555_regulator_ops;
 328        rdesc->type = REGULATOR_VOLTAGE;
 329        rdesc->n_voltages = FAN53555_NVOLTAGES;
 330        rdesc->enable_reg = di->vol_reg;
 331        rdesc->enable_mask = VSEL_BUCK_EN;
 332        rdesc->min_uV = di->vsel_min;
 333        rdesc->uV_step = di->vsel_step;
 334        rdesc->vsel_reg = di->vol_reg;
 335        rdesc->vsel_mask = VSEL_NSEL_MASK;
 336        rdesc->owner = THIS_MODULE;
 337
 338        di->rdev = devm_regulator_register(di->dev, &di->desc, config);
 339        return PTR_ERR_OR_ZERO(di->rdev);
 340}
 341
 342static const struct regmap_config fan53555_regmap_config = {
 343        .reg_bits = 8,
 344        .val_bits = 8,
 345};
 346
 347static struct fan53555_platform_data *fan53555_parse_dt(struct device *dev,
 348                                              struct device_node *np,
 349                                              const struct regulator_desc *desc)
 350{
 351        struct fan53555_platform_data *pdata;
 352        int ret;
 353        u32 tmp;
 354
 355        pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
 356        if (!pdata)
 357                return NULL;
 358
 359        pdata->regulator = of_get_regulator_init_data(dev, np, desc);
 360
 361        ret = of_property_read_u32(np, "fcs,suspend-voltage-selector",
 362                                   &tmp);
 363        if (!ret)
 364                pdata->sleep_vsel_id = tmp;
 365
 366        return pdata;
 367}
 368
 369static const struct of_device_id fan53555_dt_ids[] = {
 370        {
 371                .compatible = "fcs,fan53555",
 372                .data = (void *)FAN53555_VENDOR_FAIRCHILD
 373        }, {
 374                .compatible = "silergy,syr827",
 375                .data = (void *)FAN53555_VENDOR_SILERGY,
 376        }, {
 377                .compatible = "silergy,syr828",
 378                .data = (void *)FAN53555_VENDOR_SILERGY,
 379        },
 380        { }
 381};
 382MODULE_DEVICE_TABLE(of, fan53555_dt_ids);
 383
 384static int fan53555_regulator_probe(struct i2c_client *client,
 385                                const struct i2c_device_id *id)
 386{
 387        struct device_node *np = client->dev.of_node;
 388        struct fan53555_device_info *di;
 389        struct fan53555_platform_data *pdata;
 390        struct regulator_config config = { };
 391        unsigned int val;
 392        int ret;
 393
 394        di = devm_kzalloc(&client->dev, sizeof(struct fan53555_device_info),
 395                                        GFP_KERNEL);
 396        if (!di)
 397                return -ENOMEM;
 398
 399        pdata = dev_get_platdata(&client->dev);
 400        if (!pdata)
 401                pdata = fan53555_parse_dt(&client->dev, np, &di->desc);
 402
 403        if (!pdata || !pdata->regulator) {
 404                dev_err(&client->dev, "Platform data not found!\n");
 405                return -ENODEV;
 406        }
 407
 408        di->regulator = pdata->regulator;
 409        if (client->dev.of_node) {
 410                di->vendor =
 411                        (unsigned long)of_device_get_match_data(&client->dev);
 412        } else {
 413                /* if no ramp constraint set, get the pdata ramp_delay */
 414                if (!di->regulator->constraints.ramp_delay) {
 415                        int slew_idx = (pdata->slew_rate & 0x7)
 416                                                ? pdata->slew_rate : 0;
 417
 418                        di->regulator->constraints.ramp_delay
 419                                                = slew_rates[slew_idx];
 420                }
 421
 422                di->vendor = id->driver_data;
 423        }
 424
 425        di->regmap = devm_regmap_init_i2c(client, &fan53555_regmap_config);
 426        if (IS_ERR(di->regmap)) {
 427                dev_err(&client->dev, "Failed to allocate regmap!\n");
 428                return PTR_ERR(di->regmap);
 429        }
 430        di->dev = &client->dev;
 431        i2c_set_clientdata(client, di);
 432        /* Get chip ID */
 433        ret = regmap_read(di->regmap, FAN53555_ID1, &val);
 434        if (ret < 0) {
 435                dev_err(&client->dev, "Failed to get chip ID!\n");
 436                return ret;
 437        }
 438        di->chip_id = val & DIE_ID;
 439        /* Get chip revision */
 440        ret = regmap_read(di->regmap, FAN53555_ID2, &val);
 441        if (ret < 0) {
 442                dev_err(&client->dev, "Failed to get chip Rev!\n");
 443                return ret;
 444        }
 445        di->chip_rev = val & DIE_REV;
 446        dev_info(&client->dev, "FAN53555 Option[%d] Rev[%d] Detected!\n",
 447                                di->chip_id, di->chip_rev);
 448        /* Device init */
 449        ret = fan53555_device_setup(di, pdata);
 450        if (ret < 0) {
 451                dev_err(&client->dev, "Failed to setup device!\n");
 452                return ret;
 453        }
 454        /* Register regulator */
 455        config.dev = di->dev;
 456        config.init_data = di->regulator;
 457        config.regmap = di->regmap;
 458        config.driver_data = di;
 459        config.of_node = np;
 460
 461        ret = fan53555_regulator_register(di, &config);
 462        if (ret < 0)
 463                dev_err(&client->dev, "Failed to register regulator!\n");
 464        return ret;
 465
 466}
 467
 468static const struct i2c_device_id fan53555_id[] = {
 469        {
 470                .name = "fan53555",
 471                .driver_data = FAN53555_VENDOR_FAIRCHILD
 472        }, {
 473                .name = "syr827",
 474                .driver_data = FAN53555_VENDOR_SILERGY
 475        }, {
 476                .name = "syr828",
 477                .driver_data = FAN53555_VENDOR_SILERGY
 478        },
 479        { },
 480};
 481MODULE_DEVICE_TABLE(i2c, fan53555_id);
 482
 483static struct i2c_driver fan53555_regulator_driver = {
 484        .driver = {
 485                .name = "fan53555-regulator",
 486                .of_match_table = of_match_ptr(fan53555_dt_ids),
 487        },
 488        .probe = fan53555_regulator_probe,
 489        .id_table = fan53555_id,
 490};
 491
 492module_i2c_driver(fan53555_regulator_driver);
 493
 494MODULE_AUTHOR("Yunfan Zhang <yfzhang@marvell.com>");
 495MODULE_DESCRIPTION("FAN53555 regulator driver");
 496MODULE_LICENSE("GPL v2");
 497