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 int isl6271a_get_fixed_voltage(struct regulator_dev *dev)
  77{
  78        return dev->desc->min_uV;
  79}
  80
  81static struct regulator_ops isl_fixed_ops = {
  82        .get_voltage    = isl6271a_get_fixed_voltage,
  83        .list_voltage   = regulator_list_voltage_linear,
  84};
  85
  86static const struct regulator_desc isl_rd[] = {
  87        {
  88                .name           = "Core Buck",
  89                .id             = 0,
  90                .n_voltages     = 16,
  91                .ops            = &isl_core_ops,
  92                .type           = REGULATOR_VOLTAGE,
  93                .owner          = THIS_MODULE,
  94                .min_uV         = ISL6271A_VOLTAGE_MIN,
  95                .uV_step        = ISL6271A_VOLTAGE_STEP,
  96        }, {
  97                .name           = "LDO1",
  98                .id             = 1,
  99                .n_voltages     = 1,
 100                .ops            = &isl_fixed_ops,
 101                .type           = REGULATOR_VOLTAGE,
 102                .owner          = THIS_MODULE,
 103                .min_uV         = 1100000,
 104        }, {
 105                .name           = "LDO2",
 106                .id             = 2,
 107                .n_voltages     = 1,
 108                .ops            = &isl_fixed_ops,
 109                .type           = REGULATOR_VOLTAGE,
 110                .owner          = THIS_MODULE,
 111                .min_uV         = 1300000,
 112        },
 113};
 114
 115static int __devinit isl6271a_probe(struct i2c_client *i2c,
 116                                     const struct i2c_device_id *id)
 117{
 118        struct regulator_config config = { };
 119        struct regulator_init_data *init_data   = i2c->dev.platform_data;
 120        struct isl_pmic *pmic;
 121        int err, i;
 122
 123        if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
 124                return -EIO;
 125
 126        pmic = devm_kzalloc(&i2c->dev, sizeof(struct isl_pmic), GFP_KERNEL);
 127        if (!pmic)
 128                return -ENOMEM;
 129
 130        pmic->client = i2c;
 131
 132        mutex_init(&pmic->mtx);
 133
 134        for (i = 0; i < 3; i++) {
 135                config.dev = &i2c->dev;
 136                if (i == 0)
 137                        config.init_data = init_data;
 138                else
 139                        config.init_data = 0;
 140                config.driver_data = pmic;
 141
 142                pmic->rdev[i] = regulator_register(&isl_rd[i], &config);
 143                if (IS_ERR(pmic->rdev[i])) {
 144                        dev_err(&i2c->dev, "failed to register %s\n", id->name);
 145                        err = PTR_ERR(pmic->rdev[i]);
 146                        goto error;
 147                }
 148        }
 149
 150        i2c_set_clientdata(i2c, pmic);
 151
 152        return 0;
 153
 154error:
 155        while (--i >= 0)
 156                regulator_unregister(pmic->rdev[i]);
 157        return err;
 158}
 159
 160static int __devexit isl6271a_remove(struct i2c_client *i2c)
 161{
 162        struct isl_pmic *pmic = i2c_get_clientdata(i2c);
 163        int i;
 164
 165        for (i = 0; i < 3; i++)
 166                regulator_unregister(pmic->rdev[i]);
 167        return 0;
 168}
 169
 170static const struct i2c_device_id isl6271a_id[] = {
 171        {.name = "isl6271a", 0 },
 172        { },
 173};
 174
 175MODULE_DEVICE_TABLE(i2c, isl6271a_id);
 176
 177static struct i2c_driver isl6271a_i2c_driver = {
 178        .driver = {
 179                .name = "isl6271a",
 180                .owner = THIS_MODULE,
 181        },
 182        .probe = isl6271a_probe,
 183        .remove = __devexit_p(isl6271a_remove),
 184        .id_table = isl6271a_id,
 185};
 186
 187static int __init isl6271a_init(void)
 188{
 189        return i2c_add_driver(&isl6271a_i2c_driver);
 190}
 191
 192static void __exit isl6271a_cleanup(void)
 193{
 194        i2c_del_driver(&isl6271a_i2c_driver);
 195}
 196
 197subsys_initcall(isl6271a_init);
 198module_exit(isl6271a_cleanup);
 199
 200MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>");
 201MODULE_DESCRIPTION("Intersil ISL6271A voltage regulator driver");
 202MODULE_LICENSE("GPL v2");
 203
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.