ad5398.c (6413B)
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 20struct 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 30static 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 38static 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 53static 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 68static 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 84static 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 124static 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 141static 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 162static 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 183static 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 191static 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 199struct ad5398_current_data_format { 200 int current_bits; 201 int current_offset; 202 int min_uA; 203 int max_uA; 204}; 205 206static const struct ad5398_current_data_format df_10_4_120 = {10, 4, 0, 120000}; 207 208static 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}; 213MODULE_DEVICE_TABLE(i2c, ad5398_id); 214 215static 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 256static struct i2c_driver ad5398_driver = { 257 .probe = ad5398_probe, 258 .driver = { 259 .name = "ad5398", 260 }, 261 .id_table = ad5398_id, 262}; 263 264static int __init ad5398_init(void) 265{ 266 return i2c_add_driver(&ad5398_driver); 267} 268subsys_initcall(ad5398_init); 269 270static void __exit ad5398_exit(void) 271{ 272 i2c_del_driver(&ad5398_driver); 273} 274module_exit(ad5398_exit); 275 276MODULE_DESCRIPTION("AD5398 and AD5821 current regulator driver"); 277MODULE_AUTHOR("Sonic Zhang"); 278MODULE_LICENSE("GPL");