summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVic Yang <victoryang@chromium.org>2013-03-08 09:22:54 +0800
committerChromeBot <chrome-bot@google.com>2013-03-08 00:07:07 -0800
commita44e0d91c8cf30c56d06ed8378b5f49760876d4a (patch)
treeb70a7431bb187b39fb0b5d81dd171a09f9ee3c09
parentf568b823219183af836567cc44912199ec24b0c2 (diff)
downloadchrome-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.c88
-rw-r--r--include/pmu_tpschrome.h1
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