• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
8 #include <linux/crc8.h>
9 #include <linux/delay.h>
10 #include <linux/i2c.h>
11 #include <linux/iio/buffer.h>
12 #include <linux/iio/iio.h>
13 #include <linux/iio/sysfs.h>
14 #include <linux/iio/trigger_consumer.h>
15 #include <linux/iio/triggered_buffer.h>
16 #include <linux/kernel.h>
17 #include <linux/module.h>
18 
19 #include "sps30.h"
20 
21 /* sensor measures reliably up to 3000 ug / m3 */
22 #define SPS30_MAX_PM 3000
23 /* minimum and maximum self cleaning periods in seconds */
24 #define SPS30_AUTO_CLEANING_PERIOD_MIN 0
25 #define SPS30_AUTO_CLEANING_PERIOD_MAX 604800
26 
27 enum {
28 	PM1,
29 	PM2P5,
30 	PM4,
31 	PM10,
32 };
33 
34 enum {
35 	RESET,
36 	MEASURING,
37 };
38 
sps30_float_to_int_clamped(__be32 * fp)39 static s32 sps30_float_to_int_clamped(__be32 *fp)
40 {
41 	int val = be32_to_cpup(fp);
42 	int mantissa = val & GENMASK(22, 0);
43 	/* this is fine since passed float is always non-negative */
44 	int exp = val >> 23;
45 	int fraction, shift;
46 
47 	/* special case 0 */
48 	if (!exp && !mantissa)
49 		return 0;
50 
51 	exp -= 127;
52 	if (exp < 0) {
53 		/* return values ranging from 1 to 99 */
54 		return ((((1 << 23) + mantissa) * 100) >> 23) >> (-exp);
55 	}
56 
57 	/* return values ranging from 100 to 300000 */
58 	shift = 23 - exp;
59 	val = (1 << exp) + (mantissa >> shift);
60 	if (val >= SPS30_MAX_PM)
61 		return SPS30_MAX_PM * 100;
62 
63 	fraction = mantissa & GENMASK(shift - 1, 0);
64 
65 	return val * 100 + ((fraction * 100) >> shift);
66 }
67 
sps30_do_meas(struct sps30_state * state,s32 * data,int size)68 static int sps30_do_meas(struct sps30_state *state, s32 *data, int size)
69 {
70 	int i, ret;
71 
72 	if (state->state == RESET) {
73 		ret = state->ops->start_meas(state);
74 		if (ret)
75 			return ret;
76 
77 		state->state = MEASURING;
78 	}
79 
80 	ret = state->ops->read_meas(state, (__be32 *)data, size);
81 	if (ret)
82 		return ret;
83 
84 	for (i = 0; i < size; i++)
85 		data[i] = sps30_float_to_int_clamped((__be32 *)&data[i]);
86 
87 	return 0;
88 }
89 
sps30_do_reset(struct sps30_state * state)90 static int sps30_do_reset(struct sps30_state *state)
91 {
92 	int ret;
93 
94 	ret = state->ops->reset(state);
95 	if (ret)
96 		return ret;
97 
98 	state->state = RESET;
99 
100 	return 0;
101 }
102 
sps30_trigger_handler(int irq,void * p)103 static irqreturn_t sps30_trigger_handler(int irq, void *p)
104 {
105 	struct iio_poll_func *pf = p;
106 	struct iio_dev *indio_dev = pf->indio_dev;
107 	struct sps30_state *state = iio_priv(indio_dev);
108 	int ret;
109 	struct {
110 		s32 data[4]; /* PM1, PM2P5, PM4, PM10 */
111 		s64 ts;
112 	} scan;
113 
114 	mutex_lock(&state->lock);
115 	ret = sps30_do_meas(state, scan.data, ARRAY_SIZE(scan.data));
116 	mutex_unlock(&state->lock);
117 	if (ret)
118 		goto err;
119 
120 	iio_push_to_buffers_with_timestamp(indio_dev, &scan,
121 					   iio_get_time_ns(indio_dev));
122 err:
123 	iio_trigger_notify_done(indio_dev->trig);
124 
125 	return IRQ_HANDLED;
126 }
127 
sps30_read_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int * val,int * val2,long mask)128 static int sps30_read_raw(struct iio_dev *indio_dev,
129 			  struct iio_chan_spec const *chan,
130 			  int *val, int *val2, long mask)
131 {
132 	struct sps30_state *state = iio_priv(indio_dev);
133 	int data[4], ret = -EINVAL;
134 
135 	switch (mask) {
136 	case IIO_CHAN_INFO_PROCESSED:
137 		switch (chan->type) {
138 		case IIO_MASSCONCENTRATION:
139 			mutex_lock(&state->lock);
140 			/* read up to the number of bytes actually needed */
141 			switch (chan->channel2) {
142 			case IIO_MOD_PM1:
143 				ret = sps30_do_meas(state, data, 1);
144 				break;
145 			case IIO_MOD_PM2P5:
146 				ret = sps30_do_meas(state, data, 2);
147 				break;
148 			case IIO_MOD_PM4:
149 				ret = sps30_do_meas(state, data, 3);
150 				break;
151 			case IIO_MOD_PM10:
152 				ret = sps30_do_meas(state, data, 4);
153 				break;
154 			}
155 			mutex_unlock(&state->lock);
156 			if (ret)
157 				return ret;
158 
159 			*val = data[chan->address] / 100;
160 			*val2 = (data[chan->address] % 100) * 10000;
161 
162 			return IIO_VAL_INT_PLUS_MICRO;
163 		default:
164 			return -EINVAL;
165 		}
166 	case IIO_CHAN_INFO_SCALE:
167 		switch (chan->type) {
168 		case IIO_MASSCONCENTRATION:
169 			switch (chan->channel2) {
170 			case IIO_MOD_PM1:
171 			case IIO_MOD_PM2P5:
172 			case IIO_MOD_PM4:
173 			case IIO_MOD_PM10:
174 				*val = 0;
175 				*val2 = 10000;
176 
177 				return IIO_VAL_INT_PLUS_MICRO;
178 			default:
179 				return -EINVAL;
180 			}
181 		default:
182 			return -EINVAL;
183 		}
184 	}
185 
186 	return -EINVAL;
187 }
188 
start_cleaning_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t len)189 static ssize_t start_cleaning_store(struct device *dev,
190 				    struct device_attribute *attr,
191 				    const char *buf, size_t len)
192 {
193 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
194 	struct sps30_state *state = iio_priv(indio_dev);
195 	int val, ret;
196 
197 	if (kstrtoint(buf, 0, &val) || val != 1)
198 		return -EINVAL;
199 
200 	mutex_lock(&state->lock);
201 	ret = state->ops->clean_fan(state);
202 	mutex_unlock(&state->lock);
203 	if (ret)
204 		return ret;
205 
206 	return len;
207 }
208 
cleaning_period_show(struct device * dev,struct device_attribute * attr,char * buf)209 static ssize_t cleaning_period_show(struct device *dev,
210 				    struct device_attribute *attr,
211 				    char *buf)
212 {
213 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
214 	struct sps30_state *state = iio_priv(indio_dev);
215 	__be32 val;
216 	int ret;
217 
218 	mutex_lock(&state->lock);
219 	ret = state->ops->read_cleaning_period(state, &val);
220 	mutex_unlock(&state->lock);
221 	if (ret)
222 		return ret;
223 
224 	return sysfs_emit(buf, "%d\n", be32_to_cpu(val));
225 }
226 
cleaning_period_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t len)227 static ssize_t cleaning_period_store(struct device *dev, struct device_attribute *attr,
228 				     const char *buf, size_t len)
229 {
230 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
231 	struct sps30_state *state = iio_priv(indio_dev);
232 	int val, ret;
233 
234 	if (kstrtoint(buf, 0, &val))
235 		return -EINVAL;
236 
237 	if ((val < SPS30_AUTO_CLEANING_PERIOD_MIN) ||
238 	    (val > SPS30_AUTO_CLEANING_PERIOD_MAX))
239 		return -EINVAL;
240 
241 	mutex_lock(&state->lock);
242 	ret = state->ops->write_cleaning_period(state, cpu_to_be32(val));
243 	if (ret) {
244 		mutex_unlock(&state->lock);
245 		return ret;
246 	}
247 
248 	msleep(20);
249 
250 	/*
251 	 * sensor requires reset in order to return up to date self cleaning
252 	 * period
253 	 */
254 	ret = sps30_do_reset(state);
255 	if (ret)
256 		dev_warn(dev,
257 			 "period changed but reads will return the old value\n");
258 
259 	mutex_unlock(&state->lock);
260 
261 	return len;
262 }
263 
cleaning_period_available_show(struct device * dev,struct device_attribute * attr,char * buf)264 static ssize_t cleaning_period_available_show(struct device *dev,
265 					      struct device_attribute *attr,
266 					      char *buf)
267 {
268 	return sysfs_emit(buf, "[%d %d %d]\n",
269 			  SPS30_AUTO_CLEANING_PERIOD_MIN, 1,
270 			  SPS30_AUTO_CLEANING_PERIOD_MAX);
271 }
272 
273 static IIO_DEVICE_ATTR_WO(start_cleaning, 0);
274 static IIO_DEVICE_ATTR_RW(cleaning_period, 0);
275 static IIO_DEVICE_ATTR_RO(cleaning_period_available, 0);
276 
277 static struct attribute *sps30_attrs[] = {
278 	&iio_dev_attr_start_cleaning.dev_attr.attr,
279 	&iio_dev_attr_cleaning_period.dev_attr.attr,
280 	&iio_dev_attr_cleaning_period_available.dev_attr.attr,
281 	NULL
282 };
283 
284 static const struct attribute_group sps30_attr_group = {
285 	.attrs = sps30_attrs,
286 };
287 
288 static const struct iio_info sps30_info = {
289 	.attrs = &sps30_attr_group,
290 	.read_raw = sps30_read_raw,
291 };
292 
293 #define SPS30_CHAN(_index, _mod) { \
294 	.type = IIO_MASSCONCENTRATION, \
295 	.modified = 1, \
296 	.channel2 = IIO_MOD_ ## _mod, \
297 	.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), \
298 	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
299 	.address = _mod, \
300 	.scan_index = _index, \
301 	.scan_type = { \
302 		.sign = 'u', \
303 		.realbits = 19, \
304 		.storagebits = 32, \
305 		.endianness = IIO_CPU, \
306 	}, \
307 }
308 
309 static const struct iio_chan_spec sps30_channels[] = {
310 	SPS30_CHAN(0, PM1),
311 	SPS30_CHAN(1, PM2P5),
312 	SPS30_CHAN(2, PM4),
313 	SPS30_CHAN(3, PM10),
314 	IIO_CHAN_SOFT_TIMESTAMP(4),
315 };
316 
sps30_devm_stop_meas(void * data)317 static void sps30_devm_stop_meas(void *data)
318 {
319 	struct sps30_state *state = data;
320 
321 	if (state->state == MEASURING)
322 		state->ops->stop_meas(state);
323 }
324 
325 static const unsigned long sps30_scan_masks[] = { 0x0f, 0x00 };
326 
sps30_probe(struct device * dev,const char * name,void * priv,const struct sps30_ops * ops)327 int sps30_probe(struct device *dev, const char *name, void *priv, const struct sps30_ops *ops)
328 {
329 	struct iio_dev *indio_dev;
330 	struct sps30_state *state;
331 	int ret;
332 
333 	indio_dev = devm_iio_device_alloc(dev, sizeof(*state));
334 	if (!indio_dev)
335 		return -ENOMEM;
336 
337 	dev_set_drvdata(dev, indio_dev);
338 
339 	state = iio_priv(indio_dev);
340 	state->dev = dev;
341 	state->priv = priv;
342 	state->ops = ops;
343 	mutex_init(&state->lock);
344 
345 	indio_dev->info = &sps30_info;
346 	indio_dev->name = name;
347 	indio_dev->channels = sps30_channels;
348 	indio_dev->num_channels = ARRAY_SIZE(sps30_channels);
349 	indio_dev->modes = INDIO_DIRECT_MODE;
350 	indio_dev->available_scan_masks = sps30_scan_masks;
351 
352 	ret = sps30_do_reset(state);
353 	if (ret) {
354 		dev_err(dev, "failed to reset device\n");
355 		return ret;
356 	}
357 
358 	ret = state->ops->show_info(state);
359 	if (ret) {
360 		dev_err(dev, "failed to read device info\n");
361 		return ret;
362 	}
363 
364 	ret = devm_add_action_or_reset(dev, sps30_devm_stop_meas, state);
365 	if (ret)
366 		return ret;
367 
368 	ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL,
369 					      sps30_trigger_handler, NULL);
370 	if (ret)
371 		return ret;
372 
373 	return devm_iio_device_register(dev, indio_dev);
374 }
375 EXPORT_SYMBOL_NS_GPL(sps30_probe, IIO_SPS30);
376 
377 MODULE_AUTHOR("Tomasz Duszynski <tduszyns@gmail.com>");
378 MODULE_DESCRIPTION("Sensirion SPS30 particulate matter sensor driver");
379 MODULE_LICENSE("GPL v2");
380