diff options
Diffstat (limited to 'drivers/iio/imu/adis16400.c')
| -rw-r--r-- | drivers/iio/imu/adis16400.c | 514 |
1 files changed, 233 insertions, 281 deletions
diff --git a/drivers/iio/imu/adis16400.c b/drivers/iio/imu/adis16400.c index 229f2ff98469..36323ad149e0 100644 --- a/drivers/iio/imu/adis16400.c +++ b/drivers/iio/imu/adis16400.c @@ -10,22 +10,15 @@ * Copyright (c) 2011 Analog Devices Inc. */ -#include <linux/interrupt.h> #include <linux/irq.h> -#include <linux/delay.h> -#include <linux/mutex.h> #include <linux/device.h> #include <linux/kernel.h> #include <linux/spi/spi.h> -#include <linux/slab.h> -#include <linux/sysfs.h> -#include <linux/list.h> #include <linux/module.h> #include <linux/debugfs.h> #include <linux/bitops.h> #include <linux/iio/iio.h> -#include <linux/iio/sysfs.h> #include <linux/iio/buffer.h> #include <linux/iio/trigger_consumer.h> #include <linux/iio/imu/adis.h> @@ -173,9 +166,11 @@ struct adis16400_chip_info { * @variant: chip variant info * @filt_int: integer part of requested filter frequency * @adis: adis device + * @avail_scan_mask: NULL terminated array of bitmaps of channels + * that must be enabled together **/ struct adis16400_state { - struct adis16400_chip_info *variant; + const struct adis16400_chip_info *variant; int filt_int; struct adis adis; @@ -207,8 +202,6 @@ enum { ADIS16400_SCAN_TIMESTAMP, }; -#ifdef CONFIG_DEBUG_FS - static ssize_t adis16400_show_serial_number(struct file *file, char __user *userbuf, size_t count, loff_t *ppos) { @@ -278,11 +271,14 @@ static int adis16400_show_flash_count(void *arg, u64 *val) DEFINE_DEBUGFS_ATTRIBUTE(adis16400_flash_count_fops, adis16400_show_flash_count, NULL, "%lld\n"); -static int adis16400_debugfs_init(struct iio_dev *indio_dev) +static void adis16400_debugfs_init(struct iio_dev *indio_dev) { struct adis16400_state *st = iio_priv(indio_dev); struct dentry *d = iio_get_debugfs_dentry(indio_dev); + if (!IS_ENABLED(CONFIG_DEBUG_FS)) + return; + if (st->variant->flags & ADIS16400_HAS_SERIAL_NUMBER) debugfs_create_file_unsafe("serial_number", 0400, d, st, &adis16400_serial_number_fops); @@ -291,37 +287,8 @@ static int adis16400_debugfs_init(struct iio_dev *indio_dev) d, st, &adis16400_product_id_fops); debugfs_create_file_unsafe("flash_count", 0400, d, st, &adis16400_flash_count_fops); - - return 0; } -#else - -static int adis16400_debugfs_init(struct iio_dev *indio_dev) -{ - return 0; -} - -#endif - -enum adis16400_chip_variant { - ADIS16300, - ADIS16334, - ADIS16350, - ADIS16360, - ADIS16362, - ADIS16364, - ADIS16367, - ADIS16400, - ADIS16445, - ADIS16448, -}; - -static struct adis_burst adis16400_burst = { - .en = true, - .reg_cmd = ADIS16400_GLOB_CMD, -}; - static int adis16334_get_freq(struct adis16400_state *st) { int ret; @@ -455,7 +422,7 @@ static int adis16400_initial_setup(struct iio_dev *indio_dev) st->adis.spi->mode = SPI_MODE_3; spi_setup(st->adis.spi); - ret = adis_initial_startup(&st->adis); + ret = __adis_initial_startup(&st->adis); if (ret) return ret; @@ -465,8 +432,7 @@ static int adis16400_initial_setup(struct iio_dev *indio_dev) if (ret) goto err_ret; - ret = sscanf(indio_dev->name, "adis%u\n", &device_id); - if (ret != 1) { + if (sscanf(indio_dev->name, "adis%u\n", &device_id) != 1) { ret = -EINVAL; goto err_ret; } @@ -477,7 +443,7 @@ static int adis16400_initial_setup(struct iio_dev *indio_dev) dev_info(&indio_dev->dev, "%s: prod_id 0x%04x at CS%d (irq %d)\n", indio_dev->name, prod_id, - st->adis.spi->chip_select, st->adis.spi->irq); + spi_get_chipselect(st->adis.spi, 0), st->adis.spi->irq); } /* use high spi speed if possible */ if (st->variant->flags & ADIS16400_HAS_SLOW_MODE) { @@ -508,42 +474,38 @@ static int adis16400_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int val, int val2, long info) { struct adis16400_state *st = iio_priv(indio_dev); - struct mutex *slock = &st->adis.state_lock; - int ret, sps; + int sps; switch (info) { case IIO_CHAN_INFO_CALIBBIAS: - ret = adis_write_reg_16(&st->adis, - adis16400_addresses[chan->scan_index], val); - return ret; + return adis_write_reg_16(&st->adis, + adis16400_addresses[chan->scan_index], + val); case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: /* * Need to cache values so we can update if the frequency * changes. */ - mutex_lock(slock); - st->filt_int = val; - /* Work out update to current value */ - sps = st->variant->get_freq(st); - if (sps < 0) { - mutex_unlock(slock); - return sps; + adis_dev_auto_scoped_lock(&st->adis) { + st->filt_int = val; + /* Work out update to current value */ + sps = st->variant->get_freq(st); + if (sps < 0) + return sps; + + return __adis16400_set_filter(indio_dev, sps, + val * 1000 + val2 / 1000); } - - ret = __adis16400_set_filter(indio_dev, sps, - val * 1000 + val2 / 1000); - mutex_unlock(slock); - return ret; + unreachable(); case IIO_CHAN_INFO_SAMP_FREQ: sps = val * 1000 + val2 / 1000; if (sps <= 0) return -EINVAL; - mutex_lock(slock); - ret = st->variant->set_freq(st, sps); - mutex_unlock(slock); - return ret; + adis_dev_auto_scoped_lock(&st->adis) + return st->variant->set_freq(st, sps); + unreachable(); default: return -EINVAL; } @@ -553,7 +515,6 @@ static int adis16400_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long info) { struct adis16400_state *st = iio_priv(indio_dev); - struct mutex *slock = &st->adis.state_lock; int16_t val16; int ret; @@ -609,29 +570,30 @@ static int adis16400_read_raw(struct iio_dev *indio_dev, *val = st->variant->temp_offset; return IIO_VAL_INT; case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: - mutex_lock(slock); - /* Need both the number of taps and the sampling frequency */ - ret = __adis_read_reg_16(&st->adis, - ADIS16400_SENS_AVG, - &val16); - if (ret) { - mutex_unlock(slock); - return ret; + adis_dev_auto_scoped_lock(&st->adis) { + /* + * Need both the number of taps and the sampling + * frequency + */ + ret = __adis_read_reg_16(&st->adis, ADIS16400_SENS_AVG, + &val16); + if (ret) + return ret; + + ret = st->variant->get_freq(st); + if (ret) + return ret; } - ret = st->variant->get_freq(st); - mutex_unlock(slock); - if (ret) - return ret; ret /= adis16400_3db_divisors[val16 & 0x07]; *val = ret / 1000; *val2 = (ret % 1000) * 1000; return IIO_VAL_INT_PLUS_MICRO; case IIO_CHAN_INFO_SAMP_FREQ: - mutex_lock(slock); - ret = st->variant->get_freq(st); - mutex_unlock(slock); - if (ret) - return ret; + adis_dev_auto_scoped_lock(&st->adis) { + ret = st->variant->get_freq(st); + if (ret) + return ret; + } *val = ret / 1000; *val2 = (ret % 1000) * 1000; return IIO_VAL_INT_PLUS_MICRO; @@ -647,35 +609,30 @@ static irqreturn_t adis16400_trigger_handler(int irq, void *p) struct iio_dev *indio_dev = pf->indio_dev; struct adis16400_state *st = iio_priv(indio_dev); struct adis *adis = &st->adis; - u32 old_speed_hz = st->adis.spi->max_speed_hz; void *buffer; int ret; - if (!adis->buffer) - return -ENOMEM; - - if (!(st->variant->flags & ADIS16400_NO_BURST) && - st->adis.spi->max_speed_hz > ADIS16400_SPI_BURST) { - st->adis.spi->max_speed_hz = ADIS16400_SPI_BURST; - spi_setup(st->adis.spi); - } - ret = spi_sync(adis->spi, &adis->msg); if (ret) dev_err(&adis->spi->dev, "Failed to read data: %d\n", ret); - if (!(st->variant->flags & ADIS16400_NO_BURST)) { - st->adis.spi->max_speed_hz = old_speed_hz; - spi_setup(st->adis.spi); - } - - if (st->variant->flags & ADIS16400_BURST_DIAG_STAT) + if (st->variant->flags & ADIS16400_BURST_DIAG_STAT) { buffer = adis->buffer + sizeof(u16); - else - buffer = adis->buffer; + /* + * The size here is always larger than, or equal to the true + * size of the channel data. This may result in a larger copy + * than necessary, but as the target buffer will be + * buffer->scan_bytes this will be safe. + */ + iio_push_to_buffers_with_ts_unaligned(indio_dev, buffer, + indio_dev->scan_bytes - sizeof(pf->timestamp), + pf->timestamp); + } else { + iio_push_to_buffers_with_timestamp(indio_dev, + adis->buffer, + pf->timestamp); + } - iio_push_to_buffers_with_timestamp(indio_dev, buffer, - pf->timestamp); iio_trigger_notify_done(indio_dev->trig); @@ -947,7 +904,7 @@ static const char * const adis16400_status_error_msgs[] = { [ADIS16400_DIAG_STAT_POWER_LOW] = "Power supply below 4.75V", }; -#define ADIS16400_DATA(_timeouts) \ +#define ADIS16400_DATA(_timeouts, _burst_len) \ { \ .msc_ctrl_reg = ADIS16400_MSC_CTRL, \ .glob_cmd_reg = ADIS16400_GLOB_CMD, \ @@ -973,6 +930,9 @@ static const char * const adis16400_status_error_msgs[] = { BIT(ADIS16400_DIAG_STAT_POWER_HIGH) | \ BIT(ADIS16400_DIAG_STAT_POWER_LOW), \ .timeouts = (_timeouts), \ + .burst_reg_cmd = ADIS16400_GLOB_CMD, \ + .burst_len = (_burst_len), \ + .burst_max_speed_hz = ADIS16400_SPI_BURST \ } static const struct adis_timeout adis16300_timeouts = { @@ -1011,137 +971,142 @@ static const struct adis_timeout adis16448_timeouts = { .self_test_ms = 45, }; -static struct adis16400_chip_info adis16400_chips[] = { - [ADIS16300] = { - .channels = adis16300_channels, - .num_channels = ARRAY_SIZE(adis16300_channels), - .flags = ADIS16400_HAS_PROD_ID | ADIS16400_HAS_SLOW_MODE | - ADIS16400_HAS_SERIAL_NUMBER, - .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */ - .accel_scale_micro = 5884, - .temp_scale_nano = 140000000, /* 0.14 C */ - .temp_offset = 25000000 / 140000, /* 25 C = 0x00 */ - .set_freq = adis16400_set_freq, - .get_freq = adis16400_get_freq, - .adis_data = ADIS16400_DATA(&adis16300_timeouts), - }, - [ADIS16334] = { - .channels = adis16334_channels, - .num_channels = ARRAY_SIZE(adis16334_channels), - .flags = ADIS16400_HAS_PROD_ID | ADIS16400_NO_BURST | - ADIS16400_HAS_SERIAL_NUMBER, - .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */ - .accel_scale_micro = IIO_G_TO_M_S_2(1000), /* 1 mg */ - .temp_scale_nano = 67850000, /* 0.06785 C */ - .temp_offset = 25000000 / 67850, /* 25 C = 0x00 */ - .set_freq = adis16334_set_freq, - .get_freq = adis16334_get_freq, - .adis_data = ADIS16400_DATA(&adis16334_timeouts), - }, - [ADIS16350] = { - .channels = adis16350_channels, - .num_channels = ARRAY_SIZE(adis16350_channels), - .gyro_scale_micro = IIO_DEGREE_TO_RAD(73260), /* 0.07326 deg/s */ - .accel_scale_micro = IIO_G_TO_M_S_2(2522), /* 0.002522 g */ - .temp_scale_nano = 145300000, /* 0.1453 C */ - .temp_offset = 25000000 / 145300, /* 25 C = 0x00 */ - .flags = ADIS16400_NO_BURST | ADIS16400_HAS_SLOW_MODE, - .set_freq = adis16400_set_freq, - .get_freq = adis16400_get_freq, - .adis_data = ADIS16400_DATA(&adis16300_timeouts), - }, - [ADIS16360] = { - .channels = adis16350_channels, - .num_channels = ARRAY_SIZE(adis16350_channels), - .flags = ADIS16400_HAS_PROD_ID | ADIS16400_HAS_SLOW_MODE | - ADIS16400_HAS_SERIAL_NUMBER, - .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */ - .accel_scale_micro = IIO_G_TO_M_S_2(3333), /* 3.333 mg */ - .temp_scale_nano = 136000000, /* 0.136 C */ - .temp_offset = 25000000 / 136000, /* 25 C = 0x00 */ - .set_freq = adis16400_set_freq, - .get_freq = adis16400_get_freq, - .adis_data = ADIS16400_DATA(&adis16300_timeouts), - }, - [ADIS16362] = { - .channels = adis16350_channels, - .num_channels = ARRAY_SIZE(adis16350_channels), - .flags = ADIS16400_HAS_PROD_ID | ADIS16400_HAS_SLOW_MODE | - ADIS16400_HAS_SERIAL_NUMBER, - .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */ - .accel_scale_micro = IIO_G_TO_M_S_2(333), /* 0.333 mg */ - .temp_scale_nano = 136000000, /* 0.136 C */ - .temp_offset = 25000000 / 136000, /* 25 C = 0x00 */ - .set_freq = adis16400_set_freq, - .get_freq = adis16400_get_freq, - .adis_data = ADIS16400_DATA(&adis16362_timeouts), - }, - [ADIS16364] = { - .channels = adis16350_channels, - .num_channels = ARRAY_SIZE(adis16350_channels), - .flags = ADIS16400_HAS_PROD_ID | ADIS16400_HAS_SLOW_MODE | - ADIS16400_HAS_SERIAL_NUMBER, - .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */ - .accel_scale_micro = IIO_G_TO_M_S_2(1000), /* 1 mg */ - .temp_scale_nano = 136000000, /* 0.136 C */ - .temp_offset = 25000000 / 136000, /* 25 C = 0x00 */ - .set_freq = adis16400_set_freq, - .get_freq = adis16400_get_freq, - .adis_data = ADIS16400_DATA(&adis16362_timeouts), - }, - [ADIS16367] = { - .channels = adis16350_channels, - .num_channels = ARRAY_SIZE(adis16350_channels), - .flags = ADIS16400_HAS_PROD_ID | ADIS16400_HAS_SLOW_MODE | - ADIS16400_HAS_SERIAL_NUMBER, - .gyro_scale_micro = IIO_DEGREE_TO_RAD(2000), /* 0.2 deg/s */ - .accel_scale_micro = IIO_G_TO_M_S_2(3333), /* 3.333 mg */ - .temp_scale_nano = 136000000, /* 0.136 C */ - .temp_offset = 25000000 / 136000, /* 25 C = 0x00 */ - .set_freq = adis16400_set_freq, - .get_freq = adis16400_get_freq, - .adis_data = ADIS16400_DATA(&adis16300_timeouts), - }, - [ADIS16400] = { - .channels = adis16400_channels, - .num_channels = ARRAY_SIZE(adis16400_channels), - .flags = ADIS16400_HAS_PROD_ID | ADIS16400_HAS_SLOW_MODE, - .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */ - .accel_scale_micro = IIO_G_TO_M_S_2(3333), /* 3.333 mg */ - .temp_scale_nano = 140000000, /* 0.14 C */ - .temp_offset = 25000000 / 140000, /* 25 C = 0x00 */ - .set_freq = adis16400_set_freq, - .get_freq = adis16400_get_freq, - .adis_data = ADIS16400_DATA(&adis16400_timeouts), - }, - [ADIS16445] = { - .channels = adis16445_channels, - .num_channels = ARRAY_SIZE(adis16445_channels), - .flags = ADIS16400_HAS_PROD_ID | - ADIS16400_HAS_SERIAL_NUMBER | - ADIS16400_BURST_DIAG_STAT, - .gyro_scale_micro = IIO_DEGREE_TO_RAD(10000), /* 0.01 deg/s */ - .accel_scale_micro = IIO_G_TO_M_S_2(250), /* 1/4000 g */ - .temp_scale_nano = 73860000, /* 0.07386 C */ - .temp_offset = 31000000 / 73860, /* 31 C = 0x00 */ - .set_freq = adis16334_set_freq, - .get_freq = adis16334_get_freq, - .adis_data = ADIS16400_DATA(&adis16445_timeouts), - }, - [ADIS16448] = { - .channels = adis16448_channels, - .num_channels = ARRAY_SIZE(adis16448_channels), - .flags = ADIS16400_HAS_PROD_ID | - ADIS16400_HAS_SERIAL_NUMBER | - ADIS16400_BURST_DIAG_STAT, - .gyro_scale_micro = IIO_DEGREE_TO_RAD(40000), /* 0.04 deg/s */ - .accel_scale_micro = IIO_G_TO_M_S_2(833), /* 1/1200 g */ - .temp_scale_nano = 73860000, /* 0.07386 C */ - .temp_offset = 31000000 / 73860, /* 31 C = 0x00 */ - .set_freq = adis16334_set_freq, - .get_freq = adis16334_get_freq, - .adis_data = ADIS16400_DATA(&adis16448_timeouts), - } +static const struct adis16400_chip_info adis16300_chip_info = { + .channels = adis16300_channels, + .num_channels = ARRAY_SIZE(adis16300_channels), + .flags = ADIS16400_HAS_PROD_ID | ADIS16400_HAS_SLOW_MODE | + ADIS16400_HAS_SERIAL_NUMBER, + .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */ + .accel_scale_micro = 5884, + .temp_scale_nano = 140000000, /* 0.14 C */ + .temp_offset = 25000000 / 140000, /* 25 C = 0x00 */ + .set_freq = adis16400_set_freq, + .get_freq = adis16400_get_freq, + .adis_data = ADIS16400_DATA(&adis16300_timeouts, 18), +}; + +static const struct adis16400_chip_info adis16334_chip_info = { + .channels = adis16334_channels, + .num_channels = ARRAY_SIZE(adis16334_channels), + .flags = ADIS16400_HAS_PROD_ID | ADIS16400_NO_BURST | + ADIS16400_HAS_SERIAL_NUMBER, + .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */ + .accel_scale_micro = IIO_G_TO_M_S_2(1000), /* 1 mg */ + .temp_scale_nano = 67850000, /* 0.06785 C */ + .temp_offset = 25000000 / 67850, /* 25 C = 0x00 */ + .set_freq = adis16334_set_freq, + .get_freq = adis16334_get_freq, + .adis_data = ADIS16400_DATA(&adis16334_timeouts, 0), +}; + +static const struct adis16400_chip_info adis16350_chip_info = { + .channels = adis16350_channels, + .num_channels = ARRAY_SIZE(adis16350_channels), + .gyro_scale_micro = IIO_DEGREE_TO_RAD(73260), /* 0.07326 deg/s */ + .accel_scale_micro = IIO_G_TO_M_S_2(2522), /* 0.002522 g */ + .temp_scale_nano = 145300000, /* 0.1453 C */ + .temp_offset = 25000000 / 145300, /* 25 C = 0x00 */ + .flags = ADIS16400_NO_BURST | ADIS16400_HAS_SLOW_MODE, + .set_freq = adis16400_set_freq, + .get_freq = adis16400_get_freq, + .adis_data = ADIS16400_DATA(&adis16300_timeouts, 0), +}; + +static const struct adis16400_chip_info adis16360_chip_info = { + .channels = adis16350_channels, + .num_channels = ARRAY_SIZE(adis16350_channels), + .flags = ADIS16400_HAS_PROD_ID | ADIS16400_HAS_SLOW_MODE | + ADIS16400_HAS_SERIAL_NUMBER, + .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */ + .accel_scale_micro = IIO_G_TO_M_S_2(3333), /* 3.333 mg */ + .temp_scale_nano = 136000000, /* 0.136 C */ + .temp_offset = 25000000 / 136000, /* 25 C = 0x00 */ + .set_freq = adis16400_set_freq, + .get_freq = adis16400_get_freq, + .adis_data = ADIS16400_DATA(&adis16300_timeouts, 28), +}; + +static const struct adis16400_chip_info adis16362_chip_info = { + .channels = adis16350_channels, + .num_channels = ARRAY_SIZE(adis16350_channels), + .flags = ADIS16400_HAS_PROD_ID | ADIS16400_HAS_SLOW_MODE | + ADIS16400_HAS_SERIAL_NUMBER, + .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */ + .accel_scale_micro = IIO_G_TO_M_S_2(333), /* 0.333 mg */ + .temp_scale_nano = 136000000, /* 0.136 C */ + .temp_offset = 25000000 / 136000, /* 25 C = 0x00 */ + .set_freq = adis16400_set_freq, + .get_freq = adis16400_get_freq, + .adis_data = ADIS16400_DATA(&adis16362_timeouts, 28), +}; + +static const struct adis16400_chip_info adis16364_chip_info = { + .channels = adis16350_channels, + .num_channels = ARRAY_SIZE(adis16350_channels), + .flags = ADIS16400_HAS_PROD_ID | ADIS16400_HAS_SLOW_MODE | + ADIS16400_HAS_SERIAL_NUMBER, + .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */ + .accel_scale_micro = IIO_G_TO_M_S_2(1000), /* 1 mg */ + .temp_scale_nano = 136000000, /* 0.136 C */ + .temp_offset = 25000000 / 136000, /* 25 C = 0x00 */ + .set_freq = adis16400_set_freq, + .get_freq = adis16400_get_freq, + .adis_data = ADIS16400_DATA(&adis16362_timeouts, 28), +}; + +static const struct adis16400_chip_info adis16367_chip_info = { + .channels = adis16350_channels, + .num_channels = ARRAY_SIZE(adis16350_channels), + .flags = ADIS16400_HAS_PROD_ID | ADIS16400_HAS_SLOW_MODE | + ADIS16400_HAS_SERIAL_NUMBER, + .gyro_scale_micro = IIO_DEGREE_TO_RAD(2000), /* 0.2 deg/s */ + .accel_scale_micro = IIO_G_TO_M_S_2(3333), /* 3.333 mg */ + .temp_scale_nano = 136000000, /* 0.136 C */ + .temp_offset = 25000000 / 136000, /* 25 C = 0x00 */ + .set_freq = adis16400_set_freq, + .get_freq = adis16400_get_freq, + .adis_data = ADIS16400_DATA(&adis16300_timeouts, 28), +}; + +static const struct adis16400_chip_info adis16400_chip_info = { + .channels = adis16400_channels, + .num_channels = ARRAY_SIZE(adis16400_channels), + .flags = ADIS16400_HAS_PROD_ID | ADIS16400_HAS_SLOW_MODE, + .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */ + .accel_scale_micro = IIO_G_TO_M_S_2(3333), /* 3.333 mg */ + .temp_scale_nano = 140000000, /* 0.14 C */ + .temp_offset = 25000000 / 140000, /* 25 C = 0x00 */ + .set_freq = adis16400_set_freq, + .get_freq = adis16400_get_freq, + .adis_data = ADIS16400_DATA(&adis16400_timeouts, 24), +}; + +static const struct adis16400_chip_info adis16445_chip_info = { + .channels = adis16445_channels, + .num_channels = ARRAY_SIZE(adis16445_channels), + .flags = ADIS16400_HAS_PROD_ID | ADIS16400_HAS_SERIAL_NUMBER | + ADIS16400_BURST_DIAG_STAT, + .gyro_scale_micro = IIO_DEGREE_TO_RAD(10000), /* 0.01 deg/s */ + .accel_scale_micro = IIO_G_TO_M_S_2(250), /* 1/4000 g */ + .temp_scale_nano = 73860000, /* 0.07386 C */ + .temp_offset = 31000000 / 73860, /* 31 C = 0x00 */ + .set_freq = adis16334_set_freq, + .get_freq = adis16334_get_freq, + .adis_data = ADIS16400_DATA(&adis16445_timeouts, 16), +}; + +static const struct adis16400_chip_info adis16448_chip_info = { + .channels = adis16448_channels, + .num_channels = ARRAY_SIZE(adis16448_channels), + .flags = ADIS16400_HAS_PROD_ID | ADIS16400_HAS_SERIAL_NUMBER | + ADIS16400_BURST_DIAG_STAT, + .gyro_scale_micro = IIO_DEGREE_TO_RAD(40000), /* 0.04 deg/s */ + .accel_scale_micro = IIO_G_TO_M_S_2(833), /* 1/1200 g */ + .temp_scale_nano = 73860000, /* 0.07386 C */ + .temp_offset = 31000000 / 73860, /* 31 C = 0x00 */ + .set_freq = adis16334_set_freq, + .get_freq = adis16334_get_freq, + .adis_data = ADIS16400_DATA(&adis16448_timeouts, 24), }; static const struct iio_info adis16400_info = { @@ -1164,6 +1129,12 @@ static void adis16400_setup_chan_mask(struct adis16400_state *st) st->avail_scan_mask[0] |= BIT(ch->scan_index); } } + +static void adis16400_stop(void *data) +{ + adis16400_stop_device(data); +} + static int adis16400_probe(struct spi_device *spi) { struct adis16400_state *st; @@ -1176,12 +1147,9 @@ static int adis16400_probe(struct spi_device *spi) return -ENOMEM; st = iio_priv(indio_dev); - /* this is only used for removal purposes */ - spi_set_drvdata(spi, indio_dev); /* setup the industrialio driver allocated elements */ - st->variant = &adis16400_chips[spi_get_device_id(spi)->driver_data]; - indio_dev->dev.parent = &spi->dev; + st->variant = spi_get_device_match_data(spi); indio_dev->name = spi_get_device_id(spi)->name; indio_dev->channels = st->variant->channels; indio_dev->num_channels = st->variant->num_channels; @@ -1191,9 +1159,6 @@ static int adis16400_probe(struct spi_device *spi) if (!(st->variant->flags & ADIS16400_NO_BURST)) { adis16400_setup_chan_mask(st); indio_dev->available_scan_masks = st->avail_scan_mask; - st->adis.burst = &adis16400_burst; - if (st->variant->flags & ADIS16400_BURST_DIAG_STAT) - st->adis.burst_extra_len = sizeof(u16); } adis16400_data = &st->variant->adis_data; @@ -1202,57 +1167,44 @@ static int adis16400_probe(struct spi_device *spi) if (ret) return ret; - ret = adis_setup_buffer_and_trigger(&st->adis, indio_dev, - adis16400_trigger_handler); + ret = devm_adis_setup_buffer_and_trigger(&st->adis, indio_dev, adis16400_trigger_handler); if (ret) return ret; /* Get the device into a sane initial state */ ret = adis16400_initial_setup(indio_dev); if (ret) - goto error_cleanup_buffer; - ret = iio_device_register(indio_dev); - if (ret) - goto error_cleanup_buffer; - - adis16400_debugfs_init(indio_dev); - return 0; - -error_cleanup_buffer: - adis_cleanup_buffer_and_trigger(&st->adis, indio_dev); - return ret; -} - -static int adis16400_remove(struct spi_device *spi) -{ - struct iio_dev *indio_dev = spi_get_drvdata(spi); - struct adis16400_state *st = iio_priv(indio_dev); + return ret; - iio_device_unregister(indio_dev); - adis16400_stop_device(indio_dev); + ret = devm_add_action_or_reset(&spi->dev, adis16400_stop, indio_dev); + if (ret) + return ret; - adis_cleanup_buffer_and_trigger(&st->adis, indio_dev); + ret = devm_iio_device_register(&spi->dev, indio_dev); + if (ret) + return ret; + adis16400_debugfs_init(indio_dev); return 0; } static const struct spi_device_id adis16400_id[] = { - {"adis16300", ADIS16300}, - {"adis16305", ADIS16300}, - {"adis16334", ADIS16334}, - {"adis16350", ADIS16350}, - {"adis16354", ADIS16350}, - {"adis16355", ADIS16350}, - {"adis16360", ADIS16360}, - {"adis16362", ADIS16362}, - {"adis16364", ADIS16364}, - {"adis16365", ADIS16360}, - {"adis16367", ADIS16367}, - {"adis16400", ADIS16400}, - {"adis16405", ADIS16400}, - {"adis16445", ADIS16445}, - {"adis16448", ADIS16448}, - {} + { "adis16300", (kernel_ulong_t)&adis16300_chip_info }, + { "adis16305", (kernel_ulong_t)&adis16300_chip_info }, + { "adis16334", (kernel_ulong_t)&adis16334_chip_info }, + { "adis16350", (kernel_ulong_t)&adis16350_chip_info }, + { "adis16354", (kernel_ulong_t)&adis16350_chip_info }, + { "adis16355", (kernel_ulong_t)&adis16350_chip_info }, + { "adis16360", (kernel_ulong_t)&adis16360_chip_info }, + { "adis16362", (kernel_ulong_t)&adis16362_chip_info }, + { "adis16364", (kernel_ulong_t)&adis16364_chip_info }, + { "adis16365", (kernel_ulong_t)&adis16360_chip_info }, + { "adis16367", (kernel_ulong_t)&adis16367_chip_info }, + { "adis16400", (kernel_ulong_t)&adis16400_chip_info }, + { "adis16405", (kernel_ulong_t)&adis16400_chip_info }, + { "adis16445", (kernel_ulong_t)&adis16445_chip_info }, + { "adis16448", (kernel_ulong_t)&adis16448_chip_info }, + { } }; MODULE_DEVICE_TABLE(spi, adis16400_id); @@ -1262,10 +1214,10 @@ static struct spi_driver adis16400_driver = { }, .id_table = adis16400_id, .probe = adis16400_probe, - .remove = adis16400_remove, }; module_spi_driver(adis16400_driver); MODULE_AUTHOR("Manuel Stahl <manuel.stahl@iis.fraunhofer.de>"); MODULE_DESCRIPTION("Analog Devices ADIS16400/5 IMU SPI driver"); MODULE_LICENSE("GPL v2"); +MODULE_IMPORT_NS("IIO_ADISLIB"); |
