diff options
Diffstat (limited to 'drivers/iio/imu')
-rw-r--r-- | drivers/iio/imu/adis.c | 68 | ||||
-rw-r--r-- | drivers/iio/imu/adis16400.c | 140 | ||||
-rw-r--r-- | drivers/iio/imu/adis16460.c | 40 | ||||
-rw-r--r-- | drivers/iio/imu/adis16480.c | 197 | ||||
-rw-r--r-- | drivers/iio/imu/adis_buffer.c | 3 | ||||
-rw-r--r-- | drivers/iio/imu/inv_mpu6050/Kconfig | 12 | ||||
-rw-r--r-- | drivers/iio/imu/inv_mpu6050/inv_mpu_core.c | 651 | ||||
-rw-r--r-- | drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c | 111 | ||||
-rw-r--r-- | drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h | 58 | ||||
-rw-r--r-- | drivers/iio/imu/inv_mpu6050/inv_mpu_magn.c | 49 | ||||
-rw-r--r-- | drivers/iio/imu/inv_mpu6050/inv_mpu_magn.h | 5 | ||||
-rw-r--r-- | drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c | 57 | ||||
-rw-r--r-- | drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c | 74 | ||||
-rw-r--r-- | drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c | 160 | ||||
-rw-r--r-- | drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h | 4 | ||||
-rw-r--r-- | drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c | 5 |
16 files changed, 953 insertions, 681 deletions
diff --git a/drivers/iio/imu/adis.c b/drivers/iio/imu/adis.c index 022bb54fb748..a8afd01de4f3 100644 --- a/drivers/iio/imu/adis.c +++ b/drivers/iio/imu/adis.c @@ -7,6 +7,7 @@ */ #include <linux/delay.h> +#include <linux/gpio/consumer.h> #include <linux/mutex.h> #include <linux/device.h> #include <linux/kernel.h> @@ -346,8 +347,8 @@ static int adis_self_test(struct adis *adis) int ret; const struct adis_timeout *timeouts = adis->data->timeouts; - ret = __adis_write_reg_16(adis, adis->data->msc_ctrl_reg, - adis->data->self_test_mask); + ret = __adis_write_reg_16(adis, adis->data->self_test_reg, + adis->data->self_test_mask); if (ret) { dev_err(&adis->spi->dev, "Failed to initiate self test: %d\n", ret); @@ -359,42 +360,71 @@ static int adis_self_test(struct adis *adis) ret = __adis_check_status(adis); if (adis->data->self_test_no_autoclear) - __adis_write_reg_16(adis, adis->data->msc_ctrl_reg, 0x00); + __adis_write_reg_16(adis, adis->data->self_test_reg, 0x00); return ret; } /** - * adis_inital_startup() - Performs device self-test + * __adis_initial_startup() - Device initial setup * @adis: The adis device * + * The function performs a HW reset via a reset pin that should be specified + * via GPIOLIB. If no pin is configured a SW reset will be performed. + * The RST pin for the ADIS devices should be configured as ACTIVE_LOW. + * + * After the self-test operation is performed, the function will also check + * that the product ID is as expected. This assumes that drivers providing + * 'prod_id_reg' will also provide the 'prod_id'. + * * Returns 0 if the device is operational, a negative error code otherwise. * * This function should be called early on in the device initialization sequence * to ensure that the device is in a sane and known state and that it is usable. */ -int adis_initial_startup(struct adis *adis) +int __adis_initial_startup(struct adis *adis) { + const struct adis_timeout *timeouts = adis->data->timeouts; + struct gpio_desc *gpio; + uint16_t prod_id; int ret; - mutex_lock(&adis->state_lock); + /* check if the device has rst pin low */ + gpio = devm_gpiod_get_optional(&adis->spi->dev, "reset", GPIOD_ASIS); + if (IS_ERR(gpio)) + return PTR_ERR(gpio); + + if (gpio) { + gpiod_set_value_cansleep(gpio, 1); + msleep(10); + /* bring device out of reset */ + gpiod_set_value_cansleep(gpio, 0); + msleep(timeouts->reset_ms); + } else { + ret = __adis_reset(adis); + if (ret) + return ret; + } ret = adis_self_test(adis); - if (ret) { - dev_err(&adis->spi->dev, "Self-test failed, trying reset.\n"); - __adis_reset(adis); - ret = adis_self_test(adis); - if (ret) { - dev_err(&adis->spi->dev, "Second self-test failed, giving up.\n"); - goto out_unlock; - } - } + if (ret) + return ret; -out_unlock: - mutex_unlock(&adis->state_lock); - return ret; + if (!adis->data->prod_id_reg) + return 0; + + ret = adis_read_reg_16(adis, adis->data->prod_id_reg, &prod_id); + if (ret) + return ret; + + if (prod_id != adis->data->prod_id) + dev_warn(&adis->spi->dev, + "Device ID(%u) and product ID(%u) do not match.", + adis->data->prod_id, prod_id); + + return 0; } -EXPORT_SYMBOL_GPL(adis_initial_startup); +EXPORT_SYMBOL_GPL(__adis_initial_startup); /** * adis_single_conversion() - Performs a single sample conversion diff --git a/drivers/iio/imu/adis16400.c b/drivers/iio/imu/adis16400.c index cfb1c19eb930..05e70c1c4835 100644 --- a/drivers/iio/imu/adis16400.c +++ b/drivers/iio/imu/adis16400.c @@ -156,7 +156,7 @@ struct adis16400_state; struct adis16400_chip_info { const struct iio_chan_spec *channels; - const struct adis_timeout *timeouts; + const struct adis_data adis_data; const int num_channels; const long flags; unsigned int gyro_scale_micro; @@ -930,12 +930,64 @@ static const struct iio_chan_spec adis16334_channels[] = { IIO_CHAN_SOFT_TIMESTAMP(ADIS16400_SCAN_TIMESTAMP), }; +static const char * const adis16400_status_error_msgs[] = { + [ADIS16400_DIAG_STAT_ZACCL_FAIL] = "Z-axis accelerometer self-test failure", + [ADIS16400_DIAG_STAT_YACCL_FAIL] = "Y-axis accelerometer self-test failure", + [ADIS16400_DIAG_STAT_XACCL_FAIL] = "X-axis accelerometer self-test failure", + [ADIS16400_DIAG_STAT_XGYRO_FAIL] = "X-axis gyroscope self-test failure", + [ADIS16400_DIAG_STAT_YGYRO_FAIL] = "Y-axis gyroscope self-test failure", + [ADIS16400_DIAG_STAT_ZGYRO_FAIL] = "Z-axis gyroscope self-test failure", + [ADIS16400_DIAG_STAT_ALARM2] = "Alarm 2 active", + [ADIS16400_DIAG_STAT_ALARM1] = "Alarm 1 active", + [ADIS16400_DIAG_STAT_FLASH_CHK] = "Flash checksum error", + [ADIS16400_DIAG_STAT_SELF_TEST] = "Self test error", + [ADIS16400_DIAG_STAT_OVERFLOW] = "Sensor overrange", + [ADIS16400_DIAG_STAT_SPI_FAIL] = "SPI failure", + [ADIS16400_DIAG_STAT_FLASH_UPT] = "Flash update failed", + [ADIS16400_DIAG_STAT_POWER_HIGH] = "Power supply above 5.25V", + [ADIS16400_DIAG_STAT_POWER_LOW] = "Power supply below 4.75V", +}; + +#define ADIS16400_DATA(_timeouts) \ +{ \ + .msc_ctrl_reg = ADIS16400_MSC_CTRL, \ + .glob_cmd_reg = ADIS16400_GLOB_CMD, \ + .diag_stat_reg = ADIS16400_DIAG_STAT, \ + .read_delay = 50, \ + .write_delay = 50, \ + .self_test_mask = ADIS16400_MSC_CTRL_MEM_TEST, \ + .self_test_reg = ADIS16400_MSC_CTRL, \ + .status_error_msgs = adis16400_status_error_msgs, \ + .status_error_mask = BIT(ADIS16400_DIAG_STAT_ZACCL_FAIL) | \ + BIT(ADIS16400_DIAG_STAT_YACCL_FAIL) | \ + BIT(ADIS16400_DIAG_STAT_XACCL_FAIL) | \ + BIT(ADIS16400_DIAG_STAT_XGYRO_FAIL) | \ + BIT(ADIS16400_DIAG_STAT_YGYRO_FAIL) | \ + BIT(ADIS16400_DIAG_STAT_ZGYRO_FAIL) | \ + BIT(ADIS16400_DIAG_STAT_ALARM2) | \ + BIT(ADIS16400_DIAG_STAT_ALARM1) | \ + BIT(ADIS16400_DIAG_STAT_FLASH_CHK) | \ + BIT(ADIS16400_DIAG_STAT_SELF_TEST) | \ + BIT(ADIS16400_DIAG_STAT_OVERFLOW) | \ + BIT(ADIS16400_DIAG_STAT_SPI_FAIL) | \ + BIT(ADIS16400_DIAG_STAT_FLASH_UPT) | \ + BIT(ADIS16400_DIAG_STAT_POWER_HIGH) | \ + BIT(ADIS16400_DIAG_STAT_POWER_LOW), \ + .timeouts = (_timeouts), \ +} + static const struct adis_timeout adis16300_timeouts = { .reset_ms = ADIS16400_STARTUP_DELAY, .sw_reset_ms = ADIS16400_STARTUP_DELAY, .self_test_ms = ADIS16400_STARTUP_DELAY, }; +static const struct adis_timeout adis16334_timeouts = { + .reset_ms = 60, + .sw_reset_ms = 60, + .self_test_ms = 14, +}; + static const struct adis_timeout adis16362_timeouts = { .reset_ms = 130, .sw_reset_ms = 130, @@ -972,7 +1024,7 @@ static struct adis16400_chip_info adis16400_chips[] = { .temp_offset = 25000000 / 140000, /* 25 C = 0x00 */ .set_freq = adis16400_set_freq, .get_freq = adis16400_get_freq, - .timeouts = &adis16300_timeouts, + .adis_data = ADIS16400_DATA(&adis16300_timeouts), }, [ADIS16334] = { .channels = adis16334_channels, @@ -985,6 +1037,7 @@ static struct adis16400_chip_info adis16400_chips[] = { .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, @@ -996,7 +1049,7 @@ static struct adis16400_chip_info adis16400_chips[] = { .flags = ADIS16400_NO_BURST | ADIS16400_HAS_SLOW_MODE, .set_freq = adis16400_set_freq, .get_freq = adis16400_get_freq, - .timeouts = &adis16300_timeouts, + .adis_data = ADIS16400_DATA(&adis16300_timeouts), }, [ADIS16360] = { .channels = adis16350_channels, @@ -1009,7 +1062,7 @@ static struct adis16400_chip_info adis16400_chips[] = { .temp_offset = 25000000 / 136000, /* 25 C = 0x00 */ .set_freq = adis16400_set_freq, .get_freq = adis16400_get_freq, - .timeouts = &adis16300_timeouts, + .adis_data = ADIS16400_DATA(&adis16300_timeouts), }, [ADIS16362] = { .channels = adis16350_channels, @@ -1022,7 +1075,7 @@ static struct adis16400_chip_info adis16400_chips[] = { .temp_offset = 25000000 / 136000, /* 25 C = 0x00 */ .set_freq = adis16400_set_freq, .get_freq = adis16400_get_freq, - .timeouts = &adis16362_timeouts, + .adis_data = ADIS16400_DATA(&adis16362_timeouts), }, [ADIS16364] = { .channels = adis16350_channels, @@ -1035,7 +1088,7 @@ static struct adis16400_chip_info adis16400_chips[] = { .temp_offset = 25000000 / 136000, /* 25 C = 0x00 */ .set_freq = adis16400_set_freq, .get_freq = adis16400_get_freq, - .timeouts = &adis16362_timeouts, + .adis_data = ADIS16400_DATA(&adis16362_timeouts), }, [ADIS16367] = { .channels = adis16350_channels, @@ -1048,7 +1101,7 @@ static struct adis16400_chip_info adis16400_chips[] = { .temp_offset = 25000000 / 136000, /* 25 C = 0x00 */ .set_freq = adis16400_set_freq, .get_freq = adis16400_get_freq, - .timeouts = &adis16300_timeouts, + .adis_data = ADIS16400_DATA(&adis16300_timeouts), }, [ADIS16400] = { .channels = adis16400_channels, @@ -1060,7 +1113,7 @@ static struct adis16400_chip_info adis16400_chips[] = { .temp_offset = 25000000 / 140000, /* 25 C = 0x00 */ .set_freq = adis16400_set_freq, .get_freq = adis16400_get_freq, - .timeouts = &adis16400_timeouts, + .adis_data = ADIS16400_DATA(&adis16400_timeouts), }, [ADIS16445] = { .channels = adis16445_channels, @@ -1074,7 +1127,7 @@ static struct adis16400_chip_info adis16400_chips[] = { .temp_offset = 31000000 / 73860, /* 31 C = 0x00 */ .set_freq = adis16334_set_freq, .get_freq = adis16334_get_freq, - .timeouts = &adis16445_timeouts, + .adis_data = ADIS16400_DATA(&adis16445_timeouts), }, [ADIS16448] = { .channels = adis16448_channels, @@ -1088,7 +1141,7 @@ static struct adis16400_chip_info adis16400_chips[] = { .temp_offset = 31000000 / 73860, /* 31 C = 0x00 */ .set_freq = adis16334_set_freq, .get_freq = adis16334_get_freq, - .timeouts = &adis16448_timeouts, + .adis_data = ADIS16400_DATA(&adis16448_timeouts), } }; @@ -1099,52 +1152,6 @@ static const struct iio_info adis16400_info = { .debugfs_reg_access = adis_debugfs_reg_access, }; -static const char * const adis16400_status_error_msgs[] = { - [ADIS16400_DIAG_STAT_ZACCL_FAIL] = "Z-axis accelerometer self-test failure", - [ADIS16400_DIAG_STAT_YACCL_FAIL] = "Y-axis accelerometer self-test failure", - [ADIS16400_DIAG_STAT_XACCL_FAIL] = "X-axis accelerometer self-test failure", - [ADIS16400_DIAG_STAT_XGYRO_FAIL] = "X-axis gyroscope self-test failure", - [ADIS16400_DIAG_STAT_YGYRO_FAIL] = "Y-axis gyroscope self-test failure", - [ADIS16400_DIAG_STAT_ZGYRO_FAIL] = "Z-axis gyroscope self-test failure", - [ADIS16400_DIAG_STAT_ALARM2] = "Alarm 2 active", - [ADIS16400_DIAG_STAT_ALARM1] = "Alarm 1 active", - [ADIS16400_DIAG_STAT_FLASH_CHK] = "Flash checksum error", - [ADIS16400_DIAG_STAT_SELF_TEST] = "Self test error", - [ADIS16400_DIAG_STAT_OVERFLOW] = "Sensor overrange", - [ADIS16400_DIAG_STAT_SPI_FAIL] = "SPI failure", - [ADIS16400_DIAG_STAT_FLASH_UPT] = "Flash update failed", - [ADIS16400_DIAG_STAT_POWER_HIGH] = "Power supply above 5.25V", - [ADIS16400_DIAG_STAT_POWER_LOW] = "Power supply below 4.75V", -}; - -static const struct adis_data adis16400_data = { - .msc_ctrl_reg = ADIS16400_MSC_CTRL, - .glob_cmd_reg = ADIS16400_GLOB_CMD, - .diag_stat_reg = ADIS16400_DIAG_STAT, - - .read_delay = 50, - .write_delay = 50, - - .self_test_mask = ADIS16400_MSC_CTRL_MEM_TEST, - - .status_error_msgs = adis16400_status_error_msgs, - .status_error_mask = BIT(ADIS16400_DIAG_STAT_ZACCL_FAIL) | - BIT(ADIS16400_DIAG_STAT_YACCL_FAIL) | - BIT(ADIS16400_DIAG_STAT_XACCL_FAIL) | - BIT(ADIS16400_DIAG_STAT_XGYRO_FAIL) | - BIT(ADIS16400_DIAG_STAT_YGYRO_FAIL) | - BIT(ADIS16400_DIAG_STAT_ZGYRO_FAIL) | - BIT(ADIS16400_DIAG_STAT_ALARM2) | - BIT(ADIS16400_DIAG_STAT_ALARM1) | - BIT(ADIS16400_DIAG_STAT_FLASH_CHK) | - BIT(ADIS16400_DIAG_STAT_SELF_TEST) | - BIT(ADIS16400_DIAG_STAT_OVERFLOW) | - BIT(ADIS16400_DIAG_STAT_SPI_FAIL) | - BIT(ADIS16400_DIAG_STAT_FLASH_UPT) | - BIT(ADIS16400_DIAG_STAT_POWER_HIGH) | - BIT(ADIS16400_DIAG_STAT_POWER_LOW), -}; - static void adis16400_setup_chan_mask(struct adis16400_state *st) { const struct adis16400_chip_info *chip_info = st->variant; @@ -1158,23 +1165,6 @@ static void adis16400_setup_chan_mask(struct adis16400_state *st) st->avail_scan_mask[0] |= BIT(ch->scan_index); } } - -static struct adis_data *adis16400_adis_data_alloc(struct adis16400_state *st, - struct device *dev) -{ - struct adis_data *data; - - data = devm_kmalloc(dev, sizeof(struct adis_data), GFP_KERNEL); - if (!data) - return ERR_PTR(-ENOMEM); - - memcpy(data, &adis16400_data, sizeof(*data)); - - data->timeouts = st->variant->timeouts; - - return data; -} - static int adis16400_probe(struct spi_device *spi) { struct adis16400_state *st; @@ -1207,9 +1197,7 @@ static int adis16400_probe(struct spi_device *spi) st->adis.burst->extra_len = sizeof(u16); } - adis16400_data = adis16400_adis_data_alloc(st, &spi->dev); - if (IS_ERR(adis16400_data)) - return PTR_ERR(adis16400_data); + adis16400_data = &st->variant->adis_data; ret = adis_init(&st->adis, indio_dev, spi, adis16400_data); if (ret) diff --git a/drivers/iio/imu/adis16460.c b/drivers/iio/imu/adis16460.c index 9539cfe4a259..0027683d0256 100644 --- a/drivers/iio/imu/adis16460.c +++ b/drivers/iio/imu/adis16460.c @@ -333,40 +333,6 @@ static int adis16460_enable_irq(struct adis *adis, bool enable) return 0; } -static int adis16460_initial_setup(struct iio_dev *indio_dev) -{ - struct adis16460 *st = iio_priv(indio_dev); - uint16_t prod_id; - unsigned int device_id; - int ret; - - adis_reset(&st->adis); - msleep(222); - - ret = adis_write_reg_16(&st->adis, ADIS16460_REG_GLOB_CMD, BIT(1)); - if (ret) - return ret; - msleep(75); - - ret = adis_check_status(&st->adis); - if (ret) - return ret; - - ret = adis_read_reg_16(&st->adis, ADIS16460_REG_PROD_ID, &prod_id); - if (ret) - return ret; - - ret = sscanf(indio_dev->name, "adis%u\n", &device_id); - if (ret != 1) - return -EINVAL; - - if (prod_id != device_id) - dev_warn(&indio_dev->dev, "Device ID(%u) and product ID(%u) do not match.", - device_id, prod_id); - - return 0; -} - #define ADIS16460_DIAG_STAT_IN_CLK_OOS 7 #define ADIS16460_DIAG_STAT_FLASH_MEM 6 #define ADIS16460_DIAG_STAT_SELF_TEST 5 @@ -392,6 +358,10 @@ static const struct adis_timeout adis16460_timeouts = { static const struct adis_data adis16460_data = { .diag_stat_reg = ADIS16460_REG_DIAG_STAT, .glob_cmd_reg = ADIS16460_REG_GLOB_CMD, + .prod_id_reg = ADIS16460_REG_PROD_ID, + .prod_id = 16460, + .self_test_mask = BIT(2), + .self_test_reg = ADIS16460_REG_GLOB_CMD, .has_paging = false, .read_delay = 5, .write_delay = 5, @@ -439,7 +409,7 @@ static int adis16460_probe(struct spi_device *spi) adis16460_enable_irq(&st->adis, 0); - ret = adis16460_initial_setup(indio_dev); + ret = __adis_initial_startup(&st->adis); if (ret) goto error_cleanup_buffer; diff --git a/drivers/iio/imu/adis16480.c b/drivers/iio/imu/adis16480.c index dac87f1001fd..cfae0e4476e7 100644 --- a/drivers/iio/imu/adis16480.c +++ b/drivers/iio/imu/adis16480.c @@ -138,7 +138,7 @@ struct adis16480_chip_info { unsigned int max_dec_rate; const unsigned int *filter_freqs; bool has_pps_clk_mode; - const struct adis_timeout *timeouts; + const struct adis_data adis_data; }; enum adis16480_int_pin { @@ -796,6 +796,58 @@ enum adis16480_variant { ADIS16497_3, }; +#define ADIS16480_DIAG_STAT_XGYRO_FAIL 0 +#define ADIS16480_DIAG_STAT_YGYRO_FAIL 1 +#define ADIS16480_DIAG_STAT_ZGYRO_FAIL 2 +#define ADIS16480_DIAG_STAT_XACCL_FAIL 3 +#define ADIS16480_DIAG_STAT_YACCL_FAIL 4 +#define ADIS16480_DIAG_STAT_ZACCL_FAIL 5 +#define ADIS16480_DIAG_STAT_XMAGN_FAIL 8 +#define ADIS16480_DIAG_STAT_YMAGN_FAIL 9 +#define ADIS16480_DIAG_STAT_ZMAGN_FAIL 10 +#define ADIS16480_DIAG_STAT_BARO_FAIL 11 + +static const char * const adis16480_status_error_msgs[] = { + [ADIS16480_DIAG_STAT_XGYRO_FAIL] = "X-axis gyroscope self-test failure", + [ADIS16480_DIAG_STAT_YGYRO_FAIL] = "Y-axis gyroscope self-test failure", + [ADIS16480_DIAG_STAT_ZGYRO_FAIL] = "Z-axis gyroscope self-test failure", + [ADIS16480_DIAG_STAT_XACCL_FAIL] = "X-axis accelerometer self-test failure", + [ADIS16480_DIAG_STAT_YACCL_FAIL] = "Y-axis accelerometer self-test failure", + [ADIS16480_DIAG_STAT_ZACCL_FAIL] = "Z-axis accelerometer self-test failure", + [ADIS16480_DIAG_STAT_XMAGN_FAIL] = "X-axis magnetometer self-test failure", + [ADIS16480_DIAG_STAT_YMAGN_FAIL] = "Y-axis magnetometer self-test failure", + [ADIS16480_DIAG_STAT_ZMAGN_FAIL] = "Z-axis magnetometer self-test failure", + [ADIS16480_DIAG_STAT_BARO_FAIL] = "Barometer self-test failure", +}; + +static int adis16480_enable_irq(struct adis *adis, bool enable); + +#define ADIS16480_DATA(_prod_id, _timeouts) \ +{ \ + .diag_stat_reg = ADIS16480_REG_DIAG_STS, \ + .glob_cmd_reg = ADIS16480_REG_GLOB_CMD, \ + .prod_id_reg = ADIS16480_REG_PROD_ID, \ + .prod_id = (_prod_id), \ + .has_paging = true, \ + .read_delay = 5, \ + .write_delay = 5, \ + .self_test_mask = BIT(1), \ + .self_test_reg = ADIS16480_REG_GLOB_CMD, \ + .status_error_msgs = adis16480_status_error_msgs, \ + .status_error_mask = BIT(ADIS16480_DIAG_STAT_XGYRO_FAIL) | \ + BIT(ADIS16480_DIAG_STAT_YGYRO_FAIL) | \ + BIT(ADIS16480_DIAG_STAT_ZGYRO_FAIL) | \ + BIT(ADIS16480_DIAG_STAT_XACCL_FAIL) | \ + BIT(ADIS16480_DIAG_STAT_YACCL_FAIL) | \ + BIT(ADIS16480_DIAG_STAT_ZACCL_FAIL) | \ + BIT(ADIS16480_DIAG_STAT_XMAGN_FAIL) | \ + BIT(ADIS16480_DIAG_STAT_YMAGN_FAIL) | \ + BIT(ADIS16480_DIAG_STAT_ZMAGN_FAIL) | \ + BIT(ADIS16480_DIAG_STAT_BARO_FAIL), \ + .enable_irq = adis16480_enable_irq, \ + .timeouts = (_timeouts), \ +} + static const struct adis_timeout adis16485_timeouts = { .reset_ms = 560, .sw_reset_ms = 120, @@ -838,7 +890,7 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { .int_clk = 2460000, .max_dec_rate = 2048, .filter_freqs = adis16480_def_filter_freqs, - .timeouts = &adis16485_timeouts, + .adis_data = ADIS16480_DATA(16375, &adis16485_timeouts), }, [ADIS16480] = { .channels = adis16480_channels, @@ -851,7 +903,7 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { .int_clk = 2460000, .max_dec_rate = 2048, .filter_freqs = adis16480_def_filter_freqs, - .timeouts = &adis16480_timeouts, + .adis_data = ADIS16480_DATA(16480, &adis16480_timeouts), }, [ADIS16485] = { .channels = adis16485_channels, @@ -864,7 +916,7 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { .int_clk = 2460000, .max_dec_rate = 2048, .filter_freqs = adis16480_def_filter_freqs, - .timeouts = &adis16485_timeouts, + .adis_data = ADIS16480_DATA(16485, &adis16485_timeouts), }, [ADIS16488] = { .channels = adis16480_channels, @@ -877,7 +929,7 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { .int_clk = 2460000, .max_dec_rate = 2048, .filter_freqs = adis16480_def_filter_freqs, - .timeouts = &adis16485_timeouts, + .adis_data = ADIS16480_DATA(16488, &adis16485_timeouts), }, [ADIS16490] = { .channels = adis16485_channels, @@ -891,7 +943,7 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { .max_dec_rate = 4250, .filter_freqs = adis16495_def_filter_freqs, .has_pps_clk_mode = true, - .timeouts = &adis16495_timeouts, + .adis_data = ADIS16480_DATA(16490, &adis16495_timeouts), }, [ADIS16495_1] = { .channels = adis16485_channels, @@ -905,7 +957,7 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { .max_dec_rate = 4250, .filter_freqs = adis16495_def_filter_freqs, .has_pps_clk_mode = true, - .timeouts = &adis16495_1_timeouts, + .adis_data = ADIS16480_DATA(16495, &adis16495_1_timeouts), }, [ADIS16495_2] = { .channels = adis16485_channels, @@ -919,7 +971,7 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { .max_dec_rate = 4250, .filter_freqs = adis16495_def_filter_freqs, .has_pps_clk_mode = true, - .timeouts = &adis16495_1_timeouts, + .adis_data = ADIS16480_DATA(16495, &adis16495_1_timeouts), }, [ADIS16495_3] = { .channels = adis16485_channels, @@ -933,7 +985,7 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { .max_dec_rate = 4250, .filter_freqs = adis16495_def_filter_freqs, .has_pps_clk_mode = true, - .timeouts = &adis16495_1_timeouts, + .adis_data = ADIS16480_DATA(16495, &adis16495_1_timeouts), }, [ADIS16497_1] = { .channels = adis16485_channels, @@ -947,7 +999,7 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { .max_dec_rate = 4250, .filter_freqs = adis16495_def_filter_freqs, .has_pps_clk_mode = true, - .timeouts = &adis16495_1_timeouts, + .adis_data = ADIS16480_DATA(16497, &adis16495_1_timeouts), }, [ADIS16497_2] = { .channels = adis16485_channels, @@ -961,7 +1013,7 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { .max_dec_rate = 4250, .filter_freqs = adis16495_def_filter_freqs, .has_pps_clk_mode = true, - .timeouts = &adis16495_1_timeouts, + .adis_data = ADIS16480_DATA(16497, &adis16495_1_timeouts), }, [ADIS16497_3] = { .channels = adis16485_channels, @@ -975,7 +1027,7 @@ static const struct adis16480_chip_info adis16480_chip_info[] = { .max_dec_rate = 4250, .filter_freqs = adis16495_def_filter_freqs, .has_pps_clk_mode = true, - .timeouts = &adis16495_1_timeouts, + .adis_data = ADIS16480_DATA(16497, &adis16495_1_timeouts), }, }; @@ -1014,87 +1066,6 @@ static int adis16480_enable_irq(struct adis *adis, bool enable) return __adis_write_reg_16(adis, ADIS16480_REG_FNCTIO_CTRL, val); } -static int adis16480_initial_setup(struct iio_dev *indio_dev) -{ - struct adis16480 *st = iio_priv(indio_dev); - uint16_t prod_id; - unsigned int device_id; - int ret; - - adis_reset(&st->adis); - msleep(70); - - ret = adis_write_reg_16(&st->adis, ADIS16480_REG_GLOB_CMD, BIT(1)); - if (ret) - return ret; - msleep(30); - - ret = adis_check_status(&st->adis); - if (ret) - return ret; - - ret = adis_read_reg_16(&st->adis, ADIS16480_REG_PROD_ID, &prod_id); - if (ret) - return ret; - - ret = sscanf(indio_dev->name, "adis%u\n", &device_id); - if (ret != 1) - return -EINVAL; - - if (prod_id != device_id) - dev_warn(&indio_dev->dev, "Device ID(%u) and product ID(%u) do not match.", - device_id, prod_id); - - return 0; -} - -#define ADIS16480_DIAG_STAT_XGYRO_FAIL 0 -#define ADIS16480_DIAG_STAT_YGYRO_FAIL 1 -#define ADIS16480_DIAG_STAT_ZGYRO_FAIL 2 -#define ADIS16480_DIAG_STAT_XACCL_FAIL 3 -#define ADIS16480_DIAG_STAT_YACCL_FAIL 4 -#define ADIS16480_DIAG_STAT_ZACCL_FAIL 5 -#define ADIS16480_DIAG_STAT_XMAGN_FAIL 8 -#define ADIS16480_DIAG_STAT_YMAGN_FAIL 9 -#define ADIS16480_DIAG_STAT_ZMAGN_FAIL 10 -#define ADIS16480_DIAG_STAT_BARO_FAIL 11 - -static const char * const adis16480_status_error_msgs[] = { - [ADIS16480_DIAG_STAT_XGYRO_FAIL] = "X-axis gyroscope self-test failure", - [ADIS16480_DIAG_STAT_YGYRO_FAIL] = "Y-axis gyroscope self-test failure", - [ADIS16480_DIAG_STAT_ZGYRO_FAIL] = "Z-axis gyroscope self-test failure", - [ADIS16480_DIAG_STAT_XACCL_FAIL] = "X-axis accelerometer self-test failure", - [ADIS16480_DIAG_STAT_YACCL_FAIL] = "Y-axis accelerometer self-test failure", - [ADIS16480_DIAG_STAT_ZACCL_FAIL] = "Z-axis accelerometer self-test failure", - [ADIS16480_DIAG_STAT_XMAGN_FAIL] = "X-axis magnetometer self-test failure", - [ADIS16480_DIAG_STAT_YMAGN_FAIL] = "Y-axis magnetometer self-test failure", - [ADIS16480_DIAG_STAT_ZMAGN_FAIL] = "Z-axis magnetometer self-test failure", - [ADIS16480_DIAG_STAT_BARO_FAIL] = "Barometer self-test failure", -}; - -static const struct adis_data adis16480_data = { - .diag_stat_reg = ADIS16480_REG_DIAG_STS, - .glob_cmd_reg = ADIS16480_REG_GLOB_CMD, - .has_paging = true, - - .read_delay = 5, - .write_delay = 5, - - .status_error_msgs = adis16480_status_error_msgs, - .status_error_mask = BIT(ADIS16480_DIAG_STAT_XGYRO_FAIL) | - BIT(ADIS16480_DIAG_STAT_YGYRO_FAIL) | - BIT(ADIS16480_DIAG_STAT_ZGYRO_FAIL) | - BIT(ADIS16480_DIAG_STAT_XACCL_FAIL) | - BIT(ADIS16480_DIAG_STAT_YACCL_FAIL) | - BIT(ADIS16480_DIAG_STAT_ZACCL_FAIL) | - BIT(ADIS16480_DIAG_STAT_XMAGN_FAIL) | - BIT(ADIS16480_DIAG_STAT_YMAGN_FAIL) | - BIT(ADIS16480_DIAG_STAT_ZMAGN_FAIL) | - BIT(ADIS16480_DIAG_STAT_BARO_FAIL), - - .enable_irq = adis16480_enable_irq, -}; - static int adis16480_config_irq_pin(struct device_node *of_node, struct adis16480 *st) { @@ -1245,22 +1216,6 @@ static int adis16480_get_ext_clocks(struct adis16480 *st) return 0; } -static struct adis_data *adis16480_adis_data_alloc(struct adis16480 *st, - struct device *dev) -{ - struct adis_data *data; - - data = devm_kmalloc(dev, sizeof(struct adis_data), GFP_KERNEL); - if (!data) - return ERR_PTR(-ENOMEM); - - memcpy(data, &adis16480_data, sizeof(*data)); - - data->timeouts = st->chip_info->timeouts; - - return data; -} - static int adis16480_probe(struct spi_device *spi) { const struct spi_device_id *id = spi_get_device_id(spi); @@ -1285,26 +1240,28 @@ static int adis16480_probe(struct spi_device *spi) indio_dev->info = &adis16480_info; indio_dev->modes = INDIO_DIRECT_MODE; - adis16480_data = adis16480_adis_data_alloc(st, &spi->dev); - if (IS_ERR(adis16480_data)) - return PTR_ERR(adis16480_data); + adis16480_data = &st->chip_info->adis_data; ret = adis_init(&st->adis, indio_dev, spi, adis16480_data); if (ret) return ret; - ret = adis16480_config_irq_pin(spi->dev.of_node, st); + ret = __adis_initial_startup(&st->adis); if (ret) return ret; + ret = adis16480_config_irq_pin(spi->dev.of_node, st); + if (ret) + goto error_stop_device; + ret = adis16480_get_ext_clocks(st); if (ret) - return ret; + goto error_stop_device; if (!IS_ERR_OR_NULL(st->ext_clk)) { ret = adis16480_ext_clk_config(st, spi->dev.of_node, true); if (ret) - return ret; + goto error_stop_device; st->clk_freq = clk_get_rate(st->ext_clk); st->clk_freq *= 1000; /* micro */ @@ -1316,24 +1273,20 @@ static int adis16480_probe(struct spi_device *spi) if (ret) goto error_clk_disable_unprepare; - ret = adis16480_initial_setup(indio_dev); - if (ret) - goto error_cleanup_buffer; - ret = iio_device_register(indio_dev); if (ret) - goto error_stop_device; + goto error_cleanup_buffer; adis16480_debugfs_init(indio_dev); return 0; -error_stop_device: - adis16480_stop_device(indio_dev); error_cleanup_buffer: adis_cleanup_buffer_and_trigger(&st->adis, indio_dev); error_clk_disable_unprepare: clk_disable_unprepare(st->ext_clk); +error_stop_device: + adis16480_stop_device(indio_dev); return ret; } diff --git a/drivers/iio/imu/adis_buffer.c b/drivers/iio/imu/adis_buffer.c index 3f4dd5c00b03..04e5e2a0fd6b 100644 --- a/drivers/iio/imu/adis_buffer.c +++ b/drivers/iio/imu/adis_buffer.c @@ -97,7 +97,8 @@ int adis_update_scan_mode(struct iio_dev *indio_dev, if (j != scan_count) adis->xfer[j].cs_change = 1; adis->xfer[j].len = 2; - adis->xfer[j].delay_usecs = adis->data->read_delay; + adis->xfer[j].delay.value = adis->data->read_delay; + adis->xfer[j].delay.unit = SPI_DELAY_UNIT_USECS; if (j < scan_count) adis->xfer[j].tx_buf = &tx[j]; if (j >= 1) diff --git a/drivers/iio/imu/inv_mpu6050/Kconfig b/drivers/iio/imu/inv_mpu6050/Kconfig index 017bc0fcc365..7137ea6f25db 100644 --- a/drivers/iio/imu/inv_mpu6050/Kconfig +++ b/drivers/iio/imu/inv_mpu6050/Kconfig @@ -15,9 +15,9 @@ config INV_MPU6050_I2C select INV_MPU6050_IIO select REGMAP_I2C help - This driver supports the Invensense MPU6050/6500/6515, - MPU9150/9250/9255 and ICM20608/20602 motion tracking devices - over I2C. + This driver supports the Invensense MPU6050/9150, + MPU6500/6515/9250/9255, ICM20608/20609/20689, ICM20602/ICM20690 and + IAM20680 motion tracking devices over I2C. This driver can be built as a module. The module will be called inv-mpu6050-i2c. @@ -27,8 +27,8 @@ config INV_MPU6050_SPI select INV_MPU6050_IIO select REGMAP_SPI help - This driver supports the Invensense MPU6000/6500/6515, - MPU9250/9255 and ICM20608/20602 motion tracking devices - over SPI. + This driver supports the Invensense MPU6000, + MPU6500/6515/9250/9255, ICM20608/20609/20689, ICM20602/ICM20690 and + IAM20680 motion tracking devices over SPI. This driver can be built as a module. The module will be called inv-mpu6050-spi. diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c index 5096fc49012d..7cb9ff3d3e94 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c @@ -16,6 +16,8 @@ #include <linux/acpi.h> #include <linux/platform_device.h> #include <linux/regulator/consumer.h> +#include <linux/pm.h> +#include <linux/pm_runtime.h> #include "inv_mpu_iio.h" #include "inv_mpu_magn.h" @@ -99,9 +101,31 @@ static const struct inv_mpu6050_reg_map reg_set_6050 = { }; static const struct inv_mpu6050_chip_config chip_config_6050 = { + .clk = INV_CLK_INTERNAL, .fsr = INV_MPU6050_FSR_2000DPS, .lpf = INV_MPU6050_FILTER_20HZ, - .divider = INV_MPU6050_FIFO_RATE_TO_DIVIDER(INV_MPU6050_INIT_FIFO_RATE), + .divider = INV_MPU6050_FIFO_RATE_TO_DIVIDER(50), + .gyro_en = true, + .accl_en = true, + .temp_en = true, + .magn_en = false, + .gyro_fifo_enable = false, + .accl_fifo_enable = false, + .temp_fifo_enable = false, + .magn_fifo_enable = false, + .accl_fs = INV_MPU6050_FS_02G, + .user_ctrl = 0, +}; + +static const struct inv_mpu6050_chip_config chip_config_6500 = { + .clk = INV_CLK_PLL, + .fsr = INV_MPU6050_FSR_2000DPS, + .lpf = INV_MPU6050_FILTER_20HZ, + .divider = INV_MPU6050_FIFO_RATE_TO_DIVIDER(50), + .gyro_en = true, + .accl_en = true, + .temp_en = true, + .magn_en = false, .gyro_fifo_enable = false, .accl_fifo_enable = false, .temp_fifo_enable = false, @@ -124,7 +148,7 @@ static const struct inv_mpu6050_hw hw_info[] = { .whoami = INV_MPU6500_WHOAMI_VALUE, .name = "MPU6500", .reg = ®_set_6500, - .config = &chip_config_6050, + .config = &chip_config_6500, .fifo_size = 512, .temp = {INV_MPU6500_TEMP_OFFSET, INV_MPU6500_TEMP_SCALE}, }, @@ -132,7 +156,7 @@ static const struct inv_mpu6050_hw hw_info[] = { .whoami = INV_MPU6515_WHOAMI_VALUE, .name = "MPU6515", .reg = ®_set_6500, - .config = &chip_config_6050, + .config = &chip_config_6500, .fifo_size = 512, .temp = {INV_MPU6500_TEMP_OFFSET, INV_MPU6500_TEMP_SCALE}, }, @@ -156,7 +180,7 @@ static const struct inv_mpu6050_hw hw_info[] = { .whoami = INV_MPU9250_WHOAMI_VALUE, .name = "MPU9250", .reg = ®_set_6500, - .config = &chip_config_6050, + .config = &chip_config_6500, .fifo_size = 512, .temp = {INV_MPU6500_TEMP_OFFSET, INV_MPU6500_TEMP_SCALE}, }, @@ -164,7 +188,7 @@ static const struct inv_mpu6050_hw hw_info[] = { .whoami = INV_MPU9255_WHOAMI_VALUE, .name = "MPU9255", .reg = ®_set_6500, - .config = &chip_config_6050, + .config = &chip_config_6500, .fifo_size = 512, .temp = {INV_MPU6500_TEMP_OFFSET, INV_MPU6500_TEMP_SCALE}, }, @@ -172,104 +196,242 @@ static const struct inv_mpu6050_hw hw_info[] = { .whoami = INV_ICM20608_WHOAMI_VALUE, .name = "ICM20608", .reg = ®_set_6500, - .config = &chip_config_6050, + .config = &chip_config_6500, .fifo_size = 512, .temp = {INV_ICM20608_TEMP_OFFSET, INV_ICM20608_TEMP_SCALE}, }, { + .whoami = INV_ICM20609_WHOAMI_VALUE, + .name = "ICM20609", + .reg = ®_set_6500, + .config = &chip_config_6500, + .fifo_size = 4 * 1024, + .temp = {INV_ICM20608_TEMP_OFFSET, INV_ICM20608_TEMP_SCALE}, + }, + { + .whoami = INV_ICM20689_WHOAMI_VALUE, + .name = "ICM20689", + .reg = ®_set_650 |