root/drivers/iio/chemical/ccs811.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ccs811_start_sensor_application
  2. ccs811_setup
  3. ccs811_get_measurement
  4. ccs811_read_raw
  5. ccs811_set_trigger_state
  6. ccs811_trigger_handler
  7. ccs811_data_rdy_trigger_poll
  8. ccs811_probe
  9. ccs811_remove

   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 };
  79 
  80 static const struct iio_chan_spec ccs811_channels[] = {
  81         {
  82                 .type = IIO_CURRENT,
  83                 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
  84                                       BIT(IIO_CHAN_INFO_SCALE),
  85                 .scan_index = -1,
  86         }, {
  87                 .type = IIO_VOLTAGE,
  88                 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
  89                                       BIT(IIO_CHAN_INFO_SCALE),
  90                 .scan_index = -1,
  91         }, {
  92                 .type = IIO_CONCENTRATION,
  93                 .channel2 = IIO_MOD_CO2,
  94                 .modified = 1,
  95                 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
  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                 },
 104         }, {
 105                 .type = IIO_CONCENTRATION,
 106                 .channel2 = IIO_MOD_VOC,
 107                 .modified = 1,
 108                 .info_mask_separate =  BIT(IIO_CHAN_INFO_RAW) |
 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                 },
 117         },
 118         IIO_CHAN_SOFT_TIMESTAMP(2),
 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  */
 125 static 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 
 133         if ((ret & CCS811_STATUS_FW_MODE_APPLICATION))
 134                 return 0;
 135 
 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 
 157 static 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 
 169 static 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 
 191 static 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:
 200                 ret = iio_device_claim_direct_mode(indio_dev);
 201                 if (ret)
 202                         return ret;
 203                 mutex_lock(&data->lock);
 204                 ret = ccs811_get_measurement(data);
 205                 if (ret < 0) {
 206                         mutex_unlock(&data->lock);
 207                         iio_device_release_direct_mode(indio_dev);
 208                         return ret;
 209                 }
 210 
 211                 switch (chan->type) {
 212                 case IIO_VOLTAGE:
 213                         *val = be16_to_cpu(data->buffer.raw_data) &
 214                                            CCS811_VOLTAGE_MASK;
 215                         ret = IIO_VAL_INT;
 216                         break;
 217                 case IIO_CURRENT:
 218                         *val = be16_to_cpu(data->buffer.raw_data) >> 10;
 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);
 239                 iio_device_release_direct_mode(indio_dev);
 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;
 257                                 *val2 = 100;
 258                                 return IIO_VAL_INT_PLUS_MICRO;
 259                         case IIO_MOD_VOC:
 260                                 *val = 0;
 261                                 *val2 = 100;
 262                                 return IIO_VAL_INT_PLUS_NANO;
 263                         default:
 264                                 return -EINVAL;
 265                         }
 266                 default:
 267                         return -EINVAL;
 268                 }
 269         default:
 270                 return -EINVAL;
 271         }
 272 }
 273 
 274 static const struct iio_info ccs811_info = {
 275         .read_raw = ccs811_read_raw,
 276 };
 277 
 278 static 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 
 299 static const struct iio_trigger_ops ccs811_trigger_ops = {
 300         .set_trigger_state = ccs811_set_trigger_state,
 301 };
 302 
 303 static 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 
 322 err:
 323         iio_trigger_notify_done(indio_dev->trig);
 324 
 325         return IRQ_HANDLED;
 326 }
 327 
 328 static 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 
 339 static 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 
 356         if (ret != CCS811_HW_ID_VALUE) {
 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;
 387         indio_dev->modes = INDIO_DIRECT_MODE;
 388 
 389         indio_dev->channels = ccs811_channels;
 390         indio_dev->num_channels = ARRAY_SIZE(ccs811_channels);
 391 
 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 
 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");
 428                 goto err_trigger_unregister;
 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 
 438 err_buffer_cleanup:
 439         iio_triggered_buffer_cleanup(indio_dev);
 440 err_trigger_unregister:
 441         if (data->drdy_trig)
 442                 iio_trigger_unregister(data->drdy_trig);
 443 err_poweroff:
 444         i2c_smbus_write_byte_data(client, CCS811_MEAS_MODE, CCS811_MODE_IDLE);
 445 
 446         return ret;
 447 }
 448 
 449 static int ccs811_remove(struct i2c_client *client)
 450 {
 451         struct iio_dev *indio_dev = i2c_get_clientdata(client);
 452         struct ccs811_data *data = iio_priv(indio_dev);
 453 
 454         iio_device_unregister(indio_dev);
 455         iio_triggered_buffer_cleanup(indio_dev);
 456         if (data->drdy_trig)
 457                 iio_trigger_unregister(data->drdy_trig);
 458 
 459         return i2c_smbus_write_byte_data(client, CCS811_MEAS_MODE,
 460                                          CCS811_MODE_IDLE);
 461 }
 462 
 463 static const struct i2c_device_id ccs811_id[] = {
 464         {"ccs811", 0},
 465         {       }
 466 };
 467 MODULE_DEVICE_TABLE(i2c, ccs811_id);
 468 
 469 static 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 };
 477 module_i2c_driver(ccs811_driver);
 478 
 479 MODULE_AUTHOR("Narcisa Vasile <narcisaanamaria12@gmail.com>");
 480 MODULE_DESCRIPTION("CCS811 volatile organic compounds sensor");
 481 MODULE_LICENSE("GPL v2");

/* [<][>][^][v][top][bottom][index][help] */