summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYidi Lin <yidi.lin@mediatek.com>2017-06-14 10:54:28 +0800
committerchrome-bot <chrome-bot@chromium.org>2018-03-19 17:04:54 -0700
commit7640df67aaf2fa8d135ee04f9a63090816adaf17 (patch)
tree4345e611c05a459b022becdc81dc38a229c5f6af
parent1c03af23e1f8a62b6815fd520de5ace9e365b12f (diff)
downloadchrome-ec-7640df67aaf2fa8d135ee04f9a63090816adaf17.tar.gz
driver: kionix: Add software reset flow for KX022
Kionix suggests that it is recommended to issue the Software Reset command after the device was powered. This is effective against dynamic or non-linear behavior of a power supply or unexpected noise above normal on the power rail during a power up. BRANCH=eve BUG=b:62607555 TEST=kx022: 1. press power button 10 second to power off. 2. power on the DUT 3. refresh + power button to cold reboot the DUT 4. Check the g-sensor by 'ectool motionsense' kxcj9: eve: sensor kxcj9 found. Signed-off-by: Yidi Lin <yidi.lin@mediatek.com> Reviewed-on: https://chromium-review.googlesource.com/536723 Reviewed-by: Gwendal Grignou <gwendal@chromium.org> (cherry picked from commit 5a52614b8c87ab1de84c461b7bbd0b4a14dc7fdb) Conflict in init routine in accel_kionix.c. By moving WHOAMI after reset, we expect the test to work the first time.) Change-Id: I362f2af59253519aa35b72cfb6b666c49e425777 Signed-off-by: Gwendal Grignou <gwendal@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/753969
-rw-r--r--driver/accel_kionix.c141
-rw-r--r--driver/accel_kx022.h3
2 files changed, 95 insertions, 49 deletions
diff --git a/driver/accel_kionix.c b/driver/accel_kionix.c
index b3a1cde3ab..150a050226 100644
--- a/driver/accel_kionix.c
+++ b/driver/accel_kionix.c
@@ -513,68 +513,107 @@ static int init(const struct motion_sensor_t *s)
int ret, val, reg, reset_field;
uint8_t timeout;
- /* The chip can take up to 10ms to boot */
mutex_lock(s->mutex);
- reg = KIONIX_WHO_AM_I(V(s));
- timeout = 0;
- do {
- msleep(1);
- /* Read WHO_AM_I to be sure the device has booted */
- ret = raw_read8(s->port, s->addr, reg, &val);
- if (ret == EC_SUCCESS)
- break;
-
- /* Check for timeout. */
- if (timeout++ > 20) {
- ret = EC_ERROR_TIMEOUT;
- break;
+ if (V(s)) {
+ /* The chip can take up to 10ms to boot */
+ reg = KIONIX_WHO_AM_I(V(s));
+ timeout = 0;
+ do {
+ msleep(1);
+ /* Read WHO_AM_I to be sure the device has booted */
+ ret = raw_read8(s->port, s->addr, reg, &val);
+ if (ret == EC_SUCCESS)
+ break;
+
+ /* Check for timeout. */
+ if (timeout++ > 20) {
+ ret = EC_ERROR_TIMEOUT;
+ break;
+ }
+ } while (1);
+ } else {
+ /* Write 0x00 to the internal register for KX022 */
+ reg = KX022_INTERNAL;
+ ret = raw_write8(s->port, s->addr, reg, 0x0);
+ if (ret != EC_SUCCESS) {
+ /*
+ * For I2C communication, if ACK was not received
+ * from the first address, resend the command using
+ * the second address.
+ */
+ if (!KIONIX_IS_SPI(s->addr)) {
+ ret = raw_write8(s->port, s->addr & ~4, reg,
+ 0x0);
+ }
}
- } while (1);
- if (ret != EC_SUCCESS) {
- mutex_unlock(s->mutex);
- return ret;
}
+ if (ret != EC_SUCCESS)
+ goto reset_failed;
+
+ /* Issue a software reset. */
reg = KIONIX_CTRL2_REG(V(s));
reset_field = KIONIX_RESET_FIELD(V(s));
- /* Issue a software reset. */
+ if (V(s)) {
+ /* Place the sensor in standby mode to make changes. */
+ ret = disable_sensor(s, &val);
+ if (ret != EC_SUCCESS)
+ goto reset_failed;
+ ret = raw_read8(s->port, s->addr, reg, &val);
+ if (ret != EC_SUCCESS)
+ goto reset_failed;
- /* Place the sensor in standby mode to make changes. */
- ret = disable_sensor(s, &val);
- if (ret != EC_SUCCESS) {
- mutex_unlock(s->mutex);
- return ret;
- }
- ret = raw_read8(s->port, s->addr, reg, &val);
- if (ret != EC_SUCCESS) {
- mutex_unlock(s->mutex);
- return ret;
- }
- val |= reset_field;
- ret = raw_write8(s->port, s->addr, reg, val);
- if (ret != EC_SUCCESS) {
- mutex_unlock(s->mutex);
- return ret;
+ val |= reset_field;
+ } else {
+ /* Write 0 to CTRL2 for KX022 */
+ ret = raw_write8(s->port, s->addr, reg, 0x0);
+ if (ret != EC_SUCCESS)
+ goto reset_failed;
+
+ val = reset_field;
}
- /* The SRST will be cleared when reset is complete. */
- timeout = 0;
- do {
- msleep(1);
+ ret = raw_write8(s->port, s->addr, reg, val);
+ if (ret != EC_SUCCESS)
+ goto reset_failed;
+
+ if (V(s)) {
+ /* The SRST will be cleared when reset is complete. */
+ timeout = 0;
+ do {
+ msleep(1);
+
+ ret = raw_read8(s->port, s->addr, reg, &val);
+ /* Reset complete. */
+ if ((ret == EC_SUCCESS) && !(val & reset_field))
+ break;
+ /* Check for timeout. */
+ if (timeout++ > 20) {
+ ret = EC_ERROR_TIMEOUT;
+ goto reset_failed;
+ }
+ } while (1);
+ } else {
+ /* Wait 2 milliseconds for completion of the software reset. */
+ msleep(2);
+ reg = KX022_COTR;
ret = raw_read8(s->port, s->addr, reg, &val);
- /* Reset complete. */
- if ((ret == EC_SUCCESS) && !(val & reset_field))
- break;
-
- /* Check for timeout. */
- if (timeout++ > 20) {
- ret = EC_ERROR_TIMEOUT;
- mutex_unlock(s->mutex);
- return ret;
+ if (val != KX022_COTR_VAL_DEFAULT) {
+ CPRINTF("[%s: the software reset failed]\n", s->name);
+ ret = EC_ERROR_HW_INTERNAL;
+ goto reset_failed;
}
- } while (1);
+ }
+
+ reg = KIONIX_WHO_AM_I(V(s));
+ ret = raw_read8(s->port, s->addr, reg, &val);
+ if (ret != EC_SUCCESS || val != KIONIX_WHO_AM_I_VAL(V(s))) {
+ ret = EC_ERROR_HW_INTERNAL;
+ goto reset_failed;
+ }
+
mutex_unlock(s->mutex);
/* Initialize with the desired parameters. */
@@ -586,6 +625,10 @@ static int init(const struct motion_sensor_t *s)
return ret;
return sensor_init_done(s);
+
+reset_failed:
+ mutex_unlock(s->mutex);
+ return ret;
}
const struct accelgyro_drv kionix_accel_drv = {
diff --git a/driver/accel_kx022.h b/driver/accel_kx022.h
index 7fd7508395..1192881384 100644
--- a/driver/accel_kx022.h
+++ b/driver/accel_kx022.h
@@ -30,6 +30,8 @@
#define KX022_ZOUT_L 0x0a
#define KX022_ZOUT_H 0x0b
#define KX022_COTR 0x0c
+#define KX022_COTR_VAL_COTC 0xAA
+#define KX022_COTR_VAL_DEFAULT 0x55
#define KX022_WHOAMI 0x0f
#define KX022_TSCP 0x10
#define KX022_TSPP 0x11
@@ -70,6 +72,7 @@
#define KX022_BUF_CLEAR 0x3e
#define KX022_BUF_READ 0x3f
#define KX022_SELF_TEST 0x60
+#define KX022_INTERNAL 0x7f
#define KX022_CNTL1_PC1 (1 << 7)