diff options
Diffstat (limited to 'board')
-rw-r--r-- | board/samus_pd/usb_pd_policy.c | 53 | ||||
-rw-r--r-- | board/zinger/board.c | 36 | ||||
-rw-r--r-- | board/zinger/board.h | 54 | ||||
-rw-r--r-- | board/zinger/hardware.c | 6 | ||||
-rw-r--r-- | board/zinger/usb_pd_policy.c | 104 |
5 files changed, 208 insertions, 45 deletions
diff --git a/board/samus_pd/usb_pd_policy.c b/board/samus_pd/usb_pd_policy.c index 2004f6c53f..036653af9a 100644 --- a/board/samus_pd/usb_pd_policy.c +++ b/board/samus_pd/usb_pd_policy.c @@ -257,20 +257,19 @@ static int pd_custom_vdm(int port, int cnt, uint32_t *payload, break; case VDO_CMD_READ_INFO: case VDO_CMD_SEND_INFO: - /* if last word is present, it contains lots of info */ + /* copy hash */ if (cnt == 7) { - /* send host event */ - pd_send_host_event(PD_EVENT_UPDATE_DEVICE); - dev_id = VDO_INFO_HW_DEV_ID(payload[6]); + pd_dev_store_rw_hash(port, dev_id, payload + 1); + + pd_send_host_event(PD_EVENT_UPDATE_DEVICE); CPRINTF("Dev:0x%04x SW:%d RW:%d\n", dev_id, VDO_INFO_SW_DBG_VER(payload[6]), VDO_INFO_IS_RW(payload[6])); - } - /* copy hash */ - if (cnt >= 6) + } else if (cnt == 6) { + /* really old devices don't have last byte */ pd_dev_store_rw_hash(port, dev_id, payload + 1); - + } break; case VDO_CMD_CURRENT: CPRINTF("Current: %dmA\n", payload[1]); @@ -383,6 +382,36 @@ static void svdm_exit_dp_mode(int port) gpio_set_level(PORT_TO_HPD(port), 0); } +static int svdm_enter_gfu_mode(int port, uint32_t mode_caps) +{ + /* Always enter GFU mode */ + return 0; +} + +static void svdm_exit_gfu_mode(int port) +{ +} + +static int svdm_gfu_status(int port, uint32_t *payload) +{ + /* + * This is called after enter mode is successful, send unstructured + * VDM to read info. + */ + pd_send_vdm(port, USB_VID_GOOGLE, VDO_CMD_READ_INFO, NULL, 0); + return 0; +} + +static int svdm_gfu_config(int port, uint32_t *payload) +{ + return 0; +} + +static int svdm_gfu_attention(int port, uint32_t *payload) +{ + return 0; +} + const struct svdm_amode_fx supported_modes[] = { { .svid = USB_SID_DISPLAYPORT, @@ -392,5 +421,13 @@ const struct svdm_amode_fx supported_modes[] = { .attention = &svdm_dp_attention, .exit = &svdm_exit_dp_mode, }, + { + .svid = USB_VID_GOOGLE, + .enter = &svdm_enter_gfu_mode, + .status = &svdm_gfu_status, + .config = &svdm_gfu_config, + .attention = &svdm_gfu_attention, + .exit = &svdm_exit_gfu_mode, + } }; const int supported_modes_cnt = ARRAY_SIZE(supported_modes); diff --git a/board/zinger/board.c b/board/zinger/board.c index 23776e084b..5dcbef04fb 100644 --- a/board/zinger/board.c +++ b/board/zinger/board.c @@ -12,6 +12,7 @@ #include "task.h" #include "usb_pd.h" #include "util.h" +#include "version.h" /* Insert the RSA public key definition */ const struct rsa_public_key pkey __attribute__((section(".rsa_pubkey"))) = @@ -22,6 +23,10 @@ static const void *rw_sig = (void *)CONFIG_FLASH_BASE + CONFIG_FW_RW_OFF /* Large 768-Byte buffer for RSA computation : could be re-use afterwards... */ static uint32_t rsa_workbuf[3 * RSANUMWORDS]; +static uint8_t *rw_hash; +static uint8_t rw_flash_changed; +static uint32_t info_data[6]; + extern void pd_rx_handler(void); /* RW firmware reset vector */ @@ -55,14 +60,12 @@ int is_ro_mode(void) static int check_rw_valid(void) { int good; - uint8_t *hash; /* Check if we have a RW firmware flashed */ if (*rw_rst == 0xffffffff) return 0; - hash = flash_hash_rw(); - good = rsa_verify(&pkey, (void *)rw_sig, (void *)hash, rsa_workbuf); + good = rsa_verify(&pkey, (void *)rw_sig, (void *)rw_hash, rsa_workbuf); if (!good) { debug_printf("RSA verify FAILED\n"); return 0; @@ -71,6 +74,30 @@ static int check_rw_valid(void) return 1; } +uint32_t *board_get_info(void) +{ + if (rw_flash_changed) { + /* re-calculate RW hash */ + rw_hash = flash_hash_rw(); + rw_flash_changed = 0; + } + + /* copy first 20 bytes of RW hash */ + memcpy(info_data, rw_hash, 5 * sizeof(uint32_t)); + + /* copy other info into data msg */ + info_data[5] = VDO_INFO(CONFIG_USB_PD_HW_DEV_ID_BOARD_MAJOR, + CONFIG_USB_PD_HW_DEV_ID_BOARD_MINOR, + ver_get_numcommits(), !is_ro_mode()); + + return info_data; +} + +void board_rw_contents_change(void) +{ + rw_flash_changed = 1; +} + extern void pd_task(void); int main(void) @@ -79,6 +106,9 @@ int main(void) debug_printf("Power supply started ... %s\n", is_ro_mode() ? "RO" : "RW"); + /* calculate hash of RW */ + rw_hash = flash_hash_rw(); + /* Verify RW firmware and use it if valid */ if (is_ro_mode() && check_rw_valid()) jump_to_rw(); diff --git a/board/zinger/board.h b/board/zinger/board.h index e1bef03452..c599e4bd17 100644 --- a/board/zinger/board.h +++ b/board/zinger/board.h @@ -17,21 +17,17 @@ /* the UART console is on USART1 (PA9/PA10) */ #define CONFIG_UART_CONSOLE 1 +#ifdef BOARD_ZINGER +#define CONFIG_USB_PD_HW_DEV_ID_BOARD_MAJOR USB_PD_HW_DEV_ID_ZINGER +#define CONFIG_USB_PD_HW_DEV_ID_BOARD_MINOR 0 +#elif defined(BOARD_MINIMUFFIN) +#define CONFIG_USB_PD_HW_DEV_ID_BOARD_MAJOR USB_PD_HW_DEV_ID_MINIMUFFIN +#define CONFIG_USB_PD_HW_DEV_ID_BOARD_MINOR 0 +#else +#error "Board does not have a USB-PD HW Device ID" +#endif + /* Optional features */ -#define CONFIG_USB_POWER_DELIVERY -#define CONFIG_USB_PD_CUSTOM_VDM -#undef CONFIG_USB_PD_DUAL_ROLE -#undef CONFIG_USB_PD_INTERNAL_COMP -#undef CONFIG_USB_PD_RX_COMP_IRQ -#define CONFIG_USB_PD_SIMPLE_DFP -#define CONFIG_HW_CRC -#define CONFIG_RSA -#define CONFIG_SHA256 -#undef CONFIG_WATCHDOG_HELP -#undef CONFIG_WATCHDOG_PERIOD_MS -#define CONFIG_WATCHDOG_PERIOD_MS 2300 -#undef CONFIG_LID_SWITCH -#undef CONFIG_TASK_PROFILING #undef CONFIG_COMMON_GPIO #undef CONFIG_COMMON_PANIC_OUTPUT #undef CONFIG_COMMON_RUNTIME @@ -44,12 +40,38 @@ #undef CONFIG_FMAP #define CONFIG_HIBERNATE #define CONFIG_HIBERNATE_WAKEUP_PINS STM32_PWR_CSR_EWUP1 +#define CONFIG_HW_CRC +#undef CONFIG_LID_SWITCH +#define CONFIG_RSA +#define CONFIG_SHA256 +#undef CONFIG_TASK_PROFILING +#define CONFIG_USB_POWER_DELIVERY +#define CONFIG_USB_PD_ALT_MODE +#define CONFIG_USB_PD_CUSTOM_VDM +#undef CONFIG_USB_PD_DUAL_ROLE +#undef CONFIG_USB_PD_INTERNAL_COMP +#undef CONFIG_USB_PD_RX_COMP_IRQ +#define CONFIG_USB_PD_SIMPLE_DFP +#define CONFIG_USB_PD_IDENTITY_HW_VERS CONFIG_USB_PD_HW_DEV_ID_BOARD_MINOR +#define CONFIG_USB_PD_IDENTITY_SW_VERS 0 +#undef CONFIG_WATCHDOG_HELP +#undef CONFIG_WATCHDOG_PERIOD_MS +#define CONFIG_WATCHDOG_PERIOD_MS 2300 /* debug printf flash footprinf is about 1400 bytes */ #define CONFIG_DEBUG_PRINTF #define UARTN CONFIG_UART_CONSOLE #define UARTN_BASE STM32_USART_BASE(CONFIG_UART_CONSOLE) +/* USB configuration */ +#if defined(BOARD_ZINGER) +#define CONFIG_USB_PID 0x5012 +#define CONFIG_USB_BCD_DEV 0x0001 /* v 0.01 */ +#elif defined(BOARD_MINIMUFFIN) +#define CONFIG_USB_PID 0x5013 +#define CONFIG_USB_BCD_DEV 0x0001 /* v 0.01 */ +#endif + #ifndef __ASSEMBLER__ #include "common.h" @@ -91,6 +113,10 @@ void __enter_hibernate(uint32_t seconds, uint32_t microseconds); /* Reboot the CPU */ void cpu_reset(void); +/* Board version information functions */ +uint32_t *board_get_info(void); +void board_rw_contents_change(void); + #endif /* !__ASSEMBLER__ */ #endif /* __BOARD_H */ diff --git a/board/zinger/hardware.c b/board/zinger/hardware.c index 1fca39a61e..59e2f8b24b 100644 --- a/board/zinger/hardware.c +++ b/board/zinger/hardware.c @@ -307,6 +307,9 @@ int flash_write_rw(int offset, int size, const char *data) int res = EC_SUCCESS; int i; + /* notify board of a RW flash contents change */ + board_rw_contents_change(); + if ((uint32_t)address > CONFIG_FLASH_BASE + CONFIG_FLASH_SIZE) return EC_ERROR_INVAL; @@ -358,6 +361,9 @@ int flash_erase_rw(void) int offset = CONFIG_FW_RW_OFF; int size = CONFIG_FW_RW_SIZE; + /* notify board of a RW flash contents change */ + board_rw_contents_change(); + /* unlock CR if needed */ if (STM32_FLASH_CR & CR_LOCK) { STM32_FLASH_KEYR = KEY1; diff --git a/board/zinger/usb_pd_policy.c b/board/zinger/usb_pd_policy.c index d2d0fbcb8a..0f6bcdfccd 100644 --- a/board/zinger/usb_pd_policy.c +++ b/board/zinger/usb_pd_policy.c @@ -395,35 +395,99 @@ void pd_adc_interrupt(void) DECLARE_IRQ(STM32_IRQ_ADC_COMP, pd_adc_interrupt, 1); /* ----------------- Vendor Defined Messages ------------------ */ -static uint32_t info_data[6]; -uint32_t *pd_get_info(void) +const uint32_t vdo_idh = VDO_IDH(0, /* data caps as USB host */ + 0, /* data caps as USB device */ + IDH_PTYPE_AMA, /* Alternate mode */ + 1, /* supports alt modes */ + USB_VID_GOOGLE); + +const uint32_t vdo_product = VDO_PRODUCT(CONFIG_USB_PID, CONFIG_USB_BCD_DEV); + +const uint32_t vdo_ama = VDO_AMA(CONFIG_USB_PD_IDENTITY_HW_VERS, + CONFIG_USB_PD_IDENTITY_SW_VERS, + 0, 0, 0, 0, /* SS[TR][12] */ + 0, /* Vconn power */ + 0, /* Vconn power required */ + 0, /* Vbus power required */ + AMA_USBSS_BBONLY /* USB SS support */); + +/* When set true, we are in GFU mode */ +static int gfu_mode; + +static int svdm_response_identity(int port, uint32_t *payload) { - void *hash; - - /* calculate RW hash */ - hash = flash_hash_rw(); - /* copy first 20 bytes of RW hash */ - memcpy(info_data, hash, 5 * sizeof(uint32_t)); - /* copy other info into data msg */ -#ifdef BOARD_ZINGER - info_data[5] = VDO_INFO(USB_PD_HW_DEV_ID_ZINGER, 1, - ver_get_numcommits(), !is_ro_mode()); -#elif defined(BOARD_MINIMUFFIN) - info_data[5] = VDO_INFO(USB_PD_HW_DEV_ID_MINIMUFFIN, 0, - ver_get_numcommits(), !is_ro_mode()); -#else -#error "Board does not have a USB-PD HW Device ID" -#endif + payload[VDO_I(IDH)] = vdo_idh; + payload[VDO_I(CSTAT)] = VDO_CSTAT(0); + payload[VDO_I(PRODUCT)] = vdo_product; + payload[VDO_I(AMA)] = vdo_ama; + return VDO_I(AMA) + 1; +} + +static int svdm_response_svids(int port, uint32_t *payload) +{ + payload[1] = VDO_SVID(USB_VID_GOOGLE, 0); + return 2; +} + +/* Will only ever be a single mode for this device */ +#define MODE_CNT 1 +#define OPOS 1 + +const uint32_t vdo_dp_mode[MODE_CNT] = { + VDO_MODE_GOOGLE(MODE_GOOGLE_FU) +}; + +static int svdm_response_modes(int port, uint32_t *payload) +{ + if (PD_VDO_VID(payload[0]) != USB_VID_GOOGLE) + return 0; /* nak */ + + memcpy(payload + 1, vdo_dp_mode, sizeof(vdo_dp_mode)); + return MODE_CNT + 1; +} + +static int svdm_enter_mode(int port, uint32_t *payload) +{ + /* SID & mode request is valid */ + if ((PD_VDO_VID(payload[0]) != USB_VID_GOOGLE) || + (PD_VDO_OPOS(payload[0]) != OPOS)) + return 0; /* will generate NAK */ + + gfu_mode = 1; + debug_printf("GFU\n"); + return 1; +} - return info_data; +static int svdm_exit_mode(int port, uint32_t *payload) +{ + gfu_mode = 0; + return 1; /* Must return ACK */ } +static struct amode_fx dp_fx = { + .status = NULL, + .config = NULL, +}; + +const struct svdm_response svdm_rsp = { + .identity = &svdm_response_identity, + .svids = &svdm_response_svids, + .modes = &svdm_response_modes, + .enter_mode = &svdm_enter_mode, + .amode = &dp_fx, + .exit_mode = &svdm_exit_mode, +}; + static int pd_custom_vdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload) { static int flash_offset; int cmd = PD_VDO_CMD(payload[0]); int rsize = 1; + + if (PD_VDO_VID(payload[0]) != USB_VID_GOOGLE || !gfu_mode) + return 0; + debug_printf("%T] VDM/%d [%d] %08x\n", cnt, cmd, payload[0]); *rpayload = payload; @@ -439,7 +503,7 @@ static int pd_custom_vdm(int port, int cnt, uint32_t *payload, break; case VDO_CMD_READ_INFO: /* copy info into response */ - memcpy(payload + 1, pd_get_info(), 24); + memcpy(payload + 1, board_get_info(), 24); rsize = 7; break; case VDO_CMD_FLASH_ERASE: |