summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlec Berg <alecaberg@chromium.org>2014-11-13 10:51:49 -0800
committerchrome-internal-fetch <chrome-internal-fetch@google.com>2014-11-15 06:57:32 +0000
commitc44bd8b3a324148a898f865bcce1e6153bf3de8f (patch)
tree34c8beeb0f383ab46872f5160c14f974ac3b828b
parent56bbd902abb2219cb3ae42aa1546d0b6fc3a04a0 (diff)
downloadchrome-ec-stabilize-6480.B.tar.gz
pd: zinger: add firmware update alternate mode to zingerstabilize-6480.B
Add a Google Firmware Update alternate mode to zinger. This mode must be entered in order to allow the unstructured VDMs that we use for sending a new firmware. BUG=chrome-os-partner:33754 BRANCH=samus TEST=load on samus and zinger. see that "GFU" is printed on zinger console to represent that it entered GFU mode. use twinkie to see that samus sent discover identity, discover svids, discover modes, enter mode, and then read info. See on samus pd console that we received result of read info. from samus pd console with zinger attached: > pe 1 dump IDENT: [ID Header] 2c0018d1 :: AMA, VID:18d1 [Cert Stat] 00000000 [2] 50100001 [3] 00000003 [4] 52136b91 [5] 0401137d SVID[0]: 18d1 MODES: [1] 00000000 MODE[1]: svid:18d1 caps:00000000 Also, use a samus with cros_pd_update running in kernel, and see that zinger auto-updates when plugged in. Performed 10 updates with no failures. Change-Id: I8d4d38e4a9f649fe0889f688f262630ef55106ee Signed-off-by: Alec Berg <alecaberg@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/229622 Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
-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
-rw-r--r--common/usb_pd_policy.c8
-rw-r--r--common/usb_pd_protocol.c5
-rw-r--r--include/usb_pd.h16
8 files changed, 226 insertions, 56 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:
diff --git a/common/usb_pd_policy.c b/common/usb_pd_policy.c
index 0ffcd2086e..5bcb58dd71 100644
--- a/common/usb_pd_policy.c
+++ b/common/usb_pd_policy.c
@@ -18,8 +18,13 @@
#include "usb_pd_config.h"
#include "version.h"
+#ifdef CONFIG_COMMON_RUNTIME
#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args)
#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args)
+#else
+#define CPRINTS(format, args...)
+#define CPRINTF(format, args...)
+#endif
#ifdef CONFIG_USB_PD_ALT_MODE
@@ -441,6 +446,9 @@ DECLARE_DEFERRED(pd_usb_billboard_deferred);
#ifndef CONFIG_USB_PD_ALT_MODE_DFP
int pd_exit_mode(int port, uint32_t *payload)
{
+#ifdef CONFIG_USB_PD_ALT_MODE
+ svdm_rsp.exit_mode(port, payload);
+#endif
return 0;
}
#endif /* !CONFIG_USB_PD_ALT_MODE_DFP */
diff --git a/common/usb_pd_protocol.c b/common/usb_pd_protocol.c
index 6c9dc18e04..5382bc24be 100644
--- a/common/usb_pd_protocol.c
+++ b/common/usb_pd_protocol.c
@@ -355,14 +355,11 @@ static inline void set_state(int port, enum pd_states next_state)
#endif
pd[port].dev_id = 0;
pd[port].flags &= ~PD_FLAGS_RESET_ON_DISCONNECT_MASK;
-#ifdef CONFIG_USB_PD_ALT_MODE_DFP
pd_exit_mode(port, NULL);
-#else
#ifdef CONFIG_USBC_SS_MUX
board_set_usb_mux(port, TYPEC_MUX_NONE,
pd[port].polarity);
#endif
-#endif
#ifdef CONFIG_USBC_VCONN
pd_set_vconn(port, pd[port].polarity, 0);
#endif
@@ -2607,7 +2604,7 @@ static int hc_remote_flash(struct host_cmd_handler_args *args)
pd_send_vdm(port, USB_VID_GOOGLE, VDO_CMD_REBOOT, NULL, 0);
/* Delay to give time for device to reboot */
- usleep(750 * MSEC);
+ usleep(900 * MSEC);
return EC_RES_SUCCESS;
case USB_PD_FW_FLASH_ERASE:
diff --git a/include/usb_pd.h b/include/usb_pd.h
index 22d753e7d8..cb588102d0 100644
--- a/include/usb_pd.h
+++ b/include/usb_pd.h
@@ -376,6 +376,15 @@ struct pd_policy {
#define PD_VDO_SVID_SVID1(vdo) ((vdo) & 0xffff)
/*
+ * Google modes capabilities
+ * <31:8> : reserved
+ * <7:0> : mode
+ */
+#define VDO_MODE_GOOGLE(mode) (mode & 0xff)
+
+#define MODE_GOOGLE_FU 1 /* Firmware Update mode */
+
+/*
* Mode Capabilities
*
* Number of VDOs supplied is SID dependent (but <= 6 VDOS?)
@@ -751,13 +760,6 @@ void pd_new_contract(int port, int pr_role, int dr_role,
void pd_execute_data_swap(int port, int data_role);
/**
- * Get PD device info used for VDO_CMD_SEND_INFO / VDO_CMD_READ_INFO
- *
- * @return Pointer to data payload for VDO_CMD_*_INFO
- */
-uint32_t *pd_get_info(void);
-
-/**
* Handle Vendor Defined Messages
*
* @param port USB-C port number