summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRong Chang <rongchang@chromium.org>2015-08-19 23:34:29 +0800
committerchrome-bot <chrome-bot@chromium.org>2015-09-03 04:24:34 -0700
commit229bac23f15a7636ccb25b6861655e3e0923a0e9 (patch)
tree9b56587f1ec55ed77da369c1d9122b5ca70ec7d0
parenta572c882e46b11ec2cdcc2f5d84ce1f47ecc14d2 (diff)
downloadchrome-ec-229bac23f15a7636ccb25b6861655e3e0923a0e9.tar.gz
oak: handle USB BC 1.2 status change
Before oak rev4, BC 1.2 status change was polled on VBUS change. The designed is changed to use a single interrupt pin for both ports. BRANCH=none BUG=chrome-os-partner:42610 TEST=manual make EXTRA_CFLAGS=-DBOARD_REV=3 BOARD=oak -j emerge-oak chromeos-ec load on oak rev3 and check BC 1.2 charging current Change-Id: I9e6cdbb83468b5e4086cc86caadf7f2e3cbe6e48 Signed-off-by: Rong Chang <rongchang@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/294442
-rw-r--r--board/oak/board.c83
-rw-r--r--board/oak/ec.tasklist8
-rw-r--r--board/oak/gpio.inc12
-rw-r--r--board/oak/usb_pd_policy.c4
-rw-r--r--common/usb_charger.c15
-rw-r--r--include/usb_charge.h1
6 files changed, 119 insertions, 4 deletions
diff --git a/board/oak/board.c b/board/oak/board.c
index b77e582930..6759383f90 100644
--- a/board/oak/board.c
+++ b/board/oak/board.c
@@ -65,6 +65,14 @@ void pd_mcu_interrupt(enum gpio_signal signal)
#endif
}
+#if BOARD_REV >= OAK_REV4
+void usb_evt(enum gpio_signal signal)
+{
+ task_set_event(TASK_ID_USB_CHG_P0, USB_CHG_EVENT_INTR, 0);
+ task_set_event(TASK_ID_USB_CHG_P1, USB_CHG_EVENT_INTR, 0);
+}
+#endif /* BOARD_REV >= OAK_REV4 */
+
#include "gpio_list.h"
/* power signal list. Must match order of enum power_signal. */
@@ -195,6 +203,20 @@ static void board_init(void)
gpio_set_level(GPIO_SYSTEM_POWER_H, 1);
/* Enable PD MCU interrupt */
gpio_enable_interrupt(GPIO_PD_MCU_INT);
+
+#if BOARD_REV >= OAK_REV4
+ /* Enable BC 1.2 interrupt */
+ gpio_enable_interrupt(GPIO_USB_BC12_INT);
+#endif /* BOARD_REV >= OAK_REV4 */
+
+#if BOARD_REV >= OAK_REV3
+ /* Update VBUS supplier */
+ usb_charger_vbus_change(0, !gpio_get_level(GPIO_USB_C0_VBUS_WAKE_L));
+ usb_charger_vbus_change(1, !gpio_get_level(GPIO_USB_C1_VBUS_WAKE_L));
+#else
+ usb_charger_vbus_change(0, 0);
+ usb_charger_vbus_change(1, 0);
+#endif
}
DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT);
@@ -382,3 +404,64 @@ static int host_event_status_host_cmd(struct host_cmd_handler_args *args)
DECLARE_HOST_COMMAND(EC_CMD_PD_HOST_EVENT_STATUS, host_event_status_host_cmd,
EC_VER_MASK(0));
+#if BOARD_REV < OAK_REV4
+/**
+ * Check VBUS state and trigger USB BC1.2 charger.
+ */
+void vbus_task(void)
+{
+ struct {
+ uint8_t interrupt;
+ uint8_t device_type;
+ uint8_t charger_status;
+ uint8_t vbus;
+ } bc12[CONFIG_USB_PD_PORT_COUNT];
+ uint8_t port, vbus, reg, wake;
+
+ while (1) {
+ for (port = 0; port < CONFIG_USB_PD_PORT_COUNT; port++) {
+#if BOARD_REV == OAK_REV3
+ vbus = !gpio_get_level(port ? GPIO_USB_C1_VBUS_WAKE_L :
+ GPIO_USB_C0_VBUS_WAKE_L);
+#else
+ vbus = tcpm_get_vbus_level(port);
+#endif
+ /* check if VBUS changed */
+ if (((bc12[port].vbus >> port) & 1) == vbus)
+ continue;
+ /* wait 1.2 seconds and check BC 1.2 status */
+ msleep(1200);
+
+ if (vbus)
+ bc12[port].vbus |= 1 << port;
+ else
+ bc12[port].vbus &= ~(1 << port);
+
+ wake = 0;
+ reg = pi3usb9281_get_interrupts(port);
+ if (reg != bc12[port].interrupt) {
+ bc12[port].interrupt = reg;
+ wake++;
+ }
+
+ reg = pi3usb9281_get_device_type(port);
+ if (reg != bc12[port].device_type) {
+ bc12[port].device_type = reg;
+ wake++;
+ }
+
+ reg = pi3usb9281_get_charger_status(port);
+ if (reg != bc12[port].charger_status) {
+ bc12[port].charger_status = reg;
+ wake++;
+ }
+
+ if (wake)
+ task_set_event(port ? TASK_ID_USB_CHG_P1 :
+ TASK_ID_USB_CHG_P0,
+ USB_CHG_EVENT_BC12, 0);
+ }
+ task_wait_event(-1);
+ }
+}
+#endif /* BOARD_REV < OAK_REV4 */
diff --git a/board/oak/ec.tasklist b/board/oak/ec.tasklist
index 30b716c885..b31d3ab71b 100644
--- a/board/oak/ec.tasklist
+++ b/board/oak/ec.tasklist
@@ -16,8 +16,16 @@
* 'd' in an opaque parameter passed to the routine at startup
* 's' is the stack size in bytes; must be a multiple of 8
*/
+
+#if BOARD_REV < OAK_REV4
+#define TASK_VBUS(n, r, d, s) TASK_ALWAYS(n, r, d, s)
+#else
+#define TASK_VBUS(n, r, d, s)
+#endif
+
#define CONFIG_TASK_LIST \
TASK_ALWAYS(HOOKS, hook_task, NULL, LARGER_TASK_STACK_SIZE) \
+ TASK_VBUS(VBUS, vbus_task, NULL, TASK_STACK_SIZE) \
TASK_ALWAYS(USB_CHG_P0, usb_charger_task, NULL, TASK_STACK_SIZE) \
TASK_ALWAYS(USB_CHG_P1, usb_charger_task, NULL, TASK_STACK_SIZE) \
TASK_ALWAYS(CHARGER, charger_task, NULL, LARGER_TASK_STACK_SIZE) \
diff --git a/board/oak/gpio.inc b/board/oak/gpio.inc
index 013cddea0e..18341f3b91 100644
--- a/board/oak/gpio.inc
+++ b/board/oak/gpio.inc
@@ -24,6 +24,18 @@ GPIO_INT(KB_IN05, PIN(C, 14), GPIO_KB_INPUT, keyboard_raw_gpio_interrupt)
GPIO_INT(KB_IN06, PIN(C, 15), GPIO_KB_INPUT, keyboard_raw_gpio_interrupt)
GPIO_INT(KB_IN07, PIN(D, 2), GPIO_KB_INPUT, keyboard_raw_gpio_interrupt)
+/* Board specific interrupt and input */
+#if BOARD_REV == OAK_REV2
+GPIO(USB_VBUS_WAKE_L, PIN(E, 1), GPIO_INPUT)
+#elif BOARD_REV == OAK_REV3
+GPIO(USB_C0_VBUS_WAKE_L, PIN(E, 1), GPIO_INPUT)
+GPIO(USB_C1_VBUS_WAKE_L, PIN(F, 2), GPIO_INPUT)
+#elif BOARD_REV >= OAK_REV4
+GPIO_INT(USB_BC12_INT, PIN(E, 1), GPIO_INT_FALLING, usb_evt)
+GPIO(USB_C0_VBUS_WAKE_L, PIN(D, 12), GPIO_INPUT)
+GPIO(USB_C1_VBUS_WAKE_L, PIN(F, 2), GPIO_INPUT)
+#endif
+
/* Inputs without interrupt handlers */
GPIO(5V_POWER_GOOD, PIN(A, 1), GPIO_INPUT)
GPIO(EC_WAKE, PIN(A, 0), GPIO_INPUT|GPIO_PULL_DOWN)
diff --git a/board/oak/usb_pd_policy.c b/board/oak/usb_pd_policy.c
index 62c3444285..9849d41069 100644
--- a/board/oak/usb_pd_policy.c
+++ b/board/oak/usb_pd_policy.c
@@ -128,6 +128,10 @@ void typec_set_input_current_limit(int port, uint32_t max_ma,
int pd_board_checks(void)
{
+#if BOARD_REV <= OAK_REV3
+ /* wake up VBUS task to check vbus change */
+ task_wake(TASK_ID_VBUS);
+#endif
return EC_SUCCESS;
}
diff --git a/common/usb_charger.c b/common/usb_charger.c
index 99263fafc9..0474bc18b8 100644
--- a/common/usb_charger.c
+++ b/common/usb_charger.c
@@ -100,9 +100,6 @@ static void usb_charger_bc12_detect(int port)
charge.voltage = USB_CHARGER_VOLTAGE_MV;
- /* Read interrupt register to clear on chip */
- pi3usb9281_get_interrupts(port);
-
if (usb_charger_port_is_sourcing_vbus(port)) {
/* If we're sourcing VBUS then we're not charging */
device_type = charger_status = 0;
@@ -203,7 +200,9 @@ static void usb_charger_bc12_detect(int port)
void usb_charger_task(void)
{
+ const int attach_mask = PI3USB9281_INT_ATTACH | PI3USB9281_INT_DETACH;
int port = (task_get_current() == TASK_ID_USB_CHG_P0 ? 0 : 1);
+ int interrupt;
uint32_t evt;
/* Initialize chip and enable interrupts */
@@ -214,8 +213,16 @@ void usb_charger_task(void)
while (1) {
/* Wait for interrupt */
evt = task_wait_event(-1);
+ /* Read interrupt register to clear on chip */
+ interrupt = pi3usb9281_get_interrupts(port);
+
+ /* Interrupt from the Pericom chip, determine interrupt type */
+ if (evt & USB_CHG_EVENT_INTR) {
+ if (interrupt & attach_mask)
+ usb_charger_bc12_detect(port);
+ }
- /* Interrupt from the Pericom chip, determine charger type */
+ /* Ignore interrupt status and determine charger type */
if (evt & USB_CHG_EVENT_BC12)
usb_charger_bc12_detect(port);
diff --git a/include/usb_charge.h b/include/usb_charge.h
index e7d620bd81..0714fc3a44 100644
--- a/include/usb_charge.h
+++ b/include/usb_charge.h
@@ -50,6 +50,7 @@ int usb_charge_ports_enabled(void);
/* Events handled by the USB_CHG task */
#define USB_CHG_EVENT_BC12 TASK_EVENT_CUSTOM(1)
#define USB_CHG_EVENT_VBUS TASK_EVENT_CUSTOM(2)
+#define USB_CHG_EVENT_INTR TASK_EVENT_CUSTOM(3)
/**
* Returns true if the passed port is a power source.