ad5446.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * AD5446 CORE DAC driver
  4. *
  5. * Copyright 2010 Analog Devices Inc.
  6. */
  7. #include <linux/array_size.h>
  8. #include <linux/cleanup.h>
  9. #include <linux/device.h>
  10. #include <linux/err.h>
  11. #include <linux/export.h>
  12. #include <linux/iio/iio.h>
  13. #include <linux/kstrtox.h>
  14. #include <linux/module.h>
  15. #include <linux/mutex.h>
  16. #include <linux/regulator/consumer.h>
  17. #include <linux/sysfs.h>
  18. #include "ad5446.h"
  19. #define MODE_PWRDWN_1k 0x1
  20. #define MODE_PWRDWN_100k 0x2
  21. #define MODE_PWRDWN_TRISTATE 0x3
  22. static const char * const ad5446_powerdown_modes[] = {
  23. "1kohm_to_gnd", "100kohm_to_gnd", "three_state"
  24. };
  25. static int ad5446_set_powerdown_mode(struct iio_dev *indio_dev,
  26. const struct iio_chan_spec *chan,
  27. unsigned int mode)
  28. {
  29. struct ad5446_state *st = iio_priv(indio_dev);
  30. st->pwr_down_mode = mode + 1;
  31. return 0;
  32. }
  33. static int ad5446_get_powerdown_mode(struct iio_dev *indio_dev,
  34. const struct iio_chan_spec *chan)
  35. {
  36. struct ad5446_state *st = iio_priv(indio_dev);
  37. return st->pwr_down_mode - 1;
  38. }
  39. static const struct iio_enum ad5446_powerdown_mode_enum = {
  40. .items = ad5446_powerdown_modes,
  41. .num_items = ARRAY_SIZE(ad5446_powerdown_modes),
  42. .get = ad5446_get_powerdown_mode,
  43. .set = ad5446_set_powerdown_mode,
  44. };
  45. static ssize_t ad5446_read_dac_powerdown(struct iio_dev *indio_dev,
  46. uintptr_t private,
  47. const struct iio_chan_spec *chan,
  48. char *buf)
  49. {
  50. struct ad5446_state *st = iio_priv(indio_dev);
  51. return sysfs_emit(buf, "%d\n", st->pwr_down);
  52. }
  53. static ssize_t ad5446_write_dac_powerdown(struct iio_dev *indio_dev,
  54. uintptr_t private,
  55. const struct iio_chan_spec *chan,
  56. const char *buf, size_t len)
  57. {
  58. struct ad5446_state *st = iio_priv(indio_dev);
  59. unsigned int shift;
  60. unsigned int val;
  61. bool powerdown;
  62. int ret;
  63. ret = kstrtobool(buf, &powerdown);
  64. if (ret)
  65. return ret;
  66. guard(mutex)(&st->lock);
  67. st->pwr_down = powerdown;
  68. if (st->pwr_down) {
  69. shift = chan->scan_type.realbits + chan->scan_type.shift;
  70. val = st->pwr_down_mode << shift;
  71. } else {
  72. val = st->cached_val;
  73. }
  74. ret = st->chip_info->write(st, val);
  75. if (ret)
  76. return ret;
  77. return len;
  78. }
  79. const struct iio_chan_spec_ext_info ad5446_ext_info_powerdown[] = {
  80. {
  81. .name = "powerdown",
  82. .read = ad5446_read_dac_powerdown,
  83. .write = ad5446_write_dac_powerdown,
  84. .shared = IIO_SEPARATE,
  85. },
  86. IIO_ENUM("powerdown_mode", IIO_SEPARATE, &ad5446_powerdown_mode_enum),
  87. IIO_ENUM_AVAILABLE("powerdown_mode", IIO_SHARED_BY_TYPE, &ad5446_powerdown_mode_enum),
  88. { }
  89. };
  90. EXPORT_SYMBOL_NS_GPL(ad5446_ext_info_powerdown, "IIO_AD5446");
  91. static int ad5446_read_raw(struct iio_dev *indio_dev,
  92. struct iio_chan_spec const *chan,
  93. int *val,
  94. int *val2,
  95. long m)
  96. {
  97. struct ad5446_state *st = iio_priv(indio_dev);
  98. switch (m) {
  99. case IIO_CHAN_INFO_RAW:
  100. *val = st->cached_val >> chan->scan_type.shift;
  101. return IIO_VAL_INT;
  102. case IIO_CHAN_INFO_SCALE:
  103. *val = st->vref_mv;
  104. *val2 = chan->scan_type.realbits;
  105. return IIO_VAL_FRACTIONAL_LOG2;
  106. }
  107. return -EINVAL;
  108. }
  109. static int ad5446_write_dac_raw(struct iio_dev *indio_dev,
  110. const struct iio_chan_spec *chan,
  111. int val)
  112. {
  113. struct ad5446_state *st = iio_priv(indio_dev);
  114. if (val >= (1 << chan->scan_type.realbits) || val < 0)
  115. return -EINVAL;
  116. val <<= chan->scan_type.shift;
  117. guard(mutex)(&st->lock);
  118. st->cached_val = val;
  119. if (st->pwr_down)
  120. return 0;
  121. return st->chip_info->write(st, val);
  122. }
  123. static int ad5446_write_raw(struct iio_dev *indio_dev,
  124. struct iio_chan_spec const *chan, int val,
  125. int val2, long mask)
  126. {
  127. switch (mask) {
  128. case IIO_CHAN_INFO_RAW:
  129. return ad5446_write_dac_raw(indio_dev, chan, val);
  130. default:
  131. return -EINVAL;
  132. }
  133. }
  134. static const struct iio_info ad5446_info = {
  135. .read_raw = ad5446_read_raw,
  136. .write_raw = ad5446_write_raw,
  137. };
  138. int ad5446_probe(struct device *dev, const char *name,
  139. const struct ad5446_chip_info *chip_info)
  140. {
  141. struct ad5446_state *st;
  142. struct iio_dev *indio_dev;
  143. int ret;
  144. indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
  145. if (!indio_dev)
  146. return -ENOMEM;
  147. st = iio_priv(indio_dev);
  148. st->chip_info = chip_info;
  149. st->dev = dev;
  150. indio_dev->name = name;
  151. indio_dev->info = &ad5446_info;
  152. indio_dev->modes = INDIO_DIRECT_MODE;
  153. indio_dev->channels = &st->chip_info->channel;
  154. indio_dev->num_channels = 1;
  155. ret = devm_mutex_init(dev, &st->lock);
  156. if (ret)
  157. return ret;
  158. st->pwr_down_mode = MODE_PWRDWN_1k;
  159. ret = devm_regulator_get_enable_read_voltage(dev, "vcc");
  160. if (ret < 0 && ret != -ENODEV)
  161. return ret;
  162. if (ret == -ENODEV) {
  163. if (!chip_info->int_vref_mv)
  164. return dev_err_probe(dev, ret,
  165. "reference voltage unspecified\n");
  166. st->vref_mv = chip_info->int_vref_mv;
  167. } else {
  168. st->vref_mv = ret / 1000;
  169. }
  170. return devm_iio_device_register(dev, indio_dev);
  171. }
  172. EXPORT_SYMBOL_NS_GPL(ad5446_probe, "IIO_AD5446");
  173. MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>");
  174. MODULE_DESCRIPTION("Analog Devices CORE AD5446 DAC and similar devices");
  175. MODULE_LICENSE("GPL v2");