ad5110.c (8009B)
1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Analog Devices AD5110 digital potentiometer driver 4 * 5 * Copyright (C) 2021 Mugilraj Dhavachelvan <dmugil2000@gmail.com> 6 * 7 * Datasheet: https://www.analog.com/media/en/technical-documentation/data-sheets/AD5110_5112_5114.pdf 8 */ 9 10#include <linux/bitfield.h> 11#include <linux/delay.h> 12#include <linux/device.h> 13#include <linux/i2c.h> 14#include <linux/module.h> 15 16#include <linux/iio/iio.h> 17#include <linux/iio/sysfs.h> 18 19/* AD5110 commands */ 20#define AD5110_EEPROM_WR 1 21#define AD5110_RDAC_WR 2 22#define AD5110_SHUTDOWN 3 23#define AD5110_RESET 4 24#define AD5110_RDAC_RD 5 25#define AD5110_EEPROM_RD 6 26 27/* AD5110_EEPROM_RD data */ 28#define AD5110_WIPER_POS 0 29#define AD5110_RESISTOR_TOL 1 30 31#define AD5110_WIPER_RESISTANCE 70 32 33struct ad5110_cfg { 34 int max_pos; 35 int kohms; 36 int shift; 37}; 38 39enum ad5110_type { 40 AD5110_10, 41 AD5110_80, 42 AD5112_05, 43 AD5112_10, 44 AD5112_80, 45 AD5114_10, 46 AD5114_80, 47}; 48 49static const struct ad5110_cfg ad5110_cfg[] = { 50 [AD5110_10] = { .max_pos = 128, .kohms = 10 }, 51 [AD5110_80] = { .max_pos = 128, .kohms = 80 }, 52 [AD5112_05] = { .max_pos = 64, .kohms = 5, .shift = 1 }, 53 [AD5112_10] = { .max_pos = 64, .kohms = 10, .shift = 1 }, 54 [AD5112_80] = { .max_pos = 64, .kohms = 80, .shift = 1 }, 55 [AD5114_10] = { .max_pos = 32, .kohms = 10, .shift = 2 }, 56 [AD5114_80] = { .max_pos = 32, .kohms = 80, .shift = 2 }, 57}; 58 59struct ad5110_data { 60 struct i2c_client *client; 61 s16 tol; /* resistor tolerance */ 62 bool enable; 63 struct mutex lock; 64 const struct ad5110_cfg *cfg; 65 /* 66 * DMA (thus cache coherency maintenance) requires the 67 * transfer buffers to live in their own cache lines. 68 */ 69 u8 buf[2] ____cacheline_aligned; 70}; 71 72static const struct iio_chan_spec ad5110_channels[] = { 73 { 74 .type = IIO_RESISTANCE, 75 .output = 1, 76 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_OFFSET) | 77 BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_ENABLE), 78 }, 79}; 80 81static int ad5110_read(struct ad5110_data *data, u8 cmd, int *val) 82{ 83 int ret; 84 85 mutex_lock(&data->lock); 86 data->buf[0] = cmd; 87 data->buf[1] = *val; 88 89 ret = i2c_master_send_dmasafe(data->client, data->buf, sizeof(data->buf)); 90 if (ret < 0) { 91 goto error; 92 } else if (ret != sizeof(data->buf)) { 93 ret = -EIO; 94 goto error; 95 } 96 97 ret = i2c_master_recv_dmasafe(data->client, data->buf, 1); 98 if (ret < 0) { 99 goto error; 100 } else if (ret != 1) { 101 ret = -EIO; 102 goto error; 103 } 104 105 *val = data->buf[0]; 106 ret = 0; 107 108error: 109 mutex_unlock(&data->lock); 110 return ret; 111} 112 113static int ad5110_write(struct ad5110_data *data, u8 cmd, u8 val) 114{ 115 int ret; 116 117 mutex_lock(&data->lock); 118 data->buf[0] = cmd; 119 data->buf[1] = val; 120 121 ret = i2c_master_send_dmasafe(data->client, data->buf, sizeof(data->buf)); 122 if (ret < 0) { 123 goto error; 124 } else if (ret != sizeof(data->buf)) { 125 ret = -EIO; 126 goto error; 127 } 128 129 ret = 0; 130 131error: 132 mutex_unlock(&data->lock); 133 return ret; 134} 135 136static int ad5110_resistor_tol(struct ad5110_data *data, u8 cmd, int val) 137{ 138 int ret; 139 140 ret = ad5110_read(data, cmd, &val); 141 if (ret) 142 return ret; 143 144 data->tol = data->cfg->kohms * (val & GENMASK(6, 0)) * 10 / 8; 145 if (!(val & BIT(7))) 146 data->tol *= -1; 147 148 return 0; 149} 150 151static ssize_t store_eeprom_show(struct device *dev, 152 struct device_attribute *attr, 153 char *buf) 154{ 155 struct iio_dev *indio_dev = dev_to_iio_dev(dev); 156 struct ad5110_data *data = iio_priv(indio_dev); 157 int val = AD5110_WIPER_POS; 158 int ret; 159 160 ret = ad5110_read(data, AD5110_EEPROM_RD, &val); 161 if (ret) 162 return ret; 163 164 val = val >> data->cfg->shift; 165 return iio_format_value(buf, IIO_VAL_INT, 1, &val); 166} 167 168static ssize_t store_eeprom_store(struct device *dev, 169 struct device_attribute *attr, 170 const char *buf, size_t len) 171{ 172 struct iio_dev *indio_dev = dev_to_iio_dev(dev); 173 struct ad5110_data *data = iio_priv(indio_dev); 174 int ret; 175 176 ret = ad5110_write(data, AD5110_EEPROM_WR, 0); 177 if (ret) { 178 dev_err(&data->client->dev, "RDAC to EEPROM write failed\n"); 179 return ret; 180 } 181 182 /* The storing of EEPROM data takes approximately 18 ms. */ 183 msleep(20); 184 185 return len; 186} 187 188static IIO_DEVICE_ATTR_RW(store_eeprom, 0); 189 190static struct attribute *ad5110_attributes[] = { 191 &iio_dev_attr_store_eeprom.dev_attr.attr, 192 NULL 193}; 194 195static const struct attribute_group ad5110_attribute_group = { 196 .attrs = ad5110_attributes, 197}; 198 199static int ad5110_read_raw(struct iio_dev *indio_dev, 200 struct iio_chan_spec const *chan, 201 int *val, int *val2, long mask) 202{ 203 struct ad5110_data *data = iio_priv(indio_dev); 204 int ret; 205 206 switch (mask) { 207 case IIO_CHAN_INFO_RAW: 208 ret = ad5110_read(data, AD5110_RDAC_RD, val); 209 if (ret) 210 return ret; 211 212 *val = *val >> data->cfg->shift; 213 return IIO_VAL_INT; 214 case IIO_CHAN_INFO_OFFSET: 215 *val = AD5110_WIPER_RESISTANCE * data->cfg->max_pos; 216 *val2 = 1000 * data->cfg->kohms + data->tol; 217 return IIO_VAL_FRACTIONAL; 218 case IIO_CHAN_INFO_SCALE: 219 *val = 1000 * data->cfg->kohms + data->tol; 220 *val2 = data->cfg->max_pos; 221 return IIO_VAL_FRACTIONAL; 222 case IIO_CHAN_INFO_ENABLE: 223 *val = data->enable; 224 return IIO_VAL_INT; 225 default: 226 return -EINVAL; 227 } 228} 229 230static int ad5110_write_raw(struct iio_dev *indio_dev, 231 struct iio_chan_spec const *chan, 232 int val, int val2, long mask) 233{ 234 struct ad5110_data *data = iio_priv(indio_dev); 235 int ret; 236 237 switch (mask) { 238 case IIO_CHAN_INFO_RAW: 239 if (val > data->cfg->max_pos || val < 0) 240 return -EINVAL; 241 242 return ad5110_write(data, AD5110_RDAC_WR, val << data->cfg->shift); 243 case IIO_CHAN_INFO_ENABLE: 244 if (val < 0 || val > 1) 245 return -EINVAL; 246 if (data->enable == val) 247 return 0; 248 ret = ad5110_write(data, AD5110_SHUTDOWN, val ? 0 : 1); 249 if (ret) 250 return ret; 251 data->enable = val; 252 return 0; 253 default: 254 return -EINVAL; 255 } 256} 257 258static const struct iio_info ad5110_info = { 259 .read_raw = ad5110_read_raw, 260 .write_raw = ad5110_write_raw, 261 .attrs = &ad5110_attribute_group, 262}; 263 264#define AD5110_COMPATIBLE(of_compatible, cfg) { \ 265 .compatible = of_compatible, \ 266 .data = &ad5110_cfg[cfg], \ 267} 268 269static const struct of_device_id ad5110_of_match[] = { 270 AD5110_COMPATIBLE("adi,ad5110-10", AD5110_10), 271 AD5110_COMPATIBLE("adi,ad5110-80", AD5110_80), 272 AD5110_COMPATIBLE("adi,ad5112-05", AD5112_05), 273 AD5110_COMPATIBLE("adi,ad5112-10", AD5112_10), 274 AD5110_COMPATIBLE("adi,ad5112-80", AD5112_80), 275 AD5110_COMPATIBLE("adi,ad5114-10", AD5114_10), 276 AD5110_COMPATIBLE("adi,ad5114-80", AD5114_80), 277 { } 278}; 279MODULE_DEVICE_TABLE(of, ad5110_of_match); 280 281static const struct i2c_device_id ad5110_id[] = { 282 { "ad5110-10", AD5110_10 }, 283 { "ad5110-80", AD5110_80 }, 284 { "ad5112-05", AD5112_05 }, 285 { "ad5112-10", AD5112_10 }, 286 { "ad5112-80", AD5112_80 }, 287 { "ad5114-10", AD5114_10 }, 288 { "ad5114-80", AD5114_80 }, 289 { } 290}; 291MODULE_DEVICE_TABLE(i2c, ad5110_id); 292 293static int ad5110_probe(struct i2c_client *client) 294{ 295 struct device *dev = &client->dev; 296 struct iio_dev *indio_dev; 297 struct ad5110_data *data; 298 int ret; 299 300 indio_dev = devm_iio_device_alloc(dev, sizeof(*data)); 301 if (!indio_dev) 302 return -ENOMEM; 303 304 data = iio_priv(indio_dev); 305 data->client = client; 306 mutex_init(&data->lock); 307 data->enable = 1; 308 data->cfg = device_get_match_data(dev); 309 310 /* refresh RDAC register with EEPROM */ 311 ret = ad5110_write(data, AD5110_RESET, 0); 312 if (ret) { 313 dev_err(dev, "Refresh RDAC with EEPROM failed\n"); 314 return ret; 315 } 316 317 ret = ad5110_resistor_tol(data, AD5110_EEPROM_RD, AD5110_RESISTOR_TOL); 318 if (ret) { 319 dev_err(dev, "Read resistor tolerance failed\n"); 320 return ret; 321 } 322 323 indio_dev->modes = INDIO_DIRECT_MODE; 324 indio_dev->info = &ad5110_info; 325 indio_dev->channels = ad5110_channels; 326 indio_dev->num_channels = ARRAY_SIZE(ad5110_channels); 327 indio_dev->name = client->name; 328 329 return devm_iio_device_register(dev, indio_dev); 330} 331 332static struct i2c_driver ad5110_driver = { 333 .driver = { 334 .name = "ad5110", 335 .of_match_table = ad5110_of_match, 336 }, 337 .probe_new = ad5110_probe, 338 .id_table = ad5110_id, 339}; 340module_i2c_driver(ad5110_driver); 341 342MODULE_AUTHOR("Mugilraj Dhavachelvan <dmugil2000@gmail.com>"); 343MODULE_DESCRIPTION("AD5110 digital potentiometer"); 344MODULE_LICENSE("GPL v2");