diff --git a/board/dingdong/board.h b/board/dingdong/board.h index c814b6f48d..814df199bc 100644 --- a/board/dingdong/board.h +++ b/board/dingdong/board.h @@ -21,6 +21,7 @@ #define CONFIG_HW_CRC #define CONFIG_USB #define CONFIG_USB_BOS +#define CONFIG_USB_INHIBIT #define CONFIG_USB_POWER_DELIVERY #define CONFIG_USB_PD_ALT_MODE #define CONFIG_USB_PD_DUAL_ROLE diff --git a/board/dingdong/usb_pd_policy.c b/board/dingdong/usb_pd_policy.c index 2e18792733..5894427ca8 100644 --- a/board/dingdong/usb_pd_policy.c +++ b/board/dingdong/usb_pd_policy.c @@ -13,6 +13,7 @@ #include "task.h" #include "timer.h" #include "util.h" +#include "usb.h" #include "usb_pd.h" #include "version.h" @@ -145,10 +146,8 @@ const uint32_t vdo_dp_mode[MODE_CNT] = { static int svdm_response_modes(int port, uint32_t *payload) { - if (PD_VDO_VID(payload[0]) != USB_SID_DISPLAYPORT) { - /* TODO(tbroch) USB billboard enabled here then */ - return 1; /* will generate a NAK */ - } + if (PD_VDO_VID(payload[0]) != USB_SID_DISPLAYPORT) + return 0; /* nak */ memcpy(payload + 1, vdo_dp_mode, sizeof(vdo_dp_mode)); return MODE_CNT + 1; @@ -187,11 +186,12 @@ static int svdm_enter_mode(int port, uint32_t *payload) (PD_VDO_OPOS(payload[0]) != OPOS)) return 0; /* will generate NAK */ + /* TODO(tbroch) Enumerate USB BB here with updated mode choice */ alt_mode = OPOS; return 1; } -int pd_alt_mode(int port) +int pd_alt_mode(void) { return alt_mode; } diff --git a/board/hoho/board.h b/board/hoho/board.h index c341b479fe..d98ba5b135 100644 --- a/board/hoho/board.h +++ b/board/hoho/board.h @@ -29,6 +29,7 @@ #define CONFIG_SPI_CS_GPIO GPIO_PD_MCDP_SPI_CS_L #define CONFIG_USB #define CONFIG_USB_BOS +#define CONFIG_USB_INHIBIT #define CONFIG_USB_POWER_DELIVERY #define CONFIG_USB_PD_ALT_MODE #define CONFIG_USB_PD_DUAL_ROLE diff --git a/board/hoho/usb_pd_policy.c b/board/hoho/usb_pd_policy.c index 4eff69b49e..3da52023c3 100644 --- a/board/hoho/usb_pd_policy.c +++ b/board/hoho/usb_pd_policy.c @@ -12,6 +12,7 @@ #include "registers.h" #include "task.h" #include "timer.h" +#include "usb.h" #include "usb_pd.h" #include "util.h" #include "version.h" @@ -145,10 +146,8 @@ const uint32_t vdo_dp_mode[MODE_CNT] = { static int svdm_response_modes(int port, uint32_t *payload) { - if (PD_VDO_VID(payload[0]) != USB_SID_DISPLAYPORT) { - /* TODO(tbroch) USB billboard enabled here then */ - return 1; /* will generate a NAK */ - } + if (PD_VDO_VID(payload[0]) != USB_SID_DISPLAYPORT) + return 0; /* nak */ memcpy(payload + 1, vdo_dp_mode, sizeof(vdo_dp_mode)); return MODE_CNT + 1; @@ -186,11 +185,12 @@ static int svdm_enter_mode(int port, uint32_t *payload) (PD_VDO_OPOS(payload[0]) != OPOS)) return 0; /* will generate a NAK */ + /* TODO(tbroch) Enumerate USB BB here with updated mode choice */ alt_mode = OPOS; return 1; } -int pd_alt_mode(int port) +int pd_alt_mode(void) { return alt_mode; } diff --git a/chip/stm32/usb.c b/chip/stm32/usb.c index b9f69ec848..409cb4f69d 100644 --- a/chip/stm32/usb.c +++ b/chip/stm32/usb.c @@ -297,20 +297,37 @@ void usb_init(void) /* set interrupts mask : reset/correct tranfer/errors */ STM32_USB_CNTR = 0xe400; - /* set pull-up on DP for FS mode */ -#ifdef CHIP_VARIANT_STM32L15X - STM32_SYSCFG_PMC |= 1; -#elif defined(CHIP_FAMILY_STM32F0) - STM32_USB_BCDR |= 1 << 15 /* DPPU */; -#else - /* hardwired or regular GPIO on other platforms */ +#ifndef CONFIG_USB_INHIBIT + usb_connect(); #endif CPRINTF("USB init done\n"); } -#ifndef CONFIG_USB_INHIBIT DECLARE_HOOK(HOOK_INIT, usb_init, HOOK_PRIO_DEFAULT); + +void usb_disconnect(void) +{ + /* disable pull-up on DP to disconnect */ +#ifdef CHIP_VARIANT_STM32L15X + STM32_SYSCFG_PMC &= ~1; +#elif defined(CHIP_FAMILY_STM32F0) + STM32_USB_BCDR &= ~(1 << 15) /* DPPU */; +#else +#warn "usb disconnect not implemented for this chip family" #endif +} + +void usb_connect(void) +{ + /* enable pull-up on DP to connect */ +#ifdef CHIP_VARIANT_STM32L15X + STM32_SYSCFG_PMC |= 1; +#elif defined(CHIP_FAMILY_STM32F0) + STM32_USB_BCDR |= (1 << 15) /* DPPU */; +#else +#warn "usb connect not implemented for this chip family" +#endif +} void usb_release(void) { diff --git a/common/usb_pd_policy.c b/common/usb_pd_policy.c index f0ae2cffab..87e1062817 100644 --- a/common/usb_pd_policy.c +++ b/common/usb_pd_policy.c @@ -7,11 +7,13 @@ #include "common.h" #include "console.h" #include "gpio.h" +#include "hooks.h" #include "host_command.h" #include "registers.h" #include "task.h" #include "timer.h" #include "util.h" +#include "usb.h" #include "usb_pd.h" #include "usb_pd_config.h" #include "version.h" @@ -382,10 +384,6 @@ int pd_svdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload) return 0; } -int pd_alt_mode(int port) -{ - return 0; -} #endif /* CONFIG_USB_PD_ALT_MODE */ #ifndef CONFIG_USB_PD_CUSTOM_VDM @@ -395,6 +393,18 @@ int pd_vdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload) } #endif /* !CONFIG_USB_PD_CUSTOM_VDM */ +void pd_usb_billboard_deferred(void) +{ +#if defined(CONFIG_USB_PD_ALT_MODE) && !defined(CONFIG_USB_PD_ALT_MODE_DFP) \ + && !defined(CONFIG_USB_PD_SIMPLE_DFP) + + if (!pd_alt_mode()) + usb_connect(); + +#endif +} +DECLARE_DEFERRED(pd_usb_billboard_deferred); + #ifndef CONFIG_USB_PD_ALT_MODE_DFP int pd_exit_mode(int port, uint32_t *payload) { diff --git a/common/usb_pd_protocol.c b/common/usb_pd_protocol.c index c91893c4c5..c44e070043 100644 --- a/common/usb_pd_protocol.c +++ b/common/usb_pd_protocol.c @@ -185,6 +185,9 @@ static const uint8_t dec4b5b[] = { #define PD_T_DRP_SRC (30*MSEC) /* toggle time for source DRP */ #define PD_T_SRC_RECOVER (760*MSEC) /* between 660ms and 1000ms */ +/* from USB Type-C Specification Table 5-1 */ +#define PD_T_AME (1*SECOND) /* timeout from UFP attach to Alt Mode Entry */ + /* Port role at startup */ #ifdef CONFIG_USB_PD_DUAL_ROLE #define PD_ROLE_DEFAULT PD_ROLE_SINK @@ -1464,6 +1467,9 @@ void pd_task(void) #endif set_state(port, PD_STATE_SNK_DISCOVERY); timeout = 10*MSEC; + hook_call_deferred( + pd_usb_billboard_deferred, + PD_T_AME); break; } } @@ -1750,7 +1756,7 @@ static int remote_flashing(int argc, char **argv) void pd_send_hpd(int port, enum hpd_event hpd) { uint32_t data[1]; - int opos = pd_alt_mode(port); + int opos = pd_alt_mode(); if (!opos) return; diff --git a/include/usb.h b/include/usb.h index df6426fc64..bce830ebb3 100644 --- a/include/usb.h +++ b/include/usb.h @@ -296,6 +296,8 @@ extern void (*usb_iface_request[]) (usb_uint *ep0_buf_rx, usb_uint *ep0_buf_tx); /* functions to start/stop USB */ void usb_init(void); +void usb_disconnect(void); +void usb_connect(void); void usb_release(void); #endif /* USB_H */ diff --git a/include/usb_pd.h b/include/usb_pd.h index c13e5e9588..072f070359 100644 --- a/include/usb_pd.h +++ b/include/usb_pd.h @@ -784,10 +784,9 @@ void board_flip_usb_mux(int port); /** * Determine if in alternate mode or not. * - * @param port port number. * @return object position of mode chosen in alternate mode otherwise zero. */ -int pd_alt_mode(int port); +int pd_alt_mode(void); /** * Send hpd over USB PD. @@ -796,6 +795,11 @@ int pd_alt_mode(int port); * @param hpd hotplug detect type. */ void pd_send_hpd(int port, enum hpd_event hpd); + +/** + * Enable USB Billboard Device. + */ +void pd_usb_billboard_deferred(void); /* --- Physical layer functions : chip specific --- */ /* Packet preparation/retrieval */