File Index
Files and directories
Sign in
FILE

adis.c

File preview with syntax highlighting.

linux-6.19.14/drivers/iio/imu/adis.c C
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*
  3 * Common library for ADIS16XXX devices
  4 *
  5 * Copyright 2012 Analog Devices Inc.
  6 *   Author: Lars-Peter Clausen <lars@metafoo.de>
  7 */
  8
  9#include <linux/delay.h>
 10#include <linux/gpio/consumer.h>
 11#include <linux/mutex.h>
 12#include <linux/device.h>
 13#include <linux/kernel.h>
 14#include <linux/spi/spi.h>
 15#include <linux/module.h>
 16#include <linux/unaligned.h>
 17
 18#include <linux/iio/iio.h>
 19#include <linux/iio/imu/adis.h>
 20
 21#define ADIS_MSC_CTRL_DATA_RDY_EN	BIT(2)
 22#define ADIS_MSC_CTRL_DATA_RDY_POL_HIGH	BIT(1)
 23#define ADIS_MSC_CTRL_DATA_RDY_DIO2	BIT(0)
 24#define ADIS_GLOB_CMD_SW_RESET		BIT(7)
 25
 26/**
 27 * __adis_write_reg() - write N bytes to register (unlocked version)
 28 * @adis: The adis device
 29 * @reg: The address of the lower of the two registers
 30 * @value: The value to write to device (up to 4 bytes)
 31 * @size: The size of the @value (in bytes)
 32 */
 33int __adis_write_reg(struct adis *adis, unsigned int reg, unsigned int value,
 34		     unsigned int size)
 35{
 36	unsigned int page = reg / ADIS_PAGE_SIZE;
 37	int ret, i;
 38	struct spi_message msg;
 39	struct spi_transfer xfers[] = {
 40		{
 41			.tx_buf = adis->tx,
 42			.len = 2,
 43			.cs_change = 1,
 44			.delay.value = adis->data->write_delay,
 45			.delay.unit = SPI_DELAY_UNIT_USECS,
 46		}, {
 47			.tx_buf = adis->tx + 2,
 48			.len = 2,
 49			.cs_change = 1,
 50			.delay.value = adis->data->write_delay,
 51			.delay.unit = SPI_DELAY_UNIT_USECS,
 52		}, {
 53			.tx_buf = adis->tx + 4,
 54			.len = 2,
 55			.cs_change = 1,
 56			.delay.value = adis->data->write_delay,
 57			.delay.unit = SPI_DELAY_UNIT_USECS,
 58		}, {
 59			.tx_buf = adis->tx + 6,
 60			.len = 2,
 61			.delay.value = adis->data->write_delay,
 62			.delay.unit = SPI_DELAY_UNIT_USECS,
 63		}, {
 64			.tx_buf = adis->tx + 8,
 65			.len = 2,
 66			.delay.value = adis->data->write_delay,
 67			.delay.unit = SPI_DELAY_UNIT_USECS,
 68		},
 69	};
 70
 71	spi_message_init(&msg);
 72
 73	if (adis->current_page != page) {
 74		adis->tx[0] = ADIS_WRITE_REG(ADIS_REG_PAGE_ID);
 75		adis->tx[1] = page;
 76		spi_message_add_tail(&xfers[0], &msg);
 77	}
 78
 79	switch (size) {
 80	case 4:
 81		adis->tx[8] = ADIS_WRITE_REG(reg + 3);
 82		adis->tx[9] = (value >> 24) & 0xff;
 83		adis->tx[6] = ADIS_WRITE_REG(reg + 2);
 84		adis->tx[7] = (value >> 16) & 0xff;
 85		fallthrough;
 86	case 2:
 87		adis->tx[4] = ADIS_WRITE_REG(reg + 1);
 88		adis->tx[5] = (value >> 8) & 0xff;
 89		fallthrough;
 90	case 1:
 91		adis->tx[2] = ADIS_WRITE_REG(reg);
 92		adis->tx[3] = value & 0xff;
 93		break;
 94	default:
 95		return -EINVAL;
 96	}
 97
 98	xfers[size].cs_change = 0;
 99
100	for (i = 1; i <= size; i++)
101		spi_message_add_tail(&xfers[i], &msg);
102
103	ret = spi_sync(adis->spi, &msg);
104	if (ret) {
105		dev_err(&adis->spi->dev, "Failed to write register 0x%02X: %d\n",
106			reg, ret);
107	} else {
108		adis->current_page = page;
109	}
110
111	return ret;
112}
113EXPORT_SYMBOL_NS_GPL(__adis_write_reg, "IIO_ADISLIB");
114
115/**
116 * __adis_read_reg() - read N bytes from register (unlocked version)
117 * @adis: The adis device
118 * @reg: The address of the lower of the two registers
119 * @val: The value read back from the device
120 * @size: The size of the @val buffer
121 */
122int __adis_read_reg(struct adis *adis, unsigned int reg, unsigned int *val,
123		    unsigned int size)
124{
125	unsigned int page = reg / ADIS_PAGE_SIZE;
126	struct spi_message msg;
127	int ret;
128	struct spi_transfer xfers[] = {
129		{
130			.tx_buf = adis->tx,
131			.len = 2,
132			.cs_change = 1,
133			.delay.value = adis->data->write_delay,
134			.delay.unit = SPI_DELAY_UNIT_USECS,
135		}, {
136			.tx_buf = adis->tx + 2,
137			.len = 2,
138			.cs_change = 1,
139			.delay.value = adis->data->read_delay,
140			.delay.unit = SPI_DELAY_UNIT_USECS,
141		}, {
142			.tx_buf = adis->tx + 4,
143			.rx_buf = adis->rx,
144			.len = 2,
145			.cs_change = 1,
146			.delay.value = adis->data->read_delay,
147			.delay.unit = SPI_DELAY_UNIT_USECS,
148		}, {
149			.rx_buf = adis->rx + 2,
150			.len = 2,
151			.delay.value = adis->data->read_delay,
152			.delay.unit = SPI_DELAY_UNIT_USECS,
153		},
154	};
155
156	spi_message_init(&msg);
157
158	if (adis->current_page != page) {
159		adis->tx[0] = ADIS_WRITE_REG(ADIS_REG_PAGE_ID);
160		adis->tx[1] = page;
161		spi_message_add_tail(&xfers[0], &msg);
162	}
163
164	switch (size) {
165	case 4:
166		adis->tx[2] = ADIS_READ_REG(reg + 2);
167		adis->tx[3] = 0;
168		spi_message_add_tail(&xfers[1], &msg);
169		fallthrough;
170	case 2:
171		adis->tx[4] = ADIS_READ_REG(reg);
172		adis->tx[5] = 0;
173		spi_message_add_tail(&xfers[2], &msg);
174		spi_message_add_tail(&xfers[3], &msg);
175		break;
176	default:
177		return -EINVAL;
178	}
179
180	ret = spi_sync(adis->spi, &msg);
181	if (ret) {
182		dev_err(&adis->spi->dev, "Failed to read register 0x%02X: %d\n",
183			reg, ret);
184		return ret;
185	}
186
187	adis->current_page = page;
188
189	switch (size) {
190	case 4:
191		*val = get_unaligned_be32(adis->rx);
192		break;
193	case 2:
194		*val = get_unaligned_be16(adis->rx + 2);
195		break;
196	}
197
198	return ret;
199}
200EXPORT_SYMBOL_NS_GPL(__adis_read_reg, "IIO_ADISLIB");
201/**
202 * __adis_update_bits_base() - ADIS Update bits function - Unlocked version
203 * @adis: The adis device
204 * @reg: The address of the lower of the two registers
205 * @mask: Bitmask to change
206 * @val: Value to be written
207 * @size: Size of the register to update
208 *
209 * Updates the desired bits of @reg in accordance with @mask and @val.
210 */
211int __adis_update_bits_base(struct adis *adis, unsigned int reg, const u32 mask,
212			    const u32 val, u8 size)
213{
214	int ret;
215	u32 __val;
216
217	ret = adis->ops->read(adis, reg, &__val, size);
218	if (ret)
219		return ret;
220
221	__val = (__val & ~mask) | (val & mask);
222
223	return adis->ops->write(adis, reg, __val, size);
224}
225EXPORT_SYMBOL_NS_GPL(__adis_update_bits_base, "IIO_ADISLIB");
226
227#ifdef CONFIG_DEBUG_FS
228
229int adis_debugfs_reg_access(struct iio_dev *indio_dev, unsigned int reg,
230			    unsigned int writeval, unsigned int *readval)
231{
232	struct adis *adis = iio_device_get_drvdata(indio_dev);
233
234	if (readval) {
235		u16 val16;
236		int ret;
237
238		ret = adis_read_reg_16(adis, reg, &val16);
239		if (ret == 0)
240			*readval = val16;
241
242		return ret;
243	}
244
245	return adis_write_reg_16(adis, reg, writeval);
246}
247EXPORT_SYMBOL_NS(adis_debugfs_reg_access, "IIO_ADISLIB");
248
249#endif
250
251/**
252 * __adis_enable_irq() - Enable or disable data ready IRQ (unlocked)
253 * @adis: The adis device
254 * @enable: Whether to enable the IRQ
255 *
256 * Returns 0 on success, negative error code otherwise
257 */
258int __adis_enable_irq(struct adis *adis, bool enable)
259{
260	int ret;
261	u16 msc;
262
263	if (adis->data->enable_irq)
264		return adis->data->enable_irq(adis, enable);
265
266	if (adis->data->unmasked_drdy) {
267		if (enable)
268			enable_irq(adis->spi->irq);
269		else
270			disable_irq(adis->spi->irq);
271
272		return 0;
273	}
274
275	ret = __adis_read_reg_16(adis, adis->data->msc_ctrl_reg, &msc);
276	if (ret)
277		return ret;
278
279	msc |= ADIS_MSC_CTRL_DATA_RDY_POL_HIGH;
280	msc &= ~ADIS_MSC_CTRL_DATA_RDY_DIO2;
281	if (enable)
282		msc |= ADIS_MSC_CTRL_DATA_RDY_EN;
283	else
284		msc &= ~ADIS_MSC_CTRL_DATA_RDY_EN;
285
286	return __adis_write_reg_16(adis, adis->data->msc_ctrl_reg, msc);
287}
288EXPORT_SYMBOL_NS(__adis_enable_irq, "IIO_ADISLIB");
289
290/**
291 * __adis_check_status() - Check the device for error conditions (unlocked)
292 * @adis: The adis device
293 *
294 * Returns 0 on success, a negative error code otherwise
295 */
296int __adis_check_status(struct adis *adis)
297{
298	unsigned int status;
299	int diag_stat_bits;
300	u16 status_16 = 0;
301	int ret;
302	int i;
303
304	if (adis->data->diag_stat_size) {
305		ret = adis->ops->read(adis, adis->data->diag_stat_reg, &status,
306				      adis->data->diag_stat_size);
307	} else {
308		ret = __adis_read_reg_16(adis, adis->data->diag_stat_reg,
309					 &status_16);
310		status = status_16;
311	}
312	if (ret)
313		return ret;
314
315	status &= adis->data->status_error_mask;
316
317	if (status == 0)
318		return 0;
319
320	diag_stat_bits = BITS_PER_BYTE * (adis->data->diag_stat_size ?
321					  adis->data->diag_stat_size : 2);
322
323	for (i = 0; i < diag_stat_bits; ++i) {
324		if (status & BIT(i)) {
325			dev_err(&adis->spi->dev, "%s.\n",
326				adis->data->status_error_msgs[i]);
327		}
328	}
329
330	return -EIO;
331}
332EXPORT_SYMBOL_NS_GPL(__adis_check_status, "IIO_ADISLIB");
333
334/**
335 * __adis_reset() - Reset the device (unlocked version)
336 * @adis: The adis device
337 *
338 * Returns 0 on success, a negative error code otherwise
339 */
340int __adis_reset(struct adis *adis)
341{
342	int ret;
343	const struct adis_timeout *timeouts = adis->data->timeouts;
344
345	ret = __adis_write_reg_8(adis, adis->data->glob_cmd_reg,
346				 ADIS_GLOB_CMD_SW_RESET);
347	if (ret) {
348		dev_err(&adis->spi->dev, "Failed to reset device: %d\n", ret);
349		return ret;
350	}
351
352	msleep(timeouts->sw_reset_ms);
353
354	return 0;
355}
356EXPORT_SYMBOL_NS_GPL(__adis_reset, "IIO_ADIS_LIB");
357
358static int adis_self_test(struct adis *adis)
359{
360	int ret;
361	const struct adis_timeout *timeouts = adis->data->timeouts;
362
363	ret = __adis_write_reg_16(adis, adis->data->self_test_reg,
364				  adis->data->self_test_mask);
365	if (ret) {
366		dev_err(&adis->spi->dev, "Failed to initiate self test: %d\n",
367			ret);
368		return ret;
369	}
370
371	msleep(timeouts->self_test_ms);
372
373	ret = __adis_check_status(adis);
374
375	if (adis->data->self_test_no_autoclear)
376		__adis_write_reg_16(adis, adis->data->self_test_reg, 0x00);
377
378	return ret;
379}
380
381/**
382 * __adis_initial_startup() - Device initial setup
383 * @adis: The adis device
384 *
385 * The function performs a HW reset via a reset pin that should be specified
386 * via GPIOLIB. If no pin is configured a SW reset will be performed.
387 * The RST pin for the ADIS devices should be configured as ACTIVE_LOW.
388 *
389 * After the self-test operation is performed, the function will also check
390 * that the product ID is as expected. This assumes that drivers providing
391 * 'prod_id_reg' will also provide the 'prod_id'.
392 *
393 * Returns 0 if the device is operational, a negative error code otherwise.
394 *
395 * This function should be called early on in the device initialization sequence
396 * to ensure that the device is in a sane and known state and that it is usable.
397 */
398int __adis_initial_startup(struct adis *adis)
399{
400	const struct adis_timeout *timeouts = adis->data->timeouts;
401	struct gpio_desc *gpio;
402	u16 prod_id;
403	int ret;
404
405	/* check if the device has rst pin low */
406	gpio = devm_gpiod_get_optional(&adis->spi->dev, "reset", GPIOD_OUT_HIGH);
407	if (IS_ERR(gpio))
408		return PTR_ERR(gpio);
409
410	if (gpio) {
411		usleep_range(10, 12);
412		/* bring device out of reset */
413		gpiod_set_value_cansleep(gpio, 0);
414		msleep(timeouts->reset_ms);
415	} else {
416		ret = __adis_reset(adis);
417		if (ret)
418			return ret;
419	}
420
421	ret = adis_self_test(adis);
422	if (ret)
423		return ret;
424
425	/*
426	 * don't bother calling this if we can't unmask the IRQ as in this case
427	 * the IRQ is most likely not yet requested and we will request it
428	 * with 'IRQF_NO_AUTOEN' anyways.
429	 */
430	if (!adis->data->unmasked_drdy)
431		__adis_enable_irq(adis, false);
432
433	if (!adis->data->prod_id_reg)
434		return 0;
435
436	ret = adis_read_reg_16(adis, adis->data->prod_id_reg, &prod_id);
437	if (ret)
438		return ret;
439
440	if (prod_id != adis->data->prod_id)
441		dev_warn(&adis->spi->dev,
442			 "Device ID(%u) and product ID(%u) do not match.\n",
443			 adis->data->prod_id, prod_id);
444
445	return 0;
446}
447EXPORT_SYMBOL_NS_GPL(__adis_initial_startup, "IIO_ADISLIB");
448
449/**
450 * adis_single_conversion() - Performs a single sample conversion
451 * @indio_dev: The IIO device
452 * @chan: The IIO channel
453 * @error_mask: Mask for the error bit
454 * @val: Result of the conversion
455 *
456 * Returns IIO_VAL_INT on success, a negative error code otherwise.
457 *
458 * The function performs a single conversion on a given channel and post
459 * processes the value accordingly to the channel spec. If a error_mask is given
460 * the function will check if the mask is set in the returned raw value. If it
461 * is set the function will perform a self-check. If the device does not report
462 * a error bit in the channels raw value set error_mask to 0.
463 */
464int adis_single_conversion(struct iio_dev *indio_dev,
465			   const struct iio_chan_spec *chan,
466			   unsigned int error_mask, int *val)
467{
468	struct adis *adis = iio_device_get_drvdata(indio_dev);
469	unsigned int uval;
470	int ret;
471
472	guard(mutex)(&adis->state_lock);
473
474	ret = adis->ops->read(adis, chan->address, &uval,
475			      chan->scan_type.storagebits / 8);
476	if (ret)
477		return ret;
478
479	if (uval & error_mask) {
480		ret = __adis_check_status(adis);
481		if (ret)
482			return ret;
483	}
484
485	if (chan->scan_type.sign == 's')
486		*val = sign_extend32(uval, chan->scan_type.realbits - 1);
487	else
488		*val = uval & ((1 << chan->scan_type.realbits) - 1);
489
490	return IIO_VAL_INT;
491}
492EXPORT_SYMBOL_NS_GPL(adis_single_conversion, "IIO_ADISLIB");
493
494static const struct adis_ops adis_default_ops = {
495	.read = __adis_read_reg,
496	.write = __adis_write_reg,
497	.reset = __adis_reset,
498};
499
500/**
501 * adis_init() - Initialize adis device structure
502 * @adis:	The adis device
503 * @indio_dev:	The iio device
504 * @spi:	The spi device
505 * @data:	Chip specific data
506 *
507 * Returns 0 on success, a negative error code otherwise.
508 *
509 * This function must be called, before any other adis helper function may be
510 * called.
511 */
512int adis_init(struct adis *adis, struct iio_dev *indio_dev,
513	      struct spi_device *spi, const struct adis_data *data)
514{
515	if (!data || !data->timeouts) {
516		dev_err(&spi->dev, "No config data or timeouts not defined!\n");
517		return -EINVAL;
518	}
519
520	mutex_init(&adis->state_lock);
521
522	if (!spi->cs_inactive.value) {
523		spi->cs_inactive.value = data->cs_change_delay;
524		spi->cs_inactive.unit = SPI_DELAY_UNIT_USECS;
525	}
526
527	adis->spi = spi;
528	adis->data = data;
529	if (!adis->ops)
530		adis->ops = &adis_default_ops;
531	else if (!adis->ops->write || !adis->ops->read || !adis->ops->reset)
532		return -EINVAL;
533
534	iio_device_set_drvdata(indio_dev, adis);
535
536	if (data->has_paging) {
537		/* Need to set the page before first read/write */
538		adis->current_page = -1;
539	} else {
540		/* Page will always be 0 */
541		adis->current_page = 0;
542	}
543
544	return 0;
545}
546EXPORT_SYMBOL_NS_GPL(adis_init, "IIO_ADISLIB");
547
548MODULE_LICENSE("GPL");
549MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
550MODULE_DESCRIPTION("Common library code for ADIS16XXX devices");
~/ Read-only file preview.