Linux Audio

Check our new training course

Linux BSP upgrade and security maintenance

Need help to get security updates for your Linux BSP?
Loading...
  1// SPDX-License-Identifier: GPL-2.0+
  2/*
  3 * ADIS16460 IMU driver
  4 *
  5 * Copyright 2019 Analog Devices Inc.
  6 */
  7
 
  8#include <linux/module.h>
  9#include <linux/spi/spi.h>
 10
 11#include <linux/iio/iio.h>
 12#include <linux/iio/imu/adis.h>
 13
 14#include <linux/debugfs.h>
 15
 16#define ADIS16460_REG_FLASH_CNT		0x00
 17#define ADIS16460_REG_DIAG_STAT		0x02
 18#define ADIS16460_REG_X_GYRO_LOW	0x04
 19#define ADIS16460_REG_X_GYRO_OUT	0x06
 20#define ADIS16460_REG_Y_GYRO_LOW	0x08
 21#define ADIS16460_REG_Y_GYRO_OUT	0x0A
 22#define ADIS16460_REG_Z_GYRO_LOW	0x0C
 23#define ADIS16460_REG_Z_GYRO_OUT	0x0E
 24#define ADIS16460_REG_X_ACCL_LOW	0x10
 25#define ADIS16460_REG_X_ACCL_OUT	0x12
 26#define ADIS16460_REG_Y_ACCL_LOW	0x14
 27#define ADIS16460_REG_Y_ACCL_OUT	0x16
 28#define ADIS16460_REG_Z_ACCL_LOW	0x18
 29#define ADIS16460_REG_Z_ACCL_OUT	0x1A
 30#define ADIS16460_REG_SMPL_CNTR		0x1C
 31#define ADIS16460_REG_TEMP_OUT		0x1E
 32#define ADIS16460_REG_X_DELT_ANG	0x24
 33#define ADIS16460_REG_Y_DELT_ANG	0x26
 34#define ADIS16460_REG_Z_DELT_ANG	0x28
 35#define ADIS16460_REG_X_DELT_VEL	0x2A
 36#define ADIS16460_REG_Y_DELT_VEL	0x2C
 37#define ADIS16460_REG_Z_DELT_VEL	0x2E
 38#define ADIS16460_REG_MSC_CTRL		0x32
 39#define ADIS16460_REG_SYNC_SCAL		0x34
 40#define ADIS16460_REG_DEC_RATE		0x36
 41#define ADIS16460_REG_FLTR_CTRL		0x38
 42#define ADIS16460_REG_GLOB_CMD		0x3E
 43#define ADIS16460_REG_X_GYRO_OFF	0x40
 44#define ADIS16460_REG_Y_GYRO_OFF	0x42
 45#define ADIS16460_REG_Z_GYRO_OFF	0x44
 46#define ADIS16460_REG_X_ACCL_OFF	0x46
 47#define ADIS16460_REG_Y_ACCL_OFF	0x48
 48#define ADIS16460_REG_Z_ACCL_OFF	0x4A
 49#define ADIS16460_REG_LOT_ID1		0x52
 50#define ADIS16460_REG_LOT_ID2		0x54
 51#define ADIS16460_REG_PROD_ID		0x56
 52#define ADIS16460_REG_SERIAL_NUM	0x58
 53#define ADIS16460_REG_CAL_SGNTR		0x60
 54#define ADIS16460_REG_CAL_CRC		0x62
 55#define ADIS16460_REG_CODE_SGNTR	0x64
 56#define ADIS16460_REG_CODE_CRC		0x66
 57
 58struct adis16460_chip_info {
 59	unsigned int num_channels;
 60	const struct iio_chan_spec *channels;
 61	unsigned int gyro_max_val;
 62	unsigned int gyro_max_scale;
 63	unsigned int accel_max_val;
 64	unsigned int accel_max_scale;
 65};
 66
 67struct adis16460 {
 68	const struct adis16460_chip_info *chip_info;
 69	struct adis adis;
 70};
 71
 72#ifdef CONFIG_DEBUG_FS
 73
 74static int adis16460_show_serial_number(void *arg, u64 *val)
 75{
 76	struct adis16460 *adis16460 = arg;
 77	u16 serial;
 78	int ret;
 79
 80	ret = adis_read_reg_16(&adis16460->adis, ADIS16460_REG_SERIAL_NUM,
 81		&serial);
 82	if (ret)
 83		return ret;
 84
 85	*val = serial;
 86
 87	return 0;
 88}
 89DEFINE_DEBUGFS_ATTRIBUTE(adis16460_serial_number_fops,
 90		adis16460_show_serial_number, NULL, "0x%.4llx\n");
 91
 92static int adis16460_show_product_id(void *arg, u64 *val)
 93{
 94	struct adis16460 *adis16460 = arg;
 95	u16 prod_id;
 96	int ret;
 97
 98	ret = adis_read_reg_16(&adis16460->adis, ADIS16460_REG_PROD_ID,
 99		&prod_id);
100	if (ret)
101		return ret;
102
103	*val = prod_id;
104
105	return 0;
106}
107DEFINE_DEBUGFS_ATTRIBUTE(adis16460_product_id_fops,
108		adis16460_show_product_id, NULL, "%llu\n");
109
110static int adis16460_show_flash_count(void *arg, u64 *val)
111{
112	struct adis16460 *adis16460 = arg;
113	u32 flash_count;
114	int ret;
115
116	ret = adis_read_reg_32(&adis16460->adis, ADIS16460_REG_FLASH_CNT,
117		&flash_count);
118	if (ret)
119		return ret;
120
121	*val = flash_count;
122
123	return 0;
124}
125DEFINE_DEBUGFS_ATTRIBUTE(adis16460_flash_count_fops,
126		adis16460_show_flash_count, NULL, "%lld\n");
127
128static int adis16460_debugfs_init(struct iio_dev *indio_dev)
129{
130	struct adis16460 *adis16460 = iio_priv(indio_dev);
131	struct dentry *d = iio_get_debugfs_dentry(indio_dev);
132
133	debugfs_create_file_unsafe("serial_number", 0400,
134			d, adis16460, &adis16460_serial_number_fops);
135	debugfs_create_file_unsafe("product_id", 0400,
136			d, adis16460, &adis16460_product_id_fops);
137	debugfs_create_file_unsafe("flash_count", 0400,
138			d, adis16460, &adis16460_flash_count_fops);
139
140	return 0;
141}
142
143#else
144
145static int adis16460_debugfs_init(struct iio_dev *indio_dev)
146{
147	return 0;
148}
149
150#endif
151
152static int adis16460_set_freq(struct iio_dev *indio_dev, int val, int val2)
153{
154	struct adis16460 *st = iio_priv(indio_dev);
155	int t;
156
157	t =  val * 1000 + val2 / 1000;
158	if (t <= 0)
159		return -EINVAL;
160
161	t = 2048000 / t;
162	if (t > 2048)
163		t = 2048;
164
165	if (t != 0)
166		t--;
167
168	return adis_write_reg_16(&st->adis, ADIS16460_REG_DEC_RATE, t);
169}
170
171static int adis16460_get_freq(struct iio_dev *indio_dev, int *val, int *val2)
172{
173	struct adis16460 *st = iio_priv(indio_dev);
174	uint16_t t;
175	int ret;
176	unsigned int freq;
177
178	ret = adis_read_reg_16(&st->adis, ADIS16460_REG_DEC_RATE, &t);
179	if (ret)
180		return ret;
181
182	freq = 2048000 / (t + 1);
183	*val = freq / 1000;
184	*val2 = (freq % 1000) * 1000;
185
186	return IIO_VAL_INT_PLUS_MICRO;
187}
188
189static int adis16460_read_raw(struct iio_dev *indio_dev,
190	const struct iio_chan_spec *chan, int *val, int *val2, long info)
191{
192	struct adis16460 *st = iio_priv(indio_dev);
193
194	switch (info) {
195	case IIO_CHAN_INFO_RAW:
196		return adis_single_conversion(indio_dev, chan, 0, val);
197	case IIO_CHAN_INFO_SCALE:
198		switch (chan->type) {
199		case IIO_ANGL_VEL:
200			*val = st->chip_info->gyro_max_scale;
201			*val2 = st->chip_info->gyro_max_val;
202			return IIO_VAL_FRACTIONAL;
203		case IIO_ACCEL:
204			*val = st->chip_info->accel_max_scale;
205			*val2 = st->chip_info->accel_max_val;
206			return IIO_VAL_FRACTIONAL;
207		case IIO_TEMP:
208			*val = 50; /* 50 milli degrees Celsius/LSB */
209			return IIO_VAL_INT;
210		default:
211			return -EINVAL;
212		}
213	case IIO_CHAN_INFO_OFFSET:
214		*val = 500; /* 25 degrees Celsius = 0x0000 */
215		return IIO_VAL_INT;
216	case IIO_CHAN_INFO_SAMP_FREQ:
217		return adis16460_get_freq(indio_dev, val, val2);
218	default:
219		return -EINVAL;
220	}
221}
222
223static int adis16460_write_raw(struct iio_dev *indio_dev,
224	const struct iio_chan_spec *chan, int val, int val2, long info)
225{
226	switch (info) {
227	case IIO_CHAN_INFO_SAMP_FREQ:
228		return adis16460_set_freq(indio_dev, val, val2);
229	default:
230		return -EINVAL;
231	}
232}
233
234enum {
235	ADIS16460_SCAN_GYRO_X,
236	ADIS16460_SCAN_GYRO_Y,
237	ADIS16460_SCAN_GYRO_Z,
238	ADIS16460_SCAN_ACCEL_X,
239	ADIS16460_SCAN_ACCEL_Y,
240	ADIS16460_SCAN_ACCEL_Z,
241	ADIS16460_SCAN_TEMP,
242};
243
244#define ADIS16460_MOD_CHANNEL(_type, _mod, _address, _si, _bits) \
245	{ \
246		.type = (_type), \
247		.modified = 1, \
248		.channel2 = (_mod), \
249		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
250		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
251		.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
252		.address = (_address), \
253		.scan_index = (_si), \
254		.scan_type = { \
255			.sign = 's', \
256			.realbits = (_bits), \
257			.storagebits = (_bits), \
258			.endianness = IIO_BE, \
259		}, \
260	}
261
262#define ADIS16460_GYRO_CHANNEL(_mod) \
263	ADIS16460_MOD_CHANNEL(IIO_ANGL_VEL, IIO_MOD_ ## _mod, \
264	ADIS16460_REG_ ## _mod ## _GYRO_LOW, ADIS16460_SCAN_GYRO_ ## _mod, \
265	32)
266
267#define ADIS16460_ACCEL_CHANNEL(_mod) \
268	ADIS16460_MOD_CHANNEL(IIO_ACCEL, IIO_MOD_ ## _mod, \
269	ADIS16460_REG_ ## _mod ## _ACCL_LOW, ADIS16460_SCAN_ACCEL_ ## _mod, \
270	32)
271
272#define ADIS16460_TEMP_CHANNEL() { \
273		.type = IIO_TEMP, \
274		.indexed = 1, \
275		.channel = 0, \
276		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
277			BIT(IIO_CHAN_INFO_SCALE) | \
278			BIT(IIO_CHAN_INFO_OFFSET), \
279		.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
280		.address = ADIS16460_REG_TEMP_OUT, \
281		.scan_index = ADIS16460_SCAN_TEMP, \
282		.scan_type = { \
283			.sign = 's', \
284			.realbits = 16, \
285			.storagebits = 16, \
286			.endianness = IIO_BE, \
287		}, \
288	}
289
290static const struct iio_chan_spec adis16460_channels[] = {
291	ADIS16460_GYRO_CHANNEL(X),
292	ADIS16460_GYRO_CHANNEL(Y),
293	ADIS16460_GYRO_CHANNEL(Z),
294	ADIS16460_ACCEL_CHANNEL(X),
295	ADIS16460_ACCEL_CHANNEL(Y),
296	ADIS16460_ACCEL_CHANNEL(Z),
297	ADIS16460_TEMP_CHANNEL(),
298	IIO_CHAN_SOFT_TIMESTAMP(7)
299};
300
301static const struct adis16460_chip_info adis16460_chip_info = {
302	.channels = adis16460_channels,
303	.num_channels = ARRAY_SIZE(adis16460_channels),
304	/*
305	 * storing the value in rad/degree and the scale in degree
306	 * gives us the result in rad and better precession than
307	 * storing the scale directly in rad.
308	 */
309	.gyro_max_val = IIO_RAD_TO_DEGREE(200 << 16),
310	.gyro_max_scale = 1,
311	.accel_max_val = IIO_M_S_2_TO_G(20000 << 16),
312	.accel_max_scale = 5,
313};
314
315static const struct iio_info adis16460_info = {
316	.read_raw = &adis16460_read_raw,
317	.write_raw = &adis16460_write_raw,
318	.update_scan_mode = adis_update_scan_mode,
319	.debugfs_reg_access = adis_debugfs_reg_access,
320};
321
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
322#define ADIS16460_DIAG_STAT_IN_CLK_OOS	7
323#define ADIS16460_DIAG_STAT_FLASH_MEM	6
324#define ADIS16460_DIAG_STAT_SELF_TEST	5
325#define ADIS16460_DIAG_STAT_OVERRANGE	4
326#define ADIS16460_DIAG_STAT_SPI_COMM	3
327#define ADIS16460_DIAG_STAT_FLASH_UPT	2
328
329static const char * const adis16460_status_error_msgs[] = {
330	[ADIS16460_DIAG_STAT_IN_CLK_OOS] = "Input clock out of sync",
331	[ADIS16460_DIAG_STAT_FLASH_MEM] = "Flash memory failure",
332	[ADIS16460_DIAG_STAT_SELF_TEST] = "Self test diagnostic failure",
333	[ADIS16460_DIAG_STAT_OVERRANGE] = "Sensor overrange",
334	[ADIS16460_DIAG_STAT_SPI_COMM] = "SPI communication failure",
335	[ADIS16460_DIAG_STAT_FLASH_UPT] = "Flash update failure",
336};
337
338static const struct adis_timeout adis16460_timeouts = {
339	.reset_ms = 225,
340	.sw_reset_ms = 225,
341	.self_test_ms = 10,
342};
343
344static const struct adis_data adis16460_data = {
345	.diag_stat_reg = ADIS16460_REG_DIAG_STAT,
346	.glob_cmd_reg = ADIS16460_REG_GLOB_CMD,
347	.prod_id_reg = ADIS16460_REG_PROD_ID,
348	.prod_id = 16460,
349	.self_test_mask = BIT(2),
350	.self_test_reg = ADIS16460_REG_GLOB_CMD,
351	.has_paging = false,
352	.read_delay = 5,
353	.write_delay = 5,
354	.cs_change_delay = 16,
355	.status_error_msgs = adis16460_status_error_msgs,
356	.status_error_mask = BIT(ADIS16460_DIAG_STAT_IN_CLK_OOS) |
357		BIT(ADIS16460_DIAG_STAT_FLASH_MEM) |
358		BIT(ADIS16460_DIAG_STAT_SELF_TEST) |
359		BIT(ADIS16460_DIAG_STAT_OVERRANGE) |
360		BIT(ADIS16460_DIAG_STAT_SPI_COMM) |
361		BIT(ADIS16460_DIAG_STAT_FLASH_UPT),
362	.unmasked_drdy = true,
363	.timeouts = &adis16460_timeouts,
364};
365
366static int adis16460_probe(struct spi_device *spi)
367{
368	struct iio_dev *indio_dev;
369	struct adis16460 *st;
370	int ret;
371
372	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
373	if (indio_dev == NULL)
374		return -ENOMEM;
375
 
 
376	st = iio_priv(indio_dev);
377
378	st->chip_info = &adis16460_chip_info;
 
379	indio_dev->name = spi_get_device_id(spi)->name;
380	indio_dev->channels = st->chip_info->channels;
381	indio_dev->num_channels = st->chip_info->num_channels;
382	indio_dev->info = &adis16460_info;
383	indio_dev->modes = INDIO_DIRECT_MODE;
384
385	ret = adis_init(&st->adis, indio_dev, spi, &adis16460_data);
386	if (ret)
387		return ret;
388
389	ret = devm_adis_setup_buffer_and_trigger(&st->adis, indio_dev, NULL);
390	if (ret)
391		return ret;
392
393	ret = __adis_initial_startup(&st->adis);
 
 
394	if (ret)
395		return ret;
396
397	ret = devm_iio_device_register(&spi->dev, indio_dev);
398	if (ret)
399		return ret;
400
401	adis16460_debugfs_init(indio_dev);
402
403	return 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
404}
405
406static const struct spi_device_id adis16460_ids[] = {
407	{ "adis16460", 0 },
408	{}
409};
410MODULE_DEVICE_TABLE(spi, adis16460_ids);
411
412static const struct of_device_id adis16460_of_match[] = {
413	{ .compatible = "adi,adis16460" },
414	{}
415};
416MODULE_DEVICE_TABLE(of, adis16460_of_match);
417
418static struct spi_driver adis16460_driver = {
419	.driver = {
420		.name = "adis16460",
421		.of_match_table = adis16460_of_match,
422	},
423	.id_table = adis16460_ids,
424	.probe = adis16460_probe,
 
425};
426module_spi_driver(adis16460_driver);
427
428MODULE_AUTHOR("Dragos Bogdan <dragos.bogdan@analog.com>");
429MODULE_DESCRIPTION("Analog Devices ADIS16460 IMU driver");
430MODULE_LICENSE("GPL");
431MODULE_IMPORT_NS(IIO_ADISLIB);
  1// SPDX-License-Identifier: GPL-2.0+
  2/*
  3 * ADIS16460 IMU driver
  4 *
  5 * Copyright 2019 Analog Devices Inc.
  6 */
  7
  8#include <linux/delay.h>
  9#include <linux/module.h>
 10#include <linux/spi/spi.h>
 11
 12#include <linux/iio/iio.h>
 13#include <linux/iio/imu/adis.h>
 14
 15#include <linux/debugfs.h>
 16
 17#define ADIS16460_REG_FLASH_CNT		0x00
 18#define ADIS16460_REG_DIAG_STAT		0x02
 19#define ADIS16460_REG_X_GYRO_LOW	0x04
 20#define ADIS16460_REG_X_GYRO_OUT	0x06
 21#define ADIS16460_REG_Y_GYRO_LOW	0x08
 22#define ADIS16460_REG_Y_GYRO_OUT	0x0A
 23#define ADIS16460_REG_Z_GYRO_LOW	0x0C
 24#define ADIS16460_REG_Z_GYRO_OUT	0x0E
 25#define ADIS16460_REG_X_ACCL_LOW	0x10
 26#define ADIS16460_REG_X_ACCL_OUT	0x12
 27#define ADIS16460_REG_Y_ACCL_LOW	0x14
 28#define ADIS16460_REG_Y_ACCL_OUT	0x16
 29#define ADIS16460_REG_Z_ACCL_LOW	0x18
 30#define ADIS16460_REG_Z_ACCL_OUT	0x1A
 31#define ADIS16460_REG_SMPL_CNTR		0x1C
 32#define ADIS16460_REG_TEMP_OUT		0x1E
 33#define ADIS16460_REG_X_DELT_ANG	0x24
 34#define ADIS16460_REG_Y_DELT_ANG	0x26
 35#define ADIS16460_REG_Z_DELT_ANG	0x28
 36#define ADIS16460_REG_X_DELT_VEL	0x2A
 37#define ADIS16460_REG_Y_DELT_VEL	0x2C
 38#define ADIS16460_REG_Z_DELT_VEL	0x2E
 39#define ADIS16460_REG_MSC_CTRL		0x32
 40#define ADIS16460_REG_SYNC_SCAL		0x34
 41#define ADIS16460_REG_DEC_RATE		0x36
 42#define ADIS16460_REG_FLTR_CTRL		0x38
 43#define ADIS16460_REG_GLOB_CMD		0x3E
 44#define ADIS16460_REG_X_GYRO_OFF	0x40
 45#define ADIS16460_REG_Y_GYRO_OFF	0x42
 46#define ADIS16460_REG_Z_GYRO_OFF	0x44
 47#define ADIS16460_REG_X_ACCL_OFF	0x46
 48#define ADIS16460_REG_Y_ACCL_OFF	0x48
 49#define ADIS16460_REG_Z_ACCL_OFF	0x4A
 50#define ADIS16460_REG_LOT_ID1		0x52
 51#define ADIS16460_REG_LOT_ID2		0x54
 52#define ADIS16460_REG_PROD_ID		0x56
 53#define ADIS16460_REG_SERIAL_NUM	0x58
 54#define ADIS16460_REG_CAL_SGNTR		0x60
 55#define ADIS16460_REG_CAL_CRC		0x62
 56#define ADIS16460_REG_CODE_SGNTR	0x64
 57#define ADIS16460_REG_CODE_CRC		0x66
 58
 59struct adis16460_chip_info {
 60	unsigned int num_channels;
 61	const struct iio_chan_spec *channels;
 62	unsigned int gyro_max_val;
 63	unsigned int gyro_max_scale;
 64	unsigned int accel_max_val;
 65	unsigned int accel_max_scale;
 66};
 67
 68struct adis16460 {
 69	const struct adis16460_chip_info *chip_info;
 70	struct adis adis;
 71};
 72
 73#ifdef CONFIG_DEBUG_FS
 74
 75static int adis16460_show_serial_number(void *arg, u64 *val)
 76{
 77	struct adis16460 *adis16460 = arg;
 78	u16 serial;
 79	int ret;
 80
 81	ret = adis_read_reg_16(&adis16460->adis, ADIS16460_REG_SERIAL_NUM,
 82		&serial);
 83	if (ret < 0)
 84		return ret;
 85
 86	*val = serial;
 87
 88	return 0;
 89}
 90DEFINE_SIMPLE_ATTRIBUTE(adis16460_serial_number_fops,
 91	adis16460_show_serial_number, NULL, "0x%.4llx\n");
 92
 93static int adis16460_show_product_id(void *arg, u64 *val)
 94{
 95	struct adis16460 *adis16460 = arg;
 96	u16 prod_id;
 97	int ret;
 98
 99	ret = adis_read_reg_16(&adis16460->adis, ADIS16460_REG_PROD_ID,
100		&prod_id);
101	if (ret < 0)
102		return ret;
103
104	*val = prod_id;
105
106	return 0;
107}
108DEFINE_SIMPLE_ATTRIBUTE(adis16460_product_id_fops,
109	adis16460_show_product_id, NULL, "%llu\n");
110
111static int adis16460_show_flash_count(void *arg, u64 *val)
112{
113	struct adis16460 *adis16460 = arg;
114	u32 flash_count;
115	int ret;
116
117	ret = adis_read_reg_32(&adis16460->adis, ADIS16460_REG_FLASH_CNT,
118		&flash_count);
119	if (ret < 0)
120		return ret;
121
122	*val = flash_count;
123
124	return 0;
125}
126DEFINE_SIMPLE_ATTRIBUTE(adis16460_flash_count_fops,
127	adis16460_show_flash_count, NULL, "%lld\n");
128
129static int adis16460_debugfs_init(struct iio_dev *indio_dev)
130{
131	struct adis16460 *adis16460 = iio_priv(indio_dev);
 
132
133	debugfs_create_file("serial_number", 0400, indio_dev->debugfs_dentry,
134		adis16460, &adis16460_serial_number_fops);
135	debugfs_create_file("product_id", 0400, indio_dev->debugfs_dentry,
136		adis16460, &adis16460_product_id_fops);
137	debugfs_create_file("flash_count", 0400, indio_dev->debugfs_dentry,
138		adis16460, &adis16460_flash_count_fops);
139
140	return 0;
141}
142
143#else
144
145static int adis16460_debugfs_init(struct iio_dev *indio_dev)
146{
147	return 0;
148}
149
150#endif
151
152static int adis16460_set_freq(struct iio_dev *indio_dev, int val, int val2)
153{
154	struct adis16460 *st = iio_priv(indio_dev);
155	int t;
156
157	t =  val * 1000 + val2 / 1000;
158	if (t <= 0)
159		return -EINVAL;
160
161	t = 2048000 / t;
162	if (t > 2048)
163		t = 2048;
164
165	if (t != 0)
166		t--;
167
168	return adis_write_reg_16(&st->adis, ADIS16460_REG_DEC_RATE, t);
169}
170
171static int adis16460_get_freq(struct iio_dev *indio_dev, int *val, int *val2)
172{
173	struct adis16460 *st = iio_priv(indio_dev);
174	uint16_t t;
175	int ret;
176	unsigned int freq;
177
178	ret = adis_read_reg_16(&st->adis, ADIS16460_REG_DEC_RATE, &t);
179	if (ret < 0)
180		return ret;
181
182	freq = 2048000 / (t + 1);
183	*val = freq / 1000;
184	*val2 = (freq % 1000) * 1000;
185
186	return IIO_VAL_INT_PLUS_MICRO;
187}
188
189static int adis16460_read_raw(struct iio_dev *indio_dev,
190	const struct iio_chan_spec *chan, int *val, int *val2, long info)
191{
192	struct adis16460 *st = iio_priv(indio_dev);
193
194	switch (info) {
195	case IIO_CHAN_INFO_RAW:
196		return adis_single_conversion(indio_dev, chan, 0, val);
197	case IIO_CHAN_INFO_SCALE:
198		switch (chan->type) {
199		case IIO_ANGL_VEL:
200			*val = st->chip_info->gyro_max_scale;
201			*val2 = st->chip_info->gyro_max_val;
202			return IIO_VAL_FRACTIONAL;
203		case IIO_ACCEL:
204			*val = st->chip_info->accel_max_scale;
205			*val2 = st->chip_info->accel_max_val;
206			return IIO_VAL_FRACTIONAL;
207		case IIO_TEMP:
208			*val = 50; /* 50 milli degrees Celsius/LSB */
209			return IIO_VAL_INT;
210		default:
211			return -EINVAL;
212		}
213	case IIO_CHAN_INFO_OFFSET:
214		*val = 500; /* 25 degrees Celsius = 0x0000 */
215		return IIO_VAL_INT;
216	case IIO_CHAN_INFO_SAMP_FREQ:
217		return adis16460_get_freq(indio_dev, val, val2);
218	default:
219		return -EINVAL;
220	}
221}
222
223static int adis16460_write_raw(struct iio_dev *indio_dev,
224	const struct iio_chan_spec *chan, int val, int val2, long info)
225{
226	switch (info) {
227	case IIO_CHAN_INFO_SAMP_FREQ:
228		return adis16460_set_freq(indio_dev, val, val2);
229	default:
230		return -EINVAL;
231	}
232}
233
234enum {
235	ADIS16460_SCAN_GYRO_X,
236	ADIS16460_SCAN_GYRO_Y,
237	ADIS16460_SCAN_GYRO_Z,
238	ADIS16460_SCAN_ACCEL_X,
239	ADIS16460_SCAN_ACCEL_Y,
240	ADIS16460_SCAN_ACCEL_Z,
241	ADIS16460_SCAN_TEMP,
242};
243
244#define ADIS16460_MOD_CHANNEL(_type, _mod, _address, _si, _bits) \
245	{ \
246		.type = (_type), \
247		.modified = 1, \
248		.channel2 = (_mod), \
249		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
250		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
251		.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
252		.address = (_address), \
253		.scan_index = (_si), \
254		.scan_type = { \
255			.sign = 's', \
256			.realbits = (_bits), \
257			.storagebits = (_bits), \
258			.endianness = IIO_BE, \
259		}, \
260	}
261
262#define ADIS16460_GYRO_CHANNEL(_mod) \
263	ADIS16460_MOD_CHANNEL(IIO_ANGL_VEL, IIO_MOD_ ## _mod, \
264	ADIS16460_REG_ ## _mod ## _GYRO_LOW, ADIS16460_SCAN_GYRO_ ## _mod, \
265	32)
266
267#define ADIS16460_ACCEL_CHANNEL(_mod) \
268	ADIS16460_MOD_CHANNEL(IIO_ACCEL, IIO_MOD_ ## _mod, \
269	ADIS16460_REG_ ## _mod ## _ACCL_LOW, ADIS16460_SCAN_ACCEL_ ## _mod, \
270	32)
271
272#define ADIS16460_TEMP_CHANNEL() { \
273		.type = IIO_TEMP, \
274		.indexed = 1, \
275		.channel = 0, \
276		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
277			BIT(IIO_CHAN_INFO_SCALE) | \
278			BIT(IIO_CHAN_INFO_OFFSET), \
279		.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
280		.address = ADIS16460_REG_TEMP_OUT, \
281		.scan_index = ADIS16460_SCAN_TEMP, \
282		.scan_type = { \
283			.sign = 's', \
284			.realbits = 16, \
285			.storagebits = 16, \
286			.endianness = IIO_BE, \
287		}, \
288	}
289
290static const struct iio_chan_spec adis16460_channels[] = {
291	ADIS16460_GYRO_CHANNEL(X),
292	ADIS16460_GYRO_CHANNEL(Y),
293	ADIS16460_GYRO_CHANNEL(Z),
294	ADIS16460_ACCEL_CHANNEL(X),
295	ADIS16460_ACCEL_CHANNEL(Y),
296	ADIS16460_ACCEL_CHANNEL(Z),
297	ADIS16460_TEMP_CHANNEL(),
298	IIO_CHAN_SOFT_TIMESTAMP(7)
299};
300
301static const struct adis16460_chip_info adis16460_chip_info = {
302	.channels = adis16460_channels,
303	.num_channels = ARRAY_SIZE(adis16460_channels),
304	/*
305	 * storing the value in rad/degree and the scale in degree
306	 * gives us the result in rad and better precession than
307	 * storing the scale directly in rad.
308	 */
309	.gyro_max_val = IIO_RAD_TO_DEGREE(200 << 16),
310	.gyro_max_scale = 1,
311	.accel_max_val = IIO_M_S_2_TO_G(20000 << 16),
312	.accel_max_scale = 5,
313};
314
315static const struct iio_info adis16460_info = {
316	.read_raw = &adis16460_read_raw,
317	.write_raw = &adis16460_write_raw,
318	.update_scan_mode = adis_update_scan_mode,
319	.debugfs_reg_access = adis_debugfs_reg_access,
320};
321
322static int adis16460_enable_irq(struct adis *adis, bool enable)
323{
324	/*
325	 * There is no way to gate the data-ready signal internally inside the
326	 * ADIS16460 :(
327	 */
328	if (enable)
329		enable_irq(adis->spi->irq);
330	else
331		disable_irq(adis->spi->irq);
332
333	return 0;
334}
335
336static int adis16460_initial_setup(struct iio_dev *indio_dev)
337{
338	struct adis16460 *st = iio_priv(indio_dev);
339	uint16_t prod_id;
340	unsigned int device_id;
341	int ret;
342
343	adis_reset(&st->adis);
344	msleep(222);
345
346	ret = adis_write_reg_16(&st->adis, ADIS16460_REG_GLOB_CMD, BIT(1));
347	if (ret)
348		return ret;
349	msleep(75);
350
351	ret = adis_check_status(&st->adis);
352	if (ret)
353		return ret;
354
355	ret = adis_read_reg_16(&st->adis, ADIS16460_REG_PROD_ID, &prod_id);
356	if (ret)
357		return ret;
358
359	ret = sscanf(indio_dev->name, "adis%u\n", &device_id);
360	if (ret != 1)
361		return -EINVAL;
362
363	if (prod_id != device_id)
364		dev_warn(&indio_dev->dev, "Device ID(%u) and product ID(%u) do not match.",
365				device_id, prod_id);
366
367	return 0;
368}
369
370#define ADIS16460_DIAG_STAT_IN_CLK_OOS	7
371#define ADIS16460_DIAG_STAT_FLASH_MEM	6
372#define ADIS16460_DIAG_STAT_SELF_TEST	5
373#define ADIS16460_DIAG_STAT_OVERRANGE	4
374#define ADIS16460_DIAG_STAT_SPI_COMM	3
375#define ADIS16460_DIAG_STAT_FLASH_UPT	2
376
377static const char * const adis16460_status_error_msgs[] = {
378	[ADIS16460_DIAG_STAT_IN_CLK_OOS] = "Input clock out of sync",
379	[ADIS16460_DIAG_STAT_FLASH_MEM] = "Flash memory failure",
380	[ADIS16460_DIAG_STAT_SELF_TEST] = "Self test diagnostic failure",
381	[ADIS16460_DIAG_STAT_OVERRANGE] = "Sensor overrange",
382	[ADIS16460_DIAG_STAT_SPI_COMM] = "SPI communication failure",
383	[ADIS16460_DIAG_STAT_FLASH_UPT] = "Flash update failure",
384};
385
 
 
 
 
 
 
386static const struct adis_data adis16460_data = {
387	.diag_stat_reg = ADIS16460_REG_DIAG_STAT,
388	.glob_cmd_reg = ADIS16460_REG_GLOB_CMD,
 
 
 
 
389	.has_paging = false,
390	.read_delay = 5,
391	.write_delay = 5,
392	.cs_change_delay = 16,
393	.status_error_msgs = adis16460_status_error_msgs,
394	.status_error_mask = BIT(ADIS16460_DIAG_STAT_IN_CLK_OOS) |
395		BIT(ADIS16460_DIAG_STAT_FLASH_MEM) |
396		BIT(ADIS16460_DIAG_STAT_SELF_TEST) |
397		BIT(ADIS16460_DIAG_STAT_OVERRANGE) |
398		BIT(ADIS16460_DIAG_STAT_SPI_COMM) |
399		BIT(ADIS16460_DIAG_STAT_FLASH_UPT),
400	.enable_irq = adis16460_enable_irq,
 
401};
402
403static int adis16460_probe(struct spi_device *spi)
404{
405	struct iio_dev *indio_dev;
406	struct adis16460 *st;
407	int ret;
408
409	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
410	if (indio_dev == NULL)
411		return -ENOMEM;
412
413	spi_set_drvdata(spi, indio_dev);
414
415	st = iio_priv(indio_dev);
416
417	st->chip_info = &adis16460_chip_info;
418	indio_dev->dev.parent = &spi->dev;
419	indio_dev->name = spi_get_device_id(spi)->name;
420	indio_dev->channels = st->chip_info->channels;
421	indio_dev->num_channels = st->chip_info->num_channels;
422	indio_dev->info = &adis16460_info;
423	indio_dev->modes = INDIO_DIRECT_MODE;
424
425	ret = adis_init(&st->adis, indio_dev, spi, &adis16460_data);
426	if (ret)
427		return ret;
428
429	ret = adis_setup_buffer_and_trigger(&st->adis, indio_dev, NULL);
430	if (ret)
431		return ret;
432
433	adis16460_enable_irq(&st->adis, 0);
434
435	ret = adis16460_initial_setup(indio_dev);
436	if (ret)
437		goto error_cleanup_buffer;
438
439	ret = iio_device_register(indio_dev);
440	if (ret)
441		goto error_cleanup_buffer;
442
443	adis16460_debugfs_init(indio_dev);
444
445	return 0;
446
447error_cleanup_buffer:
448	adis_cleanup_buffer_and_trigger(&st->adis, indio_dev);
449	return ret;
450}
451
452static int adis16460_remove(struct spi_device *spi)
453{
454	struct iio_dev *indio_dev = spi_get_drvdata(spi);
455	struct adis16460 *st = iio_priv(indio_dev);
456
457	iio_device_unregister(indio_dev);
458
459	adis_cleanup_buffer_and_trigger(&st->adis, indio_dev);
460
461	return 0;
462}
463
464static const struct spi_device_id adis16460_ids[] = {
465	{ "adis16460", 0 },
466	{}
467};
468MODULE_DEVICE_TABLE(spi, adis16460_ids);
469
470static const struct of_device_id adis16460_of_match[] = {
471	{ .compatible = "adi,adis16460" },
472	{}
473};
474MODULE_DEVICE_TABLE(of, adis16460_of_match);
475
476static struct spi_driver adis16460_driver = {
477	.driver = {
478		.name = "adis16460",
479		.of_match_table = adis16460_of_match,
480	},
481	.id_table = adis16460_ids,
482	.probe = adis16460_probe,
483	.remove = adis16460_remove,
484};
485module_spi_driver(adis16460_driver);
486
487MODULE_AUTHOR("Dragos Bogdan <dragos.bogdan@analog.com>");
488MODULE_DESCRIPTION("Analog Devices ADIS16460 IMU driver");
489MODULE_LICENSE("GPL");