File Index
Files and directories
Sign in
FILE

ens160_core.c

File preview with syntax highlighting.

linux-6.19.14/drivers/iio/chemical/ens160_core.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * ScioSense ENS160 multi-gas sensor driver
  4 *
  5 * Copyright (c) 2024 Gustavo Silva <gustavograzs@gmail.com>
  6 *
  7 * Datasheet:
  8 *  https://www.sciosense.com/wp-content/uploads/2023/12/ENS160-Datasheet.pdf
  9 */
 10
 11#include <linux/bitfield.h>
 12#include <linux/iio/iio.h>
 13#include <linux/iio/trigger.h>
 14#include <linux/iio/trigger_consumer.h>
 15#include <linux/iio/triggered_buffer.h>
 16#include <linux/module.h>
 17#include <linux/regmap.h>
 18
 19#include "ens160.h"
 20
 21#define ENS160_PART_ID 0x160
 22
 23#define ENS160_BOOTING_TIME_MS 10U
 24
 25#define ENS160_REG_PART_ID		0x00
 26
 27#define ENS160_REG_OPMODE		0x10
 28
 29#define ENS160_REG_CONFIG		0x11
 30#define ENS160_REG_CONFIG_INTEN		BIT(0)
 31#define ENS160_REG_CONFIG_INTDAT	BIT(1)
 32#define ENS160_REG_CONFIG_INT_CFG	BIT(5)
 33
 34#define ENS160_REG_MODE_DEEP_SLEEP	0x00
 35#define ENS160_REG_MODE_IDLE		0x01
 36#define ENS160_REG_MODE_STANDARD	0x02
 37#define ENS160_REG_MODE_RESET		0xF0
 38
 39#define ENS160_REG_COMMAND		0x12
 40#define ENS160_REG_COMMAND_GET_APPVER	0x0E
 41#define ENS160_REG_COMMAND_CLRGPR	0xCC
 42
 43#define ENS160_REG_TEMP_IN		0x13
 44#define ENS160_REG_RH_IN		0x15
 45#define ENS160_REG_DEVICE_STATUS	0x20
 46#define ENS160_REG_DATA_AQI		0x21
 47#define ENS160_REG_DATA_TVOC		0x22
 48#define ENS160_REG_DATA_ECO2		0x24
 49#define ENS160_REG_DATA_T		0x30
 50#define ENS160_REG_DATA_RH		0x32
 51#define ENS160_REG_GPR_READ4		0x4C
 52
 53#define ENS160_STATUS_VALIDITY_FLAG	GENMASK(3, 2)
 54
 55#define ENS160_STATUS_NORMAL		0x00
 56
 57struct ens160_data {
 58	struct regmap *regmap;
 59	/* Protect reads from the sensor */
 60	struct mutex mutex;
 61	struct {
 62		__le16 chans[2];
 63		aligned_s64 timestamp;
 64	} scan __aligned(IIO_DMA_MINALIGN);
 65	u8 fw_version[3];
 66	__le16 buf;
 67};
 68
 69static const struct iio_chan_spec ens160_channels[] = {
 70	{
 71		.type = IIO_CONCENTRATION,
 72		.channel2 = IIO_MOD_VOC,
 73		.modified = 1,
 74		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
 75				      BIT(IIO_CHAN_INFO_SCALE),
 76		.address = ENS160_REG_DATA_TVOC,
 77		.scan_index = 0,
 78		.scan_type = {
 79			.sign = 'u',
 80			.realbits = 16,
 81			.storagebits = 16,
 82			.endianness = IIO_LE,
 83		},
 84	},
 85	{
 86		.type = IIO_CONCENTRATION,
 87		.channel2 = IIO_MOD_CO2,
 88		.modified = 1,
 89		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
 90				      BIT(IIO_CHAN_INFO_SCALE),
 91		.address = ENS160_REG_DATA_ECO2,
 92		.scan_index = 1,
 93		.scan_type = {
 94			.sign = 'u',
 95			.realbits = 16,
 96			.storagebits = 16,
 97			.endianness = IIO_LE,
 98		},
 99	},
100	IIO_CHAN_SOFT_TIMESTAMP(2),
101};
102
103static int __ens160_read_raw(struct iio_dev *indio_dev,
104			     struct iio_chan_spec const *chan,
105			     int *val)
106{
107	struct ens160_data *data = iio_priv(indio_dev);
108	int ret;
109
110	guard(mutex)(&data->mutex);
111	ret = regmap_bulk_read(data->regmap, chan->address,
112			       &data->buf, sizeof(data->buf));
113	if (ret)
114		return ret;
115	*val = le16_to_cpu(data->buf);
116	return IIO_VAL_INT;
117}
118
119static int ens160_read_raw(struct iio_dev *indio_dev,
120			   struct iio_chan_spec const *chan,
121			   int *val, int *val2, long mask)
122{
123	int ret;
124
125	switch (mask) {
126	case IIO_CHAN_INFO_RAW:
127		if (!iio_device_claim_direct(indio_dev))
128			return -EBUSY;
129		ret = __ens160_read_raw(indio_dev, chan, val);
130		iio_device_release_direct(indio_dev);
131		return ret;
132	case IIO_CHAN_INFO_SCALE:
133		switch (chan->channel2) {
134		case IIO_MOD_CO2:
135			/* The sensor reads CO2 data as ppm */
136			*val = 0;
137			*val2 = 100;
138			return IIO_VAL_INT_PLUS_MICRO;
139		case IIO_MOD_VOC:
140			/* The sensor reads VOC data as ppb */
141			*val = 0;
142			*val2 = 100;
143			return IIO_VAL_INT_PLUS_NANO;
144		default:
145			return -EINVAL;
146		}
147	default:
148		return -EINVAL;
149	}
150}
151
152static int ens160_set_mode(struct ens160_data *data, u8 mode)
153{
154	int ret;
155
156	ret = regmap_write(data->regmap, ENS160_REG_OPMODE, mode);
157	if (ret)
158		return ret;
159
160	msleep(ENS160_BOOTING_TIME_MS);
161
162	return 0;
163}
164
165static void ens160_set_idle(void *data)
166{
167	ens160_set_mode(data, ENS160_REG_MODE_IDLE);
168}
169
170static int ens160_chip_init(struct ens160_data *data)
171{
172	struct device *dev = regmap_get_device(data->regmap);
173	unsigned int status;
174	int ret;
175
176	ret = ens160_set_mode(data, ENS160_REG_MODE_RESET);
177	if (ret)
178		return ret;
179
180	ret = regmap_bulk_read(data->regmap, ENS160_REG_PART_ID, &data->buf,
181			       sizeof(data->buf));
182	if (ret)
183		return ret;
184
185	if (le16_to_cpu(data->buf) != ENS160_PART_ID)
186		return -ENODEV;
187
188	ret = ens160_set_mode(data, ENS160_REG_MODE_IDLE);
189	if (ret)
190		return ret;
191
192	ret = regmap_write(data->regmap, ENS160_REG_COMMAND,
193			   ENS160_REG_COMMAND_CLRGPR);
194	if (ret)
195		return ret;
196
197	ret = regmap_write(data->regmap, ENS160_REG_COMMAND,
198			   ENS160_REG_COMMAND_GET_APPVER);
199	if (ret)
200		return ret;
201
202	ret = regmap_bulk_read(data->regmap, ENS160_REG_GPR_READ4,
203			       data->fw_version, sizeof(data->fw_version));
204	if (ret)
205		return ret;
206
207	dev_info(dev, "firmware version: %u.%u.%u\n", data->fw_version[2],
208		 data->fw_version[1], data->fw_version[0]);
209
210	ret = ens160_set_mode(data, ENS160_REG_MODE_STANDARD);
211	if (ret)
212		return ret;
213
214	ret = devm_add_action_or_reset(dev, ens160_set_idle, data);
215	if (ret)
216		return ret;
217
218	ret = regmap_read(data->regmap, ENS160_REG_DEVICE_STATUS, &status);
219	if (ret)
220		return ret;
221
222	if (FIELD_GET(ENS160_STATUS_VALIDITY_FLAG, status)
223	    != ENS160_STATUS_NORMAL)
224		return -EINVAL;
225
226	return 0;
227}
228
229static const struct iio_info ens160_info = {
230	.read_raw = ens160_read_raw,
231};
232
233static int ens160_suspend(struct device *dev)
234{
235	struct iio_dev *indio_dev = dev_get_drvdata(dev);
236	struct ens160_data *data = iio_priv(indio_dev);
237
238	return ens160_set_mode(data, ENS160_REG_MODE_DEEP_SLEEP);
239}
240
241static int ens160_resume(struct device *dev)
242{
243	struct iio_dev *indio_dev = dev_get_drvdata(dev);
244	struct ens160_data *data = iio_priv(indio_dev);
245	int ret;
246
247	ret = ens160_set_mode(data, ENS160_REG_MODE_IDLE);
248	if (ret)
249		return ret;
250
251	return ens160_set_mode(data, ENS160_REG_MODE_STANDARD);
252}
253EXPORT_NS_SIMPLE_DEV_PM_OPS(ens160_pm_ops, ens160_suspend, ens160_resume,
254			    IIO_ENS160);
255
256static irqreturn_t ens160_trigger_handler(int irq, void *p)
257{
258	struct iio_poll_func *pf = p;
259	struct iio_dev *indio_dev = pf->indio_dev;
260	struct ens160_data *data = iio_priv(indio_dev);
261	int ret;
262
263	guard(mutex)(&data->mutex);
264
265	ret = regmap_bulk_read(data->regmap, ENS160_REG_DATA_TVOC,
266			       data->scan.chans, sizeof(data->scan.chans));
267	if (ret)
268		goto err;
269
270	iio_push_to_buffers_with_ts(indio_dev, &data->scan, sizeof(data->scan),
271				    pf->timestamp);
272err:
273	iio_trigger_notify_done(indio_dev->trig);
274
275	return IRQ_HANDLED;
276}
277
278static int ens160_set_trigger_state(struct iio_trigger *trig, bool state)
279{
280	struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
281	struct ens160_data *data = iio_priv(indio_dev);
282	unsigned int int_bits = ENS160_REG_CONFIG_INTEN |
283				ENS160_REG_CONFIG_INTDAT |
284				ENS160_REG_CONFIG_INT_CFG;
285
286	if (state)
287		return regmap_set_bits(data->regmap, ENS160_REG_CONFIG,
288				       int_bits);
289	else
290		return regmap_clear_bits(data->regmap, ENS160_REG_CONFIG,
291					 int_bits);
292}
293
294static const struct iio_trigger_ops ens160_trigger_ops = {
295	.set_trigger_state = ens160_set_trigger_state,
296	.validate_device = iio_trigger_validate_own_device,
297};
298
299static int ens160_setup_trigger(struct iio_dev *indio_dev, int irq)
300{
301	struct device *dev = indio_dev->dev.parent;
302	struct iio_trigger *trig;
303	int ret;
304
305	trig = devm_iio_trigger_alloc(dev, "%s-dev%d", indio_dev->name,
306				      iio_device_id(indio_dev));
307	if (!trig)
308		return -ENOMEM;
309
310	trig->ops = &ens160_trigger_ops;
311	iio_trigger_set_drvdata(trig, indio_dev);
312
313	ret = devm_iio_trigger_register(dev, trig);
314	if (ret)
315		return ret;
316
317	indio_dev->trig = iio_trigger_get(trig);
318
319	ret = devm_request_threaded_irq(dev, irq,
320					iio_trigger_generic_data_rdy_poll,
321					NULL,
322					IRQF_ONESHOT,
323					indio_dev->name,
324					indio_dev->trig);
325	if (ret)
326		return dev_err_probe(dev, ret, "failed to request irq\n");
327
328	return 0;
329}
330
331int devm_ens160_core_probe(struct device *dev, struct regmap *regmap, int irq,
332			   const char *name)
333{
334	struct ens160_data *data;
335	struct iio_dev *indio_dev;
336	int ret;
337
338	indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
339	if (!indio_dev)
340		return -ENOMEM;
341
342	data = iio_priv(indio_dev);
343	data->regmap = regmap;
344
345	indio_dev->name = name;
346	indio_dev->info = &ens160_info;
347	indio_dev->modes = INDIO_DIRECT_MODE;
348	indio_dev->channels = ens160_channels;
349	indio_dev->num_channels = ARRAY_SIZE(ens160_channels);
350
351	if (irq > 0) {
352		ret = ens160_setup_trigger(indio_dev, irq);
353		if (ret)
354			return dev_err_probe(dev, ret,
355					     "failed to setup trigger\n");
356	}
357
358	ret = ens160_chip_init(data);
359	if (ret)
360		return dev_err_probe(dev, ret, "chip initialization failed\n");
361
362	mutex_init(&data->mutex);
363
364	ret = devm_iio_triggered_buffer_setup(dev, indio_dev,
365					      iio_pollfunc_store_time,
366					      ens160_trigger_handler, NULL);
367	if (ret)
368		return ret;
369
370	return devm_iio_device_register(dev, indio_dev);
371}
372EXPORT_SYMBOL_NS(devm_ens160_core_probe, "IIO_ENS160");
373
374MODULE_AUTHOR("Gustavo Silva <gustavograzs@gmail.com>");
375MODULE_DESCRIPTION("ScioSense ENS160 driver");
376MODULE_LICENSE("GPL v2");
~/ Read-only file preview.