• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * ccs811.c - Support for AMS CCS811 VOC Sensor
4  *
5  * Copyright (C) 2017 Narcisa Vasile <narcisaanamaria12@gmail.com>
6  *
7  * Datasheet: ams.com/content/download/951091/2269479/CCS811_DS000459_3-00.pdf
8  *
9  * IIO driver for AMS CCS811 (I2C address 0x5A/0x5B set by ADDR Low/High)
10  *
11  * TODO:
12  * 1. Make the drive mode selectable form userspace
13  * 2. Add support for interrupts
14  * 3. Adjust time to wait for data to be ready based on selected operation mode
15  * 4. Read error register and put the information in logs
16  */
17 
18 #include <linux/delay.h>
19 #include <linux/i2c.h>
20 #include <linux/iio/iio.h>
21 #include <linux/iio/buffer.h>
22 #include <linux/iio/trigger.h>
23 #include <linux/iio/triggered_buffer.h>
24 #include <linux/iio/trigger_consumer.h>
25 #include <linux/module.h>
26 
27 #define CCS811_STATUS		0x00
28 #define CCS811_MEAS_MODE	0x01
29 #define CCS811_ALG_RESULT_DATA	0x02
30 #define CCS811_RAW_DATA		0x03
31 #define CCS811_HW_ID		0x20
32 #define CCS811_HW_ID_VALUE	0x81
33 #define CCS811_HW_VERSION	0x21
34 #define CCS811_HW_VERSION_VALUE	0x10
35 #define CCS811_HW_VERSION_MASK	0xF0
36 #define CCS811_ERR		0xE0
37 /* Used to transition from boot to application mode */
38 #define CCS811_APP_START	0xF4
39 
40 /* Status register flags */
41 #define CCS811_STATUS_ERROR		BIT(0)
42 #define CCS811_STATUS_DATA_READY	BIT(3)
43 #define CCS811_STATUS_APP_VALID_MASK	BIT(4)
44 #define CCS811_STATUS_APP_VALID_LOADED	BIT(4)
45 /*
46  * Value of FW_MODE bit of STATUS register describes the sensor's state:
47  * 0: Firmware is in boot mode, this allows new firmware to be loaded
48  * 1: Firmware is in application mode. CCS811 is ready to take ADC measurements
49  */
50 #define CCS811_STATUS_FW_MODE_MASK	BIT(7)
51 #define CCS811_STATUS_FW_MODE_APPLICATION	BIT(7)
52 
53 /* Measurement modes */
54 #define CCS811_MODE_IDLE	0x00
55 #define CCS811_MODE_IAQ_1SEC	0x10
56 #define CCS811_MODE_IAQ_10SEC	0x20
57 #define CCS811_MODE_IAQ_60SEC	0x30
58 #define CCS811_MODE_RAW_DATA	0x40
59 
60 #define CCS811_MEAS_MODE_INTERRUPT	BIT(3)
61 
62 #define CCS811_VOLTAGE_MASK	0x3FF
63 
64 struct ccs811_reading {
65 	__be16 co2;
66 	__be16 voc;
67 	u8 status;
68 	u8 error;
69 	__be16 raw_data;
70 } __attribute__((__packed__));
71 
72 struct ccs811_data {
73 	struct i2c_client *client;
74 	struct mutex lock; /* Protect readings */
75 	struct ccs811_reading buffer;
76 	struct iio_trigger *drdy_trig;
77 	bool drdy_trig_on;
78 	/* Ensures correct alignment of timestamp if present */
79 	struct {
80 		s16 channels[2];
81 		s64 ts __aligned(8);
82 	} scan;
83 };
84 
85 static const struct iio_chan_spec ccs811_channels[] = {
86 	{
87 		.type = IIO_CURRENT,
88 		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
89 				      BIT(IIO_CHAN_INFO_SCALE),
90 		.scan_index = -1,
91 	}, {
92 		.type = IIO_VOLTAGE,
93 		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
94 				      BIT(IIO_CHAN_INFO_SCALE),
95 		.scan_index = -1,
96 	}, {
97 		.type = IIO_CONCENTRATION,
98 		.channel2 = IIO_MOD_CO2,
99 		.modified = 1,
100 		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
101 				      BIT(IIO_CHAN_INFO_SCALE),
102 		.scan_index = 0,
103 		.scan_type = {
104 			.sign = 'u',
105 			.realbits = 16,
106 			.storagebits = 16,
107 			.endianness = IIO_BE,
108 		},
109 	}, {
110 		.type = IIO_CONCENTRATION,
111 		.channel2 = IIO_MOD_VOC,
112 		.modified = 1,
113 		.info_mask_separate =  BIT(IIO_CHAN_INFO_RAW) |
114 				       BIT(IIO_CHAN_INFO_SCALE),
115 		.scan_index = 1,
116 		.scan_type = {
117 			.sign = 'u',
118 			.realbits = 16,
119 			.storagebits = 16,
120 			.endianness = IIO_BE,
121 		},
122 	},
123 	IIO_CHAN_SOFT_TIMESTAMP(2),
124 };
125 
126 /*
127  * The CCS811 powers-up in boot mode. A setup write to CCS811_APP_START will
128  * transition the sensor to application mode.
129  */
ccs811_start_sensor_application(struct i2c_client * client)130 static int ccs811_start_sensor_application(struct i2c_client *client)
131 {
132 	int ret;
133 
134 	ret = i2c_smbus_read_byte_data(client, CCS811_STATUS);
135 	if (ret < 0)
136 		return ret;
137 
138 	if ((ret & CCS811_STATUS_FW_MODE_APPLICATION))
139 		return 0;
140 
141 	if ((ret & CCS811_STATUS_APP_VALID_MASK) !=
142 	    CCS811_STATUS_APP_VALID_LOADED)
143 		return -EIO;
144 
145 	ret = i2c_smbus_write_byte(client, CCS811_APP_START);
146 	if (ret < 0)
147 		return ret;
148 
149 	ret = i2c_smbus_read_byte_data(client, CCS811_STATUS);
150 	if (ret < 0)
151 		return ret;
152 
153 	if ((ret & CCS811_STATUS_FW_MODE_MASK) !=
154 	    CCS811_STATUS_FW_MODE_APPLICATION) {
155 		dev_err(&client->dev, "Application failed to start. Sensor is still in boot mode.\n");
156 		return -EIO;
157 	}
158 
159 	return 0;
160 }
161 
ccs811_setup(struct i2c_client * client)162 static int ccs811_setup(struct i2c_client *client)
163 {
164 	int ret;
165 
166 	ret = ccs811_start_sensor_application(client);
167 	if (ret < 0)
168 		return ret;
169 
170 	return i2c_smbus_write_byte_data(client, CCS811_MEAS_MODE,
171 					 CCS811_MODE_IAQ_1SEC);
172 }
173 
ccs811_get_measurement(struct ccs811_data * data)174 static int ccs811_get_measurement(struct ccs811_data *data)
175 {
176 	int ret, tries = 11;
177 
178 	/* Maximum waiting time: 1s, as measurements are made every second */
179 	while (tries-- > 0) {
180 		ret = i2c_smbus_read_byte_data(data->client, CCS811_STATUS);
181 		if (ret < 0)
182 			return ret;
183 
184 		if ((ret & CCS811_STATUS_DATA_READY) || tries == 0)
185 			break;
186 		msleep(100);
187 	}
188 	if (!(ret & CCS811_STATUS_DATA_READY))
189 		return -EIO;
190 
191 	return i2c_smbus_read_i2c_block_data(data->client,
192 					    CCS811_ALG_RESULT_DATA, 8,
193 					    (char *)&data->buffer);
194 }
195 
ccs811_read_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int * val,int * val2,long mask)196 static int ccs811_read_raw(struct iio_dev *indio_dev,
197 			   struct iio_chan_spec const *chan,
198 			   int *val, int *val2, long mask)
199 {
200 	struct ccs811_data *data = iio_priv(indio_dev);
201 	int ret;
202 
203 	switch (mask) {
204 	case IIO_CHAN_INFO_RAW:
205 		ret = iio_device_claim_direct_mode(indio_dev);
206 		if (ret)
207 			return ret;
208 		mutex_lock(&data->lock);
209 		ret = ccs811_get_measurement(data);
210 		if (ret < 0) {
211 			mutex_unlock(&data->lock);
212 			iio_device_release_direct_mode(indio_dev);
213 			return ret;
214 		}
215 
216 		switch (chan->type) {
217 		case IIO_VOLTAGE:
218 			*val = be16_to_cpu(data->buffer.raw_data) &
219 					   CCS811_VOLTAGE_MASK;
220 			ret = IIO_VAL_INT;
221 			break;
222 		case IIO_CURRENT:
223 			*val = be16_to_cpu(data->buffer.raw_data) >> 10;
224 			ret = IIO_VAL_INT;
225 			break;
226 		case IIO_CONCENTRATION:
227 			switch (chan->channel2) {
228 			case IIO_MOD_CO2:
229 				*val = be16_to_cpu(data->buffer.co2);
230 				ret =  IIO_VAL_INT;
231 				break;
232 			case IIO_MOD_VOC:
233 				*val = be16_to_cpu(data->buffer.voc);
234 				ret = IIO_VAL_INT;
235 				break;
236 			default:
237 				ret = -EINVAL;
238 			}
239 			break;
240 		default:
241 			ret = -EINVAL;
242 		}
243 		mutex_unlock(&data->lock);
244 		iio_device_release_direct_mode(indio_dev);
245 
246 		return ret;
247 
248 	case IIO_CHAN_INFO_SCALE:
249 		switch (chan->type) {
250 		case IIO_VOLTAGE:
251 			*val = 1;
252 			*val2 = 612903;
253 			return IIO_VAL_INT_PLUS_MICRO;
254 		case IIO_CURRENT:
255 			*val = 0;
256 			*val2 = 1000;
257 			return IIO_VAL_INT_PLUS_MICRO;
258 		case IIO_CONCENTRATION:
259 			switch (chan->channel2) {
260 			case IIO_MOD_CO2:
261 				*val = 0;
262 				*val2 = 100;
263 				return IIO_VAL_INT_PLUS_MICRO;
264 			case IIO_MOD_VOC:
265 				*val = 0;
266 				*val2 = 100;
267 				return IIO_VAL_INT_PLUS_NANO;
268 			default:
269 				return -EINVAL;
270 			}
271 		default:
272 			return -EINVAL;
273 		}
274 	default:
275 		return -EINVAL;
276 	}
277 }
278 
279 static const struct iio_info ccs811_info = {
280 	.read_raw = ccs811_read_raw,
281 };
282 
ccs811_set_trigger_state(struct iio_trigger * trig,bool state)283 static int ccs811_set_trigger_state(struct iio_trigger *trig,
284 				    bool state)
285 {
286 	struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
287 	struct ccs811_data *data = iio_priv(indio_dev);
288 	int ret;
289 
290 	ret = i2c_smbus_read_byte_data(data->client, CCS811_MEAS_MODE);
291 	if (ret < 0)
292 		return ret;
293 
294 	if (state)
295 		ret |= CCS811_MEAS_MODE_INTERRUPT;
296 	else
297 		ret &= ~CCS811_MEAS_MODE_INTERRUPT;
298 
299 	data->drdy_trig_on = state;
300 
301 	return i2c_smbus_write_byte_data(data->client, CCS811_MEAS_MODE, ret);
302 }
303 
304 static const struct iio_trigger_ops ccs811_trigger_ops = {
305 	.set_trigger_state = ccs811_set_trigger_state,
306 };
307 
ccs811_trigger_handler(int irq,void * p)308 static irqreturn_t ccs811_trigger_handler(int irq, void *p)
309 {
310 	struct iio_poll_func *pf = p;
311 	struct iio_dev *indio_dev = pf->indio_dev;
312 	struct ccs811_data *data = iio_priv(indio_dev);
313 	struct i2c_client *client = data->client;
314 	int ret;
315 
316 	ret = i2c_smbus_read_i2c_block_data(client, CCS811_ALG_RESULT_DATA,
317 					    sizeof(data->scan.channels),
318 					    (u8 *)data->scan.channels);
319 	if (ret != 4) {
320 		dev_err(&client->dev, "cannot read sensor data\n");
321 		goto err;
322 	}
323 
324 	iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
325 					   iio_get_time_ns(indio_dev));
326 
327 err:
328 	iio_trigger_notify_done(indio_dev->trig);
329 
330 	return IRQ_HANDLED;
331 }
332 
ccs811_data_rdy_trigger_poll(int irq,void * private)333 static irqreturn_t ccs811_data_rdy_trigger_poll(int irq, void *private)
334 {
335 	struct iio_dev *indio_dev = private;
336 	struct ccs811_data *data = iio_priv(indio_dev);
337 
338 	if (data->drdy_trig_on)
339 		iio_trigger_poll(data->drdy_trig);
340 
341 	return IRQ_HANDLED;
342 }
343 
ccs811_probe(struct i2c_client * client,const struct i2c_device_id * id)344 static int ccs811_probe(struct i2c_client *client,
345 			const struct i2c_device_id *id)
346 {
347 	struct iio_dev *indio_dev;
348 	struct ccs811_data *data;
349 	int ret;
350 
351 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WRITE_BYTE
352 				     | I2C_FUNC_SMBUS_BYTE_DATA
353 				     | I2C_FUNC_SMBUS_READ_I2C_BLOCK))
354 		return -EOPNOTSUPP;
355 
356 	/* Check hardware id (should be 0x81 for this family of devices) */
357 	ret = i2c_smbus_read_byte_data(client, CCS811_HW_ID);
358 	if (ret < 0)
359 		return ret;
360 
361 	if (ret != CCS811_HW_ID_VALUE) {
362 		dev_err(&client->dev, "hardware id doesn't match CCS81x\n");
363 		return -ENODEV;
364 	}
365 
366 	ret = i2c_smbus_read_byte_data(client, CCS811_HW_VERSION);
367 	if (ret < 0)
368 		return ret;
369 
370 	if ((ret & CCS811_HW_VERSION_MASK) != CCS811_HW_VERSION_VALUE) {
371 		dev_err(&client->dev, "no CCS811 sensor\n");
372 		return -ENODEV;
373 	}
374 
375 	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
376 	if (!indio_dev)
377 		return -ENOMEM;
378 
379 	ret = ccs811_setup(client);
380 	if (ret < 0)
381 		return ret;
382 
383 	data = iio_priv(indio_dev);
384 	i2c_set_clientdata(client, indio_dev);
385 	data->client = client;
386 
387 	mutex_init(&data->lock);
388 
389 	indio_dev->dev.parent = &client->dev;
390 	indio_dev->name = id->name;
391 	indio_dev->info = &ccs811_info;
392 	indio_dev->modes = INDIO_DIRECT_MODE;
393 
394 	indio_dev->channels = ccs811_channels;
395 	indio_dev->num_channels = ARRAY_SIZE(ccs811_channels);
396 
397 	if (client->irq > 0) {
398 		ret = devm_request_threaded_irq(&client->dev, client->irq,
399 						ccs811_data_rdy_trigger_poll,
400 						NULL,
401 						IRQF_TRIGGER_FALLING |
402 						IRQF_ONESHOT,
403 						"ccs811_irq", indio_dev);
404 		if (ret) {
405 			dev_err(&client->dev, "irq request error %d\n", -ret);
406 			goto err_poweroff;
407 		}
408 
409 		data->drdy_trig = devm_iio_trigger_alloc(&client->dev,
410 							 "%s-dev%d",
411 							 indio_dev->name,
412 							 indio_dev->id);
413 		if (!data->drdy_trig) {
414 			ret = -ENOMEM;
415 			goto err_poweroff;
416 		}
417 
418 		data->drdy_trig->dev.parent = &client->dev;
419 		data->drdy_trig->ops = &ccs811_trigger_ops;
420 		iio_trigger_set_drvdata(data->drdy_trig, indio_dev);
421 		ret = iio_trigger_register(data->drdy_trig);
422 		if (ret)
423 			goto err_poweroff;
424 
425 		indio_dev->trig = iio_trigger_get(data->drdy_trig);
426 	}
427 
428 	ret = iio_triggered_buffer_setup(indio_dev, NULL,
429 					 ccs811_trigger_handler, NULL);
430 
431 	if (ret < 0) {
432 		dev_err(&client->dev, "triggered buffer setup failed\n");
433 		goto err_trigger_unregister;
434 	}
435 
436 	ret = iio_device_register(indio_dev);
437 	if (ret < 0) {
438 		dev_err(&client->dev, "unable to register iio device\n");
439 		goto err_buffer_cleanup;
440 	}
441 	return 0;
442 
443 err_buffer_cleanup:
444 	iio_triggered_buffer_cleanup(indio_dev);
445 err_trigger_unregister:
446 	if (data->drdy_trig)
447 		iio_trigger_unregister(data->drdy_trig);
448 err_poweroff:
449 	i2c_smbus_write_byte_data(client, CCS811_MEAS_MODE, CCS811_MODE_IDLE);
450 
451 	return ret;
452 }
453 
ccs811_remove(struct i2c_client * client)454 static int ccs811_remove(struct i2c_client *client)
455 {
456 	struct iio_dev *indio_dev = i2c_get_clientdata(client);
457 	struct ccs811_data *data = iio_priv(indio_dev);
458 
459 	iio_device_unregister(indio_dev);
460 	iio_triggered_buffer_cleanup(indio_dev);
461 	if (data->drdy_trig)
462 		iio_trigger_unregister(data->drdy_trig);
463 
464 	return i2c_smbus_write_byte_data(client, CCS811_MEAS_MODE,
465 					 CCS811_MODE_IDLE);
466 }
467 
468 static const struct i2c_device_id ccs811_id[] = {
469 	{"ccs811", 0},
470 	{	}
471 };
472 MODULE_DEVICE_TABLE(i2c, ccs811_id);
473 
474 static struct i2c_driver ccs811_driver = {
475 	.driver = {
476 		.name = "ccs811",
477 	},
478 	.probe = ccs811_probe,
479 	.remove = ccs811_remove,
480 	.id_table = ccs811_id,
481 };
482 module_i2c_driver(ccs811_driver);
483 
484 MODULE_AUTHOR("Narcisa Vasile <narcisaanamaria12@gmail.com>");
485 MODULE_DESCRIPTION("CCS811 volatile organic compounds sensor");
486 MODULE_LICENSE("GPL v2");
487