scd4x.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Sensirion SCD4X carbon dioxide sensor i2c driver
  4. *
  5. * Copyright (C) 2021 Protonic Holland
  6. * Author: Roan van Dijk <[email protected]>
  7. *
  8. * I2C slave address: 0x62
  9. *
  10. * Datasheets:
  11. * https://www.sensirion.com/file/datasheet_scd4x
  12. */
  13. #include <asm/unaligned.h>
  14. #include <linux/crc8.h>
  15. #include <linux/delay.h>
  16. #include <linux/device.h>
  17. #include <linux/i2c.h>
  18. #include <linux/iio/buffer.h>
  19. #include <linux/iio/iio.h>
  20. #include <linux/iio/sysfs.h>
  21. #include <linux/iio/trigger.h>
  22. #include <linux/iio/trigger_consumer.h>
  23. #include <linux/iio/triggered_buffer.h>
  24. #include <linux/iio/types.h>
  25. #include <linux/kernel.h>
  26. #include <linux/mutex.h>
  27. #include <linux/string.h>
  28. #include <linux/sysfs.h>
  29. #include <linux/types.h>
  30. #define SCD4X_CRC8_POLYNOMIAL 0x31
  31. #define SCD4X_TIMEOUT_ERR 1000
  32. #define SCD4X_READ_BUF_SIZE 9
  33. #define SCD4X_COMMAND_BUF_SIZE 2
  34. #define SCD4X_WRITE_BUF_SIZE 5
  35. #define SCD4X_FRC_MIN_PPM 0
  36. #define SCD4X_FRC_MAX_PPM 2000
  37. #define SCD4X_READY_MASK 0x01
  38. /*Commands SCD4X*/
  39. enum scd4x_cmd {
  40. CMD_START_MEAS = 0x21b1,
  41. CMD_READ_MEAS = 0xec05,
  42. CMD_STOP_MEAS = 0x3f86,
  43. CMD_SET_TEMP_OFFSET = 0x241d,
  44. CMD_GET_TEMP_OFFSET = 0x2318,
  45. CMD_FRC = 0x362f,
  46. CMD_SET_ASC = 0x2416,
  47. CMD_GET_ASC = 0x2313,
  48. CMD_GET_DATA_READY = 0xe4b8,
  49. };
  50. enum scd4x_channel_idx {
  51. SCD4X_CO2,
  52. SCD4X_TEMP,
  53. SCD4X_HR,
  54. };
  55. struct scd4x_state {
  56. struct i2c_client *client;
  57. /* maintain access to device, to prevent concurrent reads/writes */
  58. struct mutex lock;
  59. struct regulator *vdd;
  60. };
  61. DECLARE_CRC8_TABLE(scd4x_crc8_table);
  62. static int scd4x_i2c_xfer(struct scd4x_state *state, char *txbuf, int txsize,
  63. char *rxbuf, int rxsize)
  64. {
  65. struct i2c_client *client = state->client;
  66. int ret;
  67. ret = i2c_master_send(client, txbuf, txsize);
  68. if (ret < 0)
  69. return ret;
  70. if (ret != txsize)
  71. return -EIO;
  72. if (rxsize == 0)
  73. return 0;
  74. ret = i2c_master_recv(client, rxbuf, rxsize);
  75. if (ret < 0)
  76. return ret;
  77. if (ret != rxsize)
  78. return -EIO;
  79. return 0;
  80. }
  81. static int scd4x_send_command(struct scd4x_state *state, enum scd4x_cmd cmd)
  82. {
  83. char buf[SCD4X_COMMAND_BUF_SIZE];
  84. int ret;
  85. /*
  86. * Measurement needs to be stopped before sending commands.
  87. * Except stop and start command.
  88. */
  89. if ((cmd != CMD_STOP_MEAS) && (cmd != CMD_START_MEAS)) {
  90. ret = scd4x_send_command(state, CMD_STOP_MEAS);
  91. if (ret)
  92. return ret;
  93. /* execution time for stopping measurement */
  94. msleep_interruptible(500);
  95. }
  96. put_unaligned_be16(cmd, buf);
  97. ret = scd4x_i2c_xfer(state, buf, 2, buf, 0);
  98. if (ret)
  99. return ret;
  100. if ((cmd != CMD_STOP_MEAS) && (cmd != CMD_START_MEAS)) {
  101. ret = scd4x_send_command(state, CMD_START_MEAS);
  102. if (ret)
  103. return ret;
  104. }
  105. return 0;
  106. }
  107. static int scd4x_read(struct scd4x_state *state, enum scd4x_cmd cmd,
  108. void *response, int response_sz)
  109. {
  110. struct i2c_client *client = state->client;
  111. char buf[SCD4X_READ_BUF_SIZE];
  112. char *rsp = response;
  113. int i, ret;
  114. char crc;
  115. /*
  116. * Measurement needs to be stopped before sending commands.
  117. * Except for reading measurement and data ready command.
  118. */
  119. if ((cmd != CMD_GET_DATA_READY) && (cmd != CMD_READ_MEAS)) {
  120. ret = scd4x_send_command(state, CMD_STOP_MEAS);
  121. if (ret)
  122. return ret;
  123. /* execution time for stopping measurement */
  124. msleep_interruptible(500);
  125. }
  126. /* CRC byte for every 2 bytes of data */
  127. response_sz += response_sz / 2;
  128. put_unaligned_be16(cmd, buf);
  129. ret = scd4x_i2c_xfer(state, buf, 2, buf, response_sz);
  130. if (ret)
  131. return ret;
  132. for (i = 0; i < response_sz; i += 3) {
  133. crc = crc8(scd4x_crc8_table, buf + i, 2, CRC8_INIT_VALUE);
  134. if (crc != buf[i + 2]) {
  135. dev_err(&client->dev, "CRC error\n");
  136. return -EIO;
  137. }
  138. *rsp++ = buf[i];
  139. *rsp++ = buf[i + 1];
  140. }
  141. /* start measurement */
  142. if ((cmd != CMD_GET_DATA_READY) && (cmd != CMD_READ_MEAS)) {
  143. ret = scd4x_send_command(state, CMD_START_MEAS);
  144. if (ret)
  145. return ret;
  146. }
  147. return 0;
  148. }
  149. static int scd4x_write(struct scd4x_state *state, enum scd4x_cmd cmd, uint16_t arg)
  150. {
  151. char buf[SCD4X_WRITE_BUF_SIZE];
  152. int ret;
  153. char crc;
  154. put_unaligned_be16(cmd, buf);
  155. put_unaligned_be16(arg, buf + 2);
  156. crc = crc8(scd4x_crc8_table, buf + 2, 2, CRC8_INIT_VALUE);
  157. buf[4] = crc;
  158. /* measurement needs to be stopped before sending commands */
  159. ret = scd4x_send_command(state, CMD_STOP_MEAS);
  160. if (ret)
  161. return ret;
  162. /* execution time */
  163. msleep_interruptible(500);
  164. ret = scd4x_i2c_xfer(state, buf, SCD4X_WRITE_BUF_SIZE, buf, 0);
  165. if (ret)
  166. return ret;
  167. /* start measurement, except for forced calibration command */
  168. if (cmd != CMD_FRC) {
  169. ret = scd4x_send_command(state, CMD_START_MEAS);
  170. if (ret)
  171. return ret;
  172. }
  173. return 0;
  174. }
  175. static int scd4x_write_and_fetch(struct scd4x_state *state, enum scd4x_cmd cmd,
  176. uint16_t arg, void *response, int response_sz)
  177. {
  178. struct i2c_client *client = state->client;
  179. char buf[SCD4X_READ_BUF_SIZE];
  180. char *rsp = response;
  181. int i, ret;
  182. char crc;
  183. ret = scd4x_write(state, CMD_FRC, arg);
  184. if (ret)
  185. goto err;
  186. /* execution time */
  187. msleep_interruptible(400);
  188. /* CRC byte for every 2 bytes of data */
  189. response_sz += response_sz / 2;
  190. ret = i2c_master_recv(client, buf, response_sz);
  191. if (ret < 0)
  192. goto err;
  193. if (ret != response_sz) {
  194. ret = -EIO;
  195. goto err;
  196. }
  197. for (i = 0; i < response_sz; i += 3) {
  198. crc = crc8(scd4x_crc8_table, buf + i, 2, CRC8_INIT_VALUE);
  199. if (crc != buf[i + 2]) {
  200. dev_err(&client->dev, "CRC error\n");
  201. ret = -EIO;
  202. goto err;
  203. }
  204. *rsp++ = buf[i];
  205. *rsp++ = buf[i + 1];
  206. }
  207. return scd4x_send_command(state, CMD_START_MEAS);
  208. err:
  209. /*
  210. * on error try to start the measurement,
  211. * puts sensor back into continuous measurement
  212. */
  213. scd4x_send_command(state, CMD_START_MEAS);
  214. return ret;
  215. }
  216. static int scd4x_read_meas(struct scd4x_state *state, uint16_t *meas)
  217. {
  218. int i, ret;
  219. __be16 buf[3];
  220. ret = scd4x_read(state, CMD_READ_MEAS, buf, sizeof(buf));
  221. if (ret)
  222. return ret;
  223. for (i = 0; i < ARRAY_SIZE(buf); i++)
  224. meas[i] = be16_to_cpu(buf[i]);
  225. return 0;
  226. }
  227. static int scd4x_wait_meas_poll(struct scd4x_state *state)
  228. {
  229. struct i2c_client *client = state->client;
  230. int tries = 6;
  231. int ret;
  232. do {
  233. __be16 bval;
  234. uint16_t val;
  235. ret = scd4x_read(state, CMD_GET_DATA_READY, &bval, sizeof(bval));
  236. if (ret)
  237. return -EIO;
  238. val = be16_to_cpu(bval);
  239. /* new measurement available */
  240. if (val & 0x7FF)
  241. return 0;
  242. msleep_interruptible(1000);
  243. } while (--tries);
  244. /* try to start sensor on timeout */
  245. ret = scd4x_send_command(state, CMD_START_MEAS);
  246. if (ret)
  247. dev_err(&client->dev, "failed to start measurement: %d\n", ret);
  248. return -ETIMEDOUT;
  249. }
  250. static int scd4x_read_poll(struct scd4x_state *state, uint16_t *buf)
  251. {
  252. int ret;
  253. ret = scd4x_wait_meas_poll(state);
  254. if (ret)
  255. return ret;
  256. return scd4x_read_meas(state, buf);
  257. }
  258. static int scd4x_read_channel(struct scd4x_state *state, int chan)
  259. {
  260. int ret;
  261. uint16_t buf[3];
  262. ret = scd4x_read_poll(state, buf);
  263. if (ret)
  264. return ret;
  265. return buf[chan];
  266. }
  267. static int scd4x_read_raw(struct iio_dev *indio_dev,
  268. struct iio_chan_spec const *chan, int *val,
  269. int *val2, long mask)
  270. {
  271. struct scd4x_state *state = iio_priv(indio_dev);
  272. int ret;
  273. __be16 tmp;
  274. switch (mask) {
  275. case IIO_CHAN_INFO_RAW:
  276. ret = iio_device_claim_direct_mode(indio_dev);
  277. if (ret)
  278. return ret;
  279. mutex_lock(&state->lock);
  280. ret = scd4x_read_channel(state, chan->address);
  281. mutex_unlock(&state->lock);
  282. iio_device_release_direct_mode(indio_dev);
  283. if (ret < 0)
  284. return ret;
  285. *val = ret;
  286. return IIO_VAL_INT;
  287. case IIO_CHAN_INFO_SCALE:
  288. if (chan->type == IIO_CONCENTRATION) {
  289. *val = 0;
  290. *val2 = 100;
  291. return IIO_VAL_INT_PLUS_MICRO;
  292. } else if (chan->type == IIO_TEMP) {
  293. *val = 175000;
  294. *val2 = 65536;
  295. return IIO_VAL_FRACTIONAL;
  296. } else if (chan->type == IIO_HUMIDITYRELATIVE) {
  297. *val = 100000;
  298. *val2 = 65536;
  299. return IIO_VAL_FRACTIONAL;
  300. }
  301. return -EINVAL;
  302. case IIO_CHAN_INFO_OFFSET:
  303. *val = -16852;
  304. *val2 = 114286;
  305. return IIO_VAL_INT_PLUS_MICRO;
  306. case IIO_CHAN_INFO_CALIBBIAS:
  307. mutex_lock(&state->lock);
  308. ret = scd4x_read(state, CMD_GET_TEMP_OFFSET, &tmp, sizeof(tmp));
  309. mutex_unlock(&state->lock);
  310. if (ret)
  311. return ret;
  312. *val = be16_to_cpu(tmp);
  313. return IIO_VAL_INT;
  314. default:
  315. return -EINVAL;
  316. }
  317. }
  318. static int scd4x_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan,
  319. int val, int val2, long mask)
  320. {
  321. struct scd4x_state *state = iio_priv(indio_dev);
  322. int ret = 0;
  323. switch (mask) {
  324. case IIO_CHAN_INFO_CALIBBIAS:
  325. mutex_lock(&state->lock);
  326. ret = scd4x_write(state, CMD_SET_TEMP_OFFSET, val);
  327. mutex_unlock(&state->lock);
  328. return ret;
  329. default:
  330. return -EINVAL;
  331. }
  332. }
  333. static ssize_t calibration_auto_enable_show(struct device *dev,
  334. struct device_attribute *attr, char *buf)
  335. {
  336. struct iio_dev *indio_dev = dev_to_iio_dev(dev);
  337. struct scd4x_state *state = iio_priv(indio_dev);
  338. int ret;
  339. __be16 bval;
  340. u16 val;
  341. mutex_lock(&state->lock);
  342. ret = scd4x_read(state, CMD_GET_ASC, &bval, sizeof(bval));
  343. mutex_unlock(&state->lock);
  344. if (ret) {
  345. dev_err(dev, "failed to read automatic calibration");
  346. return ret;
  347. }
  348. val = (be16_to_cpu(bval) & SCD4X_READY_MASK) ? 1 : 0;
  349. return sysfs_emit(buf, "%d\n", val);
  350. }
  351. static ssize_t calibration_auto_enable_store(struct device *dev,
  352. struct device_attribute *attr,
  353. const char *buf, size_t len)
  354. {
  355. struct iio_dev *indio_dev = dev_to_iio_dev(dev);
  356. struct scd4x_state *state = iio_priv(indio_dev);
  357. bool val;
  358. int ret;
  359. uint16_t value;
  360. ret = kstrtobool(buf, &val);
  361. if (ret)
  362. return ret;
  363. value = val;
  364. mutex_lock(&state->lock);
  365. ret = scd4x_write(state, CMD_SET_ASC, value);
  366. mutex_unlock(&state->lock);
  367. if (ret)
  368. dev_err(dev, "failed to set automatic calibration");
  369. return ret ?: len;
  370. }
  371. static ssize_t calibration_forced_value_store(struct device *dev,
  372. struct device_attribute *attr,
  373. const char *buf, size_t len)
  374. {
  375. struct iio_dev *indio_dev = dev_to_iio_dev(dev);
  376. struct scd4x_state *state = iio_priv(indio_dev);
  377. uint16_t val, arg;
  378. int ret;
  379. ret = kstrtou16(buf, 0, &arg);
  380. if (ret)
  381. return ret;
  382. if (arg < SCD4X_FRC_MIN_PPM || arg > SCD4X_FRC_MAX_PPM)
  383. return -EINVAL;
  384. mutex_lock(&state->lock);
  385. ret = scd4x_write_and_fetch(state, CMD_FRC, arg, &val, sizeof(val));
  386. mutex_unlock(&state->lock);
  387. if (ret)
  388. return ret;
  389. if (val == 0xff) {
  390. dev_err(dev, "forced calibration has failed");
  391. return -EINVAL;
  392. }
  393. return len;
  394. }
  395. static IIO_DEVICE_ATTR_RW(calibration_auto_enable, 0);
  396. static IIO_DEVICE_ATTR_WO(calibration_forced_value, 0);
  397. static IIO_CONST_ATTR(calibration_forced_value_available,
  398. __stringify([SCD4X_FRC_MIN_PPM 1 SCD4X_FRC_MAX_PPM]));
  399. static struct attribute *scd4x_attrs[] = {
  400. &iio_dev_attr_calibration_auto_enable.dev_attr.attr,
  401. &iio_dev_attr_calibration_forced_value.dev_attr.attr,
  402. &iio_const_attr_calibration_forced_value_available.dev_attr.attr,
  403. NULL
  404. };
  405. static const struct attribute_group scd4x_attr_group = {
  406. .attrs = scd4x_attrs,
  407. };
  408. static const struct iio_info scd4x_info = {
  409. .attrs = &scd4x_attr_group,
  410. .read_raw = scd4x_read_raw,
  411. .write_raw = scd4x_write_raw,
  412. };
  413. static const struct iio_chan_spec scd4x_channels[] = {
  414. {
  415. .type = IIO_CONCENTRATION,
  416. .channel2 = IIO_MOD_CO2,
  417. .modified = 1,
  418. .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
  419. BIT(IIO_CHAN_INFO_SCALE),
  420. .address = SCD4X_CO2,
  421. .scan_index = SCD4X_CO2,
  422. .scan_type = {
  423. .sign = 'u',
  424. .realbits = 16,
  425. .storagebits = 16,
  426. .endianness = IIO_BE,
  427. },
  428. },
  429. {
  430. .type = IIO_TEMP,
  431. .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
  432. BIT(IIO_CHAN_INFO_SCALE) |
  433. BIT(IIO_CHAN_INFO_OFFSET) |
  434. BIT(IIO_CHAN_INFO_CALIBBIAS),
  435. .address = SCD4X_TEMP,
  436. .scan_index = SCD4X_TEMP,
  437. .scan_type = {
  438. .sign = 'u',
  439. .realbits = 16,
  440. .storagebits = 16,
  441. .endianness = IIO_BE,
  442. },
  443. },
  444. {
  445. .type = IIO_HUMIDITYRELATIVE,
  446. .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
  447. BIT(IIO_CHAN_INFO_SCALE),
  448. .address = SCD4X_HR,
  449. .scan_index = SCD4X_HR,
  450. .scan_type = {
  451. .sign = 'u',
  452. .realbits = 16,
  453. .storagebits = 16,
  454. .endianness = IIO_BE,
  455. },
  456. },
  457. };
  458. static int scd4x_suspend(struct device *dev)
  459. {
  460. struct iio_dev *indio_dev = dev_get_drvdata(dev);
  461. struct scd4x_state *state = iio_priv(indio_dev);
  462. int ret;
  463. ret = scd4x_send_command(state, CMD_STOP_MEAS);
  464. if (ret)
  465. return ret;
  466. return regulator_disable(state->vdd);
  467. }
  468. static int scd4x_resume(struct device *dev)
  469. {
  470. struct iio_dev *indio_dev = dev_get_drvdata(dev);
  471. struct scd4x_state *state = iio_priv(indio_dev);
  472. int ret;
  473. ret = regulator_enable(state->vdd);
  474. if (ret)
  475. return ret;
  476. return scd4x_send_command(state, CMD_START_MEAS);
  477. }
  478. static DEFINE_SIMPLE_DEV_PM_OPS(scd4x_pm_ops, scd4x_suspend, scd4x_resume);
  479. static void scd4x_stop_meas(void *state)
  480. {
  481. scd4x_send_command(state, CMD_STOP_MEAS);
  482. }
  483. static void scd4x_disable_regulator(void *data)
  484. {
  485. struct scd4x_state *state = data;
  486. regulator_disable(state->vdd);
  487. }
  488. static irqreturn_t scd4x_trigger_handler(int irq, void *p)
  489. {
  490. struct iio_poll_func *pf = p;
  491. struct iio_dev *indio_dev = pf->indio_dev;
  492. struct scd4x_state *state = iio_priv(indio_dev);
  493. struct {
  494. uint16_t data[3];
  495. int64_t ts __aligned(8);
  496. } scan;
  497. int ret;
  498. memset(&scan, 0, sizeof(scan));
  499. mutex_lock(&state->lock);
  500. ret = scd4x_read_poll(state, scan.data);
  501. mutex_unlock(&state->lock);
  502. if (ret)
  503. goto out;
  504. iio_push_to_buffers_with_timestamp(indio_dev, &scan, iio_get_time_ns(indio_dev));
  505. out:
  506. iio_trigger_notify_done(indio_dev->trig);
  507. return IRQ_HANDLED;
  508. }
  509. static int scd4x_probe(struct i2c_client *client, const struct i2c_device_id *id)
  510. {
  511. static const unsigned long scd4x_scan_masks[] = { 0x07, 0x00 };
  512. struct device *dev = &client->dev;
  513. struct iio_dev *indio_dev;
  514. struct scd4x_state *state;
  515. int ret;
  516. indio_dev = devm_iio_device_alloc(dev, sizeof(*state));
  517. if (!indio_dev)
  518. return -ENOMEM;
  519. state = iio_priv(indio_dev);
  520. mutex_init(&state->lock);
  521. state->client = client;
  522. crc8_populate_msb(scd4x_crc8_table, SCD4X_CRC8_POLYNOMIAL);
  523. indio_dev->info = &scd4x_info;
  524. indio_dev->name = client->name;
  525. indio_dev->channels = scd4x_channels;
  526. indio_dev->num_channels = ARRAY_SIZE(scd4x_channels);
  527. indio_dev->modes = INDIO_DIRECT_MODE;
  528. indio_dev->available_scan_masks = scd4x_scan_masks;
  529. state->vdd = devm_regulator_get(dev, "vdd");
  530. if (IS_ERR(state->vdd))
  531. return dev_err_probe(dev, PTR_ERR(state->vdd), "failed to get regulator\n");
  532. ret = regulator_enable(state->vdd);
  533. if (ret)
  534. return ret;
  535. ret = devm_add_action_or_reset(dev, scd4x_disable_regulator, state);
  536. if (ret)
  537. return ret;
  538. ret = scd4x_send_command(state, CMD_STOP_MEAS);
  539. if (ret) {
  540. dev_err(dev, "failed to stop measurement: %d\n", ret);
  541. return ret;
  542. }
  543. /* execution time */
  544. msleep_interruptible(500);
  545. ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL, scd4x_trigger_handler, NULL);
  546. if (ret)
  547. return ret;
  548. ret = scd4x_send_command(state, CMD_START_MEAS);
  549. if (ret) {
  550. dev_err(dev, "failed to start measurement: %d\n", ret);
  551. return ret;
  552. }
  553. ret = devm_add_action_or_reset(dev, scd4x_stop_meas, state);
  554. if (ret)
  555. return ret;
  556. return devm_iio_device_register(dev, indio_dev);
  557. }
  558. static const struct of_device_id scd4x_dt_ids[] = {
  559. { .compatible = "sensirion,scd40" },
  560. { .compatible = "sensirion,scd41" },
  561. { }
  562. };
  563. MODULE_DEVICE_TABLE(of, scd4x_dt_ids);
  564. static struct i2c_driver scd4x_i2c_driver = {
  565. .driver = {
  566. .name = KBUILD_MODNAME,
  567. .of_match_table = scd4x_dt_ids,
  568. .pm = pm_sleep_ptr(&scd4x_pm_ops),
  569. },
  570. .probe = scd4x_probe,
  571. };
  572. module_i2c_driver(scd4x_i2c_driver);
  573. MODULE_AUTHOR("Roan van Dijk <[email protected]>");
  574. MODULE_DESCRIPTION("Sensirion SCD4X carbon dioxide sensor core driver");
  575. MODULE_LICENSE("GPL v2");