diff options
author | Gwendal Grignou <gwendal@chromium.org> | 2015-11-24 12:21:44 -0800 |
---|---|---|
committer | ChromeOS bot <3su6n15k.default@developer.gserviceaccount.com> | 2015-12-01 19:01:54 +0000 |
commit | 087959dca16294bd4c8dca4fd9e6cd26762324d5 (patch) | |
tree | 9ccd86b168d34aba3b316d8dae514140663b8a55 | |
parent | 5c13f7e2c4d717fa5950f8f64c420a12d2674d30 (diff) | |
download | chrome-ec-087959dca16294bd4c8dca4fd9e6cd26762324d5.tar.gz |
driver: si114x: Unlock the device if stuck
It is possible for the ALS state machine and the chip to not
agree: The EC thinks the device is busy making a measurement,
while the chip is waiting for the IRQ status register to be written.
It is not clear how it happened, an IRQ must have been lost.
Reinitiliazed the chip is stuck for 10s.
BRANCH=smaug
BUG=chrome-os-partner:45627
TEST=With an extra patch that force the IRQ handler to not do anything
every 100th, check the device recovers.
Use andro sensor to monitor light/proximity outputs.
Change-Id: I80d50bf92af127f85f82dc5c0ae318d4cfe06812
Signed-off-by: Gwendal Grignou <gwendal@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/313668
(cherry picked from commit 53fa1d1f0938f7021727880207631f2c9b82e115)
Signed-off-by: Gwendal Grignou <gwendal@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/314958
-rw-r--r-- | driver/als_si114x.c | 25 | ||||
-rw-r--r-- | driver/als_si114x.h | 3 |
2 files changed, 27 insertions, 1 deletions
diff --git a/driver/als_si114x.c b/driver/als_si114x.c index dc1c53f00b..e23bc06854 100644 --- a/driver/als_si114x.c +++ b/driver/als_si114x.c @@ -21,6 +21,8 @@ #define CPRINTF(format, args...) cprintf(CC_ACCEL, format, ## args) #define CPRINTS(format, args...) cprints(CC_ACCEL, format, ## args) +static int init(const struct motion_sensor_t *s); + /** * Read 8bit register from device. */ @@ -258,8 +260,29 @@ static int read(const struct motion_sensor_t *s, vector_3_t v) break; case SI114X_ALS_IN_PROGRESS_PS_PENDING: case SI114X_PS_IN_PROGRESS_ALS_PENDING: - default: ret = EC_ERROR_ACCESS_DENIED; + break; + case SI114X_NOT_READY: + ret = EC_ERROR_NOT_POWERED; + } + if (ret == EC_ERROR_ACCESS_DENIED && + s->type == MOTIONSENSE_TYPE_LIGHT) { + timestamp_t ts_now = get_time(); + + /* + * We were unable to access the sensor for THRES time. + * We should reset the sensor to clear the interrupt register + * and the state machine. + */ + if (time_after(ts_now.le.lo, + s->last_collection + SI114X_DENIED_THRESHOLD)) { + int ret, val; + + ret = raw_read8(s->addr, SI114X_REG_IRQ_STATUS, &val); + CPRINTS("%d stuck IRQ_STATUS 0x%02x - ret %d", + s->name, val, ret); + init(s); + } } return ret; } diff --git a/driver/als_si114x.h b/driver/als_si114x.h index 93e9b9a9bc..5fbc3c665f 100644 --- a/driver/als_si114x.h +++ b/driver/als_si114x.h @@ -208,6 +208,9 @@ #define SI114X_COVERED_THRESHOLD 5 #define SI114X_OVERFLOW 0xffff +/* Time to wait before re-initializing the device if access is denied */ +#define SI114X_DENIED_THRESHOLD (10 * SECOND) + extern const struct accelgyro_drv si114x_drv; enum si114x_state { |