summaryrefslogtreecommitdiff
path: root/driver/accelgyro_lsm6dso.c
diff options
context:
space:
mode:
authorGwendal Grignou <gwendal@chromium.org>2021-09-09 14:42:16 -0700
committerCommit Bot <commit-bot@chromium.org>2021-09-10 22:05:17 +0000
commitb41956ce171f969721974a73d7b80a947610cbb7 (patch)
tree8a34b11a5ff7eb7d5de40ea349af51f14ad5f814 /driver/accelgyro_lsm6dso.c
parent155d8545cab4fad0718485c37fcf8eeb5948f3f2 (diff)
downloadchrome-ec-b41956ce171f969721974a73d7b80a947610cbb7.tar.gz
driver: lsm6dso: Fix FIFO processing
Add a loop in irq_handler to match datasheet documentation: """ 1. Read the FIFO_STATUS1 and FIFO_STATUS2 registers to check how many words are stored in the FIFO. This information is contained in the DIFF_FIFO_[9:0] bits. 2. For each word in FIFO, read the FIFO word (tag and output data) and interpret it on the basis of the FIFO tag. 3. Go to step 1. """ We need to read the FIFO length at the end of the IRQ handler to be sure a new item has not been put while the FIFO was being read. Otherwise, we will not get interrupt and will stop processing FIFO when the FIFO status register still shows the FIFO as not empty. However, using linux kernel st_lsm6dsx_read_tagged_fifo() as model, read only one word at a time: When reading 2 7bytes word at time, the FIFO would still claim one entry remains: The 3rd entry would be a copy of the accelerometer data, but with a corrupted z axis.That why we fail the data test, the gravity vector is not measured at 9.81m/s^2. There was a bug in the interrupt handler that would read the FIFO twice, which was presenting the data: both gyro and accel at the same ODR: [7623.475256 Base Accel FIFO status: 8002] [7623.476548 Base Gyro sending vector num: 2 raw: 0x00000007 - 0xFFFFFFF6 - 0xFFFFFFF9] [7623.477526 Base Accel sending vector num: 1 raw: 0xFFFFFFCC - 0xFFFFE275 - 0xFFFFE818] [7623.479271 Base Accel FIFO status: 8001] [7623.480333 Base Accel sending vector num: 1 raw: 0xFFFFFFCC - 0xFFFFE275 - 0x00000C18] [7623.481699 Base Accel FIFO status: 0000] We must only run the irq_hanlder for the main/accelerometer sensor. Restructure irq_hanlder to match other driver, like accelgyro_bm160.c. BUG=b:195700255,b:192219470 BRANCH=dedede TEST=Running tast run <ip> hardware.SensorIioserviceHard Check we get the right amount of samples. Signed-off-by: Gwendal Grignou <gwendal@chromium.org> Change-Id: I5820dec4c7c5ccb1ebeda854398738d1af60290c Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3150679 Reviewed-by: Keith Short <keithshort@chromium.org>
Diffstat (limited to 'driver/accelgyro_lsm6dso.c')
-rw-r--r--driver/accelgyro_lsm6dso.c55
1 files changed, 27 insertions, 28 deletions
diff --git a/driver/accelgyro_lsm6dso.c b/driver/accelgyro_lsm6dso.c
index ca4d85edb8..fbce687f2c 100644
--- a/driver/accelgyro_lsm6dso.c
+++ b/driver/accelgyro_lsm6dso.c
@@ -159,32 +159,25 @@ static void push_fifo_data(struct motion_sensor_t *main_s, uint8_t *fifo,
motion_sense_fifo_stage_data(&vect, sensor, 3, saved_ts);
}
-static inline int load_fifo(struct motion_sensor_t *s,
- const struct lsm6dso_fstatus *fsts,
+static inline int load_fifo(struct motion_sensor_t *main_s,
+ const uint16_t fifo_len,
uint32_t saved_ts)
{
- uint8_t fifo[FIFO_READ_LEN], *ptr;
- int i, err, read_len = 0, word_len, fifo_len;
- uint16_t fifo_depth;
-
- fifo_depth = fsts->len & LSM6DSO_FIFO_DIFF_MASK;
- fifo_len = fifo_depth * LSM6DSO_FIFO_SAMPLE_SIZE;
- while (read_len < fifo_len) {
- word_len = GENERIC_MIN(fifo_len - read_len, sizeof(fifo));
- err = st_raw_read_n_noinc(s->port, s->i2c_spi_addr_flags,
+ uint8_t fifo[LSM6DSO_FIFO_SAMPLE_SIZE];
+ int i, err;
+
+ for (i = 0; i < fifo_len; i++) {
+ err = st_raw_read_n_noinc(main_s->port,
+ main_s->i2c_spi_addr_flags,
LSM6DSO_FIFO_DATA_ADDR_TAG,
- fifo, word_len);
+ fifo, LSM6DSO_FIFO_SAMPLE_SIZE);
if (err != EC_SUCCESS)
return err;
- for (i = 0; i < word_len; i += LSM6DSO_FIFO_SAMPLE_SIZE) {
- ptr = &fifo[i];
- push_fifo_data(LSM6DSO_MAIN_SENSOR(s), ptr, saved_ts);
- }
- read_len += word_len;
+ push_fifo_data(main_s, fifo, saved_ts);
}
- return read_len;
+ return EC_SUCCESS;
}
/**
@@ -234,31 +227,37 @@ void lsm6dso_interrupt(enum gpio_signal signal)
*/
static int irq_handler(struct motion_sensor_t *s, uint32_t *event)
{
- int ret = EC_SUCCESS;
+ int ret = EC_SUCCESS, fifo_len = 0;
struct lsm6dso_fstatus fsts;
+ bool has_read_fifo = false;
- if (((s->type != MOTIONSENSE_TYPE_ACCEL) &&
- (s->type != MOTIONSENSE_TYPE_GYRO)) ||
+ if ((s->type != MOTIONSENSE_TYPE_ACCEL) ||
(!(*event & CONFIG_ACCEL_LSM6DSO_INT_EVENT)))
return EC_ERROR_NOT_HANDLED;
- if (IS_ENABLED(CONFIG_ACCEL_FIFO)) {
+ if (!IS_ENABLED(CONFIG_ACCEL_FIFO))
+ return EC_SUCCESS;
+
+ do {
/* Read how many data patterns on FIFO to read. */
ret = st_raw_read_n_noinc(s->port, s->i2c_spi_addr_flags,
LSM6DSO_FIFO_STS1_ADDR,
(uint8_t *)&fsts, sizeof(fsts));
if (ret != EC_SUCCESS)
- return ret;
+ break;
if (fsts.len & (LSM6DSO_FIFO_DATA_OVR | LSM6DSO_FIFO_FULL))
CPRINTS("%s FIFO Overrun: %04x", s->name, fsts.len);
- if (fsts.len & LSM6DSO_FIFO_DIFF_MASK)
- ret = load_fifo(s, &fsts, last_interrupt_timestamp);
+ fifo_len = fsts.len & LSM6DSO_FIFO_DIFF_MASK;
+ if (fifo_len) {
+ ret = load_fifo(s, fifo_len, last_interrupt_timestamp);
+ has_read_fifo = true;
+ }
+ } while (fifo_len != 0 && ret == EC_SUCCESS);
- if (IS_ENABLED(CONFIG_ACCEL_FIFO) && ret > 0)
- motion_sense_fifo_commit_data();
- }
+ if (ret == EC_SUCCESS && has_read_fifo)
+ motion_sense_fifo_commit_data();
return ret;
}