119370Spst// SPDX-License-Identifier: GPL-2.0
2130803Smarcel/*
3130803Smarcel * Senseair Sunrise 006-0-0007 CO2 sensor driver.
4130803Smarcel *
5130803Smarcel * Copyright (C) 2021 Jacopo Mondi
619370Spst *
719370Spst * List of features not yet supported by the driver:
819370Spst * - controllable EN pin
998944Sobrien * - single-shot operations using the nDRY pin.
1019370Spst * - ABC/target calibration
1198944Sobrien */
1298944Sobrien
1398944Sobrien#include <linux/bitops.h>
1498944Sobrien#include <linux/i2c.h>
1519370Spst#include <linux/kernel.h>
1698944Sobrien#include <linux/mod_devicetable.h>
1798944Sobrien#include <linux/module.h>
1898944Sobrien#include <linux/mutex.h>
1998944Sobrien#include <linux/regmap.h>
2019370Spst#include <linux/time64.h>
2198944Sobrien
2298944Sobrien#include <linux/iio/iio.h>
2398944Sobrien
2498944Sobrien#define DRIVER_NAME "sunrise_co2"
2519370Spst
2619370Spst#define SUNRISE_ERROR_STATUS_REG		0x00
27130803Smarcel#define SUNRISE_CO2_FILTERED_COMP_REG		0x06
2819370Spst#define SUNRISE_CHIP_TEMPERATURE_REG		0x08
2919370Spst#define SUNRISE_CALIBRATION_STATUS_REG		0x81
3019370Spst#define SUNRISE_CALIBRATION_COMMAND_REG		0x82
3119370Spst#define SUNRISE_CALIBRATION_FACTORY_CMD		0x7c02
3219370Spst#define SUNRISE_CALIBRATION_BACKGROUND_CMD	0x7c06
3319370Spst/*
3419370Spst * The calibration timeout is not characterized in the datasheet.
3519370Spst * Use 30 seconds as a reasonable upper limit.
3619370Spst */
3719370Spst#define SUNRISE_CALIBRATION_TIMEOUT_US		(30 * USEC_PER_SEC)
3819370Spst
3919370Spststruct sunrise_dev {
4098944Sobrien	struct i2c_client *client;
4198944Sobrien	struct regmap *regmap;
4219370Spst	/* Protects access to IIO attributes. */
4319370Spst	struct mutex lock;
4498944Sobrien	bool ignore_nak;
4598944Sobrien};
4646283Sdfr
4798944Sobrien/* Custom regmap read/write operations: perform unlocked access to the i2c bus. */
4898944Sobrien
4919370Spststatic int sunrise_regmap_read(void *context, const void *reg_buf,
5098944Sobrien			       size_t reg_size, void *val_buf, size_t val_size)
5198944Sobrien{
5219370Spst	struct i2c_client *client = context;
5398944Sobrien	struct sunrise_dev *sunrise = i2c_get_clientdata(client);
5498944Sobrien	union i2c_smbus_data data;
5519370Spst	int ret;
5619370Spst
5719370Spst	if (reg_size != 1 || !val_size)
5819370Spst		return -EINVAL;
5998944Sobrien
6098944Sobrien	memset(&data, 0, sizeof(data));
6119370Spst	data.block[0] = val_size;
62130803Smarcel
6319370Spst	/*
6419370Spst	 * Wake up sensor by sending sensor address: START, sensor address,
6519370Spst	 * STOP. Sensor will not ACK this byte.
6619370Spst	 *
6719370Spst	 * The chip enters a low power state after 15ms without
6819370Spst	 * communications or after a complete read/write sequence.
6998944Sobrien	 */
7098944Sobrien	__i2c_smbus_xfer(client->adapter, client->addr,
7119370Spst			 sunrise->ignore_nak ? I2C_M_IGNORE_NAK : 0,
7219370Spst			 I2C_SMBUS_WRITE, 0, I2C_SMBUS_BYTE_DATA, &data);
7319370Spst
7419370Spst	usleep_range(500, 1500);
7519370Spst
7619370Spst	ret = __i2c_smbus_xfer(client->adapter, client->addr, client->flags,
7719370Spst			       I2C_SMBUS_READ, ((u8 *)reg_buf)[0],
7819370Spst			       I2C_SMBUS_I2C_BLOCK_DATA, &data);
7919370Spst	if (ret < 0)
8019370Spst		return ret;
8119370Spst
8219370Spst	memcpy(val_buf, &data.block[1], data.block[0]);
8319370Spst
8419370Spst	return 0;
8519370Spst}
8698944Sobrien
8719370Spststatic int sunrise_regmap_write(void *context, const void *val_buf, size_t count)
8819370Spst{
8919370Spst	struct i2c_client *client = context;
9019370Spst	struct sunrise_dev *sunrise = i2c_get_clientdata(client);
9119370Spst	union i2c_smbus_data data;
9219370Spst
9319370Spst	/* Discard reg address from values count. */
9419370Spst	if (!count)
9519370Spst		return -EINVAL;
9619370Spst	count--;
9719370Spst
9819370Spst	memset(&data, 0, sizeof(data));
9998944Sobrien	data.block[0] = count;
10098944Sobrien	memcpy(&data.block[1], (u8 *)val_buf + 1, count);
10119370Spst
10219370Spst	__i2c_smbus_xfer(client->adapter, client->addr,
10319370Spst			 sunrise->ignore_nak ? I2C_M_IGNORE_NAK : 0,
10419370Spst			 I2C_SMBUS_WRITE, 0, I2C_SMBUS_BYTE_DATA, &data);
10519370Spst
10619370Spst	usleep_range(500, 1500);
10719370Spst
10819370Spst	return __i2c_smbus_xfer(client->adapter, client->addr, client->flags,
10919370Spst				I2C_SMBUS_WRITE, ((u8 *)val_buf)[0],
11019370Spst				I2C_SMBUS_I2C_BLOCK_DATA, &data);
11119370Spst}
11219370Spst
11319370Spst/*
11419370Spst * Sunrise i2c read/write operations: lock the i2c segment to avoid losing the
11519370Spst * wake up session. Use custom regmap operations that perform unlocked access to
11619370Spst * the i2c bus.
11719370Spst */
11819370Spststatic int sunrise_read_byte(struct sunrise_dev *sunrise, u8 reg)
11919370Spst{
12019370Spst	const struct i2c_client *client = sunrise->client;
12119370Spst	const struct device *dev = &client->dev;
12219370Spst	unsigned int val;
12319370Spst	int ret;
12419370Spst
12519370Spst	i2c_lock_bus(client->adapter, I2C_LOCK_SEGMENT);
12619370Spst	ret = regmap_read(sunrise->regmap, reg, &val);
12719370Spst	i2c_unlock_bus(client->adapter, I2C_LOCK_SEGMENT);
12819370Spst	if (ret) {
12919370Spst		dev_err(dev, "Read byte failed: reg 0x%02x (%d)\n", reg, ret);
13019370Spst		return ret;
13119370Spst	}
13219370Spst
13319370Spst	return val;
13419370Spst}
13519370Spst
13619370Spststatic int sunrise_read_word(struct sunrise_dev *sunrise, u8 reg, u16 *val)
13719370Spst{
13819370Spst	const struct i2c_client *client = sunrise->client;
13919370Spst	const struct device *dev = &client->dev;
14019370Spst	__be16 be_val;
14119370Spst	int ret;
14219370Spst
14319370Spst	i2c_lock_bus(client->adapter, I2C_LOCK_SEGMENT);
14419370Spst	ret = regmap_bulk_read(sunrise->regmap, reg, &be_val, sizeof(be_val));
14519370Spst	i2c_unlock_bus(client->adapter, I2C_LOCK_SEGMENT);
14698944Sobrien	if (ret) {
14719370Spst		dev_err(dev, "Read word failed: reg 0x%02x (%d)\n", reg, ret);
14819370Spst		return ret;
14919370Spst	}
15019370Spst
15119370Spst	*val = be16_to_cpu(be_val);
15219370Spst
15319370Spst	return 0;
15419370Spst}
15519370Spst
15698944Sobrienstatic int sunrise_write_byte(struct sunrise_dev *sunrise, u8 reg, u8 val)
15798944Sobrien{
15819370Spst	const struct i2c_client *client = sunrise->client;
15919370Spst	const struct device *dev = &client->dev;
16019370Spst	int ret;
16119370Spst
16219370Spst	i2c_lock_bus(client->adapter, I2C_LOCK_SEGMENT);
16319370Spst	ret = regmap_write(sunrise->regmap, reg, val);
16419370Spst	i2c_unlock_bus(client->adapter, I2C_LOCK_SEGMENT);
16519370Spst	if (ret)
16619370Spst		dev_err(dev, "Write byte failed: reg 0x%02x (%d)\n", reg, ret);
16719370Spst
16819370Spst	return ret;
16919370Spst}
17019370Spst
17119370Spststatic int sunrise_write_word(struct sunrise_dev *sunrise, u8 reg, u16 data)
17219370Spst{
17319370Spst	const struct i2c_client *client = sunrise->client;
17419370Spst	const struct device *dev = &client->dev;
17519370Spst	__be16 be_data = cpu_to_be16(data);
17619370Spst	int ret;
17719370Spst
17898944Sobrien	i2c_lock_bus(client->adapter, I2C_LOCK_SEGMENT);
17919370Spst	ret = regmap_bulk_write(sunrise->regmap, reg, &be_data, sizeof(be_data));
18019370Spst	i2c_unlock_bus(client->adapter, I2C_LOCK_SEGMENT);
18119370Spst	if (ret)
18219370Spst		dev_err(dev, "Write word failed: reg 0x%02x (%d)\n", reg, ret);
18398944Sobrien
18419370Spst	return ret;
18519370Spst}
18619370Spst
18719370Spst/* Trigger a calibration cycle. */
18898944Sobrien
18998944Sobrienenum {
19098944Sobrien	SUNRISE_CALIBRATION_FACTORY,
19119370Spst	SUNRISE_CALIBRATION_BACKGROUND,
19298944Sobrien};
19319370Spst
19419370Spststatic const struct sunrise_calib_data {
19519370Spst	u16 cmd;
19619370Spst	u8 bit;
19798944Sobrien	const char * const name;
19819370Spst} calib_data[] = {
19919370Spst	[SUNRISE_CALIBRATION_FACTORY] = {
20098944Sobrien		SUNRISE_CALIBRATION_FACTORY_CMD,
20119370Spst		BIT(2),
20298944Sobrien		"factory_calibration",
20319370Spst	},
20498944Sobrien	[SUNRISE_CALIBRATION_BACKGROUND] = {
20598944Sobrien		SUNRISE_CALIBRATION_BACKGROUND_CMD,
20698944Sobrien		BIT(5),
20719370Spst		"background_calibration",
20898944Sobrien	},
20998944Sobrien};
21098944Sobrien
21198944Sobrienstatic int sunrise_calibrate(struct sunrise_dev *sunrise,
21298944Sobrien			     const struct sunrise_calib_data *data)
21319370Spst{
21419370Spst	unsigned int status;
21519370Spst	int ret;
21619370Spst
21719370Spst	/* Reset the calibration status reg. */
21819370Spst	ret = sunrise_write_byte(sunrise, SUNRISE_CALIBRATION_STATUS_REG, 0x00);
21998944Sobrien	if (ret)
22019370Spst		return ret;
22119370Spst
22219370Spst	/* Write a calibration command and poll the calibration status bit. */
22319370Spst	ret = sunrise_write_word(sunrise, SUNRISE_CALIBRATION_COMMAND_REG, data->cmd);
22419370Spst	if (ret)
22519370Spst		return ret;
22698944Sobrien
22719370Spst	dev_dbg(&sunrise->client->dev, "%s in progress\n", data->name);
22819370Spst
22919370Spst	/*
23019370Spst	 * Calibration takes several seconds, so the sleep time between reads
23198944Sobrien	 * can be pretty relaxed.
23219370Spst	 */
23319370Spst	return read_poll_timeout(sunrise_read_byte, status, status & data->bit,
23419370Spst				 200000, SUNRISE_CALIBRATION_TIMEOUT_US, false,
23519370Spst				 sunrise, SUNRISE_CALIBRATION_STATUS_REG);
23619370Spst}
23719370Spst
23819370Spststatic ssize_t sunrise_cal_factory_write(struct iio_dev *iiodev,
23919370Spst					 uintptr_t private,
24019370Spst					 const struct iio_chan_spec *chan,
24119370Spst					 const char *buf, size_t len)
24219370Spst{
24319370Spst	struct sunrise_dev *sunrise = iio_priv(iiodev);
24419370Spst	bool enable;
24519370Spst	int ret;
24619370Spst
24719370Spst	ret = kstrtobool(buf, &enable);
24819370Spst	if (ret)
24919370Spst		return ret;
25019370Spst
25119370Spst	if (!enable)
25219370Spst		return len;
25319370Spst
25419370Spst	mutex_lock(&sunrise->lock);
25519370Spst	ret = sunrise_calibrate(sunrise, &calib_data[SUNRISE_CALIBRATION_FACTORY]);
25619370Spst	mutex_unlock(&sunrise->lock);
25798944Sobrien	if (ret)
25819370Spst		return ret;
25919370Spst
26019370Spst	return len;
26119370Spst}
26246283Sdfr
26398944Sobrienstatic ssize_t sunrise_cal_background_write(struct iio_dev *iiodev,
26419370Spst					    uintptr_t private,
26519370Spst					    const struct iio_chan_spec *chan,
26619370Spst					    const char *buf, size_t len)
26719370Spst{
26819370Spst	struct sunrise_dev *sunrise = iio_priv(iiodev);
26919370Spst	bool enable;
27019370Spst	int ret;
27119370Spst
27219370Spst	ret = kstrtobool(buf, &enable);
27319370Spst	if (ret)
27419370Spst		return ret;
27519370Spst
27619370Spst	if (!enable)
27719370Spst		return len;
27819370Spst
27919370Spst	mutex_lock(&sunrise->lock);
28019370Spst	ret = sunrise_calibrate(sunrise, &calib_data[SUNRISE_CALIBRATION_BACKGROUND]);
28119370Spst	mutex_unlock(&sunrise->lock);
28219370Spst	if (ret)
28319370Spst		return ret;
28419370Spst
28519370Spst	return len;
28698944Sobrien}
28798944Sobrien
28819370Spst /* Enumerate and retrieve the chip error status. */
28919370Spstenum {
29019370Spst	SUNRISE_ERROR_FATAL,
29119370Spst	SUNRISE_ERROR_I2C,
29219370Spst	SUNRISE_ERROR_ALGORITHM,
29319370Spst	SUNRISE_ERROR_CALIBRATION,
29419370Spst	SUNRISE_ERROR_SELF_DIAGNOSTIC,
29519370Spst	SUNRISE_ERROR_OUT_OF_RANGE,
29619370Spst	SUNRISE_ERROR_MEMORY,
29719370Spst	SUNRISE_ERROR_NO_MEASUREMENT,
29819370Spst	SUNRISE_ERROR_LOW_VOLTAGE,
29919370Spst	SUNRISE_ERROR_MEASUREMENT_TIMEOUT,
30019370Spst};
30119370Spst
30219370Spststatic const char * const sunrise_error_statuses[] = {
30319370Spst	[SUNRISE_ERROR_FATAL] = "error_fatal",
30419370Spst	[SUNRISE_ERROR_I2C] = "error_i2c",
30519370Spst	[SUNRISE_ERROR_ALGORITHM] = "error_algorithm",
30619370Spst	[SUNRISE_ERROR_CALIBRATION] = "error_calibration",
30719370Spst	[SUNRISE_ERROR_SELF_DIAGNOSTIC] = "error_self_diagnostic",
30819370Spst	[SUNRISE_ERROR_OUT_OF_RANGE] = "error_out_of_range",
30919370Spst	[SUNRISE_ERROR_MEMORY] = "error_memory",
31019370Spst	[SUNRISE_ERROR_NO_MEASUREMENT] = "error_no_measurement",
31119370Spst	[SUNRISE_ERROR_LOW_VOLTAGE] = "error_low_voltage",
31219370Spst	[SUNRISE_ERROR_MEASUREMENT_TIMEOUT] = "error_measurement_timeout",
31319370Spst};
31419370Spst
31519370Spststatic const struct iio_enum sunrise_error_statuses_enum = {
31619370Spst	.items = sunrise_error_statuses,
31719370Spst	.num_items = ARRAY_SIZE(sunrise_error_statuses),
31819370Spst};
31919370Spst
32019370Spststatic ssize_t sunrise_error_status_read(struct iio_dev *iiodev,
32119370Spst					 uintptr_t private,
32219370Spst					 const struct iio_chan_spec *chan,
32319370Spst					 char *buf)
32419370Spst{
32519370Spst	struct sunrise_dev *sunrise = iio_priv(iiodev);
32619370Spst	unsigned long errors;
32798944Sobrien	ssize_t len = 0;
32819370Spst	u16 value;
32919370Spst	int ret;
33019370Spst	u8 i;
33119370Spst
332130803Smarcel	mutex_lock(&sunrise->lock);
333130803Smarcel	ret = sunrise_read_word(sunrise, SUNRISE_ERROR_STATUS_REG, &value);
334130803Smarcel	if (ret) {
335130803Smarcel		mutex_unlock(&sunrise->lock);
336130803Smarcel		return ret;
33719370Spst	}
33819370Spst
33919370Spst	errors = value;
34019370Spst	for_each_set_bit(i, &errors, ARRAY_SIZE(sunrise_error_statuses))
34119370Spst		len += sysfs_emit_at(buf, len, "%s ", sunrise_error_statuses[i]);
34219370Spst
34319370Spst	if (len)
34419370Spst		buf[len - 1] = '\n';
34519370Spst
34619370Spst	mutex_unlock(&sunrise->lock);
34719370Spst
34819370Spst	return len;
34919370Spst}
35019370Spst
35119370Spststatic const struct iio_chan_spec_ext_info sunrise_concentration_ext_info[] = {
35219370Spst	/* Calibration triggers. */
35319370Spst	{
35419370Spst		.name = "calibration_factory",
35519370Spst		.write = sunrise_cal_factory_write,
35619370Spst		.shared = IIO_SEPARATE,
35719370Spst	},
35819370Spst	{
35919370Spst		.name = "calibration_background",
36019370Spst		.write = sunrise_cal_background_write,
36119370Spst		.shared = IIO_SEPARATE,
36219370Spst	},
36319370Spst
364130803Smarcel	/* Error statuses. */
36519370Spst	{
36619370Spst		.name = "error_status",
36719370Spst		.read = sunrise_error_status_read,
36819370Spst		.shared = IIO_SHARED_BY_ALL,
36919370Spst	},
37019370Spst	{
37119370Spst		.name = "error_status_available",
37219370Spst		.shared = IIO_SHARED_BY_ALL,
37319370Spst		.read = iio_enum_available_read,
37419370Spst		.private = (uintptr_t)&sunrise_error_statuses_enum,
37519370Spst	},
37619370Spst	{}
37719370Spst};
37819370Spst
37919370Spststatic const struct iio_chan_spec sunrise_channels[] = {
38019370Spst	{
38119370Spst		.type = IIO_CONCENTRATION,
38219370Spst		.modified = 1,
38319370Spst		.channel2 = IIO_MOD_CO2,
38419370Spst		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
38519370Spst				      BIT(IIO_CHAN_INFO_SCALE),
38619370Spst		.ext_info = sunrise_concentration_ext_info,
38719370Spst	},
38819370Spst	{
38919370Spst		.type = IIO_TEMP,
39019370Spst		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
39119370Spst				      BIT(IIO_CHAN_INFO_SCALE),
39219370Spst	},
39319370Spst};
39419370Spst
39519370Spststatic int sunrise_read_raw(struct iio_dev *iio_dev,
39619370Spst			    const struct iio_chan_spec *chan,
39798944Sobrien			    int *val, int *val2, long mask)
39898944Sobrien{
39998944Sobrien	struct sunrise_dev *sunrise = iio_priv(iio_dev);
40019370Spst	u16 value;
40119370Spst	int ret;
40219370Spst
40319370Spst	switch (mask) {
40419370Spst	case IIO_CHAN_INFO_RAW:
40519370Spst		switch (chan->type) {
40619370Spst		case IIO_CONCENTRATION:
407			mutex_lock(&sunrise->lock);
408			ret = sunrise_read_word(sunrise, SUNRISE_CO2_FILTERED_COMP_REG,
409						&value);
410			mutex_unlock(&sunrise->lock);
411
412			if (ret)
413				return ret;
414
415			*val = value;
416			return IIO_VAL_INT;
417
418		case IIO_TEMP:
419			mutex_lock(&sunrise->lock);
420			ret = sunrise_read_word(sunrise, SUNRISE_CHIP_TEMPERATURE_REG,
421						&value);
422			mutex_unlock(&sunrise->lock);
423
424			if (ret)
425				return ret;
426
427			*val = value;
428			return IIO_VAL_INT;
429
430		default:
431			return -EINVAL;
432		}
433
434	case IIO_CHAN_INFO_SCALE:
435		switch (chan->type) {
436		case IIO_CONCENTRATION:
437			/*
438			 * 1 / 10^4 to comply with IIO scale for CO2
439			 * (percentage). The chip CO2 reading range is [400 -
440			 * 5000] ppm which corresponds to [0,004 - 0,5] %.
441			 */
442			*val = 1;
443			*val2 = 10000;
444			return IIO_VAL_FRACTIONAL;
445
446		case IIO_TEMP:
447			/* x10 to comply with IIO scale (millidegrees celsius). */
448			*val = 10;
449			return IIO_VAL_INT;
450
451		default:
452			return -EINVAL;
453		}
454
455	default:
456		return -EINVAL;
457	}
458}
459
460static const struct iio_info sunrise_info = {
461	.read_raw = sunrise_read_raw,
462};
463
464static const struct regmap_bus sunrise_regmap_bus = {
465	.read = sunrise_regmap_read,
466	.write = sunrise_regmap_write,
467};
468
469static const struct regmap_config sunrise_regmap_config = {
470	.reg_bits = 8,
471	.val_bits = 8,
472};
473
474static int sunrise_probe(struct i2c_client *client)
475{
476	struct sunrise_dev *sunrise;
477	struct iio_dev *iio_dev;
478
479	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA |
480						      I2C_FUNC_SMBUS_BLOCK_DATA)) {
481		dev_err(&client->dev,
482			"Adapter does not support required functionalities\n");
483		return -EOPNOTSUPP;
484	}
485
486	iio_dev = devm_iio_device_alloc(&client->dev, sizeof(*sunrise));
487	if (!iio_dev)
488		return -ENOMEM;
489
490	sunrise = iio_priv(iio_dev);
491	sunrise->client = client;
492	mutex_init(&sunrise->lock);
493
494	i2c_set_clientdata(client, sunrise);
495
496	sunrise->regmap = devm_regmap_init(&client->dev, &sunrise_regmap_bus,
497					   client, &sunrise_regmap_config);
498	if (IS_ERR(sunrise->regmap)) {
499		dev_err(&client->dev, "Failed to initialize regmap\n");
500		return PTR_ERR(sunrise->regmap);
501	}
502
503	/*
504	 * The chip nacks the wake up message. If the adapter does not support
505	 * protocol mangling do not set the I2C_M_IGNORE_NAK flag at the expense
506	 * of possible cruft in the logs.
507	 */
508	if (i2c_check_functionality(client->adapter, I2C_FUNC_PROTOCOL_MANGLING))
509		sunrise->ignore_nak = true;
510
511	iio_dev->info = &sunrise_info;
512	iio_dev->name = DRIVER_NAME;
513	iio_dev->channels = sunrise_channels;
514	iio_dev->num_channels = ARRAY_SIZE(sunrise_channels);
515	iio_dev->modes = INDIO_DIRECT_MODE;
516
517	return devm_iio_device_register(&client->dev, iio_dev);
518}
519
520static const struct of_device_id sunrise_of_match[] = {
521	{ .compatible = "senseair,sunrise-006-0-0007" },
522	{}
523};
524MODULE_DEVICE_TABLE(of, sunrise_of_match);
525
526static struct i2c_driver sunrise_driver = {
527	.driver = {
528		.name = DRIVER_NAME,
529		.of_match_table = sunrise_of_match,
530	},
531	.probe = sunrise_probe,
532};
533module_i2c_driver(sunrise_driver);
534
535MODULE_AUTHOR("Jacopo Mondi <jacopo@jmondi.org>");
536MODULE_DESCRIPTION("Senseair Sunrise 006-0-0007 CO2 sensor IIO driver");
537MODULE_LICENSE("GPL v2");
538