brintos

brintos / linux-shallow public Read only

0
0
Text · 17.4 KiB · 600e972 Raw
709 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * ADXRS290 SPI Gyroscope Driver4 *5 * Copyright (C) 2020 Nishant Malpani <nish.malpani25@gmail.com>6 * Copyright (C) 2020 Analog Devices, Inc.7 */8 9#include <linux/bitfield.h>10#include <linux/bitops.h>11#include <linux/delay.h>12#include <linux/device.h>13#include <linux/kernel.h>14#include <linux/module.h>15#include <linux/spi/spi.h>16 17#include <linux/iio/buffer.h>18#include <linux/iio/iio.h>19#include <linux/iio/sysfs.h>20#include <linux/iio/trigger.h>21#include <linux/iio/triggered_buffer.h>22#include <linux/iio/trigger_consumer.h>23 24#define ADXRS290_ADI_ID		0xAD25#define ADXRS290_MEMS_ID	0x1D26#define ADXRS290_DEV_ID		0x9227 28#define ADXRS290_REG_ADI_ID	0x0029#define ADXRS290_REG_MEMS_ID	0x0130#define ADXRS290_REG_DEV_ID	0x0231#define ADXRS290_REG_REV_ID	0x0332#define ADXRS290_REG_SN0	0x04 /* Serial Number Registers, 4 bytes */33#define ADXRS290_REG_DATAX0	0x08 /* Roll Rate o/p Data Regs, 2 bytes */34#define ADXRS290_REG_DATAY0	0x0A /* Pitch Rate o/p Data Regs, 2 bytes */35#define ADXRS290_REG_TEMP0	0x0C36#define ADXRS290_REG_POWER_CTL	0x1037#define ADXRS290_REG_FILTER	0x1138#define ADXRS290_REG_DATA_RDY	0x1239 40#define ADXRS290_READ		BIT(7)41#define ADXRS290_TSM		BIT(0)42#define ADXRS290_MEASUREMENT	BIT(1)43#define ADXRS290_DATA_RDY_OUT	BIT(0)44#define ADXRS290_SYNC_MASK	GENMASK(1, 0)45#define ADXRS290_SYNC(x)	FIELD_PREP(ADXRS290_SYNC_MASK, x)46#define ADXRS290_LPF_MASK	GENMASK(2, 0)47#define ADXRS290_LPF(x)		FIELD_PREP(ADXRS290_LPF_MASK, x)48#define ADXRS290_HPF_MASK	GENMASK(7, 4)49#define ADXRS290_HPF(x)		FIELD_PREP(ADXRS290_HPF_MASK, x)50 51#define ADXRS290_READ_REG(reg)	(ADXRS290_READ | (reg))52 53#define ADXRS290_MAX_TRANSITION_TIME_MS 10054 55enum adxrs290_mode {56	ADXRS290_MODE_STANDBY,57	ADXRS290_MODE_MEASUREMENT,58};59 60enum adxrs290_scan_index {61	ADXRS290_IDX_X,62	ADXRS290_IDX_Y,63	ADXRS290_IDX_TEMP,64	ADXRS290_IDX_TS,65};66 67struct adxrs290_state {68	struct spi_device	*spi;69	/* Serialize reads and their subsequent processing */70	struct mutex		lock;71	enum adxrs290_mode	mode;72	unsigned int		lpf_3db_freq_idx;73	unsigned int		hpf_3db_freq_idx;74	struct iio_trigger      *dready_trig;75	/* Ensure correct alignment of timestamp when present */76	struct {77		s16 channels[3];78		s64 ts __aligned(8);79	} buffer;80};81 82/*83 * Available cut-off frequencies of the low pass filter in Hz.84 * The integer part and fractional part are represented separately.85 */86static const int adxrs290_lpf_3db_freq_hz_table[][2] = {87	[0] = {480, 0},88	[1] = {320, 0},89	[2] = {160, 0},90	[3] = {80, 0},91	[4] = {56, 600000},92	[5] = {40, 0},93	[6] = {28, 300000},94	[7] = {20, 0},95};96 97/*98 * Available cut-off frequencies of the high pass filter in Hz.99 * The integer part and fractional part are represented separately.100 */101static const int adxrs290_hpf_3db_freq_hz_table[][2] = {102	[0] = {0, 0},103	[1] = {0, 11000},104	[2] = {0, 22000},105	[3] = {0, 44000},106	[4] = {0, 87000},107	[5] = {0, 175000},108	[6] = {0, 350000},109	[7] = {0, 700000},110	[8] = {1, 400000},111	[9] = {2, 800000},112	[10] = {11, 300000},113};114 115static int adxrs290_get_rate_data(struct iio_dev *indio_dev, const u8 cmd, int *val)116{117	struct adxrs290_state *st = iio_priv(indio_dev);118	int ret = 0;119	int temp;120 121	mutex_lock(&st->lock);122	temp = spi_w8r16(st->spi, cmd);123	if (temp < 0) {124		ret = temp;125		goto err_unlock;126	}127 128	*val = sign_extend32(temp, 15);129 130err_unlock:131	mutex_unlock(&st->lock);132	return ret;133}134 135static int adxrs290_get_temp_data(struct iio_dev *indio_dev, int *val)136{137	const u8 cmd = ADXRS290_READ_REG(ADXRS290_REG_TEMP0);138	struct adxrs290_state *st = iio_priv(indio_dev);139	int ret = 0;140	int temp;141 142	mutex_lock(&st->lock);143	temp = spi_w8r16(st->spi, cmd);144	if (temp < 0) {145		ret = temp;146		goto err_unlock;147	}148 149	/* extract lower 12 bits temperature reading */150	*val = sign_extend32(temp, 11);151 152err_unlock:153	mutex_unlock(&st->lock);154	return ret;155}156 157static int adxrs290_get_3db_freq(struct iio_dev *indio_dev, u8 *val, u8 *val2)158{159	const u8 cmd = ADXRS290_READ_REG(ADXRS290_REG_FILTER);160	struct adxrs290_state *st = iio_priv(indio_dev);161	int ret = 0;162	short temp;163 164	mutex_lock(&st->lock);165	temp = spi_w8r8(st->spi, cmd);166	if (temp < 0) {167		ret = temp;168		goto err_unlock;169	}170 171	*val = FIELD_GET(ADXRS290_LPF_MASK, temp);172	*val2 = FIELD_GET(ADXRS290_HPF_MASK, temp);173 174err_unlock:175	mutex_unlock(&st->lock);176	return ret;177}178 179static int adxrs290_spi_write_reg(struct spi_device *spi, const u8 reg,180				  const u8 val)181{182	u8 buf[2];183 184	buf[0] = reg;185	buf[1] = val;186 187	return spi_write_then_read(spi, buf, ARRAY_SIZE(buf), NULL, 0);188}189 190static int adxrs290_find_match(const int (*freq_tbl)[2], const int n,191			       const int val, const int val2)192{193	int i;194 195	for (i = 0; i < n; i++) {196		if (freq_tbl[i][0] == val && freq_tbl[i][1] == val2)197			return i;198	}199 200	return -EINVAL;201}202 203static int adxrs290_set_filter_freq(struct iio_dev *indio_dev,204				    const unsigned int lpf_idx,205				    const unsigned int hpf_idx)206{207	struct adxrs290_state *st = iio_priv(indio_dev);208	u8 val;209 210	val = ADXRS290_HPF(hpf_idx) | ADXRS290_LPF(lpf_idx);211 212	return adxrs290_spi_write_reg(st->spi, ADXRS290_REG_FILTER, val);213}214 215static int adxrs290_set_mode(struct iio_dev *indio_dev, enum adxrs290_mode mode)216{217	struct adxrs290_state *st = iio_priv(indio_dev);218	int val, ret;219 220	if (st->mode == mode)221		return 0;222 223	mutex_lock(&st->lock);224 225	ret = spi_w8r8(st->spi, ADXRS290_READ_REG(ADXRS290_REG_POWER_CTL));226	if (ret < 0)227		goto out_unlock;228 229	val = ret;230 231	switch (mode) {232	case ADXRS290_MODE_STANDBY:233		val &= ~ADXRS290_MEASUREMENT;234		break;235	case ADXRS290_MODE_MEASUREMENT:236		val |= ADXRS290_MEASUREMENT;237		break;238	default:239		ret = -EINVAL;240		goto out_unlock;241	}242 243	ret = adxrs290_spi_write_reg(st->spi, ADXRS290_REG_POWER_CTL, val);244	if (ret < 0) {245		dev_err(&st->spi->dev, "unable to set mode: %d\n", ret);246		goto out_unlock;247	}248 249	/* update cached mode */250	st->mode = mode;251 252out_unlock:253	mutex_unlock(&st->lock);254	return ret;255}256 257static void adxrs290_chip_off_action(void *data)258{259	struct iio_dev *indio_dev = data;260 261	adxrs290_set_mode(indio_dev, ADXRS290_MODE_STANDBY);262}263 264static int adxrs290_initial_setup(struct iio_dev *indio_dev)265{266	struct adxrs290_state *st = iio_priv(indio_dev);267	struct spi_device *spi = st->spi;268	int ret;269 270	ret = adxrs290_spi_write_reg(spi, ADXRS290_REG_POWER_CTL,271				     ADXRS290_MEASUREMENT | ADXRS290_TSM);272	if (ret < 0)273		return ret;274 275	st->mode = ADXRS290_MODE_MEASUREMENT;276 277	return devm_add_action_or_reset(&spi->dev, adxrs290_chip_off_action,278					indio_dev);279}280 281static int adxrs290_read_raw(struct iio_dev *indio_dev,282			     struct iio_chan_spec const *chan,283			     int *val,284			     int *val2,285			     long mask)286{287	struct adxrs290_state *st = iio_priv(indio_dev);288	unsigned int t;289	int ret;290 291	switch (mask) {292	case IIO_CHAN_INFO_RAW:293		ret = iio_device_claim_direct_mode(indio_dev);294		if (ret)295			return ret;296 297		switch (chan->type) {298		case IIO_ANGL_VEL:299			ret = adxrs290_get_rate_data(indio_dev,300						     ADXRS290_READ_REG(chan->address),301						     val);302			if (ret < 0)303				break;304 305			ret = IIO_VAL_INT;306			break;307		case IIO_TEMP:308			ret = adxrs290_get_temp_data(indio_dev, val);309			if (ret < 0)310				break;311 312			ret = IIO_VAL_INT;313			break;314		default:315			ret = -EINVAL;316			break;317		}318 319		iio_device_release_direct_mode(indio_dev);320		return ret;321	case IIO_CHAN_INFO_SCALE:322		switch (chan->type) {323		case IIO_ANGL_VEL:324			/* 1 LSB = 0.005 degrees/sec */325			*val = 0;326			*val2 = 87266;327			return IIO_VAL_INT_PLUS_NANO;328		case IIO_TEMP:329			/* 1 LSB = 0.1 degrees Celsius */330			*val = 100;331			return IIO_VAL_INT;332		default:333			return -EINVAL;334		}335	case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:336		switch (chan->type) {337		case IIO_ANGL_VEL:338			t = st->lpf_3db_freq_idx;339			*val = adxrs290_lpf_3db_freq_hz_table[t][0];340			*val2 = adxrs290_lpf_3db_freq_hz_table[t][1];341			return IIO_VAL_INT_PLUS_MICRO;342		default:343			return -EINVAL;344		}345	case IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY:346		switch (chan->type) {347		case IIO_ANGL_VEL:348			t = st->hpf_3db_freq_idx;349			*val = adxrs290_hpf_3db_freq_hz_table[t][0];350			*val2 = adxrs290_hpf_3db_freq_hz_table[t][1];351			return IIO_VAL_INT_PLUS_MICRO;352		default:353			return -EINVAL;354		}355	}356 357	return -EINVAL;358}359 360static int adxrs290_write_raw(struct iio_dev *indio_dev,361			      struct iio_chan_spec const *chan,362			      int val,363			      int val2,364			      long mask)365{366	struct adxrs290_state *st = iio_priv(indio_dev);367	int ret, lpf_idx, hpf_idx;368 369	ret = iio_device_claim_direct_mode(indio_dev);370	if (ret)371		return ret;372 373	switch (mask) {374	case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:375		lpf_idx = adxrs290_find_match(adxrs290_lpf_3db_freq_hz_table,376					      ARRAY_SIZE(adxrs290_lpf_3db_freq_hz_table),377					      val, val2);378		if (lpf_idx < 0) {379			ret = -EINVAL;380			break;381		}382 383		/* caching the updated state of the low-pass filter */384		st->lpf_3db_freq_idx = lpf_idx;385		/* retrieving the current state of the high-pass filter */386		hpf_idx = st->hpf_3db_freq_idx;387		ret = adxrs290_set_filter_freq(indio_dev, lpf_idx, hpf_idx);388		break;389 390	case IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY:391		hpf_idx = adxrs290_find_match(adxrs290_hpf_3db_freq_hz_table,392					      ARRAY_SIZE(adxrs290_hpf_3db_freq_hz_table),393					      val, val2);394		if (hpf_idx < 0) {395			ret = -EINVAL;396			break;397		}398 399		/* caching the updated state of the high-pass filter */400		st->hpf_3db_freq_idx = hpf_idx;401		/* retrieving the current state of the low-pass filter */402		lpf_idx = st->lpf_3db_freq_idx;403		ret = adxrs290_set_filter_freq(indio_dev, lpf_idx, hpf_idx);404		break;405 406	default:407		ret = -EINVAL;408		break;409	}410 411	iio_device_release_direct_mode(indio_dev);412	return ret;413}414 415static int adxrs290_read_avail(struct iio_dev *indio_dev,416			       struct iio_chan_spec const *chan,417			       const int **vals, int *type, int *length,418			       long mask)419{420	switch (mask) {421	case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:422		*vals = (const int *)adxrs290_lpf_3db_freq_hz_table;423		*type = IIO_VAL_INT_PLUS_MICRO;424		/* Values are stored in a 2D matrix */425		*length = ARRAY_SIZE(adxrs290_lpf_3db_freq_hz_table) * 2;426 427		return IIO_AVAIL_LIST;428	case IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY:429		*vals = (const int *)adxrs290_hpf_3db_freq_hz_table;430		*type = IIO_VAL_INT_PLUS_MICRO;431		/* Values are stored in a 2D matrix */432		*length = ARRAY_SIZE(adxrs290_hpf_3db_freq_hz_table) * 2;433 434		return IIO_AVAIL_LIST;435	default:436		return -EINVAL;437	}438}439 440static int adxrs290_reg_access_rw(struct spi_device *spi, unsigned int reg,441				  unsigned int *readval)442{443	int ret;444 445	ret = spi_w8r8(spi, ADXRS290_READ_REG(reg));446	if (ret < 0)447		return ret;448 449	*readval = ret;450 451	return 0;452}453 454static int adxrs290_reg_access(struct iio_dev *indio_dev, unsigned int reg,455			       unsigned int writeval, unsigned int *readval)456{457	struct adxrs290_state *st = iio_priv(indio_dev);458 459	if (readval)460		return adxrs290_reg_access_rw(st->spi, reg, readval);461	else462		return adxrs290_spi_write_reg(st->spi, reg, writeval);463}464 465static int adxrs290_data_rdy_trigger_set_state(struct iio_trigger *trig,466					       bool state)467{468	struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);469	struct adxrs290_state *st = iio_priv(indio_dev);470	int ret;471	u8 val;472 473	val = state ? ADXRS290_SYNC(ADXRS290_DATA_RDY_OUT) : 0;474 475	ret = adxrs290_spi_write_reg(st->spi, ADXRS290_REG_DATA_RDY, val);476	if (ret < 0)477		dev_err(&st->spi->dev, "failed to start data rdy interrupt\n");478 479	return ret;480}481 482static void adxrs290_reset_trig(struct iio_trigger *trig)483{484	struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);485	int val;486 487	/*488	 * Data ready interrupt is reset after a read of the data registers.489	 * Here, we only read the 16b DATAY registers as that marks the end of490	 * a read of the data registers and initiates a reset for the interrupt491	 * line.492	 */493	adxrs290_get_rate_data(indio_dev,494			       ADXRS290_READ_REG(ADXRS290_REG_DATAY0), &val);495}496 497static const struct iio_trigger_ops adxrs290_trigger_ops = {498	.set_trigger_state = &adxrs290_data_rdy_trigger_set_state,499	.validate_device = &iio_trigger_validate_own_device,500	.reenable = &adxrs290_reset_trig,501};502 503static irqreturn_t adxrs290_trigger_handler(int irq, void *p)504{505	struct iio_poll_func *pf = p;506	struct iio_dev *indio_dev = pf->indio_dev;507	struct adxrs290_state *st = iio_priv(indio_dev);508	u8 tx = ADXRS290_READ_REG(ADXRS290_REG_DATAX0);509	int ret;510 511	mutex_lock(&st->lock);512 513	/* exercise a bulk data capture starting from reg DATAX0... */514	ret = spi_write_then_read(st->spi, &tx, sizeof(tx), st->buffer.channels,515				  sizeof(st->buffer.channels));516	if (ret < 0)517		goto out_unlock_notify;518 519	iio_push_to_buffers_with_timestamp(indio_dev, &st->buffer,520					   pf->timestamp);521 522out_unlock_notify:523	mutex_unlock(&st->lock);524	iio_trigger_notify_done(indio_dev->trig);525 526	return IRQ_HANDLED;527}528 529#define ADXRS290_ANGL_VEL_CHANNEL(reg, axis) {				\530	.type = IIO_ANGL_VEL,						\531	.address = reg,							\532	.modified = 1,							\533	.channel2 = IIO_MOD_##axis,					\534	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),			\535	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |		\536	BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY) |		\537	BIT(IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY),		\538	.info_mask_shared_by_type_available =				\539	BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY) |		\540	BIT(IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY),		\541	.scan_index = ADXRS290_IDX_##axis,				\542	.scan_type = {                                                  \543		.sign = 's',                                            \544		.realbits = 16,                                         \545		.storagebits = 16,                                      \546		.endianness = IIO_LE,					\547	},                                                              \548}549 550static const struct iio_chan_spec adxrs290_channels[] = {551	ADXRS290_ANGL_VEL_CHANNEL(ADXRS290_REG_DATAX0, X),552	ADXRS290_ANGL_VEL_CHANNEL(ADXRS290_REG_DATAY0, Y),553	{554		.type = IIO_TEMP,555		.address = ADXRS290_REG_TEMP0,556		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |557		BIT(IIO_CHAN_INFO_SCALE),558		.scan_index = ADXRS290_IDX_TEMP,559		.scan_type = {560			.sign = 's',561			.realbits = 12,562			.storagebits = 16,563			.endianness = IIO_LE,564		},565	},566	IIO_CHAN_SOFT_TIMESTAMP(ADXRS290_IDX_TS),567};568 569static const unsigned long adxrs290_avail_scan_masks[] = {570	BIT(ADXRS290_IDX_X) | BIT(ADXRS290_IDX_Y) | BIT(ADXRS290_IDX_TEMP),571	0572};573 574static const struct iio_info adxrs290_info = {575	.read_raw = &adxrs290_read_raw,576	.write_raw = &adxrs290_write_raw,577	.read_avail = &adxrs290_read_avail,578	.debugfs_reg_access = &adxrs290_reg_access,579};580 581static int adxrs290_probe_trigger(struct iio_dev *indio_dev)582{583	struct adxrs290_state *st = iio_priv(indio_dev);584	int ret;585 586	if (!st->spi->irq) {587		dev_info(&st->spi->dev, "no irq, using polling\n");588		return 0;589	}590 591	st->dready_trig = devm_iio_trigger_alloc(&st->spi->dev, "%s-dev%d",592						 indio_dev->name,593						 iio_device_id(indio_dev));594	if (!st->dready_trig)595		return -ENOMEM;596 597	st->dready_trig->ops = &adxrs290_trigger_ops;598	iio_trigger_set_drvdata(st->dready_trig, indio_dev);599 600	ret = devm_request_irq(&st->spi->dev, st->spi->irq,601			       &iio_trigger_generic_data_rdy_poll,602			       IRQF_ONESHOT, "adxrs290_irq", st->dready_trig);603	if (ret < 0)604		return dev_err_probe(&st->spi->dev, ret,605				     "request irq %d failed\n", st->spi->irq);606 607	ret = devm_iio_trigger_register(&st->spi->dev, st->dready_trig);608	if (ret) {609		dev_err(&st->spi->dev, "iio trigger register failed\n");610		return ret;611	}612 613	indio_dev->trig = iio_trigger_get(st->dready_trig);614 615	return 0;616}617 618static int adxrs290_probe(struct spi_device *spi)619{620	struct iio_dev *indio_dev;621	struct adxrs290_state *st;622	u8 val, val2;623	int ret;624 625	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));626	if (!indio_dev)627		return -ENOMEM;628 629	st = iio_priv(indio_dev);630	st->spi = spi;631 632	indio_dev->name = "adxrs290";633	indio_dev->modes = INDIO_DIRECT_MODE;634	indio_dev->channels = adxrs290_channels;635	indio_dev->num_channels = ARRAY_SIZE(adxrs290_channels);636	indio_dev->info = &adxrs290_info;637	indio_dev->available_scan_masks = adxrs290_avail_scan_masks;638 639	mutex_init(&st->lock);640 641	val = spi_w8r8(spi, ADXRS290_READ_REG(ADXRS290_REG_ADI_ID));642	if (val != ADXRS290_ADI_ID) {643		dev_err(&spi->dev, "Wrong ADI ID 0x%02x\n", val);644		return -ENODEV;645	}646 647	val = spi_w8r8(spi, ADXRS290_READ_REG(ADXRS290_REG_MEMS_ID));648	if (val != ADXRS290_MEMS_ID) {649		dev_err(&spi->dev, "Wrong MEMS ID 0x%02x\n", val);650		return -ENODEV;651	}652 653	val = spi_w8r8(spi, ADXRS290_READ_REG(ADXRS290_REG_DEV_ID));654	if (val != ADXRS290_DEV_ID) {655		dev_err(&spi->dev, "Wrong DEV ID 0x%02x\n", val);656		return -ENODEV;657	}658 659	/* default mode the gyroscope starts in */660	st->mode = ADXRS290_MODE_STANDBY;661 662	/* switch to measurement mode and switch on the temperature sensor */663	ret = adxrs290_initial_setup(indio_dev);664	if (ret < 0)665		return ret;666 667	/* max transition time to measurement mode */668	msleep(ADXRS290_MAX_TRANSITION_TIME_MS);669 670	ret = adxrs290_get_3db_freq(indio_dev, &val, &val2);671	if (ret < 0)672		return ret;673 674	st->lpf_3db_freq_idx = val;675	st->hpf_3db_freq_idx = val2;676 677	ret = devm_iio_triggered_buffer_setup(&spi->dev, indio_dev,678					      &iio_pollfunc_store_time,679					      &adxrs290_trigger_handler, NULL);680	if (ret < 0)681		return dev_err_probe(&spi->dev, ret,682				     "iio triggered buffer setup failed\n");683 684	ret = adxrs290_probe_trigger(indio_dev);685	if (ret < 0)686		return ret;687 688	return devm_iio_device_register(&spi->dev, indio_dev);689}690 691static const struct of_device_id adxrs290_of_match[] = {692	{ .compatible = "adi,adxrs290" },693	{ }694};695MODULE_DEVICE_TABLE(of, adxrs290_of_match);696 697static struct spi_driver adxrs290_driver = {698	.driver = {699		.name = "adxrs290",700		.of_match_table = adxrs290_of_match,701	},702	.probe = adxrs290_probe,703};704module_spi_driver(adxrs290_driver);705 706MODULE_AUTHOR("Nishant Malpani <nish.malpani25@gmail.com>");707MODULE_DESCRIPTION("Analog Devices ADXRS290 Gyroscope SPI driver");708MODULE_LICENSE("GPL");709