diff options
author | Vic Yang <victoryang@chromium.org> | 2013-03-08 09:22:54 +0800 |
---|---|---|
committer | ChromeBot <chrome-bot@google.com> | 2013-03-08 00:07:07 -0800 |
commit | a44e0d91c8cf30c56d06ed8378b5f49760876d4a (patch) | |
tree | b70a7431bb187b39fb0b5d81dd171a09f9ee3c09 | |
parent | f568b823219183af836567cc44912199ec24b0c2 (diff) | |
download | chrome-ec-a44e0d91c8cf30c56d06ed8378b5f49760876d4a.tar.gz |
spring: support new ID detection circuit
This enables the EC to switch the signals to ANX7808 properly.
BUG=chrome-os-partner:18165
TEST=Manual on reworked Spring board
BRANCH=none
Change-Id: Ib3ff57e17afab9ba8fc78fdb037e65aae844f38b
Signed-off-by: Vic Yang <victoryang@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/44897
Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
-rw-r--r-- | board/spring/usb_charging.c | 88 | ||||
-rw-r--r-- | include/pmu_tpschrome.h | 1 |
2 files changed, 78 insertions, 11 deletions
diff --git a/board/spring/usb_charging.c b/board/spring/usb_charging.c index 1c90de6455..0279a7a7c3 100644 --- a/board/spring/usb_charging.c +++ b/board/spring/usb_charging.c @@ -27,8 +27,11 @@ #define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ## args) /* Devices that need VBUS power */ -#define POWERED_DEVICE_TYPE (TSU6721_TYPE_OTG | \ - TSU6721_TYPE_JIG_UART_ON) +#define POWERED_5000_DEVICE_TYPE (TSU6721_TYPE_OTG) +#define POWERED_3300_DEVICE_TYPE (TSU6721_TYPE_JIG_UART_ON) + +/* Voltage threshold of D+ for video */ +#define VIDEO_ID_THRESHOLD 1335 /* PWM controlled current limit */ #define I_LIMIT_500MA 90 @@ -50,6 +53,11 @@ #define PWM_CTRL_VBUS_LOW 4500 #define PWM_CTRL_VBUS_HIGH 4700 /* Must be higher than 4.5V */ +/* Delay for signals to settle */ +#define DELAY_POWER_MS 20 +#define DELAY_USB_DP_DN_MS 20 +#define DELAY_ID_MUX_MS 30 + static int current_dev_type = TSU6721_TYPE_NONE; static int nominal_pwm_duty; static int current_pwm_duty; @@ -163,7 +171,7 @@ static int board_apple_charger_current(void) tsu6721_disable_interrupts(); tsu6721_mux(TSU6721_MUX_USB); /* Wait 20ms for signal to stablize */ - msleep(20); + msleep(DELAY_USB_DP_DN_MS); adc_read_all_channels(data); vp = data[ADC_CH_USB_DP_SNS]; vn = data[ADC_CH_USB_DN_SNS]; @@ -177,6 +185,26 @@ static int board_apple_charger_current(void) return apple_charger_type[type]; } +static int board_probe_video(int device_type) +{ + tsu6721_disable_interrupts(); + gpio_set_level(GPIO_ID_MUX, 0); + msleep(DELAY_ID_MUX_MS); + + if (adc_read_channel(ADC_CH_USB_DP_SNS) > VIDEO_ID_THRESHOLD) { + /* Actually an USB host */ + gpio_set_level(GPIO_ID_MUX, 1); + msleep(DELAY_ID_MUX_MS); + tsu6721_enable_interrupts(); + return device_type; + } else { + /* Not USB host but video */ + device_type = (device_type & ~TSU6721_TYPE_USB_HOST) | + TSU6721_TYPE_JIG_UART_ON; + return device_type; + } +} + void board_pwm_duty_cycle(int percent) { if (current_ilim_config != ILIM_CONFIG_PWM) @@ -270,6 +298,14 @@ void usb_charge_interrupt(enum gpio_signal signal) task_wake(TASK_ID_PMU_TPS65090_CHARGER); } +static int usb_has_power_input(int dev_type) +{ + if (dev_type & TSU6721_TYPE_JIG_UART_ON) + return 1; + return (dev_type & TSU6721_TYPE_VBUS_DEBOUNCED) && + !(dev_type & POWERED_5000_DEVICE_TYPE); +} + static void usb_device_change(int dev_type) { int need_boost; @@ -281,6 +317,13 @@ static void usb_device_change(int dev_type) over_current_pwm_duty = 0; /* + * Video output is recognized incorrectly as USB host. When we see + * USB host, probe for video output. + */ + if (dev_type & TSU6721_TYPE_USB_HOST) + dev_type = board_probe_video(dev_type); + + /* * When a power source is removed, record time, power source type, * and PWM duty cycle. Then when we see a power source, compare type * and calculate time difference to determine if we have just @@ -309,24 +352,28 @@ static void usb_device_change(int dev_type) } /* - * Supply VBUS if needed. If we toggle power output, wait for a moment, - * and then update device type. To avoid race condition, check if power - * requirement changes during this time. + * Supply 5V VBUS if needed. If we toggle power output, wait for a + * moment, and then update device type. To avoid race condition, check + * if power requirement changes during this time. */ do { if (retry_limit-- <= 0) break; - need_boost = !(dev_type & POWERED_DEVICE_TYPE); + need_boost = !(dev_type & POWERED_5000_DEVICE_TYPE); if (need_boost != gpio_get_level(GPIO_BOOST_EN)) { gpio_set_level(GPIO_BOOST_EN, need_boost); - msleep(20); + msleep(DELAY_POWER_MS); dev_type = tsu6721_get_device_type(); } - } while (need_boost == !!(dev_type & POWERED_DEVICE_TYPE)); + } while (need_boost == !!(dev_type & POWERED_5000_DEVICE_TYPE)); + + /* Supply 3.3V VBUS if needed. */ + if (dev_type & POWERED_3300_DEVICE_TYPE) { + pmu_enable_fet(FET_VIDEO, 1, NULL); + } - if ((dev_type & TSU6721_TYPE_VBUS_DEBOUNCED) && - !(dev_type & POWERED_DEVICE_TYPE)) { + if (usb_has_power_input(dev_type)) { /* Limit USB port current. 500mA for not listed types. */ int current_limit = I_LIMIT_500MA; if (dev_type & TSU6721_TYPE_CHG12) @@ -376,6 +423,25 @@ static void usb_device_change(int dev_type) current_dev_type = dev_type; } +/* + * TODO(victoryang): Get rid of polling loop when ADC watchdog is ready. + * See crosbug.com/p/18171 + */ +static void board_usb_monitor_detach(void) +{ + if (!(current_dev_type & TSU6721_TYPE_JIG_UART_ON)) + return; + + if (adc_read_channel(ADC_CH_USB_DP_SNS) > VIDEO_ID_THRESHOLD) { + pmu_enable_fet(FET_VIDEO, 0, NULL); + gpio_set_level(GPIO_ID_MUX, 1); + msleep(DELAY_ID_MUX_MS); + tsu6721_enable_interrupts(); + usb_device_change(TSU6721_TYPE_NONE); + } +} +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(); diff --git a/include/pmu_tpschrome.h b/include/pmu_tpschrome.h index 54da1bca57..9b9c0ff0d5 100644 --- a/include/pmu_tpschrome.h +++ b/include/pmu_tpschrome.h @@ -69,6 +69,7 @@ enum FASTCHARGE_TIMEOUT { }; #define FET_BACKLIGHT 1 +#define FET_VIDEO 2 #define FET_WWAN 3 #define FET_CAMERA 5 #define FET_LCD_PANEL 6 |