summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVic Yang <victoryang@chromium.org>2013-06-17 11:06:55 +0800
committerChromeBot <chrome-bot@google.com>2013-06-17 10:31:50 -0700
commitb93658ba02cf381e2a0e20c4d7128814d685e502 (patch)
treecf2627ae7eca5340ac7a2f1ac9505775736d2b6b
parent37b5adb123f52b721eda63b36ad6743281fd46df (diff)
downloadchrome-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.c61
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.