| @@ -0,0 +1,407 @@ |
| | 1 | // SPDX-License-Identifier: GPL-2.0 |
| | 2 | /* |
| | 3 | * Sensirion SPS30 particulate matter sensor driver |
| | 4 | * |
| | 5 | * Copyright (c) Tomasz Duszynski <tduszyns@gmail.com> |
| | 6 | * |
| | 7 | * I2C slave address: 0x69 |
| | 8 | * |
| | 9 | * TODO: |
| | 10 | * - support for turning on fan cleaning |
| | 11 | * - support for reading/setting auto cleaning interval |
| | 12 | */ |
| | 13 | |
| | 14 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
| | 15 | |
| | 16 | #include <asm/unaligned.h> |
| | 17 | #include <linux/crc8.h> |
| | 18 | #include <linux/delay.h> |
| | 19 | #include <linux/i2c.h> |
| | 20 | #include <linux/iio/buffer.h> |
| | 21 | #include <linux/iio/iio.h> |
| | 22 | #include <linux/iio/sysfs.h> |
| | 23 | #include <linux/iio/trigger_consumer.h> |
| | 24 | #include <linux/iio/triggered_buffer.h> |
| | 25 | #include <linux/module.h> |
| | 26 | |
| | 27 | #define SPS30_CRC8_POLYNOMIAL 0x31 |
| | 28 | /* max number of bytes needed to store PM measurements or serial string */ |
| | 29 | #define SPS30_MAX_READ_SIZE 48 |
| | 30 | /* sensor measures reliably up to 3000 ug / m3 */ |
| | 31 | #define SPS30_MAX_PM 3000 |
| | 32 | |
| | 33 | /* SPS30 commands */ |
| | 34 | #define SPS30_START_MEAS 0x0010 |
| | 35 | #define SPS30_STOP_MEAS 0x0104 |
| | 36 | #define SPS30_RESET 0xd304 |
| | 37 | #define SPS30_READ_DATA_READY_FLAG 0x0202 |
| | 38 | #define SPS30_READ_DATA 0x0300 |
| | 39 | #define SPS30_READ_SERIAL 0xd033 |
| | 40 | |
| | 41 | enum { |
| | 42 | PM1, |
| | 43 | PM2P5, |
| | 44 | PM4, |
| | 45 | PM10, |
| | 46 | }; |
| | 47 | |
| | 48 | struct sps30_state { |
| | 49 | struct i2c_client *client; |
| | 50 | /* |
| | 51 | * Guards against concurrent access to sensor registers. |
| | 52 | * Must be held whenever sequence of commands is to be executed. |
| | 53 | */ |
| | 54 | struct mutex lock; |
| | 55 | }; |
| | 56 | |
| | 57 | DECLARE_CRC8_TABLE(sps30_crc8_table); |
| | 58 | |
| | 59 | static int sps30_write_then_read(struct sps30_state *state, u8 *txbuf, |
| | 60 | int txsize, u8 *rxbuf, int rxsize) |
| | 61 | { |
| | 62 | int ret; |
| | 63 | |
| | 64 | /* |
| | 65 | * Sensor does not support repeated start so instead of |
| | 66 | * sending two i2c messages in a row we just send one by one. |
| | 67 | */ |
| | 68 | ret = i2c_master_send(state->client, txbuf, txsize); |
| | 69 | if (ret != txsize) |
| | 70 | return ret < 0 ? ret : -EIO; |
| | 71 | |
| | 72 | if (!rxbuf) |
| | 73 | return 0; |
| | 74 | |
| | 75 | ret = i2c_master_recv(state->client, rxbuf, rxsize); |
| | 76 | if (ret != rxsize) |
| | 77 | return ret < 0 ? ret : -EIO; |
| | 78 | |
| | 79 | return 0; |
| | 80 | } |
| | 81 | |
| | 82 | static int sps30_do_cmd(struct sps30_state *state, u16 cmd, u8 *data, int size) |
| | 83 | { |
| | 84 | /* |
| | 85 | * Internally sensor stores measurements in a following manner: |
| | 86 | * |
| | 87 | * PM1: upper two bytes, crc8, lower two bytes, crc8 |
| | 88 | * PM2P5: upper two bytes, crc8, lower two bytes, crc8 |
| | 89 | * PM4: upper two bytes, crc8, lower two bytes, crc8 |
| | 90 | * PM10: upper two bytes, crc8, lower two bytes, crc8 |
| | 91 | * |
| | 92 | * What follows next are number concentration measurements and |
| | 93 | * typical particle size measurement which we omit. |
| | 94 | */ |
| | 95 | u8 buf[SPS30_MAX_READ_SIZE] = { cmd >> 8, cmd }; |
| | 96 | int i, ret = 0; |
| | 97 | |
| | 98 | switch (cmd) { |
| | 99 | case SPS30_START_MEAS: |
| | 100 | buf[2] = 0x03; |
| | 101 | buf[3] = 0x00; |
| | 102 | buf[4] = crc8(sps30_crc8_table, &buf[2], 2, CRC8_INIT_VALUE); |
| | 103 | ret = sps30_write_then_read(state, buf, 5, NULL, 0); |
| | 104 | break; |
| | 105 | case SPS30_STOP_MEAS: |
| | 106 | case SPS30_RESET: |
| | 107 | ret = sps30_write_then_read(state, buf, 2, NULL, 0); |
| | 108 | break; |
| | 109 | case SPS30_READ_DATA_READY_FLAG: |
| | 110 | case SPS30_READ_DATA: |
| | 111 | case SPS30_READ_SERIAL: |
| | 112 | /* every two data bytes are checksummed */ |
| | 113 | size += size / 2; |
| | 114 | ret = sps30_write_then_read(state, buf, 2, buf, size); |
| | 115 | break; |
| | 116 | } |
| | 117 | |
| | 118 | if (ret) |
| | 119 | return ret; |
| | 120 | |
| | 121 | /* validate received data and strip off crc bytes */ |
| | 122 | for (i = 0; i < size; i += 3) { |
| | 123 | u8 crc = crc8(sps30_crc8_table, &buf[i], 2, CRC8_INIT_VALUE); |
| | 124 | |
| | 125 | if (crc != buf[i + 2]) { |
| | 126 | dev_err(&state->client->dev, |
| | 127 | "data integrity check failed\n"); |
| | 128 | return -EIO; |
| | 129 | } |
| | 130 | |
| | 131 | *data++ = buf[i]; |
| | 132 | *data++ = buf[i + 1]; |
| | 133 | } |
| | 134 | |
| | 135 | return 0; |
| | 136 | } |
| | 137 | |
| | 138 | static s32 sps30_float_to_int_clamped(const u8 *fp) |
| | 139 | { |
| | 140 | int val = get_unaligned_be32(fp); |
| | 141 | int mantissa = val & GENMASK(22, 0); |
| | 142 | /* this is fine since passed float is always non-negative */ |
| | 143 | int exp = val >> 23; |
| | 144 | int fraction, shift; |
| | 145 | |
| | 146 | /* special case 0 */ |
| | 147 | if (!exp && !mantissa) |
| | 148 | return 0; |
| | 149 | |
| | 150 | exp -= 127; |
| | 151 | if (exp < 0) { |
| | 152 | /* return values ranging from 1 to 99 */ |
| | 153 | return ((((1 << 23) + mantissa) * 100) >> 23) >> (-exp); |
| | 154 | } |
| | 155 | |
| | 156 | /* return values ranging from 100 to 300000 */ |
| | 157 | shift = 23 - exp; |
| | 158 | val = (1 << exp) + (mantissa >> shift); |
| | 159 | if (val >= SPS30_MAX_PM) |
| | 160 | return SPS30_MAX_PM * 100; |
| | 161 | |
| | 162 | fraction = mantissa & GENMASK(shift - 1, 0); |
| | 163 | |
| | 164 | return val * 100 + ((fraction * 100) >> shift); |
| | 165 | } |
| | 166 | |
| | 167 | static int sps30_do_meas(struct sps30_state *state, s32 *data, int size) |
| | 168 | { |
| | 169 | int i, ret, tries = 5; |
| | 170 | u8 tmp[16]; |
| | 171 | |
| | 172 | while (tries--) { |
| | 173 | ret = sps30_do_cmd(state, SPS30_READ_DATA_READY_FLAG, tmp, 2); |
| | 174 | if (ret) |
| | 175 | return -EIO; |
| | 176 | |
| | 177 | /* new measurements ready to be read */ |
| | 178 | if (tmp[1] == 1) |
| | 179 | break; |
| | 180 | |
| | 181 | msleep_interruptible(300); |
| | 182 | } |
| | 183 | |
| | 184 | if (!tries) |
| | 185 | return -ETIMEDOUT; |
| | 186 | |
| | 187 | ret = sps30_do_cmd(state, SPS30_READ_DATA, tmp, sizeof(int) * size); |
| | 188 | if (ret) |
| | 189 | return ret; |
| | 190 | |
| | 191 | for (i = 0; i < size; i++) |
| | 192 | data[i] = sps30_float_to_int_clamped(&tmp[4 * i]); |
| | 193 | |
| | 194 | return 0; |
| | 195 | } |
| | 196 | |
| | 197 | static irqreturn_t sps30_trigger_handler(int irq, void *p) |
| | 198 | { |
| | 199 | struct iio_poll_func *pf = p; |
| | 200 | struct iio_dev *indio_dev = pf->indio_dev; |
| | 201 | struct sps30_state *state = iio_priv(indio_dev); |
| | 202 | int ret; |
| | 203 | s32 data[4 + 2]; /* PM1, PM2P5, PM4, PM10, timestamp */ |
| | 204 | |
| | 205 | mutex_lock(&state->lock); |
| | 206 | ret = sps30_do_meas(state, data, 4); |
| | 207 | mutex_unlock(&state->lock); |
| | 208 | if (ret) |
| | 209 | goto err; |
| | 210 | |
| | 211 | iio_push_to_buffers_with_timestamp(indio_dev, data, |
| | 212 | iio_get_time_ns(indio_dev)); |
| | 213 | err: |
| | 214 | iio_trigger_notify_done(indio_dev->trig); |
| | 215 | |
| | 216 | return IRQ_HANDLED; |
| | 217 | } |
| | 218 | |
| | 219 | static int sps30_read_raw(struct iio_dev *indio_dev, |
| | 220 | struct iio_chan_spec const *chan, |
| | 221 | int *val, int *val2, long mask) |
| | 222 | { |
| | 223 | struct sps30_state *state = iio_priv(indio_dev); |
| | 224 | int data[4], ret = -EINVAL; |
| | 225 | |
| | 226 | switch (mask) { |
| | 227 | case IIO_CHAN_INFO_PROCESSED: |
| | 228 | switch (chan->type) { |
| | 229 | case IIO_MASSCONCENTRATION: |
| | 230 | mutex_lock(&state->lock); |
| | 231 | /* read up to the number of bytes actually needed */ |
| | 232 | switch (chan->channel2) { |
| | 233 | case IIO_MOD_PM1: |
| | 234 | ret = sps30_do_meas(state, data, 1); |
| | 235 | break; |
| | 236 | case IIO_MOD_PM2P5: |
| | 237 | ret = sps30_do_meas(state, data, 2); |
| | 238 | break; |
| | 239 | case IIO_MOD_PM4: |
| | 240 | ret = sps30_do_meas(state, data, 3); |
| | 241 | break; |
| | 242 | case IIO_MOD_PM10: |
| | 243 | ret = sps30_do_meas(state, data, 4); |
| | 244 | break; |
| | 245 | } |
| | 246 | mutex_unlock(&state->lock); |
| | 247 | if (ret) |
| | 248 | return ret; |
| | 249 | |
| | 250 | *val = data[chan->address] / 100; |
| | 251 | *val2 = (data[chan->address] % 100) * 10000; |
| | 252 | |
| | 253 | return IIO_VAL_INT_PLUS_MICRO; |
| | 254 | default: |
| | 255 | return -EINVAL; |
| | 256 | } |
| | 257 | case IIO_CHAN_INFO_SCALE: |
| | 258 | switch (chan->type) { |
| | 259 | case IIO_MASSCONCENTRATION: |
| | 260 | switch (chan->channel2) { |
| | 261 | case IIO_MOD_PM1: |
| | 262 | case IIO_MOD_PM2P5: |
| | 263 | case IIO_MOD_PM4: |
| | 264 | case IIO_MOD_PM10: |
| | 265 | *val = 0; |
| | 266 | *val2 = 10000; |
| | 267 | |
| | 268 | return IIO_VAL_INT_PLUS_MICRO; |
| | 269 | } |
| | 270 | default: |
| | 271 | return -EINVAL; |
| | 272 | } |
| | 273 | } |
| | 274 | |
| | 275 | return -EINVAL; |
| | 276 | } |
| | 277 | |
| | 278 | static const struct iio_info sps30_info = { |
| | 279 | .read_raw = sps30_read_raw, |
| | 280 | }; |
| | 281 | |
| | 282 | #define SPS30_CHAN(_index, _mod) { \ |
| | 283 | .type = IIO_MASSCONCENTRATION, \ |
| | 284 | .modified = 1, \ |
| | 285 | .channel2 = IIO_MOD_ ## _mod, \ |
| | 286 | .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), \ |
| | 287 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ |
| | 288 | .address = _mod, \ |
| | 289 | .scan_index = _index, \ |
| | 290 | .scan_type = { \ |
| | 291 | .sign = 'u', \ |
| | 292 | .realbits = 19, \ |
| | 293 | .storagebits = 32, \ |
| | 294 | .endianness = IIO_CPU, \ |
| | 295 | }, \ |
| | 296 | } |
| | 297 | |
| | 298 | static const struct iio_chan_spec sps30_channels[] = { |
| | 299 | SPS30_CHAN(0, PM1), |
| | 300 | SPS30_CHAN(1, PM2P5), |
| | 301 | SPS30_CHAN(2, PM4), |
| | 302 | SPS30_CHAN(3, PM10), |
| | 303 | IIO_CHAN_SOFT_TIMESTAMP(4), |
| | 304 | }; |
| | 305 | |
| | 306 | static void sps30_stop_meas(void *data) |
| | 307 | { |
| | 308 | struct sps30_state *state = data; |
| | 309 | |
| | 310 | sps30_do_cmd(state, SPS30_STOP_MEAS, NULL, 0); |
| | 311 | } |
| | 312 | |
| | 313 | static const unsigned long sps30_scan_masks[] = { 0x0f, 0x00 }; |
| | 314 | |
| | 315 | static int sps30_probe(struct i2c_client *client) |
| | 316 | { |
| | 317 | struct iio_dev *indio_dev; |
| | 318 | struct sps30_state *state; |
| | 319 | u8 buf[32]; |
| | 320 | int ret; |
| | 321 | |
| | 322 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) |
| | 323 | return -EOPNOTSUPP; |
| | 324 | |
| | 325 | indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*state)); |
| | 326 | if (!indio_dev) |
| | 327 | return -ENOMEM; |
| | 328 | |
| | 329 | state = iio_priv(indio_dev); |
| | 330 | i2c_set_clientdata(client, indio_dev); |
| | 331 | state->client = client; |
| | 332 | indio_dev->dev.parent = &client->dev; |
| | 333 | indio_dev->info = &sps30_info; |
| | 334 | indio_dev->name = client->name; |
| | 335 | indio_dev->channels = sps30_channels; |
| | 336 | indio_dev->num_channels = ARRAY_SIZE(sps30_channels); |
| | 337 | indio_dev->modes = INDIO_DIRECT_MODE; |
| | 338 | indio_dev->available_scan_masks = sps30_scan_masks; |
| | 339 | |
| | 340 | mutex_init(&state->lock); |
| | 341 | crc8_populate_msb(sps30_crc8_table, SPS30_CRC8_POLYNOMIAL); |
| | 342 | |
| | 343 | ret = sps30_do_cmd(state, SPS30_RESET, NULL, 0); |
| | 344 | if (ret) { |
| | 345 | dev_err(&client->dev, "failed to reset device\n"); |
| | 346 | return ret; |
| | 347 | } |
| | 348 | msleep(300); |
| | 349 | /* |
| | 350 | * Power-on-reset causes sensor to produce some glitch on i2c bus and |
| | 351 | * some controllers end up in error state. Recover simply by placing |
| | 352 | * some data on the bus, for example STOP_MEAS command, which |
| | 353 | * is NOP in this case. |
| | 354 | */ |
| | 355 | sps30_do_cmd(state, SPS30_STOP_MEAS, NULL, 0); |
| | 356 | |
| | 357 | ret = sps30_do_cmd(state, SPS30_READ_SERIAL, buf, sizeof(buf)); |
| | 358 | if (ret) { |
| | 359 | dev_err(&client->dev, "failed to read serial number\n"); |
| | 360 | return ret; |
| | 361 | } |
| | 362 | /* returned serial number is already NUL terminated */ |
| | 363 | dev_info(&client->dev, "serial number: %s\n", buf); |
| | 364 | |
| | 365 | ret = sps30_do_cmd(state, SPS30_START_MEAS, NULL, 0); |
| | 366 | if (ret) { |
| | 367 | dev_err(&client->dev, "failed to start measurement\n"); |
| | 368 | return ret; |
| | 369 | } |
| | 370 | |
| | 371 | ret = devm_add_action_or_reset(&client->dev, sps30_stop_meas, state); |
| | 372 | if (ret) |
| | 373 | return ret; |
| | 374 | |
| | 375 | ret = devm_iio_triggered_buffer_setup(&client->dev, indio_dev, NULL, |
| | 376 | sps30_trigger_handler, NULL); |
| | 377 | if (ret) |
| | 378 | return ret; |
| | 379 | |
| | 380 | return devm_iio_device_register(&client->dev, indio_dev); |
| | 381 | } |
| | 382 | |
| | 383 | static const struct i2c_device_id sps30_id[] = { |
| | 384 | { "sps30" }, |
| | 385 | { } |
| | 386 | }; |
| | 387 | MODULE_DEVICE_TABLE(i2c, sps30_id); |
| | 388 | |
| | 389 | static const struct of_device_id sps30_of_match[] = { |
| | 390 | { .compatible = "sensirion,sps30" }, |
| | 391 | { } |
| | 392 | }; |
| | 393 | MODULE_DEVICE_TABLE(of, sps30_of_match); |
| | 394 | |
| | 395 | static struct i2c_driver sps30_driver = { |
| | 396 | .driver = { |
| | 397 | .name = "sps30", |
| | 398 | .of_match_table = sps30_of_match, |
| | 399 | }, |
| | 400 | .id_table = sps30_id, |
| | 401 | .probe_new = sps30_probe, |
| | 402 | }; |
| | 403 | module_i2c_driver(sps30_driver); |
| | 404 | |
| | 405 | MODULE_AUTHOR("Tomasz Duszynski <tduszyns@gmail.com>"); |
| | 406 | MODULE_DESCRIPTION("Sensirion SPS30 particulate matter sensor driver"); |
| | 407 | MODULE_LICENSE("GPL v2"); |