]>
Commit | Line | Data |
---|---|---|
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 | ||
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"); |