diff options
Diffstat (limited to 'drivers/iio/imu')
-rw-r--r-- | drivers/iio/imu/adis.c | 139 | ||||
-rw-r--r-- | drivers/iio/imu/adis16400.c | 115 | ||||
-rw-r--r-- | drivers/iio/imu/adis16460.c | 7 | ||||
-rw-r--r-- | drivers/iio/imu/adis16480.c | 92 | ||||
-rw-r--r-- | drivers/iio/imu/adis_buffer.c | 4 | ||||
-rw-r--r-- | drivers/iio/imu/inv_mpu6050/Kconfig | 9 | ||||
-rw-r--r-- | drivers/iio/imu/inv_mpu6050/inv_mpu_core.c | 237 | ||||
-rw-r--r-- | drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c | 2 | ||||
-rw-r--r-- | drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h | 22 | ||||
-rw-r--r-- | drivers/iio/imu/inv_mpu6050/inv_mpu_magn.c | 80 | ||||
-rw-r--r-- | drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c | 11 | ||||
-rw-r--r-- | drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c | 1 | ||||
-rw-r--r-- | drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c | 4 | ||||
-rw-r--r-- | drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h | 49 | ||||
-rw-r--r-- | drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c | 27 | ||||
-rw-r--r-- | drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c | 121 | ||||
-rw-r--r-- | drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c | 3 | ||||
-rw-r--r-- | drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c | 76 | ||||
-rw-r--r-- | drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c | 3 |
19 files changed, 664 insertions, 338 deletions
diff --git a/drivers/iio/imu/adis.c b/drivers/iio/imu/adis.c index e14c8536fd09..022bb54fb748 100644 --- a/drivers/iio/imu/adis.c +++ b/drivers/iio/imu/adis.c @@ -26,7 +26,14 @@ #define ADIS_MSC_CTRL_DATA_RDY_DIO2 BIT(0) #define ADIS_GLOB_CMD_SW_RESET BIT(7) -int adis_write_reg(struct adis *adis, unsigned int reg, +/** + * __adis_write_reg() - write N bytes to register (unlocked version) + * @adis: The adis device + * @reg: The address of the lower of the two registers + * @value: The value to write to device (up to 4 bytes) + * @size: The size of the @value (in bytes) + */ +int __adis_write_reg(struct adis *adis, unsigned int reg, unsigned int value, unsigned int size) { unsigned int page = reg / ADIS_PAGE_SIZE; @@ -38,7 +45,8 @@ int adis_write_reg(struct adis *adis, unsigned int reg, .bits_per_word = 8, .len = 2, .cs_change = 1, - .delay_usecs = adis->data->write_delay, + .delay.value = adis->data->write_delay, + .delay.unit = SPI_DELAY_UNIT_USECS, .cs_change_delay.value = adis->data->cs_change_delay, .cs_change_delay.unit = SPI_DELAY_UNIT_USECS, }, { @@ -46,7 +54,8 @@ int adis_write_reg(struct adis *adis, unsigned int reg, .bits_per_word = 8, .len = 2, .cs_change = 1, - .delay_usecs = adis->data->write_delay, + .delay.value = adis->data->write_delay, + .delay.unit = SPI_DELAY_UNIT_USECS, .cs_change_delay.value = adis->data->cs_change_delay, .cs_change_delay.unit = SPI_DELAY_UNIT_USECS, }, { @@ -54,24 +63,25 @@ int adis_write_reg(struct adis *adis, unsigned int reg, .bits_per_word = 8, .len = 2, .cs_change = 1, - .delay_usecs = adis->data->write_delay, + .delay.value = adis->data->write_delay, + .delay.unit = SPI_DELAY_UNIT_USECS, .cs_change_delay.value = adis->data->cs_change_delay, .cs_change_delay.unit = SPI_DELAY_UNIT_USECS, }, { .tx_buf = adis->tx + 6, .bits_per_word = 8, .len = 2, - .delay_usecs = adis->data->write_delay, + .delay.value = adis->data->write_delay, + .delay.unit = SPI_DELAY_UNIT_USECS, }, { .tx_buf = adis->tx + 8, .bits_per_word = 8, .len = 2, - .delay_usecs = adis->data->write_delay, + .delay.value = adis->data->write_delay, + .delay.unit = SPI_DELAY_UNIT_USECS, }, }; - mutex_lock(&adis->txrx_lock); - spi_message_init(&msg); if (adis->current_page != page) { @@ -96,8 +106,7 @@ int adis_write_reg(struct adis *adis, unsigned int reg, adis->tx[3] = value & 0xff; break; default: - ret = -EINVAL; - goto out_unlock; + return -EINVAL; } xfers[size].cs_change = 0; @@ -113,20 +122,18 @@ int adis_write_reg(struct adis *adis, unsigned int reg, adis->current_page = page; } -out_unlock: - mutex_unlock(&adis->txrx_lock); - return ret; } -EXPORT_SYMBOL_GPL(adis_write_reg); +EXPORT_SYMBOL_GPL(__adis_write_reg); /** - * adis_read_reg() - read 2 bytes from a 16-bit register + * __adis_read_reg() - read N bytes from register (unlocked version) * @adis: The adis device * @reg: The address of the lower of the two registers * @val: The value read back from the device + * @size: The size of the @val buffer */ -int adis_read_reg(struct adis *adis, unsigned int reg, +int __adis_read_reg(struct adis *adis, unsigned int reg, unsigned int *val, unsigned int size) { unsigned int page = reg / ADIS_PAGE_SIZE; @@ -138,7 +145,8 @@ int adis_read_reg(struct adis *adis, unsigned int reg, .bits_per_word = 8, .len = 2, .cs_change = 1, - .delay_usecs = adis->data->write_delay, + .delay.value = adis->data->write_delay, + .delay.unit = SPI_DELAY_UNIT_USECS, .cs_change_delay.value = adis->data->cs_change_delay, .cs_change_delay.unit = SPI_DELAY_UNIT_USECS, }, { @@ -146,7 +154,8 @@ int adis_read_reg(struct adis *adis, unsigned int reg, .bits_per_word = 8, .len = 2, .cs_change = 1, - .delay_usecs = adis->data->read_delay, + .delay.value = adis->data->read_delay, + .delay.unit = SPI_DELAY_UNIT_USECS, .cs_change_delay.value = adis->data->cs_change_delay, .cs_change_delay.unit = SPI_DELAY_UNIT_USECS, }, { @@ -155,18 +164,19 @@ int adis_read_reg(struct adis *adis, unsigned int reg, .bits_per_word = 8, .len = 2, .cs_change = 1, - .delay_usecs = adis->data->read_delay, + .delay.value = adis->data->read_delay, + .delay.unit = SPI_DELAY_UNIT_USECS, .cs_change_delay.value = adis->data->cs_change_delay, .cs_change_delay.unit = SPI_DELAY_UNIT_USECS, }, { .rx_buf = adis->rx + 2, .bits_per_word = 8, .len = 2, - .delay_usecs = adis->data->read_delay, + .delay.value = adis->data->read_delay, + .delay.unit = SPI_DELAY_UNIT_USECS, }, }; - mutex_lock(&adis->txrx_lock); spi_message_init(&msg); if (adis->current_page != page) { @@ -188,15 +198,14 @@ int adis_read_reg(struct adis *adis, unsigned int reg, spi_message_add_tail(&xfers[3], &msg); break; default: - ret = -EINVAL; - goto out_unlock; + return -EINVAL; } ret = spi_sync(adis->spi, &msg); if (ret) { dev_err(&adis->spi->dev, "Failed to read register 0x%02X: %d\n", reg, ret); - goto out_unlock; + return ret; } else { adis->current_page = page; } @@ -210,12 +219,9 @@ int adis_read_reg(struct adis *adis, unsigned int reg, break; } -out_unlock: - mutex_unlock(&adis->txrx_lock); - return ret; } -EXPORT_SYMBOL_GPL(adis_read_reg); +EXPORT_SYMBOL_GPL(__adis_read_reg); #ifdef CONFIG_DEBUG_FS @@ -253,12 +259,16 @@ int adis_enable_irq(struct adis *adis, bool enable) int ret = 0; uint16_t msc; - if (adis->data->enable_irq) - return adis->data->enable_irq(adis, enable); + mutex_lock(&adis->state_lock); + + if (adis->data->enable_irq) { + ret = adis->data->enable_irq(adis, enable); + goto out_unlock; + } - ret = adis_read_reg_16(adis, adis->data->msc_ctrl_reg, &msc); + ret = __adis_read_reg_16(adis, adis->data->msc_ctrl_reg, &msc); if (ret) - goto error_ret; + goto out_unlock; msc |= ADIS_MSC_CTRL_DATA_RDY_POL_HIGH; msc &= ~ADIS_MSC_CTRL_DATA_RDY_DIO2; @@ -267,26 +277,27 @@ int adis_enable_irq(struct adis *adis, bool enable) else msc &= ~ADIS_MSC_CTRL_DATA_RDY_EN; - ret = adis_write_reg_16(adis, adis->data->msc_ctrl_reg, msc); + ret = __adis_write_reg_16(adis, adis->data->msc_ctrl_reg, msc); -error_ret: +out_unlock: + mutex_unlock(&adis->state_lock); return ret; } EXPORT_SYMBOL(adis_enable_irq); /** - * adis_check_status() - Check the device for error conditions + * __adis_check_status() - Check the device for error conditions (unlocked) * @adis: The adis device * * Returns 0 on success, a negative error code otherwise */ -int adis_check_status(struct adis *adis) +int __adis_check_status(struct adis *adis) { uint16_t status; int ret; int i; - ret = adis_read_reg_16(adis, adis->data->diag_stat_reg, &status); + ret = __adis_read_reg_16(adis, adis->data->diag_stat_reg, &status); if (ret) return ret; @@ -304,32 +315,38 @@ int adis_check_status(struct adis *adis) return -EIO; } -EXPORT_SYMBOL_GPL(adis_check_status); +EXPORT_SYMBOL_GPL(__adis_check_status); /** - * adis_reset() - Reset the device + * __adis_reset() - Reset the device (unlocked version) * @adis: The adis device * * Returns 0 on success, a negative error code otherwise */ -int adis_reset(struct adis *adis) +int __adis_reset(struct adis *adis) { int ret; + const struct adis_timeout *timeouts = adis->data->timeouts; - ret = adis_write_reg_8(adis, adis->data->glob_cmd_reg, + ret = __adis_write_reg_8(adis, adis->data->glob_cmd_reg, ADIS_GLOB_CMD_SW_RESET); - if (ret) + if (ret) { dev_err(&adis->spi->dev, "Failed to reset device: %d\n", ret); + return ret; + } - return ret; + msleep(timeouts->sw_reset_ms); + + return 0; } -EXPORT_SYMBOL_GPL(adis_reset); +EXPORT_SYMBOL_GPL(__adis_reset); 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, + ret = __adis_write_reg_16(adis, adis->data->msc_ctrl_reg, adis->data->self_test_mask); if (ret) { dev_err(&adis->spi->dev, "Failed to initiate self test: %d\n", @@ -337,12 +354,12 @@ static int adis_self_test(struct adis *adis) return ret; } - msleep(adis->data->startup_delay); + msleep(timeouts->self_test_ms); - ret = adis_check_status(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->msc_ctrl_reg, 0x00); return ret; } @@ -360,19 +377,22 @@ int adis_initial_startup(struct adis *adis) { int ret; + mutex_lock(&adis->state_lock); + ret = adis_self_test(adis); if (ret) { dev_err(&adis->spi->dev, "Self-test failed, trying reset.\n"); - adis_reset(adis); - msleep(adis->data->startup_delay); + __adis_reset(adis); ret = adis_self_test(adis); if (ret) { dev_err(&adis->spi->dev, "Second self-test failed, giving up.\n"); - return ret; + goto out_unlock; } } - return 0; +out_unlock: + mutex_unlock(&adis->state_lock); + return ret; } EXPORT_SYMBOL_GPL(adis_initial_startup); @@ -398,15 +418,15 @@ int adis_single_conversion(struct iio_dev *indio_dev, unsigned int uval; int ret; - mutex_lock(&indio_dev->mlock); + mutex_lock(&adis->state_lock); - ret = adis_read_reg(adis, chan->address, &uval, + ret = __adis_read_reg(adis, chan->address, &uval, chan->scan_type.storagebits / 8); if (ret) goto err_unlock; if (uval & error_mask) { - ret = adis_check_status(adis); + ret = __adis_check_status(adis); if (ret) goto err_unlock; } @@ -418,7 +438,7 @@ int adis_single_conversion(struct iio_dev *indio_dev, ret = IIO_VAL_INT; err_unlock: - mutex_unlock(&indio_dev->mlock); + mutex_unlock(&adis->state_lock); return ret; } EXPORT_SYMBOL_GPL(adis_single_conversion); @@ -438,7 +458,12 @@ EXPORT_SYMBOL_GPL(adis_single_conversion); int adis_init(struct adis *adis, struct iio_dev *indio_dev, struct spi_device *spi, const struct adis_data *data) { - mutex_init(&adis->txrx_lock); + if (!data || !data->timeouts) { + dev_err(&spi->dev, "No config data or timeouts not defined!\n"); + return -EINVAL; + } + + mutex_init(&adis->state_lock); adis->spi = spi; adis->data = data; iio_device_set_drvdata(indio_dev, adis); diff --git a/drivers/iio/imu/adis16400.c b/drivers/iio/imu/adis16400.c index 44e46dc96e00..cfb1c19eb930 100644 --- a/drivers/iio/imu/adis16400.c +++ b/drivers/iio/imu/adis16400.c @@ -156,12 +156,14 @@ struct adis16400_state; struct adis16400_chip_info { const struct iio_chan_spec *channels; + const struct adis_timeout *timeouts; const int num_channels; const long flags; unsigned int gyro_scale_micro; unsigned int accel_scale_micro; int temp_scale_nano; int temp_offset; + /* set_freq() & get_freq() need to avoid using ADIS lib's state lock */ int (*set_freq)(struct adis16400_state *st, unsigned int freq); int (*get_freq)(struct adis16400_state *st); }; @@ -326,7 +328,7 @@ static int adis16334_get_freq(struct adis16400_state *st) int ret; uint16_t t; - ret = adis_read_reg_16(&st->adis, ADIS16400_SMPL_PRD, &t); + ret = __adis_read_reg_16(&st->adis, ADIS16400_SMPL_PRD, &t); if (ret) return ret; @@ -350,7 +352,7 @@ static int adis16334_set_freq(struct adis16400_state *st, unsigned int freq) t <<= ADIS16334_RATE_DIV_SHIFT; t |= ADIS16334_RATE_INT_CLK; - return adis_write_reg_16(&st->adis, ADIS16400_SMPL_PRD, t); + return __adis_write_reg_16(&st->adis, ADIS16400_SMPL_PRD, t); } static int adis16400_get_freq(struct adis16400_state *st) @@ -358,7 +360,7 @@ static int adis16400_get_freq(struct adis16400_state *st) int sps, ret; uint16_t t; - ret = adis_read_reg_16(&st->adis, ADIS16400_SMPL_PRD, &t); + ret = __adis_read_reg_16(&st->adis, ADIS16400_SMPL_PRD, &t); if (ret) return ret; @@ -390,7 +392,7 @@ static int adis16400_set_freq(struct adis16400_state *st, unsigned int freq) else st->adis.spi->max_speed_hz = ADIS16400_SPI_FAST; - return adis_write_reg_8(&st->adis, ADIS16400_SMPL_PRD, val); + return __adis_write_reg_8(&st->adis, ADIS16400_SMPL_PRD, val); } static const unsigned int adis16400_3db_divisors[] = { @@ -404,7 +406,7 @@ static const unsigned int adis16400_3db_divisors[] = { [7] = 200, /* Not a valid setting */ }; -static int adis16400_set_filter(struct iio_dev *indio_dev, int sps, int val) +static int __adis16400_set_filter(struct iio_dev *indio_dev, int sps, int val) { struct adis16400_state *st = iio_priv(indio_dev); uint16_t val16; @@ -415,11 +417,11 @@ static int adis16400_set_filter(struct iio_dev *indio_dev, int sps, int val) break; } - ret = adis_read_reg_16(&st->adis, ADIS16400_SENS_AVG, &val16); + ret = __adis_read_reg_16(&st->adis, ADIS16400_SENS_AVG, &val16); if (ret) return ret; - ret = adis_write_reg_16(&st->adis, ADIS16400_SENS_AVG, + ret = __adis_write_reg_16(&st->adis, ADIS16400_SENS_AVG, (val16 & ~0x07) | i); return ret; } @@ -507,32 +509,31 @@ 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; switch (info) { case IIO_CHAN_INFO_CALIBBIAS: - mutex_lock(&indio_dev->mlock); ret = adis_write_reg_16(&st->adis, adis16400_addresses[chan->scan_index], val); - mutex_unlock(&indio_dev->mlock); return ret; case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: /* * Need to cache values so we can update if the frequency * changes. */ - mutex_lock(&indio_dev->mlock); + mutex_lock(slock); st->filt_int = val; /* Work out update to current value */ sps = st->variant->get_freq(st); if (sps < 0) { - mutex_unlock(&indio_dev->mlock); + mutex_unlock(slock); return sps; } - ret = adis16400_set_filter(indio_dev, sps, + ret = __adis16400_set_filter(indio_dev, sps, val * 1000 + val2 / 1000); - mutex_unlock(&indio_dev->mlock); + mutex_unlock(slock); return ret; case IIO_CHAN_INFO_SAMP_FREQ: sps = val * 1000 + val2 / 1000; @@ -540,9 +541,9 @@ static int adis16400_write_raw(struct iio_dev *indio_dev, if (sps <= 0) return -EINVAL; - mutex_lock(&indio_dev->mlock); + mutex_lock(slock); ret = st->variant->set_freq(st, sps); - mutex_unlock(&indio_dev->mlock); + mutex_unlock(slock); return ret; default: return -EINVAL; @@ -553,6 +554,7 @@ 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; @@ -596,10 +598,8 @@ static int adis16400_read_raw(struct iio_dev *indio_dev, return -EINVAL; } case IIO_CHAN_INFO_CALIBBIAS: - mutex_lock(&indio_dev->mlock); ret = adis_read_reg_16(&st->adis, adis16400_addresses[chan->scan_index], &val16); - mutex_unlock(&indio_dev->mlock); if (ret) return ret; val16 = sign_extend32(val16, 11); @@ -610,27 +610,27 @@ 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(&indio_dev->mlock); + mutex_lock(slock); /* Need both the number of taps and the sampling frequency */ - ret = adis_read_reg_16(&st->adis, + ret = __adis_read_reg_16(&st->adis, ADIS16400_SENS_AVG, &val16); if (ret) { - mutex_unlock(&indio_dev->mlock); + mutex_unlock(slock); return ret; } ret = st->variant->get_freq(st); - if (ret >= 0) { - ret /= adis16400_3db_divisors[val16 & 0x07]; - *val = ret / 1000; - *val2 = (ret % 1000) * 1000; - } - mutex_unlock(&indio_dev->mlock); + 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; *val = ret / 1000; @@ -930,6 +930,36 @@ static const struct iio_chan_spec adis16334_channels[] = { IIO_CHAN_SOFT_TIMESTAMP(ADIS16400_SCAN_TIMESTAMP), }; +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 adis16362_timeouts = { + .reset_ms = 130, + .sw_reset_ms = 130, + .self_test_ms = 12, +}; + +static const struct adis_timeout adis16400_timeouts = { + .reset_ms = 170, + .sw_reset_ms = 170, + .self_test_ms = 12, +}; + +static const struct adis_timeout adis16445_timeouts = { + .reset_ms = 55, + .sw_reset_ms = 55, + .self_test_ms = 16, +}; + +static const struct adis_timeout adis16448_timeouts = { + .reset_ms = 90, + .sw_reset_ms = 90, + .self_test_ms = 45, +}; + static struct adis16400_chip_info adis16400_chips[] = { [ADIS16300] = { .channels = adis16300_channels, @@ -942,6 +972,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, }, [ADIS16334] = { .channels = adis16334_channels, @@ -965,6 +996,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, }, [ADIS16360] = { .channels = adis16350_channels, @@ -977,6 +1009,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, }, [ADIS16362] = { .channels = adis16350_channels, @@ -989,6 +1022,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, }, [ADIS16364] = { .channels = adis16350_channels, @@ -1001,6 +1035,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, }, [ADIS16367] = { .channels = adis16350_channels, @@ -1013,6 +1048,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, }, [ADIS16400] = { .channels = adis16400_channels, @@ -1024,6 +1060,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, }, [ADIS16445] = { .channels = adis16445_channels, @@ -1037,6 +1074,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, }, [ADIS16448] = { .channels = adis16448_channels, @@ -1050,6 +1088,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, } }; @@ -1087,7 +1126,6 @@ static const struct adis_data adis16400_data = { .write_delay = 50, .self_test_mask = ADIS16400_MSC_CTRL_MEM_TEST, - .startup_delay = ADIS16400_STARTUP_DELAY, .status_error_msgs = adis16400_status_error_msgs, .status_error_mask = BIT(ADIS16400_DIAG_STAT_ZACCL_FAIL) | @@ -1121,11 +1159,28 @@ static void adis16400_setup_chan_mask(struct adis16400_state *st) } } +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; struct iio_dev *indio_dev; int ret; + const struct adis_data *adis16400_data; indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); if (indio_dev == NULL) @@ -1152,7 +1207,11 @@ static int adis16400_probe(struct spi_device *spi) st->adis.burst->extra_len = sizeof(u16); } - ret = adis_init(&st->adis, indio_dev, spi, &adis16400_data); + adis16400_data = adis16400_adis_data_alloc(st, &spi->dev); + if (IS_ERR(adis16400_data)) + return PTR_ERR(adis16400_data); + + ret = adis_init(&st->adis, indio_dev, spi, adis16400_data); if (ret) return ret; diff --git a/drivers/iio/imu/adis16460.c b/drivers/iio/imu/adis16460.c index b55812521537..9539cfe4a259 100644 --- a/drivers/iio/imu/adis16460.c +++ b/drivers/iio/imu/adis16460.c @@ -383,6 +383,12 @@ static const char * const adis16460_status_error_msgs[] = { [ADIS16460_DIAG_STAT_FLASH_UPT] = "Flash update failure", }; +static const struct adis_timeout adis16460_timeouts = { + .reset_ms = 225, + .sw_reset_ms = 225, + .self_test_ms = 10, +}; + static const struct adis_data adis16460_data = { .diag_stat_reg = ADIS16460_REG_DIAG_STAT, .glob_cmd_reg = ADIS16460_REG_GLOB_CMD, @@ -398,6 +404,7 @@ static const struct adis_data adis16460_data = { BIT(ADIS16460_DIAG_STAT_SPI_COMM) | BIT(ADIS16460_DIAG_STAT_FLASH_UPT), .enable_irq = adis16460_enable_irq, + .timeouts = &adis16460_timeouts, }; static int adis16460_probe(struct spi_device *spi) diff --git a/drivers/iio/imu/adis16480.c b/drivers/iio/imu/adis16480.c index 748f8bbf184d..dac87f1001fd 100644 --- a/drivers/iio/imu/adis16480.c +++ b/drivers/iio/imu/adis16480.c @@ -138,6 +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; }; enum adis16480_int_pin { @@ -555,6 +556,7 @@ static int adis16480_set_filter_freq(struct iio_dev *indio_dev, const struct iio_chan_spec *chan, unsigned int freq) { struct adis16480 *st = iio_priv(indio_dev); + struct mutex *slock = &st->adis.state_lock; unsigned int enable_mask, offset, reg; unsigned int diff, best_diff; unsigned int i, best_freq; @@ -565,9 +567,11 @@ static int adis16480_set_filter_freq(struct iio_dev *indio_dev, offset = ad16480_filter_data[chan->scan_index][1]; enable_mask = BIT(offset + 2); - ret = adis_read_reg_16(&st->adis, reg, &val); + mutex_lock(slock); + + ret = __adis_read_reg_16(&st->adis, reg, &val); if (ret) - return ret; + goto out_unlock; if (freq == 0) { val &= ~enable_mask; @@ -589,7 +593,11 @@ static int adis16480_set_filter_freq(struct iio_dev *indio_dev, val |= enable_mask; } - return adis_write_reg_16(&st->adis, reg, val); + ret = __adis_write_reg_16(&st->adis, reg, val); +out_unlock: + mutex_unlock(slock); + + return ret; } static int adis16480_read_raw(struct iio_dev *indio_dev, @@ -779,6 +787,7 @@ enum adis16480_variant { ADIS16480, ADIS16485, ADIS16488, + ADIS16490, ADIS16495_1, ADIS16495_2, ADIS16495_3, @@ -787,6 +796,30 @@ enum adis16480_variant { ADIS16497_3, }; +static const struct adis_timeout adis16485_timeouts = { + .reset_ms = 560, + .sw_reset_ms = 120, + .self_test_ms = 12, +}; + +static const struct adis_timeout adis16480_timeouts = { + .reset_ms = 560, + .sw_reset_ms = 560, + .self_test_ms = 12, +}; + +static const struct adis_timeout adis16495_timeouts = { + .reset_ms = 170, + .sw_reset_ms = 130, + .self_test_ms = 40, +}; + +static const struct adis_timeout adis16495_1_timeouts = { + .reset_ms = 250, + .sw_reset_ms = 210, + .self_test_ms = 20, +}; + static const struct adis16480_chip_info adis16480_chip_info[] = { [ADIS16375] = { .channels = adis16485_channels, @@ -805,6 +838,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, }, [ADIS16480] = { .channels = adis16480_channels, @@ -817,6 +851,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, }, [ADIS16485] = { .channels = adis16485_channels, @@ -829,6 +864,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, }, [ADIS16488] = { .channels = adis16480_channels, @@ -841,6 +877,21 @@ 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, + }, + [ADIS16490] = { + .channels = adis16485_channels, + .num_channels = ARRAY_SIZE(adis16485_channels), + .gyro_max_val = 20000 << 16, + .gyro_max_scale = IIO_DEGREE_TO_RAD(100), + .accel_max_val = IIO_M_S_2_TO_G(16000 << 16), + .accel_max_scale = 8, + .temp_scale = 14285, /* 14.285 milli degree Celsius */ + .int_clk = 4250000, + .max_dec_rate = 4250, + .filter_freqs = adis16495_def_filter_freqs, + .has_pps_clk_mode = true, + .timeouts = &adis16495_timeouts, }, [ADIS16495_1] = { .channels = adis16485_channels, @@ -854,6 +905,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, }, [ADIS16495_2] = { .channels = adis16485_channels, @@ -867,6 +919,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, }, [ADIS16495_3] = { .channels = adis16485_channels, @@ -880,6 +933,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, }, [ADIS16497_1] = { .channels = adis16485_channels, @@ -893,6 +947,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, }, [ADIS16497_2] = { .channels = adis16485_channels, @@ -906,6 +961,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, }, [ADIS16497_3] = { .channels = adis16485_channels, @@ -919,6 +975,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, }, }; @@ -947,14 +1004,14 @@ static int adis16480_enable_irq(struct adis *adis, bool enable) uint16_t val; int ret; - ret = adis_read_reg_16(adis, ADIS16480_REG_FNCTIO_CTRL, &val); + ret = __adis_read_reg_16(adis, ADIS16480_REG_FNCTIO_CTRL, &val); if (ret) return ret; val &= ~ADIS16480_DRDY_EN_MSK; val |= ADIS16480_DRDY_EN(enable); - return adis_write_reg_16(adis, ADIS16480_REG_FNCTIO_CTRL, val); + return __adis_write_reg_16(adis, ADIS16480_REG_FNCTIO_CTRL, val); } static int adis16480_initial_setup(struct iio_dev *indio_dev) @@ -1188,9 +1245,26 @@ 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); + const struct adis_data *adis16480_data; struct iio_dev *indio_dev; struct adis16480 *st; int ret; @@ -1211,7 +1285,11 @@ static int adis16480_probe(struct spi_device *spi) indio_dev->info = &adis16480_info; indio_dev->modes = INDIO_DIRECT_MODE; - ret = adis_init(&st->adis, indio_dev, spi, &adis16480_data); + adis16480_data = adis16480_adis_data_alloc(st, &spi->dev); + if (IS_ERR(adis16480_data)) + return PTR_ERR(adis16480_data); + + ret = adis_init(&st->adis, indio_dev, spi, adis16480_data); if (ret) return ret; @@ -1278,6 +1356,7 @@ static const struct spi_device_id adis16480_ids[] = { { "adis16480", ADIS16480 }, { "adis16485", ADIS16485 }, { "adis16488", ADIS16488 }, + { "adis16490", ADIS16490 }, { "adis16495-1", ADIS16495_1 }, { "adis16495-2", ADIS16495_2 }, { "adis16495-3", ADIS16495_3 }, @@ -1293,6 +1372,7 @@ static const struct of_device_id adis16480_of_match[] = { { .compatible = "adi,adis16480" }, { .compatible = "adi,adis16485" }, { .compatible = "adi,adis16488" }, + { .compatible = "adi,adis16490" }, { .compatible = "adi,adis16495-1" }, { .compatible = "adi,adis16495-2" }, { .compatible = "adi,adis16495-3" }, diff --git a/drivers/iio/imu/adis_buffer.c b/drivers/iio/imu/adis_buffer.c index 4998a89d083d..3f4dd5c00b03 100644 --- a/drivers/iio/imu/adis_buffer.c +++ b/drivers/iio/imu/adis_buffer.c @@ -129,7 +129,7 @@ static irqreturn_t adis_trigger_handler(int irq, void *p) return -ENOMEM; if (adis->data->has_paging) { - mutex_lock(&adis->txrx_lock); + mutex_lock(&adis->state_lock); if (adis->current_page != 0) { adis->tx[0] = ADIS_WRITE_REG(ADIS_REG_PAGE_ID); adis->tx[1] = 0; @@ -144,7 +144,7 @@ static irqreturn_t adis_trigger_handler(int irq, void *p) if (adis->data->has_paging) { adis->current_page = 0; - mutex_unlock(&adis->txrx_lock); + mutex_unlock(&adis->state_lock); } iio_push_to_buffers_with_timestamp(indio_dev, adis->buffer, diff --git a/drivers/iio/imu/inv_mpu6050/Kconfig b/drivers/iio/imu/inv_mpu6050/Kconfig index e4c4c12236a7..017bc0fcc365 100644 --- a/drivers/iio/imu/inv_mpu6050/Kconfig +++ b/drivers/iio/imu/inv_mpu6050/Kconfig @@ -10,11 +10,12 @@ config INV_MPU6050_IIO config INV_MPU6050_I2C tristate "Invensense MPU6050 devices (I2C)" - depends on I2C_MUX + depends on I2C + select I2C_MUX select INV_MPU6050_IIO select REGMAP_I2C help - This driver supports the Invensense MPU6000/6050/6500/6515, + This driver supports the Invensense MPU6050/6500/6515, MPU9150/9250/9255 and ICM20608/20602 motion tracking devices over I2C. This driver can be built as a module. The module will be called @@ -26,8 +27,8 @@ config INV_MPU6050_SPI select INV_MPU6050_IIO select REGMAP_SPI help - This driver supports the Invensense MPU6000/6050/6500/6515, - MPU9150/9250/9255 and ICM20608/20602 motion tracking devices + This driver supports the Invensense MPU6000/6500/6515, + MPU9250/9255 and ICM20608/20602 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 0686e41bb8a1..5096fc49012d 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c @@ -104,6 +104,7 @@ static const struct inv_mpu6050_chip_config chip_config_6050 = { .divider = INV_MPU6050_FIFO_RATE_TO_DIVIDER(INV_MPU6050_INIT_FIFO_RATE), .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, @@ -856,19 +857,27 @@ static const struct iio_chan_spec_ext_info inv_ext_info[] = { .ext_info = inv_ext_info, \ } +#define INV_MPU6050_TEMP_CHAN(_index) \ + { \ + .type = IIO_TEMP, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) \ + | BIT(IIO_CHAN_INFO_OFFSET) \ + | BIT(IIO_CHAN_INFO_SCALE), \ + .scan_index = _index, \ + .scan_type = { \ + .sign = 's', \ + .realbits = 16, \ + .storagebits = 16, \ + .shift = 0, \ + .endianness = IIO_BE, \ + }, \ + } + static const struct iio_chan_spec inv_mpu_channels[] = { IIO_CHAN_SOFT_TIMESTAMP(INV_MPU6050_SCAN_TIMESTAMP), - /* - * Note that temperature should only be via polled reading only, - * not the final scan elements output. - */ - { - .type = IIO_TEMP, - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) - | BIT(IIO_CHAN_INFO_OFFSET) - | BIT(IIO_CHAN_INFO_SCALE), - .scan_index = -1, - }, + + INV_MPU6050_TEMP_CHAN(INV_MPU6050_SCAN_TEMP), + INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_X, INV_MPU6050_SCAN_GYRO_X), INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_Y, INV_MPU6050_SCAN_GYRO_Y), INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_Z, INV_MPU6050_SCAN_GYRO_Z), @@ -878,22 +887,29 @@ static const struct iio_chan_spec inv_mpu_channels[] = { INV_MPU6050_CHAN(IIO_ACCEL, IIO_MOD_Z, INV_MPU6050_SCAN_ACCL_Z), }; +#define INV_MPU6050_SCAN_MASK_3AXIS_ACCEL \ + (BIT(INV_MPU6050_SCAN_ACCL_X) \ + | BIT(INV_MPU6050_SCAN_ACCL_Y) \ + | BIT(INV_MPU6050_SCAN_ACCL_Z)) + +#define INV_MPU6050_SCAN_MASK_3AXIS_GYRO \ + (BIT(INV_MPU6050_SCAN_GYRO_X) \ + | BIT(INV_MPU6050_SCAN_GYRO_Y) \ + | BIT(INV_MPU6050_SCAN_GYRO_Z)) + +#define INV_MPU6050_SCAN_MASK_TEMP (BIT(INV_MPU6050_SCAN_TEMP)) + static const unsigned long inv_mpu_scan_masks[] = { /* 3-axis accel */ - BIT(INV_MPU6050_SCAN_ACCL_X) - | BIT(INV_MPU6050_SCAN_ACCL_Y) - | BIT(INV_MPU6050_SCAN_ACCL_Z), + INV_MPU6050_SCAN_MASK_3AXIS_ACCEL, + INV_MPU6050_SCAN_MASK_3AXIS_ACCEL | INV_MPU6050_SCAN_MASK_TEMP, /* 3-axis gyro */ - BIT(INV_MPU6050_SCAN_GYRO_X) - | BIT(INV_MPU6050_SCAN_GYRO_Y) - | BIT(INV_MPU6050_SCAN_GYRO_Z), + INV_MPU6050_SCAN_MASK_3AXIS_GYRO, + INV_MPU6050_SCAN_MASK_3AXIS_GYRO | INV_MPU6050_SCAN_MASK_TEMP, /* 6-axis accel + gyro */ - BIT(INV_MPU6050_SCAN_ACCL_X) - | BIT(INV_MPU6050_SCAN_ACCL_Y) - | BIT(INV_MPU6050_SCAN_ACCL_Z) - | BIT(INV_MPU6050_SCAN_GYRO_X) - | BIT(INV_MPU6050_SCAN_GYRO_Y) - | BIT(INV_MPU6050_SCAN_GYRO_Z), + INV_MPU6050_SCAN_MASK_3AXIS_ACCEL | INV_MPU6050_SCAN_MASK_3AXIS_GYRO, + INV_MPU6050_SCAN_MASK_3AXIS_ACCEL | INV_MPU6050_SCAN_MASK_3AXIS_GYRO + | INV_MPU6050_SCAN_MASK_TEMP, 0, }; @@ -915,19 +931,30 @@ static const unsigned long inv_mpu_scan_masks[] = { .ext_info = inv_ext_info, \ } +static const struct iio_chan_spec inv_mpu9150_channels[] = { + IIO_CHAN_SOFT_TIMESTAMP(INV_MPU9X50_SCAN_TIMESTAMP), + + INV_MPU6050_TEMP_CHAN(INV_MPU6050_SCAN_TEMP), + + INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_X, INV_MPU6050_SCAN_GYRO_X), + INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_Y, INV_MPU6050_SCAN_GYRO_Y), + INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_Z, INV_MPU6050_SCAN_GYRO_Z), + + INV_MPU6050_CHAN(IIO_ACCEL, IIO_MOD_X, INV_MPU6050_SCAN_ACCL_X), + INV_MPU6050_CHAN(IIO_ACCEL, IIO_MOD_Y, INV_MPU6050_SCAN_ACCL_Y), + INV_MPU6050_CHAN(IIO_ACCEL, IIO_MOD_Z, INV_MPU6050_SCAN_ACCL_Z), + + /* Magnetometer resolution is 13 bits */ + INV_MPU9X50_MAGN_CHAN(IIO_MOD_X, 13, INV_MPU9X50_SCAN_MAGN_X), + INV_MPU9X50_MAGN_CHAN(IIO_MOD_Y, 13, INV_MPU9X50_SCAN_MAGN_Y), + INV_MPU9X50_MAGN_CHAN(IIO_MOD_Z, 13, INV_MPU9X50_SCAN_MAGN_Z), +}; + static const struct iio_chan_spec inv_mpu9250_channels[] = { IIO_CHAN_SOFT_TIMESTAMP(INV_MPU9X50_SCAN_TIMESTAMP), - /* - * Note that temperature should only be via polled reading only, - * not the final scan elements output. - */ - { - .type = IIO_TEMP, - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) - | BIT(IIO_CHAN_INFO_OFFSET) - | BIT(IIO_CHAN_INFO_SCALE), - .scan_index = -1, - }, + + INV_MPU6050_TEMP_CHAN(INV_MPU6050_SCAN_TEMP), + INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_X, INV_MPU6050_SCAN_GYRO_X), INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_Y, INV_MPU6050_SCAN_GYRO_Y), INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_Z, INV_MPU6050_SCAN_GYRO_Z), @@ -942,98 +969,50 @@ static const struct iio_chan_spec inv_mpu9250_channels[] = { INV_MPU9X50_MAGN_CHAN(IIO_MOD_Z, 16, INV_MPU9X50_SCAN_MAGN_Z), }; +#define INV_MPU9X50_SCAN_MASK_3AXIS_MAGN \ + (BIT(INV_MPU9X50_SCAN_MAGN_X) \ + | BIT(INV_MPU9X50_SCAN_MAGN_Y) \ + | BIT(INV_MPU9X50_SCAN_MAGN_Z)) + static const unsigned long inv_mpu9x50_scan_masks[] = { /* 3-axis accel */ - BIT(INV_MPU6050_SCAN_ACCL_X) - | BIT(INV_MPU6050_SCAN_ACCL_Y) - | BIT(INV_MPU6050_SCAN_ACCL_Z), + INV_MPU6050_SCAN_MASK_3AXIS_ACCEL, + INV_MPU6050_SCAN_MASK_3AXIS_ACCEL | INV_MPU6050_SCAN_MASK_TEMP, /* 3-axis gyro */ - BIT(INV_MPU6050_SCAN_GYRO_X) - | BIT(INV_MPU6050_SCAN_GYRO_Y) - | BIT(INV_MPU6050_SCAN_GYRO_Z), + INV_MPU6050_SCAN_MASK_3AXIS_GYRO, + INV_MPU6050_SCAN_MASK_3AXIS_GYRO | INV_MPU6050_SCAN_MASK_TEMP, /* 3-axis magn */ - BIT(INV_MPU9X50_SCAN_MAGN_X) - | BIT(INV_MPU9X50_SCAN_MAGN_Y) - | BIT(INV_MPU9X50_SCAN_MAGN_Z), + INV_MPU9X50_SCAN_MASK_3AXIS_MAGN, + INV_MPU9X50_SCAN_MASK_3AXIS_MAGN | INV_MPU6050_SCAN_MASK_TEMP, /* 6-axis accel + gyro */ - BIT(INV_MPU6050_SCAN_ACCL_X) - | BIT(INV_MPU6050_SCAN_ACCL_Y) - | BIT(INV_MPU6050_SCAN_ACCL_Z) - | BIT(INV_MPU6050_SCAN_GYRO_X) - | BIT(INV_MPU6050_SCAN_GYRO_Y) - | BIT(INV_MPU6050_SCAN_GYRO_Z), + INV_MPU6050_SCAN_MASK_3AXIS_ACCEL | INV_MPU6050_SCAN_MASK_3AXIS_GYRO, + INV_MPU6050_SCAN_MASK_3AXIS_ACCEL | INV_MPU6050_SCAN_MASK_3AXIS_GYRO + | INV_MPU6050_SCAN_MASK_TEMP, /* 6-axis accel + magn */ - BIT(INV_MPU6050_SCAN_ACCL_X) - | BIT(INV_MPU6050_SCAN_ACCL_Y) - | BIT(INV_MPU6050_SCAN_ACCL_Z) - | BIT(INV_MPU9X50_SCAN_MAGN_X) - | BIT(INV_MPU9X50_SCAN_MAGN_Y) - | BIT(INV_MPU9X50_SCAN_MAGN_Z), + INV_MPU6050_SCAN_MASK_3AXIS_ACCEL | INV_MPU9X50_SCAN_MASK_3AXIS_MAGN, + INV_MPU6050_SCAN_MASK_3AXIS_ACCEL | INV_MPU9X50_SCAN_MASK_3AXIS_MAGN + | INV_MPU6050_SCAN_MASK_TEMP, /* 6-axis gyro + magn */ - BIT(INV_MPU6050_SCAN_GYRO_X) - | BIT(INV_MPU6050_SCAN_GYRO_Y) - | BIT(INV_MPU6050_SCAN_GYRO_Z) - | BIT(INV_MPU9X50_SCAN_MAGN_X) - | BIT(INV_MPU9X50_SCAN_MAGN_Y) - | BIT(INV_MPU9X50_SCAN_MAGN_Z), + INV_MPU6050_SCAN_MASK_3AXIS_GYRO | INV_MPU9X50_SCAN_MASK_3AXIS_MAGN, + INV_MPU6050_SCAN_MASK_3AXIS_GYRO | INV_MPU9X50_SCAN_MASK_3AXIS_MAGN + | INV_MPU6050_SCAN_MASK_TEMP, /* 9-axis accel + gyro + magn */ - BIT(INV_MPU6050_SCAN_ACCL_X) - | BIT(INV_MPU6050_SCAN_ACCL_Y) - | BIT(INV_MPU6050_SCAN_ACCL_Z) - | BIT(INV_MPU6050_SCAN_GYRO_X) - | BIT(INV_MPU6050_SCAN_GYRO_Y) - | BIT(INV_MPU6050_SCAN_GYRO_Z) - | BIT(INV_MPU9X50_SCAN_MAGN_X) - | BIT(INV_MPU9X50_SCAN_MAGN_Y) - | BIT(INV_MPU9X50_SCAN_MAGN_Z), + INV_MPU6050_SCAN_MASK_3AXIS_ACCEL | INV_MPU6050_SCAN_MASK_3AXIS_GYRO + | INV_MPU9X50_SCAN_MASK_3AXIS_MAGN, + INV_MPU6050_SCAN_MASK_3AXIS_ACCEL | INV_MPU6050_SCAN_MASK_3AXIS_GYRO + | INV_MPU9X50_SCAN_MASK_3AXIS_MAGN + | INV_MPU6050_SCAN_MASK_TEMP, 0, }; -static const struct iio_chan_spec inv_icm20602_channels[] = { - IIO_CHAN_SOFT_TIMESTAMP(INV_ICM20602_SCAN_TIMESTAMP), - { - .type = IIO_TEMP, - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) - | BIT(IIO_CHAN_INFO_OFFSET) - | BIT(IIO_CHAN_INFO_SCALE), - .scan_index = INV_ICM20602_SCAN_TEMP, - .scan_type = { - .sign = 's', - .realbits = 16, - .storagebits = 16, - .shift = 0, - .endianness = IIO_BE, - }, - }, - - INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_X, INV_ICM20602_SCAN_GYRO_X), - INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_Y, INV_ICM20602_SCAN_GYRO_Y), - INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_Z, INV_ICM20602_SCAN_GYRO_Z), - - INV_MPU6050_CHAN(IIO_ACCEL, IIO_MOD_Y, INV_ICM20602_SCAN_ACCL_Y), - INV_MPU6050_CHAN(IIO_ACCEL, IIO_MOD_X, INV_ICM20602_SCAN_ACCL_X), - INV_MPU6050_CHAN(IIO_ACCEL, IIO_MOD_Z, INV_ICM20602_SCAN_ACCL_Z), -}; - static const unsigned long inv_icm20602_scan_masks[] = { /* 3-axis accel + temp (mandatory) */ - BIT(INV_ICM20602_SCAN_ACCL_X) - | BIT(INV_ICM20602_SCAN_ACCL_Y) - | BIT(INV_ICM20602_SCAN_ACCL_Z) - | BIT(INV_ICM20602_SCAN_TEMP), + INV_MPU6050_SCAN_MASK_3AXIS_ACCEL | INV_MPU6050_SCAN_MASK_TEMP, /* 3-axis gyro + temp (mandatory) */ - BIT(INV_ICM20602_SCAN_GYRO_X) - | BIT(INV_ICM20602_SCAN_GYRO_Y) - | BIT(INV_ICM20602_SCAN_GYRO_Z) - | BIT(INV_ICM20602_SCAN_TEMP), + INV_MPU6050_SCAN_MASK_3AXIS_GYRO | INV_MPU6050_SCAN_MASK_TEMP, /* 6-axis accel + gyro + temp (mandatory) */ - BIT(INV_ICM20602_SCAN_ACCL_X) - | BIT(INV_ICM20602_SCAN_ACCL_Y) - | BIT(INV_ICM20602_SCAN_ACCL_Z) - | BIT(INV_ICM20602_SCAN_GYRO_X) - | BIT(INV_ICM20602_SCAN_GYRO_Y) - | BIT(INV_ICM20602_SCAN_GYRO_Z) - | BIT(INV_ICM20602_SCAN_TEMP), + INV_MPU6050_SCAN_MASK_3AXIS_ACCEL | INV_MPU6050_SCAN_MASK_3AXIS_GYRO + | INV_MPU6050_SCAN_MASK_TEMP, 0, }; @@ -1241,7 +1220,7 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name, irq_type = irqd_get_trigger_type(desc); if (!irq_type) irq_type = IRQF_TRIGGER_RISING; - if (irq_type == IRQF_TRIGGER_RISING) + if (irq_type & IRQF_TRIGGER_RISING) // rising or both-edge st->irq_mask = INV_MPU6050_ACTIVE_HIGH; else if (irq_type == IRQF_TRIGGER_FALLING) st->irq_mask = INV_MPU6050_ACTIVE_LOW; @@ -1324,25 +1303,20 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name, inv_mpu_bus_setup(indio_dev); switch (chip_type) { + case INV_MPU9150: + indio_dev->channels = inv_mpu9150_channels; + indio_dev->num_channels = ARRAY_SIZE(inv_mpu9150_channels); + indio_dev->available_scan_masks = inv_mpu9x50_scan_masks; + break; case INV_MPU9250: case INV_MPU9255: - /* - * Use magnetometer inside the chip only if there is no i2c - * auxiliary device in use. - */ - if (!st->magn_disabled) { - indio_dev->channels = inv_mpu9250_channels; - indio_dev->num_channels = ARRAY_SIZE(inv_mpu9250_channels); - indio_dev->available_scan_masks = inv_mpu9x50_scan_masks; - } else { - indio_dev->channels = inv_mpu_channels; - indio_dev->num_channels = ARRAY_SIZE(inv_mpu_channels); - indio_dev->available_scan_masks = inv_mpu_scan_masks; - } + indio_dev->channels = inv_mpu9250_channels; + indio_dev->num_channels = ARRAY_SIZE(inv_mpu9250_channels); + indio_dev->available_scan_masks = inv_mpu9x50_scan_masks; break; case INV_ICM20602: - indio_dev->channels = inv_icm20602_channels; - indio_dev->num_channels = ARRAY_SIZE(inv_icm20602_channels); + indio_dev->channels = inv_mpu_channels; + indio_dev->num_channels = ARRAY_SIZE(inv_mpu_channels); indio_dev->available_scan_masks = inv_icm20602_scan_masks; break; default: @@ -1351,6 +1325,15 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name, indio_dev->available_scan_masks = inv_mpu_scan_masks; break; } + /* + * Use magnetometer inside the chip only if there is no i2c + * auxiliary device in use. Otherwise Going back to 6-axis only. + */ + if (st->magn_disabled) { + indio_dev->channels = inv_mpu_channels; + indio_dev->num_channels = ARRAY_SIZE(inv_mpu_channels); + indio_dev->available_scan_masks = inv_mpu_scan_masks; + } indio_dev->info = &mpu_info; indio_dev->modes = INDIO_BUFFER_TRIGGERED; diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c index 389cc8505e0e..f47a28b4be23 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c @@ -77,6 +77,7 @@ static bool inv_mpu_i2c_aux_bus(struct device *dev) case INV_ICM20602: /* no i2c auxiliary bus on the chip */ return false; + case INV_MPU9150: case INV_MPU9250: case INV_MPU9255: if (st->magn_disabled) @@ -102,6 +103,7 @@ static int inv_mpu_magn_disable(struct iio_dev *indio_dev) struct device_node *mux_node; switch (st->chip_type) { + case INV_MPU9150: case INV_MPU9250: case INV_MPU9255: mux_node = of_get_child_by_name(dev->of_node, "i2c-gate"); diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h index b096e010d4ee..6158fca7f70e 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h @@ -86,6 +86,7 @@ enum inv_devices { * @accl_fs: accel full scale range. * @accl_fifo_enable: enable accel data output * @gyro_fifo_enable: enable gyro data output + * @temp_fifo_enable: enable temp data output * @magn_fifo_enable: enable magn data output * @divider: chip sample rate divider (sample rate divider - 1) */ @@ -95,6 +96,7 @@ struct inv_mpu6050_chip_config { unsigned int accl_fs:2; unsigned int accl_fifo_enable:1; unsigned int gyro_fifo_enable:1; + unsigned int temp_fifo_enable:1; unsigned int magn_fifo_enable:1; u8 divider; u8 user_ctrl; @@ -184,6 +186,7 @@ struct inv_mpu6050_state { #define INV_MPU6050_BIT_SLAVE_2 0x04 #define INV_MPU6050_BIT_ACCEL_OUT 0x08 #define INV_MPU6050_BITS_GYRO_OUT 0x70 +#define INV_MPU6050_BIT_TEMP_OUT 0x80 #define INV_MPU6050_REG_I2C_MST_CTRL 0x24 #define INV_MPU6050_BITS_I2C_MST_CLK_400KHZ 0x0D @@ -268,8 +271,8 @@ struct inv_mpu6050_state { /* MPU9X50 9-axis magnetometer */ #define INV_MPU9X50_BYTES_MAGN 7 -/* ICM20602 FIFO samples include temperature readings */ -#define INV_ICM20602_BYTES_PER_TEMP_SENSOR 2 +/* FIFO temperature sample size */ +#define INV_MPU6050_BYTES_PER_TEMP_SENSOR 2 /* mpu6500 registers */ #define INV_MPU6500_REG_ACCEL_CONFIG_2 0x1D @@ -298,7 +301,7 @@ struct inv_mpu6050_state { #define INV_ICM20608_TEMP_OFFSET 8170 #define INV_ICM20608_TEMP_SCALE 3059976 -/* 6 + 6 + 7 (for MPU9x50) = 19 round up to 24 and plus 8 */ +/* 6 + 6 + 2 + 7 (for MPU9x50) = 21 round up to 24 and plus 8 */ #define INV_MPU6050_OUTPUT_DATA_SIZE 32 #define INV_MPU6050_REG_INT_PIN_CFG 0x37 @@ -344,6 +347,7 @@ enum inv_mpu6050_scan { INV_MPU6050_SCAN_ACCL_X, INV_MPU6050_SCAN_ACCL_Y, INV_MPU6050_SCAN_ACCL_Z, + INV_MPU6050_SCAN_TEMP, INV_MPU6050_SCAN_GYRO_X, INV_MPU6050_SCAN_GYRO_Y, INV_MPU6050_SCAN_GYRO_Z, @@ -355,18 +359,6 @@ enum inv_mpu6050_scan { INV_MPU9X50_SCAN_TIMESTAMP, }; -/* scan element definition for ICM20602, which includes temperature */ -enum inv_icm20602_scan { - INV_ICM20602_SCAN_ACCL_X, - INV_ICM20602_SCAN_ACCL_Y, - INV_ICM20602_SCAN_ACCL_Z, - INV_ICM20602_SCAN_TEMP, - INV_ICM20602_SCAN_GYRO_X, - INV_ICM20602_SCAN_GYRO_Y, - INV_ICM20602_SCAN_GYRO_Z, - INV_ICM20602_SCAN_TIMESTAMP, -}; - enum inv_mpu6050_filter_e { INV_MPU6050_FILTER_256HZ_NOLPF2 = 0, INV_MPU6050_FILTER_188HZ, diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.c index 02735af152c8..4f192352521e 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.c @@ -12,7 +12,9 @@ #include "inv_mpu_magn.h" /* - * MPU9250 magnetometer is an AKM AK8963 chip on I2C aux bus + * MPU9xxx magnetometer are AKM chips on I2C aux bus + * MPU9150 is AK8975 + * MPU9250 is AK8963 */ #define INV_MPU_MAGN_I2C_ADDR 0x0C @@ -33,10 +35,10 @@ #define INV_MPU_MAGN_BITS_MODE_PWDN 0x00 #define INV_MPU_MAGN_BITS_MODE_SINGLE 0x01 #define INV_MPU_MAGN_BITS_MODE_FUSE 0x0F -#define INV_MPU_MAGN_BIT_OUTPUT_BIT 0x10 +#define INV_MPU9250_MAGN_BIT_OUTPUT_BIT 0x10 -#define INV_MPU_MAGN_REG_CNTL2 0x0B -#define INV_MPU_MAGN_BIT_SRST 0x01 +#define INV_MPU9250_MAGN_REG_CNTL2 0x0B +#define INV_MPU9250_MAGN_BIT_SRST 0x01 #define INV_MPU_MAGN_REG_ASAX 0x10 #define INV_MPU_MAGN_REG_ASAY 0x11 @@ -48,6 +50,7 @@ static bool inv_magn_supported(const struct inv_mpu6050_state *st) { switch (st->chip_type) { + case INV_MPU9150: case INV_MPU9250: case INV_MPU9255: return true; @@ -61,6 +64,7 @@ static int inv_magn_init(struct inv_mpu6050_state *st) { uint8_t val; uint8_t asa[3]; + int32_t sensitivity; int ret; /* check whoami */ @@ -71,12 +75,19 @@ static int inv_magn_init(struct inv_mpu6050_state *st) if (val != INV_MPU_MAGN_BITS_WIA) return -ENODEV; - /* reset chip */ - ret = inv_mpu_aux_write(st, INV_MPU_MAGN_I2C_ADDR, - INV_MPU_MAGN_REG_CNTL2, - INV_MPU_MAGN_BIT_SRST); - if (ret) - return ret; + /* software reset for MPU925x only */ + switch (st->chip_type) { + case INV_MPU9250: + case INV_MPU9255: + ret = inv_mpu_aux_write(st, INV_MPU_MAGN_I2C_ADDR, + INV_MPU9250_MAGN_REG_CNTL2, + INV_MPU9250_MAGN_BIT_SRST); + if (ret) + return ret; + break; + default: + break; + } /* read fuse ROM data */ ret = inv_mpu_aux_write(st, INV_MPU_MAGN_I2C_ADDR, @@ -98,22 +109,36 @@ static int inv_magn_init(struct inv_mpu6050_state *st) return ret; /* + * Sensor sentivity + * 1 uT = 0.01 G and value is in micron (1e6) + * sensitvity = x uT * 0.01 * 1e6 + */ + switch (st->chip_type) { + case INV_MPU9150: + /* sensor sensitivity is 0.3 uT */ + sensitivity = 3000; + break; + case INV_MPU9250: + case INV_MPU9255: + /* sensor sensitivity in 16 bits mode: 0.15 uT */ + sensitivity = 1500; + break; + default: + return -EINVAL; + } + + /* * Sensitivity adjustement and scale to Gauss * * Hadj = H * (((ASA - 128) * 0.5 / 128) + 1) * Factor simplification: * Hadj = H * ((ASA + 128) / 256) * - * Sensor sentivity - * 0.15 uT in 16 bits mode - * 1 uT = 0.01 G and value is in micron (1e6) - * sensitvity = 0.15 uT * 0.01 * 1e6 - * - * raw_to_gauss = Hadj * 1500 + * raw_to_gauss = Hadj * sensitivity */ - st->magn_raw_to_gauss[0] = (((int32_t)asa[0] + 128) * 1500) / 256; - st->magn_raw_to_gauss[1] = (((int32_t)asa[1] + 128) * 1500) / 256; - st->magn_raw_to_gauss[2] = (((int32_t)asa[2] + 128) * 1500) / 256; + st->magn_raw_to_gauss[0] = (((int32_t)asa[0] + 128) * sensitivity) / 256; + st->magn_raw_to_gauss[1] = (((int32_t)asa[1] + 128) * sensitivity) / 256; + st->magn_raw_to_gauss[2] = (((int32_t)asa[2] + 128) * sensitivity) / 256; return 0; } @@ -129,6 +154,7 @@ static int inv_magn_init(struct inv_mpu6050_state *st) */ int inv_mpu_magn_probe(struct inv_mpu6050_state *st) { + uint8_t val; int ret; /* quit if chip is not supported */ @@ -179,10 +205,17 @@ int inv_mpu_magn_probe(struct inv_mpu6050_state *st) if (ret) return ret; - /* add 16 bits mode */ - ret = regmap_write(st->map, INV_MPU6050_REG_I2C_SLV_DO(1), - INV_MPU_MAGN_BITS_MODE_SINGLE | - INV_MPU_MAGN_BIT_OUTPUT_BIT); + /* add 16 bits mode for MPU925x */ + val = INV_MPU_MAGN_BITS_MODE_SINGLE; + switch (st->chip_type) { + case INV_MPU9250: + case INV_MPU9255: + val |= INV_MPU9250_MAGN_BIT_OUTPUT_BIT; + break; + default: + break; + } + ret = regmap_write(st->map, INV_MPU6050_REG_I2C_SLV_DO(1), val); if (ret) return ret; @@ -237,6 +270,7 @@ int inv_mpu_magn_set_orient(struct inv_mpu6050_state *st) /* fill magnetometer orientation */ switch (st->chip_type) { + case INV_MPU9150: case INV_MPU9250: case INV_MPU9255: /* x <- y */ diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c index 10d16ec5104b..f9fdf4302a91 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c @@ -142,6 +142,8 @@ int inv_reset_fifo(struct iio_dev *indio_dev) d |= INV_MPU6050_BITS_GYRO_OUT; if (st->chip_config.accl_fifo_enable) d |= INV_MPU6050_BIT_ACCEL_OUT; + if (st->chip_config.temp_fifo_enable) + d |= INV_MPU6050_BIT_TEMP_OUT; if (st->chip_config.magn_fifo_enable) d |= INV_MPU6050_BIT_SLAVE_0; result = regmap_write(st->map, st->reg->fifo_en, d); @@ -183,11 +185,8 @@ irqreturn_t inv_mpu6050_read_fifo(int irq, void *p) "failed to ack interrupt\n"); goto flush_fifo; } - if (!(int_status & INV_MPU6050_BIT_RAW_DATA_RDY_INT)) { - dev_warn(regmap_get_device(st->map), - "spurious interrupt with status 0x%x\n", int_status); + if (!(int_status & INV_MPU6050_BIT_RAW_DATA_RDY_INT)) goto end_session; - } if (!(st->chip_config.accl_fifo_enable | st->chip_config.gyro_fifo_enable | @@ -200,8 +199,8 @@ irqreturn_t inv_mpu6050_read_fifo(int irq, void *p) if (st->chip_config.gyro_fifo_enable) bytes_per_datum += INV_MPU6050_BYTES_PER_3AXIS_SENSOR; - if (st->chip_type == INV_ICM20602) - bytes_per_datum += INV_ICM20602_BYTES_PER_TEMP_SENSOR; + if (st->chip_config.temp_fifo_enable) + bytes_per_datum += INV_MPU6050_BYTES_PER_TEMP_SENSOR; if (st->chip_config.magn_fifo_enable) bytes_per_datum += INV_MPU9X50_BYTES_MAGN; diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c index 142692fc0758..ec102d5a5c77 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c @@ -74,7 +74,6 @@ static int inv_mpu_probe(struct spi_device *spi) static const struct spi_device_id inv_mpu_id[] = { {"mpu6000", INV_MPU6000}, {"mpu6500", INV_MPU6500}, - {"mpu9150", INV_MPU9150}, {"mpu9250", INV_MPU9250}, {"mpu9255", INV_MPU9255}, {"icm20608", INV_ICM20608}, diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c index d7d951927a44..5199fe790c30 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c @@ -24,6 +24,9 @@ static void inv_scan_query_mpu6050(struct iio_dev *indio_dev) indio_dev->active_scan_mask) || test_bit(INV_MPU6050_SCAN_ACCL_Z, indio_dev->active_scan_mask); + + st->chip_config.temp_fifo_enable = + test_bit(INV_MPU6050_SCAN_TEMP, indio_dev->active_scan_mask); } static void inv_scan_query_mpu9x50(struct iio_dev *indio_dev) @@ -50,6 +53,7 @@ static void inv_scan_query(struct iio_dev *indio_dev) struct inv_mpu6050_state *st = iio_priv(indio_dev); switch (st->chip_type) { + case INV_MPU9150: case INV_MPU9250: case INV_MPU9255: return inv_scan_query_mpu9x50(indio_dev); diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h index dc55d7dff3eb..9c3486a8134f 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h @@ -76,6 +76,7 @@ enum st_lsm6dsx_hw_id { .endianness = IIO_LE, \ }, \ .event_spec = &st_lsm6dsx_event, \ + .ext_info = st_lsm6dsx_accel_ext_info, \ .num_event_specs = 1, \ } @@ -176,21 +177,38 @@ struct st_lsm6dsx_hw_ts_settings { * @pullup_en: i2c controller pull-up register info (addr + mask). * @aux_sens: aux sensor register info (addr + mask). * @wr_once: write_once register info (addr + mask). + * @emb_func: embedded function register info (addr + mask). + * @num_ext_dev: max number of slave devices. * @shub_out: sensor hub first output register info. * @slv0_addr: slave0 address in secondary page. * @dw_slv0_addr: slave0 write register address in secondary page. * @batch_en: Enable/disable FIFO batching. + * @pause: controller pause value. */ struct st_lsm6dsx_shub_settings { struct st_lsm6dsx_reg page_mux; - struct st_lsm6dsx_reg master_en; - struct st_lsm6dsx_reg pullup_en; + struct { + bool sec_page; + u8 addr; + u8 mask; + } master_en; + struct { + bool sec_page; + u8 addr; + u8 mask; + } pullup_en; struct st_lsm6dsx_reg aux_sens; struct st_lsm6dsx_reg wr_once; - u8 shub_out; + struct st_lsm6dsx_reg emb_func; + u8 num_ext_dev; + struct { + bool sec_page; + u8 addr; + } shub_out; u8 slv0_addr; u8 dw_slv0_addr; u8 batch_en; + u8 pause; }; struct st_lsm6dsx_event_settings { @@ -361,6 +379,7 @@ struct st_lsm6dsx_sensor { * @enable_event: enabled event bitmask. * @iio_devs: Pointers to acc/gyro iio_dev instances. * @settings: Pointer to the specific sensor settings in use. + * @orientation: sensor chip orientation relative to main hardware. */ struct st_lsm6dsx_hw { struct device *dev; @@ -387,16 +406,21 @@ struct st_lsm6dsx_hw { struct iio_dev *iio_devs[ST_LSM6DSX_ID_MAX]; const struct st_lsm6dsx_settings *settings; + + struct iio_mount_matrix orientation; }; -static const struct iio_event_spec st_lsm6dsx_event = { +static __maybe_unused const struct iio_event_spec st_lsm6dsx_event = { .type = IIO_EV_TYPE_THRESH, .dir = IIO_EV_DIR_EITHER, .mask_separate = BIT(IIO_EV_INFO_VALUE) | BIT(IIO_EV_INFO_ENABLE) }; -static const unsigned long st_lsm6dsx_available_scan_masks[] = {0x7, 0x0}; +static __maybe_unused const unsigned long st_lsm6dsx_available_scan_masks[] = { + 0x7, 0x0, +}; + extern const struct dev_pm_ops st_lsm6dsx_pm_ops; int st_lsm6dsx_probe(struct device *dev, int irq, int hw_id, @@ -457,4 +481,19 @@ st_lsm6dsx_write_locked(struct st_lsm6dsx_hw *hw, unsigned int addr, return err; } +static const inline struct iio_mount_matrix * +st_lsm6dsx_get_mount_matrix(const struct iio_dev *iio_dev, + const struct iio_chan_spec *chan) +{ + struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev); + struct st_lsm6dsx_hw *hw = sensor->hw; + + return &hw->orientation; +} + +static const struct iio_chan_spec_ext_info st_lsm6dsx_accel_ext_info[] = { + IIO_MOUNT_MATRIX(IIO_SHARED_BY_ALL, st_lsm6dsx_get_mount_matrix), + { } +}; + #endif /* ST_LSM6DSX_H */ diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c index cb536b81a1c2..bb899345f2bb 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c @@ -336,12 +336,13 @@ static inline int st_lsm6dsx_read_block(struct st_lsm6dsx_hw *hw, u8 addr, */ int st_lsm6dsx_read_fifo(struct st_lsm6dsx_hw *hw) { + struct st_lsm6dsx_sensor *acc_sensor, *gyro_sensor, *ext_sensor = NULL; + int err, acc_sip, gyro_sip, ts_sip, ext_sip, read_len, offset; u16 fifo_len, pattern_len = hw->sip * ST_LSM6DSX_SAMPLE_SIZE; u16 fifo_diff_mask = hw->settings->fifo_ops.fifo_diff.mask; - int err, acc_sip, gyro_sip, ts_sip, read_len, offset; - struct st_lsm6dsx_sensor *acc_sensor, *gyro_sensor; u8 gyro_buff[ST_LSM6DSX_IIO_BUFF_SIZE]; u8 acc_buff[ST_LSM6DSX_IIO_BUFF_SIZE]; + u8 ext_buff[ST_LSM6DSX_IIO_BUFF_SIZE]; bool reset_ts = false; __le16 fifo_status; s64 ts = 0; @@ -364,6 +365,8 @@ int st_lsm6dsx_read_fifo(struct st_lsm6dsx_hw *hw) acc_sensor = iio_priv(hw->iio_devs[ST_LSM6DSX_ID_ACC]); gyro_sensor = iio_priv(hw->iio_devs[ST_LSM6DSX_ID_GYRO]); + if (hw->iio_devs[ST_LSM6DSX_ID_EXT0]) + ext_sensor = iio_priv(hw->iio_devs[ST_LSM6DSX_ID_EXT0]); for (read_len = 0; read_len < fifo_len; read_len += pattern_len) { err = st_lsm6dsx_read_block(hw, ST_LSM6DSX_REG_FIFO_OUTL_ADDR, @@ -391,12 +394,13 @@ int st_lsm6dsx_read_fifo(struct st_lsm6dsx_hw *hw) * following pattern is repeated every 9 samples: * - Gx, Gy, Gz, Ax, Ay, Az, Ts, Gx, Gy, Gz, Ts, Gx, .. */ + ext_sip = ext_sensor ? ext_sensor->sip : 0; gyro_sip = gyro_sensor->sip; acc_sip = acc_sensor->sip; ts_sip = hw->ts_sip; offset = 0; - while (acc_sip > 0 || gyro_sip > 0) { + while (acc_sip > 0 || gyro_sip > 0 || ext_sip > 0) { if (gyro_sip > 0) { memcpy(gyro_buff, &hw->buff[offset], ST_LSM6DSX_SAMPLE_SIZE); @@ -407,6 +411,11 @@ int st_lsm6dsx_read_fifo(struct st_lsm6dsx_hw *hw) ST_LSM6DSX_SAMPLE_SIZE); offset += ST_LSM6DSX_SAMPLE_SIZE; } + if (ext_sip > 0) { + memcpy(ext_buff, &hw->buff[offset], + ST_LSM6DSX_SAMPLE_SIZE); + offset += ST_LSM6DSX_SAMPLE_SIZE; + } if (ts_sip-- > 0) { u8 data[ST_LSM6DSX_SAMPLE_SIZE]; @@ -440,6 +449,10 @@ int st_lsm6dsx_read_fifo(struct st_lsm6dsx_hw *hw) iio_push_to_buffers_with_timestamp( hw->iio_devs[ST_LSM6DSX_ID_ACC], acc_buff, acc_sensor->ts_ref + ts); + if (ext_sip-- > 0) + iio_push_to_buffers_with_timestamp( + hw->iio_devs[ST_LSM6DSX_ID_EXT0], + ext_buff, ext_sensor->ts_ref + ts); } } @@ -638,12 +651,12 @@ int st_lsm6dsx_update_fifo(struct st_lsm6dsx_sensor *sensor, bool enable) err = st_lsm6dsx_sensor_set_enable(sensor, enable); if (err < 0) goto out; - - err = st_lsm6dsx_set_fifo_odr(sensor, enable); - if (err < 0) - goto out; } + err = st_lsm6dsx_set_fifo_odr(sensor, enable); + if (err < 0) + goto out; + err = st_lsm6dsx_update_decimators(hw); if (err < 0) goto out; diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c index b921dd9e108f..84d219ae6aee 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c @@ -54,6 +54,7 @@ #include <linux/interrupt.h> #include <linux/irq.h> #include <linux/pm.h> +#include <linux/property.h> #include <linux/regmap.h> #include <linux/bitfield.h> @@ -655,6 +656,10 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { .addr = 0x08, .mask = GENMASK(5, 3), }, + [ST_LSM6DSX_ID_EXT0] = { + .addr = 0x09, + .mask = GENMASK(2, 0), + }, }, .fifo_ops = { .update_fifo = st_lsm6dsx_update_fifo, @@ -687,6 +692,39 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { .mask = GENMASK(5, 3), }, }, + .shub_settings = { + .page_mux = { + .addr = 0x01, + .mask = BIT(7), + }, + .master_en = { + .addr = 0x1a, + .mask = BIT(0), + }, + .pullup_en = { + .addr = 0x1a, + .mask = BIT(3), + }, + .aux_sens = { + .addr = 0x04, + .mask = GENMASK(5, 4), + }, + .wr_once = { + .addr = 0x07, + .mask = BIT(5), + }, + .emb_func = { + .addr = 0x19, + .mask = BIT(2), + }, + .num_ext_dev = 1, + .shub_out = { + .addr = 0x2e, + }, + .slv0_addr = 0x02, + .dw_slv0_addr = 0x0e, + .pause = 0x7, + }, .event_settings = { .enable_reg = { .addr = 0x58, @@ -867,10 +905,12 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { .mask = BIT(6), }, .master_en = { + .sec_page = true, .addr = 0x14, .mask = BIT(2), }, .pullup_en = { + .sec_page = true, .addr = 0x14, .mask = BIT(3), }, @@ -882,7 +922,11 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { .addr = 0x14, .mask = BIT(6), }, - .shub_out = 0x02, + .num_ext_dev = 3, + .shub_out = { + .sec_page = true, + .addr = 0x02, + }, .slv0_addr = 0x15, .dw_slv0_addr = 0x21, .batch_en = BIT(3), @@ -1241,10 +1285,12 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { .mask = BIT(6), }, .master_en = { + .sec_page = true, .addr = 0x14, .mask = BIT(2), }, .pullup_en = { + .sec_page = true, .addr = 0x14, .mask = BIT(3), }, @@ -1256,7 +1302,11 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { .addr = 0x14, .mask = BIT(6), }, - .shub_out = 0x02, + .num_ext_dev = 3, + .shub_out = { + .sec_page = true, + .addr = 0x02, + }, .slv0_addr = 0x15, .dw_slv0_addr = 0x21, .batch_en = BIT(3), @@ -1506,8 +1556,11 @@ static int st_lsm6dsx_read_oneshot(struct st_lsm6dsx_sensor *sensor, if (err < 0) return err; - if (!hw->enable_event) - st_lsm6dsx_sensor_set_enable(sensor, false); + if (!hw->enable_event) { + err = st_lsm6dsx_sensor_set_enable(sensor, false); + if (err < 0) + return err; + } *val = (s16)le16_to_cpu(data); @@ -1609,11 +1662,11 @@ static int st_lsm6dsx_event_setup(struct st_lsm6dsx_hw *hw, int state) } static int st_lsm6dsx_read_event(struct iio_dev *iio_dev, - const struct iio_chan_spec *chan, - enum iio_event_type type, - enum iio_event_direction dir, - enum iio_event_info info, - int *val, int *val2) + const struct iio_chan_spec *chan, + enum iio_event_type type, + enum iio_event_direction dir, + enum iio_event_info info, + int *val, int *val2) { struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev); struct st_lsm6dsx_hw *hw = sensor->hw; @@ -1827,14 +1880,14 @@ static const struct iio_info st_lsm6dsx_gyro_info = { .hwfifo_set_watermark = st_lsm6dsx_set_watermark, }; -static int st_lsm6dsx_of_get_drdy_pin(struct st_lsm6dsx_hw *hw, int *drdy_pin) +static int st_lsm6dsx_get_drdy_pin(struct st_lsm6dsx_hw *hw, int *drdy_pin) { - struct device_node *np = hw->dev->of_node; + struct device *dev = hw->dev; - if (!np) + if (!dev_fwnode(dev)) return -EINVAL; - return of_property_read_u32(np, "st,drdy-int-pin", drdy_pin); + return device_property_read_u32(dev, "st,drdy-int-pin", drdy_pin); } static int @@ -1843,7 +1896,7 @@ st_lsm6dsx_get_drdy_reg(struct st_lsm6dsx_hw *hw, { int err = 0, drdy_pin; - if (st_lsm6dsx_of_get_drdy_pin(hw, &drdy_pin) < 0) { + if (st_lsm6dsx_get_drdy_pin(hw, &drdy_pin) < 0) { struct st_sensors_platform_data *pdata; struct device *dev = hw->dev; @@ -1872,26 +1925,29 @@ st_lsm6dsx_get_drdy_reg(struct st_lsm6dsx_hw *hw, static int st_lsm6dsx_init_shub(struct st_lsm6dsx_hw *hw) { const struct st_lsm6dsx_shub_settings *hub_settings; - struct device_node *np = hw->dev->of_node; struct st_sensors_platform_data *pdata; + struct device *dev = hw->dev; unsigned int data; int err = 0; hub_settings = &hw->settings->shub_settings; - pdata = (struct st_sensors_platform_data *)hw->dev->platform_data; - if ((np && of_property_read_bool(np, "st,pullups")) || + pdata = (struct st_sensors_platform_data *)dev->platform_data; + if ((dev_fwnode(dev) && device_property_read_bool(dev, "st,pullups")) || (pdata && pdata->pullups)) { - err = st_lsm6dsx_set_page(hw, true); - if (err < 0) - return err; + if (hub_settings->pullup_en.sec_page) { + err = st_lsm6dsx_set_page(hw, true); + if (err < 0) + return err; + } data = ST_LSM6DSX_SHIFT_VAL(1, hub_settings->pullup_en.mask); err = regmap_update_bits(hw->regmap, hub_settings->pullup_en.addr, hub_settings->pullup_en.mask, data); - st_lsm6dsx_set_page(hw, false); + if (hub_settings->pullup_en.sec_page) + st_lsm6dsx_set_page(hw, false); if (err < 0) return err; @@ -1909,6 +1965,16 @@ static int st_lsm6dsx_init_shub(struct st_lsm6dsx_hw *hw) hub_settings->aux_sens.mask, data); st_lsm6dsx_set_page(hw, false); + + if (err < 0) + return err; + } + + if (hub_settings->emb_func.addr) { + data = ST_LSM6DSX_SHIFT_VAL(1, hub_settings->emb_func.mask); + err = regmap_update_bits(hw->regmap, + hub_settings->emb_func.addr, + hub_settings->emb_func.mask, data); } return err; @@ -2158,9 +2224,9 @@ static irqreturn_t st_lsm6dsx_handler_thread(int irq, void *private) static int st_lsm6dsx_irq_setup(struct st_lsm6dsx_hw *hw) { - struct device_node *np = hw->dev->of_node; struct st_sensors_platform_data *pdata; const struct st_lsm6dsx_reg *reg; + struct device *dev = hw->dev; unsigned long irq_type; bool irq_active_low; int err; @@ -2188,8 +2254,8 @@ static int st_lsm6dsx_irq_setup(struct st_lsm6dsx_hw *hw) if (err < 0) return err; - pdata = (struct st_sensors_platform_data *)hw->dev->platform_data; - if ((np && of_property_read_bool(np, "drive-open-drain")) || + pdata = (struct st_sensors_platform_data *)dev->platform_data; + if ((dev_fwnode(dev) && device_property_read_bool(dev, "drive-open-drain")) || (pdata && pdata->open_drain)) { reg = &hw->settings->irq_config.od; err = regmap_update_bits(hw->regmap, reg->addr, reg->mask, @@ -2219,7 +2285,6 @@ int st_lsm6dsx_probe(struct device *dev, int irq, int hw_id, { struct st_sensors_platform_data *pdata = dev->platform_data; const struct st_lsm6dsx_shub_settings *hub_settings; - struct device_node *np = dev->of_node; struct st_lsm6dsx_hw *hw; const char *name = NULL; int i, err; @@ -2273,6 +2338,10 @@ int st_lsm6dsx_probe(struct device *dev, int irq, int hw_id, return err; } + err = iio_read_mount_matrix(hw->dev, "mount-matrix", &hw->orientation); + if (err) + return err; + for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) { if (!hw->iio_devs[i]) continue; @@ -2282,7 +2351,7 @@ int st_lsm6dsx_probe(struct device *dev, int irq, int hw_id, return err; } - if ((np && of_property_read_bool(np, "wakeup-source")) || + if ((dev_fwnode(dev) && device_property_read_bool(dev, "wakeup-source")) || (pdata && pdata->wakeup_source)) device_init_wakeup(dev, true); diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c index cd47ec1fedcb..0fb32131afce 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c @@ -12,7 +12,6 @@ #include <linux/module.h> #include <linux/i2c.h> #include <linux/slab.h> -#include <linux/of.h> #include <linux/regmap.h> #include "st_lsm6dsx.h" @@ -122,7 +121,7 @@ static struct i2c_driver st_lsm6dsx_driver = { .driver = { .name = "st_lsm6dsx_i2c", .pm = &st_lsm6dsx_pm_ops, - .of_match_table = of_match_ptr(st_lsm6dsx_i2c_of_match), + .of_match_table = st_lsm6dsx_i2c_of_match, }, .probe = st_lsm6dsx_i2c_probe, .id_table = st_lsm6dsx_i2c_id_table, diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c index fa5d1001a46c..eea555617d4a 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c @@ -30,7 +30,6 @@ #include "st_lsm6dsx.h" -#define ST_LSM6DSX_MAX_SLV_NUM 3 #define ST_LSM6DSX_SLV_ADDR(n, base) ((base) + (n) * 3) #define ST_LSM6DSX_SLV_SUB_ADDR(n, base) ((base) + 1 + (n) * 3) #define ST_LSM6DSX_SLV_CONFIG(n, base) ((base) + 2 + (n) * 3) @@ -102,24 +101,31 @@ static void st_lsm6dsx_shub_wait_complete(struct st_lsm6dsx_hw *hw) } /** - * st_lsm6dsx_shub_read_reg - read i2c controller register + * st_lsm6dsx_shub_read_output - read i2c controller register * * Read st_lsm6dsx i2c controller register */ -static int st_lsm6dsx_shub_read_reg(struct st_lsm6dsx_hw *hw, u8 addr, - u8 *data, int len) +static int +st_lsm6dsx_shub_read_output(struct st_lsm6dsx_hw *hw, u8 *data, + int len) { + const struct st_lsm6dsx_shub_settings *hub_settings; int err; mutex_lock(&hw->page_lock); - err = st_lsm6dsx_set_page(hw, true); - if (err < 0) - goto out; + hub_settings = &hw->settings->shub_settings; + if (hub_settings->shub_out.sec_page) { + err = st_lsm6dsx_set_page(hw, true); + if (err < 0) + goto out; + } - err = regmap_bulk_read(hw->regmap, addr, data, len); + err = regmap_bulk_read(hw->regmap, hub_settings->shub_out.addr, + data, len); - st_lsm6dsx_set_page(hw, false); + if (hub_settings->shub_out.sec_page) + st_lsm6dsx_set_page(hw, false); out: mutex_unlock(&hw->page_lock); @@ -186,15 +192,18 @@ static int st_lsm6dsx_shub_master_enable(struct st_lsm6dsx_sensor *sensor, mutex_lock(&hw->page_lock); hub_settings = &hw->settings->shub_settings; - err = st_lsm6dsx_set_page(hw, true); - if (err < 0) - goto out; + if (hub_settings->master_en.sec_page) { + err = st_lsm6dsx_set_page(hw, true); + if (err < 0) + goto out; + } data = ST_LSM6DSX_SHIFT_VAL(enable, hub_settings->master_en.mask); err = regmap_update_bits(hw->regmap, hub_settings->master_en.addr, hub_settings->master_en.mask, data); - st_lsm6dsx_set_page(hw, false); + if (hub_settings->master_en.sec_page) + st_lsm6dsx_set_page(hw, false); out: mutex_unlock(&hw->page_lock); @@ -212,16 +221,21 @@ st_lsm6dsx_shub_read(struct st_lsm6dsx_sensor *sensor, u8 addr, u8 *data, int len) { const struct st_lsm6dsx_shub_settings *hub_settings; + u8 config[3], slv_addr, slv_config = 0; struct st_lsm6dsx_hw *hw = sensor->hw; - u8 config[3], slv_addr; + const struct st_lsm6dsx_reg *aux_sens; int err; hub_settings = &hw->settings->shub_settings; slv_addr = ST_LSM6DSX_SLV_ADDR(0, hub_settings->slv0_addr); + aux_sens = &hw->settings->shub_settings.aux_sens; + /* do not overwrite aux_sens */ + if (slv_addr + 2 == aux_sens->addr) + slv_config = ST_LSM6DSX_SHIFT_VAL(3, aux_sens->mask); config[0] = (sensor->ext_info.addr << 1) | 1; config[1] = addr; - config[2] = len & ST_LS6DSX_READ_OP_MASK; + config[2] = (len & ST_LS6DSX_READ_OP_MASK) | slv_config; err = st_lsm6dsx_shub_write_reg(hw, slv_addr, config, sizeof(config)); @@ -234,12 +248,14 @@ st_lsm6dsx_shub_read(struct st_lsm6dsx_sensor *sensor, u8 addr, st_lsm6dsx_shub_wait_complete(hw); - err = st_lsm6dsx_shub_read_reg(hw, hub_settings->shub_out, data, - len & ST_LS6DSX_READ_OP_MASK); + err = st_lsm6dsx_shub_read_output(hw, data, + len & ST_LS6DSX_READ_OP_MASK); st_lsm6dsx_shub_master_enable(sensor, false); - memset(config, 0, sizeof(config)); + config[0] = hub_settings->pause; + config[1] = 0; + config[2] = slv_config; return st_lsm6dsx_shub_write_reg(hw, slv_addr, config, sizeof(config)); } @@ -296,7 +312,8 @@ st_lsm6dsx_shub_write(struct st_lsm6dsx_sensor *sensor, u8 addr, st_lsm6dsx_shub_master_enable(sensor, false); } - memset(config, 0, sizeof(config)); + config[0] = hub_settings->pause; + config[1] = 0; return st_lsm6dsx_shub_write_reg(hw, slv_addr, config, sizeof(config)); } @@ -688,14 +705,19 @@ st_lsm6dsx_shub_check_wai(struct st_lsm6dsx_hw *hw, u8 *i2c_addr, const struct st_lsm6dsx_ext_dev_settings *settings) { const struct st_lsm6dsx_shub_settings *hub_settings; + u8 config[3], data, slv_addr, slv_config = 0; + const struct st_lsm6dsx_reg *aux_sens; struct st_lsm6dsx_sensor *sensor; - u8 config[3], data, slv_addr; bool found = false; int i, err; + sensor = iio_priv(hw->iio_devs[ST_LSM6DSX_ID_ACC]); hub_settings = &hw->settings->shub_settings; + aux_sens = &hw->settings->shub_settings.aux_sens; slv_addr = ST_LSM6DSX_SLV_ADDR(0, hub_settings->slv0_addr); - sensor = iio_priv(hw->iio_devs[ST_LSM6DSX_ID_ACC]); + /* do not overwrite aux_sens */ + if (slv_addr + 2 == aux_sens->addr) + slv_config = ST_LSM6DSX_SHIFT_VAL(3, aux_sens->mask); for (i = 0; i < ARRAY_SIZE(settings->i2c_addr); i++) { if (!settings->i2c_addr[i]) @@ -704,7 +726,7 @@ st_lsm6dsx_shub_check_wai(struct st_lsm6dsx_hw *hw, u8 *i2c_addr, /* read wai slave register */ config[0] = (settings->i2c_addr[i] << 1) | 0x1; config[1] = settings->wai.addr; - config[2] = 0x1; + config[2] = 0x1 | slv_config; err = st_lsm6dsx_shub_write_reg(hw, slv_addr, config, sizeof(config)); @@ -717,9 +739,7 @@ st_lsm6dsx_shub_check_wai(struct st_lsm6dsx_hw *hw, u8 *i2c_addr, st_lsm6dsx_shub_wait_complete(hw); - err = st_lsm6dsx_shub_read_reg(hw, - hub_settings->shub_out, - &data, sizeof(data)); + err = st_lsm6dsx_shub_read_output(hw, &data, sizeof(data)); st_lsm6dsx_shub_master_enable(sensor, false); @@ -735,7 +755,9 @@ st_lsm6dsx_shub_check_wai(struct st_lsm6dsx_hw *hw, u8 *i2c_addr, } /* reset SLV0 channel */ - memset(config, 0, sizeof(config)); + config[0] = hub_settings->pause; + config[1] = 0; + config[2] = slv_config; err = st_lsm6dsx_shub_write_reg(hw, slv_addr, config, sizeof(config)); if (err < 0) @@ -770,7 +792,7 @@ int st_lsm6dsx_shub_probe(struct st_lsm6dsx_hw *hw, const char *name) if (err < 0) return err; - if (++num_ext_dev >= ST_LSM6DSX_MAX_SLV_NUM) + if (++num_ext_dev >= hw->settings->shub_settings.num_ext_dev) break; id++; } diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c index 67ff36eac247..eb1086e4a951 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c @@ -12,7 +12,6 @@ #include <linux/module.h> #include <linux/spi/spi.h> #include <linux/slab.h> -#include <linux/of.h> #include <linux/regmap.h> #include "st_lsm6dsx.h" @@ -122,7 +121,7 @@ static struct spi_driver st_lsm6dsx_driver = { .driver = { .name = "st_lsm6dsx_spi", .pm = &st_lsm6dsx_pm_ops, - .of_match_table = of_match_ptr(st_lsm6dsx_spi_of_match), + .of_match_table = st_lsm6dsx_spi_of_match, }, .probe = st_lsm6dsx_spi_probe, .id_table = st_lsm6dsx_spi_id_table, |