root/drivers/regulator/ad5398.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ad5398_calc_current
  2. ad5398_read_reg
  3. ad5398_write_reg
  4. ad5398_get_current_limit
  5. ad5398_set_current_limit
  6. ad5398_is_enabled
  7. ad5398_enable
  8. ad5398_disable
  9. ad5398_probe
  10. ad5398_init
  11. ad5398_exit

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * Voltage and current regulation for AD5398 and AD5821
   4  *
   5  * Copyright 2010 Analog Devices Inc.
   6  *
   7  * Enter bugs at http://blackfin.uclinux.org/
   8  */
   9 
  10 #include <linux/module.h>
  11 #include <linux/err.h>
  12 #include <linux/i2c.h>
  13 #include <linux/slab.h>
  14 #include <linux/platform_device.h>
  15 #include <linux/regulator/driver.h>
  16 #include <linux/regulator/machine.h>
  17 
  18 #define AD5398_CURRENT_EN_MASK  0x8000
  19 
  20 struct ad5398_chip_info {
  21         struct i2c_client *client;
  22         int min_uA;
  23         int max_uA;
  24         unsigned int current_level;
  25         unsigned int current_mask;
  26         unsigned int current_offset;
  27         struct regulator_dev *rdev;
  28 };
  29 
  30 static int ad5398_calc_current(struct ad5398_chip_info *chip,
  31         unsigned selector)
  32 {
  33         unsigned range_uA = chip->max_uA - chip->min_uA;
  34 
  35         return chip->min_uA + (selector * range_uA / chip->current_level);
  36 }
  37 
  38 static int ad5398_read_reg(struct i2c_client *client, unsigned short *data)
  39 {
  40         unsigned short val;
  41         int ret;
  42 
  43         ret = i2c_master_recv(client, (char *)&val, 2);
  44         if (ret < 0) {
  45                 dev_err(&client->dev, "I2C read error\n");
  46                 return ret;
  47         }
  48         *data = be16_to_cpu(val);
  49 
  50         return ret;
  51 }
  52 
  53 static int ad5398_write_reg(struct i2c_client *client, const unsigned short data)
  54 {
  55         unsigned short val;
  56         int ret;
  57 
  58         val = cpu_to_be16(data);
  59         ret = i2c_master_send(client, (char *)&val, 2);
  60         if (ret != 2) {
  61                 dev_err(&client->dev, "I2C write error\n");
  62                 return ret < 0 ? ret : -EIO;
  63         }
  64 
  65         return 0;
  66 }
  67 
  68 static int ad5398_get_current_limit(struct regulator_dev *rdev)
  69 {
  70         struct ad5398_chip_info *chip = rdev_get_drvdata(rdev);
  71         struct i2c_client *client = chip->client;
  72         unsigned short data;
  73         int ret;
  74 
  75         ret = ad5398_read_reg(client, &data);
  76         if (ret < 0)
  77                 return ret;
  78 
  79         ret = (data & chip->current_mask) >> chip->current_offset;
  80 
  81         return ad5398_calc_current(chip, ret);
  82 }
  83 
  84 static int ad5398_set_current_limit(struct regulator_dev *rdev, int min_uA, int max_uA)
  85 {
  86         struct ad5398_chip_info *chip = rdev_get_drvdata(rdev);
  87         struct i2c_client *client = chip->client;
  88         unsigned range_uA = chip->max_uA - chip->min_uA;
  89         unsigned selector;
  90         unsigned short data;
  91         int ret;
  92 
  93         if (min_uA < chip->min_uA)
  94                 min_uA = chip->min_uA;
  95         if (max_uA > chip->max_uA)
  96                 max_uA = chip->max_uA;
  97 
  98         if (min_uA > chip->max_uA || max_uA < chip->min_uA)
  99                 return -EINVAL;
 100 
 101         selector = DIV_ROUND_UP((min_uA - chip->min_uA) * chip->current_level,
 102                                 range_uA);
 103         if (ad5398_calc_current(chip, selector) > max_uA)
 104                 return -EINVAL;
 105 
 106         dev_dbg(&client->dev, "changing current %duA\n",
 107                 ad5398_calc_current(chip, selector));
 108 
 109         /* read chip enable bit */
 110         ret = ad5398_read_reg(client, &data);
 111         if (ret < 0)
 112                 return ret;
 113 
 114         /* prepare register data */
 115         selector = (selector << chip->current_offset) & chip->current_mask;
 116         data = (unsigned short)selector | (data & AD5398_CURRENT_EN_MASK);
 117 
 118         /* write the new current value back as well as enable bit */
 119         ret = ad5398_write_reg(client, data);
 120 
 121         return ret;
 122 }
 123 
 124 static int ad5398_is_enabled(struct regulator_dev *rdev)
 125 {
 126         struct ad5398_chip_info *chip = rdev_get_drvdata(rdev);
 127         struct i2c_client *client = chip->client;
 128         unsigned short data;
 129         int ret;
 130 
 131         ret = ad5398_read_reg(client, &data);
 132         if (ret < 0)
 133                 return ret;
 134 
 135         if (data & AD5398_CURRENT_EN_MASK)
 136                 return 1;
 137         else
 138                 return 0;
 139 }
 140 
 141 static int ad5398_enable(struct regulator_dev *rdev)
 142 {
 143         struct ad5398_chip_info *chip = rdev_get_drvdata(rdev);
 144         struct i2c_client *client = chip->client;
 145         unsigned short data;
 146         int ret;
 147 
 148         ret = ad5398_read_reg(client, &data);
 149         if (ret < 0)
 150                 return ret;
 151 
 152         if (data & AD5398_CURRENT_EN_MASK)
 153                 return 0;
 154 
 155         data |= AD5398_CURRENT_EN_MASK;
 156 
 157         ret = ad5398_write_reg(client, data);
 158 
 159         return ret;
 160 }
 161 
 162 static int ad5398_disable(struct regulator_dev *rdev)
 163 {
 164         struct ad5398_chip_info *chip = rdev_get_drvdata(rdev);
 165         struct i2c_client *client = chip->client;
 166         unsigned short data;
 167         int ret;
 168 
 169         ret = ad5398_read_reg(client, &data);
 170         if (ret < 0)
 171                 return ret;
 172 
 173         if (!(data & AD5398_CURRENT_EN_MASK))
 174                 return 0;
 175 
 176         data &= ~AD5398_CURRENT_EN_MASK;
 177 
 178         ret = ad5398_write_reg(client, data);
 179 
 180         return ret;
 181 }
 182 
 183 static const struct regulator_ops ad5398_ops = {
 184         .get_current_limit = ad5398_get_current_limit,
 185         .set_current_limit = ad5398_set_current_limit,
 186         .enable = ad5398_enable,
 187         .disable = ad5398_disable,
 188         .is_enabled = ad5398_is_enabled,
 189 };
 190 
 191 static const struct regulator_desc ad5398_reg = {
 192         .name = "isink",
 193         .id = 0,
 194         .ops = &ad5398_ops,
 195         .type = REGULATOR_CURRENT,
 196         .owner = THIS_MODULE,
 197 };
 198 
 199 struct ad5398_current_data_format {
 200         int current_bits;
 201         int current_offset;
 202         int min_uA;
 203         int max_uA;
 204 };
 205 
 206 static const struct ad5398_current_data_format df_10_4_120 = {10, 4, 0, 120000};
 207 
 208 static const struct i2c_device_id ad5398_id[] = {
 209         { "ad5398", (kernel_ulong_t)&df_10_4_120 },
 210         { "ad5821", (kernel_ulong_t)&df_10_4_120 },
 211         { }
 212 };
 213 MODULE_DEVICE_TABLE(i2c, ad5398_id);
 214 
 215 static int ad5398_probe(struct i2c_client *client,
 216                                 const struct i2c_device_id *id)
 217 {
 218         struct regulator_init_data *init_data = dev_get_platdata(&client->dev);
 219         struct regulator_config config = { };
 220         struct ad5398_chip_info *chip;
 221         const struct ad5398_current_data_format *df =
 222                         (struct ad5398_current_data_format *)id->driver_data;
 223 
 224         if (!init_data)
 225                 return -EINVAL;
 226 
 227         chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
 228         if (!chip)
 229                 return -ENOMEM;
 230 
 231         config.dev = &client->dev;
 232         config.init_data = init_data;
 233         config.driver_data = chip;
 234 
 235         chip->client = client;
 236 
 237         chip->min_uA = df->min_uA;
 238         chip->max_uA = df->max_uA;
 239         chip->current_level = 1 << df->current_bits;
 240         chip->current_offset = df->current_offset;
 241         chip->current_mask = (chip->current_level - 1) << chip->current_offset;
 242 
 243         chip->rdev = devm_regulator_register(&client->dev, &ad5398_reg,
 244                                              &config);
 245         if (IS_ERR(chip->rdev)) {
 246                 dev_err(&client->dev, "failed to register %s %s\n",
 247                         id->name, ad5398_reg.name);
 248                 return PTR_ERR(chip->rdev);
 249         }
 250 
 251         i2c_set_clientdata(client, chip);
 252         dev_dbg(&client->dev, "%s regulator driver is registered.\n", id->name);
 253         return 0;
 254 }
 255 
 256 static struct i2c_driver ad5398_driver = {
 257         .probe = ad5398_probe,
 258         .driver         = {
 259                 .name   = "ad5398",
 260         },
 261         .id_table       = ad5398_id,
 262 };
 263 
 264 static int __init ad5398_init(void)
 265 {
 266         return i2c_add_driver(&ad5398_driver);
 267 }
 268 subsys_initcall(ad5398_init);
 269 
 270 static void __exit ad5398_exit(void)
 271 {
 272         i2c_del_driver(&ad5398_driver);
 273 }
 274 module_exit(ad5398_exit);
 275 
 276 MODULE_DESCRIPTION("AD5398 and AD5821 current regulator driver");
 277 MODULE_AUTHOR("Sonic Zhang");
 278 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */