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