summaryrefslogtreecommitdiff
path: root/board
diff options
context:
space:
mode:
Diffstat (limited to 'board')
-rw-r--r--board/samus_pd/usb_pd_policy.c53
-rw-r--r--board/zinger/board.c36
-rw-r--r--board/zinger/board.h54
-rw-r--r--board/zinger/hardware.c6
-rw-r--r--board/zinger/usb_pd_policy.c104
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: