linux/drivers/regulator/max8649.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Regulators driver for Maxim max8649
   4 *
   5 * Copyright (C) 2009-2010 Marvell International Ltd.
   6 *      Haojian Zhuang <haojian.zhuang@marvell.com>
   7 */
   8#include <linux/kernel.h>
   9#include <linux/module.h>
  10#include <linux/err.h>
  11#include <linux/i2c.h>
  12#include <linux/platform_device.h>
  13#include <linux/regulator/driver.h>
  14#include <linux/slab.h>
  15#include <linux/regulator/max8649.h>
  16#include <linux/regmap.h>
  17
  18#define MAX8649_DCDC_VMIN       750000          /* uV */
  19#define MAX8649_DCDC_VMAX       1380000         /* uV */
  20#define MAX8649_DCDC_STEP       10000           /* uV */
  21#define MAX8649_VOL_MASK        0x3f
  22
  23/* Registers */
  24#define MAX8649_MODE0           0x00
  25#define MAX8649_MODE1           0x01
  26#define MAX8649_MODE2           0x02
  27#define MAX8649_MODE3           0x03
  28#define MAX8649_CONTROL         0x04
  29#define MAX8649_SYNC            0x05
  30#define MAX8649_RAMP            0x06
  31#define MAX8649_CHIP_ID1        0x08
  32#define MAX8649_CHIP_ID2        0x09
  33
  34/* Bits */
  35#define MAX8649_EN_PD           (1 << 7)
  36#define MAX8649_VID0_PD         (1 << 6)
  37#define MAX8649_VID1_PD         (1 << 5)
  38#define MAX8649_VID_MASK        (3 << 5)
  39
  40#define MAX8649_FORCE_PWM       (1 << 7)
  41#define MAX8649_SYNC_EXTCLK     (1 << 6)
  42
  43#define MAX8649_EXT_MASK        (3 << 6)
  44
  45#define MAX8649_RAMP_MASK       (7 << 5)
  46#define MAX8649_RAMP_DOWN       (1 << 1)
  47
  48struct max8649_regulator_info {
  49        struct device           *dev;
  50        struct regmap           *regmap;
  51
  52        unsigned        mode:2; /* bit[1:0] = VID1, VID0 */
  53        unsigned        extclk_freq:2;
  54        unsigned        extclk:1;
  55        unsigned        ramp_timing:3;
  56        unsigned        ramp_down:1;
  57};
  58
  59static int max8649_enable_time(struct regulator_dev *rdev)
  60{
  61        struct max8649_regulator_info *info = rdev_get_drvdata(rdev);
  62        int voltage, rate, ret;
  63        unsigned int val;
  64
  65        /* get voltage */
  66        ret = regmap_read(info->regmap, rdev->desc->vsel_reg, &val);
  67        if (ret != 0)
  68                return ret;
  69        val &= MAX8649_VOL_MASK;
  70        voltage = regulator_list_voltage_linear(rdev, (unsigned char)val);
  71
  72        /* get rate */
  73        ret = regmap_read(info->regmap, MAX8649_RAMP, &val);
  74        if (ret != 0)
  75                return ret;
  76        ret = (val & MAX8649_RAMP_MASK) >> 5;
  77        rate = (32 * 1000) >> ret;      /* uV/uS */
  78
  79        return DIV_ROUND_UP(voltage, rate);
  80}
  81
  82static int max8649_set_mode(struct regulator_dev *rdev, unsigned int mode)
  83{
  84        struct max8649_regulator_info *info = rdev_get_drvdata(rdev);
  85
  86        switch (mode) {
  87        case REGULATOR_MODE_FAST:
  88                regmap_update_bits(info->regmap, rdev->desc->vsel_reg,
  89                                   MAX8649_FORCE_PWM, MAX8649_FORCE_PWM);
  90                break;
  91        case REGULATOR_MODE_NORMAL:
  92                regmap_update_bits(info->regmap, rdev->desc->vsel_reg,
  93                                   MAX8649_FORCE_PWM, 0);
  94                break;
  95        default:
  96                return -EINVAL;
  97        }
  98        return 0;
  99}
 100
 101static unsigned int max8649_get_mode(struct regulator_dev *rdev)
 102{
 103        struct max8649_regulator_info *info = rdev_get_drvdata(rdev);
 104        unsigned int val;
 105        int ret;
 106
 107        ret = regmap_read(info->regmap, rdev->desc->vsel_reg, &val);
 108        if (ret != 0)
 109                return ret;
 110        if (val & MAX8649_FORCE_PWM)
 111                return REGULATOR_MODE_FAST;
 112        return REGULATOR_MODE_NORMAL;
 113}
 114
 115static const struct regulator_ops max8649_dcdc_ops = {
 116        .set_voltage_sel = regulator_set_voltage_sel_regmap,
 117        .get_voltage_sel = regulator_get_voltage_sel_regmap,
 118        .list_voltage   = regulator_list_voltage_linear,
 119        .map_voltage    = regulator_map_voltage_linear,
 120        .enable         = regulator_enable_regmap,
 121        .disable        = regulator_disable_regmap,
 122        .is_enabled     = regulator_is_enabled_regmap,
 123        .enable_time    = max8649_enable_time,
 124        .set_mode       = max8649_set_mode,
 125        .get_mode       = max8649_get_mode,
 126
 127};
 128
 129static struct regulator_desc dcdc_desc = {
 130        .name           = "max8649",
 131        .ops            = &max8649_dcdc_ops,
 132        .type           = REGULATOR_VOLTAGE,
 133        .n_voltages     = 1 << 6,
 134        .owner          = THIS_MODULE,
 135        .vsel_mask      = MAX8649_VOL_MASK,
 136        .min_uV         = MAX8649_DCDC_VMIN,
 137        .uV_step        = MAX8649_DCDC_STEP,
 138        .enable_reg     = MAX8649_CONTROL,
 139        .enable_mask    = MAX8649_EN_PD,
 140        .enable_is_inverted = true,
 141};
 142
 143static const struct regmap_config max8649_regmap_config = {
 144        .reg_bits = 8,
 145        .val_bits = 8,
 146};
 147
 148static int max8649_regulator_probe(struct i2c_client *client,
 149                                             const struct i2c_device_id *id)
 150{
 151        struct max8649_platform_data *pdata = dev_get_platdata(&client->dev);
 152        struct max8649_regulator_info *info = NULL;
 153        struct regulator_dev *regulator;
 154        struct regulator_config config = { };
 155        unsigned int val;
 156        unsigned char data;
 157        int ret;
 158
 159        info = devm_kzalloc(&client->dev, sizeof(struct max8649_regulator_info),
 160                            GFP_KERNEL);
 161        if (!info)
 162                return -ENOMEM;
 163
 164        info->regmap = devm_regmap_init_i2c(client, &max8649_regmap_config);
 165        if (IS_ERR(info->regmap)) {
 166                ret = PTR_ERR(info->regmap);
 167                dev_err(&client->dev, "Failed to allocate register map: %d\n", ret);
 168                return ret;
 169        }
 170
 171        info->dev = &client->dev;
 172        i2c_set_clientdata(client, info);
 173
 174        info->mode = pdata->mode;
 175        switch (info->mode) {
 176        case 0:
 177                dcdc_desc.vsel_reg = MAX8649_MODE0;
 178                break;
 179        case 1:
 180                dcdc_desc.vsel_reg = MAX8649_MODE1;
 181                break;
 182        case 2:
 183                dcdc_desc.vsel_reg = MAX8649_MODE2;
 184                break;
 185        case 3:
 186                dcdc_desc.vsel_reg = MAX8649_MODE3;
 187                break;
 188        default:
 189                break;
 190        }
 191
 192        ret = regmap_read(info->regmap, MAX8649_CHIP_ID1, &val);
 193        if (ret != 0) {
 194                dev_err(info->dev, "Failed to detect ID of MAX8649:%d\n",
 195                        ret);
 196                return ret;
 197        }
 198        dev_info(info->dev, "Detected MAX8649 (ID:%x)\n", val);
 199
 200        /* enable VID0 & VID1 */
 201        regmap_update_bits(info->regmap, MAX8649_CONTROL, MAX8649_VID_MASK, 0);
 202
 203        /* enable/disable external clock synchronization */
 204        info->extclk = pdata->extclk;
 205        data = (info->extclk) ? MAX8649_SYNC_EXTCLK : 0;
 206        regmap_update_bits(info->regmap, dcdc_desc.vsel_reg,
 207                           MAX8649_SYNC_EXTCLK, data);
 208        if (info->extclk) {
 209                /* set external clock frequency */
 210                info->extclk_freq = pdata->extclk_freq;
 211                regmap_update_bits(info->regmap, MAX8649_SYNC, MAX8649_EXT_MASK,
 212                                   info->extclk_freq << 6);
 213        }
 214
 215        if (pdata->ramp_timing) {
 216                info->ramp_timing = pdata->ramp_timing;
 217                regmap_update_bits(info->regmap, MAX8649_RAMP, MAX8649_RAMP_MASK,
 218                                   info->ramp_timing << 5);
 219        }
 220
 221        info->ramp_down = pdata->ramp_down;
 222        if (info->ramp_down) {
 223                regmap_update_bits(info->regmap, MAX8649_RAMP, MAX8649_RAMP_DOWN,
 224                                   MAX8649_RAMP_DOWN);
 225        }
 226
 227        config.dev = &client->dev;
 228        config.init_data = pdata->regulator;
 229        config.driver_data = info;
 230        config.regmap = info->regmap;
 231
 232        regulator = devm_regulator_register(&client->dev, &dcdc_desc,
 233                                                  &config);
 234        if (IS_ERR(regulator)) {
 235                dev_err(info->dev, "failed to register regulator %s\n",
 236                        dcdc_desc.name);
 237                return PTR_ERR(regulator);
 238        }
 239
 240        return 0;
 241}
 242
 243static const struct i2c_device_id max8649_id[] = {
 244        { "max8649", 0 },
 245        { }
 246};
 247MODULE_DEVICE_TABLE(i2c, max8649_id);
 248
 249static struct i2c_driver max8649_driver = {
 250        .probe          = max8649_regulator_probe,
 251        .driver         = {
 252                .name   = "max8649",
 253        },
 254        .id_table       = max8649_id,
 255};
 256
 257static int __init max8649_init(void)
 258{
 259        return i2c_add_driver(&max8649_driver);
 260}
 261subsys_initcall(max8649_init);
 262
 263static void __exit max8649_exit(void)
 264{
 265        i2c_del_driver(&max8649_driver);
 266}
 267module_exit(max8649_exit);
 268
 269/* Module information */
 270MODULE_DESCRIPTION("MAXIM 8649 voltage regulator driver");
 271MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
 272MODULE_LICENSE("GPL");
 273