summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVic Yang <victoryang@chromium.org>2013-04-29 18:53:42 +0800
committerChromeBot <chrome-bot@google.com>2013-05-01 10:22:14 -0700
commita041fe062a1122301fb0f5a7113b14dc8c33e782 (patch)
treeaefc9381ef895ccc5f598dfa1240f7882cca1c25
parent23c8a5b7224dcc05a0793f409d16e695c04a5388 (diff)
downloadchrome-ec-a041fe062a1122301fb0f5a7113b14dc8c33e782.tar.gz
Monitor video detachment with ADC watchdog
This eliminates a per-second hook and removes a duplicated ADC read per second. Also, TSU6721 is now reset after every detachment. This way, we don't suffer from TSU6721 dirty state (most commonly seen after OTG dongle detached.) BUG=chrome-os-partner:17928 TEST=1. Test plugging/unplugging video dongle. 2. Test Toad cable mode switching. 3. Test charging with 200K charger. BRANCH=spring Original-Change-Id: Ic035b7332e07ca385d766c735ce39efd31e46034 Signed-off-by: Vic Yang <victoryang@chromium.org> Reviewed-on: https://gerrit.chromium.org/gerrit/49578 Reviewed-by: Vincent Palatin <vpalatin@chromium.org> Change-Id: Ia6cbbe102491642c514cb47919793b96e20efbbe Signed-off-by: Vic Yang <victoryang@chromium.org> Reviewed-on: https://gerrit.chromium.org/gerrit/49715 Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
-rw-r--r--board/spring/usb_charging.c104
1 files changed, 68 insertions, 36 deletions
diff --git a/board/spring/usb_charging.c b/board/spring/usb_charging.c
index f17a455bb1..1abec4ea82 100644
--- a/board/spring/usb_charging.c
+++ b/board/spring/usb_charging.c
@@ -79,7 +79,8 @@ static int nominal_pwm_duty;
static int current_pwm_duty;
static int user_pwm_duty = -1;
-static int pending_tsu6721_reset;
+static int pending_toad_redetect;
+static int pending_video_detach;
static enum {
LIMIT_NORMAL,
@@ -89,6 +90,7 @@ static enum {
static enum {
ADC_WATCH_NONE,
ADC_WATCH_TOAD,
+ ADC_WATCH_VIDEO,
} current_watchdog = ADC_WATCH_NONE;
struct {
@@ -308,7 +310,7 @@ static int board_pwm_check_vbus_low(int vbus, int battery_current)
return vbus < PWM_CTRL_VBUS_HARD_LOW && current_pwm_duty < 100;
}
-static void board_pwm_tweak(void)
+static void board_power_tweak(void)
{
int vbus, current;
@@ -316,6 +318,15 @@ static void board_pwm_tweak(void)
return;
vbus = adc_read_channel(ADC_CH_USB_VBUS_SNS);
+
+ /* Check video power input change */
+ if (current_dev_type & TSU6721_TYPE_JIG_UART_ON) {
+ if (get_video_power() && vbus > 4000)
+ set_video_power(0);
+ else if (!get_video_power() && vbus <= 4000)
+ set_video_power(1);
+ }
+
if (battery_current(&current))
return;
@@ -342,7 +353,7 @@ static void board_pwm_tweak(void)
CPRINTF("[%T PWM duty down %d%%]\n", current_pwm_duty);
}
}
-DECLARE_HOOK(HOOK_SECOND, board_pwm_tweak, HOOK_PRIO_DEFAULT);
+DECLARE_HOOK(HOOK_SECOND, board_power_tweak, HOOK_PRIO_DEFAULT);
void board_pwm_nominal_duty_cycle(int percent)
{
@@ -371,13 +382,43 @@ static void board_adc_watch_toad(void)
current_watchdog = ADC_WATCH_TOAD;
}
-static void board_adc_watchdog_interrupt(void)
+static void board_adc_watch_video(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);
+ int retry_count = 10;
+
+ /*
+ * Let DP_SNS voltage settle so that we don't trigger watchdog
+ * unintentionally.
+ */
+ while (retry_count-- &&
+ adc_read_channel(ADC_CH_USB_DP_SNS) > VIDEO_ID_THRESHOLD)
+ msleep(20);
+
+ /* DP_SNS kept high. Assuming dongle detached already. */
+ if (retry_count <= 0) {
+ pending_video_detach = 1;
+ return;
}
+
+ /*
+ * Watch DP_SNS and interrupt if voltage goes above
+ * VIDEO_ID_THRESHOLD
+ */
+ adc_enable_watchdog(STM32_AIN(2), VIDEO_ID_THRESHOLD * 4096 / 3300, 0);
+ task_clear_pending_irq(STM32_IRQ_ADC_1);
+ task_enable_irq(STM32_IRQ_ADC_1);
+ current_watchdog = ADC_WATCH_VIDEO;
+}
+
+
+static void board_adc_watchdog_interrupt(void)
+{
+ if (current_watchdog == ADC_WATCH_TOAD)
+ pending_toad_redetect = 1;
+ else if (current_watchdog == ADC_WATCH_VIDEO)
+ pending_video_detach = 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);
@@ -507,7 +548,6 @@ static void usb_log_dev_type(int dev_type)
static void usb_device_change(int dev_type)
{
-
if (current_dev_type == dev_type)
return;
@@ -533,6 +573,8 @@ static void usb_device_change(int dev_type)
if ((dev_type & TOAD_DEVICE_TYPE) &&
(dev_type & TSU6721_TYPE_VBUS_DEBOUNCED))
board_adc_watch_toad();
+ else if (dev_type & TSU6721_TYPE_JIG_UART_ON)
+ board_adc_watch_video();
usb_log_dev_type(dev_type);
@@ -545,46 +587,36 @@ static void usb_device_change(int dev_type)
enable_sleep(SLEEP_MASK_USB_PWR);
}
-/*
- * TODO(victoryang): Get rid of polling loop when ADC watchdog is ready.
- * See crosbug.com/p/18171
- */
-static void board_usb_monitor_detach(void)
+void board_usb_charge_update(int force_update)
{
- int vbus;
+ int int_val = 0;
+ int want_reset = 0;
- if (!(current_dev_type & TSU6721_TYPE_JIG_UART_ON))
- return;
+ if (pending_video_detach || pending_toad_redetect) {
+ current_watchdog = ADC_WATCH_NONE;
+ adc_disable_watchdog();
+ want_reset = 1;
+ }
- if (adc_read_channel(ADC_CH_USB_DP_SNS) > VIDEO_ID_THRESHOLD) {
+ if (pending_video_detach) {
set_video_power(0);
gpio_set_level(GPIO_ID_MUX, 0);
msleep(DELAY_ID_MUX_MS);
tsu6721_enable_interrupts();
- usb_device_change(TSU6721_TYPE_NONE);
}
- /* Check if there is external power */
- vbus = adc_read_channel(ADC_CH_USB_VBUS_SNS);
- if (get_video_power() && vbus > 4000)
- set_video_power(0);
- else if (!get_video_power() && vbus <= 4000)
- set_video_power(1);
-}
-DECLARE_HOOK(HOOK_SECOND, board_usb_monitor_detach, HOOK_PRIO_DEFAULT);
+ pending_video_detach = 0;
+ pending_toad_redetect = 0;
-void board_usb_charge_update(int force_update)
-{
- int int_val = 0;
+ if (!want_reset) {
+ int_val = tsu6721_get_interrupts();
+ want_reset = (int_val & TSU6721_INT_DETACH);
+ }
- if (pending_tsu6721_reset) {
- current_watchdog = ADC_WATCH_NONE;
- adc_disable_watchdog();
+ if (want_reset) {
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);