atlas-ezo-sensor.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * atlas-ezo-sensor.c - Support for Atlas Scientific EZO sensors
  4. *
  5. * Copyright (C) 2020 Konsulko Group
  6. * Author: Matt Ranostay <matt.ranostay@konsulko.com>
  7. */
  8. #include <linux/module.h>
  9. #include <linux/init.h>
  10. #include <linux/delay.h>
  11. #include <linux/mutex.h>
  12. #include <linux/err.h>
  13. #include <linux/i2c.h>
  14. #include <linux/of_device.h>
  15. #include <linux/iio/iio.h>
  16. #define ATLAS_EZO_DRV_NAME "atlas-ezo-sensor"
  17. #define ATLAS_INT_TIME_IN_MS 950
  18. #define ATLAS_INT_HUM_TIME_IN_MS 350
  19. enum {
  20. ATLAS_CO2_EZO,
  21. ATLAS_O2_EZO,
  22. ATLAS_HUM_EZO,
  23. };
  24. struct atlas_ezo_device {
  25. const struct iio_chan_spec *channels;
  26. int num_channels;
  27. int delay;
  28. };
  29. struct atlas_ezo_data {
  30. struct i2c_client *client;
  31. struct atlas_ezo_device *chip;
  32. /* lock to avoid multiple concurrent read calls */
  33. struct mutex lock;
  34. u8 buffer[8];
  35. };
  36. #define ATLAS_CONCENTRATION_CHANNEL(_modifier) \
  37. { \
  38. .type = IIO_CONCENTRATION, \
  39. .modified = 1,\
  40. .channel2 = _modifier, \
  41. .info_mask_separate = \
  42. BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), \
  43. .scan_index = 0, \
  44. .scan_type = { \
  45. .sign = 'u', \
  46. .realbits = 32, \
  47. .storagebits = 32, \
  48. .endianness = IIO_CPU, \
  49. }, \
  50. }
  51. static const struct iio_chan_spec atlas_co2_ezo_channels[] = {
  52. ATLAS_CONCENTRATION_CHANNEL(IIO_MOD_CO2),
  53. };
  54. static const struct iio_chan_spec atlas_o2_ezo_channels[] = {
  55. ATLAS_CONCENTRATION_CHANNEL(IIO_MOD_O2),
  56. };
  57. static const struct iio_chan_spec atlas_hum_ezo_channels[] = {
  58. {
  59. .type = IIO_HUMIDITYRELATIVE,
  60. .info_mask_separate =
  61. BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
  62. .scan_index = 0,
  63. .scan_type = {
  64. .sign = 'u',
  65. .realbits = 32,
  66. .storagebits = 32,
  67. .endianness = IIO_CPU,
  68. },
  69. },
  70. };
  71. static struct atlas_ezo_device atlas_ezo_devices[] = {
  72. [ATLAS_CO2_EZO] = {
  73. .channels = atlas_co2_ezo_channels,
  74. .num_channels = 1,
  75. .delay = ATLAS_INT_TIME_IN_MS,
  76. },
  77. [ATLAS_O2_EZO] = {
  78. .channels = atlas_o2_ezo_channels,
  79. .num_channels = 1,
  80. .delay = ATLAS_INT_TIME_IN_MS,
  81. },
  82. [ATLAS_HUM_EZO] = {
  83. .channels = atlas_hum_ezo_channels,
  84. .num_channels = 1,
  85. .delay = ATLAS_INT_HUM_TIME_IN_MS,
  86. },
  87. };
  88. static void atlas_ezo_sanitize(char *buf)
  89. {
  90. char *ptr = strchr(buf, '.');
  91. if (!ptr)
  92. return;
  93. memmove(ptr, ptr + 1, strlen(ptr));
  94. }
  95. static int atlas_ezo_read_raw(struct iio_dev *indio_dev,
  96. struct iio_chan_spec const *chan,
  97. int *val, int *val2, long mask)
  98. {
  99. struct atlas_ezo_data *data = iio_priv(indio_dev);
  100. struct i2c_client *client = data->client;
  101. if (chan->type != IIO_CONCENTRATION)
  102. return -EINVAL;
  103. switch (mask) {
  104. case IIO_CHAN_INFO_RAW: {
  105. int ret;
  106. long tmp;
  107. mutex_lock(&data->lock);
  108. tmp = i2c_smbus_write_byte(client, 'R');
  109. if (tmp < 0) {
  110. mutex_unlock(&data->lock);
  111. return tmp;
  112. }
  113. msleep(data->chip->delay);
  114. tmp = i2c_master_recv(client, data->buffer, sizeof(data->buffer));
  115. if (tmp < 0 || data->buffer[0] != 1) {
  116. mutex_unlock(&data->lock);
  117. return -EBUSY;
  118. }
  119. /* removing floating point for fixed number representation */
  120. atlas_ezo_sanitize(data->buffer + 2);
  121. ret = kstrtol(data->buffer + 1, 10, &tmp);
  122. *val = tmp;
  123. mutex_unlock(&data->lock);
  124. return ret ? ret : IIO_VAL_INT;
  125. }
  126. case IIO_CHAN_INFO_SCALE:
  127. switch (chan->type) {
  128. case IIO_HUMIDITYRELATIVE:
  129. *val = 10;
  130. return IIO_VAL_INT;
  131. case IIO_CONCENTRATION:
  132. break;
  133. default:
  134. return -EINVAL;
  135. }
  136. /* IIO_CONCENTRATION modifiers */
  137. switch (chan->channel2) {
  138. case IIO_MOD_CO2:
  139. *val = 0;
  140. *val2 = 100; /* 0.0001 */
  141. return IIO_VAL_INT_PLUS_MICRO;
  142. case IIO_MOD_O2:
  143. *val = 100;
  144. return IIO_VAL_INT;
  145. }
  146. return -EINVAL;
  147. }
  148. return 0;
  149. }
  150. static const struct iio_info atlas_info = {
  151. .read_raw = atlas_ezo_read_raw,
  152. };
  153. static const struct i2c_device_id atlas_ezo_id[] = {
  154. { "atlas-co2-ezo", ATLAS_CO2_EZO },
  155. { "atlas-o2-ezo", ATLAS_O2_EZO },
  156. { "atlas-hum-ezo", ATLAS_HUM_EZO },
  157. {}
  158. };
  159. MODULE_DEVICE_TABLE(i2c, atlas_ezo_id);
  160. static const struct of_device_id atlas_ezo_dt_ids[] = {
  161. { .compatible = "atlas,co2-ezo", .data = (void *)ATLAS_CO2_EZO, },
  162. { .compatible = "atlas,o2-ezo", .data = (void *)ATLAS_O2_EZO, },
  163. { .compatible = "atlas,hum-ezo", .data = (void *)ATLAS_HUM_EZO, },
  164. {}
  165. };
  166. MODULE_DEVICE_TABLE(of, atlas_ezo_dt_ids);
  167. static int atlas_ezo_probe(struct i2c_client *client,
  168. const struct i2c_device_id *id)
  169. {
  170. struct atlas_ezo_data *data;
  171. struct atlas_ezo_device *chip;
  172. const struct of_device_id *of_id;
  173. struct iio_dev *indio_dev;
  174. indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
  175. if (!indio_dev)
  176. return -ENOMEM;
  177. of_id = of_match_device(atlas_ezo_dt_ids, &client->dev);
  178. if (!of_id)
  179. chip = &atlas_ezo_devices[id->driver_data];
  180. else
  181. chip = &atlas_ezo_devices[(unsigned long)of_id->data];
  182. indio_dev->info = &atlas_info;
  183. indio_dev->name = ATLAS_EZO_DRV_NAME;
  184. indio_dev->channels = chip->channels;
  185. indio_dev->num_channels = chip->num_channels;
  186. indio_dev->modes = INDIO_DIRECT_MODE;
  187. data = iio_priv(indio_dev);
  188. data->client = client;
  189. data->chip = chip;
  190. mutex_init(&data->lock);
  191. return devm_iio_device_register(&client->dev, indio_dev);
  192. };
  193. static struct i2c_driver atlas_ezo_driver = {
  194. .driver = {
  195. .name = ATLAS_EZO_DRV_NAME,
  196. .of_match_table = atlas_ezo_dt_ids,
  197. },
  198. .probe = atlas_ezo_probe,
  199. .id_table = atlas_ezo_id,
  200. };
  201. module_i2c_driver(atlas_ezo_driver);
  202. MODULE_AUTHOR("Matt Ranostay <matt.ranostay@konsulko.com>");
  203. MODULE_DESCRIPTION("Atlas Scientific EZO sensors");
  204. MODULE_LICENSE("GPL");