summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVic Yang <victoryang@chromium.org>2013-03-18 15:12:05 +0800
committerChromeBot <chrome-bot@google.com>2013-03-20 17:43:18 -0700
commit5e937a8003d6e2da246916a92670f8ba6d829780 (patch)
treed4cbf624e75b9bb1c4aaaba978ee3123ddda08e2
parente2b11fab46595cd43b027bc847aaa315677381b0 (diff)
downloadchrome-ec-5e937a8003d6e2da246916a92670f8ba6d829780.tar.gz
spring: reset TSU6721 when Toad's ID changes
When Toad's ID changes, VBUS goes low for 10ms. This, however, is not picked up by TSU6721 and thus we need to monitor VBUS and reset TSU6721 when necessary. By resetting TSU6721, we can force it to update device type. BUG=chrome-os-partner:18292 TEST=manual BRANCH=spring Original-Change-Id: Ib96bbb0f101c8c5f5371591603af2dee27f01cc8 Signed-off-by: Vic Yang <victoryang@chromium.org> Reviewed-on: https://gerrit.chromium.org/gerrit/45727 (cherry picked from commit 19920f1f74f07e00160f4bb817d756f2af024744) Change-Id: Ide1ebec96b3c5597283164bdadc50a5c80196112 Signed-off-by: Vic Yang <victoryang@chromium.org> Reviewed-on: https://gerrit.chromium.org/gerrit/45991 Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
-rw-r--r--board/spring/usb_charging.c48
-rw-r--r--chip/stm32/adc.c7
-rw-r--r--common/tsu6721.c11
-rw-r--r--include/tsu6721.h3
4 files changed, 66 insertions, 3 deletions
diff --git a/board/spring/usb_charging.c b/board/spring/usb_charging.c
index 5c29af3e69..3039056893 100644
--- a/board/spring/usb_charging.c
+++ b/board/spring/usb_charging.c
@@ -31,6 +31,9 @@
#define POWERED_5000_DEVICE_TYPE (TSU6721_TYPE_OTG)
#define POWERED_3300_DEVICE_TYPE (TSU6721_TYPE_JIG_UART_ON)
+/* Toad cable */
+#define TOAD_DEVICE_TYPE (TSU6721_TYPE_UART | TSU6721_TYPE_AUDIO3)
+
/* Voltage threshold of D+ for video */
#define VIDEO_ID_THRESHOLD 1335
@@ -63,11 +66,18 @@ static int current_dev_type = TSU6721_TYPE_NONE;
static int nominal_pwm_duty;
static int current_pwm_duty;
+static int pending_tsu6721_reset;
+
static enum {
LIMIT_NORMAL,
LIMIT_AGGRESSIVE,
} current_limit_mode = LIMIT_AGGRESSIVE;
+static enum {
+ ADC_WATCH_NONE,
+ ADC_WATCH_TOAD,
+} current_watchdog = ADC_WATCH_NONE;
+
/*
* Last time we see a power source removed. Also records the power source
* type and PWM duty cycle at that moment.
@@ -299,6 +309,25 @@ void usb_charge_interrupt(enum gpio_signal signal)
task_wake(TASK_ID_PMU_TPS65090_CHARGER);
}
+static void board_adc_watch_toad(void)
+{
+ /* Watch VBUS and interrupt if voltage goes under 3V. */
+ adc_enable_watchdog(STM32_AIN(5), 4095, 1800);
+ task_clear_pending_irq(STM32_IRQ_ADC_1);
+ task_enable_irq(STM32_IRQ_ADC_1);
+ current_watchdog = ADC_WATCH_TOAD;
+}
+
+static void board_adc_watchdog_interrupt(void)
+{
+ if (current_watchdog == ADC_WATCH_TOAD) {
+ pending_tsu6721_reset = 1;
+ task_disable_irq(STM32_IRQ_ADC_1);
+ task_wake(TASK_ID_PMU_TPS65090_CHARGER);
+ }
+}
+DECLARE_IRQ(STM32_IRQ_ADC_1, board_adc_watchdog_interrupt, 2);
+
static int usb_has_power_input(int dev_type)
{
if (dev_type & TSU6721_TYPE_JIG_UART_ON)
@@ -394,6 +423,10 @@ static void usb_device_change(int dev_type)
lp5562_poweroff();
}
+ if ((dev_type & TOAD_DEVICE_TYPE) &&
+ (dev_type & TSU6721_TYPE_VBUS_DEBOUNCED))
+ board_adc_watch_toad();
+
/* Log to console */
CPRINTF("[%T USB Attached: ");
if (dev_type == TSU6721_TYPE_NONE)
@@ -416,6 +449,10 @@ static void usb_device_change(int dev_type)
CPRINTF("Apple charger]\n");
else if (dev_type & TSU6721_TYPE_JIG_UART_ON)
CPRINTF("JIG UART ON]\n");
+ else if (dev_type & TSU6721_TYPE_AUDIO3)
+ CPRINTF("Audio 3]\n");
+ else if (dev_type & TSU6721_TYPE_UART)
+ CPRINTF("UART]\n");
else if (dev_type & TSU6721_TYPE_VBUS_DEBOUNCED)
CPRINTF("Unknown with power]\n");
else
@@ -447,7 +484,16 @@ DECLARE_HOOK(HOOK_SECOND, board_usb_monitor_detach, HOOK_PRIO_DEFAULT);
void board_usb_charge_update(int force_update)
{
- int int_val = tsu6721_get_interrupts();
+ int int_val = 0;
+
+ if (pending_tsu6721_reset) {
+ current_watchdog = ADC_WATCH_NONE;
+ adc_disable_watchdog();
+ tsu6721_reset();
+ force_update = 1;
+ pending_tsu6721_reset = 0;
+ } else
+ int_val = tsu6721_get_interrupts();
if (int_val & TSU6721_INT_DETACH)
usb_device_change(TSU6721_TYPE_NONE);
diff --git a/chip/stm32/adc.c b/chip/stm32/adc.c
index b1545dac20..1aad5d5744 100644
--- a/chip/stm32/adc.c
+++ b/chip/stm32/adc.c
@@ -97,6 +97,9 @@ static int adc_enable_watchdog_no_lock(void)
/* Set channel */
STM32_ADC_CR1 = (STM32_ADC_CR1 & ~0x1f) | watchdog_ain_id;
+ /* Clear interrupt bit */
+ STM32_ADC_SR &= ~0x1;
+
/* AWDSGL=1, SCAN=1, AWDIE=1, AWDEN=1 */
STM32_ADC_CR1 |= (1 << 9) | (1 << 8) | (1 << 6) | (1 << 23);
@@ -138,8 +141,8 @@ static int adc_disable_watchdog_no_lock(void)
if (!adc_watchdog_enabled())
return EC_ERROR_UNKNOWN;
- /* AWDEN=0 */
- STM32_ADC_CR1 &= ~(1 << 23);
+ /* AWDEN=0, AWDIE=0 */
+ STM32_ADC_CR1 &= ~(1 << 23) & ~(1 << 6);
/* CONT=0 */
STM32_ADC_CR2 &= ~(1 << 1);
diff --git a/common/tsu6721.c b/common/tsu6721.c
index 7f3d1d0c7e..629e8e3e86 100644
--- a/common/tsu6721.c
+++ b/common/tsu6721.c
@@ -24,6 +24,9 @@
/* 8-bit I2C address */
#define TSU6721_I2C_ADDR (0x25 << 1)
+/* Delay values */
+#define TSU6721_SW_RESET_DELAY 15
+
static int saved_interrupts;
uint8_t tsu6721_read(uint8_t reg)
@@ -86,6 +89,14 @@ int tsu6721_get_device_type(void)
(tsu6721_read(TSU6721_REG_DEV_TYPE1));
}
+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 tsu6721_mux(enum tsu6721_mux sel)
{
uint8_t id = tsu6721_read(TSU6721_REG_ADC);
diff --git a/include/tsu6721.h b/include/tsu6721.h
index 619465453b..da9fd0ea3e 100644
--- a/include/tsu6721.h
+++ b/include/tsu6721.h
@@ -105,4 +105,7 @@ int tsu6721_get_device_type(void);
/* Control TSU6721 mux. */
int tsu6721_mux(enum tsu6721_mux sel);
+/* Reset TSU6721. */
+void tsu6721_reset(void);
+
#endif /* TSU6721_H */