Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Senseair Sunrise 006-0-0007 CO2 sensor driver.
0004  *
0005  * Copyright (C) 2021 Jacopo Mondi
0006  *
0007  * List of features not yet supported by the driver:
0008  * - controllable EN pin
0009  * - single-shot operations using the nDRY pin.
0010  * - ABC/target calibration
0011  */
0012 
0013 #include <linux/bitops.h>
0014 #include <linux/i2c.h>
0015 #include <linux/kernel.h>
0016 #include <linux/mod_devicetable.h>
0017 #include <linux/module.h>
0018 #include <linux/mutex.h>
0019 #include <linux/regmap.h>
0020 #include <linux/time64.h>
0021 
0022 #include <linux/iio/iio.h>
0023 
0024 #define DRIVER_NAME "sunrise_co2"
0025 
0026 #define SUNRISE_ERROR_STATUS_REG        0x00
0027 #define SUNRISE_CO2_FILTERED_COMP_REG       0x06
0028 #define SUNRISE_CHIP_TEMPERATURE_REG        0x08
0029 #define SUNRISE_CALIBRATION_STATUS_REG      0x81
0030 #define SUNRISE_CALIBRATION_COMMAND_REG     0x82
0031 #define SUNRISE_CALIBRATION_FACTORY_CMD     0x7c02
0032 #define SUNRISE_CALIBRATION_BACKGROUND_CMD  0x7c06
0033 /*
0034  * The calibration timeout is not characterized in the datasheet.
0035  * Use 30 seconds as a reasonable upper limit.
0036  */
0037 #define SUNRISE_CALIBRATION_TIMEOUT_US      (30 * USEC_PER_SEC)
0038 
0039 struct sunrise_dev {
0040     struct i2c_client *client;
0041     struct regmap *regmap;
0042     /* Protects access to IIO attributes. */
0043     struct mutex lock;
0044     bool ignore_nak;
0045 };
0046 
0047 /* Custom regmap read/write operations: perform unlocked access to the i2c bus. */
0048 
0049 static int sunrise_regmap_read(void *context, const void *reg_buf,
0050                    size_t reg_size, void *val_buf, size_t val_size)
0051 {
0052     struct i2c_client *client = context;
0053     struct sunrise_dev *sunrise = i2c_get_clientdata(client);
0054     union i2c_smbus_data data;
0055     int ret;
0056 
0057     if (reg_size != 1 || !val_size)
0058         return -EINVAL;
0059 
0060     memset(&data, 0, sizeof(data));
0061     data.block[0] = val_size;
0062 
0063     /*
0064      * Wake up sensor by sending sensor address: START, sensor address,
0065      * STOP. Sensor will not ACK this byte.
0066      *
0067      * The chip enters a low power state after 15ms without
0068      * communications or after a complete read/write sequence.
0069      */
0070     __i2c_smbus_xfer(client->adapter, client->addr,
0071              sunrise->ignore_nak ? I2C_M_IGNORE_NAK : 0,
0072              I2C_SMBUS_WRITE, 0, I2C_SMBUS_BYTE_DATA, &data);
0073 
0074     usleep_range(500, 1500);
0075 
0076     ret = __i2c_smbus_xfer(client->adapter, client->addr, client->flags,
0077                    I2C_SMBUS_READ, ((u8 *)reg_buf)[0],
0078                    I2C_SMBUS_I2C_BLOCK_DATA, &data);
0079     if (ret < 0)
0080         return ret;
0081 
0082     memcpy(val_buf, &data.block[1], data.block[0]);
0083 
0084     return 0;
0085 }
0086 
0087 static int sunrise_regmap_write(void *context, const void *val_buf, size_t count)
0088 {
0089     struct i2c_client *client = context;
0090     struct sunrise_dev *sunrise = i2c_get_clientdata(client);
0091     union i2c_smbus_data data;
0092 
0093     /* Discard reg address from values count. */
0094     if (!count)
0095         return -EINVAL;
0096     count--;
0097 
0098     memset(&data, 0, sizeof(data));
0099     data.block[0] = count;
0100     memcpy(&data.block[1], (u8 *)val_buf + 1, count);
0101 
0102     __i2c_smbus_xfer(client->adapter, client->addr,
0103              sunrise->ignore_nak ? I2C_M_IGNORE_NAK : 0,
0104              I2C_SMBUS_WRITE, 0, I2C_SMBUS_BYTE_DATA, &data);
0105 
0106     usleep_range(500, 1500);
0107 
0108     return __i2c_smbus_xfer(client->adapter, client->addr, client->flags,
0109                 I2C_SMBUS_WRITE, ((u8 *)val_buf)[0],
0110                 I2C_SMBUS_I2C_BLOCK_DATA, &data);
0111 }
0112 
0113 /*
0114  * Sunrise i2c read/write operations: lock the i2c segment to avoid losing the
0115  * wake up session. Use custom regmap operations that perform unlocked access to
0116  * the i2c bus.
0117  */
0118 static int sunrise_read_byte(struct sunrise_dev *sunrise, u8 reg)
0119 {
0120     const struct i2c_client *client = sunrise->client;
0121     const struct device *dev = &client->dev;
0122     unsigned int val;
0123     int ret;
0124 
0125     i2c_lock_bus(client->adapter, I2C_LOCK_SEGMENT);
0126     ret = regmap_read(sunrise->regmap, reg, &val);
0127     i2c_unlock_bus(client->adapter, I2C_LOCK_SEGMENT);
0128     if (ret) {
0129         dev_err(dev, "Read byte failed: reg 0x%02x (%d)\n", reg, ret);
0130         return ret;
0131     }
0132 
0133     return val;
0134 }
0135 
0136 static int sunrise_read_word(struct sunrise_dev *sunrise, u8 reg, u16 *val)
0137 {
0138     const struct i2c_client *client = sunrise->client;
0139     const struct device *dev = &client->dev;
0140     __be16 be_val;
0141     int ret;
0142 
0143     i2c_lock_bus(client->adapter, I2C_LOCK_SEGMENT);
0144     ret = regmap_bulk_read(sunrise->regmap, reg, &be_val, sizeof(be_val));
0145     i2c_unlock_bus(client->adapter, I2C_LOCK_SEGMENT);
0146     if (ret) {
0147         dev_err(dev, "Read word failed: reg 0x%02x (%d)\n", reg, ret);
0148         return ret;
0149     }
0150 
0151     *val = be16_to_cpu(be_val);
0152 
0153     return 0;
0154 }
0155 
0156 static int sunrise_write_byte(struct sunrise_dev *sunrise, u8 reg, u8 val)
0157 {
0158     const struct i2c_client *client = sunrise->client;
0159     const struct device *dev = &client->dev;
0160     int ret;
0161 
0162     i2c_lock_bus(client->adapter, I2C_LOCK_SEGMENT);
0163     ret = regmap_write(sunrise->regmap, reg, val);
0164     i2c_unlock_bus(client->adapter, I2C_LOCK_SEGMENT);
0165     if (ret)
0166         dev_err(dev, "Write byte failed: reg 0x%02x (%d)\n", reg, ret);
0167 
0168     return ret;
0169 }
0170 
0171 static int sunrise_write_word(struct sunrise_dev *sunrise, u8 reg, u16 data)
0172 {
0173     const struct i2c_client *client = sunrise->client;
0174     const struct device *dev = &client->dev;
0175     __be16 be_data = cpu_to_be16(data);
0176     int ret;
0177 
0178     i2c_lock_bus(client->adapter, I2C_LOCK_SEGMENT);
0179     ret = regmap_bulk_write(sunrise->regmap, reg, &be_data, sizeof(be_data));
0180     i2c_unlock_bus(client->adapter, I2C_LOCK_SEGMENT);
0181     if (ret)
0182         dev_err(dev, "Write word failed: reg 0x%02x (%d)\n", reg, ret);
0183 
0184     return ret;
0185 }
0186 
0187 /* Trigger a calibration cycle. */
0188 
0189 enum {
0190     SUNRISE_CALIBRATION_FACTORY,
0191     SUNRISE_CALIBRATION_BACKGROUND,
0192 };
0193 
0194 static const struct sunrise_calib_data {
0195     u16 cmd;
0196     u8 bit;
0197     const char * const name;
0198 } calib_data[] = {
0199     [SUNRISE_CALIBRATION_FACTORY] = {
0200         SUNRISE_CALIBRATION_FACTORY_CMD,
0201         BIT(2),
0202         "factory_calibration",
0203     },
0204     [SUNRISE_CALIBRATION_BACKGROUND] = {
0205         SUNRISE_CALIBRATION_BACKGROUND_CMD,
0206         BIT(5),
0207         "background_calibration",
0208     },
0209 };
0210 
0211 static int sunrise_calibrate(struct sunrise_dev *sunrise,
0212                  const struct sunrise_calib_data *data)
0213 {
0214     unsigned int status;
0215     int ret;
0216 
0217     /* Reset the calibration status reg. */
0218     ret = sunrise_write_byte(sunrise, SUNRISE_CALIBRATION_STATUS_REG, 0x00);
0219     if (ret)
0220         return ret;
0221 
0222     /* Write a calibration command and poll the calibration status bit. */
0223     ret = sunrise_write_word(sunrise, SUNRISE_CALIBRATION_COMMAND_REG, data->cmd);
0224     if (ret)
0225         return ret;
0226 
0227     dev_dbg(&sunrise->client->dev, "%s in progress\n", data->name);
0228 
0229     /*
0230      * Calibration takes several seconds, so the sleep time between reads
0231      * can be pretty relaxed.
0232      */
0233     return read_poll_timeout(sunrise_read_byte, status, status & data->bit,
0234                  200000, SUNRISE_CALIBRATION_TIMEOUT_US, false,
0235                  sunrise, SUNRISE_CALIBRATION_STATUS_REG);
0236 }
0237 
0238 static ssize_t sunrise_cal_factory_write(struct iio_dev *iiodev,
0239                      uintptr_t private,
0240                      const struct iio_chan_spec *chan,
0241                      const char *buf, size_t len)
0242 {
0243     struct sunrise_dev *sunrise = iio_priv(iiodev);
0244     bool enable;
0245     int ret;
0246 
0247     ret = kstrtobool(buf, &enable);
0248     if (ret)
0249         return ret;
0250 
0251     if (!enable)
0252         return len;
0253 
0254     mutex_lock(&sunrise->lock);
0255     ret = sunrise_calibrate(sunrise, &calib_data[SUNRISE_CALIBRATION_FACTORY]);
0256     mutex_unlock(&sunrise->lock);
0257     if (ret)
0258         return ret;
0259 
0260     return len;
0261 }
0262 
0263 static ssize_t sunrise_cal_background_write(struct iio_dev *iiodev,
0264                         uintptr_t private,
0265                         const struct iio_chan_spec *chan,
0266                         const char *buf, size_t len)
0267 {
0268     struct sunrise_dev *sunrise = iio_priv(iiodev);
0269     bool enable;
0270     int ret;
0271 
0272     ret = kstrtobool(buf, &enable);
0273     if (ret)
0274         return ret;
0275 
0276     if (!enable)
0277         return len;
0278 
0279     mutex_lock(&sunrise->lock);
0280     ret = sunrise_calibrate(sunrise, &calib_data[SUNRISE_CALIBRATION_BACKGROUND]);
0281     mutex_unlock(&sunrise->lock);
0282     if (ret)
0283         return ret;
0284 
0285     return len;
0286 }
0287 
0288  /* Enumerate and retrieve the chip error status. */
0289 enum {
0290     SUNRISE_ERROR_FATAL,
0291     SUNRISE_ERROR_I2C,
0292     SUNRISE_ERROR_ALGORITHM,
0293     SUNRISE_ERROR_CALIBRATION,
0294     SUNRISE_ERROR_SELF_DIAGNOSTIC,
0295     SUNRISE_ERROR_OUT_OF_RANGE,
0296     SUNRISE_ERROR_MEMORY,
0297     SUNRISE_ERROR_NO_MEASUREMENT,
0298     SUNRISE_ERROR_LOW_VOLTAGE,
0299     SUNRISE_ERROR_MEASUREMENT_TIMEOUT,
0300 };
0301 
0302 static const char * const sunrise_error_statuses[] = {
0303     [SUNRISE_ERROR_FATAL] = "error_fatal",
0304     [SUNRISE_ERROR_I2C] = "error_i2c",
0305     [SUNRISE_ERROR_ALGORITHM] = "error_algorithm",
0306     [SUNRISE_ERROR_CALIBRATION] = "error_calibration",
0307     [SUNRISE_ERROR_SELF_DIAGNOSTIC] = "error_self_diagnostic",
0308     [SUNRISE_ERROR_OUT_OF_RANGE] = "error_out_of_range",
0309     [SUNRISE_ERROR_MEMORY] = "error_memory",
0310     [SUNRISE_ERROR_NO_MEASUREMENT] = "error_no_measurement",
0311     [SUNRISE_ERROR_LOW_VOLTAGE] = "error_low_voltage",
0312     [SUNRISE_ERROR_MEASUREMENT_TIMEOUT] = "error_measurement_timeout",
0313 };
0314 
0315 static const struct iio_enum sunrise_error_statuses_enum = {
0316     .items = sunrise_error_statuses,
0317     .num_items = ARRAY_SIZE(sunrise_error_statuses),
0318 };
0319 
0320 static ssize_t sunrise_error_status_read(struct iio_dev *iiodev,
0321                      uintptr_t private,
0322                      const struct iio_chan_spec *chan,
0323                      char *buf)
0324 {
0325     struct sunrise_dev *sunrise = iio_priv(iiodev);
0326     unsigned long errors;
0327     ssize_t len = 0;
0328     u16 value;
0329     int ret;
0330     u8 i;
0331 
0332     mutex_lock(&sunrise->lock);
0333     ret = sunrise_read_word(sunrise, SUNRISE_ERROR_STATUS_REG, &value);
0334     if (ret) {
0335         mutex_unlock(&sunrise->lock);
0336         return ret;
0337     }
0338 
0339     errors = value;
0340     for_each_set_bit(i, &errors, ARRAY_SIZE(sunrise_error_statuses))
0341         len += sysfs_emit_at(buf, len, "%s ", sunrise_error_statuses[i]);
0342 
0343     if (len)
0344         buf[len - 1] = '\n';
0345 
0346     mutex_unlock(&sunrise->lock);
0347 
0348     return len;
0349 }
0350 
0351 static const struct iio_chan_spec_ext_info sunrise_concentration_ext_info[] = {
0352     /* Calibration triggers. */
0353     {
0354         .name = "calibration_factory",
0355         .write = sunrise_cal_factory_write,
0356         .shared = IIO_SEPARATE,
0357     },
0358     {
0359         .name = "calibration_background",
0360         .write = sunrise_cal_background_write,
0361         .shared = IIO_SEPARATE,
0362     },
0363 
0364     /* Error statuses. */
0365     {
0366         .name = "error_status",
0367         .read = sunrise_error_status_read,
0368         .shared = IIO_SHARED_BY_ALL,
0369     },
0370     {
0371         .name = "error_status_available",
0372         .shared = IIO_SHARED_BY_ALL,
0373         .read = iio_enum_available_read,
0374         .private = (uintptr_t)&sunrise_error_statuses_enum,
0375     },
0376     {}
0377 };
0378 
0379 static const struct iio_chan_spec sunrise_channels[] = {
0380     {
0381         .type = IIO_CONCENTRATION,
0382         .modified = 1,
0383         .channel2 = IIO_MOD_CO2,
0384         .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
0385                       BIT(IIO_CHAN_INFO_SCALE),
0386         .ext_info = sunrise_concentration_ext_info,
0387     },
0388     {
0389         .type = IIO_TEMP,
0390         .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
0391                       BIT(IIO_CHAN_INFO_SCALE),
0392     },
0393 };
0394 
0395 static int sunrise_read_raw(struct iio_dev *iio_dev,
0396                 const struct iio_chan_spec *chan,
0397                 int *val, int *val2, long mask)
0398 {
0399     struct sunrise_dev *sunrise = iio_priv(iio_dev);
0400     u16 value;
0401     int ret;
0402 
0403     switch (mask) {
0404     case IIO_CHAN_INFO_RAW:
0405         switch (chan->type) {
0406         case IIO_CONCENTRATION:
0407             mutex_lock(&sunrise->lock);
0408             ret = sunrise_read_word(sunrise, SUNRISE_CO2_FILTERED_COMP_REG,
0409                         &value);
0410             mutex_unlock(&sunrise->lock);
0411 
0412             if (ret)
0413                 return ret;
0414 
0415             *val = value;
0416             return IIO_VAL_INT;
0417 
0418         case IIO_TEMP:
0419             mutex_lock(&sunrise->lock);
0420             ret = sunrise_read_word(sunrise, SUNRISE_CHIP_TEMPERATURE_REG,
0421                         &value);
0422             mutex_unlock(&sunrise->lock);
0423 
0424             if (ret)
0425                 return ret;
0426 
0427             *val = value;
0428             return IIO_VAL_INT;
0429 
0430         default:
0431             return -EINVAL;
0432         }
0433 
0434     case IIO_CHAN_INFO_SCALE:
0435         switch (chan->type) {
0436         case IIO_CONCENTRATION:
0437             /*
0438              * 1 / 10^4 to comply with IIO scale for CO2
0439              * (percentage). The chip CO2 reading range is [400 -
0440              * 5000] ppm which corresponds to [0,004 - 0,5] %.
0441              */
0442             *val = 1;
0443             *val2 = 10000;
0444             return IIO_VAL_FRACTIONAL;
0445 
0446         case IIO_TEMP:
0447             /* x10 to comply with IIO scale (millidegrees celsius). */
0448             *val = 10;
0449             return IIO_VAL_INT;
0450 
0451         default:
0452             return -EINVAL;
0453         }
0454 
0455     default:
0456         return -EINVAL;
0457     }
0458 }
0459 
0460 static const struct iio_info sunrise_info = {
0461     .read_raw = sunrise_read_raw,
0462 };
0463 
0464 static const struct regmap_bus sunrise_regmap_bus = {
0465     .read = sunrise_regmap_read,
0466     .write = sunrise_regmap_write,
0467 };
0468 
0469 static const struct regmap_config sunrise_regmap_config = {
0470     .reg_bits = 8,
0471     .val_bits = 8,
0472 };
0473 
0474 static int sunrise_probe(struct i2c_client *client)
0475 {
0476     struct sunrise_dev *sunrise;
0477     struct iio_dev *iio_dev;
0478 
0479     if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA |
0480                               I2C_FUNC_SMBUS_BLOCK_DATA)) {
0481         dev_err(&client->dev,
0482             "Adapter does not support required functionalities\n");
0483         return -EOPNOTSUPP;
0484     }
0485 
0486     iio_dev = devm_iio_device_alloc(&client->dev, sizeof(*sunrise));
0487     if (!iio_dev)
0488         return -ENOMEM;
0489 
0490     sunrise = iio_priv(iio_dev);
0491     sunrise->client = client;
0492     mutex_init(&sunrise->lock);
0493 
0494     i2c_set_clientdata(client, sunrise);
0495 
0496     sunrise->regmap = devm_regmap_init(&client->dev, &sunrise_regmap_bus,
0497                        client, &sunrise_regmap_config);
0498     if (IS_ERR(sunrise->regmap)) {
0499         dev_err(&client->dev, "Failed to initialize regmap\n");
0500         return PTR_ERR(sunrise->regmap);
0501     }
0502 
0503     /*
0504      * The chip nacks the wake up message. If the adapter does not support
0505      * protocol mangling do not set the I2C_M_IGNORE_NAK flag at the expense
0506      * of possible cruft in the logs.
0507      */
0508     if (i2c_check_functionality(client->adapter, I2C_FUNC_PROTOCOL_MANGLING))
0509         sunrise->ignore_nak = true;
0510 
0511     iio_dev->info = &sunrise_info;
0512     iio_dev->name = DRIVER_NAME;
0513     iio_dev->channels = sunrise_channels;
0514     iio_dev->num_channels = ARRAY_SIZE(sunrise_channels);
0515     iio_dev->modes = INDIO_DIRECT_MODE;
0516 
0517     return devm_iio_device_register(&client->dev, iio_dev);
0518 }
0519 
0520 static const struct of_device_id sunrise_of_match[] = {
0521     { .compatible = "senseair,sunrise-006-0-0007" },
0522     {}
0523 };
0524 MODULE_DEVICE_TABLE(of, sunrise_of_match);
0525 
0526 static struct i2c_driver sunrise_driver = {
0527     .driver = {
0528         .name = DRIVER_NAME,
0529         .of_match_table = sunrise_of_match,
0530     },
0531     .probe_new = sunrise_probe,
0532 };
0533 module_i2c_driver(sunrise_driver);
0534 
0535 MODULE_AUTHOR("Jacopo Mondi <jacopo@jmondi.org>");
0536 MODULE_DESCRIPTION("Senseair Sunrise 006-0-0007 CO2 sensor IIO driver");
0537 MODULE_LICENSE("GPL v2");