summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYidi Lin <yidi.lin@mediatek.com>2017-06-14 10:54:28 +0800
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2017-08-02 03:41:29 +0000
commit5a52614b8c87ab1de84c461b7bbd0b4a14dc7fdb (patch)
tree4bb264e353f97af628ae0d4be3e86f531e321f13
parent57720aa9f03f820d1858f5812d101ff26e38450f (diff)
downloadchrome-ec-5a52614b8c87ab1de84c461b7bbd0b4a14dc7fdb.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-liner behavior of a power supply or unexpected noise above normal on the power rail during a power up. BRANCH=oak BUG=b:62607555 TEST=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' Change-Id: I362f2af59253519aa35b72cfb6b666c49e425777 Signed-off-by: Yidi Lin <yidi.lin@mediatek.com> Reviewed-on: https://chromium-review.googlesource.com/536723 Reviewed-by: Gwendal Grignou <gwendal@chromium.org>
-rw-r--r--driver/accel_kionix.c97
-rw-r--r--driver/accel_kx022.h3
2 files changed, 62 insertions, 38 deletions
diff --git a/driver/accel_kionix.c b/driver/accel_kionix.c
index 1267ec2989..a8c3f6ec0e 100644
--- a/driver/accel_kionix.c
+++ b/driver/accel_kionix.c
@@ -457,60 +457,82 @@ 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 && val == KIONIX_WHO_AM_I_VAL(V(s)))
- break;
-
- /* Check for timeout. */
- if (timeout++ > 20) {
- ret = EC_ERROR_TIMEOUT;
- break;
+ if (V(s)) {
+ /* Place the sensor in standby mode for KXCJ9 */
+ ret = disable_sensor(s, &val);
+ } 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)) {
+ 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;
+ } 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;
}
- val |= reset_field;
+
ret = raw_write8(s->port, s->addr, reg, val);
- if (ret != EC_SUCCESS) {
- mutex_unlock(s->mutex);
- return ret;
+ if (ret != EC_SUCCESS)
+ goto reset_failed;
+
+ if (!V(s)) {
+ /* wait 2 milliseconds for completion of the software reset*/
+ msleep(2);
+
+ reg = KX022_COTR;
+ ret = raw_read8(s->port, s->addr, reg, &val);
+ if (val != KX022_COTR_VAL_DEFAULT) {
+ CPRINTF("[%s: the software reset failed]\n", s->name);
+ ret = EC_ERROR_HW_INTERNAL;
+ goto reset_failed;
+ }
+ }
+
+ 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;
}
/* The SRST will be cleared when reset is complete. */
+ reg = KIONIX_CTRL2_REG(V(s));
timeout = 0;
do {
msleep(1);
ret = raw_read8(s->port, s->addr, reg, &val);
if (ret != EC_SUCCESS) {
- mutex_unlock(s->mutex);
- return ret;
+ goto reset_failed;
}
/* Reset complete. */
@@ -520,8 +542,7 @@ static int init(const struct motion_sensor_t *s)
/* Check for timeout. */
if (timeout++ > 5) {
ret = EC_ERROR_TIMEOUT;
- mutex_unlock(s->mutex);
- return ret;
+ goto reset_failed;
}
} while (1);
mutex_unlock(s->mutex);
@@ -540,7 +561,7 @@ static int init(const struct motion_sensor_t *s)
CPRINTF("[%T %s: Done Init type:0x%X range:%d]\n",
s->name, s->type, get_range(s));
-
+reset_failed:
mutex_unlock(s->mutex);
return ret;
}
diff --git a/driver/accel_kx022.h b/driver/accel_kx022.h
index d25d68b380..1b25ba2103 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)