cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

ccs811.c (13807B)


      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		ret = iio_trigger_register(data->drdy_trig);
    503		if (ret)
    504			goto err_poweroff;
    505
    506		indio_dev->trig = iio_trigger_get(data->drdy_trig);
    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");