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