755 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Sensirion SCD30 carbon dioxide sensor core driver4 *5 * Copyright (c) 2020 Tomasz Duszynski <tomasz.duszynski@octakon.com>6 */7#include <linux/bits.h>8#include <linux/completion.h>9#include <linux/delay.h>10#include <linux/device.h>11#include <linux/errno.h>12#include <linux/export.h>13#include <linux/iio/buffer.h>14#include <linux/iio/iio.h>15#include <linux/iio/sysfs.h>16#include <linux/iio/trigger.h>17#include <linux/iio/trigger_consumer.h>18#include <linux/iio/triggered_buffer.h>19#include <linux/iio/types.h>20#include <linux/interrupt.h>21#include <linux/irqreturn.h>22#include <linux/jiffies.h>23#include <linux/kernel.h>24#include <linux/module.h>25#include <linux/mutex.h>26#include <linux/regulator/consumer.h>27#include <linux/string.h>28#include <linux/sysfs.h>29#include <linux/types.h>30#include <asm/byteorder.h>31 32#include "scd30.h"33 34#define SCD30_PRESSURE_COMP_MIN_MBAR 70035#define SCD30_PRESSURE_COMP_MAX_MBAR 140036#define SCD30_PRESSURE_COMP_DEFAULT 101337#define SCD30_MEAS_INTERVAL_MIN_S 238#define SCD30_MEAS_INTERVAL_MAX_S 180039#define SCD30_MEAS_INTERVAL_DEFAULT SCD30_MEAS_INTERVAL_MIN_S40#define SCD30_FRC_MIN_PPM 40041#define SCD30_FRC_MAX_PPM 200042#define SCD30_TEMP_OFFSET_MAX 65536043#define SCD30_EXTRA_TIMEOUT_PER_S 25044 45enum {46 SCD30_CONC,47 SCD30_TEMP,48 SCD30_HR,49};50 51static int scd30_command_write(struct scd30_state *state, enum scd30_cmd cmd, u16 arg)52{53 return state->command(state, cmd, arg, NULL, 0);54}55 56static int scd30_command_read(struct scd30_state *state, enum scd30_cmd cmd, u16 *val)57{58 __be16 tmp;59 int ret;60 61 ret = state->command(state, cmd, 0, &tmp, sizeof(tmp));62 *val = be16_to_cpup(&tmp);63 64 return ret;65}66 67static int scd30_reset(struct scd30_state *state)68{69 int ret;70 u16 val;71 72 ret = scd30_command_write(state, CMD_RESET, 0);73 if (ret)74 return ret;75 76 /* sensor boots up within 2 secs */77 msleep(2000);78 /*79 * Power-on-reset causes sensor to produce some glitch on i2c bus and80 * some controllers end up in error state. Try to recover by placing81 * any data on the bus.82 */83 scd30_command_read(state, CMD_MEAS_READY, &val);84 85 return 0;86}87 88/* simplified float to fixed point conversion with a scaling factor of 0.01 */89static int scd30_float_to_fp(int float32)90{91 int fraction, shift,92 mantissa = float32 & GENMASK(22, 0),93 sign = (float32 & BIT(31)) ? -1 : 1,94 exp = (float32 & ~BIT(31)) >> 23;95 96 /* special case 0 */97 if (!exp && !mantissa)98 return 0;99 100 exp -= 127;101 if (exp < 0) {102 exp = -exp;103 /* return values ranging from 1 to 99 */104 return sign * ((((BIT(23) + mantissa) * 100) >> 23) >> exp);105 }106 107 /* return values starting at 100 */108 shift = 23 - exp;109 float32 = BIT(exp) + (mantissa >> shift);110 fraction = mantissa & GENMASK(shift - 1, 0);111 112 return sign * (float32 * 100 + ((fraction * 100) >> shift));113}114 115static int scd30_read_meas(struct scd30_state *state)116{117 int i, ret;118 119 ret = state->command(state, CMD_READ_MEAS, 0, state->meas, sizeof(state->meas));120 if (ret)121 return ret;122 123 be32_to_cpu_array(state->meas, (__be32 *)state->meas, ARRAY_SIZE(state->meas));124 125 for (i = 0; i < ARRAY_SIZE(state->meas); i++)126 state->meas[i] = scd30_float_to_fp(state->meas[i]);127 128 /*129 * co2 is left unprocessed while temperature and humidity are scaled130 * to milli deg C and milli percent respectively.131 */132 state->meas[SCD30_TEMP] *= 10;133 state->meas[SCD30_HR] *= 10;134 135 return 0;136}137 138static int scd30_wait_meas_irq(struct scd30_state *state)139{140 int ret, timeout;141 142 reinit_completion(&state->meas_ready);143 enable_irq(state->irq);144 timeout = msecs_to_jiffies(state->meas_interval * (1000 + SCD30_EXTRA_TIMEOUT_PER_S));145 ret = wait_for_completion_interruptible_timeout(&state->meas_ready, timeout);146 if (ret > 0)147 ret = 0;148 else if (!ret)149 ret = -ETIMEDOUT;150 151 disable_irq(state->irq);152 153 return ret;154}155 156static int scd30_wait_meas_poll(struct scd30_state *state)157{158 int timeout = state->meas_interval * SCD30_EXTRA_TIMEOUT_PER_S, tries = 5;159 160 do {161 int ret;162 u16 val;163 164 ret = scd30_command_read(state, CMD_MEAS_READY, &val);165 if (ret)166 return -EIO;167 168 /* new measurement available */169 if (val)170 break;171 172 msleep_interruptible(timeout);173 } while (--tries);174 175 return tries ? 0 : -ETIMEDOUT;176}177 178static int scd30_read_poll(struct scd30_state *state)179{180 int ret;181 182 ret = scd30_wait_meas_poll(state);183 if (ret)184 return ret;185 186 return scd30_read_meas(state);187}188 189static int scd30_read(struct scd30_state *state)190{191 if (state->irq > 0)192 return scd30_wait_meas_irq(state);193 194 return scd30_read_poll(state);195}196 197static int scd30_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan,198 int *val, int *val2, long mask)199{200 struct scd30_state *state = iio_priv(indio_dev);201 int ret = -EINVAL;202 u16 tmp;203 204 mutex_lock(&state->lock);205 switch (mask) {206 case IIO_CHAN_INFO_RAW:207 case IIO_CHAN_INFO_PROCESSED:208 if (chan->output) {209 *val = state->pressure_comp;210 ret = IIO_VAL_INT;211 break;212 }213 214 ret = iio_device_claim_direct_mode(indio_dev);215 if (ret)216 break;217 218 ret = scd30_read(state);219 if (ret) {220 iio_device_release_direct_mode(indio_dev);221 break;222 }223 224 *val = state->meas[chan->address];225 iio_device_release_direct_mode(indio_dev);226 ret = IIO_VAL_INT;227 break;228 case IIO_CHAN_INFO_SCALE:229 *val = 0;230 *val2 = 1;231 ret = IIO_VAL_INT_PLUS_MICRO;232 break;233 case IIO_CHAN_INFO_SAMP_FREQ:234 ret = scd30_command_read(state, CMD_MEAS_INTERVAL, &tmp);235 if (ret)236 break;237 238 *val = 0;239 *val2 = 1000000000 / tmp;240 ret = IIO_VAL_INT_PLUS_NANO;241 break;242 case IIO_CHAN_INFO_CALIBBIAS:243 ret = scd30_command_read(state, CMD_TEMP_OFFSET, &tmp);244 if (ret)245 break;246 247 *val = tmp;248 ret = IIO_VAL_INT;249 break;250 }251 mutex_unlock(&state->lock);252 253 return ret;254}255 256static int scd30_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan,257 int val, int val2, long mask)258{259 struct scd30_state *state = iio_priv(indio_dev);260 int ret = -EINVAL;261 262 mutex_lock(&state->lock);263 switch (mask) {264 case IIO_CHAN_INFO_SAMP_FREQ:265 if (val)266 break;267 268 val = 1000000000 / val2;269 if (val < SCD30_MEAS_INTERVAL_MIN_S || val > SCD30_MEAS_INTERVAL_MAX_S)270 break;271 272 ret = scd30_command_write(state, CMD_MEAS_INTERVAL, val);273 if (ret)274 break;275 276 state->meas_interval = val;277 break;278 case IIO_CHAN_INFO_RAW:279 switch (chan->type) {280 case IIO_PRESSURE:281 if (val < SCD30_PRESSURE_COMP_MIN_MBAR ||282 val > SCD30_PRESSURE_COMP_MAX_MBAR)283 break;284 285 ret = scd30_command_write(state, CMD_START_MEAS, val);286 if (ret)287 break;288 289 state->pressure_comp = val;290 break;291 default:292 break;293 }294 break;295 case IIO_CHAN_INFO_CALIBBIAS:296 if (val < 0 || val > SCD30_TEMP_OFFSET_MAX)297 break;298 /*299 * Manufacturer does not explicitly specify min/max sensible300 * values hence check is omitted for simplicity.301 */302 ret = scd30_command_write(state, CMD_TEMP_OFFSET / 10, val);303 }304 mutex_unlock(&state->lock);305 306 return ret;307}308 309static int scd30_write_raw_get_fmt(struct iio_dev *indio_dev, struct iio_chan_spec const *chan,310 long mask)311{312 switch (mask) {313 case IIO_CHAN_INFO_SAMP_FREQ:314 return IIO_VAL_INT_PLUS_NANO;315 case IIO_CHAN_INFO_RAW:316 case IIO_CHAN_INFO_CALIBBIAS:317 return IIO_VAL_INT;318 }319 320 return -EINVAL;321}322 323static const int scd30_pressure_raw_available[] = {324 SCD30_PRESSURE_COMP_MIN_MBAR, 1, SCD30_PRESSURE_COMP_MAX_MBAR,325};326 327static const int scd30_temp_calibbias_available[] = {328 0, 10, SCD30_TEMP_OFFSET_MAX,329};330 331static int scd30_read_avail(struct iio_dev *indio_dev, struct iio_chan_spec const *chan,332 const int **vals, int *type, int *length, long mask)333{334 switch (mask) {335 case IIO_CHAN_INFO_RAW:336 *vals = scd30_pressure_raw_available;337 *type = IIO_VAL_INT;338 339 return IIO_AVAIL_RANGE;340 case IIO_CHAN_INFO_CALIBBIAS:341 *vals = scd30_temp_calibbias_available;342 *type = IIO_VAL_INT;343 344 return IIO_AVAIL_RANGE;345 }346 347 return -EINVAL;348}349 350static ssize_t sampling_frequency_available_show(struct device *dev, struct device_attribute *attr,351 char *buf)352{353 int i = SCD30_MEAS_INTERVAL_MIN_S;354 ssize_t len = 0;355 356 do {357 len += sysfs_emit_at(buf, len, "0.%09u ", 1000000000 / i);358 /*359 * Not all values fit PAGE_SIZE buffer hence print every 6th360 * (each frequency differs by 6s in time domain from the361 * adjacent). Unlisted but valid ones are still accepted.362 */363 i += 6;364 } while (i <= SCD30_MEAS_INTERVAL_MAX_S);365 366 buf[len - 1] = '\n';367 368 return len;369}370 371static ssize_t calibration_auto_enable_show(struct device *dev, struct device_attribute *attr,372 char *buf)373{374 struct iio_dev *indio_dev = dev_to_iio_dev(dev);375 struct scd30_state *state = iio_priv(indio_dev);376 int ret;377 u16 val;378 379 mutex_lock(&state->lock);380 ret = scd30_command_read(state, CMD_ASC, &val);381 mutex_unlock(&state->lock);382 383 return ret ?: sysfs_emit(buf, "%d\n", val);384}385 386static ssize_t calibration_auto_enable_store(struct device *dev, struct device_attribute *attr,387 const char *buf, size_t len)388{389 struct iio_dev *indio_dev = dev_to_iio_dev(dev);390 struct scd30_state *state = iio_priv(indio_dev);391 bool val;392 int ret;393 394 ret = kstrtobool(buf, &val);395 if (ret)396 return ret;397 398 mutex_lock(&state->lock);399 ret = scd30_command_write(state, CMD_ASC, val);400 mutex_unlock(&state->lock);401 402 return ret ?: len;403}404 405static ssize_t calibration_forced_value_show(struct device *dev, struct device_attribute *attr,406 char *buf)407{408 struct iio_dev *indio_dev = dev_to_iio_dev(dev);409 struct scd30_state *state = iio_priv(indio_dev);410 int ret;411 u16 val;412 413 mutex_lock(&state->lock);414 ret = scd30_command_read(state, CMD_FRC, &val);415 mutex_unlock(&state->lock);416 417 return ret ?: sysfs_emit(buf, "%d\n", val);418}419 420static ssize_t calibration_forced_value_store(struct device *dev, struct device_attribute *attr,421 const char *buf, size_t len)422{423 struct iio_dev *indio_dev = dev_to_iio_dev(dev);424 struct scd30_state *state = iio_priv(indio_dev);425 int ret;426 u16 val;427 428 ret = kstrtou16(buf, 0, &val);429 if (ret)430 return ret;431 432 if (val < SCD30_FRC_MIN_PPM || val > SCD30_FRC_MAX_PPM)433 return -EINVAL;434 435 mutex_lock(&state->lock);436 ret = scd30_command_write(state, CMD_FRC, val);437 mutex_unlock(&state->lock);438 439 return ret ?: len;440}441 442static IIO_DEVICE_ATTR_RO(sampling_frequency_available, 0);443static IIO_DEVICE_ATTR_RW(calibration_auto_enable, 0);444static IIO_DEVICE_ATTR_RW(calibration_forced_value, 0);445 446static struct attribute *scd30_attrs[] = {447 &iio_dev_attr_sampling_frequency_available.dev_attr.attr,448 &iio_dev_attr_calibration_auto_enable.dev_attr.attr,449 &iio_dev_attr_calibration_forced_value.dev_attr.attr,450 NULL451};452 453static const struct attribute_group scd30_attr_group = {454 .attrs = scd30_attrs,455};456 457static const struct iio_info scd30_info = {458 .attrs = &scd30_attr_group,459 .read_raw = scd30_read_raw,460 .write_raw = scd30_write_raw,461 .write_raw_get_fmt = scd30_write_raw_get_fmt,462 .read_avail = scd30_read_avail,463};464 465#define SCD30_CHAN_SCAN_TYPE(_sign, _realbits) .scan_type = { \466 .sign = _sign, \467 .realbits = _realbits, \468 .storagebits = 32, \469 .endianness = IIO_CPU, \470}471 472static const struct iio_chan_spec scd30_channels[] = {473 {474 /*475 * this channel is special in a sense we are pretending that476 * sensor is able to change measurement chamber pressure but in477 * fact we're just setting pressure compensation value478 */479 .type = IIO_PRESSURE,480 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),481 .info_mask_separate_available = BIT(IIO_CHAN_INFO_RAW),482 .output = 1,483 .scan_index = -1,484 },485 {486 .type = IIO_CONCENTRATION,487 .channel2 = IIO_MOD_CO2,488 .address = SCD30_CONC,489 .scan_index = SCD30_CONC,490 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |491 BIT(IIO_CHAN_INFO_SCALE),492 .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),493 .modified = 1,494 495 SCD30_CHAN_SCAN_TYPE('u', 20),496 },497 {498 .type = IIO_TEMP,499 .address = SCD30_TEMP,500 .scan_index = SCD30_TEMP,501 .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |502 BIT(IIO_CHAN_INFO_CALIBBIAS),503 .info_mask_separate_available = BIT(IIO_CHAN_INFO_CALIBBIAS),504 .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),505 506 SCD30_CHAN_SCAN_TYPE('s', 18),507 },508 {509 .type = IIO_HUMIDITYRELATIVE,510 .address = SCD30_HR,511 .scan_index = SCD30_HR,512 .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),513 .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),514 515 SCD30_CHAN_SCAN_TYPE('u', 17),516 },517 IIO_CHAN_SOFT_TIMESTAMP(3),518};519 520static int scd30_suspend(struct device *dev)521{522 struct iio_dev *indio_dev = dev_get_drvdata(dev);523 struct scd30_state *state = iio_priv(indio_dev);524 int ret;525 526 ret = scd30_command_write(state, CMD_STOP_MEAS, 0);527 if (ret)528 return ret;529 530 return regulator_disable(state->vdd);531}532 533static int scd30_resume(struct device *dev)534{535 struct iio_dev *indio_dev = dev_get_drvdata(dev);536 struct scd30_state *state = iio_priv(indio_dev);537 int ret;538 539 ret = regulator_enable(state->vdd);540 if (ret)541 return ret;542 543 return scd30_command_write(state, CMD_START_MEAS, state->pressure_comp);544}545 546EXPORT_NS_SIMPLE_DEV_PM_OPS(scd30_pm_ops, scd30_suspend, scd30_resume, IIO_SCD30);547 548static void scd30_stop_meas(void *data)549{550 struct scd30_state *state = data;551 552 scd30_command_write(state, CMD_STOP_MEAS, 0);553}554 555static void scd30_disable_regulator(void *data)556{557 struct scd30_state *state = data;558 559 regulator_disable(state->vdd);560}561 562static irqreturn_t scd30_irq_handler(int irq, void *priv)563{564 struct iio_dev *indio_dev = priv;565 566 if (iio_buffer_enabled(indio_dev)) {567 iio_trigger_poll(indio_dev->trig);568 569 return IRQ_HANDLED;570 }571 572 return IRQ_WAKE_THREAD;573}574 575static irqreturn_t scd30_irq_thread_handler(int irq, void *priv)576{577 struct iio_dev *indio_dev = priv;578 struct scd30_state *state = iio_priv(indio_dev);579 int ret;580 581 ret = scd30_read_meas(state);582 if (ret)583 goto out;584 585 complete_all(&state->meas_ready);586out:587 return IRQ_HANDLED;588}589 590static irqreturn_t scd30_trigger_handler(int irq, void *p)591{592 struct iio_poll_func *pf = p;593 struct iio_dev *indio_dev = pf->indio_dev;594 struct scd30_state *state = iio_priv(indio_dev);595 struct {596 int data[SCD30_MEAS_COUNT];597 s64 ts __aligned(8);598 } scan;599 int ret;600 601 mutex_lock(&state->lock);602 if (!iio_trigger_using_own(indio_dev))603 ret = scd30_read_poll(state);604 else605 ret = scd30_read_meas(state);606 memset(&scan, 0, sizeof(scan));607 memcpy(scan.data, state->meas, sizeof(state->meas));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 scd30_set_trigger_state(struct iio_trigger *trig, bool state)619{620 struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);621 struct scd30_state *st = iio_priv(indio_dev);622 623 if (state)624 enable_irq(st->irq);625 else626 disable_irq(st->irq);627 628 return 0;629}630 631static const struct iio_trigger_ops scd30_trigger_ops = {632 .set_trigger_state = scd30_set_trigger_state,633 .validate_device = iio_trigger_validate_own_device,634};635 636static int scd30_setup_trigger(struct iio_dev *indio_dev)637{638 struct scd30_state *state = iio_priv(indio_dev);639 struct device *dev = indio_dev->dev.parent;640 struct iio_trigger *trig;641 int ret;642 643 trig = devm_iio_trigger_alloc(dev, "%s-dev%d", indio_dev->name,644 iio_device_id(indio_dev));645 if (!trig)646 return dev_err_probe(dev, -ENOMEM, "failed to allocate trigger\n");647 648 trig->ops = &scd30_trigger_ops;649 iio_trigger_set_drvdata(trig, indio_dev);650 651 ret = devm_iio_trigger_register(dev, trig);652 if (ret)653 return ret;654 655 indio_dev->trig = iio_trigger_get(trig);656 657 /*658 * Interrupt is enabled just before taking a fresh measurement659 * and disabled afterwards. This means we need to ensure it is not660 * enabled here to keep calls to enable/disable balanced.661 */662 ret = devm_request_threaded_irq(dev, state->irq, scd30_irq_handler,663 scd30_irq_thread_handler,664 IRQF_TRIGGER_HIGH | IRQF_ONESHOT |665 IRQF_NO_AUTOEN,666 indio_dev->name, indio_dev);667 if (ret)668 return dev_err_probe(dev, ret, "failed to request irq\n");669 670 return 0;671}672 673int scd30_probe(struct device *dev, int irq, const char *name, void *priv,674 scd30_command_t command)675{676 static const unsigned long scd30_scan_masks[] = { 0x07, 0x00 };677 struct scd30_state *state;678 struct iio_dev *indio_dev;679 int ret;680 u16 val;681 682 indio_dev = devm_iio_device_alloc(dev, sizeof(*state));683 if (!indio_dev)684 return -ENOMEM;685 686 state = iio_priv(indio_dev);687 state->dev = dev;688 state->priv = priv;689 state->irq = irq;690 state->pressure_comp = SCD30_PRESSURE_COMP_DEFAULT;691 state->meas_interval = SCD30_MEAS_INTERVAL_DEFAULT;692 state->command = command;693 mutex_init(&state->lock);694 init_completion(&state->meas_ready);695 696 dev_set_drvdata(dev, indio_dev);697 698 indio_dev->info = &scd30_info;699 indio_dev->name = name;700 indio_dev->channels = scd30_channels;701 indio_dev->num_channels = ARRAY_SIZE(scd30_channels);702 indio_dev->modes = INDIO_DIRECT_MODE;703 indio_dev->available_scan_masks = scd30_scan_masks;704 705 state->vdd = devm_regulator_get(dev, "vdd");706 if (IS_ERR(state->vdd))707 return dev_err_probe(dev, PTR_ERR(state->vdd), "failed to get regulator\n");708 709 ret = regulator_enable(state->vdd);710 if (ret)711 return ret;712 713 ret = devm_add_action_or_reset(dev, scd30_disable_regulator, state);714 if (ret)715 return ret;716 717 ret = scd30_reset(state);718 if (ret)719 return dev_err_probe(dev, ret, "failed to reset device\n");720 721 if (state->irq > 0) {722 ret = scd30_setup_trigger(indio_dev);723 if (ret)724 return dev_err_probe(dev, ret, "failed to setup trigger\n");725 }726 727 ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL, scd30_trigger_handler, NULL);728 if (ret)729 return ret;730 731 ret = scd30_command_read(state, CMD_FW_VERSION, &val);732 if (ret)733 return dev_err_probe(dev, ret, "failed to read firmware version\n");734 dev_info(dev, "firmware version: %d.%d\n", val >> 8, (char)val);735 736 ret = scd30_command_write(state, CMD_MEAS_INTERVAL, state->meas_interval);737 if (ret)738 return dev_err_probe(dev, ret, "failed to set measurement interval\n");739 740 ret = scd30_command_write(state, CMD_START_MEAS, state->pressure_comp);741 if (ret)742 return dev_err_probe(dev, ret, "failed to start measurement\n");743 744 ret = devm_add_action_or_reset(dev, scd30_stop_meas, state);745 if (ret)746 return ret;747 748 return devm_iio_device_register(dev, indio_dev);749}750EXPORT_SYMBOL_NS(scd30_probe, IIO_SCD30);751 752MODULE_AUTHOR("Tomasz Duszynski <tomasz.duszynski@octakon.com>");753MODULE_DESCRIPTION("Sensirion SCD30 carbon dioxide sensor core driver");754MODULE_LICENSE("GPL v2");755