tsys01.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. /*
  2. * tsys01.c - Support for Measurement-Specialties tsys01 temperature sensor
  3. *
  4. * Copyright (c) 2015 Measurement-Specialties
  5. *
  6. * Licensed under the GPL-2.
  7. *
  8. * Datasheet:
  9. * http://www.meas-spec.com/downloads/TSYS01_Digital_Temperature_Sensor.pdf
  10. */
  11. #include <linux/iio/iio.h>
  12. #include <linux/iio/sysfs.h>
  13. #include <linux/device.h>
  14. #include <linux/mutex.h>
  15. #include <linux/module.h>
  16. #include <linux/init.h>
  17. #include <linux/kernel.h>
  18. #include <linux/stat.h>
  19. #include "../common/ms_sensors/ms_sensors_i2c.h"
  20. /* TSYS01 Commands */
  21. #define TSYS01_RESET 0x1E
  22. #define TSYS01_CONVERSION_START 0x48
  23. #define TSYS01_ADC_READ 0x00
  24. #define TSYS01_PROM_READ 0xA0
  25. #define TSYS01_PROM_WORDS_NB 8
  26. struct tsys01_dev {
  27. void *client;
  28. struct mutex lock; /* lock during conversion */
  29. int (*reset)(void *cli, u8 cmd, unsigned int delay);
  30. int (*convert_and_read)(void *cli, u8 conv, u8 rd,
  31. unsigned int delay, u32 *adc);
  32. int (*read_prom_word)(void *cli, int cmd, u16 *word);
  33. u16 prom[TSYS01_PROM_WORDS_NB];
  34. };
  35. /* Multiplication coefficients for temperature computation */
  36. static const int coeff_mul[] = { -1500000, 1000000, -2000000,
  37. 4000000, -2000000 };
  38. static int tsys01_read_temperature(struct iio_dev *indio_dev,
  39. s32 *temperature)
  40. {
  41. int ret, i;
  42. u32 adc;
  43. s64 temp = 0;
  44. struct tsys01_dev *dev_data = iio_priv(indio_dev);
  45. mutex_lock(&dev_data->lock);
  46. ret = dev_data->convert_and_read(dev_data->client,
  47. TSYS01_CONVERSION_START,
  48. TSYS01_ADC_READ, 9000, &adc);
  49. mutex_unlock(&dev_data->lock);
  50. if (ret)
  51. return ret;
  52. adc >>= 8;
  53. /* Temperature algorithm */
  54. for (i = 4; i > 0; i--) {
  55. temp += coeff_mul[i] *
  56. (s64)dev_data->prom[5 - i];
  57. temp *= (s64)adc;
  58. temp = div64_s64(temp, 100000);
  59. }
  60. temp *= 10;
  61. temp += coeff_mul[0] * (s64)dev_data->prom[5];
  62. temp = div64_s64(temp, 100000);
  63. *temperature = temp;
  64. return 0;
  65. }
  66. static int tsys01_read_raw(struct iio_dev *indio_dev,
  67. struct iio_chan_spec const *channel, int *val,
  68. int *val2, long mask)
  69. {
  70. int ret;
  71. s32 temperature;
  72. switch (mask) {
  73. case IIO_CHAN_INFO_PROCESSED:
  74. switch (channel->type) {
  75. case IIO_TEMP: /* in milli °C */
  76. ret = tsys01_read_temperature(indio_dev, &temperature);
  77. if (ret)
  78. return ret;
  79. *val = temperature;
  80. return IIO_VAL_INT;
  81. default:
  82. return -EINVAL;
  83. }
  84. default:
  85. return -EINVAL;
  86. }
  87. }
  88. static const struct iio_chan_spec tsys01_channels[] = {
  89. {
  90. .type = IIO_TEMP,
  91. .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_PROCESSED),
  92. }
  93. };
  94. static const struct iio_info tsys01_info = {
  95. .read_raw = tsys01_read_raw,
  96. .driver_module = THIS_MODULE,
  97. };
  98. static bool tsys01_crc_valid(u16 *n_prom)
  99. {
  100. u8 cnt;
  101. u8 sum = 0;
  102. for (cnt = 0; cnt < TSYS01_PROM_WORDS_NB; cnt++)
  103. sum += ((n_prom[0] >> 8) + (n_prom[0] & 0xFF));
  104. return (sum == 0);
  105. }
  106. static int tsys01_read_prom(struct iio_dev *indio_dev)
  107. {
  108. int i, ret;
  109. struct tsys01_dev *dev_data = iio_priv(indio_dev);
  110. char buf[7 * TSYS01_PROM_WORDS_NB + 1];
  111. char *ptr = buf;
  112. for (i = 0; i < TSYS01_PROM_WORDS_NB; i++) {
  113. ret = dev_data->read_prom_word(dev_data->client,
  114. TSYS01_PROM_READ + (i << 1),
  115. &dev_data->prom[i]);
  116. if (ret)
  117. return ret;
  118. ret = sprintf(ptr, "0x%04x ", dev_data->prom[i]);
  119. ptr += ret;
  120. }
  121. if (!tsys01_crc_valid(dev_data->prom)) {
  122. dev_err(&indio_dev->dev, "prom crc check error\n");
  123. return -ENODEV;
  124. }
  125. *ptr = 0;
  126. dev_info(&indio_dev->dev, "PROM coefficients : %s\n", buf);
  127. return 0;
  128. }
  129. static int tsys01_probe(struct iio_dev *indio_dev, struct device *dev)
  130. {
  131. int ret;
  132. struct tsys01_dev *dev_data = iio_priv(indio_dev);
  133. mutex_init(&dev_data->lock);
  134. indio_dev->info = &tsys01_info;
  135. indio_dev->name = dev->driver->name;
  136. indio_dev->dev.parent = dev;
  137. indio_dev->modes = INDIO_DIRECT_MODE;
  138. indio_dev->channels = tsys01_channels;
  139. indio_dev->num_channels = ARRAY_SIZE(tsys01_channels);
  140. ret = dev_data->reset(dev_data->client, TSYS01_RESET, 3000);
  141. if (ret)
  142. return ret;
  143. ret = tsys01_read_prom(indio_dev);
  144. if (ret)
  145. return ret;
  146. return devm_iio_device_register(dev, indio_dev);
  147. }
  148. static int tsys01_i2c_probe(struct i2c_client *client,
  149. const struct i2c_device_id *id)
  150. {
  151. struct tsys01_dev *dev_data;
  152. struct iio_dev *indio_dev;
  153. if (!i2c_check_functionality(client->adapter,
  154. I2C_FUNC_SMBUS_WORD_DATA |
  155. I2C_FUNC_SMBUS_WRITE_BYTE |
  156. I2C_FUNC_SMBUS_READ_I2C_BLOCK)) {
  157. dev_err(&client->dev,
  158. "Adapter does not support some i2c transaction\n");
  159. return -EOPNOTSUPP;
  160. }
  161. indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*dev_data));
  162. if (!indio_dev)
  163. return -ENOMEM;
  164. dev_data = iio_priv(indio_dev);
  165. dev_data->client = client;
  166. dev_data->reset = ms_sensors_reset;
  167. dev_data->read_prom_word = ms_sensors_read_prom_word;
  168. dev_data->convert_and_read = ms_sensors_convert_and_read;
  169. i2c_set_clientdata(client, indio_dev);
  170. return tsys01_probe(indio_dev, &client->dev);
  171. }
  172. static const struct i2c_device_id tsys01_id[] = {
  173. {"tsys01", 0},
  174. {}
  175. };
  176. MODULE_DEVICE_TABLE(i2c, tsys01_id);
  177. static struct i2c_driver tsys01_driver = {
  178. .probe = tsys01_i2c_probe,
  179. .id_table = tsys01_id,
  180. .driver = {
  181. .name = "tsys01",
  182. },
  183. };
  184. module_i2c_driver(tsys01_driver);
  185. MODULE_DESCRIPTION("Measurement-Specialties tsys01 temperature driver");
  186. MODULE_AUTHOR("William Markezana <william.markezana@meas-spec.com>");
  187. MODULE_AUTHOR("Ludovic Tancerel <ludovic.tancerel@maplehightech.com>");
  188. MODULE_LICENSE("GPL v2");