diff options
author | Vic Yang <victoryang@chromium.org> | 2013-06-17 11:06:55 +0800 |
---|---|---|
committer | ChromeBot <chrome-bot@google.com> | 2013-06-17 10:31:50 -0700 |
commit | b93658ba02cf381e2a0e20c4d7128814d685e502 (patch) | |
tree | cf2627ae7eca5340ac7a2f1ac9505775736d2b6b | |
parent | 37b5adb123f52b721eda63b36ad6743281fd46df (diff) | |
download | chrome-ec-b93658ba02cf381e2a0e20c4d7128814d685e502.tar.gz |
Redetect USB device type on non-standard charger
If the device type is non-standard charger, it could be the user
plugging in the connector too slowly and TSU6721 BCD timer expired
before the connector is fully plugged in.
Extending TSU6721 BCD timer causes a big delay in Apple charger
detection, and breaks how we detect over-current. Let's do this by
a re-detection instead. If we see a different device type, just
update the device type we have. Otherwise, we reset TSU6721 to force a
re-detection.
BUG=chrome-os-partner:19765
TEST=Plug in a charger half way in. Wait for a second, plug it in all
the way. See device type changed after few seconds.
TEST=Plug in a charger half way in and leave it there. Only see
redetection once.
TEST=Plug in a charger all the way in. See correct device type.
TEST=Plug in an Apple charger. See correct device type within a second.
TEST=Plug in a Nexus 10 charger. See correct device type after 5
seconds.
BRANCH=spring
Change-Id: Ia7733972842e6040b545670df043058c55ae3c01
Signed-off-by: Vic Yang <victoryang@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/58799
Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
-rw-r--r-- | common/extpower_usb.c | 61 |
1 files changed, 59 insertions, 2 deletions
diff --git a/common/extpower_usb.c b/common/extpower_usb.c index 51068452e6..e3188cca08 100644 --- a/common/extpower_usb.c +++ b/common/extpower_usb.c @@ -97,6 +97,8 @@ static int user_pwm_duty = -1; static int pwm_fast_mode; static int pending_tsu6721_reset; +static int pending_adc_watchdog_disable; +static int pending_dev_type_update; static int restore_id_mux; static enum { @@ -150,6 +152,14 @@ static const int apple_charger_type[4] = {I_LIMIT_500MA, static int video_power_enabled; +#define NON_STD_CHARGER_REDETECT_DELAY (4 * SECOND) +static enum { + NO_REDETECT, + REDETECT_SCHEDULED, + REDETECTED, +} charger_need_redetect = NO_REDETECT; +static timestamp_t charger_redetection_time; + static int get_video_power(void) { return video_power_enabled; @@ -566,6 +576,19 @@ static void usb_device_change(int dev_type) if (dev_type != current_dev_type) { usb_log_dev_type(dev_type); keyboard_send_battery_key(); + if ((dev_type & TSU6721_TYPE_NON_STD_CHG || + dev_type == TSU6721_TYPE_VBUS_DEBOUNCED) && + charger_need_redetect == NO_REDETECT) { + /* Schedule redetection */ + charger_need_redetect = REDETECT_SCHEDULED; + charger_redetection_time = get_time(); + charger_redetection_time.val += + NON_STD_CHARGER_REDETECT_DELAY; + } else if (dev_type != TSU6721_TYPE_VBUS_DEBOUNCED && + !(dev_type & TSU6721_TYPE_NON_STD_CHG)) { + /* Not non-std charger. Disarm redetection timer. */ + charger_need_redetect = NO_REDETECT; + } current_dev_type = dev_type; } @@ -619,13 +642,24 @@ void extpower_charge_update(int force_update) restore_id_mux = 0; } - if (pending_tsu6721_reset) { + if (pending_adc_watchdog_disable) { current_watchdog = ADC_WATCH_NONE; adc_disable_watchdog(); + pending_adc_watchdog_disable = 0; + } + + if (pending_tsu6721_reset) { tsu6721_reset(); force_update = 1; pending_tsu6721_reset = 0; - } else + } + + if (pending_dev_type_update) { + force_update = 1; + pending_dev_type_update = 0; + } + + if (!force_update) int_val = tsu6721_get_interrupts(); if (int_val & TSU6721_INT_DETACH) @@ -675,6 +709,7 @@ static void adc_watchdog_interrupt(void) /* Fall through */ case ADC_WATCH_TOAD: pending_tsu6721_reset = 1; + pending_adc_watchdog_disable = 1; task_disable_irq(STM32_IRQ_ADC_1); task_wake(TASK_ID_CHARGER); break; @@ -786,6 +821,28 @@ static void usb_monitor_cable_det(void) } DECLARE_HOOK(HOOK_SECOND, usb_monitor_cable_det, HOOK_PRIO_DEFAULT); +static void usb_charger_redetect(void) +{ + if (charger_need_redetect != REDETECT_SCHEDULED) + return; + + if (timestamp_expired(charger_redetection_time, NULL)) { + CPRINTF("[%T USB Redetecting]\n"); + /* + * TSU6721 doesn't update device type if power or ID pin + * is present. Therefore, if the device type is the same, + * we need to reset TSU6721 to force a redetection. + */ + if (tsu6721_get_device_type() == current_dev_type) + pending_tsu6721_reset = 1; + else + pending_dev_type_update = 1; + charger_need_redetect = REDETECTED; + task_wake(TASK_ID_CHARGER); + } +} +DECLARE_HOOK(HOOK_SECOND, usb_charger_redetect, HOOK_PRIO_DEFAULT); + /*****************************************************************************/ /* * Console commands for debugging. |