From 229bac23f15a7636ccb25b6861655e3e0923a0e9 Mon Sep 17 00:00:00 2001 From: Rong Chang Date: Wed, 19 Aug 2015 23:34:29 +0800 Subject: 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 Reviewed-on: https://chromium-review.googlesource.com/294442 --- board/oak/board.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++ board/oak/ec.tasklist | 8 +++++ board/oak/gpio.inc | 12 +++++++ board/oak/usb_pd_policy.c | 4 +++ common/usb_charger.c | 15 ++++++--- include/usb_charge.h | 1 + 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. -- cgit v1.2.1