1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Senseair Sunrise 006-0-0007 CO2 sensor driver.
4 *
5 * Copyright (C) 2021 Jacopo Mondi
6 *
7 * List of features not yet supported by the driver:
8 * - controllable EN pin
9 * - single-shot operations using the nDRY pin.
10 * - ABC/target calibration
11 */
12
13#include <linux/bitops.h>
14#include <linux/i2c.h>
15#include <linux/kernel.h>
16#include <linux/mod_devicetable.h>
17#include <linux/module.h>
18#include <linux/mutex.h>
19#include <linux/regmap.h>
20#include <linux/time64.h>
21
22#include <linux/iio/iio.h>
23
24#define DRIVER_NAME "sunrise_co2"
25
26#define SUNRISE_ERROR_STATUS_REG 0x00
27#define SUNRISE_CO2_FILTERED_COMP_REG 0x06
28#define SUNRISE_CHIP_TEMPERATURE_REG 0x08
29#define SUNRISE_CALIBRATION_STATUS_REG 0x81
30#define SUNRISE_CALIBRATION_COMMAND_REG 0x82
31#define SUNRISE_CALIBRATION_FACTORY_CMD 0x7c02
32#define SUNRISE_CALIBRATION_BACKGROUND_CMD 0x7c06
33/*
34 * The calibration timeout is not characterized in the datasheet.
35 * Use 30 seconds as a reasonable upper limit.
36 */
37#define SUNRISE_CALIBRATION_TIMEOUT_US (30 * USEC_PER_SEC)
38
39struct sunrise_dev {
40 struct i2c_client *client;
41 struct regmap *regmap;
42 /* Protects access to IIO attributes. */
43 struct mutex lock;
44 bool ignore_nak;
45};
46
47/* Custom regmap read/write operations: perform unlocked access to the i2c bus. */
48
49static int sunrise_regmap_read(void *context, const void *reg_buf,
50 size_t reg_size, void *val_buf, size_t val_size)
51{
52 struct i2c_client *client = context;
53 struct sunrise_dev *sunrise = i2c_get_clientdata(client);
54 union i2c_smbus_data data;
55 int ret;
56
57 if (reg_size != 1 || !val_size)
58 return -EINVAL;
59
60 memset(&data, 0, sizeof(data));
61 data.block[0] = val_size;
62
63 /*
64 * Wake up sensor by sending sensor address: START, sensor address,
65 * STOP. Sensor will not ACK this byte.
66 *
67 * The chip enters a low power state after 15ms without
68 * communications or after a complete read/write sequence.
69 */
70 __i2c_smbus_xfer(adapter: client->adapter, addr: client->addr,
71 flags: sunrise->ignore_nak ? I2C_M_IGNORE_NAK : 0,
72 I2C_SMBUS_WRITE, command: 0, I2C_SMBUS_BYTE_DATA, data: &data);
73
74 usleep_range(min: 500, max: 1500);
75
76 ret = __i2c_smbus_xfer(adapter: client->adapter, addr: client->addr, flags: client->flags,
77 I2C_SMBUS_READ, command: ((u8 *)reg_buf)[0],
78 I2C_SMBUS_I2C_BLOCK_DATA, data: &data);
79 if (ret < 0)
80 return ret;
81
82 memcpy(val_buf, &data.block[1], data.block[0]);
83
84 return 0;
85}
86
87static int sunrise_regmap_write(void *context, const void *val_buf, size_t count)
88{
89 struct i2c_client *client = context;
90 struct sunrise_dev *sunrise = i2c_get_clientdata(client);
91 union i2c_smbus_data data;
92
93 /* Discard reg address from values count. */
94 if (!count)
95 return -EINVAL;
96 count--;
97
98 memset(&data, 0, sizeof(data));
99 data.block[0] = count;
100 memcpy(&data.block[1], (u8 *)val_buf + 1, count);
101
102 __i2c_smbus_xfer(adapter: client->adapter, addr: client->addr,
103 flags: sunrise->ignore_nak ? I2C_M_IGNORE_NAK : 0,
104 I2C_SMBUS_WRITE, command: 0, I2C_SMBUS_BYTE_DATA, data: &data);
105
106 usleep_range(min: 500, max: 1500);
107
108 return __i2c_smbus_xfer(adapter: client->adapter, addr: client->addr, flags: client->flags,
109 I2C_SMBUS_WRITE, command: ((u8 *)val_buf)[0],
110 I2C_SMBUS_I2C_BLOCK_DATA, data: &data);
111}
112
113/*
114 * Sunrise i2c read/write operations: lock the i2c segment to avoid losing the
115 * wake up session. Use custom regmap operations that perform unlocked access to
116 * the i2c bus.
117 */
118static int sunrise_read_byte(struct sunrise_dev *sunrise, u8 reg)
119{
120 const struct i2c_client *client = sunrise->client;
121 const struct device *dev = &client->dev;
122 unsigned int val;
123 int ret;
124
125 i2c_lock_bus(adapter: client->adapter, I2C_LOCK_SEGMENT);
126 ret = regmap_read(map: sunrise->regmap, reg, val: &val);
127 i2c_unlock_bus(adapter: client->adapter, I2C_LOCK_SEGMENT);
128 if (ret) {
129 dev_err(dev, "Read byte failed: reg 0x%02x (%d)\n", reg, ret);
130 return ret;
131 }
132
133 return val;
134}
135
136static int sunrise_read_word(struct sunrise_dev *sunrise, u8 reg, u16 *val)
137{
138 const struct i2c_client *client = sunrise->client;
139 const struct device *dev = &client->dev;
140 __be16 be_val;
141 int ret;
142
143 i2c_lock_bus(adapter: client->adapter, I2C_LOCK_SEGMENT);
144 ret = regmap_bulk_read(map: sunrise->regmap, reg, val: &be_val, val_count: sizeof(be_val));
145 i2c_unlock_bus(adapter: client->adapter, I2C_LOCK_SEGMENT);
146 if (ret) {
147 dev_err(dev, "Read word failed: reg 0x%02x (%d)\n", reg, ret);
148 return ret;
149 }
150
151 *val = be16_to_cpu(be_val);
152
153 return 0;
154}
155
156static int sunrise_write_byte(struct sunrise_dev *sunrise, u8 reg, u8 val)
157{
158 const struct i2c_client *client = sunrise->client;
159 const struct device *dev = &client->dev;
160 int ret;
161
162 i2c_lock_bus(adapter: client->adapter, I2C_LOCK_SEGMENT);
163 ret = regmap_write(map: sunrise->regmap, reg, val);
164 i2c_unlock_bus(adapter: client->adapter, I2C_LOCK_SEGMENT);
165 if (ret)
166 dev_err(dev, "Write byte failed: reg 0x%02x (%d)\n", reg, ret);
167
168 return ret;
169}
170
171static int sunrise_write_word(struct sunrise_dev *sunrise, u8 reg, u16 data)
172{
173 const struct i2c_client *client = sunrise->client;
174 const struct device *dev = &client->dev;
175 __be16 be_data = cpu_to_be16(data);
176 int ret;
177
178 i2c_lock_bus(adapter: client->adapter, I2C_LOCK_SEGMENT);
179 ret = regmap_bulk_write(map: sunrise->regmap, reg, val: &be_data, val_count: sizeof(be_data));
180 i2c_unlock_bus(adapter: client->adapter, I2C_LOCK_SEGMENT);
181 if (ret)
182 dev_err(dev, "Write word failed: reg 0x%02x (%d)\n", reg, ret);
183
184 return ret;
185}
186
187/* Trigger a calibration cycle. */
188
189enum {
190 SUNRISE_CALIBRATION_FACTORY,
191 SUNRISE_CALIBRATION_BACKGROUND,
192};
193
194static const struct sunrise_calib_data {
195 u16 cmd;
196 u8 bit;
197 const char * const name;
198} calib_data[] = {
199 [SUNRISE_CALIBRATION_FACTORY] = {
200 SUNRISE_CALIBRATION_FACTORY_CMD,
201 BIT(2),
202 "factory_calibration",
203 },
204 [SUNRISE_CALIBRATION_BACKGROUND] = {
205 SUNRISE_CALIBRATION_BACKGROUND_CMD,
206 BIT(5),
207 .name: "background_calibration",
208 },
209};
210
211static int sunrise_calibrate(struct sunrise_dev *sunrise,
212 const struct sunrise_calib_data *data)
213{
214 unsigned int status;
215 int ret;
216
217 /* Reset the calibration status reg. */
218 ret = sunrise_write_byte(sunrise, SUNRISE_CALIBRATION_STATUS_REG, val: 0x00);
219 if (ret)
220 return ret;
221
222 /* Write a calibration command and poll the calibration status bit. */
223 ret = sunrise_write_word(sunrise, SUNRISE_CALIBRATION_COMMAND_REG, data: data->cmd);
224 if (ret)
225 return ret;
226
227 dev_dbg(&sunrise->client->dev, "%s in progress\n", data->name);
228
229 /*
230 * Calibration takes several seconds, so the sleep time between reads
231 * can be pretty relaxed.
232 */
233 return read_poll_timeout(sunrise_read_byte, status, status & data->bit,
234 200000, SUNRISE_CALIBRATION_TIMEOUT_US, false,
235 sunrise, SUNRISE_CALIBRATION_STATUS_REG);
236}
237
238static ssize_t sunrise_cal_factory_write(struct iio_dev *iiodev,
239 uintptr_t private,
240 const struct iio_chan_spec *chan,
241 const char *buf, size_t len)
242{
243 struct sunrise_dev *sunrise = iio_priv(indio_dev: iiodev);
244 bool enable;
245 int ret;
246
247 ret = kstrtobool(s: buf, res: &enable);
248 if (ret)
249 return ret;
250
251 if (!enable)
252 return len;
253
254 mutex_lock(&sunrise->lock);
255 ret = sunrise_calibrate(sunrise, data: &calib_data[SUNRISE_CALIBRATION_FACTORY]);
256 mutex_unlock(lock: &sunrise->lock);
257 if (ret)
258 return ret;
259
260 return len;
261}
262
263static ssize_t sunrise_cal_background_write(struct iio_dev *iiodev,
264 uintptr_t private,
265 const struct iio_chan_spec *chan,
266 const char *buf, size_t len)
267{
268 struct sunrise_dev *sunrise = iio_priv(indio_dev: iiodev);
269 bool enable;
270 int ret;
271
272 ret = kstrtobool(s: buf, res: &enable);
273 if (ret)
274 return ret;
275
276 if (!enable)
277 return len;
278
279 mutex_lock(&sunrise->lock);
280 ret = sunrise_calibrate(sunrise, data: &calib_data[SUNRISE_CALIBRATION_BACKGROUND]);
281 mutex_unlock(lock: &sunrise->lock);
282 if (ret)
283 return ret;
284
285 return len;
286}
287
288 /* Enumerate and retrieve the chip error status. */
289enum {
290 SUNRISE_ERROR_FATAL,
291 SUNRISE_ERROR_I2C,
292 SUNRISE_ERROR_ALGORITHM,
293 SUNRISE_ERROR_CALIBRATION,
294 SUNRISE_ERROR_SELF_DIAGNOSTIC,
295 SUNRISE_ERROR_OUT_OF_RANGE,
296 SUNRISE_ERROR_MEMORY,
297 SUNRISE_ERROR_NO_MEASUREMENT,
298 SUNRISE_ERROR_LOW_VOLTAGE,
299 SUNRISE_ERROR_MEASUREMENT_TIMEOUT,
300};
301
302static const char * const sunrise_error_statuses[] = {
303 [SUNRISE_ERROR_FATAL] = "error_fatal",
304 [SUNRISE_ERROR_I2C] = "error_i2c",
305 [SUNRISE_ERROR_ALGORITHM] = "error_algorithm",
306 [SUNRISE_ERROR_CALIBRATION] = "error_calibration",
307 [SUNRISE_ERROR_SELF_DIAGNOSTIC] = "error_self_diagnostic",
308 [SUNRISE_ERROR_OUT_OF_RANGE] = "error_out_of_range",
309 [SUNRISE_ERROR_MEMORY] = "error_memory",
310 [SUNRISE_ERROR_NO_MEASUREMENT] = "error_no_measurement",
311 [SUNRISE_ERROR_LOW_VOLTAGE] = "error_low_voltage",
312 [SUNRISE_ERROR_MEASUREMENT_TIMEOUT] = "error_measurement_timeout",
313};
314
315static const struct iio_enum sunrise_error_statuses_enum = {
316 .items = sunrise_error_statuses,
317 .num_items = ARRAY_SIZE(sunrise_error_statuses),
318};
319
320static ssize_t sunrise_error_status_read(struct iio_dev *iiodev,
321 uintptr_t private,
322 const struct iio_chan_spec *chan,
323 char *buf)
324{
325 struct sunrise_dev *sunrise = iio_priv(indio_dev: iiodev);
326 unsigned long errors;
327 ssize_t len = 0;
328 u16 value;
329 int ret;
330 u8 i;
331
332 mutex_lock(&sunrise->lock);
333 ret = sunrise_read_word(sunrise, SUNRISE_ERROR_STATUS_REG, val: &value);
334 if (ret) {
335 mutex_unlock(lock: &sunrise->lock);
336 return ret;
337 }
338
339 errors = value;
340 for_each_set_bit(i, &errors, ARRAY_SIZE(sunrise_error_statuses))
341 len += sysfs_emit_at(buf, at: len, fmt: "%s ", sunrise_error_statuses[i]);
342
343 if (len)
344 buf[len - 1] = '\n';
345
346 mutex_unlock(lock: &sunrise->lock);
347
348 return len;
349}
350
351static const struct iio_chan_spec_ext_info sunrise_concentration_ext_info[] = {
352 /* Calibration triggers. */
353 {
354 .name = "calibration_factory",
355 .write = sunrise_cal_factory_write,
356 .shared = IIO_SEPARATE,
357 },
358 {
359 .name = "calibration_background",
360 .write = sunrise_cal_background_write,
361 .shared = IIO_SEPARATE,
362 },
363
364 /* Error statuses. */
365 {
366 .name = "error_status",
367 .read = sunrise_error_status_read,
368 .shared = IIO_SHARED_BY_ALL,
369 },
370 {
371 .name = "error_status_available",
372 .shared = IIO_SHARED_BY_ALL,
373 .read = iio_enum_available_read,
374 .private = (uintptr_t)&sunrise_error_statuses_enum,
375 },
376 {}
377};
378
379static const struct iio_chan_spec sunrise_channels[] = {
380 {
381 .type = IIO_CONCENTRATION,
382 .modified = 1,
383 .channel2 = IIO_MOD_CO2,
384 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
385 BIT(IIO_CHAN_INFO_SCALE),
386 .ext_info = sunrise_concentration_ext_info,
387 },
388 {
389 .type = IIO_TEMP,
390 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
391 BIT(IIO_CHAN_INFO_SCALE),
392 },
393};
394
395static int sunrise_read_raw(struct iio_dev *iio_dev,
396 const struct iio_chan_spec *chan,
397 int *val, int *val2, long mask)
398{
399 struct sunrise_dev *sunrise = iio_priv(indio_dev: iio_dev);
400 u16 value;
401 int ret;
402
403 switch (mask) {
404 case IIO_CHAN_INFO_RAW:
405 switch (chan->type) {
406 case IIO_CONCENTRATION:
407 mutex_lock(&sunrise->lock);
408 ret = sunrise_read_word(sunrise, SUNRISE_CO2_FILTERED_COMP_REG,
409 val: &value);
410 mutex_unlock(lock: &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 val: &value);
422 mutex_unlock(lock: &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(adap: 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(parent: &client->dev, sizeof_priv: sizeof(*sunrise));
487 if (!iio_dev)
488 return -ENOMEM;
489
490 sunrise = iio_priv(indio_dev: iio_dev);
491 sunrise->client = client;
492 mutex_init(&sunrise->lock);
493
494 i2c_set_clientdata(client, data: sunrise);
495
496 sunrise->regmap = devm_regmap_init(&client->dev, &sunrise_regmap_bus,
497 client, &sunrise_regmap_config);
498 if (IS_ERR(ptr: sunrise->regmap)) {
499 dev_err(&client->dev, "Failed to initialize regmap\n");
500 return PTR_ERR(ptr: 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(adap: 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

source code of linux/drivers/iio/chemical/sunrise_co2.c