File Index
Files and directories
Sign in
FILE

smi240.c

File preview with syntax highlighting.

linux-6.19.14/drivers/iio/imu/smi240.c C
  1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
  2/*
  3 * Copyright (c) 2024 Robert Bosch GmbH.
  4 */
  5#include <linux/bitfield.h>
  6#include <linux/bits.h>
  7#include <linux/delay.h>
  8#include <linux/device.h>
  9#include <linux/module.h>
 10#include <linux/regmap.h>
 11#include <linux/spi/spi.h>
 12#include <linux/unaligned.h>
 13#include <linux/units.h>
 14
 15#include <linux/iio/buffer.h>
 16#include <linux/iio/iio.h>
 17#include <linux/iio/trigger.h>
 18#include <linux/iio/trigger_consumer.h>
 19#include <linux/iio/triggered_buffer.h>
 20
 21#define SMI240_CHIP_ID 0x0024
 22
 23#define SMI240_SOFT_CONFIG_EOC_MASK BIT(0)
 24#define SMI240_SOFT_CONFIG_GYR_BW_MASK BIT(1)
 25#define SMI240_SOFT_CONFIG_ACC_BW_MASK BIT(2)
 26#define SMI240_SOFT_CONFIG_BITE_AUTO_MASK BIT(3)
 27#define SMI240_SOFT_CONFIG_BITE_REP_MASK GENMASK(6, 4)
 28
 29#define SMI240_CHIP_ID_REG 0x00
 30#define SMI240_SOFT_CONFIG_REG 0x0A
 31#define SMI240_TEMP_CUR_REG 0x10
 32#define SMI240_ACCEL_X_CUR_REG 0x11
 33#define SMI240_GYRO_X_CUR_REG 0x14
 34#define SMI240_DATA_CAP_FIRST_REG 0x17
 35#define SMI240_CMD_REG 0x2F
 36
 37#define SMI240_SOFT_RESET_CMD 0xB6
 38
 39#define SMI240_BITE_SEQUENCE_DELAY_US 140000
 40#define SMI240_FILTER_FLUSH_DELAY_US 60000
 41#define SMI240_DIGITAL_STARTUP_DELAY_US 120000
 42#define SMI240_MECH_STARTUP_DELAY_US 100000
 43
 44#define SMI240_BUS_ID 0x00
 45#define SMI240_CRC_INIT 0x05
 46#define SMI240_CRC_POLY 0x0B
 47#define SMI240_CRC_MASK GENMASK(2, 0)
 48
 49#define SMI240_READ_SD_BIT_MASK BIT(31)
 50#define SMI240_READ_DATA_MASK GENMASK(19, 4)
 51#define SMI240_READ_CS_BIT_MASK BIT(3)
 52
 53#define SMI240_WRITE_BUS_ID_MASK GENMASK(31, 30)
 54#define SMI240_WRITE_ADDR_MASK GENMASK(29, 22)
 55#define SMI240_WRITE_BIT_MASK BIT(21)
 56#define SMI240_WRITE_CAP_BIT_MASK BIT(20)
 57#define SMI240_WRITE_DATA_MASK GENMASK(18, 3)
 58
 59/* T°C = (temp / 256) + 25 */
 60#define SMI240_TEMP_OFFSET 6400   /* 25 * 256 */
 61#define SMI240_TEMP_SCALE 3906250 /* (1 / 256) * 1e9 */
 62
 63#define SMI240_ACCEL_SCALE 500  /* (1 / 2000) * 1e6 */
 64#define SMI240_GYRO_SCALE 10000 /* (1 /  100) * 1e6 */
 65
 66#define SMI240_LOW_BANDWIDTH_HZ 50
 67#define SMI240_HIGH_BANDWIDTH_HZ 400
 68
 69#define SMI240_BUILT_IN_SELF_TEST_COUNT 3
 70
 71#define SMI240_DATA_CHANNEL(_type, _axis, _index) {			\
 72	.type = _type,							\
 73	.modified = 1,							\
 74	.channel2 = IIO_MOD_##_axis,					\
 75	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),			\
 76	.info_mask_shared_by_type =					\
 77		BIT(IIO_CHAN_INFO_SCALE) |				\
 78		BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY),	\
 79	.info_mask_shared_by_type_available =				\
 80		BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY),	\
 81	.scan_index = _index,						\
 82	.scan_type = {							\
 83		.sign = 's',						\
 84		.realbits = 16,						\
 85		.storagebits = 16,					\
 86		.endianness = IIO_CPU,					\
 87	},								\
 88}
 89
 90#define SMI240_TEMP_CHANNEL(_index) {			\
 91	.type = IIO_TEMP,				\
 92	.modified = 1,					\
 93	.channel2 = IIO_MOD_TEMP_OBJECT,		\
 94	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |	\
 95		BIT(IIO_CHAN_INFO_OFFSET) |		\
 96		BIT(IIO_CHAN_INFO_SCALE),		\
 97	.scan_index = _index,				\
 98	.scan_type = {					\
 99		.sign = 's',				\
100		.realbits = 16,				\
101		.storagebits = 16,			\
102		.endianness = IIO_CPU,			\
103	},						\
104}
105
106enum capture_mode { SMI240_CAPTURE_OFF = 0, SMI240_CAPTURE_ON = 1 };
107
108struct smi240_data {
109	struct regmap *regmap;
110	u16 accel_filter_freq;
111	u16 anglvel_filter_freq;
112	u8 built_in_self_test_count;
113	enum capture_mode capture;
114	/*
115	 * Ensure natural alignment for timestamp if present.
116	 * Channel size: 2 bytes.
117	 * Max length needed: 2 * 3 channels + temp channel + 2 bytes padding + 8 byte ts.
118	 * If fewer channels are enabled, less space may be needed, as
119	 * long as the timestamp is still aligned to 8 bytes.
120	 */
121	s16 buf[12] __aligned(8);
122
123	__be32 spi_buf __aligned(IIO_DMA_MINALIGN);
124};
125
126enum {
127	SMI240_TEMP_OBJECT,
128	SMI240_SCAN_ACCEL_X,
129	SMI240_SCAN_ACCEL_Y,
130	SMI240_SCAN_ACCEL_Z,
131	SMI240_SCAN_GYRO_X,
132	SMI240_SCAN_GYRO_Y,
133	SMI240_SCAN_GYRO_Z,
134	SMI240_SCAN_TIMESTAMP,
135};
136
137static const struct iio_chan_spec smi240_channels[] = {
138	SMI240_TEMP_CHANNEL(SMI240_TEMP_OBJECT),
139	SMI240_DATA_CHANNEL(IIO_ACCEL, X, SMI240_SCAN_ACCEL_X),
140	SMI240_DATA_CHANNEL(IIO_ACCEL, Y, SMI240_SCAN_ACCEL_Y),
141	SMI240_DATA_CHANNEL(IIO_ACCEL, Z, SMI240_SCAN_ACCEL_Z),
142	SMI240_DATA_CHANNEL(IIO_ANGL_VEL, X, SMI240_SCAN_GYRO_X),
143	SMI240_DATA_CHANNEL(IIO_ANGL_VEL, Y, SMI240_SCAN_GYRO_Y),
144	SMI240_DATA_CHANNEL(IIO_ANGL_VEL, Z, SMI240_SCAN_GYRO_Z),
145	IIO_CHAN_SOFT_TIMESTAMP(SMI240_SCAN_TIMESTAMP),
146};
147
148static const int smi240_low_pass_freqs[] = { SMI240_LOW_BANDWIDTH_HZ,
149					     SMI240_HIGH_BANDWIDTH_HZ };
150
151static u8 smi240_crc3(u32 data, u8 init, u8 poly)
152{
153	u8 crc = init;
154	u8 do_xor;
155	s8 i = 31;
156
157	do {
158		do_xor = crc & 0x04;
159		crc <<= 1;
160		crc |= 0x01 & (data >> i);
161		if (do_xor)
162			crc ^= poly;
163
164		crc &= SMI240_CRC_MASK;
165	} while (--i >= 0);
166
167	return crc;
168}
169
170static bool smi240_sensor_data_is_valid(u32 data)
171{
172	if (smi240_crc3(data, SMI240_CRC_INIT, SMI240_CRC_POLY) != 0)
173		return false;
174
175	if (FIELD_GET(SMI240_READ_SD_BIT_MASK, data) &
176	    FIELD_GET(SMI240_READ_CS_BIT_MASK, data))
177		return false;
178
179	return true;
180}
181
182static int smi240_regmap_spi_read(void *context, const void *reg_buf,
183				  size_t reg_size, void *val_buf,
184				  size_t val_size)
185{
186	int ret;
187	u32 request, response;
188	u16 *val = val_buf;
189	struct spi_device *spi = context;
190	struct iio_dev *indio_dev = dev_get_drvdata(&spi->dev);
191	struct smi240_data *iio_priv_data = iio_priv(indio_dev);
192
193	if (reg_size != 1 || val_size != 2)
194		return -EINVAL;
195
196	request = FIELD_PREP(SMI240_WRITE_BUS_ID_MASK, SMI240_BUS_ID);
197	request |= FIELD_PREP(SMI240_WRITE_CAP_BIT_MASK, iio_priv_data->capture);
198	request |= FIELD_PREP(SMI240_WRITE_ADDR_MASK, *(u8 *)reg_buf);
199	request |= smi240_crc3(request, SMI240_CRC_INIT, SMI240_CRC_POLY);
200
201	iio_priv_data->spi_buf = cpu_to_be32(request);
202
203	/*
204	 * SMI240 module consists of a 32Bit Out Of Frame (OOF)
205	 * SPI protocol, where the slave interface responds to
206	 * the Master request in the next frame.
207	 * CS signal must toggle (> 700 ns) between the frames.
208	 */
209	ret = spi_write(spi, &iio_priv_data->spi_buf, sizeof(request));
210	if (ret)
211		return ret;
212
213	ret = spi_read(spi, &iio_priv_data->spi_buf, sizeof(response));
214	if (ret)
215		return ret;
216
217	response = be32_to_cpu(iio_priv_data->spi_buf);
218
219	if (!smi240_sensor_data_is_valid(response))
220		return -EIO;
221
222	*val = FIELD_GET(SMI240_READ_DATA_MASK, response);
223
224	return 0;
225}
226
227static int smi240_regmap_spi_write(void *context, const void *data,
228				   size_t count)
229{
230	u8 reg_addr;
231	u16 reg_data;
232	u32 request;
233	const u8 *data_ptr = data;
234	struct spi_device *spi = context;
235	struct iio_dev *indio_dev = dev_get_drvdata(&spi->dev);
236	struct smi240_data *iio_priv_data = iio_priv(indio_dev);
237
238	if (count < 2)
239		return -EINVAL;
240
241	reg_addr = data_ptr[0];
242	memcpy(&reg_data, &data_ptr[1], sizeof(reg_data));
243
244	request = FIELD_PREP(SMI240_WRITE_BUS_ID_MASK, SMI240_BUS_ID);
245	request |= FIELD_PREP(SMI240_WRITE_BIT_MASK, 1);
246	request |= FIELD_PREP(SMI240_WRITE_ADDR_MASK, reg_addr);
247	request |= FIELD_PREP(SMI240_WRITE_DATA_MASK, reg_data);
248	request |= smi240_crc3(request, SMI240_CRC_INIT, SMI240_CRC_POLY);
249
250	iio_priv_data->spi_buf = cpu_to_be32(request);
251
252	return spi_write(spi, &iio_priv_data->spi_buf, sizeof(request));
253}
254
255static const struct regmap_bus smi240_regmap_bus = {
256	.read = smi240_regmap_spi_read,
257	.write = smi240_regmap_spi_write,
258};
259
260static const struct regmap_config smi240_regmap_config = {
261	.reg_bits = 8,
262	.val_bits = 16,
263	.val_format_endian = REGMAP_ENDIAN_NATIVE,
264};
265
266static int smi240_soft_reset(struct smi240_data *data)
267{
268	int ret;
269
270	ret = regmap_write(data->regmap, SMI240_CMD_REG, SMI240_SOFT_RESET_CMD);
271	if (ret)
272		return ret;
273	fsleep(SMI240_DIGITAL_STARTUP_DELAY_US);
274
275	return 0;
276}
277
278static int smi240_soft_config(struct smi240_data *data)
279{
280	int ret;
281	u8 acc_bw, gyr_bw;
282	u16 request;
283
284	switch (data->accel_filter_freq) {
285	case SMI240_LOW_BANDWIDTH_HZ:
286		acc_bw = 0x1;
287		break;
288	case SMI240_HIGH_BANDWIDTH_HZ:
289		acc_bw = 0x0;
290		break;
291	default:
292		return -EINVAL;
293	}
294
295	switch (data->anglvel_filter_freq) {
296	case SMI240_LOW_BANDWIDTH_HZ:
297		gyr_bw = 0x1;
298		break;
299	case SMI240_HIGH_BANDWIDTH_HZ:
300		gyr_bw = 0x0;
301		break;
302	default:
303		return -EINVAL;
304	}
305
306	request = FIELD_PREP(SMI240_SOFT_CONFIG_EOC_MASK, 1);
307	request |= FIELD_PREP(SMI240_SOFT_CONFIG_GYR_BW_MASK, gyr_bw);
308	request |= FIELD_PREP(SMI240_SOFT_CONFIG_ACC_BW_MASK, acc_bw);
309	request |= FIELD_PREP(SMI240_SOFT_CONFIG_BITE_AUTO_MASK, 1);
310	request |= FIELD_PREP(SMI240_SOFT_CONFIG_BITE_REP_MASK,
311			      data->built_in_self_test_count - 1);
312
313	ret = regmap_write(data->regmap, SMI240_SOFT_CONFIG_REG, request);
314	if (ret)
315		return ret;
316
317	fsleep(SMI240_MECH_STARTUP_DELAY_US +
318	       data->built_in_self_test_count * SMI240_BITE_SEQUENCE_DELAY_US +
319	       SMI240_FILTER_FLUSH_DELAY_US);
320
321	return 0;
322}
323
324static int smi240_get_low_pass_filter_freq(struct smi240_data *data,
325					   int chan_type, int *val)
326{
327	switch (chan_type) {
328	case IIO_ACCEL:
329		*val = data->accel_filter_freq;
330		return 0;
331	case IIO_ANGL_VEL:
332		*val = data->anglvel_filter_freq;
333		return 0;
334	default:
335		return -EINVAL;
336	}
337}
338
339static int smi240_get_data(struct smi240_data *data, int chan_type, int axis,
340			   int *val)
341{
342	u8 reg;
343	int ret, sample;
344
345	switch (chan_type) {
346	case IIO_TEMP:
347		reg = SMI240_TEMP_CUR_REG;
348		break;
349	case IIO_ACCEL:
350		reg = SMI240_ACCEL_X_CUR_REG + (axis - IIO_MOD_X);
351		break;
352	case IIO_ANGL_VEL:
353		reg = SMI240_GYRO_X_CUR_REG + (axis - IIO_MOD_X);
354		break;
355	default:
356		return -EINVAL;
357	}
358
359	ret = regmap_read(data->regmap, reg, &sample);
360	if (ret)
361		return ret;
362
363	*val = sign_extend32(sample, 15);
364
365	return 0;
366}
367
368static irqreturn_t smi240_trigger_handler(int irq, void *p)
369{
370	struct iio_poll_func *pf = p;
371	struct iio_dev *indio_dev = pf->indio_dev;
372	struct smi240_data *data = iio_priv(indio_dev);
373	int base = SMI240_DATA_CAP_FIRST_REG, i = 0;
374	int ret, chan, sample;
375
376	data->capture = SMI240_CAPTURE_ON;
377
378	iio_for_each_active_channel(indio_dev, chan) {
379		ret = regmap_read(data->regmap, base + chan, &sample);
380		data->capture = SMI240_CAPTURE_OFF;
381		if (ret)
382			goto out;
383		data->buf[i++] = sample;
384	}
385
386	iio_push_to_buffers_with_timestamp(indio_dev, data->buf, pf->timestamp);
387
388out:
389	iio_trigger_notify_done(indio_dev->trig);
390	return IRQ_HANDLED;
391}
392
393static int smi240_read_avail(struct iio_dev *indio_dev,
394			     struct iio_chan_spec const *chan, const int **vals,
395			     int *type, int *length, long mask)
396{
397	switch (mask) {
398	case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
399		*vals = smi240_low_pass_freqs;
400		*length = ARRAY_SIZE(smi240_low_pass_freqs);
401		*type = IIO_VAL_INT;
402		return IIO_AVAIL_LIST;
403	default:
404		return -EINVAL;
405	}
406}
407
408static int smi240_read_raw(struct iio_dev *indio_dev,
409			   struct iio_chan_spec const *chan, int *val,
410			   int *val2, long mask)
411{
412	int ret;
413	struct smi240_data *data = iio_priv(indio_dev);
414
415	switch (mask) {
416	case IIO_CHAN_INFO_RAW:
417		if (!iio_device_claim_direct(indio_dev))
418			return -EBUSY;
419		ret = smi240_get_data(data, chan->type, chan->channel2, val);
420		iio_device_release_direct(indio_dev);
421		if (ret)
422			return ret;
423		return IIO_VAL_INT;
424
425	case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
426		ret = smi240_get_low_pass_filter_freq(data, chan->type, val);
427		if (ret)
428			return ret;
429		return IIO_VAL_INT;
430
431	case IIO_CHAN_INFO_SCALE:
432		switch (chan->type) {
433		case IIO_TEMP:
434			*val = SMI240_TEMP_SCALE / GIGA;
435			*val2 = SMI240_TEMP_SCALE % GIGA;
436			return IIO_VAL_INT_PLUS_NANO;
437		case IIO_ACCEL:
438			*val = 0;
439			*val2 = SMI240_ACCEL_SCALE;
440			return IIO_VAL_INT_PLUS_MICRO;
441		case IIO_ANGL_VEL:
442			*val = 0;
443			*val2 = SMI240_GYRO_SCALE;
444			return IIO_VAL_INT_PLUS_MICRO;
445		default:
446			return -EINVAL;
447		}
448
449	case IIO_CHAN_INFO_OFFSET:
450		if (chan->type == IIO_TEMP) {
451			*val = SMI240_TEMP_OFFSET;
452			return IIO_VAL_INT;
453		} else {
454			return -EINVAL;
455		}
456
457	default:
458		return -EINVAL;
459	}
460}
461
462static int smi240_write_raw(struct iio_dev *indio_dev,
463			    struct iio_chan_spec const *chan, int val, int val2,
464			    long mask)
465{
466	int ret, i;
467	struct smi240_data *data = iio_priv(indio_dev);
468
469	switch (mask) {
470	case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
471		for (i = 0; i < ARRAY_SIZE(smi240_low_pass_freqs); i++) {
472			if (val == smi240_low_pass_freqs[i])
473				break;
474		}
475
476		if (i == ARRAY_SIZE(smi240_low_pass_freqs))
477			return -EINVAL;
478
479		switch (chan->type) {
480		case IIO_ACCEL:
481			data->accel_filter_freq = val;
482			break;
483		case IIO_ANGL_VEL:
484			data->anglvel_filter_freq = val;
485			break;
486		default:
487			return -EINVAL;
488		}
489		break;
490	default:
491		return -EINVAL;
492	}
493
494	/* Write access to soft config is locked until hard/soft reset */
495	ret = smi240_soft_reset(data);
496	if (ret)
497		return ret;
498
499	return smi240_soft_config(data);
500}
501
502static int smi240_write_raw_get_fmt(struct iio_dev *indio_dev,
503				    struct iio_chan_spec const *chan, long info)
504{
505	switch (info) {
506	case IIO_CHAN_INFO_SCALE:
507		switch (chan->type) {
508		case IIO_TEMP:
509			return IIO_VAL_INT_PLUS_NANO;
510		default:
511			return IIO_VAL_INT_PLUS_MICRO;
512		}
513	default:
514		return IIO_VAL_INT_PLUS_MICRO;
515	}
516}
517
518static int smi240_init(struct smi240_data *data)
519{
520	int ret;
521
522	data->accel_filter_freq = SMI240_HIGH_BANDWIDTH_HZ;
523	data->anglvel_filter_freq = SMI240_HIGH_BANDWIDTH_HZ;
524	data->built_in_self_test_count = SMI240_BUILT_IN_SELF_TEST_COUNT;
525
526	ret = smi240_soft_reset(data);
527	if (ret)
528		return ret;
529
530	return smi240_soft_config(data);
531}
532
533static const struct iio_info smi240_info = {
534	.read_avail = smi240_read_avail,
535	.read_raw = smi240_read_raw,
536	.write_raw = smi240_write_raw,
537	.write_raw_get_fmt = smi240_write_raw_get_fmt,
538};
539
540static int smi240_probe(struct spi_device *spi)
541{
542	struct device *dev = &spi->dev;
543	struct iio_dev *indio_dev;
544	struct regmap *regmap;
545	struct smi240_data *data;
546	int ret, response;
547
548	indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
549	if (!indio_dev)
550		return -ENOMEM;
551
552	regmap = devm_regmap_init(dev, &smi240_regmap_bus, dev,
553				  &smi240_regmap_config);
554	if (IS_ERR(regmap))
555		return dev_err_probe(dev, PTR_ERR(regmap),
556				     "Failed to initialize SPI Regmap\n");
557
558	data = iio_priv(indio_dev);
559	dev_set_drvdata(dev, indio_dev);
560	data->regmap = regmap;
561	data->capture = SMI240_CAPTURE_OFF;
562
563	ret = regmap_read(data->regmap, SMI240_CHIP_ID_REG, &response);
564	if (ret)
565		return dev_err_probe(dev, ret, "Read chip id failed\n");
566
567	if (response != SMI240_CHIP_ID)
568		dev_info(dev, "Unknown chip id: 0x%04x\n", response);
569
570	ret = smi240_init(data);
571	if (ret)
572		return dev_err_probe(dev, ret,
573				     "Device initialization failed\n");
574
575	indio_dev->channels = smi240_channels;
576	indio_dev->num_channels = ARRAY_SIZE(smi240_channels);
577	indio_dev->name = "smi240";
578	indio_dev->modes = INDIO_DIRECT_MODE;
579	indio_dev->info = &smi240_info;
580
581	ret = devm_iio_triggered_buffer_setup(dev, indio_dev,
582					      iio_pollfunc_store_time,
583					      smi240_trigger_handler, NULL);
584	if (ret)
585		return dev_err_probe(dev, ret,
586				     "Setup triggered buffer failed\n");
587
588	ret = devm_iio_device_register(dev, indio_dev);
589	if (ret)
590		return dev_err_probe(dev, ret, "Register IIO device failed\n");
591
592	return 0;
593}
594
595static const struct spi_device_id smi240_spi_id[] = {
596	{ "smi240" },
597	{ }
598};
599MODULE_DEVICE_TABLE(spi, smi240_spi_id);
600
601static const struct of_device_id smi240_of_match[] = {
602	{ .compatible = "bosch,smi240" },
603	{ }
604};
605MODULE_DEVICE_TABLE(of, smi240_of_match);
606
607static struct spi_driver smi240_spi_driver = {
608	.probe = smi240_probe,
609	.id_table = smi240_spi_id,
610	.driver = {
611		.of_match_table = smi240_of_match,
612		.name = "smi240",
613	},
614};
615module_spi_driver(smi240_spi_driver);
616
617MODULE_AUTHOR("Markus Lochmann <markus.lochmann@de.bosch.com>");
618MODULE_AUTHOR("Stefan Gutmann <stefan.gutmann@de.bosch.com>");
619MODULE_DESCRIPTION("Bosch SMI240 SPI driver");
620MODULE_LICENSE("Dual BSD/GPL");
~/ Read-only file preview.