After some more tests I figured out the original soft reset timeout of 1ms is sufficient. And dropping the switch-to-SPI-mode timeout to 1ms is also sufficient. The sequence which works *for me* is now: 1. Read from 0x7f (-> switch to SPI mode) 2. Wait 1ms 3. Send SOFT_RESET 4. Wait 1ms 5. Read from 0x7f (-> switch to SPI mode required after softreset) 6. Wait 1ms 7. Read chip id The Linux BMI160 IIO driver diff is now: diff --git a/drivers/iio/imu/bmi160/bmi160_core.c b/drivers/iio/imu/bmi160/bmi160_core.c
index a77f1a834..a3ac3bd7d 100644
--- a/drivers/iio/imu/bmi160/bmi160_core.c
+++ b/drivers/iio/imu/bmi160/bmi160_core.c
@@ -94,6 +94,7 @@
#define BMI160_ACCEL_PMU_MIN_USLEEP 3800
#define BMI160_GYRO_PMU_MIN_USLEEP 80000
#define BMI160_SOFTRESET_USLEEP 1000
+#define BMI160_SPI_MODE_CHANGE_USLEEP 1000
#define BMI160_CHANNEL(_type, _axis, _index) { \
.type = _type, \
@@ -716,20 +717,29 @@ static int bmi160_chip_init(struct bmi160_data *data, bool use_spi)
return ret;
}
+ /*
+ * CS rising edge is needed before starting SPI, so do a dummy read
+ * See Section 3.2.1, page 86 of the datasheet
+ */
+ if (use_spi) {
+ ret = regmap_read(data->regmap, BMI160_REG_DUMMY, &val);
+ if (ret)
+ goto disable_regulator;
+ usleep_range(BMI160_SPI_MODE_CHANGE_USLEEP, BMI160_SPI_MODE_CHANGE_USLEEP + 1);
+ }
+
ret = regmap_write(data->regmap, BMI160_REG_CMD, BMI160_CMD_SOFTRESET);
if (ret)
goto disable_regulator;
usleep_range(BMI160_SOFTRESET_USLEEP, BMI160_SOFTRESET_USLEEP + 1);
- /*
- * CS rising edge is needed before starting SPI, so do a dummy read
- * See Section 3.2.1, page 86 of the datasheet
- */
+ /* After soft reset switch to SPI mode is required again */
if (use_spi) {
ret = regmap_read(data->regmap, BMI160_REG_DUMMY, &val);
if (ret)
goto disable_regulator;
+ usleep_range(BMI160_SPI_MODE_CHANGE_USLEEP, BMI160_SPI_MODE_CHANGE_USLEEP + 1);
}
ret = regmap_read(data->regmap, BMI160_REG_CHIP_ID, &val);
... View more