summaryrefslogtreecommitdiff
path: root/driver/als_si114x.c
diff options
context:
space:
mode:
authorGwendal Grignou <gwendal@chromium.org>2015-11-24 12:21:44 -0800
committerchrome-bot <chrome-bot@chromium.org>2015-12-01 03:46:34 -0800
commit53fa1d1f0938f7021727880207631f2c9b82e115 (patch)
treea11d2cdabb180945178f920564bdfa30274b5d53 /driver/als_si114x.c
parente803e811147212bfea43ad62bfe9d9ed293c8f8b (diff)
downloadchrome-ec-53fa1d1f0938f7021727880207631f2c9b82e115.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
Diffstat (limited to 'driver/als_si114x.c')
-rw-r--r--driver/als_si114x.c25
1 files changed, 24 insertions, 1 deletions
diff --git a/driver/als_si114x.c b/driver/als_si114x.c
index e3cb87a2a4..bdd39fa5b0 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.
*/
@@ -259,8 +261,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;
}