summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGwendal Grignou <gwendal@chromium.org>2015-11-24 12:21:44 -0800
committerChromeOS bot <3su6n15k.default@developer.gserviceaccount.com>2015-12-01 19:01:54 +0000
commit087959dca16294bd4c8dca4fd9e6cd26762324d5 (patch)
tree9ccd86b168d34aba3b316d8dae514140663b8a55
parent5c13f7e2c4d717fa5950f8f64c420a12d2674d30 (diff)
downloadchrome-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.c25
-rw-r--r--driver/als_si114x.h3
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 {