]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blame - drivers/iio/chemical/sps30.c
iio: imu: st_lsm6dsx: remove set but not used variable ''
[mirror_ubuntu-jammy-kernel.git] / drivers / iio / chemical / sps30.c
CommitLineData
232e0f6d
TD
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
41enum {
42 PM1,
43 PM2P5,
44 PM4,
45 PM10,
46};
47
48struct 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
57DECLARE_CRC8_TABLE(sps30_crc8_table);
58
59static 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
82static 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
138static 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
167static 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
197static 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));
213err:
214 iio_trigger_notify_done(indio_dev->trig);
215
216 return IRQ_HANDLED;
217}
218
219static 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
278static 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
298static 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
306static 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
313static const unsigned long sps30_scan_masks[] = { 0x0f, 0x00 };
314
315static 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
383static const struct i2c_device_id sps30_id[] = {
384 { "sps30" },
385 { }
386};
387MODULE_DEVICE_TABLE(i2c, sps30_id);
388
389static const struct of_device_id sps30_of_match[] = {
390 { .compatible = "sensirion,sps30" },
391 { }
392};
393MODULE_DEVICE_TABLE(of, sps30_of_match);
394
395static 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};
403module_i2c_driver(sps30_driver);
404
405MODULE_AUTHOR("Tomasz Duszynski <tduszyns@gmail.com>");
406MODULE_DESCRIPTION("Sensirion SPS30 particulate matter sensor driver");
407MODULE_LICENSE("GPL v2");