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 regulator_dev    *rdev[3];
  35        struct mutex            mtx;
  36};
  37
  38static int isl6271a_get_voltage_sel(struct regulator_dev *dev)
  39{
  40        struct isl_pmic *pmic = rdev_get_drvdata(dev);
  41        int idx;
  42
  43        mutex_lock(&pmic->mtx);
  44
  45        idx = i2c_smbus_read_byte(pmic->client);
  46        if (idx < 0)
  47                dev_err(&pmic->client->dev, "Error getting voltage\n");
  48
  49        mutex_unlock(&pmic->mtx);
  50        return idx;
  51}
  52
  53static int isl6271a_set_voltage_sel(struct regulator_dev *dev,
  54                                    unsigned selector)
  55{
  56        struct isl_pmic *pmic = rdev_get_drvdata(dev);
  57        int err;
  58
  59        mutex_lock(&pmic->mtx);
  60
  61        err = i2c_smbus_write_byte(pmic->client, selector);
  62        if (err < 0)
  63                dev_err(&pmic->client->dev, "Error setting voltage\n");
  64
  65        mutex_unlock(&pmic->mtx);
  66        return err;
  67}
  68
  69static struct regulator_ops isl_core_ops = {
  70        .get_voltage_sel = isl6271a_get_voltage_sel,
  71        .set_voltage_sel = isl6271a_set_voltage_sel,
  72        .list_voltage   = regulator_list_voltage_linear,
  73        .map_voltage    = regulator_map_voltage_linear,
  74};
  75
  76static struct regulator_ops isl_fixed_ops = {
  77        .list_voltage   = regulator_list_voltage_linear,
  78};
  79
  80static const struct regulator_desc isl_rd[] = {
  81        {
  82                .name           = "Core Buck",
  83                .id             = 0,
  84                .n_voltages     = 16,
  85                .ops            = &isl_core_ops,
  86                .type           = REGULATOR_VOLTAGE,
  87                .owner          = THIS_MODULE,
  88                .min_uV         = ISL6271A_VOLTAGE_MIN,
  89                .uV_step        = ISL6271A_VOLTAGE_STEP,
  90        }, {
  91                .name           = "LDO1",
  92                .id             = 1,
  93                .n_voltages     = 1,
  94                .ops            = &isl_fixed_ops,
  95                .type           = REGULATOR_VOLTAGE,
  96                .owner          = THIS_MODULE,
  97                .min_uV         = 1100000,
  98        }, {
  99                .name           = "LDO2",
 100                .id             = 2,
 101                .n_voltages     = 1,
 102                .ops            = &isl_fixed_ops,
 103                .type           = REGULATOR_VOLTAGE,
 104                .owner          = THIS_MODULE,
 105                .min_uV         = 1300000,
 106        },
 107};
 108
 109static int isl6271a_probe(struct i2c_client *i2c,
 110                                     const struct i2c_device_id *id)
 111{
 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                pmic->rdev[i] = devm_regulator_register(&i2c->dev, &isl_rd[i],
 137                                                        &config);
 138                if (IS_ERR(pmic->rdev[i])) {
 139                        dev_err(&i2c->dev, "failed to register %s\n", id->name);
 140                        return PTR_ERR(pmic->rdev[i]);
 141                }
 142        }
 143
 144        i2c_set_clientdata(i2c, pmic);
 145
 146        return 0;
 147}
 148
 149static const struct i2c_device_id isl6271a_id[] = {
 150        {.name = "isl6271a", 0 },
 151        { },
 152};
 153
 154MODULE_DEVICE_TABLE(i2c, isl6271a_id);
 155
 156static struct i2c_driver isl6271a_i2c_driver = {
 157        .driver = {
 158                .name = "isl6271a",
 159        },
 160        .probe = isl6271a_probe,
 161        .id_table = isl6271a_id,
 162};
 163
 164static int __init isl6271a_init(void)
 165{
 166        return i2c_add_driver(&isl6271a_i2c_driver);
 167}
 168
 169static void __exit isl6271a_cleanup(void)
 170{
 171        i2c_del_driver(&isl6271a_i2c_driver);
 172}
 173
 174subsys_initcall(isl6271a_init);
 175module_exit(isl6271a_cleanup);
 176
 177MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>");
 178MODULE_DESCRIPTION("Intersil ISL6271A voltage regulator driver");
 179MODULE_LICENSE("GPL v2");
 180