linux/drivers/iio/chemical/ccs811.c
<<
>>
Prefs
   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/gpio/consumer.h>
  20#include <linux/i2c.h>
  21#include <linux/iio/iio.h>
  22#include <linux/iio/buffer.h>
  23#include <linux/iio/trigger.h>
  24#include <linux/iio/triggered_buffer.h>
  25#include <linux/iio/trigger_consumer.h>
  26#include <linux/module.h>
  27
  28#define CCS811_STATUS           0x00
  29#define CCS811_MEAS_MODE        0x01
  30#define CCS811_ALG_RESULT_DATA  0x02
  31#define CCS811_RAW_DATA         0x03
  32#define CCS811_HW_ID            0x20
  33#define CCS811_HW_ID_VALUE      0x81
  34#define CCS811_HW_VERSION       0x21
  35#define CCS811_HW_VERSION_VALUE 0x10
  36#define CCS811_HW_VERSION_MASK  0xF0
  37#define CCS811_ERR              0xE0
  38/* Used to transition from boot to application mode */
  39#define CCS811_APP_START        0xF4
  40#define CCS811_SW_RESET         0xFF
  41
  42/* Status register flags */
  43#define CCS811_STATUS_ERROR             BIT(0)
  44#define CCS811_STATUS_DATA_READY        BIT(3)
  45#define CCS811_STATUS_APP_VALID_MASK    BIT(4)
  46#define CCS811_STATUS_APP_VALID_LOADED  BIT(4)
  47/*
  48 * Value of FW_MODE bit of STATUS register describes the sensor's state:
  49 * 0: Firmware is in boot mode, this allows new firmware to be loaded
  50 * 1: Firmware is in application mode. CCS811 is ready to take ADC measurements
  51 */
  52#define CCS811_STATUS_FW_MODE_MASK      BIT(7)
  53#define CCS811_STATUS_FW_MODE_APPLICATION       BIT(7)
  54
  55/* Measurement modes */
  56#define CCS811_MODE_IDLE        0x00
  57#define CCS811_MODE_IAQ_1SEC    0x10
  58#define CCS811_MODE_IAQ_10SEC   0x20
  59#define CCS811_MODE_IAQ_60SEC   0x30
  60#define CCS811_MODE_RAW_DATA    0x40
  61
  62#define CCS811_MEAS_MODE_INTERRUPT      BIT(3)
  63
  64#define CCS811_VOLTAGE_MASK     0x3FF
  65
  66struct ccs811_reading {
  67        __be16 co2;
  68        __be16 voc;
  69        u8 status;
  70        u8 error;
  71        __be16 raw_data;
  72} __attribute__((__packed__));
  73
  74struct ccs811_data {
  75        struct i2c_client *client;
  76        struct mutex lock; /* Protect readings */
  77        struct ccs811_reading buffer;
  78        struct iio_trigger *drdy_trig;
  79        struct gpio_desc *wakeup_gpio;
  80        bool drdy_trig_on;
  81        /* Ensures correct alignment of timestamp if present */
  82        struct {
  83                s16 channels[2];
  84                s64 ts __aligned(8);
  85        } scan;
  86};
  87
  88static const struct iio_chan_spec ccs811_channels[] = {
  89        {
  90                .type = IIO_CURRENT,
  91                .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
  92                                      BIT(IIO_CHAN_INFO_SCALE),
  93                .scan_index = -1,
  94        }, {
  95                .type = IIO_VOLTAGE,
  96                .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
  97                                      BIT(IIO_CHAN_INFO_SCALE),
  98                .scan_index = -1,
  99        }, {
 100                .type = IIO_CONCENTRATION,
 101                .channel2 = IIO_MOD_CO2,
 102                .modified = 1,
 103                .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
 104                                      BIT(IIO_CHAN_INFO_SCALE),
 105                .scan_index = 0,
 106                .scan_type = {
 107                        .sign = 'u',
 108                        .realbits = 16,
 109                        .storagebits = 16,
 110                        .endianness = IIO_BE,
 111                },
 112        }, {
 113                .type = IIO_CONCENTRATION,
 114                .channel2 = IIO_MOD_VOC,
 115                .modified = 1,
 116                .info_mask_separate =  BIT(IIO_CHAN_INFO_RAW) |
 117                                       BIT(IIO_CHAN_INFO_SCALE),
 118                .scan_index = 1,
 119                .scan_type = {
 120                        .sign = 'u',
 121                        .realbits = 16,
 122                        .storagebits = 16,
 123                        .endianness = IIO_BE,
 124                },
 125        },
 126        IIO_CHAN_SOFT_TIMESTAMP(2),
 127};
 128
 129/*
 130 * The CCS811 powers-up in boot mode. A setup write to CCS811_APP_START will
 131 * transition the sensor to application mode.
 132 */
 133static int ccs811_start_sensor_application(struct i2c_client *client)
 134{
 135        int ret;
 136
 137        ret = i2c_smbus_read_byte_data(client, CCS811_STATUS);
 138        if (ret < 0)
 139                return ret;
 140
 141        if ((ret & CCS811_STATUS_FW_MODE_APPLICATION))
 142                return 0;
 143
 144        if ((ret & CCS811_STATUS_APP_VALID_MASK) !=
 145            CCS811_STATUS_APP_VALID_LOADED)
 146                return -EIO;
 147
 148        ret = i2c_smbus_write_byte(client, CCS811_APP_START);
 149        if (ret < 0)
 150                return ret;
 151
 152        ret = i2c_smbus_read_byte_data(client, CCS811_STATUS);
 153        if (ret < 0)
 154                return ret;
 155
 156        if ((ret & CCS811_STATUS_FW_MODE_MASK) !=
 157            CCS811_STATUS_FW_MODE_APPLICATION) {
 158                dev_err(&client->dev, "Application failed to start. Sensor is still in boot mode.\n");
 159                return -EIO;
 160        }
 161
 162        return 0;
 163}
 164
 165static int ccs811_setup(struct i2c_client *client)
 166{
 167        int ret;
 168
 169        ret = ccs811_start_sensor_application(client);
 170        if (ret < 0)
 171                return ret;
 172
 173        return i2c_smbus_write_byte_data(client, CCS811_MEAS_MODE,
 174                                         CCS811_MODE_IAQ_1SEC);
 175}
 176
 177static void ccs811_set_wakeup(struct ccs811_data *data, bool enable)
 178{
 179        if (!data->wakeup_gpio)
 180                return;
 181
 182        gpiod_set_value(data->wakeup_gpio, enable);
 183
 184        if (enable)
 185                usleep_range(50, 60);
 186        else
 187                usleep_range(20, 30);
 188}
 189
 190static int ccs811_get_measurement(struct ccs811_data *data)
 191{
 192        int ret, tries = 11;
 193
 194        ccs811_set_wakeup(data, true);
 195
 196        /* Maximum waiting time: 1s, as measurements are made every second */
 197        while (tries-- > 0) {
 198                ret = i2c_smbus_read_byte_data(data->client, CCS811_STATUS);
 199                if (ret < 0)
 200                        return ret;
 201
 202                if ((ret & CCS811_STATUS_DATA_READY) || tries == 0)
 203                        break;
 204                msleep(100);
 205        }
 206        if (!(ret & CCS811_STATUS_DATA_READY))
 207                return -EIO;
 208
 209        ret = i2c_smbus_read_i2c_block_data(data->client,
 210                                            CCS811_ALG_RESULT_DATA, 8,
 211                                            (char *)&data->buffer);
 212        ccs811_set_wakeup(data, false);
 213
 214        return ret;
 215}
 216
 217static int ccs811_read_raw(struct iio_dev *indio_dev,
 218                           struct iio_chan_spec const *chan,
 219                           int *val, int *val2, long mask)
 220{
 221        struct ccs811_data *data = iio_priv(indio_dev);
 222        int ret;
 223
 224        switch (mask) {
 225        case IIO_CHAN_INFO_RAW:
 226                ret = iio_device_claim_direct_mode(indio_dev);
 227                if (ret)
 228                        return ret;
 229                mutex_lock(&data->lock);
 230                ret = ccs811_get_measurement(data);
 231                if (ret < 0) {
 232                        mutex_unlock(&data->lock);
 233                        iio_device_release_direct_mode(indio_dev);
 234                        return ret;
 235                }
 236
 237                switch (chan->type) {
 238                case IIO_VOLTAGE:
 239                        *val = be16_to_cpu(data->buffer.raw_data) &
 240                                           CCS811_VOLTAGE_MASK;
 241                        ret = IIO_VAL_INT;
 242                        break;
 243                case IIO_CURRENT:
 244                        *val = be16_to_cpu(data->buffer.raw_data) >> 10;
 245                        ret = IIO_VAL_INT;
 246                        break;
 247                case IIO_CONCENTRATION:
 248                        switch (chan->channel2) {
 249                        case IIO_MOD_CO2:
 250                                *val = be16_to_cpu(data->buffer.co2);
 251                                ret =  IIO_VAL_INT;
 252                                break;
 253                        case IIO_MOD_VOC:
 254                                *val = be16_to_cpu(data->buffer.voc);
 255                                ret = IIO_VAL_INT;
 256                                break;
 257                        default:
 258                                ret = -EINVAL;
 259                        }
 260                        break;
 261                default:
 262                        ret = -EINVAL;
 263                }
 264                mutex_unlock(&data->lock);
 265                iio_device_release_direct_mode(indio_dev);
 266
 267                return ret;
 268
 269        case IIO_CHAN_INFO_SCALE:
 270                switch (chan->type) {
 271                case IIO_VOLTAGE:
 272                        *val = 1;
 273                        *val2 = 612903;
 274                        return IIO_VAL_INT_PLUS_MICRO;
 275                case IIO_CURRENT:
 276                        *val = 0;
 277                        *val2 = 1000;
 278                        return IIO_VAL_INT_PLUS_MICRO;
 279                case IIO_CONCENTRATION:
 280                        switch (chan->channel2) {
 281                        case IIO_MOD_CO2:
 282                                *val = 0;
 283                                *val2 = 100;
 284                                return IIO_VAL_INT_PLUS_MICRO;
 285                        case IIO_MOD_VOC:
 286                                *val = 0;
 287                                *val2 = 100;
 288                                return IIO_VAL_INT_PLUS_NANO;
 289                        default:
 290                                return -EINVAL;
 291                        }
 292                default:
 293                        return -EINVAL;
 294                }
 295        default:
 296                return -EINVAL;
 297        }
 298}
 299
 300static const struct iio_info ccs811_info = {
 301        .read_raw = ccs811_read_raw,
 302};
 303
 304static int ccs811_set_trigger_state(struct iio_trigger *trig,
 305                                    bool state)
 306{
 307        struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
 308        struct ccs811_data *data = iio_priv(indio_dev);
 309        int ret;
 310
 311        ret = i2c_smbus_read_byte_data(data->client, CCS811_MEAS_MODE);
 312        if (ret < 0)
 313                return ret;
 314
 315        if (state)
 316                ret |= CCS811_MEAS_MODE_INTERRUPT;
 317        else
 318                ret &= ~CCS811_MEAS_MODE_INTERRUPT;
 319
 320        data->drdy_trig_on = state;
 321
 322        return i2c_smbus_write_byte_data(data->client, CCS811_MEAS_MODE, ret);
 323}
 324
 325static const struct iio_trigger_ops ccs811_trigger_ops = {
 326        .set_trigger_state = ccs811_set_trigger_state,
 327};
 328
 329static irqreturn_t ccs811_trigger_handler(int irq, void *p)
 330{
 331        struct iio_poll_func *pf = p;
 332        struct iio_dev *indio_dev = pf->indio_dev;
 333        struct ccs811_data *data = iio_priv(indio_dev);
 334        struct i2c_client *client = data->client;
 335        int ret;
 336
 337        ret = i2c_smbus_read_i2c_block_data(client, CCS811_ALG_RESULT_DATA,
 338                                            sizeof(data->scan.channels),
 339                                            (u8 *)data->scan.channels);
 340        if (ret != 4) {
 341                dev_err(&client->dev, "cannot read sensor data\n");
 342                goto err;
 343        }
 344
 345        iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
 346                                           iio_get_time_ns(indio_dev));
 347
 348err:
 349        iio_trigger_notify_done(indio_dev->trig);
 350
 351        return IRQ_HANDLED;
 352}
 353
 354static irqreturn_t ccs811_data_rdy_trigger_poll(int irq, void *private)
 355{
 356        struct iio_dev *indio_dev = private;
 357        struct ccs811_data *data = iio_priv(indio_dev);
 358
 359        if (data->drdy_trig_on)
 360                iio_trigger_poll(data->drdy_trig);
 361
 362        return IRQ_HANDLED;
 363}
 364
 365static int ccs811_reset(struct i2c_client *client)
 366{
 367        struct gpio_desc *reset_gpio;
 368        int ret;
 369
 370        reset_gpio = devm_gpiod_get_optional(&client->dev, "reset",
 371                                             GPIOD_OUT_LOW);
 372        if (IS_ERR(reset_gpio))
 373                return PTR_ERR(reset_gpio);
 374
 375        /* Try to reset using nRESET pin if available else do SW reset */
 376        if (reset_gpio) {
 377                gpiod_set_value(reset_gpio, 1);
 378                usleep_range(20, 30);
 379                gpiod_set_value(reset_gpio, 0);
 380        } else {
 381                /*
 382                 * As per the datasheet, this sequence of values needs to be
 383                 * written to the SW_RESET register for triggering the soft
 384                 * reset in the device and placing it in boot mode.
 385                 */
 386                static const u8 reset_seq[] = {
 387                        0x11, 0xE5, 0x72, 0x8A,
 388                };
 389
 390                ret = i2c_smbus_write_i2c_block_data(client, CCS811_SW_RESET,
 391                                             sizeof(reset_seq), reset_seq);
 392                if (ret < 0) {
 393                        dev_err(&client->dev, "Failed to reset sensor\n");
 394                        return ret;
 395                }
 396        }
 397
 398        /* tSTART delay required after reset */
 399        usleep_range(1000, 2000);
 400
 401        return 0;
 402}
 403
 404static int ccs811_probe(struct i2c_client *client,
 405                        const struct i2c_device_id *id)
 406{
 407        struct iio_dev *indio_dev;
 408        struct ccs811_data *data;
 409        int ret;
 410
 411        if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WRITE_BYTE
 412                                     | I2C_FUNC_SMBUS_BYTE_DATA
 413                                     | I2C_FUNC_SMBUS_READ_I2C_BLOCK))
 414                return -EOPNOTSUPP;
 415
 416        indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
 417        if (!indio_dev)
 418                return -ENOMEM;
 419
 420        data = iio_priv(indio_dev);
 421        i2c_set_clientdata(client, indio_dev);
 422        data->client = client;
 423
 424        data->wakeup_gpio = devm_gpiod_get_optional(&client->dev, "wakeup",
 425                                                    GPIOD_OUT_HIGH);
 426        if (IS_ERR(data->wakeup_gpio))
 427                return PTR_ERR(data->wakeup_gpio);
 428
 429        ccs811_set_wakeup(data, true);
 430
 431        ret = ccs811_reset(client);
 432        if (ret) {
 433                ccs811_set_wakeup(data, false);
 434                return ret;
 435        }
 436
 437        /* Check hardware id (should be 0x81 for this family of devices) */
 438        ret = i2c_smbus_read_byte_data(client, CCS811_HW_ID);
 439        if (ret < 0) {
 440                ccs811_set_wakeup(data, false);
 441                return ret;
 442        }
 443
 444        if (ret != CCS811_HW_ID_VALUE) {
 445                dev_err(&client->dev, "hardware id doesn't match CCS81x\n");
 446                ccs811_set_wakeup(data, false);
 447                return -ENODEV;
 448        }
 449
 450        ret = i2c_smbus_read_byte_data(client, CCS811_HW_VERSION);
 451        if (ret < 0) {
 452                ccs811_set_wakeup(data, false);
 453                return ret;
 454        }
 455
 456        if ((ret & CCS811_HW_VERSION_MASK) != CCS811_HW_VERSION_VALUE) {
 457                dev_err(&client->dev, "no CCS811 sensor\n");
 458                ccs811_set_wakeup(data, false);
 459                return -ENODEV;
 460        }
 461
 462        ret = ccs811_setup(client);
 463        if (ret < 0) {
 464                ccs811_set_wakeup(data, false);
 465                return ret;
 466        }
 467
 468        ccs811_set_wakeup(data, false);
 469
 470        mutex_init(&data->lock);
 471
 472        indio_dev->name = id->name;
 473        indio_dev->info = &ccs811_info;
 474        indio_dev->modes = INDIO_DIRECT_MODE;
 475
 476        indio_dev->channels = ccs811_channels;
 477        indio_dev->num_channels = ARRAY_SIZE(ccs811_channels);
 478
 479        if (client->irq > 0) {
 480                ret = devm_request_threaded_irq(&client->dev, client->irq,
 481                                                ccs811_data_rdy_trigger_poll,
 482                                                NULL,
 483                                                IRQF_TRIGGER_FALLING |
 484                                                IRQF_ONESHOT,
 485                                                "ccs811_irq", indio_dev);
 486                if (ret) {
 487                        dev_err(&client->dev, "irq request error %d\n", -ret);
 488                        goto err_poweroff;
 489                }
 490
 491                data->drdy_trig = devm_iio_trigger_alloc(&client->dev,
 492                                                         "%s-dev%d",
 493                                                         indio_dev->name,
 494                                                         iio_device_id(indio_dev));
 495                if (!data->drdy_trig) {
 496                        ret = -ENOMEM;
 497                        goto err_poweroff;
 498                }
 499
 500                data->drdy_trig->ops = &ccs811_trigger_ops;
 501                iio_trigger_set_drvdata(data->drdy_trig, indio_dev);
 502                indio_dev->trig = data->drdy_trig;
 503                iio_trigger_get(indio_dev->trig);
 504                ret = iio_trigger_register(data->drdy_trig);
 505                if (ret)
 506                        goto err_poweroff;
 507        }
 508
 509        ret = iio_triggered_buffer_setup(indio_dev, NULL,
 510                                         ccs811_trigger_handler, NULL);
 511
 512        if (ret < 0) {
 513                dev_err(&client->dev, "triggered buffer setup failed\n");
 514                goto err_trigger_unregister;
 515        }
 516
 517        ret = iio_device_register(indio_dev);
 518        if (ret < 0) {
 519                dev_err(&client->dev, "unable to register iio device\n");
 520                goto err_buffer_cleanup;
 521        }
 522        return 0;
 523
 524err_buffer_cleanup:
 525        iio_triggered_buffer_cleanup(indio_dev);
 526err_trigger_unregister:
 527        if (data->drdy_trig)
 528                iio_trigger_unregister(data->drdy_trig);
 529err_poweroff:
 530        i2c_smbus_write_byte_data(client, CCS811_MEAS_MODE, CCS811_MODE_IDLE);
 531
 532        return ret;
 533}
 534
 535static int ccs811_remove(struct i2c_client *client)
 536{
 537        struct iio_dev *indio_dev = i2c_get_clientdata(client);
 538        struct ccs811_data *data = iio_priv(indio_dev);
 539
 540        iio_device_unregister(indio_dev);
 541        iio_triggered_buffer_cleanup(indio_dev);
 542        if (data->drdy_trig)
 543                iio_trigger_unregister(data->drdy_trig);
 544
 545        return i2c_smbus_write_byte_data(client, CCS811_MEAS_MODE,
 546                                         CCS811_MODE_IDLE);
 547}
 548
 549static const struct i2c_device_id ccs811_id[] = {
 550        {"ccs811", 0},
 551        {       }
 552};
 553MODULE_DEVICE_TABLE(i2c, ccs811_id);
 554
 555static const struct of_device_id ccs811_dt_ids[] = {
 556        { .compatible = "ams,ccs811" },
 557        { }
 558};
 559MODULE_DEVICE_TABLE(of, ccs811_dt_ids);
 560
 561static struct i2c_driver ccs811_driver = {
 562        .driver = {
 563                .name = "ccs811",
 564                .of_match_table = ccs811_dt_ids,
 565        },
 566        .probe = ccs811_probe,
 567        .remove = ccs811_remove,
 568        .id_table = ccs811_id,
 569};
 570module_i2c_driver(ccs811_driver);
 571
 572MODULE_AUTHOR("Narcisa Vasile <narcisaanamaria12@gmail.com>");
 573MODULE_DESCRIPTION("CCS811 volatile organic compounds sensor");
 574MODULE_LICENSE("GPL v2");
 575
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.