Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Sensirion SPS30 particulate matter sensor serial driver
0004  *
0005  * Copyright (c) 2021 Tomasz Duszynski <tomasz.duszynski@octakon.com>
0006  */
0007 #include <linux/completion.h>
0008 #include <linux/device.h>
0009 #include <linux/errno.h>
0010 #include <linux/iio/iio.h>
0011 #include <linux/minmax.h>
0012 #include <linux/mod_devicetable.h>
0013 #include <linux/module.h>
0014 #include <linux/serdev.h>
0015 #include <linux/types.h>
0016 
0017 #include "sps30.h"
0018 
0019 #define SPS30_SERIAL_DEV_NAME "sps30"
0020 
0021 #define SPS30_SERIAL_SOF_EOF 0x7e
0022 #define SPS30_SERIAL_TIMEOUT msecs_to_jiffies(20)
0023 #define SPS30_SERIAL_MAX_BUF_SIZE 263
0024 #define SPS30_SERIAL_ESCAPE_CHAR 0x7d
0025 
0026 #define SPS30_SERIAL_FRAME_MIN_SIZE 7
0027 #define SPS30_SERIAL_FRAME_ADR_OFFSET 1
0028 #define SPS30_SERIAL_FRAME_CMD_OFFSET 2
0029 #define SPS30_SERIAL_FRAME_MOSI_LEN_OFFSET 3
0030 #define SPS30_SERIAL_FRAME_MISO_STATE_OFFSET 3
0031 #define SPS30_SERIAL_FRAME_MISO_LEN_OFFSET 4
0032 #define SPS30_SERIAL_FRAME_MISO_DATA_OFFSET 5
0033 
0034 #define SPS30_SERIAL_START_MEAS 0x00
0035 #define SPS30_SERIAL_STOP_MEAS 0x01
0036 #define SPS30_SERIAL_READ_MEAS 0x03
0037 #define SPS30_SERIAL_RESET 0xd3
0038 #define SPS30_SERIAL_CLEAN_FAN 0x56
0039 #define SPS30_SERIAL_PERIOD 0x80
0040 #define SPS30_SERIAL_DEV_INFO 0xd0
0041 #define SPS30_SERIAL_READ_VERSION 0xd1
0042 
0043 struct sps30_serial_priv {
0044     struct completion new_frame;
0045     unsigned char buf[SPS30_SERIAL_MAX_BUF_SIZE];
0046     size_t num;
0047     bool escaped;
0048     bool done;
0049 };
0050 
0051 static int sps30_serial_xfer(struct sps30_state *state, const unsigned char *buf, size_t size)
0052 {
0053     struct serdev_device *serdev = to_serdev_device(state->dev);
0054     struct sps30_serial_priv *priv = state->priv;
0055     int ret;
0056 
0057     priv->num = 0;
0058     priv->escaped = false;
0059     priv->done = false;
0060 
0061     ret = serdev_device_write(serdev, buf, size, SPS30_SERIAL_TIMEOUT);
0062     if (ret < 0)
0063         return ret;
0064     if (ret != size)
0065         return -EIO;
0066 
0067     ret = wait_for_completion_interruptible_timeout(&priv->new_frame, SPS30_SERIAL_TIMEOUT);
0068     if (ret < 0)
0069         return ret;
0070     if (!ret)
0071         return -ETIMEDOUT;
0072 
0073     return 0;
0074 }
0075 
0076 static const struct {
0077     unsigned char byte;
0078     unsigned char byte2;
0079 } sps30_serial_bytes[] = {
0080     { 0x11, 0x31 },
0081     { 0x13, 0x33 },
0082     { 0x7e, 0x5e },
0083     { 0x7d, 0x5d },
0084 };
0085 
0086 static int sps30_serial_put_byte(unsigned char *buf, unsigned char byte)
0087 {
0088     int i;
0089 
0090     for (i = 0; i < ARRAY_SIZE(sps30_serial_bytes); i++) {
0091         if (sps30_serial_bytes[i].byte != byte)
0092             continue;
0093 
0094         buf[0] = SPS30_SERIAL_ESCAPE_CHAR;
0095         buf[1] = sps30_serial_bytes[i].byte2;
0096 
0097         return 2;
0098     }
0099 
0100     buf[0] = byte;
0101 
0102     return 1;
0103 }
0104 
0105 static char sps30_serial_get_byte(bool escaped, unsigned char byte2)
0106 {
0107     int i;
0108 
0109     if (!escaped)
0110         return byte2;
0111 
0112     for (i = 0; i < ARRAY_SIZE(sps30_serial_bytes); i++) {
0113         if (sps30_serial_bytes[i].byte2 != byte2)
0114             continue;
0115 
0116         return sps30_serial_bytes[i].byte;
0117     }
0118 
0119     return 0;
0120 }
0121 
0122 static unsigned char sps30_serial_calc_chksum(const unsigned char *buf, size_t num)
0123 {
0124     unsigned int chksum = 0;
0125     size_t i;
0126 
0127     for (i = 0; i < num; i++)
0128         chksum += buf[i];
0129 
0130     return ~chksum;
0131 }
0132 
0133 static int sps30_serial_prep_frame(unsigned char *buf, unsigned char cmd,
0134                    const unsigned char *arg, size_t arg_size)
0135 {
0136     unsigned char chksum;
0137     int num = 0;
0138     size_t i;
0139 
0140     buf[num++] = SPS30_SERIAL_SOF_EOF;
0141     buf[num++] = 0;
0142     num += sps30_serial_put_byte(buf + num, cmd);
0143     num += sps30_serial_put_byte(buf + num, arg_size);
0144 
0145     for (i = 0; i < arg_size; i++)
0146         num += sps30_serial_put_byte(buf + num, arg[i]);
0147 
0148     /* SOF isn't checksummed */
0149     chksum = sps30_serial_calc_chksum(buf + 1, num - 1);
0150     num += sps30_serial_put_byte(buf + num, chksum);
0151     buf[num++] = SPS30_SERIAL_SOF_EOF;
0152 
0153     return num;
0154 }
0155 
0156 static bool sps30_serial_frame_valid(struct sps30_state *state, const unsigned char *buf)
0157 {
0158     struct sps30_serial_priv *priv = state->priv;
0159     unsigned char chksum;
0160 
0161     if ((priv->num < SPS30_SERIAL_FRAME_MIN_SIZE) ||
0162         (priv->num != SPS30_SERIAL_FRAME_MIN_SIZE +
0163          priv->buf[SPS30_SERIAL_FRAME_MISO_LEN_OFFSET])) {
0164         dev_err(state->dev, "frame has invalid number of bytes\n");
0165         return false;
0166     }
0167 
0168     if ((priv->buf[SPS30_SERIAL_FRAME_ADR_OFFSET] != buf[SPS30_SERIAL_FRAME_ADR_OFFSET]) ||
0169         (priv->buf[SPS30_SERIAL_FRAME_CMD_OFFSET] != buf[SPS30_SERIAL_FRAME_CMD_OFFSET])) {
0170         dev_err(state->dev, "frame has wrong ADR and CMD bytes\n");
0171         return false;
0172     }
0173 
0174     if (priv->buf[SPS30_SERIAL_FRAME_MISO_STATE_OFFSET]) {
0175         dev_err(state->dev, "frame with non-zero state received (0x%02x)\n",
0176             priv->buf[SPS30_SERIAL_FRAME_MISO_STATE_OFFSET]);
0177         return false;
0178     }
0179 
0180     /* SOF, checksum and EOF are not checksummed */
0181     chksum = sps30_serial_calc_chksum(priv->buf + 1, priv->num - 3);
0182     if (priv->buf[priv->num - 2] != chksum) {
0183         dev_err(state->dev, "frame integrity check failed\n");
0184         return false;
0185     }
0186 
0187     return true;
0188 }
0189 
0190 static int sps30_serial_command(struct sps30_state *state, unsigned char cmd,
0191                 const void *arg, size_t arg_size, void *rsp, size_t rsp_size)
0192 {
0193     struct sps30_serial_priv *priv = state->priv;
0194     unsigned char buf[SPS30_SERIAL_MAX_BUF_SIZE];
0195     int ret, size;
0196 
0197     size = sps30_serial_prep_frame(buf, cmd, arg, arg_size);
0198     ret = sps30_serial_xfer(state, buf, size);
0199     if (ret)
0200         return ret;
0201 
0202     if (!sps30_serial_frame_valid(state, buf))
0203         return -EIO;
0204 
0205     if (rsp) {
0206         rsp_size = min_t(size_t, priv->buf[SPS30_SERIAL_FRAME_MISO_LEN_OFFSET], rsp_size);
0207         memcpy(rsp, &priv->buf[SPS30_SERIAL_FRAME_MISO_DATA_OFFSET], rsp_size);
0208     }
0209 
0210     return rsp_size;
0211 }
0212 
0213 static int sps30_serial_receive_buf(struct serdev_device *serdev,
0214                     const unsigned char *buf, size_t size)
0215 {
0216     struct iio_dev *indio_dev = dev_get_drvdata(&serdev->dev);
0217     struct sps30_serial_priv *priv;
0218     struct sps30_state *state;
0219     unsigned char byte;
0220     size_t i;
0221 
0222     if (!indio_dev)
0223         return 0;
0224 
0225     state = iio_priv(indio_dev);
0226     priv = state->priv;
0227 
0228     /* just in case device put some unexpected data on the bus */
0229     if (priv->done)
0230         return size;
0231 
0232     /* wait for the start of frame */
0233     if (!priv->num && size && buf[0] != SPS30_SERIAL_SOF_EOF)
0234         return 1;
0235 
0236     if (priv->num + size >= ARRAY_SIZE(priv->buf))
0237         size = ARRAY_SIZE(priv->buf) - priv->num;
0238 
0239     for (i = 0; i < size; i++) {
0240         byte = buf[i];
0241         /* remove stuffed bytes on-the-fly */
0242         if (byte == SPS30_SERIAL_ESCAPE_CHAR) {
0243             priv->escaped = true;
0244             continue;
0245         }
0246 
0247         byte = sps30_serial_get_byte(priv->escaped, byte);
0248         if (priv->escaped && !byte)
0249             dev_warn(state->dev, "unrecognized escaped char (0x%02x)\n", byte);
0250 
0251         priv->buf[priv->num++] = byte;
0252 
0253         /* EOF received */
0254         if (!priv->escaped && byte == SPS30_SERIAL_SOF_EOF) {
0255             if (priv->num < SPS30_SERIAL_FRAME_MIN_SIZE)
0256                 continue;
0257 
0258             priv->done = true;
0259             complete(&priv->new_frame);
0260             i++;
0261             break;
0262         }
0263 
0264         priv->escaped = false;
0265     }
0266 
0267     return i;
0268 }
0269 
0270 static const struct serdev_device_ops sps30_serial_device_ops = {
0271     .receive_buf = sps30_serial_receive_buf,
0272     .write_wakeup = serdev_device_write_wakeup,
0273 };
0274 
0275 static int sps30_serial_start_meas(struct sps30_state *state)
0276 {
0277     /* request BE IEEE754 formatted data */
0278     unsigned char buf[] = { 0x01, 0x03 };
0279 
0280     return sps30_serial_command(state, SPS30_SERIAL_START_MEAS, buf, sizeof(buf), NULL, 0);
0281 }
0282 
0283 static int sps30_serial_stop_meas(struct sps30_state *state)
0284 {
0285     return sps30_serial_command(state, SPS30_SERIAL_STOP_MEAS, NULL, 0, NULL, 0);
0286 }
0287 
0288 static int sps30_serial_reset(struct sps30_state *state)
0289 {
0290     int ret;
0291 
0292     ret = sps30_serial_command(state, SPS30_SERIAL_RESET, NULL, 0, NULL, 0);
0293     msleep(500);
0294 
0295     return ret;
0296 }
0297 
0298 static int sps30_serial_read_meas(struct sps30_state *state, __be32 *meas, size_t num)
0299 {
0300     int ret;
0301 
0302     /* measurements are ready within a second */
0303     if (msleep_interruptible(1000))
0304         return -EINTR;
0305 
0306     ret = sps30_serial_command(state, SPS30_SERIAL_READ_MEAS, NULL, 0, meas, num * sizeof(num));
0307     if (ret < 0)
0308         return ret;
0309     /* if measurements aren't ready sensor returns empty frame */
0310     if (ret == SPS30_SERIAL_FRAME_MIN_SIZE)
0311         return -ETIMEDOUT;
0312     if (ret != num * sizeof(*meas))
0313         return -EIO;
0314 
0315     return 0;
0316 }
0317 
0318 static int sps30_serial_clean_fan(struct sps30_state *state)
0319 {
0320     return sps30_serial_command(state, SPS30_SERIAL_CLEAN_FAN, NULL, 0, NULL, 0);
0321 }
0322 
0323 static int sps30_serial_read_cleaning_period(struct sps30_state *state, __be32 *period)
0324 {
0325     unsigned char buf[] = { 0x00 };
0326     int ret;
0327 
0328     ret = sps30_serial_command(state, SPS30_SERIAL_PERIOD, buf, sizeof(buf),
0329                    period, sizeof(*period));
0330     if (ret < 0)
0331         return ret;
0332     if (ret != sizeof(*period))
0333         return -EIO;
0334 
0335     return 0;
0336 }
0337 
0338 static int sps30_serial_write_cleaning_period(struct sps30_state *state, __be32 period)
0339 {
0340     unsigned char buf[5] = { 0x00 };
0341 
0342     memcpy(buf + 1, &period, sizeof(period));
0343 
0344     return sps30_serial_command(state, SPS30_SERIAL_PERIOD, buf, sizeof(buf), NULL, 0);
0345 }
0346 
0347 static int sps30_serial_show_info(struct sps30_state *state)
0348 {
0349     /*
0350      * tell device do return serial number and add extra nul byte just in case
0351      * serial number isn't a valid string
0352      */
0353     unsigned char buf[32 + 1] = { 0x03 };
0354     struct device *dev = state->dev;
0355     int ret;
0356 
0357     ret = sps30_serial_command(state, SPS30_SERIAL_DEV_INFO, buf, 1, buf, sizeof(buf) - 1);
0358     if (ret < 0)
0359         return ret;
0360     if (ret != sizeof(buf) - 1)
0361         return -EIO;
0362 
0363     dev_info(dev, "serial number: %s\n", buf);
0364 
0365     ret = sps30_serial_command(state, SPS30_SERIAL_READ_VERSION, NULL, 0, buf, sizeof(buf) - 1);
0366     if (ret < 0)
0367         return ret;
0368     if (ret < 2)
0369         return -EIO;
0370 
0371     dev_info(dev, "fw version: %u.%u\n", buf[0], buf[1]);
0372 
0373     return 0;
0374 }
0375 
0376 static const struct sps30_ops sps30_serial_ops = {
0377     .start_meas = sps30_serial_start_meas,
0378     .stop_meas = sps30_serial_stop_meas,
0379     .read_meas = sps30_serial_read_meas,
0380     .reset = sps30_serial_reset,
0381     .clean_fan = sps30_serial_clean_fan,
0382     .read_cleaning_period = sps30_serial_read_cleaning_period,
0383     .write_cleaning_period = sps30_serial_write_cleaning_period,
0384     .show_info = sps30_serial_show_info,
0385 };
0386 
0387 static int sps30_serial_probe(struct serdev_device *serdev)
0388 {
0389     struct device *dev = &serdev->dev;
0390     struct sps30_serial_priv *priv;
0391     int ret;
0392 
0393     priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
0394     if (!priv)
0395         return -ENOMEM;
0396 
0397     init_completion(&priv->new_frame);
0398     serdev_device_set_client_ops(serdev, &sps30_serial_device_ops);
0399 
0400     ret = devm_serdev_device_open(dev, serdev);
0401     if (ret)
0402         return ret;
0403 
0404     serdev_device_set_baudrate(serdev, 115200);
0405     serdev_device_set_flow_control(serdev, false);
0406 
0407     ret = serdev_device_set_parity(serdev, SERDEV_PARITY_NONE);
0408     if (ret)
0409         return ret;
0410 
0411     return sps30_probe(dev, SPS30_SERIAL_DEV_NAME, priv, &sps30_serial_ops);
0412 }
0413 
0414 static const struct of_device_id sps30_serial_of_match[] = {
0415     { .compatible = "sensirion,sps30" },
0416     { }
0417 };
0418 MODULE_DEVICE_TABLE(of, sps30_serial_of_match);
0419 
0420 static struct serdev_device_driver sps30_serial_driver = {
0421     .driver = {
0422         .name = KBUILD_MODNAME,
0423         .of_match_table = sps30_serial_of_match,
0424     },
0425     .probe = sps30_serial_probe,
0426 };
0427 module_serdev_device_driver(sps30_serial_driver);
0428 
0429 MODULE_AUTHOR("Tomasz Duszynski <tomasz.duszynski@octakon.com>");
0430 MODULE_DESCRIPTION("Sensirion SPS30 particulate matter sensor serial driver");
0431 MODULE_LICENSE("GPL v2");
0432 MODULE_IMPORT_NS(IIO_SPS30);