280 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Voltage and current regulation for AD5398 and AD58214 *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 0x800019 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 else138 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{217 const struct i2c_device_id *id = i2c_client_get_device_id(client);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 .probe_type = PROBE_PREFER_ASYNCHRONOUS,261 },262 .id_table = ad5398_id,263};264 265static int __init ad5398_init(void)266{267 return i2c_add_driver(&ad5398_driver);268}269subsys_initcall(ad5398_init);270 271static void __exit ad5398_exit(void)272{273 i2c_del_driver(&ad5398_driver);274}275module_exit(ad5398_exit);276 277MODULE_DESCRIPTION("AD5398 and AD5821 current regulator driver");278MODULE_AUTHOR("Sonic Zhang");279MODULE_LICENSE("GPL");280