ad5110.c 7.8 KB

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