ad5272.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Analog Devices AD5272 digital potentiometer driver
  4. * Copyright (C) 2018 Phil Reid <preid@electromag.com.au>
  5. *
  6. * Datasheet: http://www.analog.com/media/en/technical-documentation/data-sheets/AD5272_5274.pdf
  7. *
  8. * DEVID #Wipers #Positions Resistor Opts (kOhm) i2c address
  9. * ad5272 1 1024 20, 50, 100 01011xx
  10. * ad5274 1 256 20, 100 01011xx
  11. */
  12. #include <linux/delay.h>
  13. #include <linux/gpio/consumer.h>
  14. #include <linux/i2c.h>
  15. #include <linux/iio/iio.h>
  16. #include <linux/module.h>
  17. #define AD5272_RDAC_WR 1
  18. #define AD5272_RDAC_RD 2
  19. #define AD5272_RESET 4
  20. #define AD5272_CTL 7
  21. #define AD5272_RDAC_WR_EN BIT(1)
  22. struct ad5272_cfg {
  23. int max_pos;
  24. int kohms;
  25. int shift;
  26. };
  27. enum ad5272_type {
  28. AD5272_020,
  29. AD5272_050,
  30. AD5272_100,
  31. AD5274_020,
  32. AD5274_100,
  33. };
  34. static const struct ad5272_cfg ad5272_cfg[] = {
  35. [AD5272_020] = { .max_pos = 1024, .kohms = 20 },
  36. [AD5272_050] = { .max_pos = 1024, .kohms = 50 },
  37. [AD5272_100] = { .max_pos = 1024, .kohms = 100 },
  38. [AD5274_020] = { .max_pos = 256, .kohms = 20, .shift = 2 },
  39. [AD5274_100] = { .max_pos = 256, .kohms = 100, .shift = 2 },
  40. };
  41. struct ad5272_data {
  42. struct i2c_client *client;
  43. struct mutex lock;
  44. const struct ad5272_cfg *cfg;
  45. u8 buf[2] ____cacheline_aligned;
  46. };
  47. static const struct iio_chan_spec ad5272_channel = {
  48. .type = IIO_RESISTANCE,
  49. .output = 1,
  50. .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
  51. .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
  52. };
  53. static int ad5272_write(struct ad5272_data *data, int reg, int val)
  54. {
  55. int ret;
  56. data->buf[0] = (reg << 2) | ((val >> 8) & 0x3);
  57. data->buf[1] = (u8)val;
  58. mutex_lock(&data->lock);
  59. ret = i2c_master_send(data->client, data->buf, sizeof(data->buf));
  60. mutex_unlock(&data->lock);
  61. return ret < 0 ? ret : 0;
  62. }
  63. static int ad5272_read(struct ad5272_data *data, int reg, int *val)
  64. {
  65. int ret;
  66. data->buf[0] = reg << 2;
  67. data->buf[1] = 0;
  68. mutex_lock(&data->lock);
  69. ret = i2c_master_send(data->client, data->buf, sizeof(data->buf));
  70. if (ret < 0)
  71. goto error;
  72. ret = i2c_master_recv(data->client, data->buf, sizeof(data->buf));
  73. if (ret < 0)
  74. goto error;
  75. *val = ((data->buf[0] & 0x3) << 8) | data->buf[1];
  76. ret = 0;
  77. error:
  78. mutex_unlock(&data->lock);
  79. return ret;
  80. }
  81. static int ad5272_read_raw(struct iio_dev *indio_dev,
  82. struct iio_chan_spec const *chan,
  83. int *val, int *val2, long mask)
  84. {
  85. struct ad5272_data *data = iio_priv(indio_dev);
  86. int ret;
  87. switch (mask) {
  88. case IIO_CHAN_INFO_RAW: {
  89. ret = ad5272_read(data, AD5272_RDAC_RD, val);
  90. *val = *val >> data->cfg->shift;
  91. return ret ? ret : IIO_VAL_INT;
  92. }
  93. case IIO_CHAN_INFO_SCALE:
  94. *val = 1000 * data->cfg->kohms;
  95. *val2 = data->cfg->max_pos;
  96. return IIO_VAL_FRACTIONAL;
  97. }
  98. return -EINVAL;
  99. }
  100. static int ad5272_write_raw(struct iio_dev *indio_dev,
  101. struct iio_chan_spec const *chan,
  102. int val, int val2, long mask)
  103. {
  104. struct ad5272_data *data = iio_priv(indio_dev);
  105. if (mask != IIO_CHAN_INFO_RAW)
  106. return -EINVAL;
  107. if (val >= data->cfg->max_pos || val < 0 || val2)
  108. return -EINVAL;
  109. return ad5272_write(data, AD5272_RDAC_WR, val << data->cfg->shift);
  110. }
  111. static const struct iio_info ad5272_info = {
  112. .read_raw = ad5272_read_raw,
  113. .write_raw = ad5272_write_raw,
  114. };
  115. static int ad5272_reset(struct ad5272_data *data)
  116. {
  117. struct gpio_desc *reset_gpio;
  118. reset_gpio = devm_gpiod_get_optional(&data->client->dev, "reset",
  119. GPIOD_OUT_LOW);
  120. if (IS_ERR(reset_gpio))
  121. return PTR_ERR(reset_gpio);
  122. if (reset_gpio) {
  123. udelay(1);
  124. gpiod_set_value(reset_gpio, 1);
  125. } else {
  126. ad5272_write(data, AD5272_RESET, 0);
  127. }
  128. usleep_range(1000, 2000);
  129. return 0;
  130. }
  131. static int ad5272_probe(struct i2c_client *client,
  132. const struct i2c_device_id *id)
  133. {
  134. struct device *dev = &client->dev;
  135. struct iio_dev *indio_dev;
  136. struct ad5272_data *data;
  137. int ret;
  138. indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
  139. if (!indio_dev)
  140. return -ENOMEM;
  141. i2c_set_clientdata(client, indio_dev);
  142. data = iio_priv(indio_dev);
  143. data->client = client;
  144. mutex_init(&data->lock);
  145. data->cfg = &ad5272_cfg[id->driver_data];
  146. ret = ad5272_reset(data);
  147. if (ret)
  148. return ret;
  149. ret = ad5272_write(data, AD5272_CTL, AD5272_RDAC_WR_EN);
  150. if (ret < 0)
  151. return -ENODEV;
  152. indio_dev->dev.parent = dev;
  153. indio_dev->info = &ad5272_info;
  154. indio_dev->channels = &ad5272_channel;
  155. indio_dev->num_channels = 1;
  156. indio_dev->name = client->name;
  157. return devm_iio_device_register(dev, indio_dev);
  158. }
  159. #if defined(CONFIG_OF)
  160. static const struct of_device_id ad5272_dt_ids[] = {
  161. { .compatible = "adi,ad5272-020", .data = (void *)AD5272_020 },
  162. { .compatible = "adi,ad5272-050", .data = (void *)AD5272_050 },
  163. { .compatible = "adi,ad5272-100", .data = (void *)AD5272_100 },
  164. { .compatible = "adi,ad5274-020", .data = (void *)AD5274_020 },
  165. { .compatible = "adi,ad5274-100", .data = (void *)AD5274_100 },
  166. {}
  167. };
  168. MODULE_DEVICE_TABLE(of, ad5272_dt_ids);
  169. #endif /* CONFIG_OF */
  170. static const struct i2c_device_id ad5272_id[] = {
  171. { "ad5272-020", AD5272_020 },
  172. { "ad5272-050", AD5272_050 },
  173. { "ad5272-100", AD5272_100 },
  174. { "ad5274-020", AD5274_020 },
  175. { "ad5274-100", AD5274_100 },
  176. {}
  177. };
  178. MODULE_DEVICE_TABLE(i2c, ad5272_id);
  179. static struct i2c_driver ad5272_driver = {
  180. .driver = {
  181. .name = "ad5272",
  182. .of_match_table = of_match_ptr(ad5272_dt_ids),
  183. },
  184. .probe = ad5272_probe,
  185. .id_table = ad5272_id,
  186. };
  187. module_i2c_driver(ad5272_driver);
  188. MODULE_AUTHOR("Phil Reid <preid@eletromag.com.au>");
  189. MODULE_DESCRIPTION("AD5272 digital potentiometer");
  190. MODULE_LICENSE("GPL v2");