linux/drivers/regulator/rtmv20-regulator.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2
   3#include <linux/delay.h>
   4#include <linux/gpio/consumer.h>
   5#include <linux/i2c.h>
   6#include <linux/interrupt.h>
   7#include <linux/kernel.h>
   8#include <linux/module.h>
   9#include <linux/property.h>
  10#include <linux/regmap.h>
  11#include <linux/regulator/driver.h>
  12
  13#define RTMV20_REG_DEVINFO      0x00
  14#define RTMV20_REG_PULSEDELAY   0x01
  15#define RTMV20_REG_PULSEWIDTH   0x03
  16#define RTMV20_REG_LDCTRL1      0x05
  17#define RTMV20_REG_ESPULSEWIDTH 0x06
  18#define RTMV20_REG_ESLDCTRL1    0x08
  19#define RTMV20_REG_LBP          0x0A
  20#define RTMV20_REG_LDCTRL2      0x0B
  21#define RTMV20_REG_FSIN1CTRL1   0x0D
  22#define RTMV20_REG_FSIN1CTRL3   0x0F
  23#define RTMV20_REG_FSIN2CTRL1   0x10
  24#define RTMV20_REG_FSIN2CTRL3   0x12
  25#define RTMV20_REG_ENCTRL       0x13
  26#define RTMV20_REG_STRBVSYNDLYL 0x29
  27#define RTMV20_REG_LDIRQ        0x30
  28#define RTMV20_REG_LDSTAT       0x40
  29#define RTMV20_REG_LDMASK       0x50
  30#define RTMV20_MAX_REGS         (RTMV20_REG_LDMASK + 1)
  31
  32#define RTMV20_VID_MASK         GENMASK(7, 4)
  33#define RICHTEK_VID             0x80
  34#define RTMV20_LDCURR_MASK      GENMASK(7, 0)
  35#define RTMV20_DELAY_MASK       GENMASK(9, 0)
  36#define RTMV20_WIDTH_MASK       GENMASK(13, 0)
  37#define RTMV20_WIDTH2_MASK      GENMASK(7, 0)
  38#define RTMV20_LBPLVL_MASK      GENMASK(3, 0)
  39#define RTMV20_LBPEN_MASK       BIT(7)
  40#define RTMV20_STROBEPOL_MASK   BIT(0)
  41#define RTMV20_VSYNPOL_MASK     BIT(1)
  42#define RTMV20_FSINEN_MASK      BIT(7)
  43#define RTMV20_ESEN_MASK        BIT(6)
  44#define RTMV20_FSINOUT_MASK     BIT(2)
  45#define LDENABLE_MASK           (BIT(3) | BIT(0))
  46
  47#define OTPEVT_MASK             BIT(4)
  48#define SHORTEVT_MASK           BIT(3)
  49#define OPENEVT_MASK            BIT(2)
  50#define LBPEVT_MASK             BIT(1)
  51#define OCPEVT_MASK             BIT(0)
  52#define FAILEVT_MASK            (SHORTEVT_MASK | OPENEVT_MASK | LBPEVT_MASK)
  53
  54#define RTMV20_LSW_MINUA        0
  55#define RTMV20_LSW_MAXUA        6000000
  56#define RTMV20_LSW_STEPUA       30000
  57
  58#define RTMV20_LSW_DEFAULTUA    3000000
  59
  60#define RTMV20_I2CRDY_TIMEUS    200
  61#define RTMV20_CSRDY_TIMEUS     2000
  62
  63struct rtmv20_priv {
  64        struct device *dev;
  65        struct regmap *regmap;
  66        struct gpio_desc *enable_gpio;
  67        struct regulator_dev *rdev;
  68};
  69
  70static int rtmv20_lsw_enable(struct regulator_dev *rdev)
  71{
  72        struct rtmv20_priv *priv = rdev_get_drvdata(rdev);
  73        int ret;
  74
  75        gpiod_set_value(priv->enable_gpio, 1);
  76
  77        /* Wait for I2C can be accessed */
  78        usleep_range(RTMV20_I2CRDY_TIMEUS, RTMV20_I2CRDY_TIMEUS + 100);
  79
  80        /* HW re-enable, disable cache only and sync regcache here */
  81        regcache_cache_only(priv->regmap, false);
  82        ret = regcache_sync(priv->regmap);
  83        if (ret)
  84                return ret;
  85
  86        return regulator_enable_regmap(rdev);
  87}
  88
  89static int rtmv20_lsw_disable(struct regulator_dev *rdev)
  90{
  91        struct rtmv20_priv *priv = rdev_get_drvdata(rdev);
  92        int ret;
  93
  94        ret = regulator_disable_regmap(rdev);
  95        if (ret)
  96                return ret;
  97
  98        /* Mark the regcache as dirty and cache only before HW disabled */
  99        regcache_cache_only(priv->regmap, true);
 100        regcache_mark_dirty(priv->regmap);
 101
 102        gpiod_set_value(priv->enable_gpio, 0);
 103
 104        return 0;
 105}
 106
 107static int rtmv20_lsw_set_current_limit(struct regulator_dev *rdev, int min_uA,
 108                                        int max_uA)
 109{
 110        int sel;
 111
 112        if (min_uA > RTMV20_LSW_MAXUA || max_uA < RTMV20_LSW_MINUA)
 113                return -EINVAL;
 114
 115        if (max_uA > RTMV20_LSW_MAXUA)
 116                max_uA = RTMV20_LSW_MAXUA;
 117
 118        sel = (max_uA - RTMV20_LSW_MINUA) / RTMV20_LSW_STEPUA;
 119
 120        /* Ensure the selected setting is still in range */
 121        if ((sel * RTMV20_LSW_STEPUA + RTMV20_LSW_MINUA) < min_uA)
 122                return -EINVAL;
 123
 124        sel <<= ffs(rdev->desc->csel_mask) - 1;
 125
 126        return regmap_update_bits(rdev->regmap, rdev->desc->csel_reg,
 127                                  rdev->desc->csel_mask, sel);
 128}
 129
 130static int rtmv20_lsw_get_current_limit(struct regulator_dev *rdev)
 131{
 132        unsigned int val;
 133        int ret;
 134
 135        ret = regmap_read(rdev->regmap, rdev->desc->csel_reg, &val);
 136        if (ret)
 137                return ret;
 138
 139        val &= rdev->desc->csel_mask;
 140        val >>= ffs(rdev->desc->csel_mask) - 1;
 141
 142        return val * RTMV20_LSW_STEPUA + RTMV20_LSW_MINUA;
 143}
 144
 145static const struct regulator_ops rtmv20_regulator_ops = {
 146        .set_current_limit = rtmv20_lsw_set_current_limit,
 147        .get_current_limit = rtmv20_lsw_get_current_limit,
 148        .enable = rtmv20_lsw_enable,
 149        .disable = rtmv20_lsw_disable,
 150        .is_enabled = regulator_is_enabled_regmap,
 151};
 152
 153static const struct regulator_desc rtmv20_lsw_desc = {
 154        .name = "rtmv20,lsw",
 155        .of_match = of_match_ptr("lsw"),
 156        .type = REGULATOR_CURRENT,
 157        .owner = THIS_MODULE,
 158        .ops = &rtmv20_regulator_ops,
 159        .csel_reg = RTMV20_REG_LDCTRL1,
 160        .csel_mask = RTMV20_LDCURR_MASK,
 161        .enable_reg = RTMV20_REG_ENCTRL,
 162        .enable_mask = LDENABLE_MASK,
 163        .enable_time = RTMV20_CSRDY_TIMEUS,
 164};
 165
 166static irqreturn_t rtmv20_irq_handler(int irq, void *data)
 167{
 168        struct rtmv20_priv *priv = data;
 169        unsigned int val;
 170        int ret;
 171
 172        ret = regmap_read(priv->regmap, RTMV20_REG_LDIRQ, &val);
 173        if (ret) {
 174                dev_err(priv->dev, "Failed to get irq flags\n");
 175                return IRQ_NONE;
 176        }
 177
 178        if (val & OTPEVT_MASK)
 179                regulator_notifier_call_chain(priv->rdev, REGULATOR_EVENT_OVER_TEMP, NULL);
 180
 181        if (val & OCPEVT_MASK)
 182                regulator_notifier_call_chain(priv->rdev, REGULATOR_EVENT_OVER_CURRENT, NULL);
 183
 184        if (val & FAILEVT_MASK)
 185                regulator_notifier_call_chain(priv->rdev, REGULATOR_EVENT_FAIL, NULL);
 186
 187        return IRQ_HANDLED;
 188}
 189
 190static u32 clamp_to_selector(u32 val, u32 min, u32 max, u32 step)
 191{
 192        u32 retval = clamp_val(val, min, max);
 193
 194        return (retval - min) / step;
 195}
 196
 197static int rtmv20_properties_init(struct rtmv20_priv *priv)
 198{
 199        const struct {
 200                const char *name;
 201                u32 def;
 202                u32 min;
 203                u32 max;
 204                u32 step;
 205                u32 addr;
 206                u32 mask;
 207        } props[] = {
 208                { "richtek,ld-pulse-delay-us", 0, 0, 100000, 100, RTMV20_REG_PULSEDELAY,
 209                        RTMV20_DELAY_MASK },
 210                { "richtek,ld-pulse-width-us", 1200, 0, 10000, 1, RTMV20_REG_PULSEWIDTH,
 211                        RTMV20_WIDTH_MASK },
 212                { "richtek,fsin1-delay-us", 23000, 0, 100000, 100, RTMV20_REG_FSIN1CTRL1,
 213                        RTMV20_DELAY_MASK },
 214                { "richtek,fsin1-width-us", 160, 40, 10000, 40, RTMV20_REG_FSIN1CTRL3,
 215                        RTMV20_WIDTH2_MASK },
 216                { "richtek,fsin2-delay-us", 23000, 0, 100000, 100, RTMV20_REG_FSIN2CTRL1,
 217                        RTMV20_DELAY_MASK },
 218                { "richtek,fsin2-width-us", 160, 40, 10000, 40, RTMV20_REG_FSIN2CTRL3,
 219                        RTMV20_WIDTH2_MASK },
 220                { "richtek,es-pulse-width-us", 1200, 0, 10000, 1, RTMV20_REG_ESPULSEWIDTH,
 221                        RTMV20_WIDTH_MASK },
 222                { "richtek,es-ld-current-microamp", 3000000, 0, 6000000, 30000,
 223                        RTMV20_REG_ESLDCTRL1, RTMV20_LDCURR_MASK },
 224                { "richtek,lbp-level-microvolt", 2700000, 2400000, 3700000, 100000, RTMV20_REG_LBP,
 225                        RTMV20_LBPLVL_MASK },
 226                { "richtek,lbp-enable", 0, 0, 1, 1, RTMV20_REG_LBP, RTMV20_LBPEN_MASK },
 227                { "richtek,strobe-polarity-high", 1, 0, 1, 1, RTMV20_REG_LDCTRL2,
 228                        RTMV20_STROBEPOL_MASK },
 229                { "richtek,vsync-polarity-high", 1, 0, 1, 1, RTMV20_REG_LDCTRL2,
 230                        RTMV20_VSYNPOL_MASK },
 231                { "richtek,fsin-enable", 0, 0, 1, 1, RTMV20_REG_ENCTRL, RTMV20_FSINEN_MASK },
 232                { "richtek,fsin-output", 0, 0, 1, 1, RTMV20_REG_ENCTRL, RTMV20_FSINOUT_MASK },
 233                { "richtek,es-enable", 0, 0, 1, 1, RTMV20_REG_ENCTRL, RTMV20_ESEN_MASK },
 234        };
 235        int i, ret;
 236
 237        for (i = 0; i < ARRAY_SIZE(props); i++) {
 238                __be16 bval16;
 239                u16 val16;
 240                u32 temp;
 241                int significant_bit = fls(props[i].mask);
 242                int shift = ffs(props[i].mask) - 1;
 243
 244                if (props[i].max > 1) {
 245                        ret = device_property_read_u32(priv->dev, props[i].name, &temp);
 246                        if (ret)
 247                                temp = props[i].def;
 248                } else
 249                        temp = device_property_read_bool(priv->dev, props[i].name);
 250
 251                temp = clamp_to_selector(temp, props[i].min, props[i].max, props[i].step);
 252
 253                /* If significant bit is over 8, two byte access, others one */
 254                if (significant_bit > 8) {
 255                        ret = regmap_raw_read(priv->regmap, props[i].addr, &bval16, sizeof(bval16));
 256                        if (ret)
 257                                return ret;
 258
 259                        val16 = be16_to_cpu(bval16);
 260                        val16 &= ~props[i].mask;
 261                        val16 |= (temp << shift);
 262                        bval16 = cpu_to_be16(val16);
 263
 264                        ret = regmap_raw_write(priv->regmap, props[i].addr, &bval16,
 265                                               sizeof(bval16));
 266                } else {
 267                        ret = regmap_update_bits(priv->regmap, props[i].addr, props[i].mask,
 268                                                 temp << shift);
 269                }
 270
 271                if (ret)
 272                        return ret;
 273        }
 274
 275        return 0;
 276}
 277
 278static int rtmv20_check_chip_exist(struct rtmv20_priv *priv)
 279{
 280        unsigned int val;
 281        int ret;
 282
 283        ret = regmap_read(priv->regmap, RTMV20_REG_DEVINFO, &val);
 284        if (ret)
 285                return ret;
 286
 287        if ((val & RTMV20_VID_MASK) != RICHTEK_VID)
 288                return -ENODEV;
 289
 290        return 0;
 291}
 292
 293static bool rtmv20_is_accessible_reg(struct device *dev, unsigned int reg)
 294{
 295        switch (reg) {
 296        case RTMV20_REG_DEVINFO ... RTMV20_REG_STRBVSYNDLYL:
 297        case RTMV20_REG_LDIRQ:
 298        case RTMV20_REG_LDSTAT:
 299        case RTMV20_REG_LDMASK:
 300                return true;
 301        }
 302        return false;
 303}
 304
 305static bool rtmv20_is_volatile_reg(struct device *dev, unsigned int reg)
 306{
 307        if (reg == RTMV20_REG_LDIRQ || reg == RTMV20_REG_LDSTAT)
 308                return true;
 309        return false;
 310}
 311
 312static const struct regmap_config rtmv20_regmap_config = {
 313        .reg_bits = 8,
 314        .val_bits = 8,
 315        .cache_type = REGCACHE_RBTREE,
 316        .max_register = RTMV20_REG_LDMASK,
 317        .num_reg_defaults_raw = RTMV20_MAX_REGS,
 318
 319        .writeable_reg = rtmv20_is_accessible_reg,
 320        .readable_reg = rtmv20_is_accessible_reg,
 321        .volatile_reg = rtmv20_is_volatile_reg,
 322};
 323
 324static int rtmv20_probe(struct i2c_client *i2c)
 325{
 326        struct rtmv20_priv *priv;
 327        struct regulator_config config = {};
 328        int ret;
 329
 330        priv = devm_kzalloc(&i2c->dev, sizeof(*priv), GFP_KERNEL);
 331        if (!priv)
 332                return -ENOMEM;
 333
 334        priv->dev = &i2c->dev;
 335
 336        /* Before regmap register, configure HW enable to make I2C accessible */
 337        priv->enable_gpio = devm_gpiod_get(&i2c->dev, "enable", GPIOD_OUT_HIGH);
 338        if (IS_ERR(priv->enable_gpio)) {
 339                dev_err(&i2c->dev, "Failed to get enable gpio\n");
 340                return PTR_ERR(priv->enable_gpio);
 341        }
 342
 343        /* Wait for I2C can be accessed */
 344        usleep_range(RTMV20_I2CRDY_TIMEUS, RTMV20_I2CRDY_TIMEUS + 100);
 345
 346        priv->regmap = devm_regmap_init_i2c(i2c, &rtmv20_regmap_config);
 347        if (IS_ERR(priv->regmap)) {
 348                dev_err(&i2c->dev, "Failed to allocate register map\n");
 349                return PTR_ERR(priv->regmap);
 350        }
 351
 352        ret = rtmv20_check_chip_exist(priv);
 353        if (ret) {
 354                dev_err(&i2c->dev, "Chip vendor info is not matched\n");
 355                return ret;
 356        }
 357
 358        ret = rtmv20_properties_init(priv);
 359        if (ret) {
 360                dev_err(&i2c->dev, "Failed to init properties\n");
 361                return ret;
 362        }
 363
 364        /*
 365         * keep in shutdown mode to minimize the current consumption
 366         * and also mark regcache as dirty
 367         */
 368        regcache_cache_only(priv->regmap, true);
 369        regcache_mark_dirty(priv->regmap);
 370        gpiod_set_value(priv->enable_gpio, 0);
 371
 372        config.dev = &i2c->dev;
 373        config.regmap = priv->regmap;
 374        config.driver_data = priv;
 375        priv->rdev = devm_regulator_register(&i2c->dev, &rtmv20_lsw_desc, &config);
 376        if (IS_ERR(priv->rdev)) {
 377                dev_err(&i2c->dev, "Failed to register regulator\n");
 378                return PTR_ERR(priv->rdev);
 379        }
 380
 381        /* Unmask all events before IRQ registered */
 382        ret = regmap_write(priv->regmap, RTMV20_REG_LDMASK, 0);
 383        if (ret)
 384                return ret;
 385
 386        return devm_request_threaded_irq(&i2c->dev, i2c->irq, NULL, rtmv20_irq_handler,
 387                                         IRQF_ONESHOT, dev_name(&i2c->dev), priv);
 388}
 389
 390static int __maybe_unused rtmv20_suspend(struct device *dev)
 391{
 392        struct i2c_client *i2c = to_i2c_client(dev);
 393
 394        /*
 395         * When system suspend, disable irq to prevent interrupt trigger
 396         * during I2C bus suspend
 397         */
 398        disable_irq(i2c->irq);
 399        if (device_may_wakeup(dev))
 400                enable_irq_wake(i2c->irq);
 401
 402        return 0;
 403}
 404
 405static int __maybe_unused rtmv20_resume(struct device *dev)
 406{
 407        struct i2c_client *i2c = to_i2c_client(dev);
 408
 409        /* Enable irq after I2C bus already resume */
 410        enable_irq(i2c->irq);
 411        if (device_may_wakeup(dev))
 412                disable_irq_wake(i2c->irq);
 413
 414        return 0;
 415}
 416
 417static SIMPLE_DEV_PM_OPS(rtmv20_pm, rtmv20_suspend, rtmv20_resume);
 418
 419static const struct of_device_id __maybe_unused rtmv20_of_id[] = {
 420        { .compatible = "richtek,rtmv20", },
 421        {}
 422};
 423MODULE_DEVICE_TABLE(of, rtmv20_of_id);
 424
 425static struct i2c_driver rtmv20_driver = {
 426        .driver = {
 427                .name = "rtmv20",
 428                .of_match_table = of_match_ptr(rtmv20_of_id),
 429                .pm = &rtmv20_pm,
 430        },
 431        .probe_new = rtmv20_probe,
 432};
 433module_i2c_driver(rtmv20_driver);
 434
 435MODULE_AUTHOR("ChiYuan Huang <cy_huang@richtek.com>");
 436MODULE_DESCRIPTION("Richtek RTMV20 Regulator Driver");
 437MODULE_LICENSE("GPL v2");
 438