ti-ads8344.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * ADS8344 16-bit 8-Channel ADC driver
  4. *
  5. * Author: Gregory CLEMENT <gregory.clement@bootlin.com>
  6. *
  7. * Datasheet: https://www.ti.com/lit/ds/symlink/ads8344.pdf
  8. */
  9. #include <linux/delay.h>
  10. #include <linux/iio/buffer.h>
  11. #include <linux/iio/iio.h>
  12. #include <linux/module.h>
  13. #include <linux/regulator/consumer.h>
  14. #include <linux/spi/spi.h>
  15. #define ADS8344_START BIT(7)
  16. #define ADS8344_SINGLE_END BIT(2)
  17. #define ADS8344_CHANNEL(channel) ((channel) << 4)
  18. #define ADS8344_CLOCK_INTERNAL 0x2 /* PD1 = 1 and PD0 = 0 */
  19. struct ads8344 {
  20. struct spi_device *spi;
  21. struct regulator *reg;
  22. /*
  23. * Lock protecting access to adc->tx_buff and rx_buff,
  24. * especially from concurrent read on sysfs file.
  25. */
  26. struct mutex lock;
  27. u8 tx_buf ____cacheline_aligned;
  28. u8 rx_buf[3];
  29. };
  30. #define ADS8344_VOLTAGE_CHANNEL(chan, addr) \
  31. { \
  32. .type = IIO_VOLTAGE, \
  33. .indexed = 1, \
  34. .channel = chan, \
  35. .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
  36. .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
  37. .address = addr, \
  38. }
  39. #define ADS8344_VOLTAGE_CHANNEL_DIFF(chan1, chan2, addr) \
  40. { \
  41. .type = IIO_VOLTAGE, \
  42. .indexed = 1, \
  43. .channel = (chan1), \
  44. .channel2 = (chan2), \
  45. .differential = 1, \
  46. .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
  47. .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
  48. .address = addr, \
  49. }
  50. static const struct iio_chan_spec ads8344_channels[] = {
  51. ADS8344_VOLTAGE_CHANNEL(0, 0),
  52. ADS8344_VOLTAGE_CHANNEL(1, 4),
  53. ADS8344_VOLTAGE_CHANNEL(2, 1),
  54. ADS8344_VOLTAGE_CHANNEL(3, 5),
  55. ADS8344_VOLTAGE_CHANNEL(4, 2),
  56. ADS8344_VOLTAGE_CHANNEL(5, 6),
  57. ADS8344_VOLTAGE_CHANNEL(6, 3),
  58. ADS8344_VOLTAGE_CHANNEL(7, 7),
  59. ADS8344_VOLTAGE_CHANNEL_DIFF(0, 1, 8),
  60. ADS8344_VOLTAGE_CHANNEL_DIFF(2, 3, 9),
  61. ADS8344_VOLTAGE_CHANNEL_DIFF(4, 5, 10),
  62. ADS8344_VOLTAGE_CHANNEL_DIFF(6, 7, 11),
  63. ADS8344_VOLTAGE_CHANNEL_DIFF(1, 0, 12),
  64. ADS8344_VOLTAGE_CHANNEL_DIFF(3, 2, 13),
  65. ADS8344_VOLTAGE_CHANNEL_DIFF(5, 4, 14),
  66. ADS8344_VOLTAGE_CHANNEL_DIFF(7, 6, 15),
  67. };
  68. static int ads8344_adc_conversion(struct ads8344 *adc, int channel,
  69. bool differential)
  70. {
  71. struct spi_device *spi = adc->spi;
  72. int ret;
  73. adc->tx_buf = ADS8344_START;
  74. if (!differential)
  75. adc->tx_buf |= ADS8344_SINGLE_END;
  76. adc->tx_buf |= ADS8344_CHANNEL(channel);
  77. adc->tx_buf |= ADS8344_CLOCK_INTERNAL;
  78. ret = spi_write(spi, &adc->tx_buf, 1);
  79. if (ret)
  80. return ret;
  81. udelay(9);
  82. ret = spi_read(spi, adc->rx_buf, sizeof(adc->rx_buf));
  83. if (ret)
  84. return ret;
  85. return adc->rx_buf[0] << 9 | adc->rx_buf[1] << 1 | adc->rx_buf[2] >> 7;
  86. }
  87. static int ads8344_read_raw(struct iio_dev *iio,
  88. struct iio_chan_spec const *channel, int *value,
  89. int *shift, long mask)
  90. {
  91. struct ads8344 *adc = iio_priv(iio);
  92. switch (mask) {
  93. case IIO_CHAN_INFO_RAW:
  94. mutex_lock(&adc->lock);
  95. *value = ads8344_adc_conversion(adc, channel->address,
  96. channel->differential);
  97. mutex_unlock(&adc->lock);
  98. if (*value < 0)
  99. return *value;
  100. return IIO_VAL_INT;
  101. case IIO_CHAN_INFO_SCALE:
  102. *value = regulator_get_voltage(adc->reg);
  103. if (*value < 0)
  104. return *value;
  105. /* convert regulator output voltage to mV */
  106. *value /= 1000;
  107. *shift = 16;
  108. return IIO_VAL_FRACTIONAL_LOG2;
  109. default:
  110. return -EINVAL;
  111. }
  112. }
  113. static const struct iio_info ads8344_info = {
  114. .read_raw = ads8344_read_raw,
  115. };
  116. static int ads8344_probe(struct spi_device *spi)
  117. {
  118. struct iio_dev *indio_dev;
  119. struct ads8344 *adc;
  120. int ret;
  121. indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*adc));
  122. if (!indio_dev)
  123. return -ENOMEM;
  124. adc = iio_priv(indio_dev);
  125. adc->spi = spi;
  126. mutex_init(&adc->lock);
  127. indio_dev->name = dev_name(&spi->dev);
  128. indio_dev->info = &ads8344_info;
  129. indio_dev->modes = INDIO_DIRECT_MODE;
  130. indio_dev->channels = ads8344_channels;
  131. indio_dev->num_channels = ARRAY_SIZE(ads8344_channels);
  132. adc->reg = devm_regulator_get(&spi->dev, "vref");
  133. if (IS_ERR(adc->reg))
  134. return PTR_ERR(adc->reg);
  135. ret = regulator_enable(adc->reg);
  136. if (ret)
  137. return ret;
  138. spi_set_drvdata(spi, indio_dev);
  139. ret = iio_device_register(indio_dev);
  140. if (ret) {
  141. regulator_disable(adc->reg);
  142. return ret;
  143. }
  144. return 0;
  145. }
  146. static int ads8344_remove(struct spi_device *spi)
  147. {
  148. struct iio_dev *indio_dev = spi_get_drvdata(spi);
  149. struct ads8344 *adc = iio_priv(indio_dev);
  150. iio_device_unregister(indio_dev);
  151. regulator_disable(adc->reg);
  152. return 0;
  153. }
  154. static const struct of_device_id ads8344_of_match[] = {
  155. { .compatible = "ti,ads8344", },
  156. {}
  157. };
  158. MODULE_DEVICE_TABLE(of, ads8344_of_match);
  159. static struct spi_driver ads8344_driver = {
  160. .driver = {
  161. .name = "ads8344",
  162. .of_match_table = ads8344_of_match,
  163. },
  164. .probe = ads8344_probe,
  165. .remove = ads8344_remove,
  166. };
  167. module_spi_driver(ads8344_driver);
  168. MODULE_AUTHOR("Gregory CLEMENT <gregory.clement@bootlin.com>");
  169. MODULE_DESCRIPTION("ADS8344 driver");
  170. MODULE_LICENSE("GPL");