diff options
author | Alec Berg <alecaberg@chromium.org> | 2014-02-28 10:21:37 -0800 |
---|---|---|
committer | chrome-internal-fetch <chrome-internal-fetch@google.com> | 2014-03-01 02:36:06 +0000 |
commit | 832a0c7988eff6a70fbb685577b7b15b36e23f4f (patch) | |
tree | 90c3253008b23b6a49a4bf41a065d50525e44a75 | |
parent | a2809457419479e6d8c6e7c75af640d47c994072 (diff) | |
download | chrome-ec-832a0c7988eff6a70fbb685577b7b15b36e23f4f.tar.gz |
rambi: fix two bugs with accelerometer driver
Two bugs are:
- Need to grab the I2C port mutex before performing i2cxfer.
- Added sending software reset command to accelerometers on init.
This is necessary because the accelerometers can be powered
through an EC reboot, and it's important we restore them to a
known state.
BUG=none
BRANCH=rambi
TEST=Manually set accelerometer setting, rebooted, manually read
that setting and verified it was restored to default.
Change-Id: Ic3034ae39c936e07ca28458a60557b9623674ff1
Original-Change-Id: I0ea571f3a8dc46052128def24cbb5c1c29638469
Signed-off-by: Alec Berg <alecaberg@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/188349
Reviewed-by: Randall Spangler <rspangler@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/188387
-rw-r--r-- | driver/accel_kxcj9.c | 31 |
1 files changed, 29 insertions, 2 deletions
diff --git a/driver/accel_kxcj9.c b/driver/accel_kxcj9.c index 83967eb873..b6160698ab 100644 --- a/driver/accel_kxcj9.c +++ b/driver/accel_kxcj9.c @@ -11,6 +11,7 @@ #include "driver/accel_kxcj9.h" #include "gpio.h" #include "i2c.h" +#include "timer.h" #include "util.h" /* Range of the accelerometers: 2G, 4G, or 8G. */ @@ -23,7 +24,6 @@ static int sensor_resolution[ACCEL_COUNT] = {KXCJ9_RES_12BIT, KXCJ9_RES_12BIT}; static int sensor_datarate[ACCEL_COUNT] = {KXCJ9_OSA_12_50HZ, KXCJ9_OSA_12_50HZ}; -#ifdef CONFIG_CMD_ACCELS /** * Read register from accelerometer. */ @@ -31,7 +31,6 @@ static int raw_read8(const int addr, const int reg, int *data_ptr) { return i2c_read8(I2C_PORT_ACCEL, addr, reg, data_ptr); } -#endif /* CONFIG_CMD_ACCELS */ /** * Write register from accelerometer. @@ -123,8 +122,10 @@ int accel_read(enum accel_id id, int *x_acc, int *y_acc, int *z_acc) return EC_ERROR_INVAL; /* Read 6 bytes starting at KXCJ9_XOUT_L. */ + i2c_lock(I2C_PORT_ACCEL, 1); ret = i2c_xfer(I2C_PORT_ACCEL, accel_addr[id], ®, 1, acc, 6, I2C_XFER_SINGLE); + i2c_lock(I2C_PORT_ACCEL, 0); if (ret != EC_SUCCESS) return ret; @@ -165,11 +166,37 @@ int accel_read(enum accel_id id, int *x_acc, int *y_acc, int *z_acc) int accel_init(enum accel_id id) { int ret = EC_SUCCESS; + int cnt = 0, ctrl2; /* Check for valid id. */ if (id < 0 || id >= ACCEL_COUNT) return EC_ERROR_INVAL; + /* + * This sensor can be powered through an EC reboot, so the state of + * the sensor is unknown here. Initiate software reset to restore + * sensor to default. + */ + ret = raw_write8(accel_addr[id], KXCJ9_CTRL2, KXCJ9_CTRL2_SRST); + if (ret != EC_SUCCESS) + return ret; + + /* Wait until software reset is complete or timeout. */ + while (1) { + raw_read8(accel_addr[id], KXCJ9_CTRL2, &ctrl2); + + /* Reset complete. */ + if (!(ctrl2 & KXCJ9_CTRL2_SRST)) + break; + + /* Check for timeout. */ + if (cnt++ > 5) + return EC_ERROR_TIMEOUT; + + /* Give more time for reset action to complete. */ + msleep(10); + } + /* Enable accelerometer, 12-bit resolution mode, +/- 2G range.*/ ret |= raw_write8(accel_addr[id], KXCJ9_CTRL1, KXCJ9_CTRL1_PC1 | sensor_resolution[id] | |