linux/drivers/regulator/isl6271a-regulator.c
<<
>>
Prefs
   1/*
   2 * isl6271a-regulator.c
   3 *
   4 * Support for Intersil ISL6271A voltage regulator
   5 *
   6 * Copyright (C) 2010 Marek Vasut <marek.vasut@gmail.com>
   7 *
   8 * This program is free software; you can redistribute it and/or
   9 * modify it under the terms of the GNU General Public License as
  10 * published by the Free Software Foundation version 2.
  11 *
  12 * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind,
  13 * whether express or implied; without even the implied warranty of
  14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15 * General Public License for more details.
  16 */
  17
  18#include <linux/kernel.h>
  19#include <linux/module.h>
  20#include <linux/init.h>
  21#include <linux/err.h>
  22#include <linux/platform_device.h>
  23#include <linux/regulator/driver.h>
  24#include <linux/i2c.h>
  25#include <linux/slab.h>
  26
  27#define ISL6271A_VOLTAGE_MIN    850000
  28#define ISL6271A_VOLTAGE_MAX    1600000
  29#define ISL6271A_VOLTAGE_STEP   50000
  30
  31/* PMIC details */
  32struct isl_pmic {
  33        struct i2c_client       *client;
  34        struct mutex            mtx;
  35};
  36
  37static int isl6271a_get_voltage_sel(struct regulator_dev *dev)
  38{
  39        struct isl_pmic *pmic = rdev_get_drvdata(dev);
  40        int idx;
  41
  42        mutex_lock(&pmic->mtx);
  43
  44        idx = i2c_smbus_read_byte(pmic->client);
  45        if (idx < 0)
  46                dev_err(&pmic->client->dev, "Error getting voltage\n");
  47
  48        mutex_unlock(&pmic->mtx);
  49        return idx;
  50}
  51
  52static int isl6271a_set_voltage_sel(struct regulator_dev *dev,
  53                                    unsigned selector)
  54{
  55        struct isl_pmic *pmic = rdev_get_drvdata(dev);
  56        int err;
  57
  58        mutex_lock(&pmic->mtx);
  59
  60        err = i2c_smbus_write_byte(pmic->client, selector);
  61        if (err < 0)
  62                dev_err(&pmic->client->dev, "Error setting voltage\n");
  63
  64        mutex_unlock(&pmic->mtx);
  65        return err;
  66}
  67
  68static const struct regulator_ops isl_core_ops = {
  69        .get_voltage_sel = isl6271a_get_voltage_sel,
  70        .set_voltage_sel = isl6271a_set_voltage_sel,
  71        .list_voltage   = regulator_list_voltage_linear,
  72        .map_voltage    = regulator_map_voltage_linear,
  73};
  74
  75static const struct regulator_ops isl_fixed_ops = {
  76        .list_voltage   = regulator_list_voltage_linear,
  77};
  78
  79static const struct regulator_desc isl_rd[] = {
  80        {
  81                .name           = "Core Buck",
  82                .id             = 0,
  83                .n_voltages     = 16,
  84                .ops            = &isl_core_ops,
  85                .type           = REGULATOR_VOLTAGE,
  86                .owner          = THIS_MODULE,
  87                .min_uV         = ISL6271A_VOLTAGE_MIN,
  88                .uV_step        = ISL6271A_VOLTAGE_STEP,
  89        }, {
  90                .name           = "LDO1",
  91                .id             = 1,
  92                .n_voltages     = 1,
  93                .ops            = &isl_fixed_ops,
  94                .type           = REGULATOR_VOLTAGE,
  95                .owner          = THIS_MODULE,
  96                .min_uV         = 1100000,
  97        }, {
  98                .name           = "LDO2",
  99                .id             = 2,
 100                .n_voltages     = 1,
 101                .ops            = &isl_fixed_ops,
 102                .type           = REGULATOR_VOLTAGE,
 103                .owner          = THIS_MODULE,
 104                .min_uV         = 1300000,
 105        },
 106};
 107
 108static int isl6271a_probe(struct i2c_client *i2c,
 109                                     const struct i2c_device_id *id)
 110{
 111        struct regulator_dev *rdev;
 112        struct regulator_config config = { };
 113        struct regulator_init_data *init_data   = dev_get_platdata(&i2c->dev);
 114        struct isl_pmic *pmic;
 115        int i;
 116
 117        if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
 118                return -EIO;
 119
 120        pmic = devm_kzalloc(&i2c->dev, sizeof(struct isl_pmic), GFP_KERNEL);
 121        if (!pmic)
 122                return -ENOMEM;
 123
 124        pmic->client = i2c;
 125
 126        mutex_init(&pmic->mtx);
 127
 128        for (i = 0; i < 3; i++) {
 129                config.dev = &i2c->dev;
 130                if (i == 0)
 131                        config.init_data = init_data;
 132                else
 133                        config.init_data = NULL;
 134                config.driver_data = pmic;
 135
 136                rdev = devm_regulator_register(&i2c->dev, &isl_rd[i], &config);
 137                if (IS_ERR(rdev)) {
 138                        dev_err(&i2c->dev, "failed to register %s\n", id->name);
 139                        return PTR_ERR(rdev);
 140                }
 141        }
 142
 143        i2c_set_clientdata(i2c, pmic);
 144
 145        return 0;
 146}
 147
 148static const struct i2c_device_id isl6271a_id[] = {
 149        {.name = "isl6271a", 0 },
 150        { },
 151};
 152
 153MODULE_DEVICE_TABLE(i2c, isl6271a_id);
 154
 155static struct i2c_driver isl6271a_i2c_driver = {
 156        .driver = {
 157                .name = "isl6271a",
 158        },
 159        .probe = isl6271a_probe,
 160        .id_table = isl6271a_id,
 161};
 162
 163static int __init isl6271a_init(void)
 164{
 165        return i2c_add_driver(&isl6271a_i2c_driver);
 166}
 167
 168static void __exit isl6271a_cleanup(void)
 169{
 170        i2c_del_driver(&isl6271a_i2c_driver);
 171}
 172
 173subsys_initcall(isl6271a_init);
 174module_exit(isl6271a_cleanup);
 175
 176MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>");
 177MODULE_DESCRIPTION("Intersil ISL6271A voltage regulator driver");
 178MODULE_LICENSE("GPL v2");
 179