Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * ccs811.c - Support for AMS CCS811 VOC Sensor
0004  *
0005  * Copyright (C) 2017 Narcisa Vasile <narcisaanamaria12@gmail.com>
0006  *
0007  * Datasheet: ams.com/content/download/951091/2269479/CCS811_DS000459_3-00.pdf
0008  *
0009  * IIO driver for AMS CCS811 (I2C address 0x5A/0x5B set by ADDR Low/High)
0010  *
0011  * TODO:
0012  * 1. Make the drive mode selectable form userspace
0013  * 2. Add support for interrupts
0014  * 3. Adjust time to wait for data to be ready based on selected operation mode
0015  * 4. Read error register and put the information in logs
0016  */
0017 
0018 #include <linux/delay.h>
0019 #include <linux/gpio/consumer.h>
0020 #include <linux/i2c.h>
0021 #include <linux/iio/iio.h>
0022 #include <linux/iio/buffer.h>
0023 #include <linux/iio/trigger.h>
0024 #include <linux/iio/triggered_buffer.h>
0025 #include <linux/iio/trigger_consumer.h>
0026 #include <linux/module.h>
0027 
0028 #define CCS811_STATUS       0x00
0029 #define CCS811_MEAS_MODE    0x01
0030 #define CCS811_ALG_RESULT_DATA  0x02
0031 #define CCS811_RAW_DATA     0x03
0032 #define CCS811_HW_ID        0x20
0033 #define CCS811_HW_ID_VALUE  0x81
0034 #define CCS811_HW_VERSION   0x21
0035 #define CCS811_HW_VERSION_VALUE 0x10
0036 #define CCS811_HW_VERSION_MASK  0xF0
0037 #define CCS811_ERR      0xE0
0038 /* Used to transition from boot to application mode */
0039 #define CCS811_APP_START    0xF4
0040 #define CCS811_SW_RESET     0xFF
0041 
0042 /* Status register flags */
0043 #define CCS811_STATUS_ERROR     BIT(0)
0044 #define CCS811_STATUS_DATA_READY    BIT(3)
0045 #define CCS811_STATUS_APP_VALID_MASK    BIT(4)
0046 #define CCS811_STATUS_APP_VALID_LOADED  BIT(4)
0047 /*
0048  * Value of FW_MODE bit of STATUS register describes the sensor's state:
0049  * 0: Firmware is in boot mode, this allows new firmware to be loaded
0050  * 1: Firmware is in application mode. CCS811 is ready to take ADC measurements
0051  */
0052 #define CCS811_STATUS_FW_MODE_MASK  BIT(7)
0053 #define CCS811_STATUS_FW_MODE_APPLICATION   BIT(7)
0054 
0055 /* Measurement modes */
0056 #define CCS811_MODE_IDLE    0x00
0057 #define CCS811_MODE_IAQ_1SEC    0x10
0058 #define CCS811_MODE_IAQ_10SEC   0x20
0059 #define CCS811_MODE_IAQ_60SEC   0x30
0060 #define CCS811_MODE_RAW_DATA    0x40
0061 
0062 #define CCS811_MEAS_MODE_INTERRUPT  BIT(3)
0063 
0064 #define CCS811_VOLTAGE_MASK 0x3FF
0065 
0066 struct ccs811_reading {
0067     __be16 co2;
0068     __be16 voc;
0069     u8 status;
0070     u8 error;
0071     __be16 raw_data;
0072 } __attribute__((__packed__));
0073 
0074 struct ccs811_data {
0075     struct i2c_client *client;
0076     struct mutex lock; /* Protect readings */
0077     struct ccs811_reading buffer;
0078     struct iio_trigger *drdy_trig;
0079     struct gpio_desc *wakeup_gpio;
0080     bool drdy_trig_on;
0081     /* Ensures correct alignment of timestamp if present */
0082     struct {
0083         s16 channels[2];
0084         s64 ts __aligned(8);
0085     } scan;
0086 };
0087 
0088 static const struct iio_chan_spec ccs811_channels[] = {
0089     {
0090         .type = IIO_CURRENT,
0091         .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
0092                       BIT(IIO_CHAN_INFO_SCALE),
0093         .scan_index = -1,
0094     }, {
0095         .type = IIO_VOLTAGE,
0096         .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
0097                       BIT(IIO_CHAN_INFO_SCALE),
0098         .scan_index = -1,
0099     }, {
0100         .type = IIO_CONCENTRATION,
0101         .channel2 = IIO_MOD_CO2,
0102         .modified = 1,
0103         .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
0104                       BIT(IIO_CHAN_INFO_SCALE),
0105         .scan_index = 0,
0106         .scan_type = {
0107             .sign = 'u',
0108             .realbits = 16,
0109             .storagebits = 16,
0110             .endianness = IIO_BE,
0111         },
0112     }, {
0113         .type = IIO_CONCENTRATION,
0114         .channel2 = IIO_MOD_VOC,
0115         .modified = 1,
0116         .info_mask_separate =  BIT(IIO_CHAN_INFO_RAW) |
0117                        BIT(IIO_CHAN_INFO_SCALE),
0118         .scan_index = 1,
0119         .scan_type = {
0120             .sign = 'u',
0121             .realbits = 16,
0122             .storagebits = 16,
0123             .endianness = IIO_BE,
0124         },
0125     },
0126     IIO_CHAN_SOFT_TIMESTAMP(2),
0127 };
0128 
0129 /*
0130  * The CCS811 powers-up in boot mode. A setup write to CCS811_APP_START will
0131  * transition the sensor to application mode.
0132  */
0133 static int ccs811_start_sensor_application(struct i2c_client *client)
0134 {
0135     int ret;
0136 
0137     ret = i2c_smbus_read_byte_data(client, CCS811_STATUS);
0138     if (ret < 0)
0139         return ret;
0140 
0141     if ((ret & CCS811_STATUS_FW_MODE_APPLICATION))
0142         return 0;
0143 
0144     if ((ret & CCS811_STATUS_APP_VALID_MASK) !=
0145         CCS811_STATUS_APP_VALID_LOADED)
0146         return -EIO;
0147 
0148     ret = i2c_smbus_write_byte(client, CCS811_APP_START);
0149     if (ret < 0)
0150         return ret;
0151 
0152     ret = i2c_smbus_read_byte_data(client, CCS811_STATUS);
0153     if (ret < 0)
0154         return ret;
0155 
0156     if ((ret & CCS811_STATUS_FW_MODE_MASK) !=
0157         CCS811_STATUS_FW_MODE_APPLICATION) {
0158         dev_err(&client->dev, "Application failed to start. Sensor is still in boot mode.\n");
0159         return -EIO;
0160     }
0161 
0162     return 0;
0163 }
0164 
0165 static int ccs811_setup(struct i2c_client *client)
0166 {
0167     int ret;
0168 
0169     ret = ccs811_start_sensor_application(client);
0170     if (ret < 0)
0171         return ret;
0172 
0173     return i2c_smbus_write_byte_data(client, CCS811_MEAS_MODE,
0174                      CCS811_MODE_IAQ_1SEC);
0175 }
0176 
0177 static void ccs811_set_wakeup(struct ccs811_data *data, bool enable)
0178 {
0179     if (!data->wakeup_gpio)
0180         return;
0181 
0182     gpiod_set_value(data->wakeup_gpio, enable);
0183 
0184     if (enable)
0185         usleep_range(50, 60);
0186     else
0187         usleep_range(20, 30);
0188 }
0189 
0190 static int ccs811_get_measurement(struct ccs811_data *data)
0191 {
0192     int ret, tries = 11;
0193 
0194     ccs811_set_wakeup(data, true);
0195 
0196     /* Maximum waiting time: 1s, as measurements are made every second */
0197     while (tries-- > 0) {
0198         ret = i2c_smbus_read_byte_data(data->client, CCS811_STATUS);
0199         if (ret < 0)
0200             return ret;
0201 
0202         if ((ret & CCS811_STATUS_DATA_READY) || tries == 0)
0203             break;
0204         msleep(100);
0205     }
0206     if (!(ret & CCS811_STATUS_DATA_READY))
0207         return -EIO;
0208 
0209     ret = i2c_smbus_read_i2c_block_data(data->client,
0210                         CCS811_ALG_RESULT_DATA, 8,
0211                         (char *)&data->buffer);
0212     ccs811_set_wakeup(data, false);
0213 
0214     return ret;
0215 }
0216 
0217 static int ccs811_read_raw(struct iio_dev *indio_dev,
0218                struct iio_chan_spec const *chan,
0219                int *val, int *val2, long mask)
0220 {
0221     struct ccs811_data *data = iio_priv(indio_dev);
0222     int ret;
0223 
0224     switch (mask) {
0225     case IIO_CHAN_INFO_RAW:
0226         ret = iio_device_claim_direct_mode(indio_dev);
0227         if (ret)
0228             return ret;
0229         mutex_lock(&data->lock);
0230         ret = ccs811_get_measurement(data);
0231         if (ret < 0) {
0232             mutex_unlock(&data->lock);
0233             iio_device_release_direct_mode(indio_dev);
0234             return ret;
0235         }
0236 
0237         switch (chan->type) {
0238         case IIO_VOLTAGE:
0239             *val = be16_to_cpu(data->buffer.raw_data) &
0240                        CCS811_VOLTAGE_MASK;
0241             ret = IIO_VAL_INT;
0242             break;
0243         case IIO_CURRENT:
0244             *val = be16_to_cpu(data->buffer.raw_data) >> 10;
0245             ret = IIO_VAL_INT;
0246             break;
0247         case IIO_CONCENTRATION:
0248             switch (chan->channel2) {
0249             case IIO_MOD_CO2:
0250                 *val = be16_to_cpu(data->buffer.co2);
0251                 ret =  IIO_VAL_INT;
0252                 break;
0253             case IIO_MOD_VOC:
0254                 *val = be16_to_cpu(data->buffer.voc);
0255                 ret = IIO_VAL_INT;
0256                 break;
0257             default:
0258                 ret = -EINVAL;
0259             }
0260             break;
0261         default:
0262             ret = -EINVAL;
0263         }
0264         mutex_unlock(&data->lock);
0265         iio_device_release_direct_mode(indio_dev);
0266 
0267         return ret;
0268 
0269     case IIO_CHAN_INFO_SCALE:
0270         switch (chan->type) {
0271         case IIO_VOLTAGE:
0272             *val = 1;
0273             *val2 = 612903;
0274             return IIO_VAL_INT_PLUS_MICRO;
0275         case IIO_CURRENT:
0276             *val = 0;
0277             *val2 = 1000;
0278             return IIO_VAL_INT_PLUS_MICRO;
0279         case IIO_CONCENTRATION:
0280             switch (chan->channel2) {
0281             case IIO_MOD_CO2:
0282                 *val = 0;
0283                 *val2 = 100;
0284                 return IIO_VAL_INT_PLUS_MICRO;
0285             case IIO_MOD_VOC:
0286                 *val = 0;
0287                 *val2 = 100;
0288                 return IIO_VAL_INT_PLUS_NANO;
0289             default:
0290                 return -EINVAL;
0291             }
0292         default:
0293             return -EINVAL;
0294         }
0295     default:
0296         return -EINVAL;
0297     }
0298 }
0299 
0300 static const struct iio_info ccs811_info = {
0301     .read_raw = ccs811_read_raw,
0302 };
0303 
0304 static int ccs811_set_trigger_state(struct iio_trigger *trig,
0305                     bool state)
0306 {
0307     struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
0308     struct ccs811_data *data = iio_priv(indio_dev);
0309     int ret;
0310 
0311     ret = i2c_smbus_read_byte_data(data->client, CCS811_MEAS_MODE);
0312     if (ret < 0)
0313         return ret;
0314 
0315     if (state)
0316         ret |= CCS811_MEAS_MODE_INTERRUPT;
0317     else
0318         ret &= ~CCS811_MEAS_MODE_INTERRUPT;
0319 
0320     data->drdy_trig_on = state;
0321 
0322     return i2c_smbus_write_byte_data(data->client, CCS811_MEAS_MODE, ret);
0323 }
0324 
0325 static const struct iio_trigger_ops ccs811_trigger_ops = {
0326     .set_trigger_state = ccs811_set_trigger_state,
0327 };
0328 
0329 static irqreturn_t ccs811_trigger_handler(int irq, void *p)
0330 {
0331     struct iio_poll_func *pf = p;
0332     struct iio_dev *indio_dev = pf->indio_dev;
0333     struct ccs811_data *data = iio_priv(indio_dev);
0334     struct i2c_client *client = data->client;
0335     int ret;
0336 
0337     ret = i2c_smbus_read_i2c_block_data(client, CCS811_ALG_RESULT_DATA,
0338                         sizeof(data->scan.channels),
0339                         (u8 *)data->scan.channels);
0340     if (ret != 4) {
0341         dev_err(&client->dev, "cannot read sensor data\n");
0342         goto err;
0343     }
0344 
0345     iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
0346                        iio_get_time_ns(indio_dev));
0347 
0348 err:
0349     iio_trigger_notify_done(indio_dev->trig);
0350 
0351     return IRQ_HANDLED;
0352 }
0353 
0354 static irqreturn_t ccs811_data_rdy_trigger_poll(int irq, void *private)
0355 {
0356     struct iio_dev *indio_dev = private;
0357     struct ccs811_data *data = iio_priv(indio_dev);
0358 
0359     if (data->drdy_trig_on)
0360         iio_trigger_poll(data->drdy_trig);
0361 
0362     return IRQ_HANDLED;
0363 }
0364 
0365 static int ccs811_reset(struct i2c_client *client)
0366 {
0367     struct gpio_desc *reset_gpio;
0368     int ret;
0369 
0370     reset_gpio = devm_gpiod_get_optional(&client->dev, "reset",
0371                          GPIOD_OUT_LOW);
0372     if (IS_ERR(reset_gpio))
0373         return PTR_ERR(reset_gpio);
0374 
0375     /* Try to reset using nRESET pin if available else do SW reset */
0376     if (reset_gpio) {
0377         gpiod_set_value(reset_gpio, 1);
0378         usleep_range(20, 30);
0379         gpiod_set_value(reset_gpio, 0);
0380     } else {
0381         /*
0382          * As per the datasheet, this sequence of values needs to be
0383          * written to the SW_RESET register for triggering the soft
0384          * reset in the device and placing it in boot mode.
0385          */
0386         static const u8 reset_seq[] = {
0387             0x11, 0xE5, 0x72, 0x8A,
0388         };
0389 
0390         ret = i2c_smbus_write_i2c_block_data(client, CCS811_SW_RESET,
0391                          sizeof(reset_seq), reset_seq);
0392         if (ret < 0) {
0393             dev_err(&client->dev, "Failed to reset sensor\n");
0394             return ret;
0395         }
0396     }
0397 
0398     /* tSTART delay required after reset */
0399     usleep_range(1000, 2000);
0400 
0401     return 0;
0402 }
0403 
0404 static int ccs811_probe(struct i2c_client *client,
0405             const struct i2c_device_id *id)
0406 {
0407     struct iio_dev *indio_dev;
0408     struct ccs811_data *data;
0409     int ret;
0410 
0411     if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WRITE_BYTE
0412                      | I2C_FUNC_SMBUS_BYTE_DATA
0413                      | I2C_FUNC_SMBUS_READ_I2C_BLOCK))
0414         return -EOPNOTSUPP;
0415 
0416     indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
0417     if (!indio_dev)
0418         return -ENOMEM;
0419 
0420     data = iio_priv(indio_dev);
0421     i2c_set_clientdata(client, indio_dev);
0422     data->client = client;
0423 
0424     data->wakeup_gpio = devm_gpiod_get_optional(&client->dev, "wakeup",
0425                             GPIOD_OUT_HIGH);
0426     if (IS_ERR(data->wakeup_gpio))
0427         return PTR_ERR(data->wakeup_gpio);
0428 
0429     ccs811_set_wakeup(data, true);
0430 
0431     ret = ccs811_reset(client);
0432     if (ret) {
0433         ccs811_set_wakeup(data, false);
0434         return ret;
0435     }
0436 
0437     /* Check hardware id (should be 0x81 for this family of devices) */
0438     ret = i2c_smbus_read_byte_data(client, CCS811_HW_ID);
0439     if (ret < 0) {
0440         ccs811_set_wakeup(data, false);
0441         return ret;
0442     }
0443 
0444     if (ret != CCS811_HW_ID_VALUE) {
0445         dev_err(&client->dev, "hardware id doesn't match CCS81x\n");
0446         ccs811_set_wakeup(data, false);
0447         return -ENODEV;
0448     }
0449 
0450     ret = i2c_smbus_read_byte_data(client, CCS811_HW_VERSION);
0451     if (ret < 0) {
0452         ccs811_set_wakeup(data, false);
0453         return ret;
0454     }
0455 
0456     if ((ret & CCS811_HW_VERSION_MASK) != CCS811_HW_VERSION_VALUE) {
0457         dev_err(&client->dev, "no CCS811 sensor\n");
0458         ccs811_set_wakeup(data, false);
0459         return -ENODEV;
0460     }
0461 
0462     ret = ccs811_setup(client);
0463     if (ret < 0) {
0464         ccs811_set_wakeup(data, false);
0465         return ret;
0466     }
0467 
0468     ccs811_set_wakeup(data, false);
0469 
0470     mutex_init(&data->lock);
0471 
0472     indio_dev->name = id->name;
0473     indio_dev->info = &ccs811_info;
0474     indio_dev->modes = INDIO_DIRECT_MODE;
0475 
0476     indio_dev->channels = ccs811_channels;
0477     indio_dev->num_channels = ARRAY_SIZE(ccs811_channels);
0478 
0479     if (client->irq > 0) {
0480         ret = devm_request_threaded_irq(&client->dev, client->irq,
0481                         ccs811_data_rdy_trigger_poll,
0482                         NULL,
0483                         IRQF_TRIGGER_FALLING |
0484                         IRQF_ONESHOT,
0485                         "ccs811_irq", indio_dev);
0486         if (ret) {
0487             dev_err(&client->dev, "irq request error %d\n", -ret);
0488             goto err_poweroff;
0489         }
0490 
0491         data->drdy_trig = devm_iio_trigger_alloc(&client->dev,
0492                              "%s-dev%d",
0493                              indio_dev->name,
0494                              iio_device_id(indio_dev));
0495         if (!data->drdy_trig) {
0496             ret = -ENOMEM;
0497             goto err_poweroff;
0498         }
0499 
0500         data->drdy_trig->ops = &ccs811_trigger_ops;
0501         iio_trigger_set_drvdata(data->drdy_trig, indio_dev);
0502         ret = iio_trigger_register(data->drdy_trig);
0503         if (ret)
0504             goto err_poweroff;
0505 
0506         indio_dev->trig = iio_trigger_get(data->drdy_trig);
0507     }
0508 
0509     ret = iio_triggered_buffer_setup(indio_dev, NULL,
0510                      ccs811_trigger_handler, NULL);
0511 
0512     if (ret < 0) {
0513         dev_err(&client->dev, "triggered buffer setup failed\n");
0514         goto err_trigger_unregister;
0515     }
0516 
0517     ret = iio_device_register(indio_dev);
0518     if (ret < 0) {
0519         dev_err(&client->dev, "unable to register iio device\n");
0520         goto err_buffer_cleanup;
0521     }
0522     return 0;
0523 
0524 err_buffer_cleanup:
0525     iio_triggered_buffer_cleanup(indio_dev);
0526 err_trigger_unregister:
0527     if (data->drdy_trig)
0528         iio_trigger_unregister(data->drdy_trig);
0529 err_poweroff:
0530     i2c_smbus_write_byte_data(client, CCS811_MEAS_MODE, CCS811_MODE_IDLE);
0531 
0532     return ret;
0533 }
0534 
0535 static int ccs811_remove(struct i2c_client *client)
0536 {
0537     struct iio_dev *indio_dev = i2c_get_clientdata(client);
0538     struct ccs811_data *data = iio_priv(indio_dev);
0539     int ret;
0540 
0541     iio_device_unregister(indio_dev);
0542     iio_triggered_buffer_cleanup(indio_dev);
0543     if (data->drdy_trig)
0544         iio_trigger_unregister(data->drdy_trig);
0545 
0546     ret = i2c_smbus_write_byte_data(client, CCS811_MEAS_MODE,
0547                     CCS811_MODE_IDLE);
0548     if (ret)
0549         dev_warn(&client->dev, "Failed to power down device (%pe)\n",
0550              ERR_PTR(ret));
0551 
0552     return 0;
0553 }
0554 
0555 static const struct i2c_device_id ccs811_id[] = {
0556     {"ccs811", 0},
0557     {   }
0558 };
0559 MODULE_DEVICE_TABLE(i2c, ccs811_id);
0560 
0561 static const struct of_device_id ccs811_dt_ids[] = {
0562     { .compatible = "ams,ccs811" },
0563     { }
0564 };
0565 MODULE_DEVICE_TABLE(of, ccs811_dt_ids);
0566 
0567 static struct i2c_driver ccs811_driver = {
0568     .driver = {
0569         .name = "ccs811",
0570         .of_match_table = ccs811_dt_ids,
0571     },
0572     .probe = ccs811_probe,
0573     .remove = ccs811_remove,
0574     .id_table = ccs811_id,
0575 };
0576 module_i2c_driver(ccs811_driver);
0577 
0578 MODULE_AUTHOR("Narcisa Vasile <narcisaanamaria12@gmail.com>");
0579 MODULE_DESCRIPTION("CCS811 volatile organic compounds sensor");
0580 MODULE_LICENSE("GPL v2");