sps30_serial.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Sensirion SPS30 particulate matter sensor serial driver
  4. *
  5. * Copyright (c) 2021 Tomasz Duszynski <[email protected]>
  6. */
  7. #include <linux/completion.h>
  8. #include <linux/device.h>
  9. #include <linux/errno.h>
  10. #include <linux/iio/iio.h>
  11. #include <linux/minmax.h>
  12. #include <linux/mod_devicetable.h>
  13. #include <linux/module.h>
  14. #include <linux/serdev.h>
  15. #include <linux/types.h>
  16. #include "sps30.h"
  17. #define SPS30_SERIAL_DEV_NAME "sps30"
  18. #define SPS30_SERIAL_SOF_EOF 0x7e
  19. #define SPS30_SERIAL_TIMEOUT msecs_to_jiffies(20)
  20. #define SPS30_SERIAL_MAX_BUF_SIZE 263
  21. #define SPS30_SERIAL_ESCAPE_CHAR 0x7d
  22. #define SPS30_SERIAL_FRAME_MIN_SIZE 7
  23. #define SPS30_SERIAL_FRAME_ADR_OFFSET 1
  24. #define SPS30_SERIAL_FRAME_CMD_OFFSET 2
  25. #define SPS30_SERIAL_FRAME_MOSI_LEN_OFFSET 3
  26. #define SPS30_SERIAL_FRAME_MISO_STATE_OFFSET 3
  27. #define SPS30_SERIAL_FRAME_MISO_LEN_OFFSET 4
  28. #define SPS30_SERIAL_FRAME_MISO_DATA_OFFSET 5
  29. #define SPS30_SERIAL_START_MEAS 0x00
  30. #define SPS30_SERIAL_STOP_MEAS 0x01
  31. #define SPS30_SERIAL_READ_MEAS 0x03
  32. #define SPS30_SERIAL_RESET 0xd3
  33. #define SPS30_SERIAL_CLEAN_FAN 0x56
  34. #define SPS30_SERIAL_PERIOD 0x80
  35. #define SPS30_SERIAL_DEV_INFO 0xd0
  36. #define SPS30_SERIAL_READ_VERSION 0xd1
  37. struct sps30_serial_priv {
  38. struct completion new_frame;
  39. unsigned char buf[SPS30_SERIAL_MAX_BUF_SIZE];
  40. size_t num;
  41. bool escaped;
  42. bool done;
  43. };
  44. static int sps30_serial_xfer(struct sps30_state *state, const unsigned char *buf, size_t size)
  45. {
  46. struct serdev_device *serdev = to_serdev_device(state->dev);
  47. struct sps30_serial_priv *priv = state->priv;
  48. int ret;
  49. priv->num = 0;
  50. priv->escaped = false;
  51. priv->done = false;
  52. ret = serdev_device_write(serdev, buf, size, SPS30_SERIAL_TIMEOUT);
  53. if (ret < 0)
  54. return ret;
  55. if (ret != size)
  56. return -EIO;
  57. ret = wait_for_completion_interruptible_timeout(&priv->new_frame, SPS30_SERIAL_TIMEOUT);
  58. if (ret < 0)
  59. return ret;
  60. if (!ret)
  61. return -ETIMEDOUT;
  62. return 0;
  63. }
  64. static const struct {
  65. unsigned char byte;
  66. unsigned char byte2;
  67. } sps30_serial_bytes[] = {
  68. { 0x11, 0x31 },
  69. { 0x13, 0x33 },
  70. { 0x7e, 0x5e },
  71. { 0x7d, 0x5d },
  72. };
  73. static int sps30_serial_put_byte(unsigned char *buf, unsigned char byte)
  74. {
  75. int i;
  76. for (i = 0; i < ARRAY_SIZE(sps30_serial_bytes); i++) {
  77. if (sps30_serial_bytes[i].byte != byte)
  78. continue;
  79. buf[0] = SPS30_SERIAL_ESCAPE_CHAR;
  80. buf[1] = sps30_serial_bytes[i].byte2;
  81. return 2;
  82. }
  83. buf[0] = byte;
  84. return 1;
  85. }
  86. static char sps30_serial_get_byte(bool escaped, unsigned char byte2)
  87. {
  88. int i;
  89. if (!escaped)
  90. return byte2;
  91. for (i = 0; i < ARRAY_SIZE(sps30_serial_bytes); i++) {
  92. if (sps30_serial_bytes[i].byte2 != byte2)
  93. continue;
  94. return sps30_serial_bytes[i].byte;
  95. }
  96. return 0;
  97. }
  98. static unsigned char sps30_serial_calc_chksum(const unsigned char *buf, size_t num)
  99. {
  100. unsigned int chksum = 0;
  101. size_t i;
  102. for (i = 0; i < num; i++)
  103. chksum += buf[i];
  104. return ~chksum;
  105. }
  106. static int sps30_serial_prep_frame(unsigned char *buf, unsigned char cmd,
  107. const unsigned char *arg, size_t arg_size)
  108. {
  109. unsigned char chksum;
  110. int num = 0;
  111. size_t i;
  112. buf[num++] = SPS30_SERIAL_SOF_EOF;
  113. buf[num++] = 0;
  114. num += sps30_serial_put_byte(buf + num, cmd);
  115. num += sps30_serial_put_byte(buf + num, arg_size);
  116. for (i = 0; i < arg_size; i++)
  117. num += sps30_serial_put_byte(buf + num, arg[i]);
  118. /* SOF isn't checksummed */
  119. chksum = sps30_serial_calc_chksum(buf + 1, num - 1);
  120. num += sps30_serial_put_byte(buf + num, chksum);
  121. buf[num++] = SPS30_SERIAL_SOF_EOF;
  122. return num;
  123. }
  124. static bool sps30_serial_frame_valid(struct sps30_state *state, const unsigned char *buf)
  125. {
  126. struct sps30_serial_priv *priv = state->priv;
  127. unsigned char chksum;
  128. if ((priv->num < SPS30_SERIAL_FRAME_MIN_SIZE) ||
  129. (priv->num != SPS30_SERIAL_FRAME_MIN_SIZE +
  130. priv->buf[SPS30_SERIAL_FRAME_MISO_LEN_OFFSET])) {
  131. dev_err(state->dev, "frame has invalid number of bytes\n");
  132. return false;
  133. }
  134. if ((priv->buf[SPS30_SERIAL_FRAME_ADR_OFFSET] != buf[SPS30_SERIAL_FRAME_ADR_OFFSET]) ||
  135. (priv->buf[SPS30_SERIAL_FRAME_CMD_OFFSET] != buf[SPS30_SERIAL_FRAME_CMD_OFFSET])) {
  136. dev_err(state->dev, "frame has wrong ADR and CMD bytes\n");
  137. return false;
  138. }
  139. if (priv->buf[SPS30_SERIAL_FRAME_MISO_STATE_OFFSET]) {
  140. dev_err(state->dev, "frame with non-zero state received (0x%02x)\n",
  141. priv->buf[SPS30_SERIAL_FRAME_MISO_STATE_OFFSET]);
  142. return false;
  143. }
  144. /* SOF, checksum and EOF are not checksummed */
  145. chksum = sps30_serial_calc_chksum(priv->buf + 1, priv->num - 3);
  146. if (priv->buf[priv->num - 2] != chksum) {
  147. dev_err(state->dev, "frame integrity check failed\n");
  148. return false;
  149. }
  150. return true;
  151. }
  152. static int sps30_serial_command(struct sps30_state *state, unsigned char cmd,
  153. const void *arg, size_t arg_size, void *rsp, size_t rsp_size)
  154. {
  155. struct sps30_serial_priv *priv = state->priv;
  156. unsigned char buf[SPS30_SERIAL_MAX_BUF_SIZE];
  157. int ret, size;
  158. size = sps30_serial_prep_frame(buf, cmd, arg, arg_size);
  159. ret = sps30_serial_xfer(state, buf, size);
  160. if (ret)
  161. return ret;
  162. if (!sps30_serial_frame_valid(state, buf))
  163. return -EIO;
  164. if (rsp) {
  165. rsp_size = min_t(size_t, priv->buf[SPS30_SERIAL_FRAME_MISO_LEN_OFFSET], rsp_size);
  166. memcpy(rsp, &priv->buf[SPS30_SERIAL_FRAME_MISO_DATA_OFFSET], rsp_size);
  167. }
  168. return rsp_size;
  169. }
  170. static int sps30_serial_receive_buf(struct serdev_device *serdev,
  171. const unsigned char *buf, size_t size)
  172. {
  173. struct iio_dev *indio_dev = dev_get_drvdata(&serdev->dev);
  174. struct sps30_serial_priv *priv;
  175. struct sps30_state *state;
  176. unsigned char byte;
  177. size_t i;
  178. if (!indio_dev)
  179. return 0;
  180. state = iio_priv(indio_dev);
  181. priv = state->priv;
  182. /* just in case device put some unexpected data on the bus */
  183. if (priv->done)
  184. return size;
  185. /* wait for the start of frame */
  186. if (!priv->num && size && buf[0] != SPS30_SERIAL_SOF_EOF)
  187. return 1;
  188. if (priv->num + size >= ARRAY_SIZE(priv->buf))
  189. size = ARRAY_SIZE(priv->buf) - priv->num;
  190. for (i = 0; i < size; i++) {
  191. byte = buf[i];
  192. /* remove stuffed bytes on-the-fly */
  193. if (byte == SPS30_SERIAL_ESCAPE_CHAR) {
  194. priv->escaped = true;
  195. continue;
  196. }
  197. byte = sps30_serial_get_byte(priv->escaped, byte);
  198. if (priv->escaped && !byte)
  199. dev_warn(state->dev, "unrecognized escaped char (0x%02x)\n", byte);
  200. priv->buf[priv->num++] = byte;
  201. /* EOF received */
  202. if (!priv->escaped && byte == SPS30_SERIAL_SOF_EOF) {
  203. if (priv->num < SPS30_SERIAL_FRAME_MIN_SIZE)
  204. continue;
  205. priv->done = true;
  206. complete(&priv->new_frame);
  207. i++;
  208. break;
  209. }
  210. priv->escaped = false;
  211. }
  212. return i;
  213. }
  214. static const struct serdev_device_ops sps30_serial_device_ops = {
  215. .receive_buf = sps30_serial_receive_buf,
  216. .write_wakeup = serdev_device_write_wakeup,
  217. };
  218. static int sps30_serial_start_meas(struct sps30_state *state)
  219. {
  220. /* request BE IEEE754 formatted data */
  221. unsigned char buf[] = { 0x01, 0x03 };
  222. return sps30_serial_command(state, SPS30_SERIAL_START_MEAS, buf, sizeof(buf), NULL, 0);
  223. }
  224. static int sps30_serial_stop_meas(struct sps30_state *state)
  225. {
  226. return sps30_serial_command(state, SPS30_SERIAL_STOP_MEAS, NULL, 0, NULL, 0);
  227. }
  228. static int sps30_serial_reset(struct sps30_state *state)
  229. {
  230. int ret;
  231. ret = sps30_serial_command(state, SPS30_SERIAL_RESET, NULL, 0, NULL, 0);
  232. msleep(500);
  233. return ret;
  234. }
  235. static int sps30_serial_read_meas(struct sps30_state *state, __be32 *meas, size_t num)
  236. {
  237. int ret;
  238. /* measurements are ready within a second */
  239. if (msleep_interruptible(1000))
  240. return -EINTR;
  241. ret = sps30_serial_command(state, SPS30_SERIAL_READ_MEAS, NULL, 0, meas, num * sizeof(num));
  242. if (ret < 0)
  243. return ret;
  244. /* if measurements aren't ready sensor returns empty frame */
  245. if (ret == SPS30_SERIAL_FRAME_MIN_SIZE)
  246. return -ETIMEDOUT;
  247. if (ret != num * sizeof(*meas))
  248. return -EIO;
  249. return 0;
  250. }
  251. static int sps30_serial_clean_fan(struct sps30_state *state)
  252. {
  253. return sps30_serial_command(state, SPS30_SERIAL_CLEAN_FAN, NULL, 0, NULL, 0);
  254. }
  255. static int sps30_serial_read_cleaning_period(struct sps30_state *state, __be32 *period)
  256. {
  257. unsigned char buf[] = { 0x00 };
  258. int ret;
  259. ret = sps30_serial_command(state, SPS30_SERIAL_PERIOD, buf, sizeof(buf),
  260. period, sizeof(*period));
  261. if (ret < 0)
  262. return ret;
  263. if (ret != sizeof(*period))
  264. return -EIO;
  265. return 0;
  266. }
  267. static int sps30_serial_write_cleaning_period(struct sps30_state *state, __be32 period)
  268. {
  269. unsigned char buf[5] = { 0x00 };
  270. memcpy(buf + 1, &period, sizeof(period));
  271. return sps30_serial_command(state, SPS30_SERIAL_PERIOD, buf, sizeof(buf), NULL, 0);
  272. }
  273. static int sps30_serial_show_info(struct sps30_state *state)
  274. {
  275. /*
  276. * tell device do return serial number and add extra nul byte just in case
  277. * serial number isn't a valid string
  278. */
  279. unsigned char buf[32 + 1] = { 0x03 };
  280. struct device *dev = state->dev;
  281. int ret;
  282. ret = sps30_serial_command(state, SPS30_SERIAL_DEV_INFO, buf, 1, buf, sizeof(buf) - 1);
  283. if (ret < 0)
  284. return ret;
  285. if (ret != sizeof(buf) - 1)
  286. return -EIO;
  287. dev_info(dev, "serial number: %s\n", buf);
  288. ret = sps30_serial_command(state, SPS30_SERIAL_READ_VERSION, NULL, 0, buf, sizeof(buf) - 1);
  289. if (ret < 0)
  290. return ret;
  291. if (ret < 2)
  292. return -EIO;
  293. dev_info(dev, "fw version: %u.%u\n", buf[0], buf[1]);
  294. return 0;
  295. }
  296. static const struct sps30_ops sps30_serial_ops = {
  297. .start_meas = sps30_serial_start_meas,
  298. .stop_meas = sps30_serial_stop_meas,
  299. .read_meas = sps30_serial_read_meas,
  300. .reset = sps30_serial_reset,
  301. .clean_fan = sps30_serial_clean_fan,
  302. .read_cleaning_period = sps30_serial_read_cleaning_period,
  303. .write_cleaning_period = sps30_serial_write_cleaning_period,
  304. .show_info = sps30_serial_show_info,
  305. };
  306. static int sps30_serial_probe(struct serdev_device *serdev)
  307. {
  308. struct device *dev = &serdev->dev;
  309. struct sps30_serial_priv *priv;
  310. int ret;
  311. priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
  312. if (!priv)
  313. return -ENOMEM;
  314. init_completion(&priv->new_frame);
  315. serdev_device_set_client_ops(serdev, &sps30_serial_device_ops);
  316. ret = devm_serdev_device_open(dev, serdev);
  317. if (ret)
  318. return ret;
  319. serdev_device_set_baudrate(serdev, 115200);
  320. serdev_device_set_flow_control(serdev, false);
  321. ret = serdev_device_set_parity(serdev, SERDEV_PARITY_NONE);
  322. if (ret)
  323. return ret;
  324. return sps30_probe(dev, SPS30_SERIAL_DEV_NAME, priv, &sps30_serial_ops);
  325. }
  326. static const struct of_device_id sps30_serial_of_match[] = {
  327. { .compatible = "sensirion,sps30" },
  328. { }
  329. };
  330. MODULE_DEVICE_TABLE(of, sps30_serial_of_match);
  331. static struct serdev_device_driver sps30_serial_driver = {
  332. .driver = {
  333. .name = KBUILD_MODNAME,
  334. .of_match_table = sps30_serial_of_match,
  335. },
  336. .probe = sps30_serial_probe,
  337. };
  338. module_serdev_device_driver(sps30_serial_driver);
  339. MODULE_AUTHOR("Tomasz Duszynski <[email protected]>");
  340. MODULE_DESCRIPTION("Sensirion SPS30 particulate matter sensor serial driver");
  341. MODULE_LICENSE("GPL v2");
  342. MODULE_IMPORT_NS(IIO_SPS30);