summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVic Yang <victoryang@chromium.org>2013-06-10 21:49:34 +0800
committerChromeBot <chrome-bot@google.com>2013-06-11 02:25:22 -0700
commit9b981bf1afe1b8c08c46f5911e8e7269349088d3 (patch)
tree30fc33d2a0a8de9580261cafb3b639dc0f2031c1
parent572193cb9ad4cd909962b2dceff287431221577d (diff)
downloadchrome-ec-9b981bf1afe1b8c08c46f5911e8e7269349088d3.tar.gz
Retry when TSU6721 initialization fails
Sometimes initialization may fail due to bad I2C bus status. Let's allow for maximum 3 tries of initialization 500ms apart from previous attempt. BUG=chrome-os-partner:20020 TEST=Boot and check device type detection still works. BRANCH=spring Change-Id: I6ccedf77c92c4b6014ca24c7a63534316eaa7b6a Signed-off-by: Vic Yang <victoryang@chromium.org> Reviewed-on: https://gerrit.chromium.org/gerrit/58071 Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
-rw-r--r--common/tsu6721.c59
-rw-r--r--include/tsu6721.h10
2 files changed, 44 insertions, 25 deletions
diff --git a/common/tsu6721.c b/common/tsu6721.c
index 41a2b9ce11..e5f519582d 100644
--- a/common/tsu6721.c
+++ b/common/tsu6721.c
@@ -27,6 +27,9 @@
/* Delay values */
#define TSU6721_SW_RESET_DELAY 15
+/* Number of retries when reset fails */
+#define TSU6721_SW_RESET_RETRY 3
+
static int saved_interrupts;
uint8_t tsu6721_read(uint8_t reg)
@@ -41,31 +44,32 @@ uint8_t tsu6721_read(uint8_t reg)
return val;
}
-void tsu6721_write(uint8_t reg, uint8_t val)
+int tsu6721_write(uint8_t reg, uint8_t val)
{
int res;
res = i2c_write8(I2C_PORT_HOST, TSU6721_I2C_ADDR, reg, val);
if (res)
CPRINTF("[%T TSU6721 I2C write failed]\n");
+ return res;
}
-void tsu6721_enable_interrupts(void)
+int tsu6721_enable_interrupts(void)
{
int ctrl = tsu6721_read(TSU6721_REG_CONTROL);
- tsu6721_write(TSU6721_REG_CONTROL, ctrl & 0x1e);
+ return tsu6721_write(TSU6721_REG_CONTROL, ctrl & 0x1e);
}
-void tsu6721_disable_interrupts(void)
+int tsu6721_disable_interrupts(void)
{
int ctrl = tsu6721_read(TSU6721_REG_CONTROL);
- tsu6721_write(TSU6721_REG_CONTROL, ctrl | 0x1);
+ return tsu6721_write(TSU6721_REG_CONTROL, ctrl | 0x1);
}
-void tsu6721_set_interrupt_mask(uint16_t mask)
+int tsu6721_set_interrupt_mask(uint16_t mask)
{
- tsu6721_write(TSU6721_REG_INT_MASK1, (~mask) & 0xff);
- tsu6721_write(TSU6721_REG_INT_MASK2, ((~mask) >> 8) & 0xff);
+ return tsu6721_write(TSU6721_REG_INT_MASK1, (~mask) & 0xff) |
+ tsu6721_write(TSU6721_REG_INT_MASK2, ((~mask) >> 8) & 0xff);
}
int tsu6721_get_interrupts(void)
@@ -91,10 +95,20 @@ int tsu6721_get_device_type(void)
void tsu6721_reset(void)
{
- tsu6721_write(TSU6721_REG_RESET, 0x1);
- /* TSU6721 reset takes ~10ms. Let's wait for 15ms to be safe. */
- msleep(TSU6721_SW_RESET_DELAY);
- tsu6721_init();
+ int i;
+
+ for (i = 0; i < TSU6721_SW_RESET_RETRY; ++i) {
+ if (i != 0) {
+ CPRINTF("[%T TSU6721 init failed. Retrying.]\n");
+ msleep(500);
+ }
+ if (tsu6721_write(TSU6721_REG_RESET, 0x1))
+ continue;
+ /* TSU6721 reset takes ~10ms. Let's wait for 15ms to be safe. */
+ msleep(TSU6721_SW_RESET_DELAY);
+ if (tsu6721_init() == EC_SUCCESS)
+ break;
+ }
}
int tsu6721_mux(enum tsu6721_mux sel)
@@ -124,26 +138,31 @@ int tsu6721_mux(enum tsu6721_mux sel)
return EC_SUCCESS;
}
-void tsu6721_init(void)
+int tsu6721_init(void)
{
uint8_t settings;
uint8_t dev_id = tsu6721_read(TSU6721_REG_DEV_ID);
+ int res = 0;
if ((dev_id != 0x0a) && (dev_id != 0x12)) {
CPRINTF("TSU6721 invalid device ID 0x%02x\n", dev_id);
- return;
+ return EC_ERROR_UNKNOWN;
}
/* set USB charger detection timeout to 600ms */
settings = tsu6721_read(TSU6721_REG_TIMER);
+ if (settings == 0xee)
+ return EC_ERROR_UNKNOWN;
settings = (settings & ~0x38) | 0x28;
- tsu6721_write(TSU6721_REG_TIMER, settings);
+ res |= tsu6721_write(TSU6721_REG_TIMER, settings);
+
+ res |= tsu6721_set_interrupt_mask(TSU6721_INT_ATTACH |
+ TSU6721_INT_DETACH |
+ TSU6721_INT_ADC_CHANGE |
+ TSU6721_INT_VBUS);
+ res |= tsu6721_enable_interrupts();
- tsu6721_set_interrupt_mask(TSU6721_INT_ATTACH |
- TSU6721_INT_DETACH |
- TSU6721_INT_ADC_CHANGE |
- TSU6721_INT_VBUS);
- tsu6721_enable_interrupts();
+ return res ? EC_ERROR_UNKNOWN : EC_SUCCESS;
}
/*
* TODO(vpalatin): using the I2C early in the HOOK_INIT
diff --git a/include/tsu6721.h b/include/tsu6721.h
index da9fd0ea3e..e614be7e09 100644
--- a/include/tsu6721.h
+++ b/include/tsu6721.h
@@ -73,22 +73,22 @@ enum tsu6721_mux {
#define TSU6721_TYPE_VBUS_DEBOUNCED 0x020000
/* Initialize TSU6721. */
-void tsu6721_init(void);
+int tsu6721_init(void);
/* Read TSU6721 register. */
uint8_t tsu6721_read(uint8_t reg);
/* Write TSU6721 register. */
-void tsu6721_write(uint8_t reg, uint8_t val);
+int tsu6721_write(uint8_t reg, uint8_t val);
/* Enable interrupts. */
-void tsu6721_enable_interrupts(void);
+int tsu6721_enable_interrupts(void);
/* Disable all interrupts. */
-void tsu6721_disable_interrupts(void);
+int tsu6721_disable_interrupts(void);
/* Set interrupt mask. */
-void tsu6721_set_interrupt_mask(uint16_t mask);
+int tsu6721_set_interrupt_mask(uint16_t mask);
/* Get and clear current interrupt status. Return value is a combination of
* TSU6721_INT_* */