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

scd4x.c (15678B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Sensirion SCD4X carbon dioxide sensor i2c driver
      4 *
      5 * Copyright (C) 2021 Protonic Holland
      6 * Author: Roan van Dijk <roan@protonic.nl>
      7 *
      8 * I2C slave address: 0x62
      9 *
     10 * Datasheets:
     11 * https://www.sensirion.com/file/datasheet_scd4x
     12 */
     13
     14#include <asm/unaligned.h>
     15#include <linux/crc8.h>
     16#include <linux/delay.h>
     17#include <linux/device.h>
     18#include <linux/i2c.h>
     19#include <linux/iio/buffer.h>
     20#include <linux/iio/iio.h>
     21#include <linux/iio/sysfs.h>
     22#include <linux/iio/trigger.h>
     23#include <linux/iio/trigger_consumer.h>
     24#include <linux/iio/triggered_buffer.h>
     25#include <linux/iio/types.h>
     26#include <linux/kernel.h>
     27#include <linux/mutex.h>
     28#include <linux/string.h>
     29#include <linux/sysfs.h>
     30#include <linux/types.h>
     31
     32#define SCD4X_CRC8_POLYNOMIAL 0x31
     33#define SCD4X_TIMEOUT_ERR 1000
     34#define SCD4X_READ_BUF_SIZE 9
     35#define SCD4X_COMMAND_BUF_SIZE 2
     36#define SCD4X_WRITE_BUF_SIZE 5
     37#define SCD4X_FRC_MIN_PPM 0
     38#define SCD4X_FRC_MAX_PPM 2000
     39#define SCD4X_READY_MASK 0x01
     40
     41/*Commands SCD4X*/
     42enum scd4x_cmd {
     43	CMD_START_MEAS          = 0x21b1,
     44	CMD_READ_MEAS           = 0xec05,
     45	CMD_STOP_MEAS           = 0x3f86,
     46	CMD_SET_TEMP_OFFSET     = 0x241d,
     47	CMD_GET_TEMP_OFFSET     = 0x2318,
     48	CMD_FRC                 = 0x362f,
     49	CMD_SET_ASC             = 0x2416,
     50	CMD_GET_ASC             = 0x2313,
     51	CMD_GET_DATA_READY      = 0xe4b8,
     52};
     53
     54enum scd4x_channel_idx {
     55	SCD4X_CO2,
     56	SCD4X_TEMP,
     57	SCD4X_HR,
     58};
     59
     60struct scd4x_state {
     61	struct i2c_client *client;
     62	/* maintain access to device, to prevent concurrent reads/writes */
     63	struct mutex lock;
     64	struct regulator *vdd;
     65};
     66
     67DECLARE_CRC8_TABLE(scd4x_crc8_table);
     68
     69static int scd4x_i2c_xfer(struct scd4x_state *state, char *txbuf, int txsize,
     70				char *rxbuf, int rxsize)
     71{
     72	struct i2c_client *client = state->client;
     73	int ret;
     74
     75	ret = i2c_master_send(client, txbuf, txsize);
     76
     77	if (ret < 0)
     78		return ret;
     79	if (ret != txsize)
     80		return -EIO;
     81
     82	if (rxsize == 0)
     83		return 0;
     84
     85	ret = i2c_master_recv(client, rxbuf, rxsize);
     86	if (ret < 0)
     87		return ret;
     88	if (ret != rxsize)
     89		return -EIO;
     90
     91	return 0;
     92}
     93
     94static int scd4x_send_command(struct scd4x_state *state, enum scd4x_cmd cmd)
     95{
     96	char buf[SCD4X_COMMAND_BUF_SIZE];
     97	int ret;
     98
     99	/*
    100	 * Measurement needs to be stopped before sending commands.
    101	 * Except stop and start command.
    102	 */
    103	if ((cmd != CMD_STOP_MEAS) && (cmd != CMD_START_MEAS)) {
    104
    105		ret = scd4x_send_command(state, CMD_STOP_MEAS);
    106		if (ret)
    107			return ret;
    108
    109		/* execution time for stopping measurement */
    110		msleep_interruptible(500);
    111	}
    112
    113	put_unaligned_be16(cmd, buf);
    114	ret = scd4x_i2c_xfer(state, buf, 2, buf, 0);
    115	if (ret)
    116		return ret;
    117
    118	if ((cmd != CMD_STOP_MEAS) && (cmd != CMD_START_MEAS)) {
    119		ret = scd4x_send_command(state, CMD_START_MEAS);
    120		if (ret)
    121			return ret;
    122	}
    123
    124	return 0;
    125}
    126
    127static int scd4x_read(struct scd4x_state *state, enum scd4x_cmd cmd,
    128			void *response, int response_sz)
    129{
    130	struct i2c_client *client = state->client;
    131	char buf[SCD4X_READ_BUF_SIZE];
    132	char *rsp = response;
    133	int i, ret;
    134	char crc;
    135
    136	/*
    137	 * Measurement needs to be stopped before sending commands.
    138	 * Except for reading measurement and data ready command.
    139	 */
    140	if ((cmd != CMD_GET_DATA_READY) && (cmd != CMD_READ_MEAS)) {
    141		ret = scd4x_send_command(state, CMD_STOP_MEAS);
    142		if (ret)
    143			return ret;
    144
    145		/* execution time for stopping measurement */
    146		msleep_interruptible(500);
    147	}
    148
    149	/* CRC byte for every 2 bytes of data */
    150	response_sz += response_sz / 2;
    151
    152	put_unaligned_be16(cmd, buf);
    153	ret = scd4x_i2c_xfer(state, buf, 2, buf, response_sz);
    154	if (ret)
    155		return ret;
    156
    157	for (i = 0; i < response_sz; i += 3) {
    158		crc = crc8(scd4x_crc8_table, buf + i, 2, CRC8_INIT_VALUE);
    159		if (crc != buf[i + 2]) {
    160			dev_err(&client->dev, "CRC error\n");
    161			return -EIO;
    162		}
    163
    164		*rsp++ = buf[i];
    165		*rsp++ = buf[i + 1];
    166	}
    167
    168	/* start measurement */
    169	if ((cmd != CMD_GET_DATA_READY) && (cmd != CMD_READ_MEAS)) {
    170		ret = scd4x_send_command(state, CMD_START_MEAS);
    171		if (ret)
    172			return ret;
    173	}
    174
    175	return 0;
    176}
    177
    178static int scd4x_write(struct scd4x_state *state, enum scd4x_cmd cmd, uint16_t arg)
    179{
    180	char buf[SCD4X_WRITE_BUF_SIZE];
    181	int ret;
    182	char crc;
    183
    184	put_unaligned_be16(cmd, buf);
    185	put_unaligned_be16(arg, buf + 2);
    186
    187	crc = crc8(scd4x_crc8_table, buf + 2, 2, CRC8_INIT_VALUE);
    188	buf[4] = crc;
    189
    190	/* measurement needs to be stopped before sending commands */
    191	ret = scd4x_send_command(state, CMD_STOP_MEAS);
    192	if (ret)
    193		return ret;
    194
    195	/* execution time */
    196	msleep_interruptible(500);
    197
    198	ret = scd4x_i2c_xfer(state, buf, SCD4X_WRITE_BUF_SIZE, buf, 0);
    199	if (ret)
    200		return ret;
    201
    202	/* start measurement, except for forced calibration command */
    203	if (cmd != CMD_FRC) {
    204		ret = scd4x_send_command(state, CMD_START_MEAS);
    205		if (ret)
    206			return ret;
    207	}
    208
    209	return 0;
    210}
    211
    212static int scd4x_write_and_fetch(struct scd4x_state *state, enum scd4x_cmd cmd,
    213				uint16_t arg, void *response, int response_sz)
    214{
    215	struct i2c_client *client = state->client;
    216	char buf[SCD4X_READ_BUF_SIZE];
    217	char *rsp = response;
    218	int i, ret;
    219	char crc;
    220
    221	ret = scd4x_write(state, CMD_FRC, arg);
    222	if (ret)
    223		goto err;
    224
    225	/* execution time */
    226	msleep_interruptible(400);
    227
    228	/* CRC byte for every 2 bytes of data */
    229	response_sz += response_sz / 2;
    230
    231	ret = i2c_master_recv(client, buf, response_sz);
    232	if (ret < 0)
    233		goto err;
    234	if (ret != response_sz) {
    235		ret = -EIO;
    236		goto err;
    237	}
    238
    239	for (i = 0; i < response_sz; i += 3) {
    240		crc = crc8(scd4x_crc8_table, buf + i, 2, CRC8_INIT_VALUE);
    241		if (crc != buf[i + 2]) {
    242			dev_err(&client->dev, "CRC error\n");
    243			ret = -EIO;
    244			goto err;
    245		}
    246
    247		*rsp++ = buf[i];
    248		*rsp++ = buf[i + 1];
    249	}
    250
    251	return scd4x_send_command(state, CMD_START_MEAS);
    252
    253err:
    254	/*
    255	 * on error try to start the measurement,
    256	 * puts sensor back into continuous measurement
    257	 */
    258	scd4x_send_command(state, CMD_START_MEAS);
    259
    260	return ret;
    261}
    262
    263static int scd4x_read_meas(struct scd4x_state *state, uint16_t *meas)
    264{
    265	int i, ret;
    266	__be16 buf[3];
    267
    268	ret = scd4x_read(state, CMD_READ_MEAS, buf, sizeof(buf));
    269	if (ret)
    270		return ret;
    271
    272	for (i = 0; i < ARRAY_SIZE(buf); i++)
    273		meas[i] = be16_to_cpu(buf[i]);
    274
    275	return 0;
    276}
    277
    278static int scd4x_wait_meas_poll(struct scd4x_state *state)
    279{
    280	struct i2c_client *client = state->client;
    281	int tries = 6;
    282	int ret;
    283
    284	do {
    285		__be16 bval;
    286		uint16_t val;
    287
    288		ret = scd4x_read(state, CMD_GET_DATA_READY, &bval, sizeof(bval));
    289		if (ret)
    290			return -EIO;
    291		val = be16_to_cpu(bval);
    292
    293		/* new measurement available */
    294		if (val & 0x7FF)
    295			return 0;
    296
    297		msleep_interruptible(1000);
    298	} while (--tries);
    299
    300	/* try to start sensor on timeout */
    301	ret = scd4x_send_command(state, CMD_START_MEAS);
    302	if (ret)
    303		dev_err(&client->dev, "failed to start measurement: %d\n", ret);
    304
    305	return -ETIMEDOUT;
    306}
    307
    308static int scd4x_read_poll(struct scd4x_state *state, uint16_t *buf)
    309{
    310	int ret;
    311
    312	ret = scd4x_wait_meas_poll(state);
    313	if (ret)
    314		return ret;
    315
    316	return scd4x_read_meas(state, buf);
    317}
    318
    319static int scd4x_read_channel(struct scd4x_state *state, int chan)
    320{
    321	int ret;
    322	uint16_t buf[3];
    323
    324	ret = scd4x_read_poll(state, buf);
    325	if (ret)
    326		return ret;
    327
    328	return buf[chan];
    329}
    330
    331static int scd4x_read_raw(struct iio_dev *indio_dev,
    332			struct iio_chan_spec const *chan, int *val,
    333			int *val2, long mask)
    334{
    335	struct scd4x_state *state = iio_priv(indio_dev);
    336	int ret;
    337	__be16 tmp;
    338
    339	switch (mask) {
    340	case IIO_CHAN_INFO_RAW:
    341		ret = iio_device_claim_direct_mode(indio_dev);
    342		if (ret)
    343			return ret;
    344
    345		mutex_lock(&state->lock);
    346		ret = scd4x_read_channel(state, chan->address);
    347		mutex_unlock(&state->lock);
    348
    349		iio_device_release_direct_mode(indio_dev);
    350		if (ret < 0)
    351			return ret;
    352
    353		*val = ret;
    354		return IIO_VAL_INT;
    355	case IIO_CHAN_INFO_SCALE:
    356		if (chan->type == IIO_CONCENTRATION) {
    357			*val = 0;
    358			*val2 = 100;
    359			return IIO_VAL_INT_PLUS_MICRO;
    360		} else if (chan->type == IIO_TEMP) {
    361			*val = 175000;
    362			*val2 = 65536;
    363			return IIO_VAL_FRACTIONAL;
    364		} else if (chan->type == IIO_HUMIDITYRELATIVE) {
    365			*val = 100000;
    366			*val2 = 65536;
    367			return IIO_VAL_FRACTIONAL;
    368		}
    369		return -EINVAL;
    370	case IIO_CHAN_INFO_OFFSET:
    371		*val = -16852;
    372		*val2 = 114286;
    373		return IIO_VAL_INT_PLUS_MICRO;
    374	case IIO_CHAN_INFO_CALIBBIAS:
    375		mutex_lock(&state->lock);
    376		ret = scd4x_read(state, CMD_GET_TEMP_OFFSET, &tmp, sizeof(tmp));
    377		mutex_unlock(&state->lock);
    378		if (ret)
    379			return ret;
    380
    381		*val = be16_to_cpu(tmp);
    382
    383		return IIO_VAL_INT;
    384	default:
    385		return -EINVAL;
    386	}
    387}
    388
    389static int scd4x_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan,
    390				int val, int val2, long mask)
    391{
    392	struct scd4x_state *state = iio_priv(indio_dev);
    393	int ret = 0;
    394
    395	switch (mask) {
    396	case IIO_CHAN_INFO_CALIBBIAS:
    397		mutex_lock(&state->lock);
    398		ret = scd4x_write(state, CMD_SET_TEMP_OFFSET, val);
    399		mutex_unlock(&state->lock);
    400
    401		return ret;
    402	default:
    403		return -EINVAL;
    404	}
    405}
    406
    407static ssize_t calibration_auto_enable_show(struct device *dev,
    408			struct device_attribute *attr, char *buf)
    409{
    410	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
    411	struct scd4x_state *state = iio_priv(indio_dev);
    412	int ret;
    413	__be16 bval;
    414	u16 val;
    415
    416	mutex_lock(&state->lock);
    417	ret = scd4x_read(state, CMD_GET_ASC, &bval, sizeof(bval));
    418	mutex_unlock(&state->lock);
    419	if (ret) {
    420		dev_err(dev, "failed to read automatic calibration");
    421		return ret;
    422	}
    423
    424	val = (be16_to_cpu(bval) & SCD4X_READY_MASK) ? 1 : 0;
    425
    426	return sysfs_emit(buf, "%d\n", val);
    427}
    428
    429static ssize_t calibration_auto_enable_store(struct device *dev,
    430					struct device_attribute *attr,
    431					const char *buf, size_t len)
    432{
    433	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
    434	struct scd4x_state *state = iio_priv(indio_dev);
    435	bool val;
    436	int ret;
    437	uint16_t value;
    438
    439	ret = kstrtobool(buf, &val);
    440	if (ret)
    441		return ret;
    442
    443	value = val;
    444
    445	mutex_lock(&state->lock);
    446	ret = scd4x_write(state, CMD_SET_ASC, value);
    447	mutex_unlock(&state->lock);
    448	if (ret)
    449		dev_err(dev, "failed to set automatic calibration");
    450
    451	return ret ?: len;
    452}
    453
    454static ssize_t calibration_forced_value_store(struct device *dev,
    455					struct device_attribute *attr,
    456					const char *buf, size_t len)
    457{
    458	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
    459	struct scd4x_state *state = iio_priv(indio_dev);
    460	uint16_t val, arg;
    461	int ret;
    462
    463	ret = kstrtou16(buf, 0, &arg);
    464	if (ret)
    465		return ret;
    466
    467	if (arg < SCD4X_FRC_MIN_PPM || arg > SCD4X_FRC_MAX_PPM)
    468		return -EINVAL;
    469
    470	mutex_lock(&state->lock);
    471	ret = scd4x_write_and_fetch(state, CMD_FRC, arg, &val, sizeof(val));
    472	mutex_unlock(&state->lock);
    473
    474	if (ret)
    475		return ret;
    476
    477	if (val == 0xff) {
    478		dev_err(dev, "forced calibration has failed");
    479		return -EINVAL;
    480	}
    481
    482	return len;
    483}
    484
    485static IIO_DEVICE_ATTR_RW(calibration_auto_enable, 0);
    486static IIO_DEVICE_ATTR_WO(calibration_forced_value, 0);
    487
    488static IIO_CONST_ATTR(calibration_forced_value_available,
    489	       __stringify([SCD4X_FRC_MIN_PPM 1 SCD4X_FRC_MAX_PPM]));
    490
    491static struct attribute *scd4x_attrs[] = {
    492	&iio_dev_attr_calibration_auto_enable.dev_attr.attr,
    493	&iio_dev_attr_calibration_forced_value.dev_attr.attr,
    494	&iio_const_attr_calibration_forced_value_available.dev_attr.attr,
    495	NULL
    496};
    497
    498static const struct attribute_group scd4x_attr_group = {
    499	.attrs = scd4x_attrs,
    500};
    501
    502static const struct iio_info scd4x_info = {
    503	.attrs = &scd4x_attr_group,
    504	.read_raw = scd4x_read_raw,
    505	.write_raw = scd4x_write_raw,
    506};
    507
    508static const struct iio_chan_spec scd4x_channels[] = {
    509	{
    510		.type = IIO_CONCENTRATION,
    511		.channel2 = IIO_MOD_CO2,
    512		.modified = 1,
    513		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
    514					BIT(IIO_CHAN_INFO_SCALE),
    515		.address = SCD4X_CO2,
    516		.scan_index = SCD4X_CO2,
    517		.scan_type = {
    518			.sign = 'u',
    519			.realbits = 16,
    520			.storagebits = 16,
    521			.endianness = IIO_BE,
    522		},
    523	},
    524	{
    525		.type = IIO_TEMP,
    526		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
    527					BIT(IIO_CHAN_INFO_SCALE) |
    528					BIT(IIO_CHAN_INFO_OFFSET) |
    529					BIT(IIO_CHAN_INFO_CALIBBIAS),
    530		.address = SCD4X_TEMP,
    531		.scan_index = SCD4X_TEMP,
    532		.scan_type = {
    533			.sign = 'u',
    534			.realbits = 16,
    535			.storagebits = 16,
    536			.endianness = IIO_BE,
    537		},
    538	},
    539	{
    540		.type = IIO_HUMIDITYRELATIVE,
    541		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
    542					BIT(IIO_CHAN_INFO_SCALE),
    543		.address = SCD4X_HR,
    544		.scan_index = SCD4X_HR,
    545		.scan_type = {
    546			.sign = 'u',
    547			.realbits = 16,
    548			.storagebits = 16,
    549			.endianness = IIO_BE,
    550		},
    551	},
    552};
    553
    554static int __maybe_unused scd4x_suspend(struct device *dev)
    555{
    556	struct iio_dev *indio_dev = dev_get_drvdata(dev);
    557	struct scd4x_state *state  = iio_priv(indio_dev);
    558	int ret;
    559
    560	ret = scd4x_send_command(state, CMD_STOP_MEAS);
    561	if (ret)
    562		return ret;
    563
    564	return regulator_disable(state->vdd);
    565}
    566
    567static int __maybe_unused scd4x_resume(struct device *dev)
    568{
    569	struct iio_dev *indio_dev = dev_get_drvdata(dev);
    570	struct scd4x_state *state = iio_priv(indio_dev);
    571	int ret;
    572
    573	ret = regulator_enable(state->vdd);
    574	if (ret)
    575		return ret;
    576
    577	return scd4x_send_command(state, CMD_START_MEAS);
    578}
    579
    580static __maybe_unused SIMPLE_DEV_PM_OPS(scd4x_pm_ops, scd4x_suspend, scd4x_resume);
    581
    582static void scd4x_stop_meas(void *state)
    583{
    584	scd4x_send_command(state, CMD_STOP_MEAS);
    585}
    586
    587static void scd4x_disable_regulator(void *data)
    588{
    589	struct scd4x_state *state = data;
    590
    591	regulator_disable(state->vdd);
    592}
    593
    594static irqreturn_t scd4x_trigger_handler(int irq, void *p)
    595{
    596	struct iio_poll_func *pf = p;
    597	struct iio_dev *indio_dev = pf->indio_dev;
    598	struct scd4x_state *state = iio_priv(indio_dev);
    599	struct {
    600		uint16_t data[3];
    601		int64_t ts __aligned(8);
    602	} scan;
    603	int ret;
    604
    605	memset(&scan, 0, sizeof(scan));
    606	mutex_lock(&state->lock);
    607	ret = scd4x_read_poll(state, scan.data);
    608	mutex_unlock(&state->lock);
    609	if (ret)
    610		goto out;
    611
    612	iio_push_to_buffers_with_timestamp(indio_dev, &scan, iio_get_time_ns(indio_dev));
    613out:
    614	iio_trigger_notify_done(indio_dev->trig);
    615	return IRQ_HANDLED;
    616}
    617
    618static int scd4x_probe(struct i2c_client *client, const struct i2c_device_id *id)
    619{
    620	static const unsigned long scd4x_scan_masks[] = { 0x07, 0x00 };
    621	struct device *dev = &client->dev;
    622	struct iio_dev *indio_dev;
    623	struct scd4x_state *state;
    624	int ret;
    625
    626	indio_dev = devm_iio_device_alloc(dev, sizeof(*state));
    627	if (!indio_dev)
    628		return -ENOMEM;
    629
    630	state = iio_priv(indio_dev);
    631	mutex_init(&state->lock);
    632	state->client = client;
    633	crc8_populate_msb(scd4x_crc8_table, SCD4X_CRC8_POLYNOMIAL);
    634
    635	indio_dev->info = &scd4x_info;
    636	indio_dev->name = client->name;
    637	indio_dev->channels = scd4x_channels;
    638	indio_dev->num_channels = ARRAY_SIZE(scd4x_channels);
    639	indio_dev->modes = INDIO_DIRECT_MODE;
    640	indio_dev->available_scan_masks = scd4x_scan_masks;
    641
    642	state->vdd = devm_regulator_get(dev, "vdd");
    643	if (IS_ERR(state->vdd))
    644		return dev_err_probe(dev, PTR_ERR(state->vdd), "failed to get regulator\n");
    645
    646	ret = regulator_enable(state->vdd);
    647	if (ret)
    648		return ret;
    649
    650	ret = devm_add_action_or_reset(dev, scd4x_disable_regulator, state);
    651	if (ret)
    652		return ret;
    653
    654	ret = scd4x_send_command(state, CMD_STOP_MEAS);
    655	if (ret) {
    656		dev_err(dev, "failed to stop measurement: %d\n", ret);
    657		return ret;
    658	}
    659
    660	/* execution time */
    661	msleep_interruptible(500);
    662
    663	ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL, scd4x_trigger_handler, NULL);
    664	if (ret)
    665		return ret;
    666
    667	ret = scd4x_send_command(state, CMD_START_MEAS);
    668	if (ret) {
    669		dev_err(dev, "failed to start measurement: %d\n", ret);
    670		return ret;
    671	}
    672
    673	ret = devm_add_action_or_reset(dev, scd4x_stop_meas, state);
    674	if (ret)
    675		return ret;
    676
    677	return devm_iio_device_register(dev, indio_dev);
    678}
    679
    680static const struct of_device_id scd4x_dt_ids[] = {
    681	{ .compatible = "sensirion,scd40" },
    682	{ .compatible = "sensirion,scd41" },
    683	{ }
    684};
    685MODULE_DEVICE_TABLE(of, scd4x_dt_ids);
    686
    687static struct i2c_driver scd4x_i2c_driver = {
    688	.driver = {
    689		.name = KBUILD_MODNAME,
    690		.of_match_table = scd4x_dt_ids,
    691		.pm = &scd4x_pm_ops
    692	},
    693	.probe = scd4x_probe,
    694};
    695module_i2c_driver(scd4x_i2c_driver);
    696
    697MODULE_AUTHOR("Roan van Dijk <roan@protonic.nl>");
    698MODULE_DESCRIPTION("Sensirion SCD4X carbon dioxide sensor core driver");
    699MODULE_LICENSE("GPL v2");